/* /vendor/leaflet/leaflet.css */
/* required styles */

.leaflet-pane,
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-tile-container,
.leaflet-pane > svg,
.leaflet-pane > canvas,
.leaflet-zoom-box,
.leaflet-image-layer,
.leaflet-layer {
	position: absolute;
	left: 0;
	top: 0;
	}
.leaflet-container {
	overflow: hidden;
	}
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow {
	-webkit-user-select: none;
	   -moz-user-select: none;
	        user-select: none;
	  -webkit-user-drag: none;
	}
/* Prevents IE11 from highlighting tiles in blue */
.leaflet-tile::selection {
	background: transparent;
}
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
.leaflet-safari .leaflet-tile {
	image-rendering: -webkit-optimize-contrast;
	}
/* hack that prevents hw layers "stretching" when loading new tiles */
.leaflet-safari .leaflet-tile-container {
	width: 1600px;
	height: 1600px;
	-webkit-transform-origin: 0 0;
	}
.leaflet-marker-icon,
.leaflet-marker-shadow {
	display: block;
	}
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
.leaflet-container .leaflet-overlay-pane svg {
	max-width: none !important;
	max-height: none !important;
	}
.leaflet-container .leaflet-marker-pane img,
.leaflet-container .leaflet-shadow-pane img,
.leaflet-container .leaflet-tile-pane img,
.leaflet-container img.leaflet-image-layer,
.leaflet-container .leaflet-tile {
	max-width: none !important;
	max-height: none !important;
	width: auto;
	padding: 0;
	}

.leaflet-container img.leaflet-tile {
	/* See: https://bugs.chromium.org/p/chromium/issues/detail?id=600120 */
	mix-blend-mode: plus-lighter;
}

.leaflet-container.leaflet-touch-zoom {
	-ms-touch-action: pan-x pan-y;
	touch-action: pan-x pan-y;
	}
.leaflet-container.leaflet-touch-drag {
	-ms-touch-action: pinch-zoom;
	/* Fallback for FF which doesn't support pinch-zoom */
	touch-action: none;
	touch-action: pinch-zoom;
}
.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
	-ms-touch-action: none;
	touch-action: none;
}
.leaflet-container {
	-webkit-tap-highlight-color: transparent;
}
.leaflet-container a {
	-webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);
}
.leaflet-tile {
	filter: inherit;
	visibility: hidden;
	}
.leaflet-tile-loaded {
	visibility: inherit;
	}
.leaflet-zoom-box {
	width: 0;
	height: 0;
	-moz-box-sizing: border-box;
	     box-sizing: border-box;
	z-index: 800;
	}
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
.leaflet-overlay-pane svg {
	-moz-user-select: none;
	}

.leaflet-pane         { z-index: 400; }

.leaflet-tile-pane    { z-index: 200; }
.leaflet-overlay-pane { z-index: 400; }
.leaflet-shadow-pane  { z-index: 500; }
.leaflet-marker-pane  { z-index: 600; }
.leaflet-tooltip-pane   { z-index: 650; }
.leaflet-popup-pane   { z-index: 700; }

.leaflet-map-pane canvas { z-index: 100; }
.leaflet-map-pane svg    { z-index: 200; }

.leaflet-vml-shape {
	width: 1px;
	height: 1px;
	}
.lvml {
	behavior: url(#default#VML);
	display: inline-block;
	position: absolute;
	}


/* control positioning */

.leaflet-control {
	position: relative;
	z-index: 800;
	pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
	pointer-events: auto;
	}
.leaflet-top,
.leaflet-bottom {
	position: absolute;
	z-index: 1000;
	pointer-events: none;
	}
.leaflet-top {
	top: 0;
	}
.leaflet-right {
	right: 0;
	}
.leaflet-bottom {
	bottom: 0;
	}
.leaflet-left {
	left: 0;
	}
.leaflet-control {
	float: left;
	clear: both;
	}
.leaflet-right .leaflet-control {
	float: right;
	}
.leaflet-top .leaflet-control {
	margin-top: 10px;
	}
.leaflet-bottom .leaflet-control {
	margin-bottom: 10px;
	}
.leaflet-left .leaflet-control {
	margin-left: 10px;
	}
.leaflet-right .leaflet-control {
	margin-right: 10px;
	}


/* zoom and fade animations */

.leaflet-fade-anim .leaflet-popup {
	opacity: 0;
	-webkit-transition: opacity 0.2s linear;
	   -moz-transition: opacity 0.2s linear;
	        transition: opacity 0.2s linear;
	}
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
	opacity: 1;
	}
.leaflet-zoom-animated {
	-webkit-transform-origin: 0 0;
	    -ms-transform-origin: 0 0;
	        transform-origin: 0 0;
	}
svg.leaflet-zoom-animated {
	will-change: transform;
}

.leaflet-zoom-anim .leaflet-zoom-animated {
	-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
	   -moz-transition:    -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
	        transition:         transform 0.25s cubic-bezier(0,0,0.25,1);
	}
.leaflet-zoom-anim .leaflet-tile,
.leaflet-pan-anim .leaflet-tile {
	-webkit-transition: none;
	   -moz-transition: none;
	        transition: none;
	}

.leaflet-zoom-anim .leaflet-zoom-hide {
	visibility: hidden;
	}


/* cursors */

.leaflet-interactive {
	cursor: pointer;
	}
.leaflet-grab {
	cursor: -webkit-grab;
	cursor:    -moz-grab;
	cursor:         grab;
	}
.leaflet-crosshair,
.leaflet-crosshair .leaflet-interactive {
	cursor: crosshair;
	}
.leaflet-popup-pane,
.leaflet-control {
	cursor: auto;
	}
.leaflet-dragging .leaflet-grab,
.leaflet-dragging .leaflet-grab .leaflet-interactive,
.leaflet-dragging .leaflet-marker-draggable {
	cursor: move;
	cursor: -webkit-grabbing;
	cursor:    -moz-grabbing;
	cursor:         grabbing;
	}

/* marker & overlays interactivity */
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-image-layer,
.leaflet-pane > svg path,
.leaflet-tile-container {
	pointer-events: none;
	}

.leaflet-marker-icon.leaflet-interactive,
.leaflet-image-layer.leaflet-interactive,
.leaflet-pane > svg path.leaflet-interactive,
svg.leaflet-image-layer.leaflet-interactive path {
	pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
	pointer-events: auto;
	}

/* visual tweaks */

.leaflet-container {
	background: #ddd;
	outline-offset: 1px;
	}
.leaflet-container a {
	color: #0078A8;
	}
.leaflet-zoom-box {
	border: 2px dotted #38f;
	background: rgba(255,255,255,0.5);
	}


/* general typography */
.leaflet-container {
	font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
	font-size: 12px;
	font-size: 0.75rem;
	line-height: 1.5;
	}


/* general toolbar styles */

.leaflet-bar {
	box-shadow: 0 1px 5px rgba(0,0,0,0.65);
	border-radius: 4px;
	}
.leaflet-bar a {
	background-color: #fff;
	border-bottom: 1px solid #ccc;
	width: 26px;
	height: 26px;
	line-height: 26px;
	display: block;
	text-align: center;
	text-decoration: none;
	color: black;
	}
.leaflet-bar a,
.leaflet-control-layers-toggle {
	background-position: 50% 50%;
	background-repeat: no-repeat;
	display: block;
	}
.leaflet-bar a:hover,
.leaflet-bar a:focus {
	background-color: #f4f4f4;
	}
.leaflet-bar a:first-child {
	border-top-left-radius: 4px;
	border-top-right-radius: 4px;
	}
.leaflet-bar a:last-child {
	border-bottom-left-radius: 4px;
	border-bottom-right-radius: 4px;
	border-bottom: none;
	}
.leaflet-bar a.leaflet-disabled {
	cursor: default;
	background-color: #f4f4f4;
	color: #bbb;
	}

.leaflet-touch .leaflet-bar a {
	width: 30px;
	height: 30px;
	line-height: 30px;
	}
.leaflet-touch .leaflet-bar a:first-child {
	border-top-left-radius: 2px;
	border-top-right-radius: 2px;
	}
.leaflet-touch .leaflet-bar a:last-child {
	border-bottom-left-radius: 2px;
	border-bottom-right-radius: 2px;
	}

/* zoom control */

.leaflet-control-zoom-in,
.leaflet-control-zoom-out {
	font: bold 18px 'Lucida Console', Monaco, monospace;
	text-indent: 1px;
	}

.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out  {
	font-size: 22px;
	}


/* layers control */

.leaflet-control-layers {
	box-shadow: 0 1px 5px rgba(0,0,0,0.4);
	background: #fff;
	border-radius: 5px;
	}
.leaflet-control-layers-toggle {
	background-image: url(/vendor/leaflet/images/layers.png);
	width: 36px;
	height: 36px;
	}
.leaflet-retina .leaflet-control-layers-toggle {
	background-image: url(/vendor/leaflet/images/layers-2x.png);
	background-size: 26px 26px;
	}
.leaflet-touch .leaflet-control-layers-toggle {
	width: 44px;
	height: 44px;
	}
.leaflet-control-layers .leaflet-control-layers-list,
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
	display: none;
	}
.leaflet-control-layers-expanded .leaflet-control-layers-list {
	display: block;
	position: relative;
	}
.leaflet-control-layers-expanded {
	padding: 6px 10px 6px 6px;
	color: #333;
	background: #fff;
	}
.leaflet-control-layers-scrollbar {
	overflow-y: scroll;
	overflow-x: hidden;
	padding-right: 5px;
	}
.leaflet-control-layers-selector {
	margin-top: 2px;
	position: relative;
	top: 1px;
	}
.leaflet-control-layers label {
	display: block;
	font-size: 13px;
	font-size: 1.08333em;
	}
.leaflet-control-layers-separator {
	height: 0;
	border-top: 1px solid #ddd;
	margin: 5px -10px 5px -6px;
	}

/* Default icon URLs */
.leaflet-default-icon-path { /* used only in path-guessing heuristic, see L.Icon.Default */
	background-image: url(/vendor/leaflet/images/marker-icon.png);
	}


/* attribution and scale controls */

.leaflet-container .leaflet-control-attribution {
	background: #fff;
	background: rgba(255, 255, 255, 0.8);
	margin: 0;
	}
.leaflet-control-attribution,
.leaflet-control-scale-line {
	padding: 0 5px;
	color: #333;
	line-height: 1.4;
	}
.leaflet-control-attribution a {
	text-decoration: none;
	}
.leaflet-control-attribution a:hover,
.leaflet-control-attribution a:focus {
	text-decoration: underline;
	}
.leaflet-attribution-flag {
	display: inline !important;
	vertical-align: baseline !important;
	width: 1em;
	height: 0.6669em;
	}
.leaflet-left .leaflet-control-scale {
	margin-left: 5px;
	}
.leaflet-bottom .leaflet-control-scale {
	margin-bottom: 5px;
	}
.leaflet-control-scale-line {
	border: 2px solid #777;
	border-top: none;
	line-height: 1.1;
	padding: 2px 5px 1px;
	white-space: nowrap;
	-moz-box-sizing: border-box;
	     box-sizing: border-box;
	background: rgba(255, 255, 255, 0.8);
	text-shadow: 1px 1px #fff;
	}
.leaflet-control-scale-line:not(:first-child) {
	border-top: 2px solid #777;
	border-bottom: none;
	margin-top: -2px;
	}
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
	border-bottom: 2px solid #777;
	}

.leaflet-touch .leaflet-control-attribution,
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
	box-shadow: none;
	}
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
	border: 2px solid rgba(0,0,0,0.2);
	background-clip: padding-box;
	}


/* popup */

.leaflet-popup {
	position: absolute;
	text-align: center;
	margin-bottom: 20px;
	}
.leaflet-popup-content-wrapper {
	padding: 1px;
	text-align: left;
	border-radius: 12px;
	}
.leaflet-popup-content {
	margin: 13px 24px 13px 20px;
	line-height: 1.3;
	font-size: 13px;
	font-size: 1.08333em;
	min-height: 1px;
	}
.leaflet-popup-content p {
	margin: 17px 0;
	margin: 1.3em 0;
	}
.leaflet-popup-tip-container {
	width: 40px;
	height: 20px;
	position: absolute;
	left: 50%;
	margin-top: -1px;
	margin-left: -20px;
	overflow: hidden;
	pointer-events: none;
	}
.leaflet-popup-tip {
	width: 17px;
	height: 17px;
	padding: 1px;

	margin: -10px auto 0;
	pointer-events: auto;

	-webkit-transform: rotate(45deg);
	   -moz-transform: rotate(45deg);
	    -ms-transform: rotate(45deg);
	        transform: rotate(45deg);
	}
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
	background: white;
	color: #333;
	box-shadow: 0 3px 14px rgba(0,0,0,0.4);
	}
.leaflet-container a.leaflet-popup-close-button {
	position: absolute;
	top: 0;
	right: 0;
	border: none;
	text-align: center;
	width: 24px;
	height: 24px;
	font: 16px/24px Tahoma, Verdana, sans-serif;
	color: #757575;
	text-decoration: none;
	background: transparent;
	}
.leaflet-container a.leaflet-popup-close-button:hover,
.leaflet-container a.leaflet-popup-close-button:focus {
	color: #585858;
	}
.leaflet-popup-scrolled {
	overflow: auto;
	}

.leaflet-oldie .leaflet-popup-content-wrapper {
	-ms-zoom: 1;
	}
.leaflet-oldie .leaflet-popup-tip {
	width: 24px;
	margin: 0 auto;

	-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
	filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
	}

.leaflet-oldie .leaflet-control-zoom,
.leaflet-oldie .leaflet-control-layers,
.leaflet-oldie .leaflet-popup-content-wrapper,
.leaflet-oldie .leaflet-popup-tip {
	border: 1px solid #999;
	}


/* div icon */

.leaflet-div-icon {
	background: #fff;
	border: 1px solid #666;
	}


/* Tooltip */
/* Base styles for the element that has a tooltip */
.leaflet-tooltip {
	position: absolute;
	padding: 6px;
	background-color: #fff;
	border: 1px solid #fff;
	border-radius: 3px;
	color: #222;
	white-space: nowrap;
	-webkit-user-select: none;
	-moz-user-select: none;
	-ms-user-select: none;
	user-select: none;
	pointer-events: none;
	box-shadow: 0 1px 3px rgba(0,0,0,0.4);
	}
.leaflet-tooltip.leaflet-interactive {
	cursor: pointer;
	pointer-events: auto;
	}
.leaflet-tooltip-top:before,
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
	position: absolute;
	pointer-events: none;
	border: 6px solid transparent;
	background: transparent;
	content: "";
	}

/* Directions */

.leaflet-tooltip-bottom {
	margin-top: 6px;
}
.leaflet-tooltip-top {
	margin-top: -6px;
}
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-top:before {
	left: 50%;
	margin-left: -6px;
	}
.leaflet-tooltip-top:before {
	bottom: 0;
	margin-bottom: -12px;
	border-top-color: #fff;
	}
.leaflet-tooltip-bottom:before {
	top: 0;
	margin-top: -12px;
	margin-left: -6px;
	border-bottom-color: #fff;
	}
.leaflet-tooltip-left {
	margin-left: -6px;
}
.leaflet-tooltip-right {
	margin-left: 6px;
}
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
	top: 50%;
	margin-top: -6px;
	}
.leaflet-tooltip-left:before {
	right: 0;
	margin-right: -12px;
	border-left-color: #fff;
	}
.leaflet-tooltip-right:before {
	left: 0;
	margin-left: -12px;
	border-right-color: #fff;
	}

/* Printing */

@media print {
	/* Prevent printers from removing background-images of controls. */
	.leaflet-control {
		-webkit-print-color-adjust: exact;
		print-color-adjust: exact;
		}
	}

/* /tokens.css */
/* TrailGoat — design tokens: the one palette vocabulary (TG-281).
 *
 * Loaded FIRST on every page, before the page's own stylesheet, so every
 * colour on the site traces back here. Page stylesheets (fuel.css, home.css,
 * site_performance.css) no longer carry their own :root palette; the theme
 * files (emerald / alpenglow / aurora / firstlight) override exactly these
 * names under their html.theme-* class, values unchanged.
 *
 * "Forest" — the default dark "trail at dusk" palette — is the plain :root
 * block below. Every token here is either today's value under a new name, or
 * a new step nothing consumes yet: this file is a visual no-op by contract. */

