/* ==========================================================================
   GPS Tools (com_gpstools) · extension bridge · Studio community kit
   --------------------------------------------------------------------------
   Sections 1-5 are kit-owned and byte-identical in Vesper, Quorum and Mimeo.
   Edit them in template-studio/kit/community/tpl/media/css/ext/gpstools.css and
   run sync-kit.mjs for all three templates. Section 6 belongs to the template.

   Loaded by PageContext::useExtension('gpstools') on pages with a GPS island
   (option com_gpstools, or the com_gpstools.styles asset: {gpstrack} and
   {gpstracks} embeds) and by the chromes around mod_gpstools_* modules.
   Bootstrap stays ON: every GPS utility carries !important at 0,2,0.

   Islands: a PHP host div.gpstools-react-component[data-gps-component] holding a
   JS-made div.gpstools-react-wrapper.gpstools-scope[data-gps-theme]. GPS mirrors
   <html data-color-scheme> into html[data-gps-theme].

   The internal palette is hard-coded Tailwind stone/emerald with !important and
   cannot be re-themed; only the wrapper ground, text, borders, focus, tables
   and Leaflet read the space-separated RGB triplets mapped below. Relative
   colour syntax (rgb(from ...)) derives them from the hex tokens; browsers
   without it keep GPS's own neutral triplets (the @supports guard).
   ========================================================================== */

/* 1. Variable map ----------------------------------------------------------- */

@supports (color: rgb(from red r g b)) {
    /* 0,2,1 beats GPS's light (0,1,0) and dark (0,2,0) blocks; the tokens
       switch with the page scheme, so one block serves both. */
    html .gpstools-react-wrapper.gpstools-scope {
        --color-background: from var(--ec-bg) r g b;
        --color-surface: from var(--ec-surface) r g b;
        --color-foreground: from var(--ec-fg) r g b;
        --color-muted: from var(--ec-fg-2) r g b;
        --color-border: from var(--ec-border) r g b;
        --color-accent: from var(--ts-link) r g b;
        --color-accent-muted: from var(--ec-surface-2) r g b;
    }
}

html .gpstools-react-wrapper {
    --radius-sm: var(--ec-btn-radius);
    --radius-md: var(--ec-btn-radius);
    --radius-lg: var(--ec-radius);
}

/* Native controls and scrollbars follow the page scheme (GPS pins light). */
html[data-color-scheme="dark"] .gpstools-react-wrapper {
    color-scheme: dark;
}

/* Leaflet controls: maps.css is injected at the end of <head> at runtime and
   wins ties, hence the island-scoped selectors (0,2,1 and up). */
.gpstools-scope .leaflet-bar a,
.gpstools-scope .leaflet-bar a:hover {
    border-color: var(--ec-border);
    background-color: var(--ec-surface);
    color: var(--ec-fg);
}

.gpstools-scope .leaflet-bar a:hover {
    background-color: var(--ec-surface-2);
}

.gpstools-scope .leaflet-bar {
    border-color: var(--ec-border);
}

/* The ground under the tiles (seen while they load, offline, or at the edges):
   stock Leaflet paints #ddd in both schemes. */
.gpstools-scope .leaflet-container {
    background: var(--ec-surface-2);
}

/* 0,3,0: Leaflet's own .leaflet-container .leaflet-control-attribution (0,2,0,
   injected later) would keep its white chip under scheme-coloured text. */
.gpstools-scope .leaflet-container .leaflet-control-attribution {
    background: color-mix(in srgb, var(--ec-surface) 92%, transparent);
    color: var(--ec-fg);
}

.gpstools-scope .leaflet-container .leaflet-control-attribution a {
    color: var(--ts-link);
}

/* Dark tiles: PageContext adds body.ts-gps-lighttiles when the configured tile
   provider is a light one (anything but stadia_smooth_dark / carto_dark); in the
   dark scheme the raster tiles are inverted, the route overlay is not. */
html[data-gps-theme="dark"] .ts-gps-lighttiles .gpstools-scope .leaflet-tile-pane {
    filter: invert(1) hue-rotate(180deg) brightness(0.85) contrast(0.9);
}

/* 2. Containment ------------------------------------------------------------ */

/* GPS's Preflight prints before Bootstrap Reboot's later rules only in part;
   inside the islands the app expects Preflight, so Reboot's link underline,
   heading sizes and list/paragraph margins are undone (0,0,1, loaded last). */
:where(.gpstools-scope) a {
    color: inherit;
    text-decoration: inherit;
}

