/*
 * The shell every service story page is built in.
 *
 * The hero, the beat scaffolding and its zigzag, the scope columns, the
 * objections list, and the `--lit` primitive that drives every scroll-linked
 * effect on these pages. Loaded before each service's own stylesheet, which
 * supplies only the visuals particular to that service.
 *
 * Extracted from the Google Ads page once a second story page needed the same
 * shell — the alternative was a second copy of 440 lines drifting away from the
 * first.
 *
 * ── the one thing to know ────────────────────────────────────────────────
 * `--lit`. Every animated item carries an `--at` cue in its inline style;
 * `--lit` turns the section's live `--p` into that item's own 0→1. Setting
 * `--lit: 1` anywhere disables the whole system, which is how the reduced-motion
 * and short-screen fallbacks work — one declaration each rather than an
 * override per effect.
 */

/* ============================================================
   The lit primitive
   ============================================================ */

/*
 * Zero until the item's cue, one an eighth of the section later. Multiplying
 * rather than dividing keeps it to a single operation, and clamping to 0→1
 * means every consumer can treat it as a plain fraction.
 */
.gd-leak__seg,
.gd-leak__item,
.gd-tier,
.gd-report__figures > li,
.gd-report__bar,
.gd-report__changes > li {
	--lit: clamp(0, (var(--p, 0) - var(--at, 0)) * 8, 1);
}


/* ============================================================
   Hero — a dark island, the way v3 opens
   ============================================================ */

/*
 * A full screen, dark, pulled up under the header.
 *
 * The header is sticky and in the flow, so without the negative margin the page
 * opens on a band of body colour above the hero — pale, and the first thing you
 * see. The matching top padding keeps the copy clear of it. Taking the whole
 * viewport also means the fold lands on the hero rather than partway into the
 * first beat, which is the same arrangement the homepage heroes use.
 */
.gd-svc-hero {
	position: relative;
	z-index: 1;
	display: grid;
	min-height: 100svh;
	/*
	 * One child, centred — but "safe", so that on a screen too short to hold it
	 * the block aligns to the top and the hero grows instead of the content
	 * overflowing equally off both ends and losing its head and foot.
	 */
	align-content: safe center;
	margin-top: calc(-1 * var(--gd-header-rest, 105px));
	padding-block: calc(var(--gd-header-rest, 105px) + clamp(1.5rem, 4vw, 3rem)) clamp(1.5rem, 3vw, 2.5rem);
	background: radial-gradient(120% 140% at 12% 0%, #141a34 0%, #0a0d1c 46%, #06070f 100%);
	color: var(--gd-text);
}

/*
 * The copy and the trust strip travel together as one centred block.
 *
 * Splitting them across two grid rows put the trust strip 42px below where its
 * own row ended, overflowing the hero and overlapping the section beneath —
 * and centring them as a flex column instead let the copy's auto margins eat
 * the free space the strip needed. With a single child there is no space to
 * distribute and no rows to disagree about: `align-content: center` holds it in
 * the middle, and the hero grows honestly when the content needs more than a
 * screen.
 */
.gd-svc-hero__body {
	position: relative;
	z-index: 1;
	display: flex;
	min-width: 0;
	flex-direction: column;
	/*
	 * The spacing is a gap rather than a margin on the strip below. As margins
	 * these collapsed with the copy's own, opening a gap 42px wider than asked
	 * for and pushing the strip out through the foot of the hero. Flex
	 * containers do not collapse margins, so the number here is the number.
	 */
	gap: clamp(2rem, 4vh, 3.5rem);
}

.gd-svc-hero__trust {
	position: relative;
	z-index: 1;
	display: grid;
	padding-top: clamp(1.25rem, 2.5vh, 2rem);
	border-top: 1px solid rgba(255, 255, 255, 0.12);
	gap: clamp(1rem, 3vw, 2.5rem);
	grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}

.gd-svc-trust { display: grid; gap: 0.2rem; }

.gd-svc-trust__figure {
	color: var(--gd-text);
	font-size: clamp(1.35rem, 2.4vw, 1.9rem);
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	letter-spacing: -0.03em;
	line-height: 1;
}

.gd-svc-trust__label {
	color: var(--gd-text-3);
	font-size: 0.83rem;
	line-height: 1.4;
}

/*
 * Three across rather than three stacked. Left to wrap, the strip added about
 * 150px and pushed the hero to more than one and a half screens on a small
 * phone — which is the opposite of what a full-height hero is for.
 */
@media (max-width: 620px) {
	.gd-svc-hero__trust {
		gap: 0.75rem;
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}

	.gd-svc-trust__figure { font-size: 1.15rem; }
	.gd-svc-trust__label { font-size: 0.7rem; }
}

/* A short screen has to give the copy the room instead. */
@media (max-height: 720px) {
	.gd-svc-hero { padding-block: calc(var(--gd-header-rest, 105px) + 1rem) 1.25rem; }
	.gd-svc-hero__lead { font-size: 0.98rem; }
	.gd-svc-hero__note { display: none; }
	.gd-svc-hero__body { gap: 1.5rem; }
	.gd-svc-hero__trust { padding-top: 1rem; }
}

/*
 * The glow is clipped by its own layer rather than by the hero.
 *
 * `overflow: hidden` on the hero was there only to contain this, and it was
 * also eating the hero's bottom padding — the trust strip lost its bottom 15 to
 * 22px depending on the viewport. Clipping here keeps the glow inside and lets
 * the hero size itself honestly.
 */
.gd-svc-hero__bg {
	position: absolute;
	inset: 0;
	z-index: 0;
	overflow: hidden;
	pointer-events: none;
}

/* Follows the scroll rather than sitting still, so the hero has some depth. */
.gd-svc-hero__glow {
	position: absolute;
	top: -30%;
	left: 8%;
	width: min(720px, 90vw);
	height: min(720px, 90vw);
	border-radius: 50%;
	background: radial-gradient(circle, rgba(124, 92, 255, 0.5), rgba(124, 92, 255, 0) 62%);
	transform: translate3d(0, calc(var(--p, 0) * 90px), 0);
	pointer-events: none;
}

.gd-svc-hero__inner { position: relative; z-index: 1; }

.gd-svc-hero__title {
	max-width: 16ch;
	margin: 0.6rem 0 0;
	font-size: clamp(2.1rem, 6.4vw, 4.4rem);
	font-weight: 800;
	line-height: 1.02;
	letter-spacing: -0.03em;
}

.gd-svc-hero__lead {
	max-width: 58ch;
	margin: clamp(1.25rem, 2.4vw, 1.9rem) 0 0;
	color: var(--gd-text-2);
	font-size: clamp(1rem, 1.35vw, 1.2rem);
	line-height: 1.65;
}

.gd-svc-hero__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.85rem;
	margin-top: clamp(1.75rem, 3vw, 2.5rem);
}

