/**
 * Epic Section Navigator
 *
 * Palette: #DC8376 active, #502F2A ink, hairlines at 10% brown.
 * Desktop: collapsed 46px, expanded 246px. Mobile (<1024px): button + bottom sheet.
 * #c2a360 is intentionally not used anywhere in this component — spec §4.5.
 * Desktop tokens/structure follow the agreed reference mockup.
 */

:root {
	/* Distance from the top of the viewport to the foot of the site header.
	   The site has no sticky header today, so the strip sits at 0; give this
	   a value if one is ever added, rather than touching the component. */
	--esn-header-offset: 0px;

	/* Pinned rather than left to emerge from padding and line-height, because
	   the scroll offset below is derived from it and must not drift with font
	   rendering. Also clears the 48px touch-target minimum. */
	--esn-strip-height: 56px;

	/* Breathing room left above a heading that has just been scrolled to. */
	--esn-scroll-gap: 24px;

	--esn-active: #DC8376;
	--esn-ink: #502F2A;
	/* Read state on the sheet: neutral brown, never green — the status card's
	   FLIGHTS OPERATING badge owns green on this page and means something
	   else entirely (spec §4.6). */
	--esn-read: rgba(80, 47, 42, 0.45);
	--esn-node-rail: rgba(80, 47, 42, 0.18);
	--esn-ink-quiet: rgba(80, 47, 42, 0.58);
	--esn-rail: rgba(80, 47, 42, 0.14);
	--esn-rail-read: rgba(80, 47, 42, 0.32);
	--esn-hairline: rgba(80, 47, 42, 0.1);
	--esn-surface: rgba(255, 255, 255, 0.94);
	--esn-collapsed-width: 46px;
	--esn-expanded-width: 246px;
	--esn-transition: 260ms;

	/* Breathing room kept clear above and below the desktop panel. */
	--esn-viewport-gap: 96px;

	/* Measured against what already sits on these pages: Leaflet's map
	   controls are 1000 and the Flatsome header is 1001, so the component has
	   to clear both. It stays under Flatsome's magnific-popup lightbox (1042)
	   and the .z-top family used by live search (9995) — if either of those is
	   open it should win. The sheet sits one above the strip that opens it. */
	--esn-z-panel: 1002;
	--esn-z-sheet: 1003;
}

/* ---------- Desktop navigator (>=1024px) ---------- */

.esn {
	position: fixed;
	top: 50%;
	right: 26px;
	transform: translateY(-50%);
	z-index: var(--esn-z-panel);
	width: var(--esn-collapsed-width);
	max-height: calc(100vh - var(--esn-viewport-gap));
	background: var(--esn-surface);
	backdrop-filter: blur(14px);
	border: 1px solid var(--esn-hairline);
	border-radius: 16px;
	box-shadow: 0 1px 2px rgba(80, 47, 42, 0.05), 0 14px 34px -10px rgba(80, 47, 42, 0.22);
	overflow: hidden;
	transition: width var(--esn-transition) cubic-bezier(0.22, 0.7, 0.28, 1);
	font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
}

.esn.is-open {
	width: var(--esn-expanded-width);
}

@media (prefers-reduced-motion: reduce) {
	.esn,
	.esn__tick,
	.esn__list a,
	.esn__list a::before {
		transition: none;
	}
}

@media (max-width: 1023.98px) {
	.esn {
		display: none;
	}
}

/* Transparent overlay covering the collapsed rail/count — the real
   interactive element per spec §4.5's "toggle is a real <button>". Hidden
   once open so it never blocks clicks on the panel's own links. */
.esn__toggle {
	all: unset;
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	cursor: pointer;
}

.esn.is-open .esn__toggle {
	display: none;
}

.esn__toggle:focus-visible {
	outline: 2px solid var(--esn-active);
	outline-offset: 2px;
	border-radius: 16px;
}

.esn__rail {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 6px;
	width: var(--esn-collapsed-width);
	padding: 14px 0 6px;
}

.esn.is-open .esn__rail {
	display: none;
}

