/**
 * css/components/logo-intro.css — header logo intro
 *
 * The header lockup draws itself in once, then gets out of the way. Driven by
 * js/cg-logo-intro.js; read that file's header for what the animation does.
 *
 * WHY THIS FILE IS SHORT
 * ----------------------
 * It replaced a sprite-sheet version roughly four times its size. That version
 * animated a RASTER copy of the logo, so most of it was machinery for making a
 * bitmap sit convincingly on top of a vector: cell calibration in ratios, a
 * sub-pixel `transform` fit measured per logo size, a decode budget, and a
 * hand-off tuned to avoid a frame where both were visible (they could never be
 * made identical — the raster carried ~4.5% more ink mass).
 *
 * The intro now animates the logo's own paths. The last frame is the lockup,
 * so there is nothing to align and nothing to blend. All of that is gone.
 *
 * THE HOLD, AND WHY IT IS A CSS ANIMATION
 * ---------------------------------------
 * The intro is a reveal: the first frame is near-empty. So the static SVG has
 * to be invisible before the first frame paints, or the visitor sees
 * logo → gone → drawn → logo, which reads as a glitch. Scripts are
 * footer-enqueued, so JS cannot win that race; only CSS applied at first paint
 * can (the same `html.cg-js` no-flash bridge header.php uses for the hero).
 *
 * Hiding the site's logo from CSS is only acceptable if CSS also un-hides it
 * WITHOUT JS, so the hold is a `steps(1, end)` animation that expires on its
 * own after `--cg-logo-hold`. A JS error, a blocked script, a throw mid-draw:
 * worst case the logo appears late. It can never be permanently missing, which
 * a class toggle owned by JS could not promise.
 *
 * Scoped to `.cg-header .cg-logo` on purpose. The sticky bar and the nav
 * overlay carry the same `.cg-logo` markup and must never hold or animate —
 * they appear mid-scroll and mid-interaction, where a drawing-on logo is noise,
 * and the overlay's would replay on every open.
 *
 * Tokens/vars only — no !important, no @layer.
 */

/*
 * Both animated logos need a positioning context for the overlay. The sticky
 * bar's `.cg-logo` is deliberately not listed — it never animates.
 */
.cg-header .cg-logo,
.cg-footer .cg-logo {
	position: relative;
}

/*
 * The animated overlay, appended by JS and removed when the intro ends.
 *
 * Same viewBox and same height as the inline lockup it covers, so the two
 * occupy an identical box and the swap at the end is invisible.
 *
 * Centred with a NEGATIVE MARGIN, not `translateY(-50%)`, and that is not a
 * style preference. A transform promotes the element to its own compositing
 * layer, which is then antialiased on its own sub-pixel phase — the overlay and
 * the static SVG end up drawn on subtly different grids even though their boxes
 * are identical to three decimal places. Invisible to a thresholded pixel diff
 * (0.004% differing) and clearly visible to an ink-centroid measurement, which
 * put the mark 0.41px out at the swap. Margins participate in ordinary layout
 * and are snapped the same way the static SVG's box is, so the two coincide.
 *
 * `top: 50%` + the margin centres on the link's box rather than assuming the
 * link is exactly logo-height — it is not on every breakpoint.
 */
.cg-logo__intro {
	/*
	 * The hairline cursor that leads each wordmark wipe — the only mark in the
	 * overlay that is not the logo, and the only colour decision in it.
	 *
	 * The design file hardcodes #FF5A1F. That is not a CG colour: the brand rust
	 * is #E3581D (--cg-rust), which is close enough that the difference reads as
	 * a mistake rather than a choice. Taking the token means the cursor tracks
	 * the palette instead of drifting from it — and it inverts correctly if the
	 * header ever runs on the ink band. Set this to a literal here if the design
	 * really does want its own orange.
	 */
	--cg-logo-intro-cursor: var( --cg-rust );

	position: absolute;
	top: 50%;
	left: 0;
	margin-top: calc( var( --cg-logo-h ) / -2 );
	display: block;
	height: var( --cg-logo-h );
	width: auto;
	color: currentColor;
	pointer-events: none;
}

/* ─── The hold ──────────────────────────────────────────────────────────── */

