/**
 * KCAI PET MAP — SHARED MARKER / ZONE / POPUP STYLES
 * ==================================================
 * Deployed byte-identically to both sites. Master: shared/petmap/kcai-petmap.css
 *
 * SCOPING. Every selector is prefixed .kpm-* and nothing here styles a Leaflet
 * internal except through a .kpm- ancestor. Both host sites already carry their
 * own map CSS (.ccm-* on KCPSR, .kcai-dir__* on KCAI) and this file has to be
 * able to land next to either without touching it.
 *
 * THEME. LIGHT-FIRST. The basemap is the standard light OpenStreetMap style —
 * the one people recognise, with terrain, landmarks and visible minor roads —
 * so the defaults below are tuned for dark marks on pale ground. The dark block
 * remains supported for the KCPSR Command Center's dark sections.
 *
 * The ring is 3px and always carries a dark outer shadow because it has to hold
 * against BOTH: a bright ring alone vanishes on a pale road surface, and a dark
 * one vanishes on dark tiles.
 *
 * COLOUR MEANS SPECIES, NOT STATUS — cat purple, dog thermal orange/red. That
 * is only safe because the map shows one status at a time; see the palette note
 * in kcai-petmap.js before changing either.
 */

/* --------------------------------------------------------------- markers */

.kpm-pin {
	position: relative;
	display: block;
	width: 100%;
	height: 100%;
	border-radius: 50%;
	/* The ring is the strong contrasting outer edge. The second, dark shadow
	   underneath it is what keeps the marker legible on a pale tile: a bright
	   ring alone disappears against a light road surface. */
	box-shadow:
		0 0 0 3px var(--kpm-ring, #FF5C33),
		0 0 0 4.5px rgba(0, 0, 0, .55),
		0 3px 10px rgba(0, 0, 0, .45);
	background: #0d1117;
	overflow: visible;
	transition: transform .16s ease, box-shadow .16s ease;
}

/*
 * The circular crop.
 *
 * background-position is written inline per marker from the resolved focal
 * point (see focalFor). The value here is only the fallback for a marker
 * rendered without one - the real decision always arrives on the element.
 *
 * NOTHING HERE TOUCHES THE ORIGINAL FILE. The crop is a viewport onto an
 * unmodified image; clearing the focal point restores the default view.
 */
.kpm-pin__photo {
	position: absolute;
	inset: 0;
	border-radius: 50%;
	background-size: cover;
	background-position: 50% 38%;   /* heads sit above centre in most pet photos */
	background-repeat: no-repeat;
	background-color: #0d1117;
}

/*
 * The safe fallback: show the WHOLE photograph rather than cut the animal's
 * head off. `contain` inside a circle leaves gaps, so a blurred copy of the
 * same image fills them - the marker stays a solid circle and the pet stays
 * entirely visible. Same pattern the KCPSR photo-fit system uses on cards.
 */
.kpm-pin__photo.is-contain {
	background-size: contain;
	background-position: 50% 50%;
	background-color: transparent;
}

.kpm-pin__blur {
	position: absolute;
	inset: 0;
	border-radius: 50%;
	background-size: cover;
	background-position: 50% 50%;
	filter: blur(6px) saturate(1.15);
	transform: scale(1.12);   /* hides the blur's soft edge inside the circle */
	opacity: .85;
}

.kpm-pin__fallback {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	background: radial-gradient(circle at 50% 35%, #26313d, #131a22 70%);
	color: var(--kpm-ring, #FF5C33);
}

.kpm-pin__fallback svg { width: 58%; height: 58%; }

/*
 * BADGES SIT BELOW THE FACE AND HANG OFF THE RIM.
 *
 * Both used to overlap the photograph — the status pip at top-right sat
 * squarely where a head is, which is the one part of the image the marker
 * exists to show. They are now both on the LOWER edge and pushed outward so
 * most of each badge is outside the circle: the species glyph off the
 * lower-left, the status letter off the lower-right.
 *
 * The lower half is the safe place for them because the resolved focal point
 * biases the crop upward (50% / 38%), so the animal's head is above centre by
 * construction and the bottom of the circle is body or ground.
 *
 * Neither badge is ever dropped. They are the non-colour half of the species
 * and status signals, and the accessible name still leads with "Lost cat" or
 * "Found dog" regardless of what is drawn.
 */
.kpm-pin__glyph {
	position: absolute;
	left: -12%;
	bottom: -12%;
	width: 19px;
	height: 19px;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	background: #0d1117;
	color: #fff;
	box-shadow: 0 0 0 1.5px var(--kpm-ring, #FF5C33);
}

.kpm-pin__glyph svg { width: 13px; height: 13px; }

/* The status letter, off the LOWER-RIGHT edge — never over the head. */
.kpm-pin__status {
	position: absolute;
	right: -12%;
	bottom: -12%;
	top: auto;
	min-width: 17px;
	height: 17px;
	padding: 0 3px;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 9px;
	background: var(--kpm-dot, #FF2D6F);
	color: #fff;
	font: 700 10px/1 system-ui, -apple-system, "Segoe UI", sans-serif;
	font-style: normal;
	box-shadow: 0 0 0 1.5px rgba(0, 0, 0, .6);
}

.kpm-pin.is-selected {
	box-shadow:
		0 0 0 4px var(--kpm-ring, #FF5C33),
		0 0 0 6px rgba(0, 0, 0, .6),
		0 0 0 10px color-mix(in srgb, var(--kpm-ring, #FF5C33) 30%, transparent),
		0 6px 18px rgba(0, 0, 0, .55);
	z-index: 1200;
}

/* Keyboard focus. Leaflet puts the marker element in the tab order and browsers
   draw the focus ring on a square box around a round marker, which reads as a
   rendering fault. A ring that follows the circle is both clearer and correct.
   :focus-visible only, so a mouse click does not leave a ring behind. */
.leaflet-marker-icon:focus-visible .kpm-pin {
	outline: none;
	box-shadow:
		0 0 0 3px #fff,
		0 0 0 6px #0d1117,
		0 0 0 9px var(--kpm-ring, #FF5C33);
}

.leaflet-marker-icon:focus-visible { outline: none; }

/* ----------------------------------------------- compact photo tier (20px) */

/*
 * At the neighbourhood tier the marker is 20 px and there is simply no room for
 * a glyph badge and a status pip on the rim - they render as two specks that
 * read as dirt on the screen. markerIcon() drops them and adds .is-compact; the
 * ring gets slightly thicker so the status colour still carries at that size,
 * and the accessible name still says "Lost" or "Found" in words.
 */
.kpm-pin.is-compact {
	box-shadow:
		0 0 0 2.5px var(--kpm-ring, #FF5C33),
		0 0 0 3.5px rgba(0, 0, 0, .6),
		0 1px 5px rgba(0, 0, 0, .4);
}

/* Badges shrink with the marker so the FACE keeps the pixels. At 34px the
   full-size 17px status pill covered about half the animal. */
.kpm-pin.is-compact .kpm-pin__glyph {
	width: 13px; height: 13px; left: -14%; bottom: -14%;
	box-shadow: 0 0 0 1px var(--kpm-ring, #FF5C33);
}
.kpm-pin.is-compact .kpm-pin__glyph svg { width: 9px; height: 9px; }

.kpm-pin.is-compact .kpm-pin__status {
	min-width: 12px; height: 12px; padding: 0 2px;
	right: -14%; bottom: -14%; top: auto;
	font-size: 8px; border-radius: 6px;
	box-shadow: 0 0 0 1px rgba(0, 0, 0, .6);
}

/* -------------------------------------------------------- interstates */

/*
 * The blue is applied through Leaflet path options, not here - these rules only
 * cover the shields, which are DOM. Note there is no CSS filter anywhere in
 * this file touching .leaflet-tile-pane: the basemap is never recoloured.
 */
.kpm-shield {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 30px;
	height: 24px;
	border-radius: 5px;
	background: #1F5FD1;
	box-shadow: 0 0 0 1.5px #fff, 0 0 0 2.5px rgba(4, 16, 31, .75), 0 1px 4px rgba(0, 0, 0, .4);
	font: 800 12px/1 system-ui, -apple-system, "Segoe UI", sans-serif;
	color: #fff;
	letter-spacing: -.02em;
}

.kpm-shield b { font-weight: 800; }

/* US routes get the squarer, paler treatment their real signs have, so I-49 and
   US-71 are distinguishable where they run together. */
.kpm-shield--us {
	background: #0F2C5C;
	border-radius: 3px;
}

/* ----------------------------------------------------------------- rings */

/* Leaflet paths do not inherit CSS transitions usefully, and the ring styling
   is set through path options in JS. These classes exist so the two ring types
   are addressable from the host page and identifiable in a DOM dump during a
   privacy audit — "which circle is the privacy one" should not require reading
   a colour. */
.kpm-ring { pointer-events: none; }
.kpm-ring--area { }
.kpm-ring--zone { }

/* --------------------------------------------------------------- popups */

.leaflet-popup-content-wrapper:has(.kpm-pop) {
	background: #0f151c;
	color: #e8eef5;
	border-radius: 14px;
	box-shadow: 0 10px 34px rgba(0, 0, 0, .5);
	padding: 0;
	overflow: hidden;
}

.leaflet-popup-content:has(.kpm-pop) { margin: 0; width: 244px !important; }
.leaflet-popup-tip:has(+ * .kpm-pop), .leaflet-popup:has(.kpm-pop) .leaflet-popup-tip { background: #0f151c; }

.kpm-pop {
	font: 400 13px/1.45 system-ui, -apple-system, "Segoe UI", sans-serif;
	padding: 12px 13px 13px;
}

.kpm-pop__head { display: flex; gap: 11px; align-items: center; margin-bottom: 10px; }

.kpm-pop__img {
	flex: 0 0 auto;
	width: 62px;
	height: 62px;
	border-radius: 11px;
	object-fit: cover;
	object-position: 50% 42%;
	background: #1a232e;
	box-shadow: 0 0 0 2px var(--kpm-ring, #FF5C33);
}

.kpm-pop__img--none {
	display: flex;
	align-items: center;
	justify-content: center;
	color: var(--kpm-ring, #FF5C33);
}
.kpm-pop__img--none svg { width: 34px; height: 34px; }

.kpm-pop__id { min-width: 0; }

.kpm-pop__badge {
	display: inline-block;
	padding: 2px 7px;
	border-radius: 999px;
	background: var(--kpm-ring, #FF5C33);
	color: #fff;
	font-size: 10px;
	font-weight: 800;
	letter-spacing: .05em;
	text-transform: uppercase;
}

.kpm-pop__tags { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; }

.kpm-pop__species {
	display: inline-block;
	padding: 2px 7px;
	border-radius: 999px;
	border: 1px solid currentColor;
	color: #9db0c4;
	font-size: 10px;
	font-weight: 700;
	letter-spacing: .04em;
	text-transform: uppercase;
}

.kpm-pop__name {
	display: block;
	margin-top: 4px;
	font-size: 16px;
	font-weight: 700;
	color: #fff;
	overflow-wrap: anywhere;
}

.kpm-pop__meta { margin: 0 0 9px; display: grid; gap: 3px; }
.kpm-pop__row { display: grid; grid-template-columns: 88px 1fr; gap: 8px; }
.kpm-pop__row dt { color: #93a4b6; font-size: 11.5px; }
.kpm-pop__row dd { margin: 0; color: #e8eef5; font-size: 12.5px; overflow-wrap: anywhere; }

.kpm-pop__zone {
	margin: 0 0 6px;
	padding: 6px 8px;
	border-left: 3px dashed var(--kpm-ring, #FF5C33);
	background: rgba(255, 92, 51, .09);
	border-radius: 0 7px 7px 0;
	font-size: 12px;
	font-weight: 600;
	color: #ffd9cc;
}

.kpm-pop--found .kpm-pop__zone { background: rgba(0, 164, 253, .1); color: #cfe6ff; }

.kpm-pop__privacy { margin: 0 0 10px; font-size: 11px; color: #8c9db0; }

.kpm-pop__cta {
	display: block;
	padding: 9px 10px;
	border-radius: 9px;
	background: var(--kpm-ring, #FF5C33);
	color: #fff !important;
	text-align: center;
	font-size: 13px;
	font-weight: 700;
	text-decoration: none;
}

.kpm-pop__cta:hover, .kpm-pop__cta:focus-visible { filter: brightness(1.12); }
.kpm-pop__cta:focus-visible { outline: 3px solid #fff; outline-offset: 2px; }

/* --------------------------------------------------------------- legend */

.kpm-legend {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px 14px;
	margin-top: 10px;
	font: 400 12px/1.4 system-ui, -apple-system, "Segoe UI", sans-serif;
	color: #9db0c4;
}

/* The status sentence. Load-bearing now that colour means species: without it a
   reader on the Found tab sees thermal-orange markers and has nothing telling
   them those are found dogs rather than lost ones. */
.kpm-legend__status {
	flex: 1 1 100%;
	margin: 0 0 2px;
	font-size: 12.5px;
	color: #445466;
}
.kpm-legend__status strong { color: #16202b; }

.kpm-legend__keys { display: flex; flex-wrap: wrap; gap: 6px 14px; }
.kpm-legend__key { display: inline-flex; align-items: center; gap: 6px; }

.kpm-legend__swatch {
	width: 15px;
	height: 15px;
	flex: 0 0 auto;
	border-radius: 50%;
	background: var(--kpm-fill, #FF3D00);
	box-shadow: 0 0 0 2px var(--kpm-ring, #FF5C33);
}

.kpm-legend__swatch--zone {
	background: rgba(255, 61, 0, .16);
	border: 2px dashed #FF2D6F;
	box-shadow: none;
}

.kpm-legend__swatch--area {
	background: rgba(255, 106, 0, .06);
	border: 1px solid rgba(255, 138, 92, .55);
	box-shadow: none;
}

.kpm-legend__note { flex: 1 1 100%; margin: 2px 0 0; font-size: 11.5px; color: #8496aa; }

/* ---------------------------------------------------------- methodology */

.kpm-method { margin-top: 8px; font: 400 12px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif; }

.kpm-method > summary {
	cursor: pointer;
	color: #9dc6ff;
	font-weight: 600;
	padding: 4px 0;
	list-style: revert;
}

.kpm-method > summary:focus-visible { outline: 2px solid #00A4FD; outline-offset: 2px; border-radius: 4px; }
.kpm-method__body { color: #9db0c4; padding: 4px 0 0 2px; }
.kpm-method__body ul { margin: 6px 0; padding-left: 18px; }
.kpm-method__body li { margin: 2px 0; }
.kpm-method__evidence, .kpm-method__future { margin: 6px 0 0; font-size: 11.5px; color: #8496aa; }

/* --------------------------------------------------- accessible list alt */

/* The map always has a text equivalent. It is not visually hidden by default on
   every surface - the KCAI directory's card grid already IS the list - but where
   a surface has no other list, this renders one. */
.kpm-list { margin: 10px 0 0; padding: 0; list-style: none; font-size: 13px; }
.kpm-list__item { padding: 5px 0; border-bottom: 1px solid rgba(255, 255, 255, .07); }
.kpm-list__item a { color: #cfe0f2; font-weight: 600; }
.kpm-list__meta { display: block; color: #8496aa; font-size: 11.5px; }

.kpm-visually-hidden {
	position: absolute !important;
	width: 1px; height: 1px;
	margin: -1px; padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* -------------------------------------------------- compact popup (phone) */

/*
 * A Leaflet popup lives INSIDE the map container and cannot escape it, so on a
 * phone the card has to fit a map that is often only 300 px tall. Measured at
 * 320 px: the full-size card was 321 px and its "View Pet Report" button was
 * below the map's bottom edge - the one control the card exists for.
 *
 * Everything here is proportion, not content: no field is dropped, so a phone
 * reader is never shown less about a pet than a desktop reader.
 */
/* The width query is the no-JS baseline; .kpm-pop--tight is set by the
   controller whenever the card is actually taller than its map, which is the
   real constraint and catches short maps at any width. */
@media (max-width: 480px) {
	.leaflet-popup-content:has(.kpm-pop) { width: 220px !important; }
	.kpm-pop { padding: 10px 11px 11px; font-size: 12.5px; }
	.kpm-pop__head { gap: 9px; margin-bottom: 8px; }
	.kpm-pop__img { width: 48px; height: 48px; border-radius: 9px; }
	.kpm-pop__img--none svg { width: 26px; height: 26px; }
	.kpm-pop__name { font-size: 14.5px; margin-top: 3px; }
	.kpm-pop__meta { margin-bottom: 7px; }
	.kpm-pop__row { grid-template-columns: 70px 1fr; gap: 6px; }
	.kpm-pop__row dt { font-size: 11px; }
	.kpm-pop__row dd { font-size: 12px; }
	.kpm-pop__zone { padding: 5px 7px; font-size: 11.5px; margin-bottom: 5px; }
	.kpm-pop__privacy { margin-bottom: 8px; font-size: 10.5px; }
	.kpm-pop__cta { padding: 8px 10px; font-size: 12.5px; }
}

.leaflet-popup-content:has(.kpm-pop--tight) { width: 220px !important; }
.kpm-pop--tight { padding: 10px 11px 11px; font-size: 12.5px; }
.kpm-pop--tight .kpm-pop__head { gap: 9px; margin-bottom: 8px; }
.kpm-pop--tight .kpm-pop__img { width: 48px; height: 48px; border-radius: 9px; }
.kpm-pop--tight .kpm-pop__img--none svg { width: 26px; height: 26px; }
.kpm-pop--tight .kpm-pop__name { font-size: 14.5px; margin-top: 3px; }
.kpm-pop--tight .kpm-pop__meta { margin-bottom: 7px; }
.kpm-pop--tight .kpm-pop__row { grid-template-columns: 70px 1fr; gap: 6px; }
.kpm-pop--tight .kpm-pop__row dt { font-size: 11px; }
.kpm-pop--tight .kpm-pop__row dd { font-size: 12px; }
.kpm-pop--tight .kpm-pop__zone { padding: 5px 7px; font-size: 11.5px; margin-bottom: 5px; }
.kpm-pop--tight .kpm-pop__privacy { margin-bottom: 8px; font-size: 10.5px; }
.kpm-pop--tight .kpm-pop__cta { padding: 8px 10px; font-size: 12.5px; }

/* ------------------------------------------------------------ light mode */

@media (prefers-color-scheme: light) {
	.leaflet-popup-content-wrapper:has(.kpm-pop) { background: #fff; color: #16202b; }
	.leaflet-popup:has(.kpm-pop) .leaflet-popup-tip { background: #fff; }
	.kpm-pop__name { color: #0d1117; }
	.kpm-pop__row dt { color: #5a6b7d; }
	.kpm-pop__row dd { color: #16202b; }
	.kpm-pop__zone { color: #8a2c10; background: rgba(255, 92, 51, .12); }
	.kpm-pop--found .kpm-pop__zone { color: #0b3f6b; background: rgba(0, 164, 253, .12); }
	.kpm-pop__privacy { color: #5a6b7d; }
	.kpm-legend, .kpm-method__body { color: #4a5b6d; }
	.kpm-legend__note, .kpm-method__evidence, .kpm-method__future { color: #5a6b7d; }
	.kpm-method > summary { color: #0b5fa8; }
	.kpm-pin { background: #fff; }
	.kpm-pin__glyph { background: #fff; color: #16202b; }
	.kpm-list__item { border-bottom-color: rgba(0, 0, 0, .1); }
	.kpm-list__item a { color: #0b5fa8; }
	.kpm-list__meta { color: #5a6b7d; }
}

/* An explicit theme attribute always beats the media query, so a host page that
   forces a theme is honoured in BOTH directions rather than only into dark. */
:root[data-theme="dark"] .leaflet-popup-content-wrapper:has(.kpm-pop) { background: #0f151c; color: #e8eef5; }
:root[data-theme="dark"] .kpm-pop__name { color: #fff; }
:root[data-theme="dark"] .kpm-pin { background: #0d1117; }
:root[data-theme="dark"] .kpm-pin__glyph { background: #0d1117; color: #fff; }

/*
 * The explicit light theme has to be COMPLETE, not a few patches.
 *
 * The sheet was authored dark-first, so anything not restated here keeps a dark
 * value — and the first light build shipped white-on-white metadata rows in the
 * popup because only the wrapper and the name had been overridden. When a host
 * page sets data-theme="light" it is asking for the whole component in light,
 * not the parts somebody remembered.
 */
:root[data-theme="light"] .leaflet-popup-content-wrapper:has(.kpm-pop) { background: #fff; color: #16202b; }
:root[data-theme="light"] .leaflet-popup:has(.kpm-pop) .leaflet-popup-tip { background: #fff; }
:root[data-theme="light"] .kpm-pop__name { color: #0d1117; }
:root[data-theme="light"] .kpm-pop__row dt { color: #5a6b7d; }
:root[data-theme="light"] .kpm-pop__row dd { color: #16202b; }
:root[data-theme="light"] .kpm-pop__species { color: #5a6b7d; }
:root[data-theme="light"] .kpm-pop__privacy { color: #5a6b7d; }
:root[data-theme="light"] .kpm-pop__zone { color: #7c2d12; background: rgba(255, 92, 31, .12); }
:root[data-theme="light"] .kpm-pin { background: #fff; }
:root[data-theme="light"] .kpm-pin__glyph { background: #fff; color: #16202b; }
:root[data-theme="light"] .kpm-legend { color: #4a5b6d; }
:root[data-theme="light"] .kpm-legend__note { color: #5a6b7d; }
:root[data-theme="light"] .kpm-legend__status { color: #445466; }
:root[data-theme="light"] .kpm-legend__status strong { color: #16202b; }
:root[data-theme="light"] .kpm-method__body { color: #4a5b6d; }
:root[data-theme="light"] .kpm-method > summary { color: #0b5fa8; }
:root[data-theme="light"] .kpm-list__item { border-bottom-color: rgba(0, 0, 0, .1); }
:root[data-theme="light"] .kpm-list__item a { color: #0b5fa8; }
:root[data-theme="light"] .kpm-list__meta { color: #5a6b7d; }

/* -------------------------------------------------------- reduced motion */

/* No pulsing and no continuously animated circles anywhere in this file by
   design - the only motion is the short hover/select transform. Somebody who
   has asked for less motion should not get even that, and Leaflet's own zoom
   animation is disabled by the host renderer on the same signal. */
@media (prefers-reduced-motion: reduce) {
	.kpm-pin { transition: none !important; }
}

/* ------------------------------------------------------- forced colours */

/* In Windows High Contrast the box-shadow ring is dropped entirely, which
   would leave a bare photo with no status edge. A real border is restored. */
@media (forced-colors: active) {
	.kpm-pin { border: 2px solid CanvasText; }
	.kpm-shield { border: 1px solid CanvasText; }
	.kpm-pin__status, .kpm-pop__badge, .kpm-pop__cta { border: 1px solid CanvasText; }
}
