/* ============================================================================
   GPH Design System v2 — light-DOM layer
   Quiet-luxury elevation. Self-contained. Additive. Reversible.

   This file holds the parts of the design system that live in the LIGHT DOM:
   the token :root block (also the source the JS clones into a constructable
   sheet for shadow roots), plus all sitewide discipline, flourishes and the
   bold tier. Components that already declare their own --gph-* keep working;
   these tokens are the cascade fallback + the new scales.

   Tiering:
     A  tokens (this :root)            — sitewide
     B  discipline (focus/motion/etc.) — sitewide, prod-safe
     C  flourishes (skel/dialog)       — sitewide, prod-safe
     D  bold tier                      — gated behind html.gph-ds-bold
   ========================================================================== */

/* ===========================================================================
   A. ONE TOKEN SOURCE OF TRUTH
   Canonical hex base kept EXACTLY as shipped so nothing shifts visually.
   State + tint/muted colours are DERIVED with color-mix(in oklch, …) so they
   stay harmonically tied to the brand base instead of being hand-picked.
   =========================================================================== */
:root {
	/* --- canonical brand base (unchanged hex) --- */
	--gph-gold-light: #c4a66a;
	--gph-gold:       #aa8c57;
	--gph-gold-dark:  #8b6f2e;
	--gph-teal:       #2a8676;
	--gph-ink:        #1d1d1d;
	--gph-ink-soft:   #3a3a3a;
	--gph-paper:      #faf8f5;
	--gph-edge:       #ece5d4;
	--gph-grey:       #6f6f6f;
	--gph-grey-soft:  #9a937f;
	--gph-white:      #ffffff;

	/* --- derived state colours (oklch mixing → harmonic, not hand-picked) --- */
	/* hover = nudge toward dark; active = a touch further. */
	--gph-gold-hover:  color-mix(in oklch, var(--gph-gold) 86%, #000);
	--gph-gold-active: color-mix(in oklch, var(--gph-gold) 78%, #000);
	--gph-teal-hover:  color-mix(in oklch, var(--gph-teal) 86%, #000);
	--gph-teal-active: color-mix(in oklch, var(--gph-teal) 78%, #000);

	/* --- tints / muteds (translucent washes of the brand colours) --- */
	--gph-gold-tint:   color-mix(in oklch, var(--gph-gold) 22%, transparent); /* ≈ rgba(170,140,87,.22) — matches exit-intent fallback */
	--gph-gold-muted:  color-mix(in oklch, var(--gph-gold) 10%, transparent);
	--gph-teal-tint:   color-mix(in oklch, var(--gph-teal) 18%, transparent);
	--gph-teal-muted:  color-mix(in oklch, var(--gph-teal) 9%,  transparent);
	--gph-ink-tint:    color-mix(in oklch, var(--gph-ink)  8%,  transparent);

	/* focus ring colour — gold, WCAG-visible against paper & dark surfaces. */
	--gph-focus:       var(--gph-gold-dark);
	--gph-focus-tint:  color-mix(in oklch, var(--gph-gold) 35%, transparent);

	/* --- radius (kept identical to editor-canvas) --- */
	--gph-radius-sm:   6px;
	--gph-radius-md:   10px;
	--gph-radius-lg:   16px;
	--gph-radius-pill: 999px;

	/* --- spacing scale (new) --- */
	--gph-space-1: 4px;
	--gph-space-2: 8px;
	--gph-space-3: 16px;
	--gph-space-4: 24px;
	--gph-space-5: 40px;
	--gph-space-6: 64px;

	/* --- UNIFIED elevation ramp (new).
	   Layered low-opacity shadows = "smooth" depth, not one harsh drop.
	   Each step stacks an ambient + a key shadow. Tuned for a cream page. --- */
	--gph-elev-1:
		0 1px 2px rgba(29,29,29,.05),
		0 1px 1px rgba(29,29,29,.04);
	--gph-elev-2:
		0 2px 4px rgba(29,29,29,.05),
		0 6px 12px -6px rgba(29,29,29,.10);
	--gph-elev-3:
		0 2px 6px rgba(29,29,29,.05),
		0 12px 28px -10px rgba(29,29,29,.14);
	--gph-elev-4:
		0 4px 10px rgba(29,29,29,.06),
		0 26px 56px -18px rgba(29,29,29,.22);

	/* Back-compat aliases for the three legacy shadow tokens so any component
	   reading them maps onto the unified ramp (values are visually equivalent). */
	--gph-shadow-sm: var(--gph-elev-1);
	--gph-shadow-md: var(--gph-elev-3);
	--gph-shadow-lg: var(--gph-elev-4);

	/* --- motion tokens (new) --- */
	--gph-dur-fast: 140ms;
	--gph-dur-base: 240ms;
	--gph-dur-slow: 420ms;
	--gph-ease-out:    cubic-bezier(.22,.61,.36,1);
	/* restrained spring — a single gentle overshoot, no bounce-fest. */
	--gph-ease-spring: linear(
		0, 0.0036 1.59%, 0.0145 3.27%, 0.0867 8.42%, 0.1939 13.71%,
		0.4669 25.31%, 0.5762 30.56%, 0.6657 35.71%, 0.7402 40.94%,
		0.8004 46.27%, 0.8482 51.78%, 0.8849 57.5%, 0.9131 63.61%,
		0.9343 70.18%, 0.9498 77.34%, 0.9607 85.3%, 0.9676 94.27%, 0.9707 100%
	);
}

/* ===========================================================================
   B. SITEWIDE DISCIPLINE  (prod-safe)
   =========================================================================== */

/* B1. Branded gold :focus-visible ring on every interactive element.
   Mouse clicks stay clean (no ring); keyboard/AT focus is clearly visible.
   We deliberately do NOT use a blanket `outline:none`. */
a:focus-visible,
button:focus-visible,
[role="button"]:focus-visible,
[tabindex]:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[contenteditable]:focus-visible,
.button:focus-visible,
.wp-block-button__link:focus-visible {
	outline: 2px solid var(--gph-focus, #8b6f2e);
	outline-offset: 2px;
	border-radius: var(--gph-radius-sm, 6px);
	box-shadow: 0 0 0 4px var(--gph-focus-tint, rgba(170,140,87,.35));
}
/* Inputs already have a border-radius — keep the ring snug to their shape. */
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
	border-radius: inherit;
}

/* B2. Branded form-control accent + selection. */
input[type="checkbox"],
input[type="radio"],
input[type="range"],
progress,
select {
	accent-color: var(--gph-teal, #2a8676);
}
::selection {
	background: color-mix(in oklch, var(--gph-teal, #2a8676) 22%, transparent);
	color: var(--gph-ink, #1d1d1d);
}

/* B3. Smooth scroll (reduced-motion-guarded below). */
@media (prefers-reduced-motion: no-preference) {
	html { scroll-behavior: smooth; }
}

/* B4. field-sizing: content — textareas grow with their content.
   Progressive: only applied where supported, so no layout risk elsewhere. */
@supports (field-sizing: content) {
	textarea.gph-grow,
	.gph-enquiry textarea,
	.gph-quote-form textarea,
	textarea[data-gph-grow] {
		field-sizing: content;
		max-height: 40vh;
	}
}

/* B5. The reduced-motion guard.
   The audit found motion stilling was only partial. This is the sitewide
   backstop: neutralise transitions, animations, smooth scroll, and the
   known Ken-Burns / scroll-reveal / stagger utilities. Light DOM here; the
   same rules are injected into shadow roots by the JS. */
@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after {
		animation-duration: .001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: .001ms !important;
		scroll-behavior: auto !important;
	}
	html { scroll-behavior: auto !important; }
	/* Known motion utilities seen in the audit. */
	.gph-kenburns,
	.gph-ken-burns,
	[class*="kenburns"],
	[class*="ken-burns"],
	.gphhl-hero__slide img,
	.gph-hero__media img {
		animation: none !important;
		transform: none !important;
	}
	/* Scroll-reveal: show immediately, don't hold content hidden. */
	.gph-reveal,
	[data-gph-reveal],
	.gph-stagger > * {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
	}
}

/* ===========================================================================
   C. TASTEFUL FLOURISHES — SAFE TIER  (prod-safe)
   =========================================================================== */

/* C1. Skeleton shimmer loading utility.
   Apply .gph-skel to a placeholder box (e.g. an image wrapper) while the
   real asset loads; remove the class (or it self-clears via :has) when ready. */
.gph-skel {
	position: relative;
	overflow: hidden;
	background: color-mix(in oklch, var(--gph-edge, #ece5d4) 70%, var(--gph-paper, #faf8f5));
	border-radius: var(--gph-radius-md, 10px);
}
.gph-skel::after {
	content: "";
	position: absolute;
	inset: 0;
	transform: translateX(-100%);
	background: linear-gradient(
		90deg,
		transparent 0,
		color-mix(in oklch, #fff 55%, transparent) 45%,
		color-mix(in oklch, #fff 55%, transparent) 55%,
		transparent 100%
	);
	animation: gph-skel-sweep 1.4s ease-in-out infinite;
}
/* An image wrapper that already contains a fully-loaded image stops shimmering. */
.gph-skel:has(img.gph-loaded)::after { animation: none; content: none; }
@keyframes gph-skel-sweep {
	100% { transform: translateX(100%); }
}
@media (prefers-reduced-motion: reduce) {
	.gph-skel::after { animation: none; }
}

/* C2. Dialog / popover entry + exit via @starting-style + allow-discrete.
   Pure CSS, progressive, reduced-motion off. Covers native <dialog>, the
   popover API, and the project's known modal panels when they sit in a
   <dialog>. We DON'T force any modal into a dialog — this only enhances
   ones that already are / become top-layer. */
@supports (transition-behavior: allow-discrete) and (overlay: auto) {
	@media (prefers-reduced-motion: no-preference) {
		dialog,
		[popover] {
			transition:
				opacity var(--gph-dur-base, 240ms) var(--gph-ease-out, ease),
				transform var(--gph-dur-base, 240ms) var(--gph-ease-out, ease),
				overlay var(--gph-dur-base, 240ms) allow-discrete,
				display var(--gph-dur-base, 240ms) allow-discrete;
		}
		dialog:not([open]),
		[popover]:not(:popover-open) {
			opacity: 0;
			transform: translateY(8px) scale(.99);
		}
		dialog[open],
		[popover]:popover-open {
			opacity: 1;
			transform: none;
		}
		@starting-style {
			dialog[open],
			[popover]:popover-open {
				opacity: 0;
				transform: translateY(8px) scale(.99);
			}
		}
	}
}

/* C3. Blurred dialog backdrop — soft frosted scrim, on top of the existing
   dim. Guarded so unsupported browsers just get the dim. */
@supports (backdrop-filter: blur(2px)) {
	dialog::backdrop {
		backdrop-filter: blur(3px) saturate(105%);
		-webkit-backdrop-filter: blur(3px) saturate(105%);
		background: color-mix(in oklch, var(--gph-ink, #1d1d1d) 28%, transparent);
	}
}

/* ===========================================================================
   D. BOLD TIER — gated behind html.gph-ds-bold (staging only on prod).
   Toggle option `gph_ds_bold` (default OFF on prod, ON on staging) adds the
   class. Everything here is additionally @supports- and reduced-motion-guarded.
   =========================================================================== */

/* D1. Restrained gold-sheen sweep across the PRIMARY CTA on hover.
   Animated @property gradient angle → GPU-cheap, one slow pass. */
@property --gph-sheen {
	syntax: "<angle>";
	inherits: false;
	initial-value: 0deg;
}
@media (prefers-reduced-motion: no-preference) {
	html.gph-ds-bold .gph-quote-btn,
	html.gph-ds-bold .gph-enquiry-cta,
	html.gph-ds-bold .gphhd__cta,
	html.gph-ds-bold .wp-block-button.is-style-fill .wp-block-button__link {
		position: relative;
		overflow: hidden;
		isolation: isolate;
	}
	html.gph-ds-bold .gph-quote-btn::after,
	html.gph-ds-bold .gph-enquiry-cta::after,
	html.gph-ds-bold .gphhd__cta::after,
	html.gph-ds-bold .wp-block-button.is-style-fill .wp-block-button__link::after {
		content: "";
		position: absolute;
		inset: 0;
		z-index: -1;
		background: linear-gradient(
			var(--gph-sheen),
			transparent 35%,
			color-mix(in oklch, #fff 55%, transparent) 50%,
			transparent 65%
		);
		opacity: 0;
		transition: opacity var(--gph-dur-fast, 140ms) var(--gph-ease-out, ease);
	}
	html.gph-ds-bold .gph-quote-btn:hover::after,
	html.gph-ds-bold .gph-enquiry-cta:hover::after,
	html.gph-ds-bold .gphhd__cta:hover::after,
	html.gph-ds-bold .wp-block-button.is-style-fill .wp-block-button__link:hover::after {
		opacity: 1;
		animation: gph-sheen-sweep 900ms var(--gph-ease-out, ease);
	}
}
@keyframes gph-sheen-sweep {
	from { --gph-sheen: 120deg; }
	to   { --gph-sheen: 300deg; }
}

/* D2. Glass header on scroll. The JS toggles html.gph-scrolled. */
@supports (backdrop-filter: blur(8px)) {
	html.gph-ds-bold.gph-scrolled .gphhd,
	html.gph-ds-bold.gph-scrolled .gphhd__main,
	html.gph-ds-bold.gph-scrolled header.site-header {
		backdrop-filter: blur(10px) saturate(120%);
		-webkit-backdrop-filter: blur(10px) saturate(120%);
		background: color-mix(in oklch, var(--gph-paper, #faf8f5) 78%, transparent);
		transition: background var(--gph-dur-base, 240ms) var(--gph-ease-out, ease);
	}
}

/* D3. Cross-document page-morph view transition.
   NOTE: `@view-transition{navigation:auto}` is a top-level at-rule that can't be
   scoped to html.gph-ds-bold. It is therefore emitted from PHP ONLY when the
   bold flag is on (so it never reaches prod). The root-animation tuning below
   is harmless without it and stays here, class-gated. Tuned gentle so it
   doesn't fight the already-shipped shared-element transition (gallery hero). */
@supports (view-transition-name: none) {
	@media (prefers-reduced-motion: no-preference) {
		html.gph-ds-bold::view-transition-old(root),
		html.gph-ds-bold::view-transition-new(root) {
			animation-duration: var(--gph-dur-base, 240ms);
			animation-timing-function: var(--gph-ease-out, ease);
		}
	}
}
