/* Accessibility panel — Figma «Доступність»:
   390 4173:17505 (frame 4173:17635),
   1440 3866:29813 (frame 3866:29167 «Головна»),
   1920 4220:17258 (frame 4220:16709 «Full HD»).
   768: the node id in the plan table (4220:18006) resolves to an
   unrelated mobile-menu/footer frame in file.json — the real 768 panel
   is 4220:18578, inside frame `4220:18066` («tablet»). See
   tests/design/a11y-panel/spec-768.md and task-7-report.md.

   The panel is a single flat markup (template-parts/a11y-panel.php)
   rather than Figma's nested title + options + reset frames, so
   vertical rhythm below is built from margins on the flat children,
   not from nested gap containers. Documented residual, not a MISSING.

   Fix round 1 (controller ruling): position switched from `fixed`
   (pinned over content while scrolling) to `absolute`, anchored to
   `.site-header`, so it scrolls away with the header at ≥1440, where
   `top`/`right` are measured from the header's own right edge rather
   than a page-mockup-derived left offset that only ever matched one
   exact viewport width.

   Round 3 (controller ruling R20, item 3): below 1440 that `absolute`
   positioning was a latent bug — anchored near the TOP of the page (the
   header), opening the panel from a page scrolled any distance down
   (the normal case for #a11y-toggle-mobile, reached through the mobile
   menu) put it off-screen, with focus moved inside it (fix round 2,
   item 6) but nothing visible. Below 1440 the panel is closer to a
   full-screen overlay anyway (390/768's own Figma frames are a
   dedicated screen, not a small popover), so it goes back to `position:
   fixed`, top-aligned under the header regardless of scroll position —
   own `max-height`/`overflow-y` still apply. ≥1440 keeps the `absolute`
   anchor under the toggle (see the media query below), which doesn't
   have this bug: the toggle that opens it is only ever reachable when
   already scrolled to the top of the header. */

/* `.site-header` (Task 4, site-header.css) sets no `position` of its
   own — this is the one declaration needed to make `.a11y-panel`'s
   `position: absolute` at ≥1440 (below) anchor to the header instead of
   the nearest OTHER positioned ancestor (or the viewport). It does not
   change the header's own layout (no positioned descendant relied on
   static flow before), and has no effect on the `position: fixed` panel
   below 1440, which ignores ancestors entirely. */
.site-header {
	position: relative;
}

.a11y-panel {
	position: fixed;
	z-index: 20;
	top: 76px;
	left: 0;
	right: 0;
	display: flex;
	flex-direction: column;
	box-sizing: border-box;
	width: auto;

	/* 383.6px (spec's own Container height at 390/768 — see task-7-report.md
	   round 3, item 2): every child row measures within tolerance on its
	   own (title/label/steppers/switches/reset all PASS), but the sum of
	   several independently-tiny, independently-accepted sub-pixel
	   differences (the title's text-box-trim approximation on our
	   substitute font, per-row rounding) still lands the whole column
	   ~1.2px short of spec's own reported total. A min-height matching
	   that total directly, rather than chasing the remainder through five
	   more roundings, is the one point where "every row already passes"
	   and "the container's own height passes" don't fall out of the same
	   arithmetic — content still grows past it if it ever needs to.
	   Clamped to max-height (round 5): a bare min-height beats
	   max-height, so on short/landscape screens the fixed panel grew past
	   the viewport and the reset button was unreachable. */
	min-height: min(383.6px, calc(100dvh - 92px));
	max-height: calc(100dvh - 92px);
	overflow-y: auto;
	background: var(--color-base-white);

	/* Figma's 0.8px stroke is "inside" and its auto layout counts it
	   (children sit at pad + 0.8 in every spec), so it is an inset shadow
	   plus 0.8px on each padding, not a border. */
	box-shadow: inset 0 0 0 0.8px var(--color-neutral-300);
	padding: 22.8px;

	/* The panel's option/switch/reset text stays at the 390 size
	   through 768 (spec-768.md: 14/18, same as spec-390.md) rather
	   than following --fs-s-text/--lh-s-text, which already steps up
	   to 16/22 at 768 elsewhere on the site — only at 1440 does the
	   panel catch up to that token. */
	--a11y-fs: calc(14px * var(--font-scale));
	--a11y-lh: calc(18px * var(--font-scale));
}

.a11y-panel[hidden] {
	display: none;
}

