/**
 * Structural layout: container, header, section rhythm, grids.
 */

.container {
	position: relative;
	max-width: var(--container-max);
	margin-inline: auto;
	padding-inline: var(--container-pad);
}

/* Vertical guide lines on both edges — a deliberate Agent Eclipse choice
   (the live reference site only has one on the right; ours keeps both).
   Lives on each full section box (header, every section, footer), not the
   inner .container, so it spans the section's whole height including its
   own padding-block, with no gap wherever a section has top/bottom padding
   before its .container starts. The x-position uses the same centering
   math .container uses (margin-inline:auto), so it lands exactly on the
   container's outer edge. Header, sections, and footer stack with no gap,
   so the per-element segments read as one continuous line down the page. */
.site-header,
.section,
.site-footer {
	position: relative;
}

.site-header::before,
.site-header::after,
.section::before,
.section::after,
.site-footer::before,
.site-footer::after {
	content: '';
	position: absolute;
	top: 0;
	bottom: 0;
	width: 1px;
	background: var(--color-border);
	pointer-events: none;
}

.site-header::before,
.section::before,
.site-footer::before {
	left: max(0px, calc((100% - var(--container-max)) / 2));
}

.site-header::after,
.section::after,
.site-footer::after {
	right: max(0px, calc((100% - var(--container-max)) / 2));
}

.section {
	padding-block: var(--space-section);
}

/* The section-seam horizontal divider (below) needs its own pseudo-element
   slot, but .section's ::before/::after are already the vertical lines
   above — so the seam divider lives on .container's ::before instead
   (a separate element, its own independent before/after budget), rather
   than fighting the vertical-line rule for the same slot on .section. */

/* Sits at the true section seam (section's own top edge, before its
   padding-block) by pulling up from .container's top by exactly the
   section's own top padding — correct only when both sections share the
   plain --space-section top padding. .hero is excluded on the left side:
   it's always first so it can never be the matched (second) section
   here, but it CAN be the preceding sibling. #trusted-by (logo-marquee)
   is excluded on the right side for a related reason: it always uses its
   own smaller custom padding-block instead of --space-section, so this
   rule's offset is wrong whenever IT is the receiving section — not just
   when hero precedes it (originally caught as a stray line through the
   hero steps row), but on any page: confirmed on /pricing, where
   pricing-tiers precedes it instead of hero and the miscalculated offset
   put the line ~109px too high, cutting through the pricing cards above
   instead of sitting at the real seam. .feature-row-section (Cortex/
   Ask/Pulse) is excluded too, but only from THIS full-width rule — Cortex
   confirmed directly on the user's own screenshot to have no seam line
   above it at all, and Ask/Pulse need a different (short, not full-width)
   treatment below rather than none, so both are kept out of this rule
   and Ask/Pulse pick theirs up from the next rule instead. */
.section:not(.hero) + .section:not(#trusted-by):not(.feature-row-section) > .container::before {
	content: '';
	position: absolute;
	top: calc(-1 * var(--space-section));
	left: 0;
	right: 0;
	border-top: 1px solid var(--color-border);
	pointer-events: none;
}

/* Ask and Pulse specifically (a feature-row-section preceded by another
   feature-row-section — Cortex never matches this, since "problem"
   precedes it, not a feature-row-section) get a SHORT seam divider
   instead — confirmed directly against the reference video
   (frame-by-frame, 3 independent frames): the line above "Ask" and above
   "Pulse" stops at roughly the text column's own width, well short of
   the visual/card side of the row. Matches the same 42%/280px-min
   proportions already established for .trusted-by__line's own short
   lead-in line, for visual consistency between the two. */
.feature-row-section + .feature-row-section > .container::before {
	content: '';
	position: absolute;
	top: calc(-1 * var(--space-section));
	left: 0;
	width: 42%;
	min-width: 280px;
	max-width: 100%;
	border-top: 1px solid var(--color-border);
	pointer-events: none;
}

.section__head {
	max-width: 660px;
}

.section__head--center {
	max-width: 620px;
	margin-inline: auto;
	text-align: center;
}

/* Heading sits near the top of this section (left-aligned, not centered)
   — reference has it shortly after the section begins, not vertically
   centered within the section like the default --space-section top
   padding would put it. */
.problem {
	position: relative;
	padding-top: var(--space-lg);
	overflow: hidden;
}

.problem__canvas {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	opacity: 0.35;
	pointer-events: none;
}

/* Standalone looping chat-demo section on the Ask page — same
   relative/overflow-hidden + absolute full-bleed canvas pattern as
   .problem above, just centered rather than preceded by a heading. */
.ask-demo {
	position: relative;
	overflow: hidden;
	text-align: center;
}

.ask-demo__canvas {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	opacity: 0.35;
	pointer-events: none;
}

/* ---------- Site header ---------- */