.gd-svc-hero__note {
	margin: 1.15rem 0 0;
	color: var(--gd-text-3);
	font-size: 0.9rem;
}


/* ============================================================
   Beat scaffolding
   ============================================================ */

.gd-beat { position: relative; }

.gd-beat__stage { justify-content: center; }

.gd-beat__inner {
	display: flex;
	width: 100%;
	flex-direction: column;
	gap: clamp(1.75rem, 3.4vw, 3rem);
}

.gd-beat__head { max-width: 62ch; }

.gd-beat__num {
	margin-right: 0.6rem;
	color: var(--gd-brand, #cc3066);
	font-variant-numeric: tabular-nums;
}

.gd-beat__title {
	margin: 0.5rem 0 0;
	font-size: clamp(1.65rem, 3.4vw, 2.9rem);
	font-weight: 800;
	line-height: 1.08;
	letter-spacing: -0.025em;
}

.gd-beat__text {
	max-width: 56ch;
	margin: clamp(0.85rem, 1.4vw, 1.15rem) 0 0;
	color: var(--gd-text-2);
	line-height: 1.65;
}

.gd-beat__foot {
	max-width: 62ch;
	margin: 0;
	color: var(--gd-text-3);
	font-size: 0.9rem;
	line-height: 1.6;
}

/*
 * Two columns once there is room for them.
 *
 * Stacked, the taller beats do not fit a single screen — the audit ran 1091px
 * into a 900px stage and the stage clips. Side by side, the copy holds the left
 * and the figure gets the full height of the right, which is also the better
 * read: the claim stays on screen while its evidence draws itself.
 *
 * The ring reads fine in a column now that its content sits inside it rather
 * than in a list beside it, so every beat takes the same shape.
 */
@media (min-width: 900px) {
	.gd-beat .gd-beat__inner {
		display: grid;
		align-items: center;
		column-gap: clamp(2.5rem, 5.5vw, 5.5rem);
		grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
		grid-template-rows: auto auto;
	}

	.gd-beat__head { grid-row: 1; grid-column: 1; align-self: end; }
	.gd-beat__foot { grid-row: 2; grid-column: 1; align-self: start; padding-top: 1.25rem; }

	/* Spans both rows so it centres against the whole column, not just the head. */
	.gd-beat__figure {
		grid-row: 1 / span 2;
		grid-column: 2;
	}

	/* Nothing follows the head in these two, so it should not be pushed up. */
	.gd-beat--leak .gd-beat__head,
	.gd-beat--report .gd-beat__head { grid-row: 1 / span 2; align-self: center; }

	/*
	 * Every other beat runs the other way round.
	 *
	 * Four two-column beats all facing the same direction read as one long
	 * template, and the eye stops travelling. Alternating gives the page a
	 * zigzag, and it also sharpens the line-up in the middle — that beat is the
	 * one that breaks the grid entirely, and it lands harder against a rhythm
	 * than against a column.
	 *
	 * Only the placement swaps. The copy stays left-aligned in both directions,
	 * because ragged-right is what you actually read, and centring or
	 * right-aligning a paragraph to match its column costs more than the
	 * symmetry is worth.
	 */
	.gd-beat--tiers .gd-beat__inner,
	.gd-beat--report .gd-beat__inner {
		grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
	}

	.gd-beat--tiers .gd-beat__head,
	.gd-beat--tiers .gd-beat__foot,
	.gd-beat--report .gd-beat__head,
	.gd-beat--report .gd-beat__foot { grid-column: 2; }

	.gd-beat--tiers .gd-beat__figure,
	.gd-beat--report .gd-beat__figure { grid-column: 1; }
}


/* ============================================================
   Scope — what you are paying for, and what you are not
   ============================================================ */

.gd-scope {
	display: grid;
	gap: clamp(1rem, 2.4vw, 1.75rem);
	grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}

.gd-scope__col {
	padding: clamp(1.35rem, 2.6vw, 2rem);
	border: 1px solid var(--gd-glass-line);
	border-radius: var(--gd-radius-lg);
	background: var(--gd-glass);
}

/* The one you are buying leads, so it carries the accent and the weight. */
.gd-scope__col--in {
	border-color: color-mix(in srgb, var(--gd-violet) 32%, transparent);
	background:
		linear-gradient(180deg, color-mix(in srgb, var(--gd-violet) 8%, transparent), transparent 55%),
		var(--gd-glass);
	box-shadow: 0 40px 80px -60px rgba(124, 92, 255, 0.75);
}

.gd-scope__head {
	display: flex;
	align-items: baseline;
	padding-bottom: clamp(0.85rem, 1.6vw, 1.15rem);
	margin-bottom: clamp(0.85rem, 1.6vw, 1.15rem);
	border-bottom: 1px solid var(--gd-glass-line);
	gap: 0.75rem;
}

.gd-scope__count {
	color: var(--gd-text-3);
	font-size: 0.8rem;
	font-variant-numeric: tabular-nums;
	font-weight: 700;
}

.gd-scope__col--in .gd-scope__count { color: var(--gd-violet); }

.gd-scope__title {
	margin: 0;
	font-size: clamp(1.05rem, 1.9vw, 1.3rem);
	font-weight: 750;
	letter-spacing: -0.015em;
}

.gd-scope__list {
	display: grid;
	margin: 0;
	padding: 0;
	gap: 0.75rem;
	list-style: none;
}

.gd-scope__list li {
	display: grid;
	align-items: start;
	column-gap: 0.75rem;
	grid-template-columns: 22px minmax(0, 1fr);
	line-height: 1.5;
}

.gd-scope__mark {
	display: grid;
	width: 22px;
	height: 22px;
	margin-top: 0.05rem;
	border-radius: 50%;
	place-items: center;
}

.gd-scope__mark svg { width: 14px; height: 14px; }

.gd-scope__col--in .gd-scope__list li { color: var(--gd-text); }

.gd-scope__col--in .gd-scope__mark {
	background: color-mix(in srgb, var(--gd-violet) 16%, transparent);
	color: var(--gd-violet);
}

/* Struck through rather than merely greyed — these are refusals, not omissions. */
.gd-scope__col--out .gd-scope__list li { color: var(--gd-text-3); }

.gd-scope__col--out .gd-scope__mark {
	background: var(--gd-glass-line);
	color: var(--gd-text-3);
}


/* ============================================================
   Objections
   ============================================================ */

.gd-faq { display: grid; gap: 0; }

.gd-faq__item { border-bottom: 1px solid var(--gd-glass-line); }

.gd-faq__q {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: clamp(1rem, 2vw, 1.4rem) 0;
	gap: 1.5rem;
	color: var(--gd-text);
	cursor: pointer;
	font-size: clamp(1rem, 1.9vw, 1.25rem);
	font-weight: 700;
	list-style: none;
}

.gd-faq__q::-webkit-details-marker { display: none; }

.gd-faq__sign {
	position: relative;
	width: 18px;
	height: 18px;
	flex: none;
}

.gd-faq__sign::before,
.gd-faq__sign::after {
	content: "";
	position: absolute;
	top: 50%;
	left: 0;
	width: 100%;
	height: 1.5px;
	border-radius: 2px;
	background: var(--gd-text-2);
	transform: translateY(-50%);
	transition: transform 0.3s var(--gd-ease);
}

.gd-faq__sign::after { transform: translateY(-50%) rotate(90deg); }
.gd-faq__item[open] .gd-faq__sign::after { transform: translateY(-50%) rotate(0deg); }

.gd-faq__a { padding: 0 0 clamp(1rem, 2vw, 1.4rem); }

.gd-faq__a p {
	max-width: 72ch;
	margin: 0;
	color: var(--gd-text-2);
	line-height: 1.65;
}


/* ============================================================
   Shared responsive + reduced-motion
   ============================================================ */

/*
 * Too narrow, or too short, to pin.
 *
 * A phone cannot hold a full beat on one screen — several run hundreds of
 * pixels past an 844px stage, and a sticky stage clips whatever does not fit.
 * So below 900px, or on any short viewport, the beats stop pinning and become
 * ordinary sections.
 *
 * They keep their animation. The scroll engine's pin model reads the section's
 * own height, and an un-pinned beat is still taller than the viewport, so `--p`
 * runs a clean 0→1 as the section passes — measured, not assumed. The cues play
 * on the way through instead of while held, which is the right behaviour on a
 * phone anyway.
 *
 * The min-height is what guarantees that. Without it a short beat could end up
 * under one screen tall, where the engine clamps travel to a single pixel and
 * every cue fires at once.
 */
@media (max-width: 899px), (max-height: 700px) {
	.gd-js .gd-beat { height: auto; }

	.gd-js .gd-beat__stage {
		position: static;
		min-height: 132svh;
		height: auto;
		padding-block: clamp(3rem, 9vw, 5rem);
		overflow: visible;
	}
}

@media (max-width: 899px) {
	.gd-beat__inner { gap: clamp(1.25rem, 4vw, 2rem); }
}

@media (prefers-reduced-motion: reduce) {
	.gd-svc-hero__glow { transform: none; }
}

/* ============================================================
   The capability rail
   ============================================================ */

/*
 * The strip under each service hero — ad channels on one page, the build stack
 * on the other. Names with a line of context rather than a row of logos: a
 * client recognises "WordPress" without a badge, and the sentence beside it is
 * doing the work the badge could not.
 */
.gd-section--tight { padding-block: clamp(2.25rem, 4vw, 3.5rem) !important; }

.gd-svc-rail__label {
	margin: 0 0 clamp(1rem, 2vw, 1.5rem);
	color: var(--gd-text-3);
	font-size: 0.72rem;
	font-weight: 800;
	letter-spacing: 0.1em;
	text-transform: uppercase;
}

.gd-svc-rail__list {
	display: grid;
	margin: 0;
	padding: 0;
	gap: clamp(0.75rem, 1.6vw, 1.15rem);
	grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
	list-style: none;
}

.gd-svc-rail__item {
	display: grid;
	padding: clamp(0.75rem, 1.5vw, 1.05rem) clamp(0.85rem, 1.7vw, 1.15rem);
	border: 1px solid var(--gd-glass-line);
	border-radius: var(--gd-radius);
	background: var(--gd-glass);
	gap: 0.2rem;
	transition: border-color 0.3s var(--gd-ease), transform 0.3s var(--gd-ease);
}

.gd-svc-rail__item:hover {
	border-color: color-mix(in srgb, var(--gd-violet) 40%, transparent);
	transform: translateY(-2px);
}

.gd-svc-rail__name {
	color: var(--gd-text);
	font-size: clamp(0.95rem, 1.5vw, 1.05rem);
	font-weight: 750;
	letter-spacing: -0.01em;
}

.gd-svc-rail__note { color: var(--gd-text-3); font-size: 0.78rem; line-height: 1.45; }

.gd-svc-rail__foot {
	max-width: 68ch;
	margin: clamp(1rem, 2vw, 1.5rem) 0 0;
	color: var(--gd-text-3);
	font-size: 0.85rem;
	line-height: 1.6;
}

@media (prefers-reduced-motion: reduce) {
	.gd-svc-rail__item { transition: none; }
	.gd-svc-rail__item:hover { transform: none; }
}
