/**
 * Attune - panel and trigger chrome.
 *
 * SPECIFICITY, AND WHY EVERY SELECTOR STARTS WITH .attune-ui
 *
 * A theme styles generic elements - button, a, span - and every control here is
 * one of those. To strip that, the reset must OUT-WEIGH the theme, so it is
 * written as `.attune-ui :is(...)` = 0-1-1. A bare `button {}` at 0-0-1 loses.
 *
 * That means every component rule below has to beat 0-1-1 in turn, so each one
 * is prefixed with .attune-ui: `.attune-ui .attune-bar` = 0-2-0. Elements that
 * carry .attune-ui themselves use `.attune-ui.attune-trigger` = 0-2-0.
 *
 * Do not drop the prefix when adding a rule. Without it the rule sits at 0-1-0,
 * loses to the reset, and the control silently reverts to browser defaults.
 *
 * Every size multiplies by --atn-u, so "Bigger menu" scales the panel from one
 * variable. Colours come from settings, printed in the head.
 */

/* -------------------------------------------------------------------------
   Reset - 0-1-1, beats a theme's element selectors
   ----------------------------------------------------------------------- */

.attune-ui :is(
	div, section, header, footer, span, p, h2, h3,
	button, a, svg, input, label
) {
	all: revert;
	box-sizing: border-box;
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	color: inherit;
	font: inherit;
	line-height: 1.3;
	letter-spacing: normal;
	word-spacing: normal;
	text-transform: none;
	text-decoration: none;
	text-shadow: none;
	box-shadow: none;
	border-radius: 0;
	min-width: 0;
	min-height: 0;
	max-width: none;
	outline: 0;
	transform: none;
	float: none;
	position: static;
}

.attune-ui :is(button, a) {
	cursor: pointer;
	-webkit-appearance: none;
	appearance: none;
}

/*
 * Interaction states, 0-2-1. The base reset above does not cover these, and a
 * theme's `button:hover` sits at 0-1-1 - which is why the panel kept flashing
 * the theme's accent colour the moment anything was hovered or focused, and why
 * the trigger changed colour when the panel closed and returned focus to it.
 *
 * Every component below therefore declares its own hover and focus at 0-3-0.
 */
.attune-ui :is(button, a):is(:hover, :focus, :focus-visible, :active, :visited) {
	background: none;
	border-color: currentColor;
	color: inherit;
	outline: 0;
	box-shadow: none;
	text-decoration: none;
	transform: none;
	filter: none;
}

/*
 * Screen-reader-only text. Needs its own rule at 0-2-0: `all: revert` on span
 * in the reset strips the clipping, which turns hidden button labels into
 * visible text piled on top of the header.
 */