.site-header {
	position: sticky;
	top: 0;
	z-index: 50;
	height: var(--header-height);
	display: flex;
	/* stretch, not center: the header's .container needs to span the full
	   bar height so its vertical guide lines reach edge to edge and meet
	   the hero section's lines with no gap. Its own children (logo/nav/
	   actions) still center via the align-items:center set on it below. */
	background: var(--color-bg);
	/* Full-bleed, edge to edge — unlike the container-width rules below it,
	   this one is always visible, not just once scrolled. */
	border-bottom: 1px solid var(--color-border);
	transition: background-color var(--duration-fast) var(--ease-standard);
}

.site-header.is-scrolled {
	background: rgba(17, 15, 13, 0.85);
	backdrop-filter: blur(10px);
}

.site-header .container {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-sm);
	width: 100%;
}

/* Logo + nav grouped as one left-aligned block, so the free space on a
   wide viewport collects in a single gap before the CTA — not split into
   two gaps around a centered nav (which is what plain 3-child
   justify-content:space-between on .container would do instead). */
.site-nav-group {
	display: flex;
	align-items: center;
	gap: var(--space-xl);
	min-width: 0;
}

.site-branding {
	display: flex;
	align-items: center;
	gap: var(--space-2xs);
	font-size: var(--fs-small);
	font-weight: 600;
	color: var(--color-text-primary);
}

.site-branding a {
	display: flex;
	align-items: center;
	gap: inherit;
	color: inherit;
	text-decoration: none;
}

.site-branding img,
.site-branding svg {
	width: 20px;
	height: 20px;
}

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

.nav-menu > li {
	position: relative;
}

.nav-menu a {
	display: inline-flex;
	align-items: center;
	gap: var(--space-3xs);
	padding: var(--space-3xs) var(--space-2xs);
	border-radius: var(--radius-sm);
	font-size: var(--fs-small);
	font-weight: 500;
	color: var(--color-text-primary);
	transition: color var(--duration-fast) var(--ease-standard),
		background-color var(--duration-fast) var(--ease-standard);
}

.nav-menu a:hover {
	color: var(--color-text-primary);
}

.nav-menu__chevron {
	width: 14px;
	height: 14px;
	color: var(--color-text-tertiary);
	transition: transform var(--duration-fast) var(--ease-standard);
}

/* Same trigger as the chevron flip below: the dropdown's open (hover)
   state also gets the pill background reference shows behind the label. */
.menu-item-has-children:hover > a {
	background: var(--color-surface-raised);
}

.menu-item-has-children:hover > a .nav-menu__chevron {
	transform: rotate(180deg);
}

/* Hover-revealed dropdown panel — no JS needed, matches the chevron
   on Features/Resources once a real submenu is assigned in the menu editor. */
.nav-menu .sub-menu {
	position: absolute;
	top: 100%;
	left: calc(-1 * var(--space-sm));
	margin-top: var(--space-sm);
	min-width: 200px;
	/* Explicit, not just inherited from .site-header's z-index:50 — the
	   panel's own translateY transform (closed vs. open state below) puts
	   it in its own stacking context, and other transformed/composited
	   elements further down the page (e.g. the hero canvas) shouldn't be
	   able to paint over it regardless of DOM order. */
	z-index: 60;
	padding: var(--space-2xs);
	background: var(--color-surface);
	border: 1px solid var(--color-border);
	border-radius: var(--radius-md);
	box-shadow: var(--shadow-card);
	opacity: 0;
	visibility: hidden;
	transform: translateY(4px);
	transition: opacity var(--duration-fast) var(--ease-standard),
		transform var(--duration-fast) var(--ease-standard),
		visibility var(--duration-fast);
}

.menu-item-has-children:hover > .sub-menu,
.menu-item-has-children:hover > .mega-menu {
	opacity: 1;
	visibility: visible;
	transform: translateY(0);
}

.nav-menu .sub-menu a {
	display: flex;
	padding: var(--space-2xs) var(--space-xs);
	border-radius: var(--radius-sm);
	white-space: nowrap;
}

.nav-menu .sub-menu a:hover {
	background: var(--color-surface-raised);
}

/* Mega-menu panels (Features/Resources in the fallback nav) — same
   hover-reveal contract as .sub-menu above, but wider and with its own
   internal layout instead of a plain link list. */
.mega-menu {
	/* Padding, radius, shadow and background below are measured directly
	   from strand.framer.website's computed styles (Features dropdown),
	   not estimated. */
	position: absolute;
	top: 100%;
	left: calc(-1 * var(--space-sm));
	margin-top: var(--space-2xs);
	padding: 4px;
	background: var(--color-surface-raised);
	border: none;
	border-radius: 10px;
	box-shadow: 0 10px 20px rgba(0, 0, 0, 0.05);
	z-index: 60;
	opacity: 0;
	visibility: hidden;
	transform: translateY(4px);
	transition: opacity var(--duration-fast) var(--ease-standard),
		transform var(--duration-fast) var(--ease-standard),
		visibility var(--duration-fast);
}

.mega-menu--features {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 0;
	width: 534px;
}