.a11y-panel__head {
	display: flex;

	/* Figma: "cancel_10486711 1" is align=center — the title sits centred
	   against the close button's own height, not flush with its top
	   (fix round 2, item 5: this closed most of the 390/768 y residual). */
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	margin: 0 0 20px 0;
}

.a11y-panel__title {
	margin: 0;
	color: var(--color-neutral-800);
	font-family: var(--font-title);
	font-size: calc(20px * var(--font-scale));
	line-height: calc(20px * var(--font-scale));

	/* Figma: leadingTrim CAP_HEIGHT on this text node (and only this one in
	   the panel — every label/switch/reset text has leadingTrim none),
	   which is why its own reported height was a documented residual, not a
	   MISSING: the line box is trimmed to the cap height, not the full
	   nominal line-height (controller ruling R18). */
	text-box-trim: trim-both;
	text-box-edge: cap alphabetic;
	text-transform: uppercase;
}

/* Close button (Figma: 32×32 `icons/cross`, `cross__4163-16956.svg`) —
   the flat markup had dropped it; fix round 1, item 7. */
.a11y-panel__close {
	display: flex;
	flex: none;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	border: 0;
	background: transparent;
	padding: 0;
	cursor: pointer;
}

.a11y-panel__close svg {
	width: 20px;
	height: 20px;
}

.a11y-panel__size {
	display: grid;
	grid-template-columns: repeat(3, max-content);
	grid-template-areas: "label label label" "minus value plus";
	justify-content: start;
	row-gap: 10px;
	margin: 0 0 16px 0;
}

.a11y-panel__label {
	grid-area: label;
	color: var(--color-neutral-800);
	font-family: var(--font-body);
	font-size: var(--a11y-fs);
	line-height: var(--a11y-lh);
	letter-spacing: var(--ls-s-text);
	font-weight: 600;
	text-transform: uppercase;
}

.a11y-panel__step,
.a11y-panel__value {
	display: flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	height: 36.4px;
	border: 0;
	box-shadow: inset 0 0 0 0.8px var(--color-neutral-300);
	background: transparent;
	color: var(--color-neutral-800);
	font-family: var(--font-body);
	font-size: calc(14px * var(--font-scale));
	line-height: calc(17px * var(--font-scale));
	text-align: center;
}

.a11y-panel__step {
	grid-area: minus;
	width: 40px;
	padding: 9px 0;
	cursor: pointer;
}

/* `aria-disabled`, not the `disabled` attribute (fix round 1, item 4):
   a real `disabled` button is removed from the tab order mid-interaction,
   which either drops focus to <body> or jumps it to the next focusable
   element — the button stays focusable and clickable-but-ignored (see
   a11y-panel.js) instead.
   Colour is --color-neutral-500 (4.75:1 on white), not the design's
   neutral-400 (2.53:1, under 1.4.11's 3:1 for a UI component) — a
   deviation from Figma for contrast, flagged in designer-questions.md
   (round 3, item 4: round 2 had instead added a one-off
   `colors.base.disabled` token to also dodge high contrast's
   neutral-400→neutral-950 remap; removed as an invented token not backed
   by the design — under high contrast this is neutral-950, the same as
   the enabled state, same trade-off as everywhere else that remap applies). */
.a11y-panel__step[aria-disabled="true"] {
	color: var(--color-neutral-500);
	cursor: not-allowed;
}

/* High contrast collapses neutral-500 into neutral-950, so colour alone
   no longer tells the disabled step from the enabled one (round 4,
   controller ruling R21). Shape and a faded glyph carry it instead, with
   no new colour token: a 2px dashed frame (a pseudo-element — an inset
   box-shadow can't be dashed, and `outline` is kept for :focus-visible)
   in full-strength neutral-950, plus the glyph alone at 55 % alpha.
   Round 5: element `opacity` also faded the focus ring (primary-800 →
   2.67:1), so only `color` is faded now — the outline keeps its own
   full-strength colour (7.59:1). Inactive components are exempt from
   1.4.3/1.4.11. Default theme untouched. */
html[data-contrast="high"] .a11y-panel__step {
	position: relative;
}

html[data-contrast="high"] .a11y-panel__step[aria-disabled="true"] {
	color: color-mix(in srgb, var(--color-neutral-950) 55%, transparent);
}

html[data-contrast="high"] .a11y-panel__step[aria-disabled="true"]::after {
	content: "";
	position: absolute;
	inset: 0;
	border: 2px dashed var(--color-neutral-950);
	pointer-events: none;
}