.attune-ui .attune-sr {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.attune-ui svg {
	display: block;
	fill: none;
	vertical-align: middle;
}

/* -------------------------------------------------------------------------
   Tokens
   ----------------------------------------------------------------------- */

.attune-ui {
	--atn-u: 1;
	--atn-brand: #0b1b4b;
	--atn-muted: #8fa5c2;
	--atn-tint: #dce4ef;
	--atn-surface: #fff;
	--atn-hover: #eef2f8;
	--atn-radius: 8px;
	--atn-trg-x: 16px;
	--atn-trg-y: 16px;
	--atn-trg-d: 48px;
	--atn-trg-t: 48px;
	--atn-trg-m: 44px;
	--atn-trg-i-d: 22px;
	--atn-trg-i-t: 22px;
	--atn-trg-i-m: 20px;
	--atn-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
	font-family: var(--atn-font);
	color: var(--atn-brand);
	box-sizing: border-box;
}

html[data-atn-menu-size="big"] .attune-ui {
	--atn-u: 1.3;
}

/* -------------------------------------------------------------------------
   Trigger
   ----------------------------------------------------------------------- */

.attune-ui.attune-trigger {
	position: fixed;
	z-index: 99998;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: calc(9px * var(--atn-u));
	height: var(--atn-trg-d);
	padding: 0 calc(18px * var(--atn-u));
	border: 2px solid var(--atn-brand);
	border-radius: 999px;
	background: var(--atn-brand);
	color: #fff;
	font-family: var(--atn-font);
	font-size: calc(15px * var(--atn-u));
	font-weight: 500;
	line-height: 1;
	cursor: pointer;
	overflow: visible;
}

.attune-ui.attune-trigger--bottom-left  { inset-block-end: var(--atn-trg-y); inset-inline-start: var(--atn-trg-x); }
.attune-ui.attune-trigger--bottom-right { inset-block-end: var(--atn-trg-y); inset-inline-end: var(--atn-trg-x); }
.attune-ui.attune-trigger--top-left     { inset-block-start: var(--atn-trg-y); inset-inline-start: var(--atn-trg-x); }
.attune-ui.attune-trigger--top-right    { inset-block-start: var(--atn-trg-y); inset-inline-end: var(--atn-trg-x); }
.attune-ui.attune-trigger--middle-left  { top: 50%; transform: translateY(-50%); inset-inline-start: var(--atn-trg-x); }
.attune-ui.attune-trigger--middle-right { top: 50%; transform: translateY(-50%); inset-inline-end: var(--atn-trg-x); }

.attune-ui.attune-trigger:hover,
.attune-ui.attune-trigger:hover:focus {
	background: var(--atn-surface);
	border-color: var(--atn-brand);
	color: var(--atn-brand);
}

/* Focus without :focus-visible must still look like the resting button, or the
   trigger changes colour every time the panel hands focus back to it. */
.attune-ui.attune-trigger:focus,
.attune-ui.attune-trigger:active {
	background: var(--atn-brand);
	border-color: var(--atn-brand);
	color: #fff;
}

.attune-ui.attune-trigger:focus-visible {
	outline: 3px solid var(--atn-brand);
	outline-offset: 3px;
}

/* line-height 0 so the icon box hugs the glyph and centres against the label */
.attune-ui .attune-trigger__icon {
	display: inline-flex;
	align-items: center;
	line-height: 0;
}

/*
 * Icon size is set per breakpoint, separately from the button's height - the
 * two are independent design decisions. The variable holds a bare length and
 * is multiplied by --atn-u here, so "Bigger menu" still scales it.
 *
 * The tablet and mobile overrides live with the other trigger breakpoint rules
 * further down, next to the shape and visibility they belong with.
 */
.attune-ui .attune-trigger__icon svg {
	width: calc(var(--atn-trg-i-d) * var(--atn-u));
	height: calc(var(--atn-trg-i-d) * var(--atn-u));
}

.attune-ui .attune-trigger__label { line-height: 1; }

/*
 * Badge shown when a preference that changes the page is active. Driven by an
 * attribute the pre-paint script sets, so it is correct on the first frame
 * rather than appearing a moment after the page settles.
 */
.attune-ui .attune-trigger__badge,
.attune-ui .attune-trigger__badge-text { display: none; }

html[data-atn-active] .attune-ui .attune-trigger__badge {
	position: absolute;
	inset-block-start: calc(-4px * var(--atn-u));
	inset-inline-end: calc(-4px * var(--atn-u));
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: calc(20px * var(--atn-u));
	height: calc(20px * var(--atn-u));
	border-radius: 50%;
	border: 2px solid var(--atn-surface);
	background: var(--atn-surface);
	color: var(--atn-brand);
	line-height: 0;
}

html[data-atn-active] .attune-ui .attune-trigger__badge svg {
	width: calc(18px * var(--atn-u));
	height: calc(18px * var(--atn-u));
}

/*
 * Shape and visibility per breakpoint.
 *
 * Driven by classes rather than custom properties, because "icon only below
 * 600px" is a media query and a media query cannot be driven by a variable.
 * Attune_Settings::trigger_classes() prints is-pill-d / is-icon-d / is-hidden-d
 * and the tablet and mobile equivalents; the breakpoints here must stay in step
 * with Attune_Admin::breakpoints().
 *
 * Icon-only keeps the label in the accessibility tree - it is clipped, not
 * removed - so the button still announces what it does.
 *
 * THE RULE THAT MATTERS: ALL THREE CLASSES ARE ON THE BUTTON AT ONCE
 *
 * A rule outside a media query applies at every width, and a rule inside
 * max-width: 1024px also applies at 400px. So each block has to UNCONDITIONALLY
 * reset the shape before applying its own, and the reset must not be keyed on
 * that block's class.
 *
 * Keying the reset on is-pill-t was the bug: with desktop pill and mobile
 * icon-only, is-icon-m clipped the label at every width (icon-only on desktop),
 * while at mobile the still-matching is-pill-t rule from the tablet block
 * un-clipped it again (label back on mobile) - precisely inverted.
 *
 * Each reset is written .attune-trigger.attune-trigger (0-3-0) so it MATCHES
 * the specificity of the is-icon-* rules above it and wins on source order. At
 * 0-2-0 it would lose no matter how far down the file it sits.
 */

/* --- Desktop, the base state ---------------------------------------- */

.attune-ui.attune-trigger.is-icon-d {
	width: var(--atn-trg-d);
	padding: 0;
}

.attune-ui.attune-trigger.is-icon-d .attune-trigger__label {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
}

.attune-ui.attune-trigger.is-hidden-d { display: none; }

/*
 * Tile visibility per breakpoint, set on the settings screen's Tiles tab.
 * Same three-class-per-breakpoint approach as the trigger above, and the
 * same rule applies: each breakpoint below has to unconditionally reset
 * display before applying its own is-hidden-* class, or a tile hidden on
 * desktop but shown on tablet would still be caught by this rule at tablet
 * width too, since nothing here is gated to desktop-only widths.
 */
.attune-ui .attune-tile.is-hidden-d { display: none; }

/* --- Tablet --------------------------------------------------------- */

@media (max-width: 1024px) {
	.attune-ui.attune-trigger { height: var(--atn-trg-t); }

	.attune-ui .attune-trigger__icon svg {
		width: calc(var(--atn-trg-i-t) * var(--atn-u));
		height: calc(var(--atn-trg-i-t) * var(--atn-u));
	}

	/* Undo desktop. Unconditional - never keyed on is-pill-t. */
	.attune-ui.attune-trigger.attune-trigger {
		display: inline-flex;
		width: auto;
		padding: 0 calc(18px * var(--atn-u));
	}

	.attune-ui.attune-trigger.attune-trigger .attune-trigger__label {
		position: static;
		width: auto;
		height: auto;
		overflow: visible;
		clip: auto;
	}

	/* Then this breakpoint's own shape. */
	.attune-ui.attune-trigger.is-icon-t {
		width: var(--atn-trg-t);
		padding: 0;
	}

	.attune-ui.attune-trigger.is-icon-t .attune-trigger__label {
		position: absolute;
		width: 1px;
		height: 1px;
		overflow: hidden;
		clip: rect(0, 0, 0, 0);
		white-space: nowrap;
	}

	.attune-ui.attune-trigger.is-hidden-t { display: none; }

	/* Undo desktop, then apply this breakpoint's own state. */
	.attune-ui .attune-tile.attune-tile { display: flex; }
	.attune-ui .attune-tile.is-hidden-t { display: none; }
}

/* --- Mobile --------------------------------------------------------- */

@media (max-width: 600px) {
	.attune-ui.attune-trigger { height: var(--atn-trg-m); }

	.attune-ui .attune-trigger__icon svg {
		width: calc(var(--atn-trg-i-m) * var(--atn-u));
		height: calc(var(--atn-trg-i-m) * var(--atn-u));
	}

	/* Undo desktop AND tablet, both of which still match at this width. */
	.attune-ui.attune-trigger.attune-trigger {
		display: inline-flex;
		width: auto;
		padding: 0 calc(18px * var(--atn-u));
	}

	.attune-ui.attune-trigger.attune-trigger .attune-trigger__label {
		position: static;
		width: auto;
		height: auto;
		overflow: visible;
		clip: auto;
	}

	.attune-ui.attune-trigger.is-icon-m {
		width: var(--atn-trg-m);
		padding: 0;
	}

	.attune-ui.attune-trigger.is-icon-m .attune-trigger__label {
		position: absolute;
		width: 1px;
		height: 1px;
		overflow: hidden;
		clip: rect(0, 0, 0, 0);
		white-space: nowrap;
	}

	.attune-ui.attune-trigger.is-hidden-m { display: none; }

	/* Undo desktop AND tablet, both of which still match at this width. */
	.attune-ui .attune-tile.attune-tile { display: flex; }
	.attune-ui .attune-tile.is-hidden-m { display: none; }
}

/* -------------------------------------------------------------------------
   Shell
   ----------------------------------------------------------------------- */

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

.attune-ui.attune-panel {
	position: fixed;
	inset: 0;
	z-index: 99999;
	pointer-events: none;
}

/*
 * Transparent by design. The panel is a side sheet, not a modal: the visitor
 * needs to watch settings land on real content while choosing.
 *
 * IT MUST NOT CATCH THE POINTER. It used to, so that tapping the page closed
 * the panel, and that one line made the whole page unreachable to every
 * pointer while the panel was open. NVDA went silent over page text, because
 * the object under the mouse was this empty div rather than the words on
 * screen; a mouse user clicking a link got nothing but a closing panel, with
 * nothing to explain it, since the scrim is invisible and the page behind is
 * not dimmed. Everything else here - aria-modal false, no focus trap - says
 * the page is still available.
 *
 * Tap-to-close still works: it moved into attune-panel.js, which watches for a
 * click outside Attune's own UI and swallows that one click, so the panel
 * closes without following the link underneath.
 */
.attune-ui .attune-panel__scrim {
	position: absolute;
	inset: 0;
	background: transparent;
	pointer-events: none;
}

/*
 * --atn-sheet-top is where the WordPress admin bar ends, published by
 * attune-panel.js when the panel opens. Without it the admin bar, which shares
 * this z-index and is printed later, covered Reset and Close.
 */
.attune-ui .attune-panel__sheet {
	position: absolute;
	inset-block: var(--atn-sheet-top, 0px) 0;
	display: flex;
	flex-direction: column;
	width: min(calc(400px * var(--atn-u)), 100vw);
	background: var(--atn-surface);
	box-shadow: 0 0 40px rgba(11, 27, 75, 0.28);
	pointer-events: auto;
}

.attune-ui.attune-panel--left  .attune-panel__sheet { inset-inline-start: 0; }
.attune-ui.attune-panel--right .attune-panel__sheet { inset-inline-end: 0; }

/* -------------------------------------------------------------------------
   Header
   ----------------------------------------------------------------------- */

.attune-ui .attune-panel__head {
	display: flex;
	align-items: center;
	gap: calc(11px * var(--atn-u));
	padding: calc(14px * var(--atn-u)) calc(16px * var(--atn-u));
	background: var(--atn-brand);
	color: #fff;
}

.attune-ui .attune-panel__mark {
	display: inline-flex;
	align-items: center;
	flex: 0 0 auto;
	line-height: 0;
	color: #fff;
}

.attune-ui .attune-panel__mark svg {
	width: calc(24px * var(--atn-u));
	height: calc(24px * var(--atn-u));
}

.attune-ui .attune-panel__titles { flex: 1 1 auto; min-width: 0; }

.attune-ui .attune-panel__project {
	display: block;
	font-size: calc(11px * var(--atn-u));
	line-height: 1.3;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: #fff;
	opacity: 0.72;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.attune-ui .attune-panel__title {
	font-size: calc(17px * var(--atn-u));
	font-weight: 500;
	line-height: 1.25;
	color: #fff;
}

.attune-ui .attune-panel__icon-btn {
	flex: 0 0 auto;
	width: calc(34px * var(--atn-u));
	height: calc(34px * var(--atn-u));
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border-radius: calc(var(--atn-radius) * 0.75);
	background: transparent;
	color: #fff;
	cursor: pointer;
}

.attune-ui .attune-panel__icon-btn svg {
	width: calc(19px * var(--atn-u));
	height: calc(19px * var(--atn-u));
}

.attune-ui .attune-panel__icon-btn:hover,
.attune-ui .attune-panel__icon-btn:active { background: rgba(255, 255, 255, 0.16); color: #fff; }
.attune-ui .attune-panel__icon-btn:focus { background: transparent; color: #fff; }
.attune-ui .attune-panel__icon-btn:focus-visible { outline: 3px solid #fff; outline-offset: -3px; }

/* -------------------------------------------------------------------------
   Bigger menu switch
   ----------------------------------------------------------------------- */

.attune-ui .attune-panel__size {
	display: flex;
	align-items: center;
	gap: calc(11px * var(--atn-u));
	padding: calc(10px * var(--atn-u)) calc(16px * var(--atn-u));
	background: var(--atn-tint);
	color: var(--atn-brand);
	font-size: calc(13px * var(--atn-u));
	line-height: 1.3;
}

/*
 * Fixed box on every axis. Height and width are both pinned and flex is locked
 * off, so nothing the theme contributes can stretch it - the previous version
 * grew taller when it turned on because inherited padding was still in play.
 */
.attune-ui .attune-switch {
	position: relative;
	flex: 0 0 auto;
	display: block;
	box-sizing: border-box;
	width: calc(44px * var(--atn-u));
	min-width: calc(44px * var(--atn-u));
	height: calc(24px * var(--atn-u));
	min-height: calc(24px * var(--atn-u));
	padding: 0;
	border: 1px solid var(--atn-muted);
	border-radius: 999px;
	background: var(--atn-surface);
	cursor: pointer;
	transition: background-color 0.12s linear;
}

/*
 * Pinned to an edge rather than moved with a transform. A transform assumes the
 * track is exactly as wide as calculated; pinning cannot overshoot.
 */
.attune-ui .attune-switch__thumb {
	position: absolute;
	top: 50%;
	inset-inline-start: calc(2px * var(--atn-u));
	inset-inline-end: auto;
	width: calc(18px * var(--atn-u));
	height: calc(18px * var(--atn-u));
	margin-top: calc(-9px * var(--atn-u));
	border-radius: 50%;
	background: var(--atn-muted);
	transition: background-color 0.12s linear;
}

.attune-ui .attune-switch[aria-pressed="true"] {
	background: var(--atn-brand);
	border-color: var(--atn-brand);
}

.attune-ui .attune-switch[aria-pressed="true"] .attune-switch__thumb {
	inset-inline-start: auto;
	inset-inline-end: calc(2px * var(--atn-u));
	background: #fff;
}

.attune-ui .attune-switch:hover,
.attune-ui .attune-switch:focus,
.attune-ui .attune-switch:active { background: var(--atn-surface); border-color: var(--atn-brand); }
.attune-ui .attune-switch[aria-pressed="true"]:hover,
.attune-ui .attune-switch[aria-pressed="true"]:focus,
.attune-ui .attune-switch[aria-pressed="true"]:active { background: var(--atn-brand); border-color: var(--atn-brand); }
.attune-ui .attune-switch:focus-visible { outline: 3px solid var(--atn-brand); outline-offset: 3px; }

/* -------------------------------------------------------------------------
   Body, groups, tiles
   ----------------------------------------------------------------------- */

.attune-ui .attune-panel__body {
	flex: 1 1 auto;
	overflow-y: auto;
	overscroll-behavior: contain;
	padding: 0 calc(16px * var(--atn-u)) calc(14px * var(--atn-u));
}

.attune-ui .attune-group { padding-top: calc(14px * var(--atn-u)); }

.attune-ui .attune-group__title {
	margin-bottom: calc(8px * var(--atn-u));
	font-size: calc(12px * var(--atn-u));
	font-weight: 500;
	line-height: 1.2;
	color: var(--atn-brand);
	opacity: 0.65;
}

.attune-ui .attune-grid {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: calc(8px * var(--atn-u));
}

/* 123px, not 118px: the bars row grew from 14px to 24px so each level is a
   real 24x24 touch target, and 5px of the difference came back off the gap
   above it. See .attune-tile__bars. */
.attune-ui .attune-tile {
	display: flex;
	flex-direction: column;
	height: calc(123px * var(--atn-u));
	overflow: hidden;
	border: 1px solid var(--atn-tint);
	border-radius: var(--atn-radius);
	background: var(--atn-surface);
}

.attune-ui .attune-tile.is-on {
	border-color: var(--atn-brand);
	background: var(--atn-tint);
}

/*
 * Hover sits lighter than the on state, so hovering an off tile never looks
 * like it is already on.
 */
.attune-ui .attune-tile:hover {
	border-color: var(--atn-muted);
	background: var(--atn-hover);
}

.attune-ui .attune-tile.is-on:hover {
	border-color: var(--atn-brand);
	background: var(--atn-tint);
}

.attune-ui .attune-tile__face {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: calc(7px * var(--atn-u));
	width: 100%;
	padding: calc(10px * var(--atn-u)) calc(6px * var(--atn-u)) 0;
	background: transparent;
	color: var(--atn-brand);
	cursor: pointer;
}

/*
 * ON/OFF TILES: AN EMPTY BUTTON OVER THE FACE, THE NAME A <label> ABOVE IT.
 *
 * Chrome treats a button with aria-pressed as a single leaf, so text inside it
 * is not text to assistive technology: NVDA's mouse tracking read "Bigger text"
 * on a choice tile and nothing at all over "Visual alerts". The wrap takes the
 * face's layout, the button covers the wrap so clicks anywhere on the face
 * still toggle, and the name is lifted above the button so the pointer reaches
 * its text. Clicking the name toggles too - a label hands its click to the
 * control it is for.
 *
 * Cost, accepted on 17 September 2026: NVDA's browse mode now reads an on/off
 * name twice ("Visual alerts", then "toggle button, pressed, Visual alerts"),
 * as it already did for Bigger menu. NVDA drops that duplicate only for
 * checkboxes and radios. Proved by nvda-tests/hover-names.py.
 */
.attune-ui .attune-tile__face-wrap {
	position: relative;
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: calc(7px * var(--atn-u));
	padding: calc(10px * var(--atn-u)) calc(6px * var(--atn-u)) 0;
}

.attune-ui .attune-tile__face-wrap .attune-tile__face {
	position: absolute;
	inset: 0;
	padding: 0;
}

/* user-select: none keeps a quick double toggle from highlighting the name,
   which it never did while it was inside the button. */
.attune-ui .attune-tile__face-wrap .attune-tile__name {
	position: relative;
	z-index: 1;
	cursor: pointer;
	-webkit-user-select: none;
	user-select: none;
}

.attune-ui .attune-tile__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	line-height: 0;
	color: var(--atn-muted);
}

.attune-ui .attune-tile.is-on .attune-tile__icon { color: var(--atn-brand); }

.attune-ui .attune-tile__icon svg {
	width: calc(23px * var(--atn-u));
	height: calc(23px * var(--atn-u));
}

.attune-ui .attune-tile__name {
	font-size: calc(13px * var(--atn-u));
	font-weight: 400;
	line-height: 1.25;
	text-align: center;
	color: var(--atn-brand);
}

/*
 * Level bars: a radio group, drawn as a staircase.
 *
 * TWO THINGS ARE DELIBERATELY SEPARATE HERE - the button's box, which is the
 * TOUCH TARGET, and its ::before, which is the VISIBLE step.
 *
 * The button is a full 24px tall so it meets WCAG 2.5.8's 24x24 minimum. The
 * bars used to be 18x7 with 21px between centres, which fails both the size
 * rule and its spacing exception; it only conformed at all through the
 * "equivalent control" get-out, since the tile face reaches the same values by
 * cycling. Making the visible bar itself 24px tall was tried on paper first
 * and rejected - five identical 24px blocks read as a row of empty buttons,
 * not as a scale.
 *
 * So the visible part ascends instead: --atn-bar-step is set per bar by
 * Attune_Panel::tile() as (position / total), and the step's height is
 * derived from it. The row then reads as a level meter the way signal-strength
 * bars do, which needs no text inside it - and needing no text is what makes
 * it work in every language. Labels were the obvious alternative and do not
 * fit: "Light contrast" or "See-through" in a 42px segment is not readable in
 * English, let alone in Greek or Polish. The written value already sits under
 * the bars in .attune-tile__level, translated.
 *
 * align-items: flex-end so every step grows from one baseline.
 */
.attune-ui .attune-tile__bars {
	display: flex;
	align-items: flex-end;
	justify-content: center;
	gap: calc(3px * var(--atn-u));
	height: calc(24px * var(--atn-u));
	margin-top: calc(4px * var(--atn-u));
	padding: 0 calc(8px * var(--atn-u));
}

/*
 * 24x24 exactly, and NOT allowed to shrink - that is the whole point, so
 * flex-shrink stays 0 and min-width matches. The bars used to shrink so that
 * "six levels never overflow a tile", which is what let them end up at 18x7.
 *
 * The widest control shipped is five levels: 5 x 24 plus four 3px gaps is
 * 132px inside a 155px row, so they fit with room to spare. A tile given many
 * more levels than that through the attune_schema filter would overflow the
 * row rather than quietly shrink below the minimum target size - the honest
 * failure, and the one that shows up immediately instead of silently
 * regressing the thing this rule exists to guarantee.
 */
.attune-ui .attune-bar {
	display: flex;
	align-items: flex-end;
	flex: 0 0 calc(24px * var(--atn-u));
	width: calc(24px * var(--atn-u));
	min-width: calc(24px * var(--atn-u));
	height: calc(24px * var(--atn-u));
	padding: 0;
	border: 0;
	background: none;
	cursor: pointer;
}

.attune-ui .attune-bar::before {
	content: "";
	display: block;
	width: 100%;
	/* 5px..20px across the levels. The range is deliberately wide - an earlier
	   6px..16px was measured correct but read as five near-identical bars on
	   screen, which defeats the point of shaping them as a scale at all. 20px
	   is the ceiling: the target above is 24px and the step needs to sit
	   inside it. */
	height: calc((5px + var(--atn-bar-step, 1) * 15px) * var(--atn-u));
	border: 1px solid var(--atn-muted);
	border-radius: 2px;
	background: var(--atn-surface);
}

.attune-ui .attune-bar.is-filled::before {
	background: var(--atn-brand);
	border-color: var(--atn-brand);
}

.attune-ui .attune-bar:hover::before { border-color: var(--atn-brand); }
.attune-ui .attune-bar.is-filled:hover::before { background: var(--atn-brand); border-color: var(--atn-brand); }
.attune-ui .attune-bar:focus-visible { outline: 3px solid var(--atn-brand); outline-offset: 2px; }

/*
 * On/off tiles get a mark for both states. An empty slot reads as "not loaded
 * yet" rather than "off", so off gets its own muted mark.
 */
.attune-ui .attune-tile__check,
.attune-ui .attune-tile__uncheck {
	align-items: center;
	justify-content: center;
	line-height: 0;
}

.attune-ui .attune-tile__check {
	display: none;
	color: var(--atn-brand);
}

.attune-ui .attune-tile__uncheck {
	display: inline-flex;
	color: var(--atn-muted);
}

.attune-ui .attune-tile.is-on .attune-tile__check { display: inline-flex; }
.attune-ui .attune-tile.is-on .attune-tile__uncheck { display: none; }

.attune-ui .attune-tile__check svg,
.attune-ui .attune-tile__uncheck svg {
	width: calc(16px * var(--atn-u));
	height: calc(16px * var(--atn-u));
}

.attune-ui .attune-tile__level {
	display: flex;
	align-items: center;
	justify-content: center;
	height: calc(22px * var(--atn-u));
	padding: 0 calc(4px * var(--atn-u));
	font-size: calc(11px * var(--atn-u));
	font-weight: 500;
	line-height: 1.2;
	color: var(--atn-brand);
	text-align: center;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.attune-ui .attune-tile__face:hover,
.attune-ui .attune-tile__face:focus,
.attune-ui .attune-tile__face:active { background: transparent; color: var(--atn-brand); }
.attune-ui .attune-tile:hover .attune-tile__icon { color: var(--atn-brand); }
.attune-ui .attune-tile__face:focus-visible { outline: 3px solid var(--atn-brand); outline-offset: -3px; }

/* -------------------------------------------------------------------------
   Status and footer
   ----------------------------------------------------------------------- */

.attune-ui .attune-panel__status {
	padding: 0 calc(16px * var(--atn-u)) calc(8px * var(--atn-u));
	min-height: calc(17px * var(--atn-u));
	font-size: calc(12px * var(--atn-u));
	line-height: 1.4;
	color: var(--atn-brand);
	opacity: 0.7;
}

.attune-ui .attune-panel__foot {
	flex: 0 0 auto;
	padding: calc(12px * var(--atn-u)) calc(16px * var(--atn-u));
	border-top: 1px solid var(--atn-tint);
	background: var(--atn-tint);
}

.attune-ui .attune-panel__actions { display: flex; gap: calc(8px * var(--atn-u)); }

.attune-ui .attune-btn {
	flex: 1 1 auto;
	min-height: calc(40px * var(--atn-u));
	padding: 0 calc(14px * var(--atn-u));
	border-radius: calc(var(--atn-radius) * 0.75);
	font-family: var(--atn-font);
	font-size: calc(13px * var(--atn-u));
	font-weight: 500;
	line-height: 1;
	cursor: pointer;
}

.attune-ui .attune-btn--solid {
	border: 1px solid var(--atn-brand);
	background: var(--atn-brand);
	color: #fff;
}

.attune-ui .attune-btn--quiet {
	border: 1px solid var(--atn-muted);
	background: var(--atn-surface);
	color: var(--atn-brand);
}

.attune-ui .attune-btn--solid:hover,
.attune-ui .attune-btn--solid:focus,
.attune-ui .attune-btn--solid:active { background: var(--atn-brand); border-color: var(--atn-brand); color: #fff; }
.attune-ui .attune-btn--quiet:hover,
.attune-ui .attune-btn--quiet:focus,
.attune-ui .attune-btn--quiet:active { background: var(--atn-surface); border-color: var(--atn-brand); color: var(--atn-brand); }
.attune-ui .attune-btn:focus-visible { outline: 3px solid var(--atn-brand); outline-offset: 2px; }

.attune-ui .attune-panel__links {
	display: flex;
	flex-wrap: wrap;
	gap: calc(12px * var(--atn-u));
	margin-top: calc(10px * var(--atn-u));
	font-size: calc(12px * var(--atn-u));
}

.attune-ui .attune-panel__links a,
.attune-ui .attune-panel__links a:hover,
.attune-ui .attune-panel__links a:focus,
.attune-ui .attune-panel__links a:visited {
	color: var(--atn-brand);
	text-decoration: underline;
}

.attune-ui .attune-panel__note {
	margin-top: calc(8px * var(--atn-u));
	font-size: calc(12px * var(--atn-u));
	line-height: 1.45;
	color: var(--atn-brand);
	opacity: 0.7;
}

html[data-atn-motion="reduced"] .attune-ui .attune-switch,
html[data-atn-motion="reduced"] .attune-ui .attune-switch__thumb {
	transition: none;
}

/* -------------------------------------------------------------------------
   Read-aloud controls

   A read-aloud bar. Not a screen reader, and nothing here says it is.

   Real markup in the footer, shown by CSS when the preference is on, so
   switching it on adds nothing to the DOM and nothing to the accessibility
   tree. display:none also keeps it out of the tab order while it is off - a
   hidden control that still takes a tab stop is its own bug.

   It sits above the trigger (z-index 99998) but below the panel (99999), so
   opening settings never leaves the bar floating over the sheet.
   ----------------------------------------------------------------------- */

.attune-ui.attune-read { display: none; }

/* The browser cannot speak: the bar would be a row of controls that do
   nothing, so it never appears. Set by attune-read-aloud.js. */
html[data-atn-tts="no"] .attune-ui.attune-read { display: none; }
html[data-atn-tts="no"] .attune-ui .attune-tile[data-atn-key="read_aloud"],
html[data-atn-tts="no"] .attune-ui .attune-tile[data-atn-key="read_speed"] { display: none; }

html[data-atn-read-aloud="on"]:not([data-atn-tts="no"]) .attune-ui.attune-read {
	position: fixed;
	z-index: 99998;
	inset-block-end: 0;
	inset-inline: 0;
	display: flex;
	align-items: center;
	gap: calc(10px * var(--atn-u));
	padding: calc(8px * var(--atn-u)) calc(12px * var(--atn-u));
	border-top: 2px solid var(--atn-brand);
	background: var(--atn-surface);
	box-shadow: 0 -4px 18px rgba(11, 27, 75, 0.16);
	font-family: var(--atn-font);
	color: var(--atn-brand);
}

.attune-ui .attune-read__mark {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	line-height: 0;
	color: var(--atn-brand);
}

.attune-ui .attune-read__mark svg {
	width: calc(22px * var(--atn-u));
	height: calc(22px * var(--atn-u));
}

/*
 * Reading indicator: three bars that rise and fall while speech is playing.
 *
 * Sound is invisible. On a muted device, or once the highlight has scrolled out
 * of view, nothing on screen said the reader was still working - which reads as
 * a broken button. CSS rather than an animated image, so it takes the brand
 * colour, costs no request, stays sharp at any size, and can actually stop.
 */
.attune-ui .attune-read__wave {
	display: flex;
	align-items: flex-end;
	gap: calc(2px * var(--atn-u));
	height: calc(18px * var(--atn-u));
}

.attune-ui .attune-read__bar {
	display: block;
	width: calc(3px * var(--atn-u));
	height: 30%;
	border-radius: 999px;
	background: var(--atn-brand);
}

.attune-ui.attune-read.is-playing .attune-read__bar {
	animation: attune-read-wave 900ms ease-in-out infinite;
}

.attune-ui.attune-read.is-playing .attune-read__bar:nth-child(2) { animation-delay: 150ms; }
.attune-ui.attune-read.is-playing .attune-read__bar:nth-child(3) { animation-delay: 300ms; }

@keyframes attune-read-wave {
	0%, 100% { height: 30%; }
	50%      { height: 100%; }
}

/*
 * Stops dead for anyone who asked for less motion - by their own setting or by
 * their device's. A looping animation is exactly what that preference is for,
 * and the bars still show the playing state by standing at full height.
 */
@media (prefers-reduced-motion: reduce) {
	html:not([data-atn-motion="allowed"]) .attune-ui.attune-read.is-playing .attune-read__bar {
		animation: none;
		height: 100%;
	}
}

html[data-atn-motion="reduced"] .attune-ui.attune-read.is-playing .attune-read__bar {
	animation: none;
	height: 100%;
}

.attune-ui .attune-read__controls {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	gap: calc(6px * var(--atn-u));
}

.attune-ui .attune-read__btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: calc(7px * var(--atn-u));
	min-height: calc(40px * var(--atn-u));
	padding: 0 calc(14px * var(--atn-u));
	border: 1px solid var(--atn-brand);
	border-radius: calc(var(--atn-radius) * 0.75);
	background: var(--atn-surface);
	color: var(--atn-brand);
	font-family: var(--atn-font);
	font-size: calc(13px * var(--atn-u));
	font-weight: 500;
	line-height: 1;
	cursor: pointer;
}

.attune-ui .attune-read__btn--main {
	background: var(--atn-brand);
	color: #fff;
}

/* Stated for every state: a theme's button:hover sits at 0-1-1 and would
   otherwise repaint these the moment they are touched. */
.attune-ui .attune-read__btn:hover,
.attune-ui .attune-read__btn:focus,
.attune-ui .attune-read__btn:active {
	background: var(--atn-surface);
	border-color: var(--atn-brand);
	color: var(--atn-brand);
}

.attune-ui .attune-read__btn--main:hover,
.attune-ui .attune-read__btn--main:focus,
.attune-ui .attune-read__btn--main:active {
	background: var(--atn-brand);
	border-color: var(--atn-brand);
	color: #fff;
}

.attune-ui .attune-read__btn:focus-visible {
	outline: 3px solid var(--atn-brand);
	outline-offset: 2px;
}

/* Disabled is shown by more than colour: the border goes dashed too. */
.attune-ui .attune-read__btn[disabled],
.attune-ui .attune-read__btn[disabled]:hover {
	border-style: dashed;
	border-color: var(--atn-muted);
	background: var(--atn-surface);
	color: var(--atn-muted);
	cursor: default;
}

.attune-ui .attune-read__icon {
	display: inline-flex;
	align-items: center;
	line-height: 0;
}

.attune-ui .attune-read__icon svg {
	width: calc(15px * var(--atn-u));
	height: calc(15px * var(--atn-u));
}

/* One button, two faces: play while stopped or paused, pause while reading. */
.attune-ui .attune-read__icon--pause { display: none; }
.attune-ui.attune-read.is-playing .attune-read__icon--play { display: none; }
.attune-ui.attune-read.is-playing .attune-read__icon--pause { display: inline-flex; }

/* Skip buttons: icon only, so they stay out of the way of the main control. */
.attune-ui .attune-read__btn--step {
	min-width: calc(38px * var(--atn-u));
	padding: 0 calc(9px * var(--atn-u));
}

/* Reading speed, on the bar rather than in the panel - it is adjusted while
   listening, and the panel would cover the text being read. */
.attune-ui .attune-read__speed {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
}

/*
 * Speed and Voice: label and dropdown inside one bordered group.
 *
 * The label was previously a bare span beside the select, and the select's own
 * width squeezed it until the two overlapped. Translations make that worse -
 * "Speed" is one short word in English and "Ταχύτητα ανάγνωσης" is not - so the
 * label is given its own space and told never to shrink, and the group grows to
 * fit whatever the language needs.
 */
.attune-ui .attune-read__speed,
.attune-ui .attune-read__voice {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	gap: calc(6px * var(--atn-u));
	max-width: 100%;
	padding: 0 calc(8px * var(--atn-u));
	border: 1px solid var(--atn-muted);
	border-radius: calc(var(--atn-radius) * 0.75);
	background: var(--atn-surface);
}

.attune-ui .attune-read__speed:focus-within,
.attune-ui .attune-read__voice:focus-within {
	border-color: var(--atn-brand);
}

/*
 * Never shrinks, and sits on its own tint so the two halves of the group read
 * as label and value rather than as one run of text.
 *
 * The group's own padding is removed for this: the label's background has to
 * reach the edge, or it looks like a floating swatch.
 */
.attune-ui .attune-read__speed,
.attune-ui .attune-read__voice {
	padding: 0;
	gap: 0;
	overflow: hidden;
}

.attune-ui .attune-read__label {
	flex: 0 0 auto;
	align-self: stretch;
	display: inline-flex;
	align-items: center;
	padding: 0 calc(9px * var(--atn-u));
	background: #f0f3f6;
	border-inline-end: 1px solid var(--atn-muted);
	font-size: calc(11px * var(--atn-u));
	font-weight: 500;
	line-height: 1.2;
	color: var(--atn-brand);
	white-space: nowrap;
}

.attune-ui .attune-read__select {
	margin-inline-start: calc(8px * var(--atn-u));
	margin-inline-end: calc(6px * var(--atn-u));
}

/* Voice choice. Hidden by the script where there is only one voice. */
.attune-ui .attune-read__voice[hidden] { display: none; }

/*
 * select is not in the reset at the top of this file, so it carries its own
 * box here. At 0-2-0 this clears a theme's `select` and `.something select`
 * rules, which otherwise arrive with their own height, font and arrow.
 */
/* The border belongs to the group around it, so the select carries none. */
.attune-ui .attune-read__select {
	flex: 0 1 auto;
	min-width: calc(64px * var(--atn-u));
	max-width: calc(150px * var(--atn-u));
	min-height: calc(32px * var(--atn-u));
	padding: 0;
	border: 0;
	background: transparent;
	color: var(--atn-brand);
	font-family: var(--atn-font);
	font-size: calc(12px * var(--atn-u));
	line-height: 1.2;
	text-overflow: ellipsis;
	cursor: pointer;
}

.attune-ui .attune-read__select:focus-visible {
	outline: 2px solid var(--atn-brand);
	outline-offset: 1px;
}

.attune-ui .attune-read__status {
	flex: 1 1 auto;
	min-width: 0;
	font-size: calc(12px * var(--atn-u));
	line-height: 1.4;
	color: var(--atn-brand);
	opacity: 0.85;
}

.attune-ui .attune-read__btn--close {
	flex: 0 0 auto;
	min-height: calc(34px * var(--atn-u));
	width: calc(34px * var(--atn-u));
	padding: 0;
	border-color: transparent;
}

.attune-ui .attune-read__btn--close:hover,
.attune-ui .attune-read__btn--close:focus {
	border-color: var(--atn-brand);
}

@media (max-width: 600px) {
	html[data-atn-read-aloud="on"]:not([data-atn-tts="no"]) .attune-ui.attune-read {
		flex-wrap: wrap;
	}

	.attune-ui .attune-read__status {
		flex: 1 1 100%;
		order: 3;
	}

	.attune-ui .attune-read__btn-text { font-size: calc(12px * var(--atn-u)); }
}

/*
 * The bar covers the bottom of the page, so the trigger steps up out of its
 * way rather than sitting underneath it.
 *
 * --atn-read-bar-h is the bar's MEASURED height, published by
 * attune-panel.js. It used to be a hardcoded 62px, which was the bar's height
 * on a wide screen - but below 600px the status line wraps onto its own row
 * and the bar grows to around 156px, so the trigger was lifted well short and
 * stayed buried underneath it. On a phone that hides the only way back into
 * the panel. The height also depends on how the speed and voice labels wrap
 * in the current language, so it cannot be a second hardcoded number either.
 *
 * 62px stays as the fallback for the moment before the observer first runs,
 * and for a browser without ResizeObserver.
 */
html[data-atn-read-aloud="on"]:not([data-atn-tts="no"]) .attune-ui.attune-trigger--bottom-left,
html[data-atn-read-aloud="on"]:not([data-atn-tts="no"]) .attune-ui.attune-trigger--bottom-right {
	inset-block-end: calc(var(--atn-trg-y) + var(--atn-read-bar-h, 62px));
}

/* -------------------------------------------------------------------------
   Read-aloud audit panel

   Only in the page at all when it was requested with ?attune_audit=1. A
   developer tool, so it is plain and dense rather than styled to match - and
   deliberately not themed by the brand colours, because it is not part of what
   a visitor ever sees.
   ----------------------------------------------------------------------- */

.attune-ui.attune-audit[hidden] { display: none; }

.attune-ui.attune-audit {
	position: fixed;
	z-index: 100000;
	inset-block-start: 0;
	inset-inline-end: 0;
	display: flex;
	flex-direction: column;
	width: min(680px, 100vw);
	max-height: 70vh;
	border: 2px solid #1b1b1b;
	background: #fff;
	color: #1b1b1b;
	font-family: var(--atn-font);
	box-shadow: 0 6px 28px rgba(0, 0, 0, 0.3);
}

.attune-ui .attune-audit__head {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 8px 10px;
	border-bottom: 1px solid #ddd;
	background: #f3f3f3;
}

.attune-ui .attune-audit__title {
	flex: 1 1 auto;
	font-size: 13px;
	font-weight: 600;
	line-height: 1.3;
}

.attune-ui .attune-audit__btn {
	flex: 0 0 auto;
	padding: 5px 10px;
	border: 1px solid #1b1b1b;
	border-radius: 3px;
	background: #fff;
	color: #1b1b1b;
	font-family: var(--atn-font);
	font-size: 12px;
	line-height: 1.2;
	cursor: pointer;
}

.attune-ui .attune-audit__btn:hover,
.attune-ui .attune-audit__btn:focus,
.attune-ui .attune-audit__btn:active {
	background: #1b1b1b;
	border-color: #1b1b1b;
	color: #fff;
}

.attune-ui .attune-audit__btn:focus-visible {
	outline: 3px solid #0b57d0;
	outline-offset: 2px;
}

.attune-ui .attune-audit__note {
	padding: 6px 10px 0;
	font-size: 12px;
	line-height: 1.3;
	color: #444;
}

/* pre is not in the reset at the top of this file, so it states its own box. */
.attune-ui .attune-audit__body {
	flex: 1 1 auto;
	margin: 0;
	padding: 10px;
	overflow: auto;
	background: #fff;
	color: #1b1b1b;
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	font-size: 12px;
	line-height: 1.5;
	white-space: pre-wrap;
	overflow-wrap: anywhere;
	-webkit-user-select: text;
	user-select: text;
}

/* -------------------------------------------------------------------------
   Image tooltip

   One element, moved between images by attune-image-tips.js. It carries
   aria-hidden and is never referenced from the image, because the alt text is
   already announced by the image itself - this is the visible copy, for people
   who cannot otherwise get at it.
   ----------------------------------------------------------------------- */

.attune-ui.attune-tip[hidden] { display: none; }

.attune-ui.attune-tip {
	position: fixed;
	top: 0;
	left: 0;
	z-index: 99997;
	display: flex;
	flex-direction: column;
	gap: calc(2px * var(--atn-u));
	max-width: min(calc(320px * var(--atn-u)), 80vw);
	padding: calc(7px * var(--atn-u)) calc(10px * var(--atn-u));
	border: 2px solid var(--atn-brand);
	border-radius: calc(var(--atn-radius) * 0.75);
	background: var(--atn-surface);
	color: var(--atn-brand);
	font-family: var(--atn-font);
	font-size: calc(13px * var(--atn-u));
	line-height: 1.4;
	box-shadow: 0 4px 18px rgba(11, 27, 75, 0.24);

	/*
	 * Inert to the pointer. A tooltip that can be hovered is also a tooltip
	 * that can sit between the pointer and the link underneath it, and this one
	 * appears on every image on the page. Escape dismisses it instead, which is
	 * what WCAG 1.4.13 asks for.
	 */
	pointer-events: none;
}

.attune-ui .attune-tip__text {
	overflow-wrap: anywhere;
}

/*
 * "This image has no description." It is a statement about the page, not the
 * description itself, so it is set apart in italics and quietened - without
 * turning into a warning. The visitor is reading, not auditing.
 */
.attune-ui.attune-tip[data-atn-state="none"] {
	border-style: dashed;
	border-color: var(--atn-muted);
}

.attune-ui.attune-tip[data-atn-state="none"] .attune-tip__text {
	font-style: italic;
	opacity: 0.8;
}

/* -------------------------------------------------------------------------
   Reading mask

   The dim is one huge box-shadow spreading from a clear band, so there is
   nothing to line up at the edges. z-index sits below the panel (99999), the
   trigger (99998) and the tooltip (99997), so every control stays at full
   brightness while the page behind it dims.
   ----------------------------------------------------------------------- */

.attune-ui.attune-mask { display: none; }

html[data-atn-reading-mask="on"] .attune-ui.attune-mask {
	position: fixed;
	z-index: 99990;
	inset-inline: 0;
	top: 0;
	display: block;
	height: var(--atn-mask-height, 150px);
	background: transparent;
	box-shadow: 0 0 0 100vmax rgba(0, 0, 0, 0.62);

	/* Never intercepts a click: it changes what the page looks like, not how
	   it works. */
	pointer-events: none;
}

/* Contrast modes already flatten the page to two colours, so a soft dim on top
   of them just makes the band harder to find. It goes darker instead. */
html[data-atn-contrast="high"][data-atn-reading-mask="on"] .attune-ui.attune-mask {
	box-shadow: 0 0 0 100vmax rgba(0, 0, 0, 0.82);
}

/*
 * The floating button, hidden on request.
 *
 * Driven by the preference attribute rather than by the server, so switching it
 * off takes effect on the spot instead of on the next page load. display:none
 * takes it out of the accessibility tree too - a button a screen reader still
 * announces after the visitor asked for it to go is not hidden, it is lying.
 *
 * THE WEIGHT IS THE WHOLE POINT OF THIS SELECTOR. The first version was
 * `html[data-atn-floating-button="off"] .attune-trigger` at 0-2-1, and it
 * worked on a desktop and did nothing at all on a tablet or a phone: the
 * per-breakpoint rules restate the trigger as `.attune-trigger.attune-trigger`
 * at 0-3-0 to undo the wider breakpoint's shape (see invariant 2 in CLAUDE.md),
 * and 0-3-0 beats 0-2-1 inside every one of those media queries. So the control
 * appeared to save, the attribute landed on <html>, and the button stayed on
 * screen for exactly the visitors most likely to be short of room.
 *
 * Doubling the class and taking the ID weight from :is() lifts this to 1-2-1,
 * clear of the breakpoint rules and of any added later, without !important.
 */
html:is(#atn-x, [data-atn-floating-button="off"]) .attune-trigger.attune-trigger {
	display: none;
}