.nav-menu .mega-menu__item {
	/* .nav-menu a (one class + one tag = higher specificity than this
	   rule's single class alone) sets align-items:center for plain nav
	   links; scoping this selector through .nav-menu too is what's needed
	   to actually outrank it, rather than just restating the property. */
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 12px;
	padding: 12px;
	border-radius: var(--radius-sm);
}

.mega-menu__item:hover {
	/* Panel bg is now --color-surface-raised (measured); this needs to be
	   a visibly lighter shade against it, not the same color. */
	background: var(--color-surface);
}

.mega-menu__item-icon {
	width: 40px;
	height: 40px;
	color: var(--color-text-tertiary);
}

.mega-menu__item-title {
	font-size: var(--fs-small);
	font-weight: 600;
	color: var(--color-text-primary);
}

.mega-menu__item-desc {
	font-size: var(--fs-micro);
	line-height: 1.4;
	color: var(--color-text-tertiary);
}

/* Values below (widths, padding, gaps, colors) are measured directly from
   strand.framer.website's Resources dropdown, not estimated. */
.mega-menu--resources {
	display: flex;
	gap: 0;
	width: 449px;
}

.mega-menu__group {
	display: flex;
	flex-direction: column;
	min-width: 0;
	padding: 8px;
}

.mega-menu__group-label {
	padding: var(--space-3xs) var(--space-xs);
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--color-text-quaternary);
}

/* ---- Support column: icon + title + description per item ---- */

.mega-menu__group--support {
	flex: 2;
	gap: 4px;
}

/* Scoped through .nav-menu, not just the single class: .nav-menu a (one
   class + one tag = higher specificity) sets its own gap/padding for
   plain nav links, and would otherwise win over this rule since this is
   also an <a> nested inside .nav-menu — same specificity fix as
   .nav-menu .mega-menu__item earlier in this file. */
.nav-menu .mega-menu__resource-item {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 8px;
	border-radius: var(--radius-sm);
}

.mega-menu__resource-item:hover {
	background: var(--color-surface-raised);
}

.mega-menu__resource-icon {
	flex: none;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	border: 1px solid var(--color-border);
	border-radius: var(--radius-sm);
	background: var(--color-surface);
	color: var(--color-text-secondary);
}

.mega-menu__resource-icon svg {
	width: 16px;
	height: 16px;
}

.mega-menu__resource-content {
	display: flex;
	flex-direction: column;
	gap: 4px;
	min-width: 0;
}

.mega-menu__resource-title {
	font-size: var(--fs-small);
	font-weight: 500;
	color: var(--color-text-primary);
}

.mega-menu__resource-desc {
	font-size: var(--fs-micro);
	color: var(--color-text-secondary);
	white-space: normal;
}

/* ---- Company column: plain bright links, divider on its left edge ---- */

.mega-menu__group--company {
	position: relative;
	flex: 1;
	gap: 0;
}

.mega-menu__group--company::before {
	content: '';
	position: absolute;
	left: 0;
	top: 0;
	bottom: 0;
	border-left: 1px solid var(--color-border);
}

.mega-menu__group--company a {
	padding: 8px 12px;
	border-radius: var(--radius-sm);
	font-size: var(--fs-small);
	font-weight: 500;
	color: var(--color-text-primary);
	white-space: nowrap;
}

.mega-menu__group--company a:hover {
	background: var(--color-surface-raised);
}

.header-actions {
	display: flex;
	align-items: center;
	gap: var(--space-sm);
}

.menu-toggle {
	display: none;
}

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

.hero {
	/* Measured directly against strand.framer.website (header height 68px,
	   badge content starts at y=92 → 24px gap) — confirms var(--space-sm)
	   was already the right value. */
	padding-top: var(--space-sm);
	/* Overrides .section's inherited --space-section bottom padding
	   (96-220px), which — stacked with .trusted-by's own top padding
	   right after it — produced a much bigger gap after the steps row
	   than the reference has between its steps and the next block. */
	padding-bottom: var(--space-lg);
}

.hero__announcement {
	/* Bleeds out to .container's outer edge on the left (matching the
	   vertical guide line's x) so .hero__announcement-row below starts
	   flush against it with no gap. NOT also re-adding padding-inline
	   here: margin:-pad + padding:pad cancel out and silently put the
	   content right back at the padded edge, which was the actual bug —
	   .hero__steps uses that combo correctly because ITS children should
	   stay inset while only its border bleeds, but this element has no
	   content of its own to keep inset; it exists purely to position
	   .hero__announcement-row, which should bleed too. */
	margin-inline: calc(-1 * var(--container-pad));
}

/* Divider deliberately wider than the badge content it sits under (not
   shrink-wrapped to it) — the reference's line runs visibly past the
   description text, not flush with its end. 656px and the 20px gap below
   are both measured directly from strand.framer.website's computed
   styles (the row's own box is 656px wide, flush against the header with
   no gap, and its border-bottom sits 20px below the badge content's own
   bottom edge). */
