/**
 * Accessibility: the one focus indicator on the site, on everything that takes keyboard focus.
 * The settings are the default for the whole site, as custom properties on :root (frontend.php).
 * A builder or theme sets the same properties on a wrapper, a class or a single element, and the
 * nearest one counts:
 *
 *   --ds-a11y-focus          the colour on light backgrounds
 *   --ds-a11y-focus-dark     the colour on dark backgrounds
 *   --ds-a11y-focus-width    the width, never less than 2px
 *   --ds-a11y-focus-offset   the space between an element and the indicator
 *   --ds-a11y-focus-style    solid, dashed, dotted or double; anything else counts as solid
 *
 * A mode is chosen with a class or a data-ds-focus attribute, on an element or on a wrapper for
 * everything focusable inside it; nested, own beats inset and inset beats ring:
 *
 *   ds-focus-ring    a box-shadow against the edge instead of the outline
 *   ds-focus-inset   the outline inside the element, for a parent with overflow: hidden
 *   ds-focus-own     nothing from here: the element keeps a focus style of its own, and with it
 *                    the job of meeting WCAG
 *
 * The rules here only read those properties and never set them. What they work out goes into
 * private ones (--_ds-a11y-*), declared on the element with focus alone.
 *
 * accessibility.js gives the element that gets focus a class for the colour it needs, from what
 * is behind it and the contrast of the colours there: ds-a11y-on-dark for the colour on dark;
 * ds-a11y-on-mixed for two tones, the outline in the light colour over a band in the dark one,
 * where the background can be light or dark (a picture, a video) or where neither colour alone
 * reaches 3:1; ds-a11y-fallback for the same in black over white, where even the two together do
 * not.
 *
 * Breakdance and WooCommerce turn the outline off on many fields, at rest or on :focus, in the
 * cart and checkout, in forms, the search form, select2 dropdowns and the faceted filters, some of
 * them with the weight of four classes. :not(#ds-a11y), an id that no element has, matches every
 * element and gives the rules here the weight of an id, so they win from any rule with classes
 * only, without !important; :where() adds nothing. The outline rule weighs (1,3,1), as in 1.0:
 * :is() counts as its heaviest part, [tabindex]:not([tabindex="-1"]) at (0,2,0). The private
 * properties weigh (1,1,1), the colours and the band (1,2,1), as the band did in 1.0, the modes
 * (1,4,1), and inset with two tones (1,5,1). focus-builders.css stays below all of them.
 */

/* An unknown style, or none, is not taken: the outline stays solid. */
@property --ds-a11y-focus-style {
	syntax: "solid | dashed | dotted | double";
	inherits: true;
	initial-value: solid;
}

