/**
 * /xartis/ — map, markers, popup, point list (docs/map-plan.md).
 * Loaded only on page-templates/template-map.php (inc/enqueue.php).
 *
 * Everything here reuses the existing component language — .card, .chip,
 * .business-card__* details and status badges — so the map page reads as part of the site
 * rather than a bolted-on widget.
 */

/* ---------- Map canvas ---------- */

/* Filter chips sit directly above the map; .chip-group carries no bottom margin of its
   own, so without this the chips were flush against the map's top edge. Matches the
   breathing room the directory gets from .business-grid's own margin-top. */
[data-map-filters] {
	margin-bottom: 30px;
}

.safi-map {
	position: relative;
	margin-bottom: 28px;
}

.safi-map__canvas {
	height: 0; /* collapsed until map.js reports the map is up */
	border-radius: var(--safi-radius-lg);
	overflow: hidden;
	border: 1px solid var(--safi-border-card);
	background: var(--safi-bg-alt);
}

/* Map primacy. Was a flat 600px, which on a 1080p laptop left the map as one element among
   several rather than the thing the page is. Now viewport-relative with a floor and a
   ceiling: ~74vh means the map fills most of the screen on any laptop, the 540px floor
   keeps it usable on a short window, and the cap stops it becoming absurd on a tall
   monitor where the point list would be pushed entirely out of sight.

   Cap lowered 880px → 780px (client review 2026-08-06): at 880 the map read as oversized
   on a large monitor and the list beneath it disappeared completely below the fold. */
.safi-map.is-ready .safi-map__canvas {
	height: clamp(540px, 74vh, 780px);
	box-shadow: var(--safi-shadow-card);
}

/* Shown until (or unless) the map initialises — JS disabled, or the vendored Leaflet
   missing, which inc/enqueue.php guards against. The list below carries the page. */
.safi-map__fallback {
	display: flex;
	align-items: center;
	gap: 9px;
	margin: 0;
	padding: 18px 20px;
	border-radius: var(--safi-radius-md);
	border: 1px dashed var(--safi-border-strong);
	background: var(--safi-surface);
	color: var(--safi-text-muted-3);
	font-size: 0.98rem;
}

.safi-map.is-ready .safi-map__fallback {
	display: none;
}

@media (max-width: 640px) {
	.safi-map.is-ready .safi-map__canvas {
		height: clamp(420px, 62vh, 560px);
	}
}

/* Tiles: a very small lift only. Positron is deliberately desaturated so the markers stay
   the loudest thing on the map — this just separates land from water a little more
   clearly at island zoom levels without turning the basemap into a colourful raster.
   Delete these two declarations to get stock Positron back. */
.safi-map .leaflet-tile-pane {
	filter: saturate(1.12) contrast(1.03);
}

/* Leaflet paints its own focus outlines; re-assert the theme's ring so keyboard focus on
   the map, markers and controls looks the same as everywhere else. */
.safi-map .leaflet-container :focus-visible {
	outline: var(--safi-focus-ring);
	outline-offset: var(--safi-focus-offset);
}

.safi-map .leaflet-container {
	font-family: var(--safi-font-body);
	background: var(--safi-bg-alt);
}

/* ---------- Markers ----------
 * Contrast recipe, measured with the WCAG relative-luminance formula (same method as
 * docs/accessibility-audit.md):
 *
 * The category fill CANNOT carry 1.4.11 on its own — most pleasant mid-tone colours land
 * around 2.4–2.9:1 against a light basemap. The 2px --safi-petrol outline is what
 * satisfies the requirement, at 10.55:1 on Positron land and 8.85:1 over water, and it
 * does so for EVERY fill including any new one. The fill is reinforcement, not the signal.
 *
 * Fill and glyph ink both arrive as inline custom properties from
 * safi_category_style_attr() (inc/categories.php). Each swatch in that palette ships with
 * its ink already chosen as whichever of white / --safi-petrol measures higher against it,
 * every pairing at or above 3:1 — which is exactly why editors pick from a fixed swatch
 * list rather than a colour picker.
 *
 * Category is never colour-alone (1.4.1): every marker carries a per-category glyph, the
 * popup names the category in text, and the legend pairs each marker with its label.
 */

.safi-marker-wrap {
	background: none;
	border: 0;
}

/* Marker scale, raised 2026-08-06 from 30px to 42px. At 30 the category glyph was ~15px
   inside a ring, which is legible on a desktop lean-in but small on a phone and small
   relative to the now much larger canvas. 42px keeps the same three-layer recipe and the
   same measured contrast — only the scale changes — and it comfortably clears WCAG 2.5.8's
   24x24 target minimum for a control that is genuinely tap-first on mobile.

   Keep .safi-marker's box in sync with iconSize/iconAnchor in assets/js/map.js: Leaflet
   positions the icon from those numbers, so a CSS-only change would offset every pin from
   its actual coordinate. */