.hero__announcement-row {
	/* The row's own box still bleeds flush to the vertical guide line
	   (so the border-bottom below touches it, per the previous fix), but
	   its CONTENT needs the standard content inset — confirmed directly
	   on the reference: the equivalent link has padding: 20px 0 20px
	   40px, landing its badge content at the exact same x as the H1
	   below (x=104 at their 1440px test width), not flush with the line. */
	display: inline-block;
	width: 656px;
	max-width: 100%;
	padding-left: var(--container-pad);
	padding-bottom: 20px;
	border-bottom: 1px solid var(--color-border);
}

.hero__grid {
	display: grid;
	grid-template-columns: minmax(0, 620px) 1fr;
	align-items: center;
	gap: var(--space-xl);
}

.hero__content {
	display: flex;
	flex-direction: column;
	gap: 20px;
}

.hero__art {
	/* No card: no background, border or radius — the reference's visual
	   bleeds straight onto the page, it isn't boxed. */
	position: relative;
	/* Explicit height, not min-height: the grid row sizes itself to its
	   tallest item, and an unconstrained-height canvas would collapse to
	   0 without one. */
	height: 460px;
}

.hero__canvas {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	display: block;
}

.hero__steps {
	margin-top: var(--space-xl);
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-xl);
}

.hero__step {
	display: flex;
	flex-direction: column;
}

/* Confirmed directly against the reference: "1."/"Connect" are two
   separately-colored H3-weight runs on one line, not one uniformly
   secondary-colored label — the number is dim (tertiary), but the word
   itself is full primary white at 600 weight, not secondary/500. */
.hero__step-label {
	font-size: var(--fs-small);
	font-weight: 600;
	color: var(--color-text-primary);
}

.hero__step-num {
	margin-right: var(--space-3xs);
	font-weight: 600;
	color: var(--color-text-tertiary);
}

.hero__step-desc {
	max-width: 22ch;
	margin-top: var(--space-xs);
	font-size: var(--fs-small);
	color: var(--color-text-tertiary);
}

/* ---------- Trusted-by line ---------- */

/* Same bleed-to-guide-line + content-inset-text pattern used elsewhere
   (.hero__announcement-row): the line itself starts flush at the
   vertical guide line, sized to roughly span the first two step
   columns above it (~40-45% of the content column), not the full width. */
.trusted-by__line {
	margin-inline: calc(-1 * var(--container-pad));
	width: 42%;
	min-width: 280px;
	max-width: 100%;
	padding-left: var(--container-pad);
	padding-top: var(--space-md);
	border-top: 1px solid var(--color-border);
}

.trusted-by__text {
	font-size: var(--fs-micro);
	color: var(--color-text-tertiary);
}

/* ---------- Logo marquee ---------- */

.marquee {
	margin-top: var(--space-md);
	overflow: hidden;
	/* overflow: hidden alone still let the (very wide, duplicated-content)
	   .marquee__track below inflate the document's horizontal scrollable
	   area in this engine even though nothing from it actually painted
	   outside this box — contain: paint makes this element an explicit
	   clip/containment boundary so the track's true size stops leaking
	   into page-level scrollWidth. */
	contain: paint;
	-webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
	mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
}

.marquee__track {
	display: flex;
	align-items: center;
	width: max-content;
	gap: var(--space-xl);
	animation: marquee-scroll 32s linear infinite;
}

.marquee__item {
	display: flex;
	align-items: center;
	gap: var(--space-2xs);
	color: var(--color-text-primary);
	font-size: var(--fs-h3);
	font-weight: 600;
	white-space: nowrap;
}

.marquee__item-icon {
	flex: none;
	width: 24px;
	height: 24px;
	color: var(--color-text-primary);
}

/* Closing line for the trusted-by section — confirmed directly on
   strand.framer.website: it's built as two separate halves ("Left" and
   "Right" in its own markup), each spanning exactly half the container
   and meeting edge-to-edge at the center, not one single full-width
   element. Reproduced the same way here rather than one div, so each
   half can draw in from its own outer edge independently. The reference
   renders each half as three color-channel strands blended with
   mix-blend-mode:screen that settle to a color matching --color-border
   almost exactly, so that's used directly instead of reproducing the
   channel-split technique; the reveal reuses the same [data-reveal]
   trigger as everything else on the page instead of a one-off observer. */
/* Bleeds out to the container's true outer edge — same technique as
   .hero__announcement above — so each half's outer end lands exactly on
   the vertical guide line's x instead of stopping at the inner content
   edge (container-pad) with a visible gap between the two. */
.trusted-by__dividers {
	display: flex;
	margin-top: var(--space-lg);
	margin-inline: calc(-1 * var(--container-pad));
}

.trusted-by__divider-half {
	flex: 1 1 0;
	height: 1px;
	background: var(--color-border);
}

.trusted-by__divider-half--left[data-reveal] {
	transform-origin: left center;
}

