/**
 * iq-dropdown — the first element on F1's POPOVER path, and the first that is
 * not a <dialog> at all. Registered as a dependent of `iqbc-layer`, so the print
 * order is
 *
 *     iqbc-base → iqbc-layer → iqbc-dropdown
 *
 * and `.iq-dropdown__panel` wins over `.iq-layer` at the equal 0-1-0 specificity
 * they share. It does NOT depend on `iqbc-panel`: that file is the chrome of a
 * NAMED REGION with a header, a close button, a scroller and a sticky footer,
 * and a dropdown has none of the five. See docs/elements/dropdown.md § Reuse.
 *
 * WHAT COMES FROM F1 AND IS NOT REPEATED HERE: `box-sizing`, the dynamic-viewport
 * cap on the block axis, `overscroll-behavior`, the `display: none !important`
 * guard that keeps a closed popover closed under Bricks' `.brxe-block { display:
 * flex }` — measured to be load-bearing, a closed `[popover]` that is also a
 * Bricks block hit-tests to itself — and the forced-colours `border: 1px solid
 * CanvasText` every layer gets. The INLINE cap is overridden below, because a
 * dropdown is a measure of its own items rather than of the viewport.
 *
 * WHAT F1 DELIBERATELY DOES NOT GIVE THIS ELEMENT: a scrim. `dialog.iq-layer::
 * backdrop` is scoped to dialogs precisely so a dropdown does not dim the page.
 * A popover DOES generate a ::backdrop box (measured — unlike a `show()`n
 * dialog, which generates none) but it is `pointer-events: none` and can never
 * capture a click, so nothing may be painted there that this element needs.
 *
 * PLACEMENT IS TWO IMPLEMENTATIONS OF ONE GUARANTEE, and the guarantee is WCAG
 * 1.4.10: the panel never leaves the viewport at 320px. The CSS path is anchor
 * positioning (`position-area` + `position-try-fallbacks`); the fallback is
 * measured by iq-dropdown.js and published back into the two custom properties
 * at the bottom of this file, where the viewport clamp is still expressed with
 * the `--iq-space-md` token rather than with a number in JavaScript. Note the
 * classic idiom is NOT available on this path: a `[popover]` is in the top
 * layer, which has no containing block but the viewport, so `position: absolute`
 * inside a `position: relative` wrapper resolves against the initial containing
 * block — measured, a panel authored at `top: 100%` of a trigger at y=20 landed
 * at y=700.
 *
 * Audited pairings: every pair this element creates already exists in
 * Contrast::relations() — text and the panel edge on `color-surface-raised`, the
 * focus ring on it, and the item label on `color-surface-alt` when hovered
 * (the "hovered accordion trigger or tab" row, which is the same meeting). The
 * two non-rows — the hover fill against the panel fill, and the divider — are
 * argued in class-contrast.php and in docs/elements/dropdown.md § Contrast.
 */

/* The component root. `inline-block` so the root hugs its trigger: the hover
   affordance below opens on `mouseenter` of THIS box, and a root stretched to
   the container's full width would open the panel from anywhere in that band.
   `position: relative` does nothing for the top-layer panel — it is here for the
   builder's "keep open while styling" path at the end of this file, where the
   panel is taken out of the top layer and laid out in flow. */
.iq-dropdown {
	position: relative;
	display: inline-block;
	max-inline-size: 100%;
}

/* The companion to the `display` above — the same 2.1.1 guard as the item rule
   at the end of § Items, and needed for the same reason one line up rather than
   one hundred: an unlayered author `display` on an .iq-* node beats both the UA
   `[hidden] { display: none }` and Bricks' layered `[hidden], template` reset.
   Measured without it, on a root given `hidden` through Bricks' `_attributes`
   repeater: `display: inline-block`, 138x44, `checkVisibility() === true`, the
   trigger still `tabIndex 0`, still focusable, and a click still opened the
   panel — a whole menu an author had asked to be gone. */
.iq-dropdown[hidden] {
	display: none !important;
}

/* The trigger is an `.iq-button` and takes its fill, size tier, focus ring,
   disabled fade and forced-colours border from iq-button.css — which is why
   this element enqueues that handle. What is added here is the chevron row.

   `anchor-name` is NOT declared here: it has to be unique per instance or every
   panel on a query-loop page anchors to the LAST trigger in tree order
   (measured: three triggers sharing one name, all three panels landed on the
   third). PHP mints it per render and writes it inline — see
   class-dropdown.php § anchor_name(). */
.iq-dropdown__trigger {
	max-inline-size: 100%;
}