.safi-marker {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 42px;
	height: 42px;
	border-radius: 50%;
	border: 2.5px solid var(--safi-petrol);
	box-shadow: 0 3px 9px rgba(20, 40, 50, 0.32);
	background: var(--safi-cat, var(--safi-cat-default));
}

.safi-marker__glyph {
	display: flex;
	color: var(--safi-cat-ink, var(--safi-petrol));
}

.safi-marker__glyph svg {
	width: 21px;
	height: 21px;
}

/* The legend stays at reading scale — it sits inline with 0.97rem text, and a 42px disc
   next to a text label would dominate the row rather than identify it. */
.safi-marker--legend {
	width: 28px;
	height: 28px;
	border-width: 2px;
	box-shadow: none;
	flex-shrink: 0;
}

.safi-marker--legend .safi-marker__glyph svg {
	width: 14px;
	height: 14px;
}

.leaflet-marker-icon:focus-visible .safi-marker {
	outline: var(--safi-focus-ring);
	outline-offset: var(--safi-focus-offset);
}

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

.map-legend {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px 22px;
	margin-bottom: 40px;
}

.map-legend__title {
	width: 100%;
	margin: 0 0 4px;
	font-size: 0.82rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--safi-teal-hover);
	font-weight: 600;
}

.map-legend__item {
	display: inline-flex;
	align-items: center;
	gap: 9px;
	font-size: 0.97rem;
	color: var(--safi-text-muted-2);
}

/* ---------- Popup ---------- */

.safi-popup .leaflet-popup-content-wrapper {
	border-radius: var(--safi-radius-md);
	background: var(--safi-surface);
	box-shadow: var(--safi-shadow-card-lg);
	padding: 0;
}

.safi-popup .leaflet-popup-content {
	margin: 0;
	padding: 20px 22px;
	line-height: 1.5;
}

.safi-popup .leaflet-popup-content:focus {
	outline: none; /* programmatic focus target; the popup itself is the visible change */
}

.safi-popup .leaflet-popup-tip {
	background: var(--safi-surface);
}

/* Close button.
 *
 * Leaflet's own rule is `.leaflet-container a.leaflet-popup-close-button` — specificity
 * (0,2,1), which beat the (0,2,0) selector used here previously. The result was that
 * Leaflet's `font: 16px/24px Tahoma` and `top/right: 0` survived while only the padding
 * applied, leaving the glyph sitting high in an off-centre box with the hover circle
 * hanging below it. Matching (0,3,1) here takes the whole rule back, and the X is centred
 * by flex rather than by a fragile line-height.
 *
 * Glyph is 5.75:1 at rest and 9.58:1 on hover — comfortably past the 3:1 that 1.4.11 asks
 * of a control. 32x32 is the hit target; WCAG 2.5.8 AA asks 24x24.
 */
.leaflet-container .safi-popup a.leaflet-popup-close-button {
	top: 10px;
	right: 10px;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	padding: 0;
	margin: 0;
	border-radius: 50%;
	font: 600 20px/1 var(--safi-font-body);
	color: var(--safi-text-muted-3);
	background: transparent;
	box-shadow: none;
	transition: background 0.15s ease, color 0.15s ease;
}

.leaflet-container .safi-popup a.leaflet-popup-close-button:hover,
.leaflet-container .safi-popup a.leaflet-popup-close-button:focus,
.leaflet-container .safi-popup a.leaflet-popup-close-button:focus-visible {
	color: var(--safi-petrol);
	background: var(--safi-bg-alt);
}

@media (prefers-reduced-motion: reduce) {
	.leaflet-container .safi-popup a.leaflet-popup-close-button {
		transition: none;
	}
}

/* ---------- Link colours inside popups ----------
 * Leaflet ships `.leaflet-container a { color: #0078A8 }` at specificity (0,1,1), which
 * outranks both `.btn--primary` and `.map-point__cta` (0,1,0). That is why the Google CTA
 * rendered with a blue label on a blue button and only "appeared" on hover — the hover
 * rule carried `color: #fff !important`, so hover was the first state that won.
 *
 * These selectors are (0,3,1). The label is now white at rest (5.38:1) and stays white on
 * hover; hover changes the BACKGROUND to --safi-teal-hover (7.06:1) and lifts the shadow,
 * which is how every other button in the theme behaves.
 */