.trusted-by__divider-half--right[data-reveal] {
	transform-origin: right center;
}

.trusted-by__divider-half[data-reveal] {
	opacity: 1;
	transform: scaleX(0);
	transition: transform calc(var(--duration-slow) * 1.4) var(--ease-standard);
	transition-delay: var(--reveal-delay, 0ms);
}

.trusted-by__divider-half[data-reveal].is-visible {
	transform: scaleX(1);
}

/* ---------- Vertical ticker (connected-sources card) ---------- */

/* Same technique as the marquee above — the row list is duplicated once
   in the DOM (integrations.php) and .ticker__track loops translateY(0)
   to translateY(-50%) — just vertical instead of horizontal. Height is
   5 row-heights so exactly 5 rows show at a time; 73px is .source-row's
   own rendered height (32px icon + space-xs padding, 16px/11px type at
   their reference-matched line-heights — round 22), measured live rather
   than derived, same approach as #demo-panel's min-height. */
.ticker {
	height: 365px;
	overflow: hidden;
	-webkit-mask-image: linear-gradient(180deg, transparent, #000 8%, #000 92%, transparent);
	mask-image: linear-gradient(180deg, transparent, #000 8%, #000 92%, transparent);
}

.ticker__track {
	animation: ticker-scroll-y 20s linear infinite;
}

/* ---------- Two-column feature rows ---------- */

/* The visual side's decorative constellation ring (visual-sources.php
   etc.) deliberately bleeds past its own 340px box via a negative inset,
   for a soft glow-beyond-the-card look. Measured against the live page,
   that bleed stays inside this section's own top/bottom padding at every
   viewport tested — but clipping it here as well is a free, defensive
   guarantee it can never visibly cross into the section above/below,
   regardless of future content or viewport changes. */
.feature-row-section {
	overflow: hidden;
}

.feature-row {
	display: grid;
	grid-template-columns: minmax(0, 480px) 1fr;
	gap: var(--space-xl);
	align-items: center;
}

.feature-row--reverse {
	grid-template-columns: 1fr minmax(0, 480px);
}

.feature-row--reverse .feature-row__visual {
	order: -1;
}

.feature-row__body {
	display: flex;
	flex-direction: column;
	gap: var(--space-md);
}

.feature-row__bullets {
	display: flex;
	gap: var(--space-sm);
}

.feature-row__visual {
	position: relative;
	min-height: 360px;
	display: flex;
	align-items: center;
	justify-content: center;
}

/* Bleeds past the card on all sides — same original particle-network
   component as the hero visual, reused here for consistency
   (initNetworkCanvas in main.js), just repositioned/resized. Shared by
   all three feature rows (Cortex/Ask/Pulse); each picks its own outline
   via a data-shape attribute (flower/round/circle) read in main.js. The
   parent .feature-row-section has overflow:hidden, so this can never
   escape into the section above/below regardless of how far it bleeds.
   width/height are set explicitly alongside inset because <canvas> is a
   replaced element: inset alone only stretches a normal box, not a
   replaced one (it falls back to its drawing-buffer intrinsic size
   instead) — without this the canvas rendered far larger than its
   wrapper+bleed (measured 1200x600 instead of ~560x564), reaching close
   enough to the section's own edges to look like it crossed them
   (round 23). */
.feature-visual__canvas {
	position: absolute;
	inset: -110px;
	width: calc(100% + 220px);
	height: calc(100% + 220px);
	opacity: 0.5;
	pointer-events: none;
}

/* ---------- Integration icon tile grid (connect-your-stack background) ---------- */

/* A dim, decorative 3-column grid of app-icon tiles sitting behind and
   to the right of the connected-sources card — shifted right so it
   straddles the card's right edge (half the grid tucked behind the
   card, half poking out past it), per the reference. z-index keeps it
   under the card without needing DOM order to do the work (the card
   still comes after it in markup, but this makes the stacking
   explicit). The card is flex-centered in .feature-row__visual with a
   fixed 460px max-width, so its right edge sits 230px right of the
   visual's own center — the translate below targets that same point,
   independent of how wide .feature-row__visual itself is. Hidden below
   1024px alongside the single-column layout the card uses there. */
.icon-tile-grid {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(calc(-50% + 230px), -50%);
	z-index: 0;
	display: grid;
	grid-template-columns: repeat(3, 56px);
	gap: var(--space-sm);
	opacity: 0.5;
	pointer-events: none;
}

.icon-tile {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 56px;
	height: 56px;
	border-radius: var(--radius-md);
	border: 1px solid var(--color-border);
	background: var(--color-surface);
}

.icon-tile svg {
	width: 18px;
	height: 18px;
	color: var(--color-text-quaternary);
}

/* ---------- Scroll-progress ruler (right edge, numbered sections) ---------- */

.section-ruler {
	position: fixed;
	top: 50%;
	right: 40px;
	transform: translateY(-50%);
	z-index: 30;
	display: flex;
	flex-direction: column;
	gap: var(--space-lg);
	opacity: 0;
	transition: opacity var(--duration-base) var(--ease-standard);
	pointer-events: none;
}

.section-ruler.is-visible {
	opacity: 1;
}

.section-ruler__group {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: var(--space-2xs);
}

.section-ruler__label {
	font-family: var(--font-mono);
	font-size: 12px;
	color: var(--color-text-quaternary);
	transition: color var(--duration-base) var(--ease-standard);
}

.section-ruler__ticks {
	display: flex;
	flex-direction: column;
	gap: var(--space-2xs);
	align-items: flex-end;
}

.section-ruler__tick {
	height: 1px;
	width: 16px;
	border-radius: var(--radius-pill);
	background: var(--color-text-quaternary);
	transition: width var(--duration-base) var(--ease-standard),
		background-color var(--duration-base) var(--ease-standard);
}

.section-ruler__group.is-active .section-ruler__label {
	color: var(--color-text-tertiary);
}

.section-ruler__group.is-active .section-ruler__tick {
	width: 26px;
	background: var(--color-text-primary);
}

@media (max-width: 1023px) {
	.section-ruler {
		display: none;
	}

	.icon-tile-grid {
		display: none;
	}
}

/* ---------- Stats / testimonial ---------- */

/* Photo column stretches the full row height (align-items:stretch); the
   text column gets its own flex centering below so it isn't also forced
   to stretch its content. 480px matches the reference's own image width
   relative to this row (measured live: 500px in a 1312px content area). */
.testimonial {
	display: grid;
	grid-template-columns: 1fr 480px;
	gap: var(--space-xl);
	align-items: stretch;
}

.testimonial > * {
	/* Grid items default to min-width: auto (content's own min-content
	   size), not 0 — at the single-column responsive breakpoint below
	   this let the text column's intrinsic width, and the photo's own
	   sizing, push the whole grid (and the document) wider than the
	   viewport instead of actually shrinking to fit it. */
	min-width: 0;
}

.testimonial > :first-child {
	display: flex;
	flex-direction: column;
	justify-content: center;
}

/* No card frame, no padding, no border-radius — flush with the
   container's edge, unlike every other bordered card on the site
   (confirmed against the live reference). */
.testimonial__photo {
	height: 100%;
	min-height: 480px;
}

.testimonial__photo img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.testimonial-nav {
	display: flex;
	gap: var(--space-2xs);
	margin-top: var(--space-md);
}

/* Exact sizing/colors measured live off the reference: 26px circles,
   no border on either — the "ghost vs active" distinction is purely
   background + icon-color contrast, not a border. */
.testimonial-nav__btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 26px;
	height: 26px;
	padding: 0;
	border-radius: var(--radius-pill);
	border: none;
	font-size: var(--fs-micro);
	line-height: 1;
	cursor: pointer;
	transition: background-color var(--duration-fast) var(--ease-standard),
		color var(--duration-fast) var(--ease-standard);
}

.testimonial-nav__btn--prev {
	background: var(--color-surface);
	color: var(--color-text-tertiary);
}

.testimonial-nav__btn--next {
	background: var(--color-border);
	color: var(--color-text-primary);
}

.stats-row {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--space-lg);
}

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

