/*
 * MediVera States — map + directory.
 *
 * DELIBERATELY UNLAYERED. An @layer rule loses to any unlayered rule regardless
 * of specificity, and this site has bare element selectors in its theme that
 * would beat a layered plugin stylesheet outright. Do not wrap any of this in
 * @layer.
 *
 * COLOURS come from the site's v4 Variables, which Elementor emits on :root
 * with readable names (--mv-green-mid and friends). Every reference carries the
 * literal Figma value as a fallback so the plugin also renders correctly on a
 * page Elementor is not involved in, and in the WP admin.
 *
 * Two colours in this file have no variable because they exist only on the map:
 * --mv-map-fill (#3E6726, the licensed state fill) and --mv-map-rim-off
 * (#6DA44B, the coming-soon rim). They are registered as v4 Variables on the
 * kit, so the var() lookups below resolve; the literals are the fallback.
 *
 * THE TEN PROPERTIES BELOW ARE THE WHOLE PALETTE. Nothing in this file names a
 * colour outside them (bar structural white on the callout box and the hover
 * label's halo), which is what lets the Appearance & Labels screen repaint both
 * features by re-declaring the same ten on the same selector — see
 * MV_States_Settings::css(). Add a new literal colour here and it silently
 * becomes un-editable, so route it through one of these or add an eleventh in
 * both places.
 */