.a11y-panel__step[data-scale="1"] {
	grid-area: plus;
	margin-left: -0.8px;
}

.a11y-panel__value {
	grid-area: value;
	margin-left: -0.8px;
	min-width: 58.6px;
	padding: 9px 12px;
	font-size: calc(13px * var(--font-scale));
	line-height: calc(15.7px * var(--font-scale));
}

.a11y-panel__switch {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	margin: 0;
	border: 0;
	border-top: 1px solid var(--color-neutral-300);
	background: transparent;
	padding: 16px 0;
	color: var(--color-neutral-800);
	font-family: var(--font-body);
	font-size: var(--a11y-fs);
	line-height: var(--a11y-lh);
	letter-spacing: var(--ls-s-text);
	font-weight: 600;
	text-align: left;
	text-transform: uppercase;
	cursor: pointer;
}

/* Not `.a11y-panel__switch:last-of-type` (fix round 2, item 4): the reset
   button is a `<button>` too, in the same parent, so it — not the third
   switch — was always the last button "of type", and the selector never
   matched anything. A dedicated class on the last switch in the markup
   (template-parts/a11y-panel.php) is unambiguous. */
.a11y-panel__switch--last {
	margin-bottom: 20px;
	border-bottom: 1px solid var(--color-neutral-300);
}

/* Track/knob drawn with pseudo-elements — Figma's Default/Variant2
   «Text» instances (3866:29813 rows 24–35): off = track, knob left;
   on = primary-800 track, knob right. Off track is neutral-500, not
   the design's neutral-300 (fix round 1, item 8: neutral-300 on white
   is ~1.48:1, under WCAG 1.4.11's 3:1 floor for non-text UI
   components; neutral-500 on white is 4.75:1). Flagged in
   designer-questions.md. */
.a11y-panel__switch::after {
	content: "";
	flex: none;
	box-sizing: border-box;
	width: 38px;
	height: 22px;
	border-radius: 999px;
	background: var(--color-neutral-500);
}

.a11y-panel__switch[aria-checked="true"]::after {
	background: var(--color-primary-800);
}

/* Positioned with `right`, not `left`: the button has zero
   horizontal padding and the track (::after) is the last flex item
   pushed flush to the button's right edge by
   justify-content: space-between, so the button's right edge is also
   the track's right edge — `right: Npx` lands the knob inside the
   track; `left: Npx` would not (it would sit under the label text,
   since the track's left edge floats wherever the label's width
   pushes it to). */
.a11y-panel__switch::before {
	content: "";
	position: absolute;
	right: 20px;
	top: 50%;
	transform: translateY(-50%);
	width: 16px;
	height: 16px;
	border-radius: 999px;
	background: var(--color-base-white);
}

.a11y-panel__switch[aria-checked="true"]::before {
	right: 4px;
}

.a11y-panel__reset {

	/* Figma: x matches every other row's left edge (22.8/32.8/40.8
	   depending on breakpoint) — the instance's own
	   `justify=center align=center` centers its icon+label pair
	   internally, it does not center the button within the panel. */
	align-self: flex-start;
	flex: none;
	margin: 0;
	border: 0;
	background: transparent;
	padding: 0;

	/* primary-700, not the design's primary-500 (fix round 1, item 8:
	   primary-500 on white is 2.81:1, under normal text's 4.5:1;
	   primary-700 is 5.49:1). Flagged in designer-questions.md. */
	color: var(--color-primary-700);
	font-family: var(--font-body);
	font-size: var(--a11y-fs);
	line-height: var(--a11y-lh);
	letter-spacing: var(--ls-s-text);
	font-weight: 600;
	text-transform: uppercase;
	cursor: pointer;
}

/* Hover — Figma «Скинути налаштування» 4234:26073 / 4234:26078 → Hover
   4309:30043 / 4309:30041: ON_HOVER, SMART_ANIMATE, 600ms, ease-out
   cubic-bezier(0, 0, 0.58, 1), text #12AD99 → #0C9586 (one step darker).
   The rest colour is already --color-primary-700 for contrast (above), so
   the hover keeps the direction one step further: --color-primary-800
   (designer-questions.md). Only the mob=off variants have the hover. */
@media (min-width: 768px) {

	.a11y-panel__reset {
		transition: color 600ms cubic-bezier(0, 0, 0.58, 1);
	}

	.a11y-panel__reset:hover,
	.a11y-panel__reset:focus-visible {
		color: var(--color-primary-800);
	}
}