:root {
    /* ---- Ground: four steps, well → page → panel → raised ---- */
    --bg-0: #07120f;          /* deepest pine — the page */
    --bg-1: #0a1a1c;          /* forest navy — panels */
    --bg-well: color-mix(in srgb, var(--bg-0) 80%, #000);   /* inset tracks & wells, below the page */
    --bg-2:    color-mix(in srgb, var(--bg-1) 93%, #fff);   /* raised — --glass-2 flattened over --bg-1 */

    /* ---- Ink: four steps, bright → text → muted → faint ---- */
    --ink: #eaf4ee;           /* near-white text */
    --muted: #8ea7a0;         /* muted sage */
    --ink-bright: color-mix(in srgb, var(--ink) 60%, #fff);          /* headline emphasis */
    --faint:      color-mix(in srgb, var(--muted) 70%, var(--bg-0)); /* hints, placeholders, disabled */

    /* ---- Accent: the one hue on duty for actions and "current" ---- */
    /* Moss (TG-282). Orange is retired from chrome — it survives only as the
       Fueling data tint below. Each theme sets its own green-family accent;
       --accent-ink is the text colour on a solid accent fill (dark ink here,
       ≥12:1 on the forest ground; First Light flips it to paper). */
    --accent: #9ae600;
    --accent-ink: var(--bg-well);
    --selection: color-mix(in srgb, var(--accent) 28%, transparent);

    /* ---- The neutral ladder: every interactive state that is not the accent ----
       Chrome (buttons, toggles, nav links, hovers, menus, toasts, inputs) uses
       ONLY --accent plus these steps of the ink. Fills: idle 4% → hover 8% →
       selected 18%. Edges: a defined border sits at 40%; hover/focus edges and
       focus rings at 25%. Never a feature tint, never a coloured glow. */
    --fill-idle: color-mix(in srgb, var(--ink) 4%, transparent);
    --fill-hover: color-mix(in srgb, var(--ink) 8%, transparent);
    --fill-selected: color-mix(in srgb, var(--ink) 18%, transparent);
    --edge: color-mix(in srgb, var(--ink) 40%, transparent);
    --edge-soft: color-mix(in srgb, var(--ink) 25%, transparent);
    --ring: color-mix(in srgb, var(--ink) 25%, transparent);

    /* ---- Lines & glass ---- */
    --line: rgba(255, 255, 255, 0.09);
    /* Half a hairline, for edges that should be felt rather than seen — the
       code chip below. Derived from --line on purpose: a theme that re-lights
       the line gets a matching faint for free (TG-299). */
    --line-faint: color-mix(in srgb, var(--line) 55%, transparent);
    --glass: rgba(255, 255, 255, 0.045);
    --glass-2: rgba(255, 255, 255, 0.07);

    /* ---- Feature palette: one hue per Run Planner section ----
       Nine sections, nine hues, spread around the wheel so no two cards read
       as the same colour (KRI-119). Every theme overrides all of them; add a
       token here and there. These belong to data-viz and section iconography
       — charts, elevation, map layers, section icons — never to chrome (TG-282):
       not buttons, not hovers, not active/selected states. */
    --c-fuel: #ff7a1a;        /* Fueling */
    --c-pace: #9ae600;        /* Pacing */
    --c-crew: #3ad17f;        /* Crew — meadow */
    --c-course: #19c3b1;      /* Course */
    --c-gear: #8b6cff;        /* Gear */
    --c-weather: #e070ee;     /* Weather — dusk sky */
    --c-climb: #ff5d73;       /* Climbs */
    --c-aid: #36c5f0;         /* Aid stations + descents */
    --gold: #ffd23f;          /* AI coach — matches Capra's wordmark gradient; brand hue, outside the feature set */

    /* ---- Status: the three semantic colours (one status vocabulary) ----
       "Saved", "needs a look", "failed" — the words every status chip, error
       line and toast dot mean. They were five different reds and a handful of
       greens across the stylesheets; now they are three names, set per theme
       like the feature hues. Semantic, not accent: --ok is never the button
       colour and --accent is never "success" (TG-282). Each theme overrides
       all three, and only the state's colour changes — the chip's shape, its
       mono caps and its 1px currentColor edge stay the same everywhere. */
    --ok: #3ad17f;            /* ready, saved, synced */
    --warn: #ffb020;          /* draft, stale, needs a look */
    --bad: #ff5d73;           /* failed, invalid, destructive */

    /* ---- Legacy names: aliases of the feature palette during transition ----
       Every existing stylesheet reads these. They resolve through the theme's
       override of the --c-* token, so a theme only sets the new names. */
    --orange: var(--c-fuel);
    --moss: var(--c-pace);
    --fern: var(--c-crew);
    --teal: var(--c-course);
    --violet: var(--c-gear);
    --plum: var(--c-weather);
    --coral: var(--c-climb);
    --aqua: var(--c-aid);

    /* ---- Corners: two radii for the whole chrome (TG-283) ----
       Depth comes from thin borders and ground steps, not from blur, so the
       corners come down to two steps: --r-ctl for anything you press (nav
       links, buttons, chips, unit toggles, inputs, menu rows) and --r-card for
       the surfaces they sit on (panels, cards, menus, modals, toasts, the
       command palette). Avatars and the theme swatch dots stay round — they
       are pictures, not controls — and so do meters, progress bars and slider
       tracks, which are data. */
    --r-ctl: 6px;
    --r-card: 10px;

    /* ---- Type: three cuts of one family (TG-288) ---- */
    /* The Red Hat superfamily, in three roles: Display for headlines and the
       wordmark, Text for body copy and the chrome, Mono for the topbar, the
       small-caps labels and every figure. TrailGoat is secretly a numbers
       product, so its figures stay set like instrument readings — tabular,
       units tracked out in caps (TG-284) — but the mono now visibly belongs to
       the same family as the prose beside it instead of being a fourth rented
       font. The system fallbacks are deliberate: block fonts.googleapis and the
       page still reads and the columns still line up. */
    --display: 'Red Hat Display', -apple-system, BlinkMacSystemFont, sans-serif;
    --body: 'Red Hat Text', -apple-system, BlinkMacSystemFont, sans-serif;
    --mono: 'Red Hat Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

    /* ---- The floor under a mono-caps label (TG-301) ----
       Mono caps with letter-spacing is the product's label voice, and it is
       the voice that shrinks first: several of these had drifted to 0.6rem —
       9.6px of tracked-out uppercase, which is under what a label can be read
       at. This is a floor, not a size. A label already above it keeps its own
       size via max(); one below it comes up to meet this. It steps UP on a
       phone, where the screen is closer but smaller and the same type is
       harder, not easier. Decorative marks (the goat's bib, the `i` glyph)
       are not labels and are exempt. */
    --mono-cap: 0.6875rem;                 /* 11px */

    /* ---- Motion: announce the change, then stop (TG-285) ---- */
    /* One easing curve and two durations for the whole product. Motion here
       exists to say something arrived — a menu, a toast, the palette — and
       then it is over. Nothing in the chrome loops forever under a planning
       tool the runner is trying to read. */
    --ease-snap: cubic-bezier(0.23, 1, 0.32, 1);   /* easeOutQuint */
    --dur-ctl: 150ms;                              /* controls */
    --dur-layer: 250ms;                            /* layers that arrive */

    /* ---- You are here: the one two-colour mark (TG-287) ----
       Omarchy's single indulgence, ported: the active window's gradient border.
       Exactly ONE element per view wears it — the section chip in view on the
       planner and Training, the active view tab on /courses. The pair is the
       wordmark's (teal→moss), so each theme's own --teal/--accent makes it
       theirs. The fill is the raised ground: the padding-box layer must be
       opaque, or the ring would bleed through the middle. Never on cards,
       buttons, menus or the topbar — that keeps its flat underline. */
    --here-ring: linear-gradient(45deg, var(--teal), var(--accent));
    --here-fill: var(--bg-2);
    --here-bg: linear-gradient(var(--here-fill), var(--here-fill)) padding-box,
               var(--here-ring) border-box;

    /* ---- Shadow: one modest pop, for floating layers only ---- */
    /* Anything that leaves the page plane — dropdown menus, the command
       palette, toasts, tooltips, popovers — shares this one token. Resting
       surfaces get a 1px --line edge and a step up the ground instead of a
       shadow (TG-283), so nothing on the page floats.
       The rest of the depth system (--raise-*, --well, --ledge-orange) stays in
       fuel.css on purpose: home.css never defined it, and nav.css reads it
       without fallbacks, so hoisting it here would grow shadows on the home
       page's chrome — a visual change that refactor could not make. */
    --shadow-pop: 0 8px 24px rgba(0, 0, 0, 0.45);
}

/* The phone step-up for --mono-cap (TG-301). Overriding the token once beats
   restating a size in every consumer's own media query. */
@media (max-width: 860px) {
    :root { --mono-cap: 0.75rem; }         /* 12px */
}

/* ===== The body face (TG-288) =====
   The default for every page, declared once here because tokens.css loads
   before any page stylesheet. A page sheet that still sets its own body face
   (fuel.css, site_performance.css) loads later and keeps winning — which is
   exactly what holds the unswept tool pages on their old families until the
   sweep issue lands. */
body { font-family: var(--body); }

/* ===== The code voice (TG-299) =====
   `code`, `kbd` and `pre` are the third cut too. Without this rule they fall
   through to the UA's own monospace — a fourth family the type system never
   chose, and the one the `<iframe>` mention on /for-race-directors was still
   set in. The chip treatment is what three page stylesheets were each drawing
   for themselves; declared once here, a `<code>` reads the same wherever it
   appears. `.85em` rather than a fixed size, so it tracks the copy around it. */
code, kbd, pre {
    font-family: var(--mono);
    font-size: 0.85em;
    background: var(--bg-well);
    border: 1px solid var(--line-faint);
    border-radius: 4px;
    padding: 1px 5px;
}

/* ===== Body links (TG-299) =====
   info.css has carried the base `a` rule since TG-220 — but only the info
   pages load info.css, which is why the one prose link on the signed-out
   Creator still rendered in the UA's blue. The rule belongs here, where every
   page already loads it, and it carries the underline a body link should have.

   Scoped to classless anchors on purpose. Every anchor the chrome draws — the
   topbar, the footer, the tool cards, the anchor buttons below — wears a class
   and paints itself; a bare `a` rule would repaint all of them and drag an
   underline through the nav. `a:not([class])` is exactly the prose link this
   is for, and it is why the button classes need no exclusion list of their
   own to stay out of it. */
a:not([class]) {
    color: var(--accent);
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* An anchor that is a button never wears one. `.export-btn` (fuel.css) and
   `.btn` / `.btn-ghost` (home.css) are drawn for `<button>` first, and only
   `.btn` ever reset the UA underline — so the `<a>` form of the others showed
   one on /courses, /discover, /pricing, /404, /about, /crew-sheet and
   /dashboard, wherever a page loaded fuel.css without the local patch
   dashboard.css had been carrying. Reset here, in every state, for every
   page. */
a.export-btn, a.btn, a.btn-ghost,
a.export-btn:hover, a.btn:hover, a.btn-ghost:hover,
a.export-btn:focus, a.btn:focus, a.btn-ghost:focus,
a.export-btn:active, a.btn:active, a.btn-ghost:active {
    text-decoration: none;
}

/* ===== The instrument voice (TG-284) =====
   Two utilities, used site-wide. `.data` is any figure the product computes —
   a pace, a distance, a vert total, a cutoff, a fuel target, an ETA — and the
   tabular figures are what make a column of them line up digit for digit.
   `.data-label` is the small-caps voice that names one: eyebrows, section
   labels, table headers.

   Page stylesheets apply the same two declarations directly to their own value
   classes (`.metric-num`, `.cs-val`, `.plan-table td`, …) rather than every
   emitter growing a class — they read `var(--mono)` at the point of use, which
   is what the token is for. These utilities are for markup that has no class of
   its own to carry it. */
.data {
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}
/* The unit rides with the figure but never competes with it: smaller, tracked
   out, in caps, and one weight down (TG-284 AC-5 — hierarchy by weight, not by
   another colour). */
.data-u,
.data .unit,
.data .u {
    font-size: 0.8em;
    font-weight: 500;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.data-label {
    font-family: var(--mono);
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

/* ===== You are here (TG-287) =====
   The double-background technique: a flat fill on the padding box over the
   gradient on the border box, with the border itself transparent so the
   gradient shows through a 1px ring. Static by design — no transition, and
   nothing here for prefers-reduced-motion to suppress. Components whose own
   base rule loads later (`.section-chip`, `.cp-chip`) restate these four
   declarations at the point of use, reading the same tokens. */
.tg-here {
    color: var(--accent);
    border: 1px solid transparent;
    background: var(--here-bg);
    transition: none;
}

/* ===== The one entrance (TG-285) =====
   Every floating layer arrives the same way: a fast fade up from 96%, on
   --ease-snap. Defined here rather than in nav.css so the pages that skip nav
   (the crew sheet, the embed) can use it too. Each consumer sets its own
   transform-origin so the layer grows out of the control that opened it. */
@keyframes tg-pop-in {
    from { opacity: 0; transform: scale(0.96); }
    to   { opacity: 1; transform: none; }
}

/* ===== Touch (2026-09-04) =====
   Two properties, applied once here because tokens.css loads first on every
   page, so every control on the site inherits the behaviour rather than each
   stylesheet remembering it.

   `touch-action: manipulation` tells the browser a tap on a control can never
   be the first half of a double-tap-to-zoom, so it dispatches the click
   immediately instead of waiting to find out. That wait is the "not very
   responsive" feeling on a phone: the control is fine, the browser is just
   holding the event. Only interactive elements are named — the page body keeps
   pinch-zoom, which is an accessibility affordance, not a bug.

   The tap highlight is turned off in favour of each control's own :active
   state: the default is a grey rectangle that ignores border-radius and paints
   over the themed press feedback the components already define. */
a, button, summary, label, select, input, textarea,
[role="button"], [role="tab"], [role="switch"], .tg-tab {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}

/* ===== Focus: one ring, every page (2026-09-24) =====
   A keyboard visitor needs to see where they are, and until now that depended
   on which stylesheet a control happened to live in — the topbar drew a ring,
   the Creator, the info pages and most of the dashboard drew nothing but the
   browser default, which is a blue that belongs to no theme. This is the site
   default: a 2px ring in the accent, 2px off the control. `outline` follows
   `border-radius` in every current engine, so a pill gets a pill-shaped ring
   and a card gets a card-shaped one without naming either.

   Wrapped in :where() so it carries ZERO specificity: any control that already
   draws its own focus treatment (an inset ring on a tab, a border-colour swap
   on a text field) keeps it, because any class selector outranks this. It only
   fills the gaps. The main landmark is the skip link's target and takes focus
   programmatically; a ring round the whole page body says nothing. */
:where(a[href], button, input, select, textarea, summary,
       [tabindex]:not([tabindex="-1"]), [contenteditable="true"]):focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
:where(main, [tabindex="-1"]):focus { outline: none; }

/* ===== Tokyo Night — the default palette, and why it lives HERE =====
   Every other theme is a scoped-override stylesheet that tg-store.js loads on
   demand, which is right for a palette most visitors never see. It is wrong
   for the DEFAULT one: tokens.css is parsed before anything paints, so the
   page comes up in the :root palette below (Forest) and only turns Tokyo Night
   when a second file arrives — a visible flash on every first visit, reported
   2026-09-05.

   A default that costs a request is a default that flashes. So Tokyo Night's
   palette and its handful of literal-colour spots ride in this file, which is
   already on the critical path, and tg-store.js loads no stylesheet for it.
   The class is still applied the same way, so nothing else changes; if Tokyo
   Night ever stops being the default, this block moves back out to its own
   file and the roster gets its `file` back. */
html.theme-tokyonight {
    --bg-0: #1a1b26;          /* tokyo midnight */
    --bg-1: #24283b;          /* storm panels */
    --ink: #c0caf5;           /* neon-sign periwinkle white */
    --muted: #9aa5ce;         /* streetlight slate */
    --accent: #7aa2f7;        /* signal blue — the one accent on duty (TG-282) */
    --c-fuel: #ff9e64;        /* Fueling — lantern orange */
    --gold: #e0af68;          /* AI coach — Capra gradient, brass */
    --c-pace: #7aa2f7;        /* Pacing — signal blue */
    --c-crew: #9ece6a;        /* Crew — vending-machine green */
    --c-course: #0db9d7;      /* Course — neon cyan */
    --c-gear: #bb9af7;        /* Gear — arcade violet */
    /* The scheme's two purples sit 1° apart (KRI-119 would call them the same
       card twice), so Weather takes a pink-shifted dusk neon instead — the
       same separation move Emerald made for --c-aid. */
    --c-weather: #d98ae0;     /* Weather — dusk neon */
    --c-climb: #f7768e;       /* Climbs — vermilion sign */
    --c-aid: #7dcfff;         /* Aid stations + descents — pale sky glass */
    --ok: #9ece6a;            /* Status — vending-machine green */
    --warn: #e0af68;          /* Status — brass */
    --bad: #f7768e;           /* Status — vermilion sign */
}

/* --- Literal-colour spots that don't read the tokens (home.css) --- */
/* .grad / .eyebrow / .btn-primary already read the tokens — signal-blue hero for free. */
/* Backdrop tints → neon cyan + arcade violet over the indigo ground */
html.theme-tokyonight .backdrop {
    background:
        radial-gradient(1200px 600px at 70% -10%, rgba(13, 185, 215, 0.10), transparent 60%),
        radial-gradient(900px 500px at 10% 10%, rgba(187, 154, 247, 0.08), transparent 55%),
        linear-gradient(180deg, var(--bg-0), var(--bg-1));
}
html.theme-tokyonight .aurora {
    background: conic-gradient(from 180deg at 50% 50%, transparent, rgba(122, 162, 247, 0.07), transparent 40%);
}
/* Goat glow → signal blue, and stop the LED colour-cycle (it hardcodes old brand hues) */
html.theme-tokyonight .goat {
    filter: drop-shadow(0 24px 36px rgba(0, 0, 0, 0.55)) drop-shadow(0 0 10px rgba(122, 162, 247, 0.45));
    animation: bob 3.2s ease-in-out infinite;
}
/* Closing CTA band glow → violet neon */
html.theme-tokyonight .cta-band {
    background-image: radial-gradient(600px 200px at 50% -20%, rgba(187, 154, 247, 0.12), transparent 70%);
}
/* Hero route SVG gradient stops → cyan → signal blue → arcade violet */
html.theme-tokyonight #hr-grad stop:nth-of-type(1) { stop-color: #0db9d7; }
html.theme-tokyonight #hr-grad stop:nth-of-type(2) { stop-color: #7aa2f7; }
html.theme-tokyonight #hr-grad stop:nth-of-type(3) { stop-color: #bb9af7; }

/* /fuel.css */
/* TrailGoat Fuel Planner — shares the palette + type of the main dashboard.
   The palette and feature accents live in tokens.css (TG-281), which every
   page loads first; this block keeps the radius and the depth system. */
:root {
    /* Legacy card corner — now an alias of the shared --r-card (TG-283). */
    --radius: var(--r-card);

    /* Depth system — one light source for the whole site.
       raise-1: resting surfaces · raise-2: interactive/raised controls ·
       raise-primary: legacy solid-CTA depth, unused since buttons went flat ·
       well: inset tracks & inputs */
    --raise-1: inset 0 1px 0 rgba(255,255,255,0.07), 0 2px 6px rgba(0,0,0,0.35);
    --raise-2: inset 0 1px 0 rgba(255,255,255,0.09), 0 2px 5px rgba(0,0,0,0.45),
               0 10px 22px -8px rgba(0,0,0,0.55);
    --raise-primary: inset 0 1px 0 rgba(255,255,255,0.38), inset 0 -2px 4px rgba(120,45,0,0.3),
               0 2px 5px rgba(0,0,0,0.45), 0 10px 22px -8px rgba(255,122,26,0.5);
    --well: inset 0 2px 6px rgba(0,0,0,0.5), inset 0 -1px 0 rgba(255,255,255,0.05);
    --ledge-orange: 0 4px 0 #a34d03;
}

/* Inline stroke icons — inherit the button's text color so they always match. */
.ico { width: 15px; height: 15px; flex: 0 0 auto; }
.ico path, .ico circle, .ico rect, .ico line, .ico polyline { fill: none; stroke: currentColor; stroke-width: 1.75;
    stroke-linecap: round; stroke-linejoin: round; }

* { box-sizing: border-box; margin: 0; padding: 0; }

@media (prefers-reduced-motion: no-preference) {
    /* Smooth only for in-page anchor jumps (the target receives focus);
       programmatic scrolls and scroll restoration stay instant. */
    html:focus-within { scroll-behavior: smooth; }
}

body {
    font-family: var(--body);
    background: var(--bg-0);
    color: var(--ink);
    min-height: 100vh;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    overflow-x: clip;   /* not `hidden`: hidden makes body a scroll container, which eats smooth scrolls */
}

/* --- Backdrop --- */
.backdrop { position: fixed; inset: 0; z-index: -1; overflow: hidden; background:
    radial-gradient(1200px 600px at 70% -10%, rgba(25, 195, 177, 0.10), transparent 60%),
    radial-gradient(900px 500px at 10% 10%, rgba(255, 122, 26, 0.08), transparent 55%),
    linear-gradient(180deg, var(--bg-0), var(--bg-1)); }
.aurora { position: absolute; inset: -20% -20% auto -20%; height: 60%;
    background: conic-gradient(from 180deg at 50% 50%, transparent, rgba(154,230,0,0.06), transparent 40%);
    filter: blur(40px); }
.ridge { position: absolute; bottom: 0; left: 0; width: 100%; height: 38vh; opacity: 0.5; }
.ridge-back { fill: #0c2220; } .ridge-mid { fill: #0a1c1a; } .ridge-front { fill: #07140f; }

/* --- Top bar --- */
.topbar { display: flex; align-items: center; justify-content: space-between; gap: 10px;
    flex-wrap: wrap; padding: 18px clamp(16px, 2vw, 30px); max-width: none; margin: 0; }
.wordmark { font-family: var(--display); font-weight: 800; font-size: 1.4rem;
    letter-spacing: 0.02em; color: var(--ink); text-decoration: none; }
.grad { background: linear-gradient(100deg, var(--teal), var(--accent));
    -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
/* Inline brand lockup for AI-coach headings — "TRAILGOAT AI" in the wordmark's
   display cut, GOAT + AI in the brand gradient (.grad). "Ask" keeps the heading's
   own font, so on the all-caps cards it stays in the mono. */
.coach-brand { font-family: var(--display); font-weight: 800; letter-spacing: 0.02em;
    color: var(--ink); text-transform: none; }

.toggles { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
/* Unit toggles — an inset track with a raised "key" for the active side, so the
   switch reads as physical and orange stays reserved for primary actions. */
.unit-toggle { display: inline-flex; gap: 4px; background: rgba(0,0,0,0.35);
    border: 1px solid rgba(255,255,255,0.09); border-radius: var(--r-ctl); padding: 4px;
    box-shadow: var(--well); }
.unit-toggle button { background: transparent; color: var(--muted); border: none; cursor: pointer;
    font-family: inherit; font-weight: 700; font-size: 0.78rem; letter-spacing: 0.04em;
    padding: 7px 16px; border-radius: calc(var(--r-ctl) - 2px); transition: all 0.15s; }
.unit-toggle button.active { color: var(--ink);
    background: linear-gradient(180deg, rgba(255,255,255,0.16), rgba(255,255,255,0.08));
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.2), 0 3px 8px rgba(0,0,0,0.45); }

/* --- Layout --- */
.wrap { max-width: 1180px; margin: 0 auto; padding: 10px clamp(16px, 4vw, 40px) 80px; }

.hero { margin: 18px 0 30px; }
.eyebrow { color: var(--accent); font-family: var(--mono); font-weight: 500; letter-spacing: 0.1em;
    text-transform: uppercase; font-size: 0.8rem; margin-bottom: 12px; }
.hero h1 { font-family: var(--display); font-weight: 800;
    font-size: clamp(2rem, 5vw, 3.2rem); line-height: 1.05; letter-spacing: -0.02em; }
.hero-sub { color: var(--muted); font-size: 1.05rem; max-width: 40rem; margin-top: 16px; }

/* --- Panels --- */
.panel { background: var(--bg-2);
    border: 1px solid var(--line); border-top-color: rgba(255,255,255,0.16);
    border-radius: var(--radius);
    padding: 24px; box-shadow: var(--raise-1); }
.inputs, .fueling-plan { margin-bottom: 22px; }
.panel-title { font-family: var(--display); font-weight: 700; font-size: 1.15rem; }
.panel-head-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
/* Buttons — one solid primary per view; everything else is tonal or quiet.
   All three share the same geometry so they line up in a toolbar. */
/* Secondary verbs are the ladder's bordered neutral (TG-282): ink label, a
   defined edge, the fill steps on hover. Never a solid accent: the tool
   pages have no solid CTA since the topbar's went (TG-290). */
.export-btn { display: inline-flex; align-items: center; justify-content: center; gap: 7px;
    background: var(--fill-idle);
    color: var(--ink); border: 1px solid var(--edge); border-radius: var(--r-ctl);
    padding: 9px 18px; font-family: inherit; font-weight: 700; font-size: 0.85rem; cursor: pointer;
    transition: transform 0.13s ease, background 0.13s ease, border-color 0.13s ease; }
.export-btn:hover { transform: translateY(-1px);
    background: var(--fill-hover); }
.export-btn:active { transform: translateY(1px); background: var(--fill-selected); }
.export-btn:disabled { opacity: 0.6; cursor: default; transform: none; }
/* Tonal — tinted glass for secondary verbs (open, reverse, undo). */
.export-btn.tonal { color: var(--ink); border: 1px solid rgba(255,255,255,0.12);
    background: linear-gradient(180deg, rgba(255,255,255,0.085), rgba(255,255,255,0.04));
    box-shadow: var(--raise-1); }
.export-btn.tonal:hover { border-color: rgba(255,255,255,0.24); filter: none; }
.export-btn.tonal:active { box-shadow: inset 0 2px 6px rgba(0,0,0,0.45); }
.export-btn.tonal .ico { color: var(--accent); }

/* The effort — three intuitive groups side by side (stack on mobile) */
.effort-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 26px; margin-top: 18px; }
.effort-col { display: flex; flex-direction: column; }
.effort-col > * + * { margin-top: 16px; }
.col-head { font-family: var(--display); font-weight: 600; font-size: 0.98rem; color: var(--ink);
    padding-bottom: 8px; border-bottom: 1px solid var(--line); }

/* Fueling plan — each section is its own card under a shared header.
   The food pack is a full-width card on top; per-hour + total sit side-by-side below it. */
.fuel-head { margin-bottom: 16px; }
.fuel-cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
.fuel-card-full { grid-column: 1 / -1; }
@media (max-width: 600px) { .fuel-cards { grid-template-columns: 1fr; } }
.fuel-card { background: var(--bg-2);
    border: 1px solid var(--line); border-top-color: rgba(255,255,255,0.16);
    border-radius: var(--radius);
    padding: 22px; box-shadow: var(--raise-1); }
.result-group { display: flex; flex-direction: column; }
.methodology { margin-top: 22px; }

/* --- Form fields --- */
.field-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 14px; }
.adv-grid { max-width: 460px; margin-top: 14px; }
.field { display: flex; flex-direction: column; gap: 6px; }
.field-block { display: flex; flex-direction: column; gap: 10px; }
.field-label { color: var(--muted); font-size: 0.85rem; font-weight: 500; }
.field-label em { color: var(--teal); font-style: normal; font-weight: 600; }
.field-label small { color: var(--muted); opacity: 0.7; font-weight: 400; }
.field-label strong { color: var(--ink); font-family: var(--display); }
.slider-hint { color: var(--gold); font-weight: 600; margin-left: 4px; }

input[type="number"], input[type="text"], input[type="search"], input[type="datetime-local"], input[type="date"], select {
    background: var(--glass-2); color: var(--ink); border: 1px solid var(--line);
    border-radius: var(--r-ctl); padding: 11px 14px; font-family: inherit; font-size: 1rem; width: 100%;
    transition: border-color 0.15s; color-scheme: dark; -webkit-appearance: none; appearance: none; }
input[type="number"]:focus, input[type="text"]:focus, input[type="search"]:focus, input[type="datetime-local"]:focus, input[type="date"]:focus, select:focus {
    outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--ring); }
input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; }
select { cursor: pointer; }
select option { background: var(--bg-1); color: var(--ink); }

/* Segmented control */
.segmented { display: inline-flex; gap: 4px; background: var(--glass-2);
    border: 1px solid var(--line); border-radius: var(--r-ctl); padding: 4px; }
.segmented button { flex: 1; background: transparent; color: var(--muted); border: none;
    cursor: pointer; font-family: inherit; font-weight: 600; font-size: 0.9rem;
    padding: 9px 12px; border-radius: calc(var(--r-ctl) - 2px); transition: all 0.15s; white-space: nowrap; }
.segmented button.active { background: var(--fill-selected); color: var(--accent); }
/* Phones: a segmented group must never widen the page (pace-split-modes hit
   500px and dragged the whole planner into horizontal scroll at 375px, KRI-109).
   The group scrolls in place instead, scrollbar hidden. */
@media (max-width: 600px) {
    .segmented { display: flex; max-width: 100%; overflow-x: auto;
        -webkit-overflow-scrolling: touch; scrollbar-width: none; }
    .segmented::-webkit-scrollbar { display: none; }
    .segmented button { flex: 0 0 auto; }
}

/* Sliders */
.slider { -webkit-appearance: none; appearance: none; width: 100%; height: 6px; border-radius: 999px;
    background: linear-gradient(90deg, var(--teal), var(--gold), var(--orange)); outline: none; }
/* outline:none above outranks the site's :where() ring, so every range input
   had no keyboard focus mark at all. Restore it, clear of the 22px thumb. */
.slider:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 22px; height: 22px;
    border-radius: 50%; background: var(--ink); border: 3px solid var(--accent); cursor: pointer;
    box-shadow: 0 2px 8px rgba(0,0,0,0.4); }
.slider::-moz-range-thumb { width: 22px; height: 22px; border-radius: 50%; background: var(--ink);
    border: 3px solid var(--accent); cursor: pointer; }

/* Flat pace + duration estimate */
.pace-row { display: flex; gap: 10px; }
.pace-row input { flex: 0 0 96px; text-align: center; }
.estimate-btn { flex: 1; color: var(--ink);
    background: linear-gradient(180deg, rgba(255,255,255,0.085), rgba(255,255,255,0.04));
    border: 1px solid var(--line); border-radius: var(--r-ctl); padding: 0 14px;
    font-family: inherit; font-weight: 600; font-size: 0.9rem; cursor: pointer;
    box-shadow: var(--raise-1);
    transition: all 0.15s; }
.estimate-btn:hover { border-color: var(--edge-soft); background: var(--fill-hover); }
.estimate-btn:active { box-shadow: inset 0 2px 6px rgba(0,0,0,0.45); }
.estimate-out { color: var(--muted); font-size: 0.85rem; margin-top: 4px; min-height: 1.1em; }
.estimate-out strong { color: var(--gold); font-family: var(--mono);
    font-weight: 700; }
.estimate-out small { opacity: 0.85; }
.estimate-out.warn { color: var(--warn); }
.estimate-out.warn strong { color: var(--warn); }

/* Weather row (date/time + button) */
.weather-row { display: flex; gap: 10px; flex-wrap: wrap; }
.weather-row input { flex: 1 1 170px; }
.weather-row .estimate-btn { flex: 0 0 auto; }

.advanced { margin-top: 20px; border-top: 1px solid var(--line); padding-top: 14px; }
.advanced summary, .methodology summary { cursor: pointer; color: var(--muted); font-weight: 600;
    font-size: 0.9rem; list-style: none; }
.advanced summary::-webkit-details-marker, .methodology summary::-webkit-details-marker { display: none; }
.advanced summary::before, .methodology summary::before { content: '＋ '; color: var(--accent); }
.advanced[open] summary::before, .methodology[open] summary::before { content: '－ '; }

/* --- Result metrics --- */
/* Gut training on the Per-hour card (TG-340) — the same segmented control the settings
   menu uses, so the two places this one value can be set look like one control. It sits
   above the grid because it is the reason the carbs number reads what it reads. */
.gut-row { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; margin-top: 14px; }
.gut-row-label { font-size: 0.78rem; font-weight: 700; letter-spacing: 0.04em;
    text-transform: uppercase; color: var(--muted); }
.gut-chips { flex: 1 1 auto; }
.gut-chips button { flex: 1 1 0; padding-left: 10px; padding-right: 10px; }
@media (max-width: 480px) { .gut-row-label { flex: 1 0 100%; } }

.metric-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: 16px; }
.metric { position: relative; background: var(--glass-2); border: 1px solid var(--line);
    border-radius: var(--radius); padding: 15px 16px; overflow: hidden; }
.metric::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 3px;
    background: var(--stat-acc); opacity: 0.9; }
.metric::after { content: ''; position: absolute; top: -40px; right: -40px; width: 110px; height: 110px;
    border-radius: 50%; background: var(--stat-acc); opacity: 0.12; filter: blur(8px); }
/* Scoped as --stat-acc (a data tint), never the global --accent (TG-282). */
.metric-water  { --stat-acc: var(--teal); }
.metric-sodium { --stat-acc: var(--violet); }
.metric-carbs  { --stat-acc: var(--gold); }
.metric-cals   { --stat-acc: var(--orange); }
.metric-label { color: var(--muted); font-family: var(--mono); font-size: max(0.74rem, var(--mono-cap)); font-weight: 500;
    letter-spacing: 0.1em; text-transform: uppercase; margin-bottom: 8px; }
.metric-num { font-family: var(--mono); font-weight: 700;
    font-size: 1.5rem; line-height: 1.05; color: var(--stat-acc); }
/* Keep a range (e.g. "998–1,831") together; let the unit wrap below if tight.
   inline-block so JS can measure its width and auto-shrink to fit the card. */
.metric-num > span:first-child { white-space: nowrap; display: inline-block; }
.metric-unit { font-size: 0.8rem; font-weight: 500; letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--muted); margin-left: 3px; }