.faq {
	display: grid;
	grid-template-columns: minmax(0, 420px) 1fr;
	gap: var(--space-xl);
}

/* Pulls the list up by exactly the first row's own top padding
   (.accordion__trigger's padding-block) so the first question's text
   lines up with the heading's top instead of sitting var(--space-sm)
   below it — confirmed against the reference, where the two start
   almost exactly level (measured live: an 8px gap from font-metric
   differences, not the ~24px gap this padding was otherwise causing). */
.accordion {
	margin-top: calc(-1 * var(--space-sm));
}

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

.site-footer {
	position: relative;
	overflow: hidden;
	padding-top: var(--space-2xl);
}

.footer__columns {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--space-lg);
}

.pricing-row {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	border-top: 1px solid var(--color-border);
}

.pricing-col {
	padding: var(--space-lg);
	border-left: 1px solid var(--color-border);
}

.pricing-col:first-child {
	border-left: none;
	padding-left: 0;
}

.pricing-col:last-child {
	padding-right: 0;
}

/* ---------- Integrations page ---------- */

.integrations-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--space-md);
}

.integrations-card.is-more {
	display: none !important;
}

/* ---------- About page ---------- */

.about-timeline {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--space-md);
	margin-top: var(--space-lg);
	padding-top: var(--space-md);
	border-top: 1px dashed var(--color-border);
}

.about-team-grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--space-md);
}

.about-team-card {
	display: block;
	color: inherit;
}

.about-team-card__avatar {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	aspect-ratio: 1;
	border-radius: var(--radius-md);
	color: #110f0d;
	font-size: var(--fs-h3);
	font-weight: 700;
}

.about-team-card__avatar--ghost {
	background: var(--color-surface);
	border: 1px dashed var(--color-border-strong);
	color: var(--color-text-tertiary);
}