.mv-states-map,
.mv-states-dir {
	--mv-map-fill-l: var(--mv-map-fill, #3e6726);
	--mv-map-rim-l: var(--mv-green-mid, #87c75f);
	--mv-map-fill-off-l: var(--mv-green-wash-lt, #f0f8eb);
	--mv-map-rim-off-l: var(--mv-map-rim-off, #6da44b);
	--mv-map-ink-l: var(--mv-green-ink, #1a2a10);
	--mv-map-accent-l: var(--mv-green, #67ad3f);
	--mv-map-soft-l: var(--mv-green-soft, #c3e3af);
	--mv-map-wash-l: var(--mv-green-wash, #e1f1d7);
	--mv-map-light-l: var(--mv-green-light, #a5d587);
	/* Focus rings. Brand green rather than ink: the dark-ink ring read as a
	   generic browser outline. #3E6726 measures 3.83:1 against the control pill
	   and 6.4:1 against white, so it clears the 3:1 that WCAG asks of a
	   non-text UI indicator on every surface it lands on here. Its own property
	   so it stays independently editable. */
	--mv-map-focus-l: var(--mv-map-fill, #3e6726);
}

/* ==========================================================================
   MAP
   ========================================================================== */

.mv-states-map {
	display: flex;
	flex-direction: column;
	/* The SVG caps at its own 1360-unit canvas width rather than upscaling — the
	   design draws it 1360 wide inside a 1440 frame — so in a wider container it
	   needs centring. A no-op below 1360, where the SVG is simply 100%. */
	align-items: center;
	gap: clamp(16px, 1.66vw, 24px);
	width: 100%;
}

/* ==========================================================================
   HOST CONTAINER DEFENCE
   ==========================================================================

   A `shortcode` widget is a flex ITEM when the container holding it is a flex
   row — and a v4 e-flexbox defaults to `row` / `nowrap`. A flex item is
   `flex: 0 1 auto`, so it sizes to its content's max-content width, and an
   <svg> with `width: 100%` contributes almost nothing. Measured on staging: the
   map rendered at **519px inside a 1440px section**, and the directory at 663px.
   Nothing errored and no audit could see it — this is the same failure mode that
   once rendered a video at 300px on page 1025 (RULES 5d).

   Two independent belts, because this must not depend on the host getting its
   container direction right:

   1. Give the SVG a real intrinsic width. The flex item's max-content size then
      becomes 1360px and `max-width: 100%` shrinks it back to whatever is
      actually available. No `:has()`, no reliance on Elementor's markup.
   2. Make the widget wrapper itself full-width. This is the only rule in this
      file that reaches outside our own classes, and it is scoped by `:has()` to
      wrappers that actually contain our output. It is what fixes the directory,
      whose content has a genuine max-content width of its own.

   Where `:has()` is unsupported the map is still correct via belt 1 and the
   list is merely narrower — degraded, not broken. */

.elementor-widget-shortcode:has(.mv-states-map),
.elementor-widget-shortcode:has(.mv-states-dir) {
	flex: 1 1 100%;
	width: 100%;
	min-width: 0;
	max-width: 100%;
}

.mv-states-map__svg {
	display: block;
	/* Not `100%` — see the note above. This is the design's own canvas width,
	   acting as the intrinsic size, clamped by max-width. The variable exists so
	   the "Map maximum width" setting can lower it; the fallback is the design
	   value, and an override cannot cause overflow because max-width still caps
	   it at the container. */
	width: var(--mv-map-canvas, 1360px);
	max-width: 100%;
	height: auto;
	/* The hover label is drawn near a state's centre and can extend past the
	   viewBox on an edge state. The label x is already clamped 46 units in from
	   each side in PHP, so nothing needs to escape the box. */
	overflow: visible;
}

/* --- Layer 1: the painted shapes ----------------------------------------- */

.mv-states-map__shapes,
.mv-states-map__pins {
	pointer-events: none;
}

.mv-state-shape {
	stroke-width: 1.318;
	transition: fill 160ms ease-out;
}

.mv-state-shape.is-licensed {
	fill: var(--mv-map-fill-l);
	stroke: var(--mv-map-rim-l);
	stroke-opacity: 0.4;
}

.mv-state-shape.is-coming-soon {
	fill: var(--mv-map-fill-off-l);
	stroke: var(--mv-map-rim-off-l);
	stroke-opacity: 1;
}

/* --- Layer 2: the status pins -------------------------------------------- */

/* `color` rather than `fill`, because the pin body inside the <use> shadow tree
   is drawn with fill="currentColor" — that is what makes one shared shape
   recolourable per instance. */
.mv-state-pin.is-licensed,
.mv-callout__pin.is-licensed,
.mv-map-legend__pin.is-licensed {
	color: var(--mv-map-rim-l);
}

.mv-state-pin.is-coming-soon,
.mv-callout__pin.is-coming-soon,
.mv-map-legend__pin.is-coming-soon {
	color: var(--mv-map-fill-l);
}

/* --- Layer 3: hit areas, hover fills, hover labels ----------------------- */

.mv-state__hit {
	fill: transparent;
	stroke: transparent;
	stroke-width: 1.318;
	/* `all` rather than the default visiblePainted, so a transparent fill still
	   hit-tests reliably across browsers. */
	pointer-events: all;
	transition: fill 160ms ease-out, stroke 160ms ease-out;
}

a.mv-state {
	cursor: pointer;
}

.mv-state.is-unlinked {
	cursor: default;
}

.mv-state__pin,
.mv-state__label {
	opacity: 0;
	pointer-events: none;
	transition: opacity 120ms ease-out;
}

/* Set explicitly. The pin body is fill="currentColor", and this one carries no
   status class, so without this the hover pin would take the HOST PAGE's text
   colour and change appearance depending on which section it is dropped into.
   Ink reads clearly against the bright hover fill either way. */
.mv-state__pin {
	color: var(--mv-map-ink-l);
}

.mv-state__label {
	fill: var(--mv-map-ink-l);
	font-family: inherit;
	font-size: 15px;
	font-weight: 500;
	letter-spacing: -0.3px;
	/* A halo instead of a tooltip box: it needs no width measurement, so the
	   label stays legible over any fill without JavaScript sizing a rect. */
	paint-order: stroke;
	stroke: #fff;
	stroke-width: 4px;
	stroke-linejoin: round;
}

.mv-state:hover .mv-state__hit,
.mv-state:focus-visible .mv-state__hit {
	fill: var(--mv-map-accent-l);
	stroke: var(--mv-map-fill-l);
}

.mv-state.is-coming-soon:hover .mv-state__hit,
.mv-state.is-coming-soon:focus-visible .mv-state__hit {
	fill: var(--mv-map-light-l);
	stroke: var(--mv-map-rim-off-l);
}

.mv-state:hover .mv-state__pin,
.mv-state:hover .mv-state__label,
.mv-state:focus-visible .mv-state__pin,
.mv-state:focus-visible .mv-state__label {
	opacity: 1;
}

.mv-state:focus {
	outline: none;
}

.mv-state:focus-visible .mv-state__hit {
	outline: none;
	stroke: var(--mv-map-ink-l);
	stroke-width: 2.6;
}

/* --- The D.C. callout ---------------------------------------------------- */

.mv-callout__lead {
	fill: none;
	stroke: var(--mv-map-fill-l);
	stroke-opacity: 0.5;
	stroke-width: 1.582;
}

.mv-callout__box {
	fill: #fff;
	stroke: var(--mv-map-fill-l);
	stroke-width: 1.977;
	transition: fill 160ms ease-out;
}

.mv-callout__shape {
	stroke-width: 2.3725;
}

.mv-callout__shape.is-licensed {
	fill: var(--mv-map-fill-l);
	stroke: var(--mv-map-rim-l);
	stroke-opacity: 0.4;
}

.mv-callout__shape.is-coming-soon {
	fill: var(--mv-map-fill-off-l);
	stroke: var(--mv-map-rim-off-l);
}

.mv-callout__label {
	fill: var(--mv-map-fill-l);
	font-family: inherit;
	font-size: 13.84px;
	font-weight: 700;
	letter-spacing: -0.2px;
}

a.mv-callout {
	cursor: pointer;
}

.mv-callout.is-unlinked {
	cursor: default;
}

a.mv-callout:hover .mv-callout__box,
a.mv-callout:focus-visible .mv-callout__box {
	fill: var(--mv-map-wash-l);
}

a.mv-callout:focus-visible .mv-callout__box {
	outline: none;
	stroke-width: 3.2;
}

/* --- Legend -------------------------------------------------------------- */

.mv-map-legend {
	display: flex;
	flex-wrap: wrap;
	gap: 8px clamp(16px, 2.3vw, 33.4px);
	align-items: center;
	justify-content: center;
	margin: 0;
	padding: 0;
	list-style: none;
}

.mv-map-legend__item {
	display: flex;
	gap: 9.5px;
	align-items: center;
	margin: 0;
	color: #212121;
	font-size: clamp(14px, 1.08vw, 15.5px);
	line-height: 1.5;
}

.mv-map-legend__swatch {
	flex: 0 0 auto;
	width: 19px;
	height: 19px;
	border: 2.4px solid color-mix(in srgb, var(--mv-map-rim-l) 40%, transparent);
	border-radius: 3.6px;
	background: var(--mv-map-fill-l);
}

.mv-map-legend__pin {
	flex: 0 0 auto;
	width: 16.7px;
	height: 21.5px;
}

/* ==========================================================================
   DIRECTORY
   ========================================================================== */

.mv-states-dir {
	display: block;
	width: 100%;
}

.mv-states-dir__head {
	display: flex;
	flex-wrap: wrap;
	gap: 16px 24px;
	align-items: flex-end;
	justify-content: space-between;
	padding-bottom: 24px;
}

.mv-states-dir__title {
	flex: 1 1 260px;
	min-width: 0;
}

/* SPECIFICITY FLOOR — see the note at the foot of this file. The kit ships
   `.elementor h2 { color: … }` at 0-1-1, which beats a plain class at 0-1-0, so
   the heading rendered in the kit's navy instead of the design's green. Scoping
   to the block root takes this to 0-2-0.
   Type comes from the kit's own `--mv-text-h2`, which is already exactly the
   design's clamp(32px, 3.89vw, 56px) — referenced rather than restated so there
   is one source of truth, and so this survives a tag other than h2. */
.mv-states-dir .mv-states-dir__title {
	margin: 0;
	color: var(--mv-map-fill-l);
	font-size: var(--mv-text-h2, clamp(32px, 3.89vw, 56px));
	font-weight: 400;
	letter-spacing: -0.05em;
	line-height: 1.03;
}

.mv-states-dir__controls {
	display: flex;
	flex-wrap: wrap;
	gap: 16px;
	align-items: flex-end;
	justify-content: flex-end;
	min-width: 0;
}

.mv-states-dir__field {
	display: flex;
	flex-direction: column;
	gap: 4px;
	/* A flex item defaults to min-width:auto, which for a field wrapping an
	   <input type="search"> is that input's intrinsic ~175px. Without these two
	   resets the controls row refuses to shrink and pushes the page sideways
	   below ~400px, even though every width here is already a percentage. */
	min-width: 0;
}

/* A real <label>, visually hidden rather than replaced by a placeholder — a
   placeholder is not an accessible name and disappears the moment you type. */
.mv-states-dir__label {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	border: 0;
	clip-path: inset(50%);
	white-space: nowrap;
}

.mv-states-dir__control {
	position: relative;
	display: flex;
	gap: 12px;
	align-items: center;
	box-sizing: border-box;
	min-width: 0;
	padding: 8px 12px;
	border-radius: 8px;
	background: var(--mv-map-light-l);
	color: var(--mv-map-ink-l);
}

/* Figma frames both control icons at 24px with the artwork inset inside that
   box — see icon_search() in the directory class. The SVGs now declare the real
   24px frame, so these are the frame sizes and the ink lands at 17.91px and
   11.57 x 6.68 respectively, which is what the design draws. */
.mv-states-dir__icon {
	flex: 0 0 auto;
	width: 24px;
	height: 24px;
	opacity: 0.8;
}

.mv-states-dir__input,
.mv-states-dir__select {
	flex: 1 1 auto;
	min-width: 0;
}

/* SPECIFICITY FLOOR — the theme reset ships `input[type="search"] { border-width:
   1px; border-radius: 3px; padding: 8px 16px }`. An attribute selector counts at
   class level, so that is 0-1-1 and it BEATS a plain class at 0-1-0: the field
   rendered as a grey outlined box inset inside the green pill instead of sitting
   flush in it. Scoped to the block root this is 0-2-0 and wins. */
.mv-states-dir .mv-states-dir__input,
.mv-states-dir .mv-states-dir__select {
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: none;
	box-shadow: none;
	color: inherit;
	font: inherit;
	font-size: 16px;
	letter-spacing: -0.03em;
	line-height: 1.6;
}

.mv-states-dir__field .mv-states-dir__control {
	width: 248px;
	max-width: 100%;
}

/* Figma draws this pill 128px wide with a 16px gap. The gap is exact; the width
   is not copied, and this is the RULE about specs being intent rather than
   gospel rather than an exception to it. 128px minus 24px of padding, a 16px gap
   and the 24px chevron leaves 64px of text — enough for the placeholder "Sort
   by" the mock shows, and not enough for any real selected value. So the pill
   keeps every other Figma property and sizes to its content instead.

   `width: auto` on a flex container whose <select> is `min-width: 0` resolves to
   the select's own max-content, which is its WIDEST OPTION — so the pill is
   stable as you change the selection rather than jumping, and a longer option
   label added on the settings screen simply fits. */
.mv-states-dir__field--sort .mv-states-dir__control {
	gap: 16px;
	width: auto;
	min-width: 128px;
}

/* ==========================================================================
   `hidden` LOSES TO ANY AUTHOR `display`
   ==========================================================================

   The UA stylesheet's `[hidden] { display: none }` is beaten by ANY author
   `display` declaration on the same element, whatever the specificity — origin
   wins before specificity is ever considered. So `.mv-states-dir__field
   { display: flex }` silently defeated the `hidden` attribute PHP puts on the
   controls, which meant a visitor with JavaScript off saw a search box that
   could not search: exactly the thing `hidden` was there to prevent. The row
   rule below already existed for the same reason; these are the ones that were
   missing. Every element in this file that is ever given `hidden` needs a line
   here. */

.mv-states-dir__field[hidden],
.mv-states-dir__control[hidden],
.mv-states-dir__combo[hidden],
.mv-states-dir__listbox[hidden] {
	display: none;
}

/* --- The branded sort menu ------------------------------------------------ */

.mv-states-dir__combo {
	position: relative;
	min-width: 0;
}

.mv-states-dir__combo-btn {
	gap: 16px;
	width: auto;
	min-width: 128px;
	max-width: 100%;
	border: 0;
	font: inherit;
	font-size: 16px;
	letter-spacing: -0.03em;
	line-height: 1.6;
	text-align: left;
	cursor: pointer;
}

.mv-states-dir__combo-value {
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* Also restated at 0-2-0 for the reset — see the button note further down. */
.mv-states-dir .mv-states-dir__combo-btn:hover,
.mv-states-dir .mv-states-dir__combo-btn:focus {
	background: var(--mv-map-light-l);
	color: var(--mv-map-ink-l);
}

.mv-states-dir .mv-states-dir__combo-btn:focus-visible {
	outline: 2px solid var(--mv-map-focus-l);
	outline-offset: 2px;
}

.mv-states-dir__combo-btn[aria-expanded="true"] .mv-states-dir__chevron {
	transform: rotate(180deg);
}

.mv-states-dir__listbox {
	position: absolute;
	z-index: 20;
	top: calc(100% + 6px);
	right: 0;
	box-sizing: border-box;
	min-width: 100%;
	margin: 0;
	padding: 4px;
	border: 1px solid var(--mv-map-rim-off-l);
	border-radius: 8px;
	background: #fff;
	box-shadow: 0 10px 24px -12px rgb(26 42 16 / 35%);
	list-style: none;
}

.mv-states-dir__opt {
	margin: 0;
	padding: 8px 12px;
	border-radius: 5px;
	color: var(--mv-map-ink-l);
	font-size: 16px;
	letter-spacing: -0.03em;
	line-height: 1.6;
	white-space: nowrap;
	cursor: pointer;
}

.mv-states-dir__opt[aria-selected="true"] {
	color: var(--mv-map-fill-l);
	font-weight: 500;
}

/* `.is-active` rather than :hover alone, because the keyboard moves the active
   option with aria-activedescendant and never moves the pointer. One class, set
   by both paths, so the two can never disagree about what is highlighted. */
.mv-states-dir__opt:hover,
.mv-states-dir__opt.is-active {
	background: var(--mv-map-light-l);
}

.mv-states-dir__input:focus,
.mv-states-dir__select:focus {
	outline: none;
}

.mv-states-dir__control:focus-within {
	outline: 2px solid var(--mv-map-focus-l);
	outline-offset: 2px;
}

.mv-states-dir__input::placeholder {
	color: currentColor;
	opacity: 0.8;
}

.mv-states-dir__select {
	appearance: none;
	cursor: pointer;
}

.mv-states-dir__chevron {
	flex: 0 0 auto;
	width: 24px;
	height: 24px;
	pointer-events: none;
	transition: transform 160ms ease-out;
}

/* --- List ---------------------------------------------------------------- */

.mv-states-dir__list {
	margin: 0;
	padding: 0;
	border-top: 1px solid var(--mv-map-ink-l);
	list-style: none;
}

.mv-states-dir__row {
	margin: 0;
	border-bottom: 1px solid var(--mv-map-ink-l);
}

.mv-states-dir__row[hidden] {
	display: none;
}

.mv-states-dir__link {
	display: flex;
	gap: 24px;
	align-items: center;
	justify-content: space-between;
	padding: 16px 0;
	text-decoration: none;
}

/* Also floored to 0-2-1. `.elementor a` is 0-1-1 and the theme reset ships a
   pink `a { color }`; today neither sets a colour that reaches here, but a plain
   `.mv-states-dir__link` at 0-1-0 would lose to the first kit rule that did. */
.mv-states-dir .mv-states-dir__link {
	color: var(--mv-map-ink-l);
	text-decoration: none;
}

.mv-states-dir__main {
	display: flex;
	flex: 1 1 auto;
	gap: 12px;
	align-items: center;
	min-width: 0;
}

/*
 * Doubled class deliberately. The theme ships `.elementor img { height: auto }`,
 * which at 0-1-1 OUTRANKS a single class — so a one-class rule here loses the
 * height outright. It happens to look correct anyway while WordPress's
 * `thumbnail` size is a hard 150x150 square crop, because `auto` on a square
 * image resolves to the same 48px. Change that crop, or attach a non-square
 * image, and every row would take a different height. 0-2-0 settles it.
 */
.mv-states-dir .mv-states-dir__thumb {
	flex: 0 0 auto;

	/*
	 * border-box because the empty variant carries a 1px border and a real photo
	 * does not. Without it the placeholder measures 50px, and a list mixing the
	 * two would step 2px sideways row to row.
	 */
	box-sizing: border-box;
	width: 48px;
	height: 48px;
	border-radius: 4px;
	object-fit: cover;
}

/*
 * The empty slot. It holds the same 48px box a real photo would, so adding
 * images later cannot reflow the list. `display:flex` on a <span> is what
 * centres the glyph — the element is inline by default and would otherwise sit
 * on the text baseline.
 */
.mv-states-dir__thumb--empty {
	display: flex;
	align-items: center;
	justify-content: center;
	border: 1px solid var(--mv-map-rim-off-l);
	background: var(--mv-map-fill-off-l);
}

.mv-states-dir__thumb-glyph {
	width: 24px;
	height: 24px;
	color: var(--mv-map-fill-l);
	opacity: 0.55;
}

.mv-states-dir__name {
	overflow: hidden;
	font-size: clamp(17px, 1.39vw, 20px);
	letter-spacing: -0.02em;
	line-height: 1.4;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.mv-states-dir__badge {
	flex: 0 0 auto;
	padding: 2px 10px;
	border: 1px solid var(--mv-map-rim-off-l);
	border-radius: 999px;
	background: var(--mv-map-fill-off-l);
	color: var(--mv-map-fill-l);
	font-size: 13px;
	letter-spacing: 0;
	line-height: 1.5;
	white-space: nowrap;
}

.mv-states-dir__more {
	display: flex;
	flex: 0 0 auto;
	gap: 4px;
	align-items: center;
	font-size: clamp(17px, 1.39vw, 20px);
	letter-spacing: -0.02em;
	line-height: 1.4;
	white-space: nowrap;
}

.mv-states-dir__more .mv-states-dir__arrow-glyph {
	width: 0.72em;
	height: 0.72em;
	transition: transform 160ms ease-out;
}

a.mv-states-dir__link:hover {
	color: var(--mv-map-fill-l);
}

a.mv-states-dir__link:hover .mv-states-dir__name,
a.mv-states-dir__link:focus-visible .mv-states-dir__name {
	text-decoration: underline;
	text-underline-offset: 3px;
}

a.mv-states-dir__link:hover .mv-states-dir__arrow-glyph {
	transform: translateX(4px);
}

a.mv-states-dir__link:focus-visible {
	outline: 2px solid var(--mv-map-focus-l);
	outline-offset: -2px;
}

/* No page attached yet. Deliberately quiet rather than pretending to be a
   link — the name and status are still the point. */
.mv-states-dir__link--inert {
	cursor: default;
}

.mv-states-dir--unlinked .mv-states-dir__more {
	display: none;
}

/* --- Pager --------------------------------------------------------------- */

.mv-states-dir__pager {
	position: relative;
	display: flex;
	flex-wrap: wrap;
	gap: 16px;
	align-items: center;
	justify-content: space-between;
	min-height: 80px;
	padding-top: 15px;
}

.mv-states-dir__pager[hidden] {
	display: none;
}

.mv-states-dir__dots {
	display: flex;
	gap: 4px;
	align-items: center;
	margin: 0;
	padding: 0;
	list-style: none;
}

.mv-states-dir__dots li {
	margin: 0;
}

.mv-states-dir__dot {
	display: block;
	padding: 10px 2px;
	border: 0;
	background: none;
	cursor: pointer;
	line-height: 0;
}

.mv-states-dir__dot-hit {
	display: block;
	width: 4px;
	height: 4px;
	border-radius: 70px;
	background: var(--mv-map-accent-l);
	opacity: 0.6;
	transition: width 160ms ease-out, opacity 160ms ease-out;
}

.mv-states-dir__dot[aria-current="true"] .mv-states-dir__dot-hit {
	width: 28px;
	opacity: 1;
}

.mv-states-dir__dot:hover .mv-states-dir__dot-hit {
	opacity: 1;
}

.mv-states-dir__dot:focus-visible {
	outline: 2px solid var(--mv-map-focus-l);
	outline-offset: 2px;
	border-radius: 4px;
}

/* ==========================================================================
   THE THEME'S BUTTON RESET PAINTS EVERY BUTTON PINK ON HOVER AND ON FOCUS
   ==========================================================================

   Measured on staging, from reset.css:

     [type="button"]:focus, [type="button"]:hover, [type="submit"]:focus,
     [type="submit"]:hover, button:focus, button:hover
        { background-color: #cc3366; color: #fff }

   `button:hover` is 0-1-1 — a pseudo-class counts at class level, exactly like
   the attribute selector in the input reset — so it beats a plain class. Three
   things were hit, and every one of them is a button:

   1. The DISABLED pager arrow. `…__arrow:hover:not([disabled])` is 0-3-0 and
      wins while the button is enabled, but it deliberately excludes the
      disabled state — and a disabled button still matches `:hover` in CSS. So
      hovering the greyed-out arrow turned it PINK.
   2. Both arrows on `:focus`, which nothing here was overriding at all.
   3. Every pagination DOT, whose whole 28x24 hit area went pink on hover.

   Restating hover AND focus for both, including the disabled case. `:focus`
   rather than only `:focus-visible`, because the reset uses plain `:focus` and
   a keyboard-invisible focus still triggers it. */

.mv-states-dir .mv-states-dir__arrow:hover:not([disabled]),
.mv-states-dir .mv-states-dir__arrow:focus:not([disabled]) {
	background: var(--mv-map-light-l);
	color: var(--mv-map-ink-l);
}

.mv-states-dir .mv-states-dir__arrow[disabled],
.mv-states-dir .mv-states-dir__arrow[disabled]:hover,
.mv-states-dir .mv-states-dir__arrow[disabled]:focus {
	background: var(--mv-map-soft-l);
	color: var(--mv-map-ink-l);
}

.mv-states-dir .mv-states-dir__dot:hover,
.mv-states-dir .mv-states-dir__dot:focus {
	background: none;
	color: inherit;
}

.mv-states-dir__arrows {
	display: flex;
	gap: 8px;
	align-items: center;
	margin-left: auto;
}

.mv-states-dir__arrow {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 50px;
	height: 50px;
	padding: 0;
	border: 0;
	border-radius: 210px;
	background: var(--mv-map-soft-l);
	color: var(--mv-map-ink-l);
	cursor: pointer;
	transition: background 160ms ease-out, opacity 160ms ease-out;
}

.mv-states-dir__arrow .mv-states-dir__arrow-glyph {
	width: 40px;
	height: 40px;
	border-radius: 50%;
	background: var(--mv-map-wash-l);
	padding: 0;
}

.mv-states-dir__arrow--prev .mv-states-dir__arrow-glyph {
	transform: rotate(180deg);
}

.mv-states-dir__arrow:hover:not([disabled]) {
	background: var(--mv-map-light-l);
}

.mv-states-dir__arrow[disabled] {
	cursor: default;
	opacity: 0.45;
}

.mv-states-dir__arrow:focus-visible {
	outline: 2px solid var(--mv-map-focus-l);
	outline-offset: 2px;
}

/* --- Live region + empty state ------------------------------------------- */

.mv-states-dir__status {
	margin: 8px 0 0;
	color: var(--mv-map-ink-l);
	font-size: 15px;
	line-height: 1.5;
	opacity: 0.8;
}

.mv-states-dir__status:empty {
	display: none;
}

/* ==========================================================================
   BREAKPOINTS
   ========================================================================== */

@media (max-width: 767px) {
	/* The map keeps its aspect ratio and scales down. It is not made
	   horizontally scrollable on purpose: at phone width the individual state
	   shapes are too small to be a realistic tap target however it is scaled,
	   and the directory below IS the mobile navigation path — every state is a
	   full-width row there. So the map reads as the illustration it effectively
	   is, with no horizontal overflow anywhere. */
	.mv-states-map {
		gap: 16px;
	}

	.mv-map-legend {
		justify-content: flex-start;
	}

	/* `flex-wrap: nowrap` is load-bearing, not tidying. In a WRAPPING column flex
	   container, a stretched item is sized to the flex LINE, and the line's cross
	   size is the widest item's MAX-CONTENT — not the container's width. So the
	   controls stretched to the search field's max-content (308px) inside a 288px
	   container and pushed the page sideways, and `min-width: 0` could not stop it
	   because the automatic minimum size applies to the main axis, not the cross
	   axis. Turning off wrapping makes it a single-line container, where a
	   stretched item takes the container's own cross size. Same family as the
	   `flex-basis` note below: a flex property means something different the
	   moment the direction changes. */
	.mv-states-dir__head {
		flex-direction: column;
		flex-wrap: nowrap;
		align-items: stretch;
	}

	/* flex-basis resolves against the MAIN axis, so the title's `1 1 260px`
	   becomes a 260px minimum HEIGHT the moment the head turns into a column —
	   which is a ~300px blank gap above the search field, not a narrower title.
	   Reset it rather than restating the basis. */
	.mv-states-dir__title {
		flex: 0 0 auto;
	}

	.mv-states-dir__controls {
		justify-content: flex-start;
	}

	.mv-states-dir__field .mv-states-dir__control,
	.mv-states-dir__field--sort .mv-states-dir__control {
		width: 100%;
	}

	.mv-states-dir__field {
		flex: 1 1 140px;
	}

	/* "See more" collapses to the arrow alone — the whole row is already the
	   link, so at this width the words only compete with the state name. The
	   text is dropped, not visually hidden, because the link's accessible name
	   is the state name and the arrow adds nothing to announce. */
	.mv-states-dir__more-text {
		display: none;
	}

	.mv-states-dir__pager {
		min-height: 0;
		padding-top: 24px;
	}
}

/* Below this, two fields side by side leave the sort select too narrow to read
   "Licensed first", and a multi-line flex container's min-content size keeps them
   from wrapping on their own. So stack them explicitly. */
@media (max-width: 479px) {
	.mv-states-dir__controls {
		flex-direction: column;
		/* Same reason as the head above — this container also turns into a
		   column, and it inherits `wrap` from the base rule. */
		flex-wrap: nowrap;
		align-items: stretch;
	}

	.mv-states-dir__field {
		flex: 0 0 auto;
	}
}

@media (prefers-reduced-motion: reduce) {
	.mv-state-shape,
	.mv-state__hit,
	.mv-state__pin,
	.mv-state__label,
	.mv-callout__box,
	.mv-states-dir__arrow,
	.mv-states-dir__dot-hit,
	.mv-states-dir__chevron,
	.mv-states-dir__more .mv-states-dir__arrow-glyph {
		transition: none;
	}

	a.mv-states-dir__link:hover .mv-states-dir__arrow-glyph {
		transform: none;
	}
}

@media (forced-colors: active) {
	.mv-state-shape.is-licensed {
		fill: CanvasText;
	}

	.mv-state-shape.is-coming-soon {
		fill: Canvas;
		stroke: CanvasText;
	}

	.mv-state:hover .mv-state__hit,
	.mv-state:focus-visible .mv-state__hit {
		fill: Highlight;
	}
}

/* ==========================================================================
   NOTE ON SPECIFICITY — read before adding a rule that sets colour or type
   ==========================================================================

   This site's kit stylesheet (post-7.css) styles bare tags inside `.elementor`:

     .elementor h1, .elementor h2, .elementor h3, .elementor h4
        → font-family, font-weight, colour, font-size, line-height, letter-spacing

   That selector is specificity 0-1-1, so it BEATS a plain single class at 0-1-0
   even though this stylesheet loads after it. Measured, not assumed: the
   directory heading rendered in the kit's `--mv-teal-heading` (#054059) while
   `.mv-states-dir__title { color: … }` was present and matching.

   So any rule here that sets colour or type on an element whose TAG the kit
   styles must be scoped to its block root (`.mv-states-dir .mv-states-dir__x`,
   0-2-0) to win. Bare-class rules are fine for everything the kit does not
   touch — layout, spacing, backgrounds, borders, our own custom properties.

   The theme reset is a second source of the same problem, and it is easy to
   under-read. `a { color: #c36 }` and `button/input/select { font: inherit }` are
   0-0-1, which a single class does beat — but the reset ALSO ships

     input[type="search"] { border-width: 1px; border-radius: 3px; padding: 8px 16px }

   and an attribute selector counts at CLASS level, so that is **0-1-1** and it
   beats a plain class outright. Do not assume a bare-tag reset is weak: check
   whether it carries an attribute selector.

   Prefer referencing a kit variable over restating a value: `--mv-text-h2` is
   already exactly the design's h2 clamp, so the heading reads it instead of
   carrying a second copy that could drift. */