/* Kit list */
.kit-list { list-style: none; margin-top: 14px; display: flex; flex-direction: column; gap: 12px; }
.kit-list li { display: flex; align-items: baseline; gap: 10px; font-size: 1rem; }
.kit-list small { color: var(--muted); }
.kit-num { font-family: var(--mono); font-weight: 700;
    font-size: 1.4rem; color: var(--moss);
    min-width: 1.6em; text-align: right; white-space: nowrap; }
.kit-note { color: var(--muted); font-size: 0.85rem; margin-top: 14px; }

/* --- Course / GPX --- */
.course { margin-bottom: 22px; }
.course-head { margin-bottom: 16px; }
.course-name-field { margin-bottom: 16px; max-width: 420px; position: relative; }
/* z-index must clear the mini map below the field: Leaflet panes/controls run
   z 400–1000 in this same stacking context, so 50 hid the dropdown behind it. */
.course-suggest { position: absolute; top: 100%; left: 0; right: 0; z-index: 1100; margin-top: 6px;
    background: rgba(7, 18, 15, 0.98); border: 1px solid var(--line); border-radius: var(--r-card);
    box-shadow: var(--shadow-pop); max-height: 300px; overflow-y: auto; }
.suggest-item { display: flex; flex-direction: column; gap: 2px; width: 100%; text-align: left;
    background: none; border: none; border-bottom: 1px solid var(--line); padding: 10px 14px;
    cursor: pointer; color: var(--ink); font-family: inherit; }
.suggest-item:last-child { border-bottom: none; }
.suggest-item:hover { background: var(--glass-2); }
.suggest-name { font-weight: 600; font-size: 0.92rem; }
.suggest-meta { color: var(--muted); font-size: 0.8rem; }
/* "Still looking" while the search reaches past the local index (TG-326) —
   deliberately not a .suggest-item: there is nothing here to click yet. */
.suggest-wait { color: var(--muted); font-size: 0.86rem; padding: 10px 14px; }
.panel-sub { color: var(--muted); font-size: 0.88rem; margin-top: 4px; }
.panel-sub.rd-sec-lead { margin-top: 0; }   /* a section's first line, straight under its title */
/* "Community" on a course search result (TG-228): official matches rank first. */
.tg-community-badge { border: 1px solid currentColor; border-radius: var(--r-ctl);
    padding: 0 6px; font-size: 10px; opacity: 0.85; }
.inline-link { color: var(--accent); text-decoration: none; font-weight: 600; white-space: nowrap; }
.inline-link:hover { text-decoration: underline; }

.dropzone { display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 8px; text-align: center; padding: 32px 20px; border: 1.5px dashed var(--line);
    border-radius: var(--radius); background: var(--glass-2); cursor: pointer;
    transition: border-color 0.15s, background 0.15s; }
.dropzone:hover, .dropzone.dragover { border-color: var(--accent); background: var(--fill-hover); }
.dz-icon { font-size: 2rem; }
.dz-icon .ico { width: 30px; height: 30px; color: var(--muted); }
.base-map-cap .ico { color: var(--teal); vertical-align: -2px; }
.tg-browse-btn .ico { color: var(--accent); }
.dz-text { color: var(--ink); font-size: 0.98rem; }
.dz-text strong { font-weight: 600; }
.dz-status { color: var(--muted); font-size: 0.85rem; min-height: 1em; }
.dz-status.error { color: var(--bad); }
/* As a rail row of its own (TG-320) it must not hold a blank line open — the
   rail's gap would space an empty box like a real one. */
.rd-status:empty { display: none; }

.course-title { font-family: var(--display); font-weight: 800; font-size: 1.4rem; color: var(--ink);
    margin: 0 2px 12px; line-height: 1.2; }
.course-stats { display: flex; flex-wrap: wrap; gap: 10px; margin: 22px 0 16px; align-items: stretch; }
/* One line per label, one baseline per row (TG-301). The tiles are a flex row
   of equal-ish boxes, so a label that wraps makes its own tile taller and
   drops its figure below the others' — the row stops reading as a set of
   readings and starts reading as six unrelated boxes. The label gets its own
   line and is not allowed to take a second; the tiles stretch to a common
   height and the figure is pushed to the bottom of each, so every figure sits
   on one baseline whether or not its label needed the room. */
.course-stat { background: var(--glass-2); border: 1px solid var(--line); border-radius: var(--r-card);
    padding: 10px 14px; flex: 1 1 110px;
    display: flex; flex-direction: column; }
.course-stat .cs-label { color: var(--muted); font-family: var(--mono); font-weight: 500;
    font-size: max(0.72rem, var(--mono-cap)); text-transform: uppercase; letter-spacing: 0.1em;
    white-space: nowrap; }
/* The qualifier that used to ride in the unit slot after the figure. Muted,
   un-tracked and sentence case: it is a footnote to the label, not a label. */
.course-stat .cs-sub { display: block; font-family: var(--body); font-weight: 400;
    font-size: 0.7rem; letter-spacing: normal; text-transform: none;
    color: var(--muted); opacity: 0.85; white-space: nowrap; }
.course-stat .cs-val { font-family: var(--mono); font-weight: 700;
    font-size: 1.2rem; margin-top: auto; padding-top: 3px; }
.course-stat .cs-val .unit { font-size: 0.72rem; font-weight: 500; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--muted); margin-left: 4px; }
.cs-gain .cs-val { color: var(--orange); }
.cs-loss .cs-val { color: var(--aqua); }
.cs-dist .cs-val { color: var(--moss); }
.cs-high .cs-val { color: var(--gold); }
.cs-low  .cs-val { color: var(--teal); }
.cs-oxy  .cs-val { color: var(--plum); }

/* Surface mix (KRI-54). Deliberately the SAME tokens the map route, the profile
   ribbon and the pace-table chips already use — grey paved · gold gravel · moss
   trail · faded unknown — so the colour language is learned once and a theme
   restyles all of it together. The tile's value takes the dominant surface's
   colour, so the number and the strip below it agree at a glance. */
.cs-surface .cs-val { color: var(--moss); }          /* d-trail (default) */
.cs-surface.d-gravel .cs-val { color: var(--gold); }
.cs-surface.d-paved  .cs-val { color: var(--muted); }
.cs-mix { display: flex; height: 5px; border-radius: 3px; overflow: hidden; margin-top: 8px; }
.cs-mix i { display: block; min-width: 1px; }
.sfx-trail   { background: var(--moss); }
.sfx-gravel  { background: var(--gold); }
.sfx-paved   { background: var(--muted); }
/* Unknown is an ABSENCE of data, not a surface — same hue, dialled back so it
   reads as "nothing here" rather than as a fourth category. */
.sfx-unknown { background: var(--muted); opacity: 0.3; }

/* Event attribution under the course title (KRI-40) */
/* Event byline ("Jun 27, 2026 · by Western States Endurance Run"): a second
   line INSIDE the course card's header band, under the title (TG-318). It is
   a summary child, so that band wraps; body face, no caps, and the chevron
   stays on the title row (its order 0 beats the byline's 11). Links inside a
   <summary> follow without toggling the card — the anchor's activation wins. */
#course-view-panel > summary { flex-wrap: wrap; row-gap: 2px; }
.rd-section > summary .course-event-line {
    flex: 1 1 100%; order: 11; margin: 0 0 0 35px;
    font-family: var(--body); font-weight: 400; font-size: 0.82rem; color: var(--muted);
    text-transform: none; letter-spacing: normal;
}
.course-event-line a { color: var(--accent); text-decoration: none; }
.course-event-line a:hover { text-decoration: underline; }
/* "Train for this race →" (KRI-82) — a CTA, so it gets the site's orange. */
.course-event-line a.rd-train-link { color: var(--accent); font-weight: 600; }
.course-event-line[hidden] { display: none; }

/* Aid-station markers (map) + matching badges (plan table) */
.leaflet-div-icon.aid-marker-wrap { background: transparent; border: 0; }
.aid-marker { display: flex; align-items: center; justify-content: center; width: 26px; height: 26px;
    border-radius: 50%; color: #06140f; font-family: var(--display); font-weight: 800;
    font-size: 0.92rem; border: 2px solid rgba(255,255,255,0.92); box-shadow: 0 1px 5px rgba(0,0,0,0.5); }
.aid-badge { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px;
    border-radius: 50%; color: #06140f; font-family: var(--display); font-weight: 800; font-size: 0.72rem;
    margin-right: 8px; vertical-align: middle; }

/* isolation: Leaflet's panes (z 400) and controls (z 1000) otherwise escape into
   the page's stacking order and paint over anything sticky above the map — on
   the Run Planner the pane's section-chip row (z 7) vanished under the tiles as
   the plan scrolled. One stacking context per map keeps Leaflet's z-indexes
   internal; .map-expanded still lifts the whole wrap with its own z-index. */