.esn__tick {
	display: block;
	width: 14px;
	height: 2px;
	border-radius: 2px;
	background: var(--esn-rail);
}

.esn__tick.is-read {
	background: var(--esn-rail-read);
}

.esn__tick.is-active {
	width: 20px;
	height: 2.5px;
	background: var(--esn-active);
}

.esn__count {
	display: block;
	width: var(--esn-collapsed-width);
	text-align: center;
	font-size: 10.5px;
	font-weight: 600;
	letter-spacing: 0.06em;
	color: var(--esn-ink-quiet);
	padding: 8px 0 12px;
}

.esn.is-open .esn__count {
	display: none;
}

.esn__panel {
	display: none;
}

.esn.is-open .esn__panel {
	display: block;
}

/* Locked to the expanded width regardless of the outer clip's current
   width, so text doesn't reflow/wrap mid-transition — only revealed as
   the outer .esn widens. */
.esn__inner {
	/* Less the panel's 1px border either side, so it lands exactly on the
	   content box instead of overflowing into the clip. */
	width: calc(var(--esn-expanded-width) - 2px);
	padding: 14px 0;
	/* Column so the list can take whatever height is left over and scroll
	   inside it — the eyebrow and the CTA stay put. */
	display: flex;
	flex-direction: column;
	max-height: calc(100vh - var(--esn-viewport-gap));
}

.esn__eyebrow {
	margin: 0;
	padding: 2px 18px 12px;
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	font-size: 10.5px;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.14em;
	color: var(--esn-ink-quiet);
}

.esn__progress {
	font-style: normal;
	color: var(--esn-active);
	letter-spacing: 0.04em;
}

/* The scroll container is the list itself, not the panel: .esn__inner is
   pinned to the expanded width so a scrollbar taken out of it would be
   clipped by the outer overflow. Here the 6px comes out of the list's own
   padding instead. min-height:0 lets it shrink below its content inside the
   flex column. */
.esn__list {
	list-style: none;
	margin: 0;
	padding: 0 10px;
	min-height: 0;
	overflow-x: hidden;
	overflow-y: auto;
	overscroll-behavior: contain;
	scrollbar-width: thin;
	scrollbar-color: var(--esn-node-rail) transparent;
}

.esn__list::-webkit-scrollbar {
	width: 6px;
}

.esn__list::-webkit-scrollbar-track {
	background: transparent;
}

.esn__list::-webkit-scrollbar-thumb {
	background: var(--esn-node-rail);
	border-radius: 3px;
}

.esn__list:hover::-webkit-scrollbar-thumb {
	background: var(--esn-rail-read);
}

.esn__link {
	position: relative;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	padding: 7px 10px 7px 18px;
	border-radius: 8px;
	font-size: 13.5px;
	font-weight: 500;
	line-height: 1.35;
	color: var(--esn-ink-quiet);
	text-decoration: none;
	transition: color 160ms ease, background 160ms ease;
}

.esn__link::before {
	content: "";
	position: absolute;
	left: 6px;
	top: 9px;
	bottom: 9px;
	width: 2px;
	border-radius: 2px;
	background: var(--esn-rail);
	transition: background 180ms ease;
}

.esn__link:hover,
.esn__link:focus-visible {
	color: var(--esn-ink);
	background: rgba(80, 47, 42, 0.045);
}

.esn__link:focus-visible {
	outline: 2px solid var(--esn-active);
	outline-offset: 2px;
}

.esn__item.is-read .esn__link::before {
	background: var(--esn-rail-read);
}

.esn__item.is-active .esn__link {
	color: var(--esn-ink);
	font-weight: 650;
}

.esn__item.is-active .esn__link::before {
	background: var(--esn-active);
	width: 2.5px;
}

/* Filled, not a text link. As brown text on a white panel it was the same
   colour as the six section links above it and a point smaller, so it read as
   a seventh, dimmer list item rather than as the one action in the panel. */
.esn__cta {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	flex: 0 0 auto;
	margin: 14px 10px 2px;
	padding: 11px 14px;
	border-radius: 8px;
	background: var(--esn-active);
	font-size: 12.5px;
	font-weight: 600;
	line-height: 1.3;
	color: #fff;
	text-decoration: none;
}