:where(.gpstools-scope) :is(h1, h2, h3, h4, h5, h6) {
    margin: 0;
    font-size: inherit;
    font-weight: inherit;
    line-height: inherit;
}

:where(.gpstools-scope) :is(p, ul, ol, dl, blockquote, figure) {
    margin: 0;
}

:where(.gpstools-scope) :is(ul, ol) {
    padding: 0;
    list-style: none;
}

/* Rich text in route and track descriptions: the reset above zeroes its margins; restore a flow rhythm. */
:where(.gpstools-scope) .prose > * + * {
    margin-block-start: 0.85em;
}

:where(.gpstools-scope) .prose :is(ul, ol) {
    padding-inline-start: 1.5em;
    list-style: disc;
}

:where(.gpstools-scope) .prose ol {
    list-style: decimal;
}

:where(.gpstools-scope) .prose blockquote {
    padding-inline-start: 1em;
    border-inline-start: 3px solid var(--ec-border);
}

/* A {gpstrack}/{gpsroute} embed in article text keeps the text's block rhythm (the island zeroes
   its margins; the Community Quiz embed has the same 1.5rem). */
.ts-prose .gpstools-react-component.gpstools-react-component {
    margin-block: 1.5rem;
}

/* 3. Leak neutralisers ------------------------------------------------------ */

/* None. GPS's global Preflight and .container are element-level or generic
   names: the template's own chrome declares these properties explicitly
   (contract 5.5 item 3), so nothing is re-declared here. */

/* 4. Default module markup -------------------------------------------------- */

/* mod_gpstools_tracks prints an inline <style> reading Bootstrap variables with
   Bootstrap-light fallbacks; the module root supplies them from the tokens so the
   list also reads right where Bootstrap is off. Its badges and empty alert are
   Bootstrap classes, themed by the bridge on Bootstrap pages. */
.gpstools-tracks {
    --bs-border-color: var(--ec-border);
    --bs-card-bg: var(--ec-surface);
    --bs-primary: var(--ts-link);
    --bs-secondary-color: var(--ec-fg-2);
}

.gpstools-tracks .gpstools-track-title {
    font-family: var(--ec-font-display);
    font-weight: 700;
    line-height: 1.3;
}

.gpstools-tracks .gpstools-track-title a {
    color: var(--ec-fg);
}

.gpstools-tracks .gpstools-track-title a:hover {
    color: var(--ts-link);
}

.gpstools-tracks .gpstools-track-thumbnail {
    overflow: clip;
    border-radius: var(--ec-btn-radius);
    background: var(--ec-surface-2);
}

.gpstools-tracks .gpstools-track-thumbnail img {
    display: block;
}

.gpstools-tracks-cards .gpstools-track-item,
.gpstools-tracks-grid .gpstools-track-item {
    border-radius: var(--ec-radius);
}

.gpstools-tracks-cards .gpstools-track-thumbnail {
    border-radius: 0;
}

.gpstools-tracks .gpstools-track-stats {
    flex-wrap: wrap;
    gap: 0.25rem 1rem;
    font-variant-numeric: tabular-nums;
}

.gpstools-tracks .badge {
    border-radius: var(--ec-btn-radius);
}

/* The card grid keeps two columns down to 480px, too narrow for a sidebar or a
   phone column: one card per row below 40rem of viewport or inside a narrow
   column (auto-fill on the track width). */
.gpstools-tracks-cards,
.gpstools-tracks-grid {
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 13rem), 1fr)) !important;
}

/* Bootstrap-off pages: the module's badges and empty state without Bootstrap. */
.ts-bs-off .gpstools-tracks .badge {
    display: inline-block;
    padding: 0.2em 0.55em;
    background: var(--ec-surface-2);
    color: var(--ec-fg);
    font-size: 0.8125rem;
    font-weight: 700;
    line-height: 1.3;
}

/* mod_gpstools_map: its inline <style> sets --gpsm-* on an ID and switches on
   html[data-color-scheme]; !important on the module class wins over both. */
.mod-gpstools-map {
    --gpsm-bg: var(--ec-surface-2) !important;
    --gpsm-surface: var(--ec-surface) !important;
    --gpsm-ink: var(--ec-fg) !important;
    --gpsm-ink-muted: var(--ec-fg-2) !important;
    --gpsm-border: var(--ec-border) !important;
    --gpsm-accent: var(--ts-link) !important;
}

