/**
 * iq-accordion / iq-accordion-nested — shared styles for both variants.
 */

.iq-accordion {
	color: var(--iq-color-text, #1f2937);
}

/* Expand/collapse animation via the modern animate-to-intrinsic-size APIs:
   - interpolate-size: allow-keywords (iq-base.css) lets height animate 0 ↔ auto
   - transition-behavior: allow-discrete defers the discrete flip
     (content-visibility, or display on the fallback path) to the end of the
     close transition
   - @starting-style provides the height: 0 starting frame when opening
   Duration is 0 under prefers-reduced-motion (WCAG 2.3.3).

   interpolate-size is Chrome-only in the engines measured for E3 (Chrome 150
   yes, Firefox 151 no, WebKit 26.4 no), so this animation is progressive
   enhancement rather than a cross-engine promise — everywhere else the panel
   toggles instantly, which is what it already did. iq-disclosure.css uses the
   portable grid-track technique instead; migrating this element to it is a
   separate change, because it needs an extra structural wrapper inside the
   panel. */
.iq-accordion__panel {
	height: auto;
	overflow: clip;
}

/* Transitions only after JS init ([data-iq-init] is set by iqAccordionInit):
   without this gate, @starting-style makes every open-on-load panel animate
   from 0 on first paint.

   `content-visibility … allow-discrete` is what the E3 find-in-page retrofit
   added, and it is load-bearing rather than decoration: a collapsed panel is
   now hidden="until-found" (iq-collapse.js), whose UA style is
   `content-visibility: hidden` rather than `display: none`. Without the
   discrete entry that flip lands at once and the CLOSE animation snaps shut —
   measured in all three engines. `display` stays in the list for the other
   path: a browser without until-found still gets boolean [hidden]. */
[data-iq-init] .iq-accordion__panel {
	transition: height var(--iq-duration-slow-effective, 320ms) var(--iq-ease-out, cubic-bezier(0.22, 1, 0.36, 1)),
		content-visibility var(--iq-duration-slow-effective, 320ms) allow-discrete,
		display var(--iq-duration-slow-effective, 320ms) allow-discrete;
}

/* Transition suppression, applied for two frames by iq-collapse.js when
   find-in-page reveals a panel: with the height transition running, the browser
   scrolls to a box that is still growing and lands the match off screen.
   Carries the [data-iq-init] prefix so it can out-specify the rule above. */
[data-iq-init] .iq-accordion__panel--instant {
	transition: none;
}

.iq-accordion__panel[hidden] {
	height: 0;
	/* The divider below is drawn on this box, and an until-found panel is
	   RENDERED — measured 1px of residual per collapsed item where display:none
	   used to hide it outright. */
	border-block-start-width: 0;
}

/* The Bricks guard, narrowed by the E3 retrofit. `.brxe-block` is display:flex,
   which beats the UA [hidden] { display: none } — but a CSS [hidden] selector
   matches hidden="until-found" as well, and forcing display:none on THAT would
   destroy find-in-page entirely. The :not() is safe only because
   iq-collapse.js writes the string exclusively where the UA understands it. */
.iq-accordion__panel[hidden]:not([hidden='until-found']) {
	display: none !important;
}

/* …and the guard is not enough on its own, which cost a round to find.
   BRICKS SHIPS ITS OWN `[hidden], template { display: none }` reset
   (frontend.min.css / frontend-layer.min.css). It is an AUTHOR-origin rule, so
   it outranks the UA sheet — and unlike the UA sheet it has no
   `:not([hidden=until-found i])` carve-out. A panel with no author `display`
   declaration of its own therefore computed `display: none` while carrying
   hidden="until-found": collapsed, out of the tree, and NOT findable, with no
   symptom other than beforematch never firing. Measured exactly that before
   this rule existed.

   `block` is the repeater variant's own value. The nestable variant's panel is
   a .brxe-block and is `flex` while open; it flips to block only while
   collapsed, where content-visibility: hidden and height: 0 make the end state
   unobservable. The one visible seam, measured and accepted: `display` is in
   the transition list, and a discrete transition between two non-`none` values
   flips at 50% — so during the last ~150ms of a NESTABLE panel's collapse its
   children lay out as blocks rather than as flex items (measured: a child went
   133px -> 1278px wide at frame 11 of 20, inside a box that was 7px tall and
   clipped). Pinning the panel to `display: block` in every state would remove
   the seam and break every Bricks Layout control an author has set on a panel;
   dropping `display` from the transition list would move the same flip to the
   START of the collapse, which is worse. iq-disclosure.css has no equivalent
   problem because it declares `display: grid` on the panel in every state. */
.iq-accordion__panel[hidden='until-found'] {
	display: block;
}

@starting-style {
	.iq-accordion__panel {
		height: 0;
	}
}

.iq-accordion__item {
	/* Block, not flex: interpolate-size height animation does not affect a
	   flex item's main size, and Bricks gives .brxe-block (nestable variant
	   items) display:flex — which silently disables the panel animation.
	   The item is a heading-above-panel stack per the structure contract, so
	   block flow is equivalent. */
	display: block;
	border: var(--iq-border-width, 1px) solid var(--iq-color-border, #6b7280);
	border-radius: var(--iq-radius-md, 8px);
	background: var(--iq-color-surface, #ffffff);
	/* Cast outside the border box, so `overflow: hidden` above does not clip it. */
	box-shadow: var(--iq-shadow-sm);
	overflow: hidden;
}

/* The item's companion. NOT `:not([hidden='until-found'])` like the panel rule
   above — that carve-out exists so find-in-page can reveal a COLLAPSED panel,
   and nothing writes `until-found` to an item. A whole accordion row is an
   ordinary thing to hide, and without this it stayed at `display: block` with
   its trigger still focusable and still expandable. */
.iq-accordion__item[hidden] {
	display: none !important;
}

.iq-accordion__item + .iq-accordion__item {
	margin-block-start: var(--iq-space-sm, 0.5rem);
}

/* Reset the heading wrapper (real <h*> in the repeater variant). */
.iq-accordion__heading {
	margin: 0;
	font-size: 1em;
}

/* THIS RULE DECLARES NO `display` AND THE COMPANION IS STILL NEEDED. On the
   nestable path the heading is a `.brxe-block`, and Bricks paints that
   `display: flex` — the same collision the panel rule at the top of this file
   documents, reached without any `display` of ours. Measured: a `hidden`
   heading stayed laid out, taking its trigger with it. */
.iq-accordion__heading[hidden] {
	display: none !important;
}

/* Trigger: real <button> (repeater) or decorated block (nestable). */
.iq-accordion__trigger {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--iq-space-sm, 0.5rem);
	inline-size: 100%;
	/* max(24px, …): the 2.5.8 floor has to bind in CSS too — the sanitizer
	   floors the site-wide token, but a per-element builder override never
	   passes through it. */
	min-block-size: max(24px, var(--iq-tap-target-min, 44px));
	padding: var(--iq-space-sm, 0.5rem) var(--iq-space-md, 1rem);
	border: 0;
	background: transparent;
	color: inherit;
	font: inherit;
	font-weight: var(--iq-font-weight-bold, 600);
	text-align: start;
	cursor: pointer;
	transition: background-color var(--iq-duration-fast-effective, 120ms) var(--iq-ease-out, cubic-bezier(0.22, 1, 0.36, 1));
}

/* The trigger's companion, and it is a 2.1.1 guard rather than tidiness:
   getItems() collects triggers structurally and filters no attribute, so a
   `hidden` trigger keeps its click and keydown handlers. Measured without the
   rule: `display: flex`, painted, `focus()` lands on it, and a real mouse click
   expanded its panel (`aria-expanded` false -> true); with the rule, all four go
   the other way. Same shape as `.iq-dropdown__panel …[hidden]`. */
.iq-accordion__trigger[hidden] {
	display: none !important;
}

.iq-accordion__trigger:hover:not(:disabled):not([aria-disabled='true']) {
	background: var(--iq-color-surface-alt, #f3f4f6);
}

/* Disabled. The trigger has `color: inherit`, so `currentColor` inside its own
   `color` property resolves to exactly the value being replaced — which is the
   one place that idiom is correct (contrast with iq-button.css, where the
   control sets its own color and needs an explicit internal).
   The chevron is drawn from currentColor and dims with the label.
   `outline` is untouched: an [aria-disabled] trigger is still focusable and its
   ring must keep full contrast (WCAG 1.4.11 / 2.4.7). */
.iq-accordion__trigger:disabled,
.iq-accordion__trigger[aria-disabled='true'] {
	color: color-mix(in oklab, currentColor, transparent var(--iq-disabled-fade, 50%));
	cursor: not-allowed;
}

/* Inset focus ring: .iq-accordion__item clips overflow (rounded corners), and
   the trigger fills the item edge-to-edge, so the default outside outline
   (iq-base.css) would be swallowed entirely (WCAG 2.4.7/2.4.11). A negative
   offset draws the ring fully inside the trigger where nothing can clip it. */
.iq-accordion__trigger:focus-visible {
	outline-offset: calc(-1 * var(--iq-focus-ring-width, 3px) - 1px);
}

/* Expanded-state marker (chevron built from a border, no icon font needed).

   The repeater renders it in PHP; the nestable variant's opt-in caret ("Show
   caret" -> [data-iq-marker]) gets the same <span> from addMarker() in
   iq-accordion.js. The second selector is that caret on the builder canvas, see
   below. */
.iq-accordion__marker,
.brx-body.iframe [data-iq-marker][data-iq-init] > .iq-accordion__item > .iq-accordion__heading .iq-accordion__trigger::after {
	flex: none;
	inline-size: 0.6em;
	block-size: 0.6em;
	border-inline-end: 2px solid currentColor;
	border-block-end: 2px solid currentColor;
	transform: rotate(45deg);
	transition: transform var(--iq-duration-effective, 200ms) var(--iq-ease-emphasized, cubic-bezier(0.2, 0, 0, 1));
}

.iq-accordion__trigger > .iq-accordion__marker {
	align-self: center;
}

/* The nestable caret's two columns: everything the author put in the trigger,
   then the marker, centred against all of it whatever that is.

   Grid rather than a forced `flex-direction: row`, because the author's layout
   has to survive: the Style tab writes to `#brxe-<id>` on the trigger, so a row
   could only be forced with !important, and that would also destroy the value
   the wrapper below needs. A grid container ignores flex-direction and flex-wrap
   but still computes them, so they stay readable for `inherit`, at every
   breakpoint and with no JS measuring anything.

   Selected on the wrapper's presence, so it reaches only triggers addMarker()
   worked on: not an accordion nested in a panel with its own setting off, and
   not the no-JS page. Without :has() the trigger stays flex and the caret lands
   where the author's direction puts it. */
.iq-accordion__trigger:has(> .iq-accordion__trigger-content) {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
}

.iq-accordion__trigger-content {
	display: flex;
	flex-direction: inherit;
	flex-wrap: inherit;
	align-items: inherit;
	justify-content: inherit;
	gap: inherit;
	min-inline-size: 0;
	/* Without it an unbreakable word runs under the marker and is clipped by the
	   item's `overflow: hidden`. Inherited, so it reaches every child. */
	overflow-wrap: anywhere;
}

/* The same caret on the builder canvas, which gets no wrapper (addMarker() says
   why). Out of flow and centred against the padding box, in a gutter reserved
   with padding, so a column trigger previews the way it renders. A preview
   approximation: an author's own trigger padding beats this gutter, which the
   frontend's real column does not depend on.
   `.brx-body.iframe` exists only on the canvas (docs/bricks-compat.md), and
   [data-iq-init] is written there too. */
.brx-body.iframe [data-iq-marker][data-iq-init] > .iq-accordion__item > .iq-accordion__heading .iq-accordion__trigger {
	position: relative;
	padding-inline-end: calc(var(--iq-space-md, 1rem) + 0.6em + var(--iq-space-sm, 0.5rem));
}

.brx-body.iframe [data-iq-marker][data-iq-init] > .iq-accordion__item > .iq-accordion__heading .iq-accordion__trigger::after {
	content: '';
	position: absolute;
	inset-block: 0;
	inset-inline-end: var(--iq-space-md, 1rem);
	margin-block: auto;
}

.iq-accordion__trigger[aria-expanded="true"] .iq-accordion__marker,
.iq-accordion__item--open > .iq-accordion__heading .iq-accordion__marker,
.brx-body.iframe [data-iq-marker][data-iq-init] > .iq-accordion__item > .iq-accordion__heading .iq-accordion__trigger[aria-expanded="true"]::after {
	transform: rotate(225deg);
}

/* Divider, not a boundary: the item is already outlined by --iq-color-border,
   and this line only separates the trigger from the panel inside it. It
   identifies no control, so 1.4.11 does not govern it and it uses the subtle
   token (see class-tokens.php on the two border colors). */
.iq-accordion__panel {
	border-block-start: var(--iq-border-width, 1px) solid var(--iq-color-border-subtle, #d1d5db);
}

.iq-accordion__content,
.iq-accordion__panel > * {
	padding: var(--iq-space-md, 1rem);
}

.iq-accordion__content > :first-child {
	margin-block-start: 0;
}

.iq-accordion__content > :last-child {
	margin-block-end: 0;
}

/* Forced colors (Windows High Contrast) — F4 baseline, see
   docs/foundations/forced-colors.md. The item border and the currentColor
   chevron survive the forcing on their own; only the disabled color-mix
   fade does not. GrayText on the trigger dims the chevron with the label,
   exactly as the currentColor design intends. */
@media (forced-colors: active) {
	.iq-accordion__trigger:disabled,
	.iq-accordion__trigger[aria-disabled='true'] {
		color: GrayText;
	}
}
