/* Galaxi — corrections to defects found auditing the design handoff.
   Loads last. Every rule here exists because a specific defect was measured in
   a real browser, and each is the smallest change that fixes it. The handoff
   stylesheets are never edited, so a design revision can be dropped in
   wholesale and this file re-applied over it.

   Findings addressed, in the order they were reported:
     1  .gx-segment--wide stretched link swallowed its own tick list
     2  mobile nav panel had no max-height, putting the CTA off-screen
     4  .gx-surface-* utilities tied correctness to stylesheet load order
     5  reduced motion left most of the brand wall unreachable
     6  .gx-stat__value overflowed its card at 320-360px
     7  .gx-segment__main / __aside had no rule in either stylesheet
     8  reduced motion left empty gaps where the pause buttons had been
     9  .gx-sent__title:focus removed the keyboard focus ring

   Finding 3 (a ?state= review hook that showed visitors a fabricated
   "enquiry received" confirmation) was removed from pages.js, not here.
   Finding 10 (decorative ordinals, aria-pressed on the pause buttons) is
   markup and lives in the templates.
*/

/* ------------------------------------------------------------------------
   4. Surface utilities must not depend on load order.

   .gx-brands and .gx-split set their own background in galaxi.css; two
   sections override that with .gx-surface-haze / .gx-surface-white from
   pages.css. Both sides were 0,1,0, so the correct result depended purely on
   pages.css loading second. A concatenating cache plugin that reordered them
   silently inverted two section backgrounds with no error anywhere.

   Raising the utilities to 0,2,0 makes the outcome the same whatever order
   the sheets arrive in. inc/enqueue.php also declares the dependency; this is
   the belt to that braces, because the failure is invisible in review.
   ---------------------------------------------------------------------- */
.gx-section.gx-surface-white,
.gx-brands.gx-surface-white,
.gx-split.gx-surface-white { background: var(--gx-white); }

.gx-section.gx-surface-haze,
.gx-brands.gx-surface-haze,
.gx-split.gx-surface-haze { background: var(--gx-haze); }

/* ------------------------------------------------------------------------
   1 + 7. The wide segment card.

   .gx-segment--wide spans both grid columns, so the stretched link's
   `inset: 0` overlay covered the card's second column as well — including
   three .gx-ticks list items which, being position:relative and later in the
   DOM, painted above an overlay pinned at z-index 0. Measured at 1440px: 42
   dead points inside the card, all resolving to LI. The three tick lines did
   nothing on click while the gaps around them navigated, and the pointer
   cursor implied the whole column was clickable.

   Fix: give the text column its own positioning context and resolve the
   overlay against that, so the overlay covers exactly the half that is
   meant to be the link. The two wrappers are also declared here, since
   neither stylesheet had a rule for them and the layout worked only because
   they happened to be the two grid children.
   ---------------------------------------------------------------------- */
.gx-segment__main { position: relative; min-width: 0; }
.gx-segment__aside { min-width: 0; }

.gx-segment--wide .gx-segment__link::after { inset: 0; z-index: 1; }

/* Nothing inside the link's own column should out-paint the overlay. */
.gx-segment--wide .gx-segment__main > * { position: static; }

@media (max-width: 1023px) {
	/* Single column below the breakpoint, so the aside sits under the text
	   rather than beside it and the overlay still covers only the text. */
	.gx-segment--wide { grid-template-columns: minmax(0, 1fr); gap: 28px; }
}

/* ------------------------------------------------------------------------
   2. The mobile nav panel must be able to scroll.

   The open panel is a fixed-position 401px block with no max-height. On any
   viewport shorter than about 500px — every phone in landscape, and a 360x420
   browser window — "Contact" and the Request a Quote button fell outside the
   viewport, and because the panel is fixed, scrolling the page could not
   reach them. That button is the only conversion action on the site.
   ---------------------------------------------------------------------- */
@media (max-width: 1023px) {
	.gx-nav__panel {
		max-height: calc(100dvh - var(--gx-nav-h));
		overflow-y: auto;
		overscroll-behavior: contain;
	}
}