@media (min-width: 768px) {

	.a11y-panel {
		padding: 40.8px 32.8px;

		/* spec-768.md's own Container height, clamped as above. */
		min-height: min(423.6px, calc(100dvh - 92px));
	}

	/* spec-768.md: only the reset link steps up to the 1440 size
	   (16/22) here — the option/switch labels stay at 14/18 until
	   1440 (--a11y-fs/--a11y-lh above). */
	.a11y-panel__reset {
		font-size: var(--fs-s-text);
		line-height: var(--lh-s-text);
	}
}

@media (min-width: 1440px) {

	.a11y-panel {

		/* Anchored under the toggle, not fixed to the viewport (round 3,
		   item 3). The reason has changed since the header became sticky
		   (fix round 1, I3): the toggle is no longer «only reachable at
		   the top of the page» — it is reachable at any scroll position,
		   and the panel now rides with it, which is what an anchored
		   popover should do. The header cannot slide out from under an
		   open panel either: header-reveal.js pins it down while
		   anything inside it has `aria-expanded="true"`. */
		position: absolute;
		top: 64px;
		left: auto;

		/* 1440 (and 1680/1919, same bucket): the toggle sits inside
		   `.site-header__bar`, which `site-header.css` right-aligns
		   with `margin-left: auto` — so the distance from the
		   header's OWN right edge to the panel is constant across
		   every width in this bucket (it depends only on the header's
		   fixed right padding plus the fixed-width content between
		   the toggle and that edge, never on viewport width). Derived
		   from the Figma page mockup at exactly 1440 (panel x=993,
		   w=300, frame w=1440 → 1440-993-300=147) and re-measured live
		   at 1440/1680/1919 — see task-7-report.md. */
		right: 147px;
		width: 300px;

		/* spec-1440.md's own Container height, clamped as above. */
		min-height: min(400.6px, calc(100dvh - 80px));
		max-height: calc(100dvh - 80px);
		padding: 22.8px;

		/* From 1440 the panel's option/switch/reset text matches
		   --fs-s-text/--lh-s-text again (16/22 here, 20/24 at 1920 —
		   that token already steps up there on its own). */
		--a11y-fs: var(--fs-s-text);
		--a11y-lh: var(--lh-s-text);
	}

	.a11y-panel__title {
		font-size: calc(24px * var(--font-scale));
		line-height: calc(24px * var(--font-scale));
	}

	.a11y-panel__head {
		margin-bottom: 32px;

		/* Round 3 (controller ruling R20, item 2): below 1440 the close
		   button (32px, visible there) sets the row's real height
		   regardless of the title's own; hidden here (below), the row's
		   height IS the title's own trimmed line box, which is ~1.2px
		   short of the spec's 17px on our substitute font (text-box-trim
		   approximates Figma's own leadingTrim measurement against a
		   different font file — see the R18 addendum for the mechanism,
		   not the residual). A `min-height` matching the spec value
		   directly restores the cascade below it (label/steppers/switches/
		   reset/panel height all measured this short, downstream) without
		   fighting font metrics pixel by pixel. */
		min-height: 17px;
	}

	/* Figma has no close-icon node on the 1440/3866:29813 or 1920/4220:17258
	   popover — only the 390/768 full-screen overlay has one (fix round 1,
	   item 7: added where the design has it, not invented elsewhere). */
	.a11y-panel__close {
		display: none;
	}

	.a11y-panel__switch--last {
		margin-bottom: 32px;
	}
}

@media (min-width: 1920px) {

	.a11y-panel {
		top: 84px;

		/* Same reasoning as 1440 (holds through 2560 and beyond): Figma
		   panel x=1323, w=400, frame w=1920 → 1920-1323-400=197. */
		right: 197px;
		width: 400px;
		max-height: calc(100dvh - 100px);
		padding: 32.8px;
	}

	.a11y-panel__title {
		font-size: calc(28px * var(--font-scale));
		line-height: calc(28px * var(--font-scale));
	}

	/* Same reasoning as the 1440 rule above — spec title height is 20px
	   here. */
	.a11y-panel__head {
		min-height: 20px;
	}

	.a11y-panel__size {
		row-gap: 14px;
		margin-bottom: 20px;
	}

	.a11y-panel__step,
	.a11y-panel__value {
		height: 44px;
	}

	.a11y-panel__step {
		width: 44px;
	}

	.a11y-panel__switch {
		padding: 20px 0;
	}
}