/* ---------- Careers page ---------- */

.careers-hero {
	margin-top: var(--space-xl);
	height: 320px;
	border-radius: var(--radius-lg);
	background:
		radial-gradient(60% 120% at 20% 20%, rgba(34, 102, 255, 0.35), transparent 60%),
		radial-gradient(50% 100% at 80% 80%, rgba(16, 236, 144, 0.25), transparent 60%),
		var(--color-surface);
	border: 1px solid var(--color-border);
}

.careers-avatar {
	display: inline-block;
	width: 32px;
	height: 32px;
	border-radius: 50%;
	border: 2px solid var(--color-bg);
}

@media (max-width: 599px) {
	.careers-hero {
		height: 200px;
	}
}

/* ---------- Blog cards ---------- */

/* ---------- Changelog page ---------- */

.changelog-layout {
	display: grid;
	grid-template-columns: minmax(0, 280px) minmax(0, 1fr);
	gap: var(--space-2xl);
}

.changelog-layout__entries {
	display: flex;
	flex-direction: column;
	gap: var(--space-2xl);
	max-width: 640px;
}

.changelog-entry {
	padding-top: var(--space-xl);
	border-top: 1px solid var(--color-border);
}

.changelog-entry:first-child {
	padding-top: 0;
	border-top: none;
}

@media (max-width: 1023px) {
	.changelog-layout {
		grid-template-columns: 1fr;
		gap: var(--space-lg);
	}
}

.blog-card__thumb {
	height: 180px;
	border-radius: var(--radius-md);
	border: 1px solid var(--color-border);
	background:
		radial-gradient(70% 140% at 30% 0%, color-mix(in srgb, var(--thumb-color) 35%, transparent), transparent 65%),
		var(--color-surface);
}

@media (max-width: 599px) {
	.about-timeline {
		grid-template-columns: 1fr;
		gap: var(--space-sm);
	}

	.about-team-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

.footer__meta {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-md);
	margin-top: var(--space-2xl);
	padding-block: var(--space-md);
	flex-wrap: wrap;
}

.footer__watermark {
	line-height: 0.75;
	font-size: clamp(80px, 14vw, 180px);
	font-weight: 700;
	font-family: var(--font-display);
	color: var(--color-surface);
	user-select: none;
	white-space: nowrap;
	overflow: hidden;
	text-align: center;
	margin-top: var(--space-2xl);
}

.footer__legal {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding-block: var(--space-md);
	font-size: var(--fs-micro);
	color: var(--color-text-tertiary);
	flex-wrap: wrap;
	gap: var(--space-xs);
}

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

