/**
 * IQ Components — shared base.
 *
 * Token fallbacks below mirror the PHP defaults in Tokens::schema(); the
 * authoritative values are injected as :root custom properties via
 * wp_add_inline_style('iqbc-base', ...). Fallbacks only matter if the inline
 * block is missing (e.g. aggressive optimization plugins).
 */

/* Focus indicator — WCAG 2.4.7 (focus visible), 2.4.13-friendly thickness.
   :focus-visible keeps mouse clicks ring-free without harming keyboard use. */
.iq-button:focus-visible,
.iq-dark-mode-toggle:focus-visible,
.iq-tabs__tab:focus-visible,
.iq-tabs__title:focus-visible,
.iq-tabs__panel:focus-visible,
.iq-accordion__trigger:focus-visible,
.iq-disclosure__trigger:focus-visible,
.iq-field__control:focus-visible,
.iq-skip-link:focus-visible,
.iq-alert__dismiss:focus-visible,
/* E8's dismiss button is exactly E1's case: a square glyph control inside a
   panel, whose own radius is `radius-sm` anyway, so the shared rule's
   `border-radius` rewrite changes nothing. `.iq-toast` itself is deliberately
   absent and takes its own copy in iq-toast.css — it is a landing target for
   the removal ladder, so it CAN hold focus, and the rewrite would square a
   16px panel for the duration (the .iq-alert / .iq-badge case exactly). */
.iq-toast__dismiss:focus-visible,
.iq-modal__close:focus-visible,
.iq-drawer__close:focus-visible,
/* The panel scroll regions, which iq-panel.js makes a tab stop only while they
   actually overflow — same case as .iq-tabs__panel above: a focusable region
   that paints nothing of its own still needs an indicator (2.4.7).
   ONE DIFFERENCE, and it is in iq-panel.css rather than here because it is those
   elements' geometry, not the shared contract: the region fills a scroll
   container with a radius, and an outline is not part of scrollable overflow, so
   the OFFSET below is inverted there to draw the ring inside. Measured: three of
   the four sides were clipped away without it. Colour, width and radius are the
   shared ones. */
.iq-modal__body:focus-visible,
.iq-drawer__body:focus-visible,
/* And the toggletip's panel (E7), which is the same case reached a different way:
   it keeps F1's block cap and `overflow: auto`, so it can scroll, and it carries
   tabindex="0" from PHP rather than from a script — because unlike the two
   above, it opens declaratively from `popovertarget` with the script blocked,
   and a tab stop that only existed when JS ran would be missing in exactly the
   no-JS configuration the element promises still works. It takes the same
   inverted offset, in iq-tooltip.css, for the same reason. Its TOOLTIP twin is
   deliberately absent from this list and must stay absent: that panel is never
   focusable. */
.iq-toggletip__panel:focus-visible,
/* E18's error summary, and its links. The CONTAINER is the same case as the
   three regions above — a focusable box that paints no indicator of its own —
   reached from a different direction: it is not a scroll region, it is a
   `tabindex="-1"` landing target that a failed submit moves focus to. Measured
   before this line, it got nothing at all after a MOUSE submit
   (`:focus-visible` false, `outline: none`) and the UA's own
   `currentColor auto 3px` after a KEYBOARD one — neither of which is the
   library's contract, and the second of which is not `--iq-color-focus-ring`.
   `:focus-visible` rather than `:focus` is deliberate and matches every region
   above: a mouse user who never sees a caret should not be shown a ring on a box
   the script focused for them.
   The `border-radius` rewrite below is a no-op on the CONTAINER, and for a real
   reason — its own radius already IS `radius-sm`, so the line restates it. It is
   NOT a no-op on the link, and this comment used to say it was: an `outline`
   follows its element's `border-radius` whether or not anything else is painted,
   so on a box that paints nothing the token rounds the RING. Measured in E23's
   round 4 on `.iq-toc__link` (4px -> 19px when the token is dialled), and the
   mechanism is the property's, not that element's. */