/* mod_gpstools_categories: six of its icon classes do not exist in Joomla's
   Font Awesome 6 build (they render blank). The build prints
   [class*=" icon-"]::before { content: var(--fa) }, so the glyph is supplied
   as --fa (Font Awesome 6 Free solid code points). */
.mod-gpstools-categories .icon-bicycle {
    --fa: "\f206";
}

.mod-gpstools-categories .icon-hiking {
    --fa: "\f6ec";
}

.mod-gpstools-categories .icon-mountain {
    --fa: "\f6fc";
}

.mod-gpstools-categories .icon-walk {
    --fa: "\f554";
}

.mod-gpstools-categories .icon-building {
    --fa: "\f1ad";
}

.mod-gpstools-categories .icon-trending-up {
    --fa: "\e098";
}

.mod-gpstools-categories .mod-list-icon {
    font-weight: 900;
}

/* Its stylesheet hard-codes Bootstrap greys, a light hover and a blue focus
   ring, with a dark block at 0,4,1 (:root[data-color-scheme="dark"] ...);
   0,4,2 wins in both schemes wherever the module's CSS prints. */
html:root[data-color-scheme] .mod-gpstools-categories .mod-list a {
    min-block-size: 44px;
    border-radius: var(--ec-btn-radius);
    color: var(--ec-fg);
}

html:root[data-color-scheme] .mod-gpstools-categories .mod-list a:hover {
    background-color: var(--ec-surface-2);
    color: var(--ec-fg);
}

html:root[data-color-scheme] .mod-gpstools-categories .mod-list a .mod-list-icon {
    color: var(--ec-fg-2);
}

html:root[data-color-scheme] .mod-gpstools-categories .mod-list a:focus-visible {
    outline: var(--ts-focus-width, 2px) solid var(--ts-focus);
    outline-offset: -2px;
}

/* 5. Page frame ------------------------------------------------------------- */

/* The host keeps a 1rem radius and, in the dark scheme, a stone gradient behind
   the island (and before it mounts): both give way to the template ground and
   corner. */
html:root .gpstools-react-component {
    border-radius: var(--ec-radius);
    background: none;
}

html .gpstools-react-wrapper {
    border-radius: var(--ec-radius);
}

/* Focus: GPS draws a 1px accent outline on links and a 1px stone ring on its
   fields, and .outline-none / focus-visible:outline-none (0,2,0 !important)
   clear the outline. Every control and link in the island takes the template
   ring (0,4,1 !important; WCAG 2.4.7). */
html .gpstools-react-wrapper.gpstools-scope :is(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
    outline: var(--ts-focus-width, 2px) solid var(--ts-focus) !important;
    outline-offset: 2px !important;
}

/* Keep that ring whole: the list header clips only its decor layers (inset-0,
   rounded like it), so it can show overflow; controls flush with another
   clipping box (the sort group) take the ring inside; a truncating meta
   row gets room for it without moving its text. */
html .gpstools-scope header.overflow-hidden {
    overflow: visible !important;
}

html .gpstools-react-wrapper.gpstools-scope .overflow-hidden:not(header, article) :is(a, button, input, select):focus-visible {
    outline-offset: calc(-1 * var(--ts-focus-width, 2px)) !important;
}

/* The card's map link is covered by its own positioned tiles: ring the card. */
html .gpstools-scope article.overflow-hidden:has(> a:first-child:focus-visible) {
    outline: var(--ts-focus-width, 2px) solid var(--ts-focus);
    outline-offset: 2px;
}

html .gpstools-scope .truncate:has(a) {
    margin: -6px;
    padding: 6px;
}

/* @ts-kit section-6 begin: 6. Design skin (template-owned; sync-kit.mjs keeps everything between these two markers) */
/* Quorum (§6.17): square cells, no shadows or gradients, Big Shoulders titles and figures, the route
   in the accent over grey tiles; the app's stone surfaces take the board's in dark. */
/* GPS marks its utilities !important (.rounded-2xl, .shadow-sm, .bg-gradient-to-br, .text-2xl …),
   so the skin answers with !important at 0,2,0 and up. People and waypoints stay round: only
   rounded-full boxes with inline padding (chips, pills) are squared. */