.map-wrap { position: relative; isolation: isolate; border-radius: var(--radius); overflow: hidden; border: 1px solid var(--line); }
/* One frame around the map (TG-300). The Course panel drew three: the section
   card's border, then 24px of padding, then the map wrap's own 1px. The card's
   edge is the frame — the map loses its border and sits 12px inside, which is
   also 24px of width the profile and the stat tiles get back on a phone.
   Scoped to the panel rather than to .map-wrap: below 861px the pane merge
   moves this content into the rail, where .rd-merged has already stripped the
   card and the map's border becomes the only one there is. */
#course-view-panel { padding: 12px; }
#course-view-panel > summary { margin: -12px; padding: 10px 12px; }
/* The id selector above rewrites the shared band's whole margin shorthand, so
   the open/collapsed bottom margins from `.rd-section[open] > summary` lose on
   specificity and have to be restated at 12px here — without them the band
   keeps its -12px bottom and the map rides up over the header (and over its
   bottom rule). This card's band is the only two-row one on the page (the
   event byline sits under the title), so it also takes 10px of vertical
   padding rather than the shared 13px: two rows at 13px read as a slab. */
#course-view-panel:not([open]) > summary { margin-bottom: -12px; }
#course-view-panel[open] > summary { margin-bottom: 12px; }
#course-view-panel .map-wrap { border: none; }
#course-map { height: 425px; width: 100%; background: var(--bg-1); }

/* 3D terrain view (MapLibre) — overlays the 2D map within the same wrap.
   position:absolute !important beats MapLibre's own .maplibregl-map{position:relative}
   (its stylesheet loads later); z-index sits above Leaflet's panes/controls. */
.tg-3d { position: absolute !important; inset: 0; z-index: 1200; background: var(--bg-1); }
.tg-3d-badge { position: absolute; top: 10px; left: 50%; transform: translateX(-50%); z-index: 1300;
    font-family: var(--mono); font-weight: 700; font-size: 0.66rem; letter-spacing: 0.06em;
    text-transform: uppercase; color: var(--gold); background: rgba(7,18,15,0.85);
    border: 1px solid rgba(255,210,63,0.45); border-radius: var(--r-ctl); padding: 4px 10px; }
.tg-3d-exit { position: absolute; top: 10px; right: 10px; z-index: 1300; cursor: pointer;
    background: rgba(7,18,15,0.92); color: var(--ink); border: 1px solid var(--line); border-radius: 8px;
    padding: 7px 12px; font-family: var(--body); font-weight: 700; font-size: 0.82rem;
    box-shadow: 0 2px 8px rgba(0,0,0,0.45); }
.tg-3d-exit:hover { border-color: var(--edge-soft); color: var(--accent); }
.map-3d-btn { display: flex !important; align-items: center; justify-content: center; width: 32px; height: 32px;
    background: rgba(7,18,15,0.92); color: var(--ink); border: 1px solid var(--line); border-radius: 8px;
    font-family: var(--body); font-weight: 800; font-size: 0.72rem; line-height: 1; text-decoration: none;
    box-shadow: 0 2px 8px rgba(0,0,0,0.45); }
.map-3d-btn:hover { border-color: var(--edge-soft); color: var(--accent); }
/* Hide the 2D Leaflet controls while the 3D overlay is up (they drive the hidden map) */
.map-wrap.tg-3d-active .leaflet-control-container { display: none; }
/* 3D flythrough control (play/pause + speed), bottom-left of the 3D view */
.tg-3d-fly { position: absolute; left: 10px; bottom: 10px; z-index: 1300; display: flex; gap: 6px; }
.tg-3d-fly-btn, .tg-3d-fly-speed { cursor: pointer; background: rgba(7,18,15,0.92); color: var(--ink);
    border: 1px solid var(--line); border-radius: 8px; font-family: var(--body); font-weight: 700;
    box-shadow: 0 2px 8px rgba(0,0,0,0.45); line-height: 1; }
.tg-3d-fly-btn { padding: 9px 14px; font-size: 0.85rem; }
.tg-3d-fly-speed { padding: 9px 11px; font-size: 0.8rem; color: var(--muted); min-width: 36px; }
.tg-3d-fly-btn:hover { border-color: var(--edge-soft); color: var(--accent); }
.tg-3d-fly-speed:hover { border-color: var(--edge-soft); color: var(--ink); }

/* Locate-me button — same glass block as the 3D/expand controls beside it.
   No resting `color`: Leaflet's `.leaflet-container a` blue wins the cascade on
   those neighbours too, so omitting it here matches them by the same mechanism. */
.map-locate-btn { display: flex !important; align-items: center; justify-content: center;
    width: 32px; height: 32px; background: rgba(7,18,15,0.92);
    border: 1px solid var(--line); border-radius: 8px; line-height: 1;
    text-decoration: none; box-shadow: 0 2px 8px rgba(0,0,0,0.45); }
.map-locate-btn svg { width: 16px; height: 16px; display: block; }
.map-locate-btn:hover { border-color: var(--edge-soft); color: var(--accent); }

/* Expand-to-fullscreen button + state */
.map-expand-btn { display: flex !important; align-items: center; justify-content: center;
    width: 32px; height: 32px; background: rgba(7,18,15,0.92); color: var(--ink);
    border: 1px solid var(--line); border-radius: 8px; font-size: 1.05rem; line-height: 1;
    text-decoration: none; box-shadow: 0 2px 8px rgba(0,0,0,0.45); }
.map-expand-btn:hover { border-color: var(--edge-soft); color: var(--accent); }
/* Course playback control (play / pause + speed) */
.map-play { display: flex; gap: 6px; }
.map-play-btn, .map-speed-btn { display: flex !important; align-items: center; justify-content: center;
    height: 32px; background: rgba(7,18,15,0.92); color: var(--ink); border: 1px solid var(--line);
    border-radius: 8px; font-size: 0.95rem; line-height: 1; text-decoration: none;
    box-shadow: 0 2px 8px rgba(0,0,0,0.45); font-family: var(--body); font-weight: 700; }
.map-play-btn { width: 32px; }
.map-speed-btn { min-width: 34px; padding: 0 8px; font-size: 0.82rem; color: var(--muted); }
.map-play-btn:hover { border-color: var(--edge-soft); color: var(--accent); }
.map-speed-btn:hover { border-color: var(--edge-soft); color: var(--ink); }
.map-wrap.map-expanded { position: fixed; inset: 0; z-index: 9999; margin: 0;
    border: none; border-radius: 0; }
.map-wrap.map-expanded #course-map,
.map-wrap.map-expanded #lib-map,
.map-wrap.map-expanded #base-map { height: 100vh; height: 100dvh; }
body.map-modal-open { overflow: hidden; }
.leaflet-container { background: var(--bg-1); font-family: inherit; }

.elev-wrap { margin-top: 16px; }
.elev-head { color: var(--muted); font-size: 0.85rem; font-weight: 600; margin-bottom: 8px; }
.elev-head small { font-weight: 400; opacity: 0.8; }
/* Elevation-profile overlay toggles (Aid stations / Climbs / Descents) */
.tg-elev-toggles { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.tg-tog { display: inline-flex; align-items: center; gap: 7px; font-family: var(--body);
    font-weight: 600; font-size: 0.8rem; color: var(--muted); background: var(--glass-2);
    border: 1px solid var(--line); border-radius: var(--r-ctl); padding: 6px 12px; cursor: pointer;
    transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease; }
.tg-tog:hover { color: var(--ink); }
/* An explicit display beats the UA [hidden] rule — restate it (same trap as
   nav.css). Without this the Night/Altitude pills "hidden" for irrelevant
   courses still rendered, lit, on every low flat race. */
.tg-tog[hidden] { display: none; }
.tg-tog .tg-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--tg, #888);
    opacity: 0.3; transition: opacity 0.15s ease; }