/* Drawn from `currentColor` and declaring no colour of its own, so Chrome's
   `forced-color-adjust: preserve-parent-color` on <svg> hands it the button's
   FORCED colour instead of leaking an author one (F4 — the measured leak). */
.iq-dropdown__chevron {
	flex: none;
	inline-size: var(--iq-icon-size, 1.25em);
	block-size: var(--iq-icon-size, 1.25em);
	transition: rotate var(--iq-duration-fast-effective, 120ms) var(--iq-ease-out, cubic-bezier(0.22, 1, 0.36, 1));
}

/* The open affordance, and it is deliberately driven by `:has(:popover-open)`
   rather than by `[aria-expanded="true"]`: aria-expanded is written by
   iq-dropdown.js, and this way the chevron still turns on the NO-JS path, where
   the panel is opened by the trigger's own `popovertarget` attribute and no
   script has run. */
.iq-dropdown:has(.iq-dropdown__panel:popover-open) .iq-dropdown__chevron {
	rotate: 180deg;
}

/* ─── The panel ──────────────────────────────────────────────────────────── */

.iq-dropdown__panel {
	/* Shrink-to-fit the items, then two caps. The inline cap REPLACES F1's
	   (same 0-1-0 specificity, later source order, which is why this file
	   declares iqbc-layer as a dependency): `--iq-panel-width` is R14's measure
	   of a floating panel and is the right ceiling for a menu of labels, while
	   the viewport term is F1's own guarantee kept verbatim so the 1.4.10 claim
	   is not weakened by the override. `min-inline-size` matches the trigger,
	   which is what makes a dropdown look attached rather than dropped nearby;
	   it lives in the @supports block below because `anchor-size()` needs an
	   anchor. */
	inline-size: max-content;
	max-inline-size: min(var(--iq-panel-width, 32em), calc(100dvw - 2 * var(--iq-space-md, 1rem)));
	/* A column of full-width rows, and `display: block` was not enough: a
	   `<button>`'s `width: auto` is intrinsic rather than stretch, so an authored
	   Bricks Button sat at its own text width while an authored link filled the
	   panel — measured, four items at 79 / 113 / 124 / 153px inside a 157px panel.
	   `align-items: stretch` is the flex default and is declared anyway, because
	   Bricks sets `align-items: flex-start` on its own blocks and a future
	   selector change should not be able to reintroduce the ragged column. */
	display: flex;
	flex-direction: column;
	align-items: stretch;
	/* The UA gives `[popover]` `inset: 0; margin: auto`, which centres it in the
	   viewport. Both are cancelled here so the placement rules below decide. */
	margin: 0;
	/* THE PADDING IS THE FOCUS RING'S CLEARANCE, which is why it is a max() and
	   not a spacing step — the same formula and the same reason as
	   `--iq-panel-pad` in iq-panel.css. An outline is drawn OUTSIDE the border
	   box and is not part of scrollable overflow, so `overflow: auto` on this
	   panel clips it: measured at one spacing step of padding, the focused item's
	   ring had 2.3px of clearance where it needs `focus-ring-offset +
	   focus-ring-width` = 5px, and three of its four sides were cut. */
	padding: max(var(--iq-space-2xs, 0.125rem), calc(var(--iq-focus-ring-width, 3px) + var(--iq-focus-ring-offset, 2px)));
	/* The panel's boundary against arbitrary page content, and unlike a modal's
	   there is no scrim under it to help — a dropdown must not dim the page. The
	   fill is opaque and the edge is the STRONG border token, audited against
	   that fill at 4.83:1 light / 5.07:1 dark, so what is behind is irrelevant to
	   the 1.4.11 question. Elevation carries the depth and is discarded under
	   forced colours; the edge is what survives, which is why it is not
	   decoration. */
	border: var(--iq-border-width, 1px) solid var(--iq-color-border, #6b7280);
	border-radius: var(--iq-radius-md, 8px);
	background: var(--iq-color-surface-raised, #ffffff);
	color: var(--iq-color-text, #1f2937);
	box-shadow: var(--iq-shadow-md);

	/* Entrance and exit (WCAG 2.3.3 via the -effective mirrors, which
	   `.iq-dropdown` re-derives through the selector list in iq-base.css — never
	   --iq-duration-fast directly). FAST is the right tier: a dropdown does not
	   change the page's shape, it is pointer feedback, and a visible ramp on it
	   reads as lag. `display` AND `overlay` both need allow-discrete — without
	   `overlay` the panel leaves the top layer the instant it is hidden and the
	   exit plays behind the page. */
	opacity: 0;
	translate: 0 calc(-1 * var(--iq-space-2xs, 0.125rem));
	transition: opacity var(--iq-duration-fast-effective, 120ms) var(--iq-ease-in, cubic-bezier(0.32, 0, 0.67, 0)),
		translate var(--iq-duration-fast-effective, 120ms) var(--iq-ease-in, cubic-bezier(0.32, 0, 0.67, 0)),
		display var(--iq-duration-fast-effective, 120ms) allow-discrete,
		overlay var(--iq-duration-fast-effective, 120ms) allow-discrete;
}

/* The panel's companion, and F1's closed-popover guard is NOT it: that rule is
   `:not(:popover-open)`, so it stops applying the moment the panel opens, and
   from there `display: flex` above is all that is left. Measured on a bare page
   with no author CSS at all, the UA hides an OPEN popover that carries `hidden`
   (`display: none`, `checkVisibility() === false`); with a `display` on the
   element it stays `flex` and painted. This restores that parity — it is the
   platform's answer, not a new one. */
.iq-dropdown__panel[hidden] {
	display: none !important;
}

.iq-dropdown__panel:popover-open {
	opacity: 1;
	translate: none;
	/* Entrances ease out, exits ease in — a split that is only real where both
	   halves exist as separate declarations, and here they do. */
	transition-timing-function: var(--iq-ease-out, cubic-bezier(0.22, 1, 0.36, 1));
}

/* The open state's starting point. Without it the panel simply appears at its
   open values: a transition needs a before-change style, and an element that was
   `display: none` a frame ago has none. */
@starting-style {
	.iq-dropdown__panel:popover-open {
		opacity: 0;
		translate: 0 calc(-1 * var(--iq-space-2xs, 0.125rem));
	}
}

/* ─── Placement, path 1: CSS anchor positioning ──────────────────────────── */

/* Chrome and Edge take this path today. `@supports` is the whole feature gate —
   an engine without anchor positioning never sees these declarations and gets
   the JS-measured path at the bottom of the file instead. Both are tested;
   docs/elements/dropdown.md § Placement says which browsers get which.

   `position-area: block-end span-inline-*` is what puts the panel FLUSH under
   the trigger — measured gap 0.0px — and that zero is load-bearing rather than
   cosmetic: WCAG 1.4.13 requires a hover-opened panel to be HOVERABLE, which
   means the pointer must be able to travel from the trigger into the panel
   without crossing anything else. A gap would need a bridging safe area; no gap
   needs nothing.

   `position-try-fallbacks: flip-inline, flip-block` is the 320px answer. What it
   does NOT do is shrink the panel — measured, a 614px panel at a 320px viewport
   stayed 614px — so the `max-inline-size` cap above is what actually holds
   1.4.10, and the fallbacks only decide which way it opens. */
@supports (position-area: block-end) and (position-try-fallbacks: flip-block) {
	.iq-dropdown__panel {
		/* `position-anchor` is written inline per instance by PHP (see the note
		   on the trigger above); this only says what to do with it. */
		position: fixed;
		inset: auto;
		min-inline-size: anchor-size(width);
		position-area: block-end span-inline-end;
		position-try-fallbacks: flip-inline, flip-block;
	}

	/* Aligned to the trigger's inline END instead — the right-hand dropdown of a
	   header bar. `span-inline-start` means "the centre column plus the
	   inline-start one", i.e. the panel's inline-end edge meets the anchor's. It
	   is logical, so it follows `dir` with no RTL branch. */
	.iq-dropdown--align-inline-end .iq-dropdown__panel {
		position-area: block-end span-inline-start;
	}
}

/* ─── Items ──────────────────────────────────────────────────────────────── */

/* The items are AUTHORED Bricks children, so they cannot be selected by a class
   this element owns — the selector is structural, and that is also why the focus
   ring below is declared here rather than joining the shared list in
   iq-base.css, which names classes. It is the same three declarations, and if
   the shared ring ever changes this rule must follow it.

   `.iq-button` is excluded: an IQ button dropped into a dropdown is meant to
   look like a button, and this rule would repaint it. A nested dropdown's own
   trigger is an `.iq-button` too, so the exclusion covers that as well. */
.iq-dropdown__panel :is(a[href], button, [role='menuitem']):not(.iq-button) {
	display: flex;
	align-items: center;
	gap: var(--iq-space-sm, 0.5rem);
	/* 24px is the WCAG 2.5.8 minimum target size — a constant of the success
	   criterion rather than a design decision, so it is deliberately not
	   tokenized, and max() holds it against a per-element builder override,
	   which never passes through Tokens::sanitize(). */
	min-block-size: max(24px, var(--iq-tap-target-min, 44px));
	padding: var(--iq-space-xs, 0.25rem) var(--iq-space-sm, 0.5rem);
	border-radius: var(--iq-radius-sm, 4px);
	/* AN ITEM IS A ROW ON THE PANEL, NOT A FREE-FLOATING CONTROL, and both of
	   these declarations are what make the audited pairing true rather than
	   approximate. Without the colour an authored link takes the theme's link
	   colour; without the transparent fill an authored Bricks Button keeps its
	   own grey — measured, `rgb(239, 239, 239)` under a label this rule had just
	   repainted `color-text`. Either way the label would be sitting on a colour
	   Contrast::relations() cannot see. With both, the pair is exactly its "Text
	   on a floating panel" row. An author who genuinely wants a coloured item
	   still has one: a `#brxe-*` rule from the Style tab is 1-0-0 and beats this
	   0-3-1 selector, and an `.iq-button` is excluded outright. */
	background-color: transparent;
	color: var(--iq-color-text, #1f2937);
	text-decoration: none;
	overflow-wrap: anywhere;
	cursor: pointer;
	transition: background-color var(--iq-duration-fast-effective, 120ms) var(--iq-ease-out, cubic-bezier(0.22, 1, 0.36, 1));
}

/* THE COMPANION TO THE `display: flex` ABOVE, AND IT IS A 2.1.1 GUARD RATHER
   THAN TIDINESS. The rule above is an unlayered author declaration, so it beats
   both the UA `[hidden] { display: none }` and Bricks' layered
   `[hidden], template { display: none }` reset — measured, a `hidden` item stayed
   at `display: flex`, 153x44, `checkVisibility() === true`, hit-testing to itself
   and firing its own click handler. iq-dropdown.js's walkOf() filters
   `hasAttribute('hidden')`, so the same item had no keyboard route at all: a
   visible, mouse-operable `role="menuitem"` that Enter, the arrows, Home/End,
   typeahead and Tab all skipped. This is the companion every other IQ display
   override already carries (iq-alert, iq-badge, iq-tabs, iq-copy-button). */
.iq-dropdown__panel :is(a[href], button, [role='menuitem']):not(.iq-button)[hidden] {
	display: none !important;
}

/* An unfilled surface opts out of the state-mix and declares its own hover pair
   (architecture.md § Interaction states) — and the pair is the one the surface
   ramp already names for this exact job: `color-surface-alt` is "hovered rows".
   It is the accordion trigger's and the disclosure trigger's rule verbatim, so
   the pairing is the audited "Text on a hovered accordion trigger or tab" row
   and this element adds no relation. */
.iq-dropdown__panel :is(a[href], button, [role='menuitem']):not(.iq-button):hover:not([aria-disabled='true']),
.iq-dropdown__panel :is(a[href], button, [role='menuitem']):not(.iq-button):focus-visible {
	background: var(--iq-color-surface-alt, #f3f4f6);
}

.iq-dropdown__panel :is(a[href], button, [role='menuitem']):not(.iq-button):focus-visible {
	outline: var(--iq-focus-ring-width, 3px) solid var(--iq-color-focus-ring, #1442cc);
	outline-offset: var(--iq-focus-ring-offset, 2px);
}

/* A disabled item is `[aria-disabled="true"]`, never `disabled`: it stays
   focusable and stays in the roving order (the APG rule iq-tabs.js already
   follows), so its focus ring must keep full contrast — which is why the fade
   is applied to the LABEL rather than as `opacity` on the item.

   THE SECOND SELECTOR IS NOT A DUPLICATE. The item rule above is 0-3-1
   (`a[href]` inside the `:is()` carries a type selector, and `:not(.iq-button)`
   adds another class), so a plain `.iq-dropdown__panel [aria-disabled]` at 0-2-0
   loses to it and the fade silently did nothing — measured, the disabled item
   painted the identical colour as an enabled one. The first selector still
   earns its place: it covers a disabled node that is none of the three item
   shapes. */
.iq-dropdown__panel [aria-disabled='true'],
.iq-dropdown__panel :is(a[href], button, [role='menuitem']):not(.iq-button)[aria-disabled='true'] {
	color: color-mix(in oklab, var(--iq-color-text, #1f2937), transparent var(--iq-disabled-fade, 50%));
	cursor: not-allowed;
}

/* An authored <hr> between groups of items. A divider INSIDE a box the panel's
   own border already bounds is the one place `color-border-subtle` is correct
   (architecture.md § Strong vs subtle borders): it identifies nothing on its
   own, so 1.4.11 does not govern it and it is deliberately not in
   Contrast::relations(). */
.iq-dropdown__panel hr {
	block-size: 0;
	margin: var(--iq-space-2xs, 0.125rem) 0;
	border: 0;
	border-block-start: var(--iq-border-width, 1px) solid var(--iq-color-border-subtle, #d1d5db);
}

/* ─── Placement, path 2: measured by JavaScript ──────────────────────────── */

/* For engines without anchor positioning. iq-dropdown.js measures the trigger
   and the panel and publishes three numbers; the CLAMP stays here, because the
   viewport gutter is `--iq-space-md` — the same token F1 uses for the same
   purpose — and a number in JavaScript would be a second source of truth for it.
   `--iq-dd-max-left` is `documentElement.clientWidth - panel width`, measured on
   the border box and ceil'd, so the gutter is subtracted from a real number
   rather than from `100dvw`, which includes a classic scrollbar. */
.iq-dropdown__panel[data-iq-placed] {
	position: fixed;
	inset: auto;
	margin: 0;
	inset-block-start: var(--iq-dd-top, 0px);
	inset-inline-start: auto;
	left: clamp(
		var(--iq-space-md, 1rem),
		var(--iq-dd-left, 0px),
		max(var(--iq-space-md, 1rem), var(--iq-dd-max-left, 0px) - var(--iq-space-md, 1rem))
	);
}

/* ─── The builder canvas ─────────────────────────────────────────────────── */

/* "Keep open while styling". A popover that is not open is `display: none`, so
   there is nothing to style — and unlike E2's dialog there is no `open`
   attribute to write, because a popover's openness is not reflected in the DOM.
   The specificity is deliberate: F1's `.iq-layer[popover]:not(:popover-open)`
   guard is 0-3-0 and `!important`, so only a higher-specificity `!important`
   rule can lift it.
   `position: static` drops the panel into the canvas flow, which is where an
   author can actually see what they are styling; it also cancels anchor
   positioning, which only applies to absolutely-positioned boxes. PHP emits the
   attribute only inside the builder, so it cannot reach a real page.

   THE ONE RECORDED EXEMPTION FROM THE `[hidden]` COMPANION RULE in this file
   (bricks-compat.md update-checklist item 19b). At 0-4-0 `!important` this rule
   outranks `.iq-dropdown__panel[hidden]` above, so a panel marked `hidden` is
   still laid out in the canvas. That is deliberate and it is the rule's whole
   job: it exists to show an author what is otherwise not shown, it is gated on
   an attribute PHP emits only for a real builder re-render (see
   Base_Element::iq_in_builder()), and it therefore cannot reach a rendered
   page. Verified by the census: on the frontend fixture this selector matches
   nothing. */
.iq-dropdown__panel[popover][data-iq-builder-open]:not(:popover-open) {
	display: flex !important;
	position: static;
	margin-block-start: var(--iq-space-2xs, 0.125rem);
	opacity: 1;
	translate: none;
}

/* ─── Forced colors (Windows High Contrast) — F4 ─────────────────────────── */

/* Surface by surface, because "no rule" and "not checked" are indistinguishable
   in a diff (forced-colors.md):
   - the PANEL's boundary was elevation over an opaque fill; the shadow is
     discarded and the fill stops identifying anything, so the border is what
     remains — it is a real border already and its colour is forced to
     `CanvasText`, and F1 adds `border: 1px solid CanvasText` to every `.iq-layer`
     underneath this file besides;
   - the TRIGGER is an `.iq-button` and takes that file's `ButtonText` border;
   - the CHEVRON declares no colour, so it inherits the button's forced one;
   - the HOVER fill is deliberately left alone: hover feedback is not a
     conformance requirement and the platform's conventions vary (F4 § What this
     deliberately does not do);
   - the FOCUS ring is an `outline`, which survives the forcing by design;
   - the DIVIDER is a border and is forced like any other.
   What is left is the one thing the forcing genuinely erases: the disabled
   `color-mix()` fade is a colour operation that never happens, and
   `[aria-disabled]` gets no native treatment, so `GrayText` has to be explicit. */
@media (forced-colors: active) {
	.iq-dropdown__panel [aria-disabled='true'],
	.iq-dropdown__panel :is(a[href], button, [role='menuitem']):not(.iq-button)[aria-disabled='true'] {
		color: GrayText;
	}
}