.leaflet-container .safi-popup a.btn--primary,
.leaflet-container .safi-popup a.btn--primary:hover,
.leaflet-container .safi-popup a.btn--primary:focus,
.leaflet-container .safi-popup a.btn--primary:focus-visible {
	color: #fff;
}

.leaflet-container .safi-popup a.btn--primary {
	background: var(--safi-teal);
	box-shadow: 0 4px 12px rgba(27, 114, 152, 0.28);
}

.leaflet-container .safi-popup a.btn--primary:hover,
.leaflet-container .safi-popup a.btn--primary:focus-visible {
	background: var(--safi-teal-hover);
	box-shadow: 0 6px 16px rgba(21, 95, 127, 0.34);
}

/* Same specificity lesson as .btn--primary above: without this, Leaflet repaints the
   outline button's label with its own #0078A8 and the control reads as a stray link. */
.leaflet-container .safi-popup a.btn--outline {
	color: var(--safi-teal-hover);
	background: transparent;
}

.leaflet-container .safi-popup a.btn--outline:hover,
.leaflet-container .safi-popup a.btn--outline:focus,
.leaflet-container .safi-popup a.btn--outline:focus-visible {
	color: #fff;
	background: var(--safi-teal);
}

/* ---------- Point content (shared by popup + list) ---------- */

/* Matches .business-card__top: category first, status pill always on the row below.
   See the note there — this is the same content in a narrower box, so it mattered more. */
.map-point__top {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 10px;
	margin-bottom: 12px;
}

/* Keep the category/status row clear of the popup's close button. */
.map-point--popup .map-point__top {
	padding-right: 34px;
}

.map-point__name {
	font-size: 1.16rem;
	line-height: 1.3;
	color: var(--safi-petrol);
	margin: 0 0 12px;
}

.map-point__details {
	margin: 0 0 16px;
}

/* .business-card__detail-empty (the em dash for a field with no value) moved to
   components.css when the directory cards adopted the same treatment — the directory
   never loads map.css, and this file chains off components.css so nothing is lost here. */

/* .map-point__advance was removed with the «Εκ των προτέρων επικοινωνία» line
   (template-parts/map-point.php). The directory card dropped the same line shortly after,
   so the styles it used are gone from components.css too. The BUSINESS PROFILE page still
   states it, in prose — see single-business.php's "Πριν την επίσκεψη" callout, which uses
   its own classes. */

.map-point__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 12px 18px;
}

.map-point__cta {
	padding: 11px 18px;
	font-size: 0.96rem;
}

/* ---------- Accessible point list ----------
 * First-class content, not a fallback (docs/map-plan.md §6). Styled as real cards so it
 * doesn't read as a degraded afterthought. */

.map-points {
	margin-top: 8px;
}

.map-points__title {
	font-size: clamp(1.4rem, 2.4vw, 1.8rem);
	color: var(--safi-petrol);
	margin: 0 0 6px;
}

.map-points__intro {
	margin: 0 0 24px;
	color: var(--safi-text-muted-3);
	font-size: 1rem;
}

/* Same grid as .business-grid on /epixeiriseis/ — auto-fill at minmax(320px, 1fr), 22px
   gap — so the two pages read as one system and the list stops rendering as a column of
   full-width slabs. auto-fill rather than auto-fit is deliberate and matches the
   directory: with auto-fit a single remaining card stretches to the full container width,
   which is exactly the slab we're getting rid of. */
.map-points__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
	gap: 22px;
}

/* 28px, up from 24px. At 24 the leading pin/phone/check glyphs in the detail rows read as
   touching the card edge — same optical effect as the hub peeks, because an icon's visual
   edge is its bounding box rather than the text baseline the padding was set against. */
.map-points__item {
	display: flex;
	flex-direction: column;
	padding: 28px;
}

/* Slightly looser rows inside the list card specifically: the popup is a narrow bubble
   where tight rows are correct, but the list card is a 320px+ grid cell and the same
   spacing reads as cramped there. Scoped to the list so the popup is untouched. */
.map-points__item .business-card__detail-row {
	gap: 12px;
}

.map-points__item .map-point__details {
	gap: 13px;
	margin-bottom: 14px;
}

.map-points__item .map-point {
	display: flex;
	flex-direction: column;
	flex: 1;
}

/* ---------- Uniform list cards ----------
   The three detail rows are now always rendered (template-parts/map-point.php), so every
   card has the same skeleton whether or not its fields are filled in. These two rules
   finish the job:

   - the grid already stretches every card in a row to the tallest, and margin-top:auto
     pins the actions to the bottom, so the buttons land on one line across the row;
   - the name gets a two-line budget, so a one-line title and a two-line title do not
     shift everything below them out of step with the card beside it.

   Together that means a row of cards reads as a set, which is the whole complaint. */