.tg-tog.on { color: var(--ink); border-color: var(--tg, #888);
    background: color-mix(in srgb, var(--tg, #888) 13%, transparent); }
.tg-tog.on .tg-dot { opacity: 1; }
/* Distance-marker pill: the dot mimics the numbered puck on the map. */
.tg-tog-mile .tg-dot { width: 11px; height: 11px; background: rgba(7, 18, 15, 0.88);
    border: 1.5px solid var(--gold); }
.elev-canvas-wrap { position: relative; height: 260px; }
.elev-empty { color: var(--muted); font-size: 0.9rem; line-height: 1.5; padding: 28px 22px;
    text-align: center; border: 1px dashed var(--line); border-radius: var(--radius);
    background: var(--glass-2); }

/* Leaflet layer switcher — match the dark UI */
.leaflet-control-layers { background: rgba(7,18,15,0.92) !important; color: var(--ink);
    border: 1px solid var(--line) !important; border-radius: var(--r-card) !important;
    box-shadow: 0 8px 24px rgba(0,0,0,0.5) !important; }
.leaflet-control-layers-expanded { padding: 8px 12px !important; }
.leaflet-control-layers label { color: var(--ink); font-size: 0.85rem; font-weight: 500; margin: 2px 0; }
.leaflet-control-layers-selector { accent-color: var(--accent); margin-right: 6px; }
.leaflet-bar a { background: rgba(7,18,15,0.92); color: var(--ink); border-color: var(--line); }
.leaflet-bar a:hover { background: var(--fill-hover); }

/* Fueling-plan per-section summary — its own card below the metric cards */
.plan-summary { margin-top: 18px; }
.plan-summary .col-head { border-bottom: none; padding-bottom: 0; margin-bottom: 10px; }
.summary-text { color: var(--muted); font-size: 0.95rem; line-height: 1.55; margin-bottom: 14px; max-width: 64ch; }
.summary-text strong { color: var(--gold); font-weight: 700; }
/* Biggest-carries strip — replaces the old duplicate per-leg table. */
.carry-head { font-family: var(--mono); font-size: 0.75rem; font-weight: 500; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--muted); margin: 0 0 8px; }
.carry-strip { list-style: none; margin: 0; padding: 0; display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 10px; }
.carry-strip li { display: flex; flex-direction: column; gap: 2px; padding: 12px 14px;
    background: rgba(255, 255, 255, 0.03); border: 1px solid var(--line); border-radius: var(--r-card); }
.carry-name { font-weight: 700; font-size: 0.92rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.carry-dist { color: var(--muted); font-family: var(--mono); font-size: 0.78rem; }
.carry-load { font-family: var(--mono); font-size: 0.92rem; font-weight: 700; margin-top: 4px; }

/* Race plan table */
.plan-wrap { margin-top: 20px; }
.plan-scroll { overflow-x: auto; margin-top: 10px; }
.plan-table { width: 100%; border-collapse: collapse; font-size: 0.92rem; }
.plan-table th { text-align: left; color: var(--muted); font-family: var(--mono); font-weight: 500;
    font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.1em;
    padding: 6px 10px; border-bottom: 1px solid var(--line); }
/* Every column but the first holds a figure. The mono face here, plus the shared
   tabular-figures rule at the foot of this file, is what makes a split table read
   down a column instead of across a ragged edge (AC-4). */
.plan-table th:not(:first-child), .plan-table td:not(:first-child) { text-align: right; white-space: nowrap; }
.plan-table td:not(:first-child), .cmp-table td:not(:first-child) { font-family: var(--mono); }
/* td inherits --ink by default — don't set color here, or it would out-specify the
   .t-* value classes when they're applied directly to a <td> (they'd stay white). */
.plan-table td { padding: 9px 10px; border-bottom: 1px solid var(--line); }
/* Zebra striping + a warm hover so it's easy to track a single row across the table. */
.plan-table tbody tr:nth-child(even) { background: color-mix(in srgb, var(--ink) 3%, transparent); }   /* ink-based: a stripe on white too */
.plan-table tbody tr:hover { background: var(--fill-hover); }
.plan-table tbody tr:hover td { border-bottom-color: var(--edge-soft); }
.plan-table .aid-name { color: var(--ink); font-weight: 500; }
/* Semantic value colours (match the elevation profile: climbs orange, descents blue).
   Scoped under .plan-table so they reliably win on a <td> as well as a <span>. */
.plan-table .t-up { color: var(--orange); font-weight: 600; }
.plan-table .t-down { color: var(--aqua); font-weight: 600; }
/* OSM surface rows + aid-leg badges (KRI-35) — tokens, so themes restyle free */
.plan-table .srf-trail { color: var(--moss); font-weight: 600; }
.plan-table .srf-gravel { color: var(--gold); font-weight: 600; }
.plan-table .srf-paved { color: var(--muted); font-weight: 600; }
.srf-chip { display: inline-block; margin-left: 6px; padding: 1px 8px; border-radius: var(--r-ctl);
    font-size: 0.68rem; font-weight: 700; letter-spacing: 0.04em;
    border: 1px solid currentColor; opacity: 0.9; vertical-align: 1px; }
.plan-table .t-pace { color: var(--gold); font-weight: 700; }
.plan-table .t-water { color: var(--teal); font-weight: 600; }
.plan-table .t-carb { color: var(--gold); font-weight: 600; }
.plan-table .t-sep { color: var(--muted); font-weight: 400; }
.plan-table .t-flat { color: var(--muted); }
/* Aid table at a glance (gpx.js): the Temp cell's cool→hot wash and the
   Water cell's volume bar (--w, the leg's share of the biggest carry). Data
   hues, so each theme tints them its own way. */
.plan-table td.t-tint { border-radius: 6px; }
.plan-table td.t-hot  { background: color-mix(in srgb, var(--c-climb) 20%, transparent); }
.plan-table td.t-warm { background: color-mix(in srgb, var(--c-fuel) 17%, transparent); }
.plan-table td.t-mild { background: color-mix(in srgb, var(--gold) 12%, transparent); }
.plan-table td.t-cool { background: color-mix(in srgb, var(--c-aid) 14%, transparent); }
.plan-table td.w-carry { border-radius: 6px;
    background: linear-gradient(90deg, color-mix(in srgb, var(--c-course) 13%, transparent) var(--w, 0%), transparent var(--w, 0%)); }
/* Climb steepness scale — gentle gold → moderate orange → steep coral. */
.plan-table .grade-soft { color: var(--gold); font-weight: 600; }
.plan-table .grade-mid { color: var(--orange); font-weight: 600; }
.plan-table .grade-hard { color: var(--coral); font-weight: 700; }
.aid-actions { display: inline-flex; gap: 4px; margin-left: 8px; vertical-align: middle; }
/* Post-race plan vs actual (2026-08). */
.cmp-drop { margin: 4px 0 10px; }
.cmp-drop.over { border-color: var(--plum); }
.cmp-headline { font-size: 0.98rem; margin: 10px 0; }
.cmp-early { color: var(--ok); font-weight: 700; }
.cmp-late { color: var(--bad); font-weight: 700; }
.cmp-table { width: 100%; border-collapse: collapse; font-size: 0.88rem; }
.cmp-table th { text-align: left; color: var(--muted); font-family: var(--mono); font-weight: 500;
    font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.1em;
    padding: 6px 10px 6px 0; border-bottom: 1px solid var(--line); }
.cmp-table td { padding: 6px 10px 6px 0; border-bottom: 1px solid var(--line); }
.cmp-table .cmp-miss td { color: var(--muted); opacity: 0.7; }
.cmp-fade { color: var(--muted); font-size: 0.88rem; margin: 12px 0 2px; }
.cmp-fade b { color: var(--plum); }
.cmp-fade a { color: var(--fern); }

/* RD verification chip on the course event line — flat outline, fern check. */
.tg-verified { display: inline-flex; align-items: center; gap: 4px; padding: 1px 8px;
    font-size: 0.78rem; font-weight: 600; color: var(--fern);
    border: 1px solid color-mix(in srgb, var(--fern) 50%, transparent); border-radius: var(--r-ctl); }
.tg-verified svg { width: 11px; height: 11px; fill: none; stroke: currentColor; stroke-width: 2.5;
    stroke-linecap: round; stroke-linejoin: round; }

/* Night marker: a stop reached in darkness (and the headlamp note's glyph). */
.aid-night { display: inline-block; margin-left: 6px; vertical-align: -1px; color: var(--violet); }
.aid-night svg { width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; }
#night-note { color: var(--muted); }
#night-note .aid-night { margin-left: 0; }

/* Cutoff badge under a stop's arrival — flat outline pill, buffer-colored.
   ok ≥ 1h of margin · tight < 1h · missed = planned arrival is past it.
   Status tokens, the split table's margin column's thresholds and hues
   (raceday.css .pace-cut-m): a state, not a data series. */
.aid-cutoff { display: block; width: fit-content; margin-top: 3px; padding: 1px 7px;
    font-size: 0.72rem; font-family: var(--body); white-space: nowrap;
    border: 1px solid var(--line); border-radius: var(--r-ctl); color: var(--muted); cursor: pointer; }
.aid-cutoff.cut-ok { border-color: color-mix(in srgb, var(--ok) 45%, transparent); color: var(--ok); }
/* Time at this stop (TG-309) — the cutoff pill's quieter sibling: same outline,
   no grading, because a dwell is a choice rather than a threat. */
.aid-dwell { display: block; width: fit-content; margin-top: 3px; padding: 1px 7px;
    font: 500 .7rem/1.5 var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap;
    border: 1px solid var(--line); border-radius: var(--r-ctl); color: var(--muted); cursor: pointer; }
.aid-dwell:hover, .aid-dwell:focus-visible { border-color: color-mix(in srgb, var(--accent) 55%, transparent); color: var(--ink); }
/* A stop too close to the start or finish to carry time (TG-314). Not
   editable, so it must not look or behave editable — the cursor and the hover
   response are what the row uses to say "this one is telling you something,
   not offering you something". */
.aid-dwell-off { cursor: default; border-style: dashed; opacity: 0.75; }
.aid-dwell-off:hover, .aid-dwell-off:focus-visible { border-color: var(--line); color: var(--muted); }
/* The 95% guard is binding: the number shown is scaled, not what was set. */
.aid-dwell-scaled { border-color: color-mix(in srgb, var(--gold) 55%, transparent); color: var(--gold); }
.aid-cutoff.cut-tight { border-color: color-mix(in srgb, var(--warn) 55%, transparent); color: var(--warn); }
.aid-cutoff.cut-missed { border-color: color-mix(in srgb, var(--bad) 60%, transparent); color: var(--bad); }
/* A pill that has something to say (TG-310): the demand goes on its own line
   inside the pill, so the buffer stays scannable and the required pace reads
   as the answer to it. nowrap comes off — the sentence is longer than the
   column, and clipping a number a runner needs is worse than a second line. */
.aid-cutoff.cut-warn { white-space: normal; max-width: 36ch; line-height: 1.35; }
.aid-cutoff .cut-need { display: block; font-weight: 600; }
.aid-rm, .aid-edit, .aid-cut { background: none; border: none; color: var(--muted); cursor: pointer;
    line-height: 1; padding: 2px 4px; border-radius: 6px; }
.aid-rm { font-size: 1.1rem; }
.aid-edit { font-size: 0.95rem; }
.aid-rm:hover { color: var(--ink); background: var(--fill-hover); }
.aid-edit:hover, .aid-cut:hover { color: var(--accent); background: var(--fill-hover); }
.aid-cut svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 2; }
.aid-fixed { color: var(--muted); font-weight: 600; }
.plan-empty { color: var(--muted); font-size: 0.85rem; padding: 12px 2px; }
.plan-note { color: var(--muted); font-size: 0.8rem; margin-top: 8px; }
.plan-note strong { color: var(--ink); font-weight: 600; }

.aid-add { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.aid-add #aid-dist { flex: 0 0 80px; }
.aid-add #aid-name { flex: 1 1 140px; }
.aid-add .estimate-btn { flex: 0 0 auto; }

.course-actions { margin-top: 18px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.course-actions .course-clear { margin-top: 0; }
.save-status { font-size: 0.85rem; color: var(--muted); }
.save-status.ok { color: var(--ok); }
.save-status.warn { color: var(--warn); }

.course-clear { margin-top: 16px; background: transparent; color: var(--muted);
    border: 1px solid var(--line); border-radius: var(--r-ctl); padding: 8px 16px; cursor: pointer;
    font-family: inherit; font-weight: 600; font-size: 0.85rem; transition: all 0.15s; }
.course-clear:hover { color: var(--ink); border-color: var(--edge-soft); background: var(--fill-hover); }

/* --- Course library page --- */
.topnav { display: flex; gap: 8px; flex-wrap: wrap; }
.back-link { color: var(--muted); text-decoration: none; font-weight: 600; font-size: 0.9rem;
    padding: 8px 16px; border: 1px solid var(--line); border-radius: var(--r-ctl); }
.back-link:hover { color: var(--ink); border-color: var(--edge-soft); background: var(--fill-hover); }
/* Primary in-app nav — mirrors the landing page (.nav from home.css). */
.nav { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.nav a { color: var(--muted); text-decoration: none; font-weight: 600; font-size: 0.92rem;
    padding: 8px 14px; border-radius: var(--r-ctl); transition: color 0.2s ease, background 0.2s ease; }
.nav a:hover { color: var(--ink); background: var(--glass); }
.nav .beta-tag { font-size: 0.62rem; font-weight: 700; color: var(--gold); margin-left: 4px;
    letter-spacing: 0.05em; vertical-align: super; }
.lib-toolbar { display: flex; gap: 10px; align-items: center; margin-bottom: 20px; flex-wrap: wrap; }
.lib-search { flex: 1 1 280px; max-width: 480px; }
.lib-manage { background: var(--glass-2); color: var(--muted); border: 1px solid var(--line);
    border-radius: var(--r-ctl); padding: 9px 16px; font-family: inherit; font-weight: 600; font-size: 0.85rem;
    cursor: pointer; white-space: nowrap; }
.lib-manage:hover { color: var(--ink); border-color: var(--edge-soft); background: var(--fill-hover); }
.lib-manage.active { color: var(--accent); border-color: var(--accent); background: var(--fill-selected); }
.lib-card { position: relative; }
.lib-del { position: absolute; top: 8px; right: 8px; width: 24px; height: 24px; border-radius: 50%;
    border: 1px solid var(--line); background: rgba(7,18,15,0.85); color: var(--muted); cursor: pointer;
    font-size: 1.1rem; line-height: 1; display: flex; align-items: center; justify-content: center; }
.lib-del:hover { color: var(--ink); border-color: var(--edge-soft); background: var(--fill-hover); }
.lib-count { color: var(--muted); font-size: 0.85rem; margin: 2px 2px 16px; }
.lib-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 16px; }

.lib-card { position: relative; display: flex; flex-direction: column; gap: 8px; text-decoration: none;
    text-align: left; width: 100%; font-family: inherit; color: var(--ink); cursor: pointer;
    background: var(--glass-2); border: 1px solid var(--line); border-radius: var(--radius);
    padding: 18px; transition: border-color 0.15s, transform 0.15s, background 0.15s; }
.lib-card:hover { border-color: var(--edge-soft); transform: translateY(-2px);
    background: var(--fill-hover); }
.lib-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lib-card-cta { color: var(--accent); font-weight: 600; }
.lib-card-name { font-family: var(--display); font-weight: 700; font-size: 1.02rem; color: var(--ink); }
.lib-card-stats { display: flex; flex-wrap: wrap; gap: 14px; color: var(--muted); font-size: 0.9rem; }
.lib-card-stats strong { color: var(--ink); font-family: var(--display); }
.lib-card-date { color: var(--teal); font-size: 0.85rem; }
.lib-card-foot { color: var(--muted); font-size: 0.78rem; margin-top: auto; opacity: 0.8; }
.lib-tag { color: var(--gold); font-size: 0.78rem; }
.lib-empty { color: var(--muted); font-size: 0.95rem; padding: 24px 4px; }

/* Course preview window (modal) */
.pv-modal-backdrop { position: fixed; inset: 0; z-index: 9000; display: flex; align-items: flex-start;
    justify-content: center; padding: 4vh 16px; overflow-y: auto;
    background: rgba(3, 9, 7, 0.82); }
.pv-modal-backdrop[hidden] { display: none; }
.pv-modal { position: relative; width: 100%; max-width: 800px; margin: auto; background: var(--bg-1);
    border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-pop); padding: 26px; }
.pv-close { position: absolute; top: 16px; right: 16px; width: 34px; height: 34px; border-radius: 50%;
    border: 1px solid var(--line); background: var(--glass-2); color: var(--muted); cursor: pointer;
    font-size: 1rem; line-height: 1; display: flex; align-items: center; justify-content: center; z-index: 2; }
.pv-close:hover { color: var(--ink); border-color: var(--edge-soft); background: var(--fill-hover); }
.lib-preview-head { margin-bottom: 16px; padding-right: 40px; }
.pv-meta { color: var(--muted); font-size: 0.88rem; margin-top: 6px; }
#pv-map { height: 450px; width: 100%; background: var(--bg-1); }
.pv-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 20px;
    padding-top: 18px; border-top: 1px solid var(--line); }
.pv-actions-label { color: var(--muted); font-size: 0.9rem; margin-right: 2px; }
body.pv-open { overflow: hidden; }

/* "Open in…" chooser modal (library page) */
.tg-modal-backdrop { position: fixed; inset: 0; z-index: 10000; display: flex; align-items: center;
    justify-content: center; padding: 20px; background: rgba(3, 9, 7, 0.8); }
.tg-modal { width: 100%; max-width: 440px; background: var(--bg-1); border: 1px solid var(--line);
    border-radius: var(--radius); box-shadow: var(--shadow-pop); padding: 24px; }
.tg-modal-eyebrow { color: var(--accent); font-family: var(--mono); font-weight: 500;
    letter-spacing: 0.1em; text-transform: uppercase; font-size: 0.72rem; }
.tg-modal-title { font-family: var(--display); font-weight: 700; font-size: 1.2rem; margin-top: 6px; }
.tg-modal-sub { color: var(--muted); font-size: 0.9rem; margin-top: 4px; }
.tg-modal-choices { display: flex; flex-direction: column; gap: 10px; margin: 18px 0 14px; }
.tg-modal-choice { display: flex; flex-direction: column; gap: 3px; text-align: left; cursor: pointer;
    background: var(--glass-2); border: 1px solid var(--line); border-radius: var(--r-card); padding: 14px 16px;
    color: var(--ink); font-family: inherit; transition: border-color 0.15s, background 0.15s; }
.tg-modal-choice:hover { border-color: var(--edge-soft); background: var(--fill-hover); }
.tg-choice-title { font-family: var(--display); font-weight: 600; font-size: 1rem; }
.tg-choice-sub { color: var(--muted); font-size: 0.83rem; }
.tg-modal-cancel { background: transparent; color: var(--muted); border: 1px solid var(--line);
    border-radius: var(--r-ctl); padding: 8px 16px; cursor: pointer; font-family: inherit; font-weight: 600;
    font-size: 0.85rem; }
.tg-modal-cancel:hover { color: var(--ink); border-color: var(--muted); }

/* --- TrailGoat AI coach --- */
.coach { margin-bottom: 22px; }
.coach-messages { display: flex; flex-direction: column; gap: 10px; margin: 16px 0; }
/* Assistant bubbles render minimal markdown (bold + bullets) — see fuel-coach.js. */
.coach-msg ul { margin: 4px 0; padding-left: 18px; }
.coach-msg li { margin: 2px 0; }
.coach-msg strong { color: var(--gold); font-weight: 700; }
.coach-msg { max-width: 85%; padding: 10px 14px; border-radius: var(--r-card); font-size: 0.92rem; line-height: 1.5;
    white-space: pre-wrap; }
.coach-user { align-self: flex-end; background: var(--fill-selected); color: var(--ink); border-bottom-right-radius: 4px; }
.coach-assistant { align-self: flex-start; background: rgba(25,195,177,0.08); border: 1px solid rgba(25,195,177,0.28);
    border-left: 3px solid var(--teal); color: var(--ink); border-bottom-left-radius: 4px; }
.coach-assistant strong { color: var(--teal); }
.coach-thinking { color: var(--teal); font-style: italic; }
.coach-suggestions { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.coach-suggestions[hidden] { display: none; }   /* the flex above was beating [hidden] */
.coach-chip { background: var(--fill-idle); color: var(--ink); border: 1px solid var(--edge-soft);
    border-radius: var(--r-ctl); padding: 7px 14px; font-family: inherit; font-size: 0.85rem; cursor: pointer;
    transition: all 0.15s; }
.coach-chip:hover { border-color: var(--edge); background: var(--fill-hover); color: var(--ink); }
.coach-input { display: flex; gap: 10px; }
/* The runner's answer to "may we keep your questions?", with a way to change it. */
.coach-consent { margin: 8px 2px 0; font-size: .8rem; color: var(--muted); line-height: 1.45; }
.coach-consent[hidden] { display: none; }
.coach-consent-change { font: inherit; font-weight: 600; color: var(--accent); background: none; border: 0;
    padding: 0; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }
.coach-consent-change:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }
.coach-input input { flex: 1; }
/* Locked Capra (KRI-199): the panel stays fully readable — hiding it would make
   the feature look absent rather than paid — but the controls go inert and the
   whole row becomes one click target for the upgrade cards. */
.coach-chip:disabled { opacity: .55; pointer-events: none; }
.coach-suggestions.coach-locked { cursor: pointer; }
.coach-chip:disabled:hover { border-color: var(--edge-soft); background: var(--fill-idle); color: var(--ink); }
.coach-input.coach-locked { cursor: pointer; }
.coach-input.coach-locked input { opacity: .55; pointer-events: none; }
.coach-input.coach-locked .export-btn { opacity: .55; pointer-events: none; }
.coach-input .export-btn { flex: 0 0 auto; }

/* Streaming (the Capra idea): stage copy until the first token, then a caret
   while tokens arrive. The caret is the bubble's own ink, not a new hue. */
.coach-streaming::after { content: ''; display: inline-block; width: 0.5em; height: 1em; margin-left: 2px;
    vertical-align: -0.15em; background: currentColor; opacity: .55; border-radius: 1px;
    animation: capra-caret 1s steps(2, start) infinite; }
@keyframes capra-caret { to { visibility: hidden; } }
.coach-thinking::before { content: ''; display: inline-block; width: 7px; height: 7px; margin-right: 8px;
    border-radius: 50%; background: var(--gold); vertical-align: 0.05em; animation: capra-pulse 1.2s var(--ease-snap) infinite; }
@keyframes capra-pulse { 50% { opacity: .25; } }
@media (prefers-reduced-motion: reduce) {
    .coach-streaming::after, .coach-thinking::before { animation: none; }
}
/* Where the reply's suggestions went — one line under the answer. */
.capra-note { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line); white-space: normal; }
.capra-note .inline-link, .capra-pop .inline-link { background: none; border: 0; padding: 0; font: inherit;
    font-size: 0.85rem; font-weight: 600; cursor: pointer; }
.capra-note .inline-link:focus-visible, .capra-pop .inline-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }

/* Capra's chip on an aid-table row: small, gold (Capra's brand hue — the one
   thing on the table that is an opinion rather than a number), and a button,
   so the printout's table clone drops it with the other controls. */
.capra-sug { display: inline-flex; align-items: center; gap: 5px; margin: 2px 0 2px 8px; padding: 2px 8px;
    min-height: 24px; max-width: 100%; border-radius: var(--r-ctl); font: inherit; font-size: 0.78rem; line-height: 1.2;
    color: var(--ink); background: color-mix(in srgb, var(--gold) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--gold) 45%, transparent); cursor: pointer; vertical-align: middle;
    text-align: left; transition: background var(--dur-ctl) var(--ease-snap), border-color var(--dur-ctl) var(--ease-snap); }
.capra-sug:hover, .capra-sug[aria-expanded="true"] { background: color-mix(in srgb, var(--gold) 18%, transparent);
    border-color: var(--gold); }
.capra-sug:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.capra-sug-by { font-family: var(--mono); font-size: 0.64rem; font-weight: 700; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--gold); }
.capra-pop { position: fixed; z-index: 60; padding: 12px 14px; background: var(--bg-2); color: var(--ink);
    border: 1px solid color-mix(in srgb, var(--gold) 45%, transparent); border-left: 3px solid var(--gold);
    border-radius: var(--r-card); box-shadow: var(--shadow-pop); font-size: 0.88rem;
    animation: capra-pop-in var(--dur-layer) var(--ease-snap); }
@keyframes capra-pop-in { from { opacity: 0; transform: translateY(-4px); } }
.capra-pop-head { font-weight: 700; line-height: 1.35; }
.capra-pop-at { font-weight: 400; color: var(--muted); }
.capra-pop-why { margin: 6px 0 0; color: var(--ink); line-height: 1.45; }
.capra-pop-actions { display: flex; align-items: center; gap: 12px; margin-top: 10px; }
@media (prefers-reduced-motion: reduce) { .capra-pop { animation: none; } }
@media (max-width: 860px) {
    .capra-sug { min-height: 32px; margin-left: 0; }
    .capra-pop-actions .export-btn, .capra-pop-actions .inline-link { min-height: 44px; }
}

/* Footer */
.foot { text-align: center; color: var(--muted); font-size: 0.85rem; padding: 30px 24px 50px; }
.foot a { color: var(--accent); text-decoration: none; }
.foot a:hover { text-decoration: underline; }

/* Methodology */
.methodology p { color: var(--muted); font-size: 0.9rem; margin-top: 12px; }
.methodology .disclaimer { color: var(--muted); }
.methodology .disclaimer strong { color: var(--gold); }

/* =========================================================================
   Two-pane app shell (Planner + Fuel) — body.split-page only.
   Mobile keeps the natural stacked, page-scroll flow (the grid/scroll panes
   only kick in at >=861px). Left = setup/inputs, right = map + outputs.
   ========================================================================= */
/* Empty-state placeholder in a result pane — shown until a course loads.
   (Global so it works on mobile too; the sibling toggle hides it once the
   course view is un-hidden by the page JS.) */
.split-empty {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 12px; min-height: 280px; text-align: center; color: var(--muted); padding: 20px;
}
.split-empty-icon { font-size: 2.6rem; opacity: 0.7; }
.split-empty p { max-width: 26rem; }
.course-view:not([hidden]) ~ .split-empty { display: none; }   /* loaded → hide placeholder */

/* Empty state = a navigable base map of the user's area (before a course loads). */
.split-empty.has-basemap { display: block; min-height: 0; padding: 0; text-align: left; }
#base-map { height: clamp(450px, 72vh, 775px); width: 100%; background: var(--bg-1); }
#base-map[hidden] { display: none; }   /* explicit height above would beat [hidden] */
/* Waiting / "open a course" cards shown in the map slot (base-map.js states 1 & 3). */
.base-map-note {
    height: clamp(450px, 72vh, 775px);
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 8px; text-align: center; padding: 24px;
    border: 1px dashed var(--line); border-radius: var(--radius);
    background: var(--glass); color: var(--ink); font-size: 0.95rem;
}
.base-map-note strong { color: var(--ink); font-size: 1.1rem; font-family: var(--display); }
.base-map-note span { max-width: 46ch; }
.base-map-note .bm-goat { display: block; width: 49px; height: 64px; margin: 0 auto;
    filter: drop-shadow(0 2px 3px rgba(0,0,0,0.55)); }
.base-map-note .bm-retry {
    margin-top: 10px; font: inherit; font-size: 0.86rem; font-weight: 600;
    color: var(--ink); background: none; border: 1px solid var(--edge);
    border-radius: var(--r-ctl); padding: 6px 14px; cursor: pointer;
}
.base-map-note .bm-retry:hover { background: var(--fill-hover); }
/* Featured-course cards (KRI-56) — the one-click wow moment. */
.bm-featured { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center;
    margin-top: 14px; width: 100%; max-width: 640px; }
.bm-card { flex: 1 1 170px; max-width: 210px; display: grid; gap: 3px; text-align: left;
    text-decoration: none; border: 1px solid var(--line); border-radius: var(--r-card);
    padding: 12px 14px; background: var(--glass-2, rgba(255,255,255,0.03));
    transition: border-color 0.15s, background 0.15s, transform 0.15s; }
.bm-card:hover { border-color: var(--edge-soft); background: var(--fill-hover);
    transform: translateY(-1px); }
.bm-card-name { font-weight: 700; color: var(--ink); font-family: var(--display);
    font-size: 0.95rem; }
.bm-card-meta { color: var(--muted); font-size: 0.78rem; }
.bm-card-go { color: var(--accent); font-size: 0.78rem; font-weight: 600; margin-top: 4px; }
.bm-fail { color: var(--bad); font-size: 0.82rem; margin-top: 6px; }
@media (max-width: 560px) {
    .bm-featured { flex-direction: column; }
    .bm-card { max-width: none; }
}
.base-map-cap { color: var(--muted); font-size: 0.86rem; margin: 12px 2px 0; max-width: none;
    display: flex; align-items: center; gap: 6px 10px; flex-wrap: wrap; }
.base-map-cap strong { color: var(--ink); }
.base-map-sub { opacity: 0.8; }
/* "You are here" mascot marker on the base map (neutralise Leaflet's default div-icon box). */
.tg-you-goat { background: none; border: 0; text-align: center;
    filter: drop-shadow(0 2px 3px rgba(0,0,0,0.55)); }
.tg-you-goat img { display: block; width: 33px; height: 44px; }

@media (min-width: 861px) {
    /* Scoped to the split-page layout ON PURPOSE. An unscoped `html {height:100%}`
       clamps the background POSITIONING AREA to one viewport on every page that
       loads this sheet, so a body gradient tiles once per screen down a long
       page (the crew sheet showed a seam every ~900px). The planner hides that
       behind its fixed .backdrop; pages without one don't.
       Two rules, not one list: an unsupported :has() would invalidate the whole
       list and take the split-page rule down with it. */
    html:has(body.split-page) { height: 100%; }
    body.split-page { height: 100%; }
    body.split-page {
        display: flex; flex-direction: column;
        height: 100vh; height: 100dvh;
        overflow: hidden;                         /* the page itself never scrolls */
    }
    body.split-page .topbar { flex: 0 0 auto; }

    body.split-page .wrap {
        max-width: none; width: 100%;
        margin: 0; padding: 0 clamp(16px, 2vw, 30px);
        flex: 1 1 auto; min-height: 0;
        display: flex; flex-direction: column;
    }
    body.split-page .foot { display: none; }      /* reclaim vertical space */

    /* Hero now lives inside .split-left so the right-pane map rises to the top, inline
       with the hero text (reclaims the wasted top-right space). */
    body.split-page .hero { flex: 0 0 auto; margin: 0; }
    body.split-page .hero h1 { font-size: clamp(1.35rem, 2.2vw, 1.85rem); }
    body.split-page .hero-sub { display: none; }

    /* Two columns fill the remaining height; each scrolls on its own. */
    body.split-page .app-split {
        flex: 1 1 auto; min-height: 0;
        display: grid; grid-template-columns: minmax(320px, 400px) 1fr; gap: 18px;
        align-items: stretch; padding-bottom: 14px;
    }
    body.split-page .split-left,
    body.split-page .split-right {
        min-height: 0; overflow-y: auto; overscroll-behavior: contain;
        display: flex; flex-direction: column; gap: 16px; padding-right: 4px;
    }
    body.split-page .split-left::-webkit-scrollbar,
    body.split-page .split-right::-webkit-scrollbar { width: 9px; }
    body.split-page .split-left::-webkit-scrollbar-thumb,
    body.split-page .split-right::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--ink) 14%, transparent); border-radius: 8px; }

    /* Panels inside the panes shouldn't add their own outer margins. */
    body.split-page .split-left > .panel,
    body.split-page .split-right > .panel { margin: 0; }
}