/* What the indicator is, for the element with focus. */
body :focus-visible:not(#ds-a11y):where(:not(.ds-focus-own, .ds-focus-own *, [data-ds-focus="own"], [data-ds-focus="own"] *)) {
	--_ds-a11y-w: max(2px, var(--ds-a11y-focus-width, 3px));
	--_ds-a11y-o: var(--ds-a11y-focus-offset, 2px);
	--_ds-a11y-c: var(--ds-a11y-focus, #000);
	--_ds-a11y-band: var(--ds-a11y-focus-dark, #fff);
}

body .ds-a11y-on-dark:focus-visible:not(#ds-a11y):where(:not(.ds-focus-own, .ds-focus-own *, [data-ds-focus="own"], [data-ds-focus="own"] *)) {
	--_ds-a11y-c: var(--ds-a11y-focus-dark, #fff);
}

body .ds-a11y-fallback:focus-visible:not(#ds-a11y):where(:not(.ds-focus-own, .ds-focus-own *, [data-ds-focus="own"], [data-ds-focus="own"] *)) {
	--_ds-a11y-c: #000;
	--_ds-a11y-band: #fff;
}

/* The outline. */
body :is(a[href], area[href], button, input:not([type="hidden"]), select, textarea, summary, [tabindex]:not([tabindex="-1"]), [role="button"], [role="link"], [role="tab"], [role="checkbox"], [role="radio"], [role="switch"], [contenteditable="true"], .button-atom):focus-visible:not(#ds-a11y):where(:not(.ds-focus-own, .ds-focus-own *, [data-ds-focus="own"], [data-ds-focus="own"] *)) {
	outline-width: var(--_ds-a11y-w);
	outline-style: var(--ds-a11y-focus-style, solid);
	outline-color: var(--_ds-a11y-outline, var(--_ds-a11y-c));
	outline-offset: var(--_ds-a11y-offset, var(--_ds-a11y-o));
}

/* Two tones: the band, from the element's edge to beyond the outline, which is drawn over it. */
body :is(.ds-a11y-on-mixed, .ds-a11y-fallback):focus-visible:not(#ds-a11y):where(:not(.ds-focus-own, .ds-focus-own *, [data-ds-focus="own"], [data-ds-focus="own"] *)) {
	--_ds-a11y-two: 1;
	box-shadow: 0 0 0 calc(var(--_ds-a11y-o) + 2 * var(--_ds-a11y-w)) var(--_ds-a11y-band);
}

/* Ring: a box-shadow of the same width against the edge, a second one outside it for two tones.
   The outline stays, transparent, for Windows' contrast themes, which show it and drop shadows. */
body :is(a[href], area[href], button, input:not([type="hidden"]), select, textarea, summary, [tabindex]:not([tabindex="-1"]), [role="button"], [role="link"], [role="tab"], [role="checkbox"], [role="radio"], [role="switch"], [contenteditable="true"], .button-atom):is(.ds-focus-ring, .ds-focus-ring *, [data-ds-focus="ring"], [data-ds-focus="ring"] *):focus-visible:not(#ds-a11y):where(:not(.ds-focus-own, .ds-focus-own *, [data-ds-focus="own"], [data-ds-focus="own"] *, .ds-focus-inset, .ds-focus-inset *, [data-ds-focus="inset"], [data-ds-focus="inset"] *)) {
	--_ds-a11y-outline: transparent;
	box-shadow: 0 0 0 var(--_ds-a11y-w) var(--_ds-a11y-c), 0 0 0 calc(2 * var(--_ds-a11y-w) * var(--_ds-a11y-two, 0)) var(--_ds-a11y-band);
}

/* Inset: the outline inside the element, the offset between it and the edge. */
body :is(a[href], area[href], button, input:not([type="hidden"]), select, textarea, summary, [tabindex]:not([tabindex="-1"]), [role="button"], [role="link"], [role="tab"], [role="checkbox"], [role="radio"], [role="switch"], [contenteditable="true"], .button-atom):is(.ds-focus-inset, .ds-focus-inset *, [data-ds-focus="inset"], [data-ds-focus="inset"] *):focus-visible:not(#ds-a11y):where(:not(.ds-focus-own, .ds-focus-own *, [data-ds-focus="own"], [data-ds-focus="own"] *)) {
	--_ds-a11y-offset: calc(-1 * (var(--_ds-a11y-w) + var(--_ds-a11y-o)));
}

body :is(a[href], area[href], button, input:not([type="hidden"]), select, textarea, summary, [tabindex]:not([tabindex="-1"]), [role="button"], [role="link"], [role="tab"], [role="checkbox"], [role="radio"], [role="switch"], [contenteditable="true"], .button-atom):is(.ds-focus-inset, .ds-focus-inset *, [data-ds-focus="inset"], [data-ds-focus="inset"] *):is(.ds-a11y-on-mixed, .ds-a11y-fallback):focus-visible:not(#ds-a11y):where(:not(.ds-focus-own, .ds-focus-own *, [data-ds-focus="own"], [data-ds-focus="own"] *)) {
	box-shadow: inset 0 0 0 calc(var(--_ds-a11y-o) + 2 * var(--_ds-a11y-w)) var(--_ds-a11y-band);
}

/* The range inputs of the price slider in WooCommerce's product filter block keep their own focus
   style against anything less than !important, as the audits found. */
body .wc-block-product-filter-price-slider__range input[type="range"]:focus-visible:where(:not(.ds-focus-own, .ds-focus-own *, [data-ds-focus="own"], [data-ds-focus="own"] *)) {
	outline-width: var(--_ds-a11y-w) !important;
	outline-style: var(--ds-a11y-focus-style, solid) !important;
	outline-color: var(--_ds-a11y-outline, var(--_ds-a11y-c)) !important;
	outline-offset: var(--_ds-a11y-offset, var(--_ds-a11y-o)) !important;
}