.map-points__item .map-point__name {
	min-height: 2.6em;
}

/* Push the actions to the bottom so cards of differing text length still line up. */
.map-points__item .map-point__actions {
	margin-top: auto;
	padding-top: 4px;
}

/* At card width the full CTA label needs to be allowed to wrap rather than force the
   track wider than its 320px minimum. */
.map-points__item .map-point__cta {
	text-align: left;
}

/* map.js turns each list heading into a button that flies the map to that marker. It's a
   convenience for pointer users; the list is fully usable without it. */
.map-points__locate {
	appearance: none;
	background: none;
	border: 0 !important;
	padding: 0;
	font: inherit;
	color: inherit;
	text-align: left;
	cursor: pointer;
	text-decoration: underline;
	text-decoration-color: var(--safi-teal-tint-strong);
	text-underline-offset: 3px;
}

.map-points__locate:hover,
.map-points__locate:focus-visible {
	color: var(--safi-teal-hover) !important;
	background: none !important;
	text-decoration-color: currentColor;
}

.map-points__empty {
	margin: 24px 0 0;
	color: var(--safi-text-muted-3);
}

/* ---------- Empty state (no coordinates entered yet) ---------- */

.map-empty {
	text-align: center;
	padding: 56px 28px;
	border-radius: var(--safi-radius-lg);
	border: 1px dashed var(--safi-border-strong);
	background: var(--safi-surface);
}

.map-empty__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 56px;
	height: 56px;
	border-radius: 50%;
	background: var(--safi-teal);
	color: #fff;
	margin-bottom: 16px;
}

.map-empty__title {
	font-size: 1.3rem;
	color: var(--safi-petrol);
	margin: 0 0 10px;
}

.map-empty__text {
	margin: 0 auto;
	max-width: 52ch;
	color: var(--safi-text-muted-3);
	line-height: 1.65;
}

/* ---------- Directory link ---------- */

.map-directory-link {
	margin: 36px 0 0;
}

.map-directory-link a {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	font-weight: 600;
	color: var(--safi-teal-hover);
	text-decoration: none;
}

.map-directory-link a:hover {
	color: var(--safi-petrol);
}

/* ---------- Skip link over the map ----------
 * Reuses .skip-link's appearance from base.css but not its positioning: that variant is
 * pinned with `top: -60px` against the nearest positioned ancestor, which for a link
 * sitting inside .section__container would drop it at the top of the document next to the
 * main skip link. This one parks off-screen and returns to normal flow above the filter
 * chips when focused, so it lands where a keyboard user expects it — immediately before
 * the map it lets them skip. */

.skip-link--map {
	position: absolute !important;
	left: -9999px;
	top: auto;
}

.skip-link--map:focus,
.skip-link--map:focus-visible {
	position: static !important;
	left: auto;
	top: auto;
	display: inline-flex;
	margin-bottom: 16px;
}

/* ---------- Mobile: popup as a bottom sheet ----------
 * Leaflet's tethered bubbles are unusable at this width — a 260px card anchored to a pin
 * near the edge ends up half off-screen with the map panning under it. Below 640px the
 * popup is pinned to the bottom of the viewport instead.
 *
 * This overrides Leaflet's inline `transform` and absolute positioning, so it is the most
 * version-sensitive rule in the file: re-check it when upgrading Leaflet
 * (assets/vendor/leaflet/VENDOR.md). */

@media (max-width: 640px) {
	.safi-map .leaflet-popup.safi-popup {
		position: fixed !important;
		left: 0 !important;
		right: 0 !important;
		bottom: 0 !important;
		top: auto !important;
		transform: none !important;
		margin: 0;
		width: 100%;
		max-width: 100%;
		z-index: 1200;
	}

	.safi-popup .leaflet-popup-content-wrapper {
		border-radius: var(--safi-radius-lg) var(--safi-radius-lg) 0 0;
		box-shadow: 0 -10px 34px rgba(20, 40, 50, 0.28);
	}

	.safi-popup .leaflet-popup-content {
		width: auto !important;
		max-height: 62vh;
		overflow-y: auto;
		padding: 22px 20px 26px;
	}

	.safi-popup .leaflet-popup-tip-container {
		display: none;
	}

	.map-point__actions {
		width: 100%;
	}

	.map-point__cta {
		width: 100%;
		justify-content: center;
	}
}