/* ===== Build your pack (food database) ===== */
.fp { margin-top: 6px; }
.fp-empty { color: var(--muted); font-size: 0.9rem; line-height: 1.5; margin: 4px 0 0; }

/* Coverage bars: pack total vs the engine's race targets. Full-width card → lay the
   bars out in a responsive grid; glossy 3D pills with a moving sheen. */
.fp-cov-sub-head { font-family: var(--body); font-weight: 400; font-size: 0.78rem; color: var(--muted); }
.fp-coverage { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 16px 26px; margin-top: 12px; }
.fp-coverage[hidden] { display: none; }
.fp-cov-row { display: flex; flex-direction: column; gap: 7px; }
.fp-cov-caf { --acc: var(--c-climb); }   /* caffeine: an informational total */
.fp-cov-top { display: flex; align-items: baseline; justify-content: space-between; }
.fp-cov-label { font-family: var(--display); font-weight: 600; font-size: 0.95rem; color: var(--ink); }
.fp-pct { font-family: var(--mono); font-weight: 700;
    font-size: 1.02rem; color: var(--acc, var(--teal));
    text-shadow: 0 0 12px color-mix(in srgb, var(--acc, var(--teal)) 55%, transparent); }
.fp-pct.over { color: var(--ok); text-shadow: 0 0 12px color-mix(in srgb, var(--ok) 55%, transparent); }

/* Track = a recessed channel (inset shadow reads as carved-in depth). */
.fp-cov-track {
    position: relative; height: 16px; border-radius: 999px; overflow: hidden;
    background: linear-gradient(180deg, rgba(0,0,0,0.45), rgba(255,255,255,0.03));
    border: 1px solid rgba(255,255,255,0.07);
    box-shadow: inset 0 2px 5px rgba(0,0,0,0.55), inset 0 -1px 0 rgba(255,255,255,0.04);
}
/* Fill = a glossy raised pill: vertical light→dark gradient + top highlight + glow. */
.fp-cov-fill {
    position: relative; height: 100%; border-radius: 999px; min-width: 6px;
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--acc, var(--teal)) 58%, #fff) 0%,
        var(--acc, var(--teal)) 45%,
        color-mix(in srgb, var(--acc, var(--teal)) 70%, #000) 100%);
    box-shadow: 0 0 14px -2px var(--acc, var(--teal)),
        inset 0 1px 0 rgba(255,255,255,0.6),
        inset 0 -3px 6px rgba(0,0,0,0.28);
    transition: width 0.5s cubic-bezier(.2,.8,.3,1);
}
/* A fixed highlight across the fill — the gloss stays, the perpetual sweep is
   gone (TG-285). */
.fp-cov-fill::after {
    content: ""; position: absolute; inset: 0; border-radius: inherit;
    background: linear-gradient(115deg, transparent 30%, rgba(255,255,255,0.28) 48%, transparent 66%);
}
@media (prefers-reduced-motion: reduce) {
    .fp-cov-fill { transition: none; }
}
.fp-cov-sub { font-size: 0.84rem; color: var(--muted); }
.fp-cov-sub small { opacity: 0.8; }
.fp-cov-info { justify-content: flex-end; }
.fp-cov-info .fp-cov-sub { color: var(--ink); }

/* Your pack */
.fp-pack-head { display: flex; align-items: baseline; justify-content: space-between; margin: 18px 0 8px; }
.fp-pack-head h4 { font-family: var(--display); font-weight: 600; font-size: 0.95rem; color: var(--ink); margin: 0; }
.fp-count { color: var(--muted); font-weight: 500; font-size: 0.82rem; margin-left: 6px; }
.fp-clear { background: none; border: 1px solid var(--line); color: var(--muted); border-radius: var(--r-ctl);
    font: inherit; font-size: 0.78rem; padding: 3px 11px; cursor: pointer; transition: all 0.15s; }
.fp-clear:hover { color: var(--ink); border-color: var(--edge-soft); background: var(--fill-hover); }

/* Fixed-height scroll region, NOT free-growing: every added pill used to push
   the food grid down mid-tap, so the second tap landed on the wrong product
   (2026-08 review, worst on phones). The pack scrolls inside itself instead —
   nothing below it ever moves. */
.fp-pack { display: flex; flex-wrap: wrap; gap: 8px; align-content: flex-start;
    height: 84px; overflow-y: auto; padding-right: 6px;
    scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--ink) 20%, transparent) transparent; }
.fp-pack::-webkit-scrollbar { width: 8px; }
.fp-pack::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--ink) 14%, transparent); border-radius: 8px; }
/* Slots (2026-09): the pack laid out as a vest — front L, front R, back —
   plus a card per drop bag. Still one fixed-height scroller, taller now it
   holds cards, for the same reason as above. */
.fp-pack { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 8px;
    height: 176px; flex-wrap: nowrap; }
.fp-slot { border: 1px solid var(--line); border-radius: var(--r-card); padding: 7px 8px 8px;
    background: var(--glass); min-width: 0; align-self: start; }
.fp-slot.is-bag { border-style: dashed; }
.fp-slot-h { display: flex; justify-content: space-between; align-items: baseline; gap: 6px; margin-bottom: 6px; }
.fp-slot-t { font-weight: 600; font-size: 0.8rem; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fp-slot-s { font-size: 0.72rem; color: var(--muted); white-space: nowrap; }
.fp-slot-pills { display: flex; flex-wrap: wrap; gap: 6px; }
.fp-slot-pills:empty::before { content: "—"; color: var(--muted); font-size: 0.8rem; }

/* Carbs per hour: what the pack can feed each hour against the target. */
.fp-meter { margin: 2px 0 16px; }
.fp-meter[hidden] { display: none; }
.fp-meter-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px;
    font-size: 0.72rem; color: var(--muted); margin-bottom: 6px; }
.fp-meter-tgt { color: var(--ink); font-size: 0.8rem; white-space: nowrap; }
.fp-meter-chart { position: relative; display: flex; align-items: flex-end; gap: 2px; height: 72px;
    padding-top: 2px; border-bottom: 1px solid var(--line); }
.fp-meter-goal { position: absolute; left: 0; right: 0; top: 2px; border-top: 1px dashed var(--edge-soft, var(--line)); pointer-events: none; }
.fp-meter-bar { flex: 1 1 0; min-width: 2px; border-radius: 2px 2px 0 0; background: var(--ok); }
.fp-meter-bar.warn { background: var(--warn); }
.fp-meter-bar.bad { background: var(--bad); }
.fp-meter-ticks { display: flex; justify-content: space-between; font-size: 0.68rem; color: var(--muted); margin-top: 3px; }
.fp-short { margin: 10px 0 0; padding: 8px 10px; border-radius: var(--r-ctl); font-size: 0.85rem;
    border: 1px solid color-mix(in srgb, var(--ok) 40%, transparent); color: var(--ink); }
.fp-short p { margin: 0; }
.fp-short.bad { border-color: color-mix(in srgb, var(--bad) 45%, transparent); }
.fp-short.bad b { color: var(--bad); }
.fp-short.ok b { color: var(--ok); }
.fp-short-sub { color: var(--muted); }
.fp-short-fix { margin-top: 8px; min-height: 36px; text-align: left; }
@media (max-width: 860px) {
    .fp-pack { height: 220px; grid-template-columns: 1fr 1fr; }
    .fp-short-fix { min-height: 44px; width: 100%; justify-content: center; }
}
@media (max-width: 420px) {
    .fp-pack { grid-template-columns: 1fr; }
}
.fp-pack-empty { grid-column: 1 / -1; color: var(--muted); font-size: 0.88rem; font-style: italic; padding: 4px 2px; }
.fp-pill { display: inline-flex; align-items: center; gap: 4px; padding: 3px 4px 3px 4px;
    border: 1px solid color-mix(in srgb, var(--cat, var(--teal)) 55%, transparent);
    background: color-mix(in srgb, var(--cat, var(--teal)) 14%, transparent);
    border-radius: var(--r-ctl); font-family: var(--body); font-size: 0.85rem; color: var(--ink); }
.fp-pill .fp-name { padding: 0 2px; }
.fp-qty { font-family: var(--mono); font-weight: 700;
    min-width: 1.1em; text-align: center;
    color: var(--cat, var(--teal)); }
.fp-step { width: 22px; height: 22px; border-radius: 50%; border: none; cursor: pointer;
    background: var(--fill-hover); color: var(--ink); font-size: 1rem; line-height: 1;
    display: inline-flex; align-items: center; justify-content: center; transition: background 0.15s; }
.fp-step:hover { background: color-mix(in srgb, var(--cat, var(--teal)) 35%, transparent); }
.fp-rm { width: 20px; height: 20px; margin-left: 2px; border: none; cursor: pointer; background: none;
    color: var(--muted); font-size: 1.05rem; line-height: 1; border-radius: 50%; transition: all 0.15s; }
.fp-rm:hover { color: var(--ink); background: var(--fill-hover); }

/* Search + food bin */
.fp-search-wrap { display: block; margin: 16px 0 10px; }
.fp-search-wrap input { width: 100%; }
/* overscroll-behavior:auto so reaching the bin's scroll limit chains back to the
   page/pane scroll instead of dead-stopping. */
.fp-bin { display: flex; flex-direction: column; gap: 14px; max-height: 360px; overflow-y: auto;
    padding-right: 4px; overscroll-behavior: auto; }
.fp-bin::-webkit-scrollbar { width: 8px; }
.fp-bin::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--ink) 14%, transparent); border-radius: 8px; }
.fp-bin-cat { display: flex; align-items: baseline; gap: 8px; margin: 0 0 8px; flex-wrap: wrap;
    font-family: var(--mono); font-weight: 700; font-size: 0.78rem; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--cat, var(--muted)); }
.fp-bin-cat small { text-transform: none; letter-spacing: 0; font-weight: 400; color: var(--muted); opacity: 0.85; }
.fp-bin-pills { display: flex; flex-wrap: wrap; gap: 8px; }
.fp-bin-none { color: var(--muted); font-size: 0.88rem; font-style: italic; }
.fp-add-pill { display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px 5px 9px;
    border: 1px solid var(--line); border-radius: var(--r-ctl); background: var(--glass); cursor: pointer;
    font-family: var(--body); font-size: 0.85rem; color: var(--muted); transition: all 0.15s; }
.fp-add-pill:hover { color: var(--ink); transform: translateY(-1px);
    border-color: var(--cat, var(--teal)); background: color-mix(in srgb, var(--cat, var(--teal)) 12%, transparent); }
.fp-add-pill:active { transform: translateY(0) scale(0.97); }
.fp-add-pill.added { color: var(--ink); border-color: color-mix(in srgb, var(--cat, var(--teal)) 55%, transparent);
    background: color-mix(in srgb, var(--cat, var(--teal)) 10%, transparent); }
.fp-add-ic { color: var(--cat, var(--teal)); font-weight: 700; line-height: 1; }
.fp-add-name { color: inherit; }
.fp-add-macros { color: var(--muted); font-size: 0.74rem; white-space: nowrap; }
.fp-add-macros small { opacity: 0.7; }

/* ===== Hour-by-hour weather strip (shared by /fuel and /raceday; logic in raceday-weather.js) ===== */
.rd-weather { margin-top: 18px; }
.rd-weather[hidden] { display: none; }
.rd-wx-strip { display: flex; align-items: stretch; gap: 8px; margin-top: 8px; }
.rd-wx-cells { flex: 1 1 auto; display: grid; grid-template-columns: repeat(12, 1fr); gap: 5px; min-width: 0; }
.rd-wx-cell {
    display: flex; flex-direction: column; align-items: center; gap: 3px;
    padding: 9px 2px; border-radius: var(--r-ctl); background: var(--glass); border: 1px solid var(--line);
    min-width: 0;
}
.rd-wx-cell.rd-wx-race { border-color: rgba(255,122,26,0.6); background: rgba(255,122,26,0.08); }
.rd-wx-cell.rd-wx-empty { opacity: 0.4; }
.rd-wx-cell.rd-wx-newday { box-shadow: inset 2px 0 0 rgba(255,210,63,0.55); }
.rd-wx-day { font-size: 0.58rem; font-weight: 700; color: var(--gold); min-height: 0.85em; white-space: nowrap; line-height: 1; }
.rd-wx-time { font-family: var(--mono); font-size: 0.64rem; color: var(--muted); white-space: nowrap; }
.rd-wx-ico { line-height: 1; color: var(--ink); display: flex; justify-content: center; }
/* Weather art is line-icon SVG (icons.js) — sized here, coloured by context. */
.rd-wx-ico .wx-ico { width: 22px; height: 22px; }
.rd-wx-race .rd-wx-ico { color: var(--orange); }
/* Small inline glyphs beside a stat (droplet, wind, sunrise, thermometer…). */
.wx-gl { width: 13px; height: 13px; vertical-align: -0.16em; opacity: .9; }
.wx-gl.aqua { color: var(--aqua); } .wx-gl.gold { color: var(--gold); } .wx-gl.orange { color: var(--orange); }
.rd-wx-temp { font-family: var(--mono); font-weight: 700; font-size: 0.9rem; }
/* Temperature steps, cool → hot (weather-explorer.js tempCls; its chart
   resolves the same tokens). Data hues: a temperature is data, not a state. */
.wx-tn { color: var(--muted); }
.wx-t0 { color: var(--c-aid); }
.wx-t1 { color: var(--c-course); }
.wx-t2 { color: var(--c-crew); }
.wx-t3 { color: var(--gold); }
.wx-t4 { color: var(--c-fuel); }
.wx-t5 { color: var(--c-climb); }
.rd-wx-pp { font-size: 0.6rem; color: var(--teal); min-height: 0.8em; white-space: nowrap; }
.rd-wx-arrow {
    flex: 0 0 auto; width: 34px; border-radius: var(--r-ctl); cursor: pointer;
    background: var(--glass-2); color: var(--ink); border: 1px solid var(--line);
    font-size: 1.2rem; line-height: 1; transition: all 0.15s ease;
}
.rd-wx-arrow:hover:not(:disabled) { border-color: var(--edge-soft); background: var(--fill-hover); }
.rd-wx-arrow:disabled { opacity: 0.3; cursor: default; }
.rd-wx-status { color: var(--muted); font-size: 0.8rem; margin-top: 8px; min-height: 1em; }
.rd-wx-status.warn { color: var(--warn); }

/* ===================== Weather explorer card (weather-explorer.js) ===================== */
.rd-wx-bar { display: flex; align-items: center; gap: 12px 18px; flex-wrap: wrap; margin-bottom: 12px; }
.rd-wx-datefield { display: inline-flex; align-items: center; gap: 8px; color: var(--muted); font-size: 0.86rem; }
.rd-wx-datefield input { background: var(--glass-2); color: var(--ink); border: 1px solid var(--line); border-radius: 10px; padding: 7px 10px; font: inherit; color-scheme: dark; }
.rd-wx-datefield input:focus { outline: none; border-color: var(--accent); }
.rd-wx-datefield input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.rd-wx-summary { display: flex; flex-wrap: wrap; gap: 7px 16px; align-items: center; color: var(--muted); font-size: 0.86rem; }
.rd-wx-summary b:not([class]) { color: var(--ink); }   /* a .wx-t* high keeps its hue */
.rd-wx-sum-note { font-style: italic; opacity: 0.85; }

.rd-wx-days { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(60px, 1fr); gap: 6px;
    overflow-x: auto; padding-bottom: 6px; margin-bottom: 14px; overscroll-behavior-x: contain; }
.rd-wx-day-chip { display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 8px 4px;
    border-radius: var(--r-ctl); background: var(--glass); border: 1px solid var(--line); cursor: pointer; color: var(--ink); transition: all 0.15s ease; }
.rd-wx-day-chip:hover { border-color: var(--edge-soft); background: var(--fill-hover); }
.rd-wx-day-chip.active { border-color: var(--accent); background: var(--fill-selected); }
.rd-wx-dc-day { font-size: 0.7rem; font-weight: 700; color: var(--muted); }
.rd-wx-dc-ico { font-size: 1.1rem; line-height: 1; }
.rd-wx-dc-hl { font-family: var(--mono); font-size: 0.72rem; }

/* Two hourly views, switchable via a pill toggle: an Apple-style temperature curve
   (Chart.js, mirrors the elevation profile's hover/drag scrubber) and the classic
   hour-by-hour cells. */
.rd-wx-chart-head { display: flex; align-items: center; justify-content: space-between; gap: 10px;
    flex-wrap: wrap; margin: 16px 0 8px; }
.rd-wx-chart-title { color: var(--muted); font-size: 0.85rem; font-weight: 600; }
.rd-wx-view-toggle { display: inline-flex; gap: 4px; background: var(--glass-2);
    border: 1px solid var(--line); border-radius: var(--r-ctl); padding: 3px; }
.rd-wx-view-toggle button { background: transparent; color: var(--muted); border: none; cursor: pointer;
    border-radius: var(--r-ctl); padding: 5px 13px; font-family: var(--body); font-weight: 600; font-size: 0.78rem; }
.rd-wx-view-toggle button.active { background: var(--fill-selected); color: var(--accent); }
.rd-wx-chart-wrap { position: relative; height: 210px; }
/* City label in the Weather header band (reverse-geocoded from the course start). */
.rd-wx-place { color: var(--ink); font-weight: 600; }
/* .rd-wx-strip sets display:flex (fuel.css), which beats the UA [hidden] rule — re-assert it
   so toggling back to the graph actually hides the hour-by-hour cells. */
.rd-wx-strip[hidden], .rd-wx-chart-wrap[hidden] { display: none; }

/* Classic hour-by-hour cells (base .rd-wx-* come from fuel.css). */
#rd-weather-card .rd-wx-cells { grid-template-columns: repeat(12, minmax(72px, 1fr)); overflow-x: auto; overscroll-behavior-x: contain; }
.rd-wx-feels { font-size: 0.6rem; color: var(--muted); min-height: 0.8em; white-space: nowrap; }
.rd-wx-wind { font-size: 0.6rem; color: var(--muted); white-space: nowrap; }
.rd-wx-cell.rd-wx-night { background: rgba(60, 80, 140, 0.16); }
.rd-wx-none { color: var(--muted); font-style: italic; padding: 8px 2px; }

@media (max-width: 560px) {
    .rd-wx-cells { grid-template-columns: repeat(12, minmax(46px, 1fr)); overflow-x: auto; }
}

/* ===== Collapsible coloured left-pane sections (shared by /raceday, /fuel, /planner) =====
   A .panel that is a <details>; the <summary> is the header. Each section carries an accent
   colour via --acc (set inline) for a coloured left edge + icon chip + chevron, so the left
   pane reads as distinct, lively cards. */
/* The collapsible card look — ONE source of truth, shared by /fuel, /planner and
   /raceday (every `.panel.rd-section`). Treatment: a mono all-caps title, a
   filled accent header band, and an accent glow outline, all keyed off the card's
   per-card `--acc` colour. Panel content padding is 14px (top/bottom) × 24px
   (left/right), so the band uses matching negative margins to bleed to the edges.
   Change the card aesthetic HERE and all three pages stay in sync. */
.rd-section { padding-top: 14px; padding-bottom: 14px; }
/* When a card is collapsed, force-hide its body even where an author rule (the base map,
   the fuel-cards grid, etc.) would otherwise display:block/grid it. Shared so the result
   cards collapse correctly on /fuel and /planner, not just /raceday. */