.iq-form__summary:focus-visible,
.iq-form__summary-link:focus-visible,
/* E27's result region: the summary's recipe — a `tabindex="-1"` box focus is
   moved to on success or on a form-level refusal — so it takes the summary's
   ring for the summary's reason. */
.iq-form__result:focus-visible,
/* E24's landing marker, and it is E18's case exactly: a `tabindex="-1"`
   box that a jump moves focus to and that paints nothing of its own, so without
   this line it gets whatever the UA happens to draw rather than the library's
   ring. Its document-level twin, `[data-iq-skip-target]`, is deliberately NOT
   here and must stay out: that node is the site owner's markup, and restyling
   somebody else's element because we sent focus to it is not this library's to
   do (iq-skip-link.css only ever removes an indicator the UA itself declined).
   This marker is ours, so it takes the contract. The `border-radius` rewrite is
   NOT a no-op here either (see the E18 note above): it rounds the ring's own
   corner, which is why `radius-sm` belongs in an element's token group wherever
   this selector list reaches it. E24 already offers it. */
.iq-skip-section__end:focus-visible,
/* E13's card link, and it is HALF of that element's indicator rather than all of
   it. This ring hugs the title text — 1.5% of the card's area on the canonical
   fixture (1.3–5.4% across the eight) against a hit area the overlay makes
   100% — so iq-card.css adds a second outline on the CARD, and the two say
   different things: this one *is a link*, that one *this whole box is
   the target*. */
.iq-card__link:focus-visible,
/* E23's contents-list link. What it paints of its own is a `border-width-thick`
   inline-start rail carrying the current-section state (2px at the shipped
   default), which the ring surrounds rather than replaces — the two say
   different things and both are visible at once.

   THE `border-radius` LINE BELOW IS NOT A NO-OP ON EITHER OF THESE TWO, which is
   what the comment here used to claim on the grounds that neither anchor paints
   a fill or a border of its own. An `outline` follows its element's
   `border-radius` regardless: with nothing else painted, the token rounds the
   RING. Measured by the E23 verifier — dialling `--iq-radius-sm` to 19px on the
   element root moves the focused link's painted corner from 4px to 19px. E23
   therefore offers `radius-sm` in its token group, and E25 has since closed the
   same gap on `.iq-card__link` (E13 shipped without it and card.md recorded it
   as open). Every element whose rules this selector list reaches now offers the
   token. */
