/*
 * Keyboard focus: the one focus system (Spec 32 §14.5, FR-32-22).
 * The core is the outline (it survives forced colours); the inner hairline and the bloom are box-shadow layers.
 * Every arm carries :not(#wpadminbar *, ...), which gives the list (1,1,0) weight so it owns outline, outline-offset
 * and box-shadow on a focused element. Blocks change the look ONLY through the --sgs-focus-* custom properties below
 * (the override contract); a bespoke outline or box-shadow on a :focus* selector fails check-focus-system.js.
 * G1 (accent) and G2 (duotone) are token values; G3 (signature) is the .sgs-focus--signature class.
 * A host with its own border sets --sgs-focus-host-border to that border's width, so the G3 band sits outside the ring.
 * Two optional site tokens shape the whole look: settings.custom.focus.offset (--wp--custom--focus--offset, a length; the
 * gap between the element and the ring, default the width) and settings.custom.focus.bloom (--wp--custom--focus--bloom,
 * a number 0 to 1 scaling the near and far glow, default 1; 0 is no glow). settings.custom.focus.style
 * (--wp--custom--focus--style) is the ring's outline-style, default solid; `auto` paints the browser's own ring.
 * settings.custom.focus.ringOnly (--wp--custom--focus--ring-only, 1 or 0, default 0) at 1 drops the hairline and the glow,
 * so the focused element shows the ring and keeps its resting shadow (--sgs-focus-under). An absent token leaves today's
 * rendering unchanged.
 */
@property --sgs-focus-angle { syntax: "<angle>"; inherits: false; initial-value: 0deg; }
@keyframes sgs-focus-spin { to { --sgs-focus-angle: 360deg; } }
/* The per-element overrides are set on the focusable element itself and must not reach its descendants: an inset card
   would otherwise hand its inset ring and halo to a swatch inside it, and a shadowed card its shadow. Registered with
   no initial value, so an unset property is still guaranteed-invalid and every var() fallback below keeps working.
   --sgs-focus-host-border is deliberately not registered: the signature ::before reads it from its host, and a pseudo-element
   inherits only through inheritance. */
@property --sgs-focus-offset { syntax: "*"; inherits: false; }
@property --sgs-focus-halo { syntax: "*"; inherits: false; }
@property --sgs-focus-under { syntax: "*"; inherits: false; }

/* 1. Tokens: the client's snapshot (settings.custom.focus -> --wp--custom--focus--*), framework defaults from the palette.
   The painted hairline is --sgs-focus-hairline: the inner token on G1, and on G2 and G3 the ground's band, the other half
   of the two-tone pair (the light inner token on a light ground, the ink on a dark one), so the core and the hairline
   are never the same colour and one of them always reaches 3:1 on a photo. --sgs-focus-ring-on-light is the light-ground
   ring on every ground, so a block whose surface turns light at a breakpoint can take it. */