.rd-section:not([open]) > :not(summary) { display: none !important; }

/* The section's identity stays in its 1px accent-tinted edge (iconography);
   the coloured glow it used to carry is gone (TG-282). */
.rd-section.panel {
    border: 1px solid color-mix(in srgb, var(--acc, var(--line)) 55%, var(--line));
    box-shadow: none;
}

.rd-section > summary {
    list-style: none; cursor: pointer; user-select: none;
    display: flex; align-items: center; gap: 9px;
    font-family: var(--mono); font-weight: 700; font-size: 1.02rem; color: var(--ink);
    text-transform: uppercase; letter-spacing: 0.02em;
    /* Filled header band — bleeds to the card edges. */
    margin: -14px -24px; padding: 13px 24px;
    background: linear-gradient(100deg, color-mix(in srgb, var(--acc, var(--muted)) 26%, transparent), transparent 92%);
    border-radius: calc(var(--radius) - 1px);
}
.rd-section > summary::-webkit-details-marker { display: none; }
/* The section title is a real <h2> (one outline for screen readers) that
   looks exactly like the summary text it wraps. */
.rd-sec-h { margin: 0; font: inherit; letter-spacing: inherit; text-transform: inherit; color: inherit; }
.rd-sec-ico {
    flex: 0 0 auto; width: 26px; height: 26px; border-radius: 8px; display: grid; place-items: center;
    font-size: 0.95rem; background: var(--acc, var(--muted));
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.28), 0 2px 5px rgba(0,0,0,0.35);
}
/* Dark stroke on the accent tile — same raised-tile treatment as the landing cards. */
.rd-sec-ico .ico { width: 15px; height: 15px; color: #081410; }
.rd-section > summary::after {
    content: '⌄'; margin-left: auto; color: var(--acc, var(--muted)); font-size: 1.1rem; line-height: 1;
    transition: transform 0.18s ease;
}

/* The AI coach card wears its gold section tint like every other section.
   The three-hue gradient ring / band / tile it used to carry is retired: the
   wordmark and the goat are the only multicolour brand marks (TG-282). Its
   "TRAILGOAT AI" title still carries the wordmark gradient via .grad. */
#coach-panel { --acc: var(--gold); position: relative; }
.rd-section[open] > summary::after { transform: rotate(180deg); }
.rd-section > summary .rd-sec-sub {
    font-family: var(--body); font-weight: 400; font-size: 0.78rem; color: var(--muted);
    text-transform: none; letter-spacing: normal;
}
/* Collapsed: the band fills the whole card. Open: band caps the top, body sits below. */
.rd-section:not([open]) > summary { margin-bottom: -14px; }
.rd-section[open] > summary {
    margin-bottom: 14px; border-bottom: 1px solid var(--line);
    border-radius: calc(var(--radius) - 1px) calc(var(--radius) - 1px) 0 0;
}

/* The fuel form must stay one element (fuel.js delegates its 'input' listener on it),
   but it shouldn't draw its own box — let its <details> children be the panes. */
.rd-form { display: contents; }

/* Space the sections' controls a touch tighter in the narrow left pane. */
.rd-section .field-block + .field-block { margin-top: 14px; }
.rd-section .effort-col > * + * { margin-top: 14px; }

/* A small note under a section heading. */
.rd-note { color: var(--muted); font-size: 0.84rem; margin: 0 0 12px; }
.rd-note:last-child { margin-bottom: 0; }
/* Clear-course control inside the Course card (left pane). */
.course-card-actions { margin-top: 12px; display: flex; flex-wrap: wrap; gap: 8px; }
/* GPX download only means something once a course is loaded (KRI-112). */
#download-gpx { display: none; }
body.has-course #download-gpx { display: inline-flex; }

/* ===== Mobile ergonomics (shared by every tool page; fuel.css is the common sheet) ===== */
@media (max-width: 860px) {
    /* iOS Safari zooms the whole page when a focused field computes under 16px.
       Guard every text-entry control — the typed selector matches the specificity
       of the themed input rules above, and this block loads later, so it wins. */
    input[type], input:not([type]), select, textarea { font-size: max(1rem, 16px); }

    /* Touch targets: grow hit areas toward the 44px minimum without inflating
       the glyphs. Isolated map-corner controls and pill controls that sit in
       tight clusters get as close as their context allows. */
    .map-3d-btn, .map-expand-btn, .map-play-btn, .map-locate-btn { width: 42px; height: 42px; }
    .map-locate-btn svg { width: 20px; height: 20px; }
    .map-speed-btn { min-width: 42px; height: 42px; }

    /* Food-pack pills: bigger steppers, comfortable pill height. */
    .fp-pill { padding: 5px 6px; }
    .fp-step { width: 34px; height: 34px; }
    .fp-rm { width: 30px; height: 30px; }
    .fp-add-pill { min-height: 44px; padding: 8px 14px 8px 11px; }
    .fp-clear { min-height: 36px; padding: 5px 14px; }

    /* Aid-station row actions (✎ / ×): full-size touch targets. */
    .aid-actions { gap: 0; margin-left: 4px; }
    .aid-rm, .aid-edit {
        min-width: 42px; min-height: 42px;
        display: inline-flex; align-items: center; justify-content: center;
    }
}

/* ===== Mobile plan tables: stacked two-line rows =====
   Under 600px the 5–6 column tables don't fit; instead of clipping the payload
   columns (pace, splits, water, carbs) off-screen, each <tr> reflows into a
   card-like row: line 1 = the label + the answer, line 2 = muted supporting
   detail. Pure CSS — the row templates in JS are untouched. Line breaks are
   deterministic: a flex-grow:1 cell fills the rest of its line, so the next
   cell always wraps. */
@media (max-width: 600px) {
    /* Stat cards: distance is the headline (full width), the rest pair up 2×2 —
       no more lone orphan card stretched across the last row. */
    .course-stats { display: grid; grid-template-columns: 1fr 1fr; }
    .course-stats .cs-dist { grid-column: 1 / -1; }

    #pace-table thead, #climbs-table thead, #plan-summary .plan-table thead,
    #raceplan-table thead, #aid-table thead, #lib-aid-table thead { display: none; }

    #pace-table, #climbs-table, #plan-summary .plan-table,
    #raceplan-table, #aid-table, #lib-aid-table { display: block; }
    #pace-table tbody, #climbs-table tbody, #plan-summary .plan-table tbody,
    #raceplan-table tbody, #aid-table tbody, #lib-aid-table tbody { display: block; }

    #pace-table tr, #climbs-table tr, #plan-summary .plan-table tr,
    #raceplan-table tr, #aid-table tr, #lib-aid-table tr {
        display: flex; flex-wrap: wrap; align-items: baseline;
        column-gap: 14px; row-gap: 3px;
        padding: 11px 4px; border-bottom: 1px solid var(--line);
    }
    #pace-table td, #climbs-table td, #plan-summary .plan-table td,
    #raceplan-table td, #aid-table td, #lib-aid-table td {
        display: block; padding: 0; border: 0; text-align: left;
    }

    /* Pacing plan — line 1: segment + target pace; line 2: gain/loss · grade · elapsed.
       The rows' ::before is an invisible full-width flex item — a deterministic
       line break between the headline cells and the detail cells. */
    #pace-table tr::before { content: ""; flex: 1 1 100%; order: 3; }
    #pace-table td:nth-child(1) { flex: 1 1 auto; order: 1; font-weight: 600; }
    #pace-table td:nth-child(4) { order: 2; }
    #pace-table td:nth-child(2) { order: 4; font-size: 0.82rem; }
    #pace-table td:nth-child(3) { order: 5; font-size: 0.82rem; }
    #pace-table td:nth-child(5) { order: 6; margin-left: auto; font-size: 0.82rem; color: var(--muted); }
    #pace-table td:nth-child(5)::before { content: "elapsed "; }

    /* Major climbs — line 1: climb + gain; line 2: from–to · length · grade */
    #climbs-table tr::before { content: ""; flex: 1 1 100%; order: 3; }
    #climbs-table td:nth-child(1) { flex: 1 1 auto; order: 1; font-weight: 600; }
    #climbs-table td:nth-child(4) { order: 2; }
    #climbs-table td:nth-child(2) { order: 4; font-size: 0.82rem; color: var(--muted); }
    #climbs-table td:nth-child(3) { order: 5; font-size: 0.82rem; color: var(--muted); }
    #climbs-table td:nth-child(5) { order: 6; margin-left: auto; font-size: 0.82rem; }

    /* Fuel plan summary — line 1: section + water + carbs; line 2: distance · arrival */
    #plan-summary .plan-table tr::before { content: ""; flex: 1 1 100%; order: 4; }
    #plan-summary .plan-table td:nth-child(1) { flex: 1 1 auto; order: 1; font-weight: 600; }
    #plan-summary .plan-table td:nth-child(4) { order: 2; }
    #plan-summary .plan-table td:nth-child(5) { order: 3; }
    #plan-summary .plan-table td:nth-child(2) { order: 5; font-size: 0.82rem; color: var(--muted); }
    #plan-summary .plan-table td:nth-child(3) { order: 6; margin-left: auto; font-size: 0.82rem; color: var(--muted); }
    #plan-summary .plan-table td:nth-child(3)::before { content: "arrive "; }

    /* Race Day plan — a card per stop, one concern per line:
         1  name (wraps as it must) · drop bag           edit / cutoff / remove
         2  crew marks — only when someone meets or hands off here
         3  dist · arrive ETA · temp
         4  cutoff pill — only when the stop has one
         5  water + carbs to carry
       The name cell wraps so a long stop name never crushes the crew pills
       and the controls never run off the right edge (a three-pill Leadville
       row used to push the cutoff clock past the screen). The arrival cell
       is display:contents so its cutoff can leave the ETA's line and take
       its own — inside a block it sat indented under the ETA, mid-row. Two
       invisible full-width items (::before/::after) are the line breaks; they
       are zero-height lines, so the space between lines rides on the items'
       own top margins rather than a row-gap the breaks would double. */
    #raceplan-table tr { row-gap: 0; }
    #raceplan-table tr::before { content: ""; flex: 1 1 100%; order: 5; }
    #raceplan-table tr::after { content: ""; flex: 1 1 100%; order: 7; }
    #raceplan-table td:nth-child(2), #raceplan-table .aid-eta, #raceplan-table td:nth-child(4),
    #raceplan-table .aid-cutoff, #raceplan-table .aid-dwell, #raceplan-table td:nth-child(5), #raceplan-table td:nth-child(6) { margin-top: 6px; }
    #raceplan-table td:nth-child(1) { flex: 1 1 100%; order: 1; display: flex; flex-wrap: wrap;
        align-items: center; column-gap: 6px; row-gap: 6px; font-weight: 600; }
    #raceplan-table td:nth-child(1) .aid-nm { flex: 1 1 0; min-width: 0; }
    #raceplan-table td:nth-child(1) .aid-bag { margin-left: 0; }
    #raceplan-table td:nth-child(1) .aid-actions { flex: 0 0 auto; margin-left: auto; }
    /* Renaming and removing stops is desk work — on a phone the two buttons
       cost a third of the name line. The cutoff clock stays: it is the one
       control a runner reaches for on race week, and the only way to set a
       cutoff on a stop that has none. */
    #raceplan-table .aid-edit, #raceplan-table .aid-rm { display: none; }
    #raceplan-table td:nth-child(1) .aid-crewline { flex: 1 1 100%; order: 9;
        display: flex; flex-wrap: wrap; align-items: center; column-gap: 6px; row-gap: 6px; }
    #raceplan-table .aid-crewline .aid-crew, #raceplan-table .aid-crewline .crew-io { margin-left: 0; }
    #raceplan-table td:nth-child(2) { order: 2; font-size: 0.82rem; color: var(--muted); }
    #raceplan-table td:nth-child(3) { display: contents; }
    #raceplan-table .aid-eta { order: 3; font-size: 0.82rem; color: var(--muted); }
    #raceplan-table .aid-eta::before { content: "arrive "; }
    #raceplan-table td:nth-child(4) { order: 4; font-size: 0.82rem; color: var(--muted); }
    #raceplan-table .aid-cutoff { order: 6; margin-top: 0; }
    /* The card is the full width on a phone, so the demand can take it. */
    #raceplan-table .aid-cutoff.cut-warn { max-width: 100%; }
    #raceplan-table .aid-dwell { order: 7; margin-top: 0; }
    #raceplan-table td:nth-child(5) { order: 8; }
    #raceplan-table td:nth-child(6) { order: 9; }
    /* Nothing to say, nothing shown: the "—" cells (Start's carry, a stop
       with no forecast) are noise once the column header is gone. */
    #raceplan-table td.plan-none { display: none; }
    /* The pacer's bar runs the full card, not just the name line. */
    #raceplan-table tr.leg-paced { box-shadow: inset 3px 0 0 var(--pc, var(--teal)); padding-left: 10px; }
    #raceplan-table tr.leg-paced td:first-child { box-shadow: none; }

    /* Pacing aid stations — line 1: checkpoint (edit controls right); line 2: distance · elapsed */
    #aid-table td:nth-child(1) { flex: 1 1 100%; order: 1; display: flex; align-items: center; }
    #aid-table td:nth-child(1) .aid-actions { margin-left: auto; }
    #aid-table td:nth-child(2) { order: 2; font-size: 0.85rem; color: var(--muted); }
    #aid-table td:nth-child(3) { order: 3; margin-left: auto; font-size: 0.85rem; color: var(--muted); }
    #aid-table td:nth-child(3)::before { content: "elapsed "; }

    /* Course Creator aid list — line 1: name + edit controls; line 2: distance */
    #lib-aid-table td:nth-child(1) { flex: 1 1 auto; order: 1; display: flex; align-items: center; }
    #lib-aid-table td:nth-child(3) { order: 2; margin-left: auto; }
    #lib-aid-table td:nth-child(2) { order: 3; flex: 1 1 100%; font-size: 0.85rem; color: var(--muted); }
}

/* ===== Mobile header compaction =====
   The desktop app-shell (≥861px) already trades the tall hero for a compact
   heading; phones — the least screen — were still getting the full-size one.
   Mirror it: small h1, no lead paragraph, tighter margins, so the first tool
   card lands inside the first viewport. (Action buttons like Race Day's
   "Plan a race" stay.) */
@media (max-width: 560px) {
    .hero { margin: 10px 0 16px; }
    .hero h1 { font-size: 1.5rem; line-height: 1.15; }
    .eyebrow { font-size: 0.72rem; margin-bottom: 6px; }
    .hero-sub { display: none; }
    .hero-cta { margin-top: 12px; }

    /* Panels: a touch less padding buys real column width at 375px. The
       .rd-section header band bleeds edge-to-edge via negative margins that
       must mirror the panel padding — keep them in lockstep. */
    .panel { padding: 18px; }
    .rd-section { padding-top: 14px; padding-bottom: 14px; }
    .rd-section > summary { margin: -14px -18px; padding: 13px 18px; }
    .rd-section:not([open]) > summary { margin-bottom: -14px; }
    .rd-section[open] > summary { margin-bottom: 14px; }

    /* Card headers: let the subtitle take its own line under the title instead
       of squeezing beside it ("HOW THE PACING WORKS grade-adjusted splits"). */
    .rd-section > summary { flex-wrap: wrap; row-gap: 2px; }
    .rd-section > summary .rd-sec-sub { flex: 1 1 100%; order: 10; margin-left: 35px; }
}

/* ===== Food bin: collapsible categories (details/summary, all widths) ===== */
.fp-bin-group > summary::-webkit-details-marker { display: none; }
.fp-bin-cat { list-style: none; cursor: pointer; user-select: none; }
.fp-bin-cat::after {
    content: '⌄'; margin-left: auto; color: var(--muted);
    font-size: 1rem; line-height: 1; transition: transform 0.18s ease;
}
.fp-bin-group[open] > .fp-bin-cat::after { transform: rotate(180deg); }
.fp-bin-count {
    font-size: 0.7rem; font-weight: 600; color: var(--muted);
    background: var(--glass-2); border: 1px solid var(--line);
    border-radius: var(--r-ctl); padding: 1px 8px; margin-left: 2px;
}
@media (max-width: 860px) {
    /* No scroll region inside the page scroll — the categories collapse instead. */
    .fp-bin { max-height: none; overflow: visible; padding-right: 0; }
    .fp-bin-cat { align-items: center; min-height: 44px; }
}

/* ===== Mobile pane merge (pairs with the nav.js module) ===== */
.merged-away { display: none !important; }

@media (max-width: 860px) {
    /* Stacked cards need breathing room — desktop's app-split grid gap only
       exists ≥861px, so phones were rendering the cards edge-to-edge. */
    body.split-page .app-split,
    body.split-page .split-left,
    body.split-page .split-right { display: flex; flex-direction: column; gap: 14px; }
    /* The column's own gap is the only spacing between cards. Two panels carry
       a legacy margin-bottom from the standalone fuel page (.fueling-plan and
       .coach, fuel.css above), which lands ON TOP of that gap: Fueling sat 36px
       from Gear where every other pair sat 14px. Desktop already zeroes these
       the same way a few blocks up; this is the phone half of that rule. */
    body.split-page .split-left > .panel,
    body.split-page .split-right > .panel { margin: 0; }

    /* A display-card body merged into its input card: divider between the
       inputs above and the map / plan / table below. */
    .rd-merged { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line); }

    /* The weather explorer card adopted into Conditions: flatten from a
       full panel to a sub-section of its host card. */
    .rd-merged .rd-section.panel {
        border: none; box-shadow: none; background: transparent;
        padding: 0; border-radius: 0;
    }
    .rd-merged .rd-section > summary {
        margin: 0; padding: 2px 0 10px; background: none; border-radius: 0;
    }
    .rd-merged .rd-section:not([open]) > summary { margin-bottom: 0; }
    .rd-merged .rd-section[open] > summary { margin-bottom: 8px; border-bottom: none; }
}