.iq-toc__link:focus-visible {
	outline: var(--iq-focus-ring-width, 3px) solid var(--iq-color-focus-ring, #1442cc);
	outline-offset: var(--iq-focus-ring-offset, 2px);
	border-radius: var(--iq-radius-sm, 4px);
}

/* Every node this library sends focus to, whoever owns the markup: Bricks'
   `main#brx-content`, a configured skip-link target, the `iq-skip-section`
   element's end marker (E4/E24) and — since E23 — every heading an `iq-toc`
   links to. `scroll-margin-block-start` keeps a `position: fixed` sticky header
   from covering the thing the browser just scrolled to; R13's default is 0px, so
   it changes nothing until a site owner measures their header.

   THE MARK IS LOAD-BEARING, not a diagnostic. Measured with a 140px offset: a
   marked target lands at y 140 and an unmarked one at y 0, because the token
   lives on this selector and nowhere else. E23 additionally READS it back — its
   scrollspy takes the line that decides "which section am I in" from the
   target's own computed `scroll-margin-block-start`, so the highlight and the
   place a click lands cannot disagree.

   It lives in the base rather than in iq-skip-link.css (where E4 wrote it)
   because two elements in different stylesheets now depend on it, and the
   alternatives were a second copy or a cross-element style dependency. */
[data-iq-skip-target] {
	scroll-margin-block-start: var(--iq-scroll-offset, 0px);
}

/* A `tabindex="-1"` landing target is not keyboard-reachable, so WCAG 2.4.7 does
   not govern it — but this deliberately does NOT remove the landing indicator
   wholesale. It only bites where the UA itself declines one (pointer-driven
   focus). MEASURED, Chrome 2026-08: after keyboard activation `:focus-visible`
   DOES match the target, so the browser's own ring is painted around the whole
   landed-on node and this rule does nothing there. That is the intended outcome,
   not an oversight: removing an indicator the UA chose to show is a worse
   default than a large one, and a site that dislikes it owns the override.
   E23 is where the pointer half earns its keep — a `tabindex="-1"` heading is
   focusable by CLICK, so without this rule clicking a heading's text would ring
   it. */
[data-iq-skip-target]:focus:not(:focus-visible) {
	outline: none;
}

/* Three components are deliberately NOT in that list, for the same measured
   reason: the `border-radius` declaration above REWRITES the focused element's
   own radius. `.iq-alert` would visibly square a large panel for the duration
   of a focus, `.iq-badge` would go from a 999px pill to a 4px box, and
   `.iq-field__option-control` (E16) would square a RADIO — measured, a
   `border-radius: 50%` radio taking this rule computes `border-radius: 4px`
   while focused, i.e. the indicator changes the shape that says "one answer
   only" for exactly as long as anyone is looking at it. All three declare the
   identical ring in their own stylesheets, minus that line. If the radius
   declaration is ever removed from here, fold them back in. */

/* Motion — WCAG 2.3.3: all component transitions collapse to 0 when the user
   prefers reduced motion.

   Every duration token has an `-effective` MIRROR declared here and zeroed in
   the reduced-motion block below, and components must only ever transition via
   a mirror — never via --iq-duration* directly. The mirrors are the only thing
   enforcing 2.3.3: a new duration wired straight into a `transition` looks
   correct and silently ignores the user's preference. Adding a duration token
   means adding its mirror in BOTH blocks.

   Easing tokens need no mirror — a timing function over a 0ms duration is
   inert, so they are referenced directly.

   The mirrors are declared on every COMPONENT ROOT as well as on :root, and
   that is not redundancy. A custom property whose value contains var() is
   substituted at computed-value time *on the element where it is declared*: a
   mirror declared only on :root resolves against :root's --iq-duration-* and
   descendants inherit the already-substituted result, so a per-element
   `#brxe-* { --iq-duration: 50ms }` override from the builder would be
   substituted nowhere and silently do nothing. Re-declaring the mirror on the
   component root makes the override re-derive there. (Same constraint that
   forces Tokens::to_css() to repeat scheme-aware tokens in every scheme block —
   see docs/architecture.md.)

   :root must keep them regardless: ::view-transition-* pseudo-elements inherit
   from the document element, not from the component that is transitioning. */
:root,
.iq-button,
.iq-tabs,
.iq-accordion,
.iq-disclosure,
.iq-dark-mode-toggle,
.iq-field,
.iq-alert,
.iq-badges,
.iq-modal,
.iq-drawer,
.iq-dropdown,
.iq-tooltip,
.iq-toggletip,
/* E8's element root, not the toast: the toast is created by script inside it
   and inherits the substituted value, while a per-element `#brxe-*` duration
   override from the builder lands on the ROOT and has to re-derive there. */
.iq-toasts,
/* E13. The card transitions exactly one property — its hover fill — and the
   mirror has to be re-declared here for the usual substitution reason: a
   per-element `#brxe-* { --iq-duration-fast: … }` override from the builder lands
   on this root and only re-derives where the mirror is declared. */
.iq-card,
/* E21. Both roots transition the fill's inline-size, and .iq-progress
   additionally spins its ring off the FOURTH mirror below. `.iq-stat` is
   deliberately absent and must stay absent: a published statistic never moves,
   so it declares no transition and no animation at all (the `.iq-copy`
   precedent — a root with nothing to animate does not join this list). */
.iq-progress,
.iq-meter {
	--iq-duration-fast-effective: var(--iq-duration-fast, 120ms);
	--iq-duration-effective: var(--iq-duration, 200ms);
	--iq-duration-slow-effective: var(--iq-duration-slow, 320ms);

	/* R19 / E21 — the fourth mirror, and the first one that is not a transition
	   tier: one revolution of the spinner. It is declared on the whole list
	   rather than on .iq-progress alone for the same reason the other three are
	   (a per-element `#brxe-* { --iq-spin-duration: … }` override only re-derives
	   where the mirror is declared), and because a list that is the same for
	   three mirrors and different for the fourth is the thing a later reader
	   "tidies". Zeroed below: an infinite rotation at 0ms is never created, so
	   the ring simply renders at rest (WCAG 2.3.3). */
	--iq-spin-duration-effective: var(--iq-spin-duration, 900ms);

	/* Disabled fade, as the percentage color-mix() wants: an opacity of 0.5
	   means mixing 50% toward `transparent`. Derived here rather than inlined
	   at ~a dozen use sites, and declared on the same selector list for the
	   same substitution reason as the mirrors above.

	   Controls fade their fill, border and label separately with this — never
	   with `opacity` on the element, which would fade the focus ring too. An
	   [aria-disabled="true"] control is still focusable, so its ring must keep
	   full contrast (WCAG 1.4.11 / 2.4.7). */
	--iq-disabled-fade: calc(100% * (1 - var(--iq-opacity-disabled, 0.5)));
}

:root {
	/* Elevation ramp. Unlike the other tokens these are NOT repeated as
	   var(--x, fallback) at each use site — a two-layer box-shadow inlined
	   everywhere is unreadable. Declaring them here instead is equivalent: the
	   inline token stylesheet is printed after this file, so its :root / .light
	   / .dark blocks all override these at equal-or-higher precedence. If the
	   inline block is ever stripped, components degrade to the correct
	   light-mode elevation rather than to none. */
	--iq-shadow-sm: 0 1px 2px -1px rgb(15 23 42 / 0.08), 0 1px 3px 0 rgb(15 23 42 / 0.1);
	--iq-shadow-md: 0 2px 4px -2px rgb(15 23 42 / 0.08), 0 4px 6px -1px rgb(15 23 42 / 0.1);
	--iq-shadow-lg: 0 4px 6px -4px rgb(15 23 42 / 0.1), 0 10px 15px -3px rgb(15 23 42 / 0.12);

	/* Modern size interpolation: lets height/width transition to/from intrinsic
	   keywords (auto, max-content, ...). Inherited; ignored (= no animation,
	   instant toggle) by browsers without support — progressive enhancement. */
	interpolate-size: allow-keywords;
}

/* Same selector list as the mirror block above — a component root that
   re-derives its mirrors must also be able to zero them, or a per-element
   duration override would survive prefers-reduced-motion (WCAG 2.3.3). */
@media (prefers-reduced-motion: reduce) {
	:root,
	.iq-button,
	.iq-tabs,
	.iq-accordion,
	.iq-disclosure,
	.iq-dark-mode-toggle,
	.iq-field,
	.iq-alert,
	.iq-badges,
	.iq-modal,
	.iq-drawer,
	.iq-dropdown,
	.iq-tooltip,
	.iq-toggletip,
	.iq-toasts,
	.iq-card,
	.iq-progress,
	.iq-meter {
		--iq-duration-fast-effective: 0ms;
		--iq-duration-effective: 0ms;
		--iq-duration-slow-effective: 0ms;
		--iq-spin-duration-effective: 0ms;
	}
}

/* Visually hidden but exposed to assistive tech — carries accessible names for
   icon-only controls (WCAG 4.1.2). */
.iq-sr-only {
	position: absolute;
	inline-size: 1px;
	block-size: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* Dark mode.
   Color tokens are re-declared by the inline token stylesheet on :root, inside
   @media (prefers-color-scheme: dark), and on .light / .dark (in that order, so
   an explicit class always wins). See includes/class-dark-mode.php. Nothing in
   the static stylesheets may hard-code a color that a token could carry. */