.esn__cta::after {
	content: "\2192";
	flex: 0 0 auto;
}

/* Darkened rather than given a second brand colour to maintain. */
.esn__cta:hover {
	filter: brightness(0.93);
}

.esn__cta:focus-visible {
	outline: 2px solid var(--esn-ink);
	outline-offset: 2px;
}

/* ---------- Mobile navigator (<1024px) ---------- */

/* Sticky strip beneath the site header. Hidden on load and revealed once the
   reader has passed the first section: on the status pages the one thing that
   must be above the fold is whether balloons flew this morning, and two
   stacked bars would take roughly 110px of a phone screen (spec §4.6).
   The reveal is JS-driven, so with JavaScript blocked the strip stays down. */
.esn-strip {
	display: none;
}

@media (max-width: 1023.98px) {
	.esn-strip {
		display: block;
		position: fixed;
		top: var(--esn-header-offset, 0px);
		left: 0;
		right: 0;
		z-index: var(--esn-z-panel);
		background: var(--esn-ink);
		transform: translateY(-100%);
		visibility: hidden;
		transition: transform var(--esn-transition) ease, visibility 0s linear var(--esn-transition);
	}

	.esn-strip.is-visible {
		transform: translateY(0);
		visibility: visible;
		transition: transform var(--esn-transition) ease, visibility 0s;
	}

	.esn-strip__toggle {
		all: unset;
		box-sizing: border-box;
		display: flex;
		align-items: center;
		gap: 12px;
		width: 100%;
		height: var(--esn-strip-height);
		padding: 0 16px;
		color: #fff;
		font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
		cursor: pointer;
	}

	.esn-strip__toggle:focus-visible {
		outline: 2px solid var(--esn-active);
		outline-offset: -2px;
	}

	/* Hamburger: three rules drawn from one box. */
	.esn-strip__icon {
		position: relative;
		flex: 0 0 auto;
		width: 16px;
		height: 2px;
		border-radius: 2px;
		background: #fff;
	}

	.esn-strip__icon::before,
	.esn-strip__icon::after {
		content: "";
		position: absolute;
		left: 0;
		width: 16px;
		height: 2px;
		border-radius: 2px;
		background: #fff;
	}

	.esn-strip__icon::before {
		top: -5px;
	}

	.esn-strip__icon::after {
		top: 5px;
	}

	.esn-strip__label {
		flex: 1 1 auto;
		font-size: 13px;
		font-weight: 600;
		letter-spacing: 0.06em;
		text-transform: uppercase;
	}

	.esn-strip__count {
		flex: 0 0 auto;
		font-size: 12px;
		font-weight: 600;
		letter-spacing: 0.04em;
		color: var(--esn-active);
	}

	/* Chevron: a rotated corner, pointing down to mean "opens below". */
	.esn-strip__chevron {
		flex: 0 0 auto;
		width: 8px;
		height: 8px;
		border-right: 2px solid rgba(255, 255, 255, 0.75);
		border-bottom: 2px solid rgba(255, 255, 255, 0.75);
		transform: translateY(-2px) rotate(45deg);
	}
}

@media (prefers-reduced-motion: reduce) {
	.esn-strip {
		transition: none;
	}
}

.esn-mobile-sheet {
	position: fixed;
	inset: 0;
	z-index: var(--esn-z-sheet);
}

.esn-mobile-sheet[hidden] {
	display: none;
}

.esn-mobile-sheet__backdrop {
	position: absolute;
	inset: 0;
	background: rgba(80, 47, 42, 0.4);
}

.esn-mobile-sheet__panel {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	max-height: 75vh;
	overflow-y: auto;
	background: #fff;
	border-radius: 16px 16px 0 0;
	padding: 20px;
}

.esn-mobile-sheet__header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin-bottom: 12px;
}

.esn-mobile-sheet__title {
	margin: 0;
	font-size: 13px;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--esn-ink);
}