/* ===== Fullscreen elevation profile (trail-map.js createProfile expand) ===== */
.tg-elev-expand { margin-left: auto; }   /* right end of the overlay toggle bar */
.elev-canvas-wrap.elev-expanded {
    position: fixed; inset: 0; z-index: 9999;
    height: auto; max-height: none;
    background: var(--bg-1, #0a1a1c);
    padding: 58px 16px 22px;
}
body.elev-modal-open { overflow: hidden; }
.tg-elev-close {
    position: absolute; top: 10px; right: 10px; z-index: 2;
    width: 44px; height: 44px; border-radius: 50%;
    background: var(--glass-2); color: var(--ink); border: 1px solid var(--line);
    font-size: 1.1rem; line-height: 1; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
}
.tg-elev-close:hover { border-color: var(--edge-soft); background: var(--fill-hover); }
.tg-elev-hint {
    position: absolute; top: 22px; left: 16px; right: 70px;
    color: var(--muted); font-size: 0.82rem; display: none;
}
/* The hint only matters on a phone held upright. */
@media (orientation: portrait) and (max-width: 860px) {
    .elev-canvas-wrap.elev-expanded .tg-elev-hint { display: block; }
}

/* ===== Map feel pass: new shared controls (trail-map.js) ===== */
/* In-map toast — gesture hint, locate status. */
.tg-map-toast {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
    z-index: 900; pointer-events: none;
    background: rgba(4, 12, 10, 0.82); color: var(--ink);
    border: 1px solid var(--line); border-radius: var(--r-ctl);
    padding: 10px 18px; font-size: 0.88rem; font-weight: 600; white-space: nowrap;
    opacity: 0; transition: opacity 0.25s ease;
}
.tg-map-toast.show { opacity: 1; }

/* Distance markers along the route. */
.tg-mile-wrap { background: none; border: 0; }
.tg-mile {
    display: flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; border-radius: 50%;
    background: rgba(7, 18, 15, 0.88); color: var(--gold);
    border: 1.5px solid var(--gold);
    font-family: var(--mono); font-weight: 700; font-size: 0.62rem;
}
/* Touch screens: at least 24×24 (WCAG 2.2 target size); trail-map.js gives
   the Leaflet icon the same box so the badge stays centred on its mile. */
@media (pointer: coarse) {
    .tg-mile { width: 24px; height: 24px; font-size: 0.66rem; }
}

/* Tap-to-inspect popup + scale bar: dark-theme the Leaflet chrome. */
.tg-inspect .leaflet-popup-content-wrapper {
    background: rgba(7, 18, 15, 0.94); color: var(--ink);
    border: 1px solid var(--line); border-radius: var(--r-card); box-shadow: var(--shadow-pop);
}
.tg-inspect .leaflet-popup-content { margin: 9px 14px; font: 600 0.88rem/1.45 var(--body); }
.tg-inspect .leaflet-popup-content b { color: var(--gold); }
.tg-inspect .leaflet-popup-tip { background: rgba(7, 18, 15, 0.94); border: 1px solid var(--line); }
.leaflet-control-scale-line {
    background: rgba(7, 18, 15, 0.75); color: var(--muted);
    border-color: var(--line); font-size: 0.66rem;
}

/* ===== Interaction grammar (audit PR 4, re-cut by TG-282) =====
   One hover language for the whole product: interactive surfaces lift a touch
   and step the neutral ladder — never a coloured glow. Hover-capable pointers
   only; reduced motion keeps color changes but drops movement. */
@media (hover: hover) {
    details.rd-section {
        transition: border-color 0.18s ease, box-shadow 0.18s ease;
    }
    /* Sections no longer lift or glow in their tint on hover (TG-282): the
       coloured glow is gone and hover never wears a feature tint. */
    .export-btn, .estimate-btn, .rd-plan-btn, .fp-clear, .course-clear, .lib-manage, .lib-create-route {
        transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease,
            background 0.15s ease, color 0.15s ease;
    }
    /* Flat buttons lift, they don't glow — .export-btn/.rd-plan-btn keep their
       own outline hover (see the base rules). */
    .lib-create-route:hover { transform: translateY(-1px); }
    .export-btn.tonal:hover, .estimate-btn:hover, .lib-create-route:hover {
        box-shadow: var(--raise-2);
    }
    .export-btn:hover, .rd-plan-btn:hover { transform: translateY(-1px); }
}
@media (prefers-reduced-motion: reduce) {
    .export-btn:hover, .estimate-btn:hover, .rd-plan-btn:hover, .lib-create-route:hover { transform: none; }
}

/* Keyboard focus wears the one accent (TG-282). */
:where(a, button, summary, [role="button"], .fp-pill):focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* Digits line up in every data surface (arrival times stop wobbling on rerender).
   One declaration site for the whole file — the mono pass (TG-284) sets the face
   on each value class and adds its selector here rather than repeating the
   property a dozen times. */
.plan-table td, .plan-table th, .cmp-table td, .cmp-table th,
.cs-val, .metric-num, .kit-num, .fp-cov-sub, .fp-pill, .fp-pct, .fp-qty,
.rd-wx-cell, .rd-wx-day-chip, .summary-text, .carry-dist, .carry-load,
.lib-item-meta, .estimate-out {
    font-variant-numeric: tabular-nums;
}

/* ===== Cross-highlighting (audit PR 5) =====
   Hovering a table row answers on the map and elevation profile — and tapping
   a map marker flashes its row. */
.aid-marker { transition: transform 0.15s ease, box-shadow 0.15s ease; }
.aid-marker-wrap { z-index: 600; }
.aid-marker-wrap.aid-hover { z-index: 900 !important; }
.aid-marker-wrap.aid-hover .aid-marker {
    transform: scale(1.45);
    /* Ink, not white: the glow has to read on First Light's light topo too. */
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--ink) 25%, transparent), 0 0 18px 2px color-mix(in srgb, var(--ink) 35%, transparent);
}
@media (hover: hover) {
    .plan-table tbody tr { cursor: default; }
}
.plan-table tbody tr.row-flash {
    animation: tg-row-flash 1.6s ease;
}
@keyframes tg-row-flash {
    0%, 60% { background: rgba(255, 210, 63, 0.18); }
    100% { background: transparent; }
}
@media (prefers-reduced-motion: reduce) {
    .aid-marker { transition: none; }
    .plan-table tbody tr.row-flash { animation: none; background: rgba(255, 210, 63, 0.14); }
}

/* ===== Depth & page transitions (audit second wave) ===== */
/* A whisper of film grain keeps the big dark fields from reading flat.
   Inline SVG turbulence — no request, ~2% opacity. */
.backdrop::after {
    content: ""; position: absolute; inset: 0; pointer-events: none;
    opacity: 0.025;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(/%23n)'/%3E%3C/svg%3E");
}

/* Cross-fade between tool pages (same-origin MPA). Free in Chromium/Safari,
   gracefully nothing elsewhere. */
@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 0.18s; }
@media (prefers-reduced-motion: reduce) {
    @view-transition { navigation: none; }
}

/* ===== Mini map in the left rail (course loaded, desktop) =====
   The right pane scrolls independently, so once you're down at the race plan
   the big map is gone — the mini map keeps every hover/tap answer in view.
   It lives behind the rail's "Show map" disclosure (#rd-sum-map, raceday.html)
   now that the rail's main job is the plan summary; gpx.js builds it only while
   the disclosure is open. Mobile keeps the merged full map instead (pane
   merge), so it's ≥861px only. */
.mini-map-wrap { display: none; margin-top: 4px; }

/* ===== The rail's three ways to start (TG-300, TG-320) =====
   Each way in gets a label and one line of hint, so the rail itself is the
   explanation the welcome popover used to give from on top of it. With a
   course loaded the whole block goes (TG-320): the rail is the pinned map
   then, the topbar search switches courses, and Clear course brings the
   three ways back. The head swaps from "Run setup" to the course name in the
   same stroke. display: contents keeps the rows as the rail's own flex items,
   so its gap spaces them exactly as before the wrapper existed. */
.rd-start { display: contents; }
.rd-start-row { display: flex; flex-direction: column; gap: 6px; }
.rd-start-hint { color: var(--muted); font-size: 0.82rem; line-height: 1.45; margin: 0; }
/* The browse link moved inside the search row, so it is spaced by that row's
   gap rather than by the rail's old negative-margin pull. */
.rd-start-row > .creator-note { margin: 0; }
.rd-start-wiz #rd-start-wizard { width: 100%; }
body.has-course .rd-start { display: none; }
.rd-rail-course { display: none; }
body.has-course .rd-rail-setup { display: none; }
body.has-course .rd-rail-course { display: flex; }
/* The browse button stays visible with a course loaded — switching is the point. */
.tg-browse-btn { background: none; border: none; padding: 0; font: inherit; cursor: pointer; }
@media (min-width: 861px) {
    body.has-course .mini-map-wrap { display: block; }
    /* Sized for a glance under the summary, not for the whole rail. */
    #mini-map { height: clamp(200px, 28vh, 360px); }
}
.map-wrap.map-expanded #mini-map { height: 100vh; height: 100dvh; }

/* ===== Mini-map aid dots =====
   Full 26px "A" badges bury the route at mini-map size — render them as small
   colored dots that grow into the badge when their row is hovered (.aid-hover
   comes from the cross-highlighting fan-out). */
.aid-marker-wrap.aid-mini { display: flex; align-items: center; justify-content: center; }
.aid-mini .aid-marker {
    width: 11px; height: 11px; font-size: 0; border-width: 1.5px;
    transition: width 0.15s ease, height 0.15s ease, font-size 0.1s ease 0.05s,
        transform 0.15s ease, box-shadow 0.15s ease;
}
.aid-mini.aid-hover .aid-marker {
    width: 26px; height: 26px; font-size: 0.92rem;
    transform: scale(1.1);   /* the base .aid-hover scale(1.45) is too much on top of the grow */
}
@media (prefers-reduced-motion: reduce) {
    .aid-mini .aid-marker { transition: none; }
}


/* ===== Full-height Course card (Race Day) =====
   The Course card is the ONLY left card, so the pane doesn't scroll — the
   card scales to the screen instead. With no course loaded the dropzone grows
   to fill it; with one loaded the plan summary (raceday.css) sits at natural
   height and the optional mini map below it is clamp-sized. overflow-y:auto
   on the pane remains as a safety net for very short windows only. */
@media (min-width: 861px) {
    body.split-page .split-left > #rd-course[open] {
        flex: 1 1 auto; min-height: 0;
        display: flex; flex-direction: column;
    }
    /* Chrome wraps a details' children in an internal ::details-content box —
       the flex above only splits [summary | content box], so the content box
       itself must flex-fill and lay its children out as a column too. Kept as
       its own rule: browsers without the pseudo drop just this block. */
    body.split-page .split-left > #rd-course[open]::details-content {
        display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0;
    }
    body.has-course .mini-elev-wrap { display: block; }
    body.split-page:not(.has-course) .split-left #rd-course .dropzone { flex: 1 1 auto; }
}
/* Mini elevation profile under the mini map. */
.mini-elev-wrap { display: none; margin-top: 10px; }
.mini-elev-wrap[hidden] { display: none; }
.mini-elev-wrap .elev-canvas-wrap { height: 140px; }

/* Goal inputs at the top of the Pacing plan panel (the left card is retired). */
.pace-goal-row { display: flex; flex-wrap: wrap; gap: 12px 28px; align-items: flex-end;
    margin: 2px 0 10px; }
.pace-goal-row .field-block { margin: 0; }

/* ===== The rail slides away (TG-320, desktop) =====
   The drag handle that used to sit between the panes is gone: a runner who
   wants the plan full-width hides the rail instead. html.rd-rail-closed is
   set before first paint by the inline script in raceday.html's head and kept
   honest by raceday.js — never without a course loaded. The column animates
   between two minmax() tracks (the same shape at both ends is what lets the
   grid interpolate it) while the rail fades and slips left under it. The seam
   and its padding go too, or a 0px column would still show 19px of them. */
@media (min-width: 861px) {
    body.split-page .app-split { transition: grid-template-columns 0.2s ease, gap 0.2s ease; }
    html.rd-rail-closed body.split-page .app-split { grid-template-columns: minmax(0px, 0px) 1fr; gap: 0; }
    body.split-page .split-left {
        min-width: 0; overflow-x: hidden;
        transition: opacity 0.2s ease, transform 0.2s ease, padding-right 0.2s ease, border-color 0.2s ease, visibility 0s linear 0s;
    }
    html.rd-rail-closed body.split-page .split-left {
        opacity: 0; transform: translateX(-24px); visibility: hidden; pointer-events: none;
        padding-right: 0; border-right-color: transparent;
        transition-delay: 0s, 0s, 0s, 0s, 0.2s;
    }
}
@media (prefers-reduced-motion: reduce) {
    body.split-page .app-split, body.split-page .split-left { transition: none; }
}

/* ===== Compact conditions controls (Weather card) =====
   The adopted inputs read as one toolbar row, not a stacked form — start
   time + fetch, temp, humidity and acclimation wrap side by side. */
#wx-conditions .effort-col { flex-direction: row; flex-wrap: wrap; align-items: flex-end; gap: 12px 22px; }
#wx-conditions .effort-col > * + * { margin-top: 0; }
#wx-conditions .field-block { display: flex; flex-direction: column; gap: 6px; margin: 0; }
#wx-conditions .weather-row { flex-wrap: nowrap; gap: 8px; }
#wx-conditions .weather-row input { flex: 0 1 auto; width: 205px; padding: 8px 10px; }
#wx-conditions .estimate-btn { padding: 8px 12px; font-size: 0.84rem; }
#wx-conditions .field-grid { display: flex; gap: 12px; }
#wx-conditions .field-grid .field { gap: 6px; }
#wx-conditions .field-grid .field input { width: 88px; padding: 8px 10px; }
#wx-conditions .segmented button { flex: 0 0 auto; padding: 7px 14px; font-size: 0.8rem; }
/* The estimate line only earns space when it has something to say. */
#wx-conditions .weather-out { margin: 0; min-height: 0; }
#wx-conditions .weather-out:empty { display: none; }

/* Aid-station rename icon (icons.js). */
.aid-ico { width: 13px; height: 13px; vertical-align: -0.1em; }

/* ===== Upgrade dialog (billing) — flat outline cards, brand rules ===== */
.tg-upg-opts { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 14px 0 4px; }
.tg-upg-opt { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; text-align: left;
    padding: 14px; background: transparent; color: var(--ink); font: inherit; cursor: pointer;
    border: 1px solid var(--line); border-radius: var(--r-card); transition: border-color .15s, box-shadow .15s; }
.tg-upg-opt:hover { border-color: var(--edge); background: var(--fill-hover); }
.tg-upg-opt b { font-family: var(--mono); letter-spacing: .02em; }
.tg-upg-price { color: var(--accent); font-weight: 700; font-size: 1.15rem; }
.tg-upg-opt small { color: var(--muted); line-height: 1.4; }
.tg-upg-note { color: var(--muted); font-size: .84rem; margin: 10px 2px 0; }
.tg-upg-note a { color: var(--accent); }
@media (max-width: 520px) { .tg-upg-opts { grid-template-columns: 1fr; } }

/* ===== Aid stations edited in place (planner-5) =====
   gpx.js: a grip to drag (or Alt+↑/↓), the name and the mile as click
   targets that open an inline field, and a type chip set per stop. The
   chips draw their word from data-t so the cell's text stays the name.
   One accent on duty: a chip that is on, the field that is open, the
   line a dragged row will land on. */
#raceplan-table .aid-grip {
    display: inline-flex; align-items: center; justify-content: center; vertical-align: middle;
    width: 20px; height: 28px; margin: 0 4px 0 -4px; border-radius: var(--r-ctl);
    color: var(--muted); cursor: grab; touch-action: none; opacity: 0.55;
    transition: opacity var(--dur-ctl) var(--ease-snap), background var(--dur-ctl) var(--ease-snap);
}
#raceplan-table .aid-grip svg { width: 16px; height: 16px; fill: currentColor; }
#raceplan-table tr:hover .aid-grip, #raceplan-table .aid-grip:focus-visible { opacity: 1; }
#raceplan-table .aid-grip:hover { background: var(--fill-hover); color: var(--ink); }
#raceplan-table .aid-grip:focus-visible,
#raceplan-table .aid-nm[role="button"]:focus-visible,
#raceplan-table .aid-mi:focus-visible,
#raceplan-table .aid-type:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
#raceplan-table .aid-nm[role="button"], #raceplan-table .aid-mi { cursor: text; border-radius: 4px; }
#raceplan-table .aid-nm[role="button"]:hover, #raceplan-table .aid-mi:hover {
    background: var(--fill-hover); box-shadow: 0 0 0 3px var(--fill-hover); }
#raceplan-table .aid-inline {
    font: inherit; color: var(--ink); background: var(--bg-well);
    border: 1px solid var(--accent); border-radius: var(--r-ctl); padding: 3px 7px; min-height: 32px;
    width: min(220px, 100%);
}
#raceplan-table .aid-inline-mile { width: 7ch; font-family: var(--mono); font-variant-numeric: tabular-nums; }
#raceplan-table .aid-inline:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
#raceplan-table tr.aid-dragging { opacity: 0.55; }
body.aid-drag-on { user-select: none; -webkit-user-select: none; cursor: grabbing; }
#raceplan-table tr.aid-drop-before td { box-shadow: inset 0 2px 0 var(--accent); }
#raceplan-table tr.aid-drop-after td { box-shadow: inset 0 -2px 0 var(--accent); }
#raceplan-table .aid-types { display: inline-flex; flex-wrap: wrap; gap: 3px; margin-left: 8px; vertical-align: middle; }
#raceplan-table .aid-type {
    min-height: 22px; padding: 0 7px; border-radius: var(--r-ctl);
    border: 1px dashed var(--line); background: none; color: var(--muted); cursor: pointer;
    font: 600 0.68rem/1 var(--body); letter-spacing: 0.02em;
    transition: background var(--dur-ctl) var(--ease-snap), color var(--dur-ctl) var(--ease-snap), border-color var(--dur-ctl) var(--ease-snap);
}
#raceplan-table .aid-type::before { content: attr(data-t); }
#raceplan-table .aid-type:hover { color: var(--ink); border-color: var(--edge-soft); }
#raceplan-table .aid-type.on {
    border-style: solid; border-color: color-mix(in srgb, var(--accent) 45%, transparent);
    color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent);
}
/* Quiet until wanted: the chips that are off show on the row's hover, while
   it is being edited or keyboard-focused, and always where there is no hover. */
@media (hover: hover) {
    #raceplan-table .aid-type:not(.on) { display: none; }
    #raceplan-table tr:hover .aid-type, #raceplan-table tr:focus-within .aid-type,
    #raceplan-table tr.aid-editing .aid-type { display: inline-block; }
}
.aid-paste-link { margin: 10px 0 0; font-size: 0.85rem; color: var(--muted); }
.aid-paste-link a { color: var(--accent); }
@media (max-width: 600px) {
    #raceplan-table td:nth-child(1) .aid-types { flex: 1 1 100%; order: 10; margin: 6px 0 0; }
    #raceplan-table .aid-type { min-height: 44px; min-width: 44px; padding: 0 10px; }
    #raceplan-table .aid-grip { width: 32px; height: 44px; opacity: 0.8; }
}
@media (prefers-reduced-motion: reduce) {
    #raceplan-table .aid-grip, #raceplan-table .aid-type { transition: none; }
}

/* /launch-beta.css */
/* The launch offer extends the shared shell, palette and typography. */
.tg-launch-note { font: 400 .88rem/1.55 var(--body); color: var(--ink); background: var(--bg-1); border: 1px solid var(--line); border-radius: var(--r-card); padding: 12px 16px; margin: 12px 0; }
.tg-launch-note a { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }
.tg-beta-label { display: none; }
html[data-launch-beta="true"] .tg-beta-label,
html[data-launch-beta="true"] .tg-plan-offline::after { display: inline-block; font: 500 var(--mono-cap)/1.3 var(--mono); text-transform: uppercase; letter-spacing: .05em; color: var(--muted); border: 1px solid var(--edge-soft); border-radius: var(--r-ctl); padding: 2px 5px; margin-left: 6px; }
html[data-launch-beta="true"] .tg-plan-offline::after { content: "Beta"; }
.tg-beta-pricing .pr-grid { margin-top: 24px; }
.tg-beta-pricing .pr-card { background: var(--bg-1); }
.tg-beta-pricing .export-btn { min-height: 44px; }
.tg-beta-pricing .info-tldr { margin: 24px 0; }
.tg-beta-pricing > .info-card { margin-top: 24px; padding: 22px; background: var(--bg-1); border: 1px solid var(--line); border-radius: var(--r-card); }
@media print { .tg-launch-note, .tg-beta-label { display: none !important; } }

html[data-launch-beta="true"] .wordmark .beta-pill { font: 500 var(--mono-cap)/1.3 var(--mono); text-transform: uppercase; letter-spacing: .04em; color: var(--muted); border: 1px solid var(--edge-soft); border-radius: var(--r-ctl); padding: 3px 5px; margin-left: 8px; }

/* Pricing during launch: every price shown, each paid card saying it's free
   until the launch window closes. The line is the accent — it is the offer —
   and sits under the price it qualifies, never in place of it. */
.tg-beta-pricing .pr-launch { font: 600 .84rem/1.4 var(--body); color: var(--accent); margin: -2px 0 12px; }
.tg-beta-pricing .pr-crew-note { color: var(--muted); font-size: .92rem; line-height: 1.5; margin: 14px 2px 0; }
.tg-beta-pricing .pr-dayblock .pr-day { margin-top: 14px; }