/* dvh is well supported but not universal; vh is a safe floor. */
@supports not (height: 100dvh) {
	@media (max-width: 1023px) {
		.gx-nav__panel { max-height: calc(100vh - var(--gx-nav-h)); }
	}
}

/* ------------------------------------------------------------------------
   6. Statistic figures must stay inside their card.

   .gx-stat__value is white-space: nowrap at 32px mono inside a 2-up grid.
   Measured with IBM Plex Mono loaded: "1,500+" cleared its card's content box
   by 8px at 360px and overflowed by 12px at 320px, rendering across the
   border. The page never gained a horizontal scrollbar because the tracks are
   minmax(0, 1fr), so the defect is invisible to an overflow check.

   These figures are editable from the admin, so the fix has to hold for
   values nobody has typed yet, not just the four in the design.
   ---------------------------------------------------------------------- */
@media (max-width: 767px) {
	:root { --gx-fs-stat: 28px; }
}

@media (max-width: 400px) {
	.gx-stats__grid,
	.gx-metrics { grid-template-columns: minmax(0, 1fr); }
}

/* ------------------------------------------------------------------------
   5 + 8. Reduced motion.

   The handoff's reduced-motion block is otherwise correct — every .js-scoped
   opacity:0 reveal state is properly reset, which is the usual bug here and
   is not present. Two things did go wrong.

   The brand wall is a 3008px row inside an overflow:hidden mask, frozen at
   translateX(0) with no scroll affordance, so a reduced-motion visitor saw 2
   of 8 logos per row at 360px — and the pause button that might have offered
   a way through is itself display:none. Wrapping the rows makes all 24
   reachable without motion.

   And hiding the pause buttons left their containers behind: a 0-height box
   with 40px, 64px or 96px of margin, reading as an unexplained gap.
   ---------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
	.gx-brands__mask {
		-webkit-mask-image: none;
		mask-image: none;
		overflow: visible;
	}

	.gx-brands__row {
		width: auto;
		flex-wrap: wrap;
		justify-content: center;
	}

	/* The duplicated set exists only to make the marquee seamless. With the
	   marquee gone it is 24 redundant tiles. */
	.gx-brands__set[aria-hidden="true"] { display: none; }

	/* Containers of the now-hidden pause buttons. */
	.gx-hero__motion,
	.gx-cta__motion,
	.gx-brands__controls,
	.gx-quote-block__controls { display: none; }
}

/* ------------------------------------------------------------------------
   9. Keep the keyboard focus ring on the sent-state heading.

   .gx-sent__title:focus { outline: none } is 0,2,0 and beat the global
   :focus-visible ring at 0,1,0, suppressing the ring for keyboard users too.
   The heading is tabindex="-1" and normally only receives scripted focus, so
   the practical impact is small — but it is the one unconditional outline
   removal in the handoff, and unconditional outline removals get copied.
   ---------------------------------------------------------------------- */
.gx-sent__title:focus { outline: 3px solid var(--gx-focus); outline-offset: 2px; }
.gx-sent__title:focus:not(:focus-visible) { outline: none; }

/* ------------------------------------------------------------------------
   Windows High Contrast / forced colours.

   The design carries meaning in fills and tinted bands, both of which are
   replaced by the user's own colours in forced-colours mode. Borders survive,
   so anything that was identified only by its fill gets one.
   ---------------------------------------------------------------------- */
@media (forced-colors: active) {
	.gx-btn--primary,
	.gx-btn--secondary { border: 2px solid ButtonText; }

	.gx-solution,
	.gx-segment,
	.gx-cat,
	.gx-grade__card,
	.gx-contact__card,
	.gx-contact__form-card,
	.gx-metric,
	.gx-stat { border: 1px solid CanvasText; }

	.gx-dot { border: 1px solid ButtonText; }
	.gx-dot.is-active { background: Highlight; }

	.gx-particles { display: none; }
}