.esn-mobile-sheet__close {
	all: unset;
	box-sizing: border-box;
	width: 32px;
	height: 32px;
	display: flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
}

.esn-mobile-sheet__close:focus-visible {
	outline: 2px solid var(--esn-active);
	outline-offset: 2px;
}

.esn-mobile-sheet__close::before {
	content: "\2715";
	color: var(--esn-ink);
}

.esn-mobile-sheet__list {
	list-style: none;
	margin: 0;
	padding: 0;
}

/* Vertical rail down the left of the list, drawn as a per-item segment so it
   survives labels that wrap to two lines. The first and last segments stop at
   their own node rather than running past the ends of the list. */
.esn-mobile-sheet__item {
	position: relative;
}

.esn-mobile-sheet__item::before {
	content: "";
	position: absolute;
	left: 10px;
	top: 0;
	bottom: 0;
	width: 2px;
	background: var(--esn-node-rail);
}

.esn-mobile-sheet__item:first-child::before {
	top: 50%;
}

.esn-mobile-sheet__item:last-child::before {
	bottom: 50%;
}

.esn-mobile-sheet__link {
	position: relative;
	display: flex;
	align-items: center;
	gap: 14px;
	padding: 10px 0;
	font-size: 15px;
	color: var(--esn-ink);
	text-decoration: none;
}

.esn-mobile-sheet__link:focus-visible {
	outline: 2px solid var(--esn-active);
	outline-offset: 2px;
}

.esn-mobile-sheet__node {
	position: relative;
	z-index: 1;
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 22px;
	height: 22px;
	border: 2px solid var(--esn-node-rail);
	border-radius: 50%;
	background: #fff;
	font-size: 11px;
	line-height: 1;
}

.esn-mobile-sheet__item.is-read .esn-mobile-sheet__node {
	border-color: var(--esn-read);
	color: var(--esn-read);
}

.esn-mobile-sheet__item.is-read .esn-mobile-sheet__node::before {
	content: "\2713";
}

.esn-mobile-sheet__item.is-active .esn-mobile-sheet__node {
	border-color: var(--esn-active);
	background: var(--esn-active);
}

.esn-mobile-sheet__item.is-read .esn-mobile-sheet__text {
	color: var(--esn-read);
}

.esn-mobile-sheet__item.is-active .esn-mobile-sheet__text {
	color: var(--esn-active);
	font-weight: 600;
}

.esn-mobile-sheet__cta {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	margin-top: 20px;
	padding: 14px 16px;
	border-radius: 10px;
	background: var(--esn-active);
	font-size: 15px;
	font-weight: 600;
	color: #fff;
	text-decoration: none;
}

.esn-mobile-sheet__cta::after {
	content: "\2192";
	flex: 0 0 auto;
}

.esn-mobile-sheet__cta:focus-visible {
	outline: 2px solid var(--esn-ink);
	outline-offset: 2px;
}

/* ---------- Scroll offsets ---------- */

/* Headings the navigator links to should not land flush against the top edge,
   or underneath whatever is pinned there. Everything is derived from the
   variables above, so moving the strip or a future sticky header moves this
   with it. Only loaded on pages where the component renders. */
h2[id] {
	scroll-margin-top: calc(var(--esn-header-offset, 0px) + var(--esn-scroll-gap));
}

@media (max-width: 1023.98px) {
	h2[id] {
		scroll-margin-top: calc(var(--esn-header-offset, 0px) + var(--esn-strip-height) + var(--esn-scroll-gap));
	}

	/* The first heading is the exception, and deterministically so: the strip
	   is shown precisely when that heading has left the top of the viewport,
	   so any scroll that parks it at the top has already hidden the strip.
	   Reserving space for a strip that will not be there leaves a hole. */
	h2[id].esn-first-section {
		scroll-margin-top: calc(var(--esn-header-offset, 0px) + var(--esn-scroll-gap));
	}
}

/* ---------- Shared ---------- */

.screen-reader-text {
	border: 0;
	clip: rect(1px, 1px, 1px, 1px);
	clip-path: inset(50%);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute;
	width: 1px;
	word-wrap: normal !important;
}