@media (max-width: 1023px) {
	.hero__grid,
	.feature-row,
	.feature-row--reverse,
	.testimonial,
	.faq {
		grid-template-columns: 1fr;
	}

	.feature-row--reverse .feature-row__visual {
		order: 0;
	}

	/* Reference stacks the hero's art above its text and centers the
	   text at this width, rather than keeping the desktop's left-aligned
	   text-first order — confirmed directly on strand.framer.website at
	   both 768px and 375px. */
	.hero__art {
		order: -1;
	}

	.hero__content {
		align-items: center;
		text-align: center;
	}

	.hero__content p {
		margin-inline: auto;
	}

	.stats-row {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.hero__steps {
		gap: var(--space-lg);
	}

	.footer__columns {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.integrations-grid {
		grid-template-columns: 1fr !important;
	}

	.pricing-row {
		grid-template-columns: 1fr;
	}

	.pricing-col {
		border-left: none !important;
		border-top: 1px solid var(--color-border);
		padding-inline: 0 !important;
	}

	.pricing-col:first-child {
		border-top: none;
	}

	.nav-menu {
		display: none;
	}

	.menu-toggle {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		width: 36px;
		height: 36px;
		padding: 0;
		border-radius: var(--radius-sm);
		border: 1px solid var(--color-border);
		background: none;
		color: var(--color-text-primary);
		cursor: pointer;
	}

	/* Mobile nav drawer — full-bleed panel anchored under the header,
	   opened by toggling .is-open on .nav-menu (see main.js initMobileMenu).
	   Submenus lose the hover-reveal positioning from the desktop rules
	   above and instead sit inline, shown only once their own parent
	   .menu-item-has-children also carries .is-open (tap-to-expand, since
	   touch has no :hover state to key off). */
	.nav-menu.is-open {
		display: flex;
		position: absolute;
		top: 100%;
		/* .container (this panel's positioned ancestor) already spans the
		   full viewport edge-to-edge — its padding is inset CONTENT, not a
		   gap outside its own box — so 0/0 here is what reaches the
		   viewport edges; subtracting --container-pad again (as if this
		   sat inside the padded content box) overshot past the edge and
		   clipped the menu labels off-screen. */
		left: 0;
		right: 0;
		flex-direction: column;
		align-items: stretch;
		max-height: calc(100vh - var(--header-height));
		padding: 0 var(--container-pad) var(--space-md);
		background: var(--color-bg);
		border-bottom: 1px solid var(--color-border);
		box-shadow: var(--shadow-card);
		overflow-y: auto;
	}

	.nav-menu.is-open > li {
		width: 100%;
		border-top: 1px solid var(--color-border);
	}

	.nav-menu.is-open > li:first-child {
		border-top: none;
	}

	.nav-menu.is-open > li > a {
		width: 100%;
		padding-block: var(--space-sm);
		justify-content: space-between;
	}

	.nav-menu.is-open .sub-menu,
	.nav-menu.is-open .mega-menu {
		display: none;
		position: static;
		opacity: 1;
		visibility: visible;
		transform: none;
		width: 100%;
		margin-top: 0;
		padding: 0 0 var(--space-sm);
		background: none;
		border: none;
		box-shadow: none;
	}

	.nav-menu.is-open .menu-item-has-children.is-open > .sub-menu {
		display: flex;
		flex-direction: column;
	}

	.nav-menu.is-open .menu-item-has-children.is-open > .mega-menu--features {
		display: grid;
		grid-template-columns: 1fr;
		width: 100%;
	}

	.nav-menu.is-open .menu-item-has-children.is-open > .mega-menu--resources {
		display: flex;
		flex-direction: column;
		width: 100%;
	}

	/* Stacked, not side-by-side, at this width — the divider belongs on
	   top, not on the left. */
	.mega-menu__group--company::before {
		left: 0;
		right: 0;
		top: 0;
		bottom: auto;
		border-left: none;
		border-top: 1px solid var(--color-border);
	}

	.nav-menu.is-open .menu-item-has-children.is-open > a .nav-menu__chevron {
		transform: rotate(180deg);
	}
}

@media (max-width: 599px) {
	.stats-row,
	.footer__columns {
		grid-template-columns: 1fr;
	}

	.hero__steps {
		flex-direction: column;
		gap: var(--space-md);
	}

	/* The announcement row's single line (fixed by design for desktop) has
	   no room for its full sentence at phone widths. Let it wrap instead
	   of overflowing. */
	.hero__announcement-row {
		display: block;
		width: 100%;
	}

	.trusted-by__line {
		width: 100%;
		min-width: 0;
	}

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

/* ---------- Feature page hero (Cortex/Ask/Pulse) ---------- */

.feature-page-hero__crumb {
	/* Left-aligned on all three feature pages — confirmed directly on
	   strand.framer.website/features/{cortex,ask,pulse}: the breadcrumb
	   sits flush left under the header regardless of whether that page's
	   own hero content below it is centered (Ask) or left-aligned
	   (Cortex, Pulse). */
	display: flex;
	align-items: center;
	justify-content: flex-start;
	gap: var(--space-2xs);
	font-size: var(--fs-small);
	padding-bottom: 20px;
	border-bottom: 1px solid var(--color-border);
}

/* ---------- Feature hero: stacked variant (Cortex) ----------
   Art sits in its own full-width row, right-aligned; the badge/H1/CTA
   row stack below it as ordinary left-aligned flow — confirmed directly
   against strand.framer.website/features/cortex (480x480 art box at the
   container's right edge, nothing beside it, then the text column
   starting fresh beneath). */

.feature-page-hero__art-row {
	display: flex;
	justify-content: flex-end;
	margin-top: var(--space-lg);
}

.feature-page-hero__art {
	position: relative;
	width: 480px;
	max-width: 100%;
	height: 480px;
}

.feature-page-hero__content {
	margin-top: var(--space-xl);
}

.feature-page-hero__title {
	max-width: none;
}

.feature-page-hero__cta-row {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--space-lg);
	margin-top: var(--space-lg);
	padding-block: var(--space-lg);
	border-top: 1px solid var(--color-border);
}

.feature-page-hero__cta-row p {
	max-width: 36ch;
	color: var(--color-text-secondary);
}

.feature-page-hero__buttons {
	display: flex;
	gap: var(--space-xs);
	flex: none;
}

@media (max-width: 1023px) {
	.feature-page-hero__art {
		width: 100%;
		height: auto;
		aspect-ratio: 1;
	}

	.feature-page-hero__cta-row {
		flex-direction: column;
	}
}

.feature-page-hero__crumb a {
	color: var(--color-text-tertiary);
}

.feature-page-hero__crumb a:hover {
	color: var(--color-text-primary);
}

.feature-page-hero__crumb span[aria-hidden] {
	color: var(--color-text-quaternary);
}

.feature-page-hero__crumb span:last-child {
	color: var(--color-text-secondary);
}

.feature-split {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--space-2xl);
	align-items: start;
}

@media (max-width: 1023px) {
	.feature-split {
		grid-template-columns: 1fr;
		gap: var(--space-xl);
	}

	.feature-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
	}
}

@media (max-width: 599px) {
	.feature-grid {
		grid-template-columns: 1fr !important;
	}
}