.gpstools-scope.gpstools-scope :is([class*="rounded-sm"], [class~="rounded"], [class*="rounded-md"], [class*="rounded-lg"], [class*="rounded-xl"], [class*="rounded-2xl"], [class*="rounded-3xl"], [class*="rounded-t-"], [class*="rounded-b-"], [class*="rounded-l-"], [class*="rounded-r-"], [class*="rounded-["]), .gpstools-scope.gpstools-scope [class~="rounded-full"]:is([class*="px-"], [class*="pl-"]), .gpstools-scope.gpstools-scope :is(input, select, textarea, button) { border-radius: 0 !important; }
.gpstools-scope.gpstools-scope [class~="rounded-full"][class~="h-1"], .gpstools-scope.gpstools-scope :has(> .leaflet-container), .gpstools-scope.gpstools-scope .leaflet-bar a { border-radius: 0 !important; }
/* 9px caps labels, waypoint numbers and faded 10px units (km/h) at the 12px floor; the units and
   the next road-book step (a link, 40% faded) at full strength (AA). */
.gpstools-scope.gpstools-scope :is([class~="text-[9px]"], [class~="text-[10px]"][class~="opacity-60"]) { font-size: 0.75rem !important; }
.gpstools-scope.gpstools-scope :is([class~="text-[10px]"][class~="opacity-60"], [class~="opacity-40"][class*="scale-"]) { opacity: 1 !important; color: var(--ec-fg-2) !important; }
.gpstools-scope.gpstools-scope :is([class*="shadow"], [class*="ring-"]):not(:focus-visible) { box-shadow: none !important; }
.gpstools-scope.gpstools-scope [class*="bg-gradient"] { background-image: none !important; background-color: var(--ec-surface) !important; }
/* A primary gradient is an action (the comment Send button): a Quorum primary, not a surface. */
.gpstools-scope.gpstools-scope [class*="bg-gradient"][class*="from-primary"] { background-color: var(--ec-accent) !important; color: var(--ec-accent-fg) !important; }
.gpstools-scope.gpstools-scope [class*="bg-gradient"][class*="from-primary"]:not(:disabled):hover { background-color: var(--ts-btn-primary-hover-bg) !important; color: var(--ts-btn-primary-hover-fg) !important; }
/* Tracks head: title on the ground at the container edge under the 2px rule (§9). */
.gpstools-scope.gpstools-scope :is(header > [class~="absolute"][class~="inset-0"][style*="background-image"], .gpstools-tracks-page > header > .inset-0) { display: none !important; }
.gpstools-scope.gpstools-scope .gpstools-tracks-page > header > .relative { padding-inline: 0 !important; }
.gpstools-scope.gpstools-scope .gpstools-tracks-page > header { border-block-start: var(--q-rule-w) solid var(--q-rule); }
.gpstools-scope.gpstools-scope h1 { font-family: var(--ec-font-display) !important; font-size: clamp(2.5rem, 2.3vw + 1.9rem, 3.5rem) !important; font-weight: 700 !important; line-height: 1 !important; letter-spacing: 0 !important; }
/* The tracks list as a gap-ruled board: 1px hairlines between square cells, no floating cards. */
.gpstools-scope.gpstools-scope [class~="grid"]:has(> article) { gap: var(--q-hair-w) !important; }
.gpstools-scope.gpstools-scope [class~="grid"] > article { border: 0 !important; outline: var(--q-hair-w) solid var(--ec-border); background-color: var(--ec-surface) !important; }
.gpstools-scope.gpstools-scope article h3 { font-family: var(--ec-font-body) !important; font-size: 1.125rem !important; font-weight: 600 !important; line-height: 1.3 !important; }
/* Metadata never under 14px (design spec §4.2); the figures in mono. */
.gpstools-scope.gpstools-scope :is([class~="text-xs"], [class~="text-[10px]"], [class~="text-[11px]"]) { font-size: 0.875rem !important; line-height: 1.35 !important; }
.gpstools-scope.gpstools-scope article [class~="border-t"] [class~="text-xs"] { font-family: var(--q-font-mono) !important; }
/* Thumbnails are raster images with the route baked in by GPS Tools: shown in greys, so the map
   stays neutral and the route reads as the ink line (the live maps draw it in the accent). */
.gpstools-scope.gpstools-scope img[src*="/thumbnails/"] { filter: grayscale(1) contrast(1.15); }
.gpstools-scope.gpstools-scope h3 { font-weight: 600; }
/* The headline figures (distance, gain, loss, time) as poster numerals; the app's utilities are
   !important, hence the size and weight here. */