/*
 * `:not(.cg-logo__intro)` is load-bearing, not tidiness.
 *
 * The overlay is itself an `<svg>` child of `.cg-logo`, so a bare `> svg`
 * matches it too and the hold would hide the very thing it exists to make room
 * for — a 3.2s intro playing at opacity 0, then the logo appearing as if
 * nothing had happened. Every rule in this section carries the exclusion.
 *
 * `.cg-js` is set by the inline script in <head>, so these only apply where JS
 * is running and can therefore be relied on to play the intro.
 * `prefers-reduced-motion: no-preference` keeps the hold away from anyone who
 * has asked for less motion — they get the logo immediately, always.
 */
@media ( prefers-reduced-motion: no-preference ) {

	html.cg-js .cg-header .cg-logo > svg:not( .cg-logo__intro ) {
		animation: cg-logo-hold var( --cg-logo-hold, 1400ms ) steps( 1, end ) both;
	}
}

/*
 * Two stops, not a fade: the SVG must be either fully hidden (the intro is
 * playing) or fully painted (the hold expired). Anything in between shows both.
 *
 * `opacity`, not `visibility`/`display`, so the SVG keeps its box and the
 * header never reflows when it appears.
 */
@keyframes cg-logo-hold {

	0%,
	99.9% {
		opacity: 0;
	}

	100% {
		opacity: 1;
	}
}

/*
 * JS has taken over. The first hold is 1400ms but a playthrough is ~3230ms, so
 * this must replace it — without it the hold expires mid-draw and paints the
 * static logo on top of a still-running intro.
 *
 * A SECOND self-expiring hold, not `animation: none`. The guarantee that CSS
 * alone always brings the logo back has to survive playback too: if the rAF
 * loop dies here, `animation: none` would leave the logo hidden for good. This
 * one covers the playthrough plus margin and then gives up on JS.
 *
 * Distinct @keyframes NAME, not a longer duration on the same one: changing
 * only `animation-duration` re-times the running animation against elapsed
 * time instead of restarting it, landing the expiry at an arbitrary point.
 *
 * `html.cg-js` is carried through here and below purely for SPECIFICITY. Each
 * has to outrank the hold rule above, and without the prefix they lose. Do not
 * "simplify" the prefix away.
 */
html.cg-js .cg-header .cg-logo.is-logo-intro > svg:not( .cg-logo__intro ) {
	animation: cg-logo-hold-play var( --cg-logo-hold-play, 4000ms ) steps( 1, end ) both;
	opacity: 0;
}

@keyframes cg-logo-hold-play {

	0%,
	99.9% {
		opacity: 0;
	}

	100% {
		opacity: 1;
	}
}

/* ─── The footer, which works the other way round ───────────────────────── */

/*
 * The footer logo animates on scroll, and NOTHING here hides it in advance.
 *
 * That is the whole difference from the header. The header sits above the fold,
 * so its logo has to be invisible before the first paint — only CSS can win
 * that race, and the price is a hold that must expire on its own so a dead
 * script cannot strand it. The footer is below the fold when the page loads, so
 * js/cg-logo-intro.js can hide it at the moment it arms and nobody sees the
 * change. There is no window in which this stylesheet hides the footer logo,
 * which means there is no failure that leaves it hidden: if the script never
 * runs, throws, or is blocked, the footer is exactly the footer it was before.
 *
 * The one case that would flash — the footer already on screen at load, on a
 * short page — is handled in the script by not animating at all.
 *
 * So the rule below is opacity only, applied while `is-logo-intro` is set, and
 * `is-logo-intro` is removed in the same synchronous block that removes the
 * overlay.
 */
html.cg-js .cg-footer .cg-logo.is-logo-intro > svg:not( .cg-logo__intro ) {
	opacity: 0;
}

/*
 * The resting state, and every not-playing case: the overlay is gone (or was
 * never added) and the hold is released. Reduced motion is handled by the media
 * query above; `?logo-intro=off`, the once-per-session skip, a browser with no
 * requestAnimationFrame and a throw mid-playback all land here.
 *
 * No transition, deliberately: the overlay's last frame and this are the same
 * picture, so the swap needs to be a single synchronous paint, not a blend.
 */
html.cg-js .cg-header .cg-logo.is-logo-static > svg:not( .cg-logo__intro ),
html.cg-js .cg-footer .cg-logo.is-logo-static > svg:not( .cg-logo__intro ) {
	animation: none;
	opacity: 1;
}