/* --sgs-focus-keep is 1, or 0 under the ringOnly switch: it scales the hairline and the glow layers to nothing. */
:root {
	--sgs-focus-keep: calc(1 - var(--wp--custom--focus--ring-only, 0));
}
:root,
.sgs-on-light,
.sgs-on-dark {
	--sgs-focus-ring-on-light: var(--wp--custom--focus--ring, var(--wp--preset--color--primary-dark, var(--wp--custom--focus--ink, var(--wp--preset--color--text, #0b1020))));
}
:root,
.sgs-on-light {
	--sgs-focus-width: var(--wp--custom--focus--width, 2px);
	--sgs-focus-inner: var(--wp--custom--focus--inner, var(--wp--preset--color--surface, #fff));
	--sgs-focus-ink: var(--wp--custom--focus--ink, var(--wp--preset--color--text, #0b1020));
	--sgs-focus-ring: var(--wp--custom--focus--ring, var(--wp--preset--color--primary-dark, var(--sgs-focus-ink)));
	--sgs-focus-ground-core: var(--sgs-focus-ink);
	--sgs-focus-ground-band: var(--sgs-focus-inner);
	--sgs-focus-hairline: var(--sgs-focus-inner);
	--sgs-focus-near: var(--wp--custom--focus--near, var(--sgs-focus-ring));
	--sgs-focus-far: var(--wp--custom--focus--far, var(--sgs-focus-ring));
	--sgs-focus-sig-a: var(--wp--custom--focus--signature-a, var(--wp--preset--color--primary));
	--sgs-focus-sig-b: var(--wp--custom--focus--signature-b, var(--wp--preset--color--accent));
	--sgs-focus-sig-c: var(--wp--custom--focus--signature-c, var(--wp--preset--color--accent-light));
}
.sgs-on-dark {
	--sgs-focus-ground-core: var(--sgs-focus-inner);
	--sgs-focus-ground-band: var(--sgs-focus-ink);
	--sgs-focus-hairline: var(--sgs-focus-inner);
	--sgs-focus-ring: var(--wp--custom--focus--ring-on-dark, var(--wp--preset--color--accent, var(--sgs-focus-inner)));
	--sgs-focus-near: var(--wp--custom--focus--near-on-dark, var(--sgs-focus-ring));
	--sgs-focus-far: var(--wp--custom--focus--far-on-dark, var(--sgs-focus-ring));
}
/* G2 wherever the ground is a photo or video, or an element asks for it. Later than .sgs-on-dark on purpose.
   The core is --sgs-focus-ground-core, which the nearest ground class sets (ink on light, the light inner token on dark),
   so a light pill inside a dark block keeps the dark core: inheritance picks the nearest ground, a "dark ancestor"
   selector could not. A block marks an always-light surface with .sgs-on-light and an always-dark one with .sgs-on-dark. */
.sgs-container--has-bg-image,
.sgs-container--has-bg-video,
.sgs-focus--duotone {
	--sgs-focus-ring: var(--sgs-focus-ground-core);
	--sgs-focus-hairline: var(--sgs-focus-ground-band);
	--sgs-focus-near: var(--sgs-focus-inner);
	--sgs-focus-far: var(--sgs-focus-ink);
}
/* Inside a clipping or full-bleed container: the ring sits on the element's edge, the hairline inside it. */
.sgs-focus--inset,
.sgs-focus--inset.sgs-focus-card > .sgs-block-link-overlay {
	--sgs-focus-offset: calc(var(--sgs-focus-width) * -1);
	--sgs-focus-halo: inset 0 0 0 calc(var(--sgs-focus-width) * 2 * var(--sgs-focus-keep, 1)) var(--sgs-focus-hairline);
}

/* 2. The indicator: one declaration set, six arms (element, adjacent proxy, scoped proxy, card proxy, card overlay, editor preview).
   A card whose stretched link (`.sgs-focus-source`, with a `::after` overlay covering the card) holds focus rings the
   whole card, because the overlay is a pseudo-element and an outline on the link would wrap only its own text box.
   A card that also carries the block-link overlay (`.sgs-block-link-overlay`, positioned above the card's media) rings
   that overlay too: an outline on the card itself paints below its positioned children, so the overlay carries the same
   ring over the photo. */
:focus-visible:not(#wpadminbar *, .editor-styles-wrapper :is([contenteditable], .block-editor-block-list__block, .components-button, [class*="block-editor-"]), [tabindex="-1"], .sgs-focus-source, input[type="range"]),
.sgs-focus-source:focus-visible + .sgs-focus-proxy:not(#wpadminbar *),
.sgs-focus-scope:has(.sgs-focus-source:focus-visible) .sgs-focus-proxy:not(#wpadminbar *),
.sgs-focus-card:has(.sgs-focus-source:focus-visible):not(#wpadminbar *),
.sgs-focus-card:has(.sgs-focus-source:focus-visible) > .sgs-block-link-overlay:not(#wpadminbar *),
.sgs-focus-preview:not(#wpadminbar *) {
	outline: var(--sgs-focus-width) var(--wp--custom--focus--style, solid) var(--sgs-focus-ring);
	outline-offset: var(--sgs-focus-offset, var(--wp--custom--focus--offset, var(--sgs-focus-width)));
	box-shadow:
		var(--sgs-focus-halo,
			0 0 0 calc(var(--sgs-focus-offset, var(--wp--custom--focus--offset, var(--sgs-focus-width))) * var(--sgs-focus-keep, 1)) var(--sgs-focus-hairline),
			0 0 calc(var(--sgs-focus-width) * 6) calc(var(--sgs-focus-width) * 2) color-mix(in srgb, var(--sgs-focus-near) calc(55% * var(--wp--custom--focus--bloom, 1) * var(--sgs-focus-keep, 1)), transparent),
			0 0 calc(var(--sgs-focus-width) * 15) calc(var(--sgs-focus-width) * 5) color-mix(in srgb, var(--sgs-focus-far) calc(30% * var(--wp--custom--focus--bloom, 1) * var(--sgs-focus-keep, 1)), transparent)),
		var(--sgs-focus-under, 0 0 #0000);
}
/* The ringOnly switch, exactly: where style queries run, the focused element's box-shadow is its resting shadow alone
   (none when it hands in none), so its computed value equals an unfocused one. Elsewhere --sgs-focus-keep has already
   scaled the hairline and glow layers to nothing. */
@container style(--wp--custom--focus--ring-only: 1) {
	:focus-visible:not(#wpadminbar *, .editor-styles-wrapper :is([contenteditable], .block-editor-block-list__block, .components-button, [class*="block-editor-"]), [tabindex="-1"], .sgs-focus-source, input[type="range"]),
	.sgs-focus-source:focus-visible + .sgs-focus-proxy:not(#wpadminbar *),
	.sgs-focus-scope:has(.sgs-focus-source:focus-visible) .sgs-focus-proxy:not(#wpadminbar *),
	.sgs-focus-card:has(.sgs-focus-source:focus-visible):not(#wpadminbar *),
	.sgs-focus-card:has(.sgs-focus-source:focus-visible) > .sgs-block-link-overlay:not(#wpadminbar *),
	.sgs-focus-preview:not(#wpadminbar *) {
		box-shadow: var(--sgs-focus-under, none);
	}
}
/* A focus source draws nothing itself: its proxy (adjacent, scoped or the card) carries the one ring. */
.sgs-focus-source:focus-visible:not(#wpadminbar *) {
	outline-style: none;
}

/* Sliders: the thumb carries the ring (one rule per engine; an unknown pseudo-element drops the whole rule). */
input[type="range"]:not(.sgs-focus-source):focus-visible:not(#wpadminbar *)::-webkit-slider-thumb {
	outline: var(--sgs-focus-width) solid var(--sgs-focus-ring);
	outline-offset: var(--sgs-focus-width);
	box-shadow: 0 0 0 var(--sgs-focus-width) var(--sgs-focus-hairline);
}
input[type="range"]:not(.sgs-focus-source):focus-visible:not(#wpadminbar *)::-moz-range-thumb {
	outline: var(--sgs-focus-width) solid var(--sgs-focus-ring);
	outline-offset: var(--sgs-focus-width);
	box-shadow: 0 0 0 var(--sgs-focus-width) var(--sgs-focus-hairline);
}

/* The slider itself draws no ring, or the browser's default ring would wrap the whole track beside the thumb's. */
input[type="range"]:not(.sgs-focus-source):focus-visible:not(#wpadminbar *) {
	outline-style: none;
}

/* Without :has() (Firefox before 121) the selector list above is invalid and the browser drops the whole rule, so this
   branch restates the arms that need no :has(): the element, the adjacent proxy, the editor preview, and a card's own
   focus source, which rings itself because no card ancestor can. The scoped proxy and the card ring need :has(). */
@supports not selector(:has(*)) {
	:focus-visible:not(#wpadminbar *, .editor-styles-wrapper :is([contenteditable], .block-editor-block-list__block, .components-button, [class*="block-editor-"]), [tabindex="-1"], .sgs-focus-source, input[type="range"]),
	.sgs-focus-source:focus-visible + .sgs-focus-proxy:not(#wpadminbar *),
	.sgs-focus-card .sgs-focus-source:focus-visible:not(#wpadminbar *),
	.sgs-focus-preview:not(#wpadminbar *) {
		outline: var(--sgs-focus-width) var(--wp--custom--focus--style, solid) var(--sgs-focus-ring);
		outline-offset: var(--sgs-focus-offset, var(--wp--custom--focus--offset, var(--sgs-focus-width)));
		box-shadow:
			var(--sgs-focus-halo,
				0 0 0 calc(var(--sgs-focus-offset, var(--wp--custom--focus--offset, var(--sgs-focus-width))) * var(--sgs-focus-keep, 1)) var(--sgs-focus-hairline),
				0 0 calc(var(--sgs-focus-width) * 6) calc(var(--sgs-focus-width) * 2) color-mix(in srgb, var(--sgs-focus-near) calc(55% * var(--wp--custom--focus--bloom, 1) * var(--sgs-focus-keep, 1)), transparent),
				0 0 calc(var(--sgs-focus-width) * 15) calc(var(--sgs-focus-width) * 5) color-mix(in srgb, var(--sgs-focus-far) calc(30% * var(--wp--custom--focus--bloom, 1) * var(--sgs-focus-keep, 1)), transparent)),
			var(--sgs-focus-under, 0 0 #0000);
	}
	@media (forced-colors: active) {
		:focus-visible:not(#wpadminbar *, .editor-styles-wrapper :is([contenteditable], .block-editor-block-list__block, .components-button, [class*="block-editor-"]), [tabindex="-1"], .sgs-focus-source, input[type="range"]),
		.sgs-focus-source:focus-visible + .sgs-focus-proxy:not(#wpadminbar *),
		.sgs-focus-card .sgs-focus-source:focus-visible:not(#wpadminbar *),
		.sgs-focus-preview:not(#wpadminbar *) {
			outline: var(--sgs-focus-width) solid Highlight;
			box-shadow: none;
		}
	}
}

/* Browsers without color-mix(): the core and the hairline, no bloom. */
@supports not (color: color-mix(in srgb, red 50%, transparent)) {
	:root, .sgs-on-light, .sgs-on-dark { --sgs-focus-near: transparent; --sgs-focus-far: transparent; }
	.sgs-focus--signature::before { display: none; }
}

/* 3. G3 signature: a G2 core plus a rotating conic border in the client's own colours (opt-in per button). */
.sgs-focus--signature { position: relative; }
.sgs-focus--signature:focus-visible:not(#wpadminbar *),
.sgs-focus--signature.sgs-focus-preview:not(#wpadminbar *) {
	--sgs-focus-ring: var(--sgs-focus-ground-core);
	--sgs-focus-hairline: var(--sgs-focus-ground-band);
	--sgs-focus-near: var(--sgs-focus-sig-b);
	--sgs-focus-far: var(--sgs-focus-sig-a);
}
@supports (mask-composite: exclude) {
	/* Anchored to the host's border box: the band runs from 2x to 3x the width outside it, beyond the ring. */
	.sgs-focus--signature:focus-visible:not(#wpadminbar *)::before,
	.sgs-focus--signature.sgs-focus-preview:not(#wpadminbar *)::before {
		content: "";
		position: absolute;
		inset: calc(var(--sgs-focus-width) * -3 - var(--sgs-focus-host-border, 0px));
		padding: var(--sgs-focus-width);
		border-radius: inherit;
		background: conic-gradient(from var(--sgs-focus-angle), var(--sgs-focus-sig-a), var(--sgs-focus-sig-b), var(--sgs-focus-sig-c), var(--sgs-focus-sig-a));
		mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
		mask-composite: exclude;
		pointer-events: none;
		animation: sgs-focus-spin 3s linear infinite;
	}
}

/* 4. Preferences. */
@media (prefers-reduced-motion: reduce) {
	.sgs-focus--signature:focus-visible:not(#wpadminbar *)::before,
	.sgs-focus--signature.sgs-focus-preview:not(#wpadminbar *)::before { animation: none; }
}
@media (prefers-contrast: more) {
	:root, .sgs-on-light, .sgs-on-dark, .sgs-container--has-bg-image, .sgs-container--has-bg-video, .sgs-focus--duotone {
		--sgs-focus-width: 3px;
		--sgs-focus-ring: var(--sgs-focus-ink);
		--sgs-focus-near: transparent;
		--sgs-focus-far: transparent;
	}
	.sgs-container--has-bg-image, .sgs-container--has-bg-video, .sgs-focus--duotone {
		--sgs-focus-ring: var(--sgs-focus-ground-core);
		--sgs-focus-near: transparent;
		--sgs-focus-far: transparent;
	}
	.sgs-focus--signature:focus-visible:not(#wpadminbar *),
	.sgs-focus--signature.sgs-focus-preview:not(#wpadminbar *) { --sgs-focus-near: transparent; --sgs-focus-far: transparent; }
	.sgs-focus--signature:focus-visible:not(#wpadminbar *)::before,
	.sgs-focus--signature.sgs-focus-preview:not(#wpadminbar *)::before { display: none; }
}
/* Forced colours: every arm repeated with its own selector, so equal weight and later source order paint a solid
   Highlight core and drop the shadows. */
@media (forced-colors: active) {
	:focus-visible:not(#wpadminbar *, .editor-styles-wrapper :is([contenteditable], .block-editor-block-list__block, .components-button, [class*="block-editor-"]), [tabindex="-1"], .sgs-focus-source, input[type="range"]),
	.sgs-focus-source:focus-visible + .sgs-focus-proxy:not(#wpadminbar *),
	.sgs-focus-scope:has(.sgs-focus-source:focus-visible) .sgs-focus-proxy:not(#wpadminbar *),
	.sgs-focus-card:has(.sgs-focus-source:focus-visible):not(#wpadminbar *),
	.sgs-focus-card:has(.sgs-focus-source:focus-visible) > .sgs-block-link-overlay:not(#wpadminbar *),
	.sgs-focus-preview:not(#wpadminbar *) {
		outline: var(--sgs-focus-width) solid Highlight;
		box-shadow: none;
	}
	input[type="range"]:not(.sgs-focus-source):focus-visible:not(#wpadminbar *)::-webkit-slider-thumb {
		outline: var(--sgs-focus-width) solid Highlight;
		outline-offset: var(--sgs-focus-width);
		box-shadow: none;
	}
	input[type="range"]:not(.sgs-focus-source):focus-visible:not(#wpadminbar *)::-moz-range-thumb {
		outline: var(--sgs-focus-width) solid Highlight;
		outline-offset: var(--sgs-focus-width);
		box-shadow: none;
	}
	.sgs-focus--signature::before { display: none; }
}