.gpstools-scope.gpstools-scope span[class~="tabular-nums"][class~="text-lg"] { font-family: var(--ec-font-display); font-size: 2rem !important; font-weight: 800 !important; line-height: 0.9 !important; }
.gpstools-scope.gpstools-scope .leaflet-overlay-pane path[stroke="#3B82F6"] { stroke: var(--ec-accent); }
.gpstools-scope.gpstools-scope .leaflet-overlay-pane path[stroke="#000000"] { stroke: var(--q-rule); }
.gpstools-scope.gpstools-scope .leaflet-tile-pane { filter: grayscale(1) contrast(0.9) brightness(1.05); }
/* 0,4,2: wins over the kit's inverted-tiles filter (0,4,1) so dark tiles are grey too. */
html[data-color-scheme="dark"] body .gpstools-scope.gpstools-scope .leaflet-tile-pane { filter: grayscale(1) invert(1) contrast(0.85) brightness(0.9); }
.gpstools-scope.gpstools-scope .leaflet-bar, .gpstools-scope.gpstools-scope .leaflet-bar a { border-radius: 0; box-shadow: none; }
html[data-gps-theme="dark"] .gpstools-scope.gpstools-scope :is([class~="dark:bg-stone-900"], [class~="dark:bg-stone-900/80"], [class~="dark:bg-stone-900/95"]) { background-color: var(--ec-surface) !important; }
html[data-gps-theme="dark"] .gpstools-scope.gpstools-scope :is([class~="dark:bg-stone-800"], [class~="dark:bg-stone-800/50"], [class~="dark:bg-stone-800/30"]) { background-color: var(--ec-surface-2) !important; }
html[data-gps-theme="dark"] .gpstools-scope.gpstools-scope :is([class~="dark:border-stone-800"], [class~="dark:border-stone-700"]) { border-color: var(--ec-border) !important; }
/* Contrast (WCAG 1.4.3): the route cards' stone meta text (2.5:1 light, 3.7:1 dark) takes the
   quiet text token, and the difficulty chips (emerald, amber, rose on their tints) take the
   success, warning and danger pairs. */
.gpstools-scope.gpstools-scope :is(.text-stone-400, .text-stone-500, [class~="dark:text-stone-400"], [class~="dark:text-stone-500"]) { color: var(--ec-fg-2) !important; }
.gpstools-scope.gpstools-scope .bg-emerald-50[class*="text-emerald-"] { background-color: var(--q-success-soft) !important; color: var(--q-success) !important; }
.gpstools-scope.gpstools-scope .bg-amber-50[class*="text-amber-"] { background-color: var(--q-warning-soft) !important; color: var(--q-warning) !important; }
/* Yellow is rationed to the signal token (design spec §1.8): the Featured chip and the featured
   star badge on the tracks board become neutral square tags, and the badge gets its word, so the
   meaning never rides on an amber fill and a white star (2.1:1). The label comes from the
   template language file (head partial: --q-l-featured). */
.gpstools-scope.gpstools-scope :is([class~="bg-amber-100"][class~="text-amber-700"], [class~="bg-amber-500/90"]) { gap: 0.375rem !important; padding: 0.25rem 0.5rem !important; background-color: var(--ec-surface-2) !important; color: var(--ec-fg) !important; font-size: 0.875rem !important; font-weight: 600 !important; line-height: 1 !important; }
/* The app's globals.css makes every span on the track page inline (!important), which stacks the
   chip's star over its word inside the flex row: one line, as tall as its sibling tags. */
.gpstools-scope.gpstools-scope [class~="bg-amber-100"][class~="text-amber-700"] { display: inline-flex !important; line-height: 1.35 !important; }
.gpstools-scope.gpstools-scope [class~="bg-amber-100"][class~="text-amber-700"] > svg { display: inline-block; }
/* The selected metric is ink in light; in dark the surface-2 map would make it the stats panel's
   colour, so it keeps a 2px accent edge. */
html[data-gps-theme="dark"] .gpstools-scope.gpstools-scope [class~="bg-stone-900"][class~="dark:bg-stone-800"] { box-shadow: inset 0 0 0 2px var(--ec-accent); }
.gpstools-scope.gpstools-scope [class~="bg-amber-500/90"]::after { content: var(--q-l-featured, "Featured"); }
.gpstools-scope.gpstools-scope [class~="text-amber-500"] { color: var(--ec-fg-2) !important; }
.gpstools-scope.gpstools-scope .bg-rose-50[class*="text-rose-"] { background-color: var(--q-danger-soft) !important; color: var(--q-danger) !important; }
/* @ts-kit section-6 end */
