*, *::before, *::after {
    box-sizing: border-box;
}

html, body {
    margin: 0;
    padding: 0;
}

body {
    background: var(--color-bg);
    color: var(--color-ink);
    font-family: var(--font-body);
    font-size: 1rem;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
    font-family: var(--font-display);
    font-weight: 600;
    line-height: 1.15;
    margin: 0 0 var(--space-3);
    color: var(--color-ink);
}

h1 {
    font-size: clamp(2.25rem, 5vw + 1rem, 3.75rem);
    font-weight: 500;
}

h2 {
    font-size: clamp(1.75rem, 3vw + 1rem, 2.5rem);
}

h3 {
    font-size: 1.35rem;
}

p {
    margin: 0 0 var(--space-3);
}

a {
    color: var(--color-brand);
    text-decoration: none;
}

    a:hover {
        text-decoration: underline;
    }

img {
    max-width: 100%;
    display: block;
}

button {
    font-family: inherit;
}

/* Layout helpers */
.container {
    width: 100%;
    max-width: var(--content-max);
    margin: 0 auto;
    padding: 0 var(--space-4);
}

.section {
    padding: var(--space-6) 0;
}

    .section--tight {
        padding: var(--space-5) 0;
    }

.section-heading {
    max-width: 640px;
    margin: 0 0 var(--space-5);
}

    .section-heading p {
        color: rgba(23, 20, 18, 0.7);
        margin: 0;
    }

/* Utility / label text — route markers, tags, mile-markers */
.label {
    font-family: var(--font-mono);
    font-size: 0.75rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-brand);
}

.marker {
    font-family: var(--font-mono);
    font-size: 0.85rem;
    color: var(--color-terracotta);
}

/* Buttons */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    font-family: var(--font-body);
    font-weight: 600;
    font-size: 0.95rem;
    padding: 0.85rem 1.6rem;
    border-radius: var(--radius-sm);
    border: 1px solid transparent;
    cursor: pointer;
    transition: transform 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
    text-decoration: none;
    line-height: 1;
}

.btn--big {
    padding: 1.1rem 2.2rem;
    font-size: 1.05rem;
    box-shadow: var(--shadow-lift);
}

    .btn--big:hover {
        transform: translateY(-1px);
    }

    .btn:hover {
        text-decoration: none;
        transform: translateY(-2px);
        box-shadow: var(--shadow-lift);
    }

    .btn:active {
        transform: translateY(0);
        box-shadow: none;
    }

.btn--primary {
    background: var(--color-teal);
    color: var(--color-off-white);
}

    .btn--primary:hover {
        background: #0e3c41;
    }

.btn--whatsapp {
    background: #25D366;
    color: #0b3d20;
}

    .btn--whatsapp:hover {
        background: #1fbd5a;
    }

/* Email, given the same weight as WhatsApp beside it — solid teal, icon and all. */
.btn--email {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: var(--color-teal);
    color: var(--color-off-white);
}

    .btn--email:hover {
        background: #0e3c41;
        color: var(--color-off-white);
    }

.btn--outline {
    background: transparent;
    border-color: var(--color-ink);
    color: var(--color-ink);
}

    .btn--outline:hover {
        background: var(--color-ink);
        color: var(--color-off-white);
    }

.btn--gold {
    background: var(--color-gold);
    color: var(--color-near-black);
}

    .btn--gold:hover {
        background: #a8804f;
    }

/* Filter chips — global, not scoped: the routes list, the route finder, the
   Plan Your Trip wizard and the admin trip-request filters all use these. They
   lived in RoutesList.razor.css until the finder shipped rendering them as bare
   browser buttons, which is what scoped CSS does to a shared class. */
.chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.chip {
    font-family: var(--font-mono);
    font-size: 0.8rem;
    letter-spacing: 0.04em;
    background: #fff;
    border: 1px solid rgba(23, 20, 18, 0.15);
    color: var(--color-ink);
    padding: 0.55rem 1.1rem;
    border-radius: 999px;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease, transform 0.15s cubic-bezier(0.34, 1.56, 0.64, 1);
}

    .chip:hover {
        border-color: var(--color-teal);
        transform: translateY(-1px);
    }

.chip--active {
    background: var(--color-teal);
    border-color: var(--color-teal);
    color: var(--color-off-white);
    transform: scale(1.05);
}

/* Route map pins and popups — global, not scoped: Leaflet injects this markup
   into its own container, so it never carries a component's scope attribute. */

/* Standard OpenStreetMap tiles are bright and busy; this mutes and warms them
   toward the site's sand palette so the teal route line reads first. Only the
   tile layer is filtered — the line and pins keep their true colours. */
.route-live-map .leaflet-tile-pane {
    filter: saturate(0.55) sepia(0.18) brightness(1.03) contrast(0.95);
}

.route-pin__dot {
    display: block;
    width: 14px;
    height: 14px;
    margin: 2px;
    border-radius: 50%;
    border: 2px solid #fff;
    box-shadow: 0 1px 4px rgba(23, 20, 18, 0.45);
}

.leaflet-popup-content-wrapper {
    border-radius: var(--radius-sm);
    font-family: var(--font-body);
}

.leaflet-popup-content {
    margin: 0.6rem 0.9rem;
    font-size: 0.9rem;
    line-height: 1.45;
}

.route-pin__sub {
    font-family: var(--font-mono);
    font-size: 0.7rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-teal);
}

.leaflet-container {
    font-family: var(--font-body);
    background: rgba(21, 82, 89, 0.06);
}

    .leaflet-container a {
        color: var(--color-teal);
    }

/* Cards */
.card {
    background: #fff;
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    overflow: hidden;
    transition: transform 0.25s ease, box-shadow 0.25s ease;
}

    .card:hover {
        transform: translateY(-4px);
        box-shadow: var(--shadow-lift);
    }

/* Photo placeholders — swapped for real photos as they're supplied */
.photo-placeholder {
    display: flex;
    align-items: flex-end;
    background: linear-gradient(120deg, var(--color-teal) 0%, var(--color-terracotta) 50%, var(--color-teal) 100%);
    background-size: 220% 220%;
    animation: driftGradient 9s ease-in-out infinite;
    border-radius: var(--radius-md);
    overflow: hidden;
    position: relative;
}

    .photo-placeholder .label {
        color: var(--color-off-white);
        background: rgba(23, 20, 18, 0.35);
        padding: 4px 10px;
        margin: var(--space-2);
        border-radius: var(--radius-sm);
    }

@keyframes driftGradient {
    0%, 100% {
        background-position: 0% 50%;
    }

    50% {
        background-position: 100% 50%;
    }
}

/* Route card grid — used on Home and the Routes list page */
.route-card-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-4);
}

@media (max-width: 960px) {
    .route-card-grid {
        grid-template-columns: 1fr 1fr;
    }
}

@media (max-width: 640px) {
    .route-card-grid {
        grid-template-columns: 1fr;
    }
}

/* Focus visibility */
:focus-visible {
    outline: 2px solid var(--color-teal);
    outline-offset: 2px;
}

/* ---------- Motion system ---------- */

/* Load-in entrance — staggered fade/rise for above-the-fold content that's
   already in view on page load (heroes), where scroll-reveal wouldn't fire
   until the user scrolls away and back. Not scroll-triggered. */
@keyframes heroEnter {
    from {
        opacity: 0;
        transform: translateY(18px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.hero-enter {
    opacity: 0;
    animation: heroEnter 0.8s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

.hero-enter--1 { animation-delay: 0.05s; }
.hero-enter--2 { animation-delay: 0.18s; }
.hero-enter--3 { animation-delay: 0.32s; }
.hero-enter--4 { animation-delay: 0.46s; }

/* Scroll reveal — elements start hidden/offset, site.js flips .is-visible
   when they enter the viewport. Falls back to visible immediately if JS
   hasn't run yet (e.g. print, JS disabled) via the noscript rule below. */
.reveal {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1), transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
}

    .reveal.is-visible {
        opacity: 1;
        transform: translateY(0);
    }

/* Stagger children of a revealed group — apply .reveal-group to the
   container and .reveal to each child; nth-child delays cascade the effect. */
.reveal-group .reveal:nth-child(1) { transition-delay: 0s; }
.reveal-group .reveal:nth-child(2) { transition-delay: 0.08s; }
.reveal-group .reveal:nth-child(3) { transition-delay: 0.16s; }
.reveal-group .reveal:nth-child(4) { transition-delay: 0.24s; }
.reveal-group .reveal:nth-child(5) { transition-delay: 0.32s; }
.reveal-group .reveal:nth-child(6) { transition-delay: 0.4s; }

noscript .reveal {
    opacity: 1;
    transform: none;
}

/* Subtle film-grain texture — layer over colored/photo sections for depth */
.grain {
    position: relative;
    isolation: isolate;
}

    .grain::before {
        content: "";
        position: absolute;
        inset: 0;
        z-index: 1;
        pointer-events: none;
        opacity: 0.05;
        mix-blend-mode: overlay;
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
    }

/* Pulse — draws the eye to the primary action without nagging.
   Set --pulse-color on the element to theme it (defaults to WhatsApp green). */
@keyframes softPulseRing {
    0% {
        box-shadow: 0 0 0 0 var(--pulse-color, rgba(37, 211, 102, 0.55));
    }

    100% {
        box-shadow: 0 0 0 16px rgba(0, 0, 0, 0);
    }
}

.pulse {
    animation: softPulseRing 2.2s cubic-bezier(0.4, 0, 0.6, 1) 3;
}

/* Waypoint — small dot + drawn-on dashed line beside a label, echoing the
   route/mile-marker motif used throughout the copy. */
.waypoint {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

    .waypoint::before {
        content: "";
        width: 7px;
        height: 7px;
        border-radius: 50%;
        background: currentColor;
        flex-shrink: 0;
    }

    .waypoint::after {
        content: "";
        height: 1px;
        width: 32px;
        background-image: repeating-linear-gradient(to right, currentColor 0 4px, transparent 4px 8px);
        transform-origin: left;
        transform: scaleX(0);
        transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1) 0.15s;
    }

    .reveal.is-visible .waypoint::after {
        transform: scaleX(1);
    }

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }

    .reveal {
        opacity: 1;
        transform: none;
    }
}

/* ---------- Not found ----------
   Global, not scoped: this markup appears in the standalone /not-found page as
   well as inside the route, destination and journal components. Scoping it to
   any one of them leaves the others unstyled. */
.not-found {
    text-align: center;
    padding-top: var(--space-7);
    padding-bottom: var(--space-7);
}

    .not-found h1 {
        margin-bottom: var(--space-3);
    }

    .not-found p {
        max-width: 52ch;
        margin-left: auto;
        margin-right: auto;
        color: rgba(23, 20, 18, 0.7);
    }

.not-found__actions {
    display: flex;
    justify-content: center;
    gap: var(--space-3);
    flex-wrap: wrap;
    margin-top: var(--space-4);
}

.not-found__links {
    margin-top: var(--space-6);
    padding-top: var(--space-4);
    border-top: 1px solid rgba(23, 20, 18, 0.12);
}

.not-found__links-row {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-3) var(--space-4);
    margin-top: var(--space-2);
}

    .not-found__links-row a {
        font-weight: 600;
        font-size: 0.95rem;
    }

/* Text for screen readers only — visible to assistive tech, not on screen.
   Global rather than scoped: labels using it live in several components. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ---------- Cookie consent (consent.js) ----------
   A small card in the bottom-left corner on desktop, clear of the WhatsApp
   button on the right; a strip along the bottom on phones, with the floating
   buttons lifted above it while it's open. */
.consent-banner {
    position: fixed;
    left: 16px;
    bottom: calc(16px + env(safe-area-inset-bottom));
    z-index: 950;
    width: min(380px, calc(100vw - 32px));
    padding: 16px 18px;
    border-radius: 14px;
    background: rgba(16, 56, 60, 0.96);
    color: var(--color-off-white);
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.3);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
    opacity: 0;
    transform: translateY(16px);
    transition: opacity 0.3s ease, transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}

    .consent-banner.is-open {
        opacity: 1;
        transform: none;
    }

.consent-banner__text {
    margin: 0 0 12px;
    font-size: 0.88rem;
    line-height: 1.5;
    color: rgba(244, 241, 234, 0.9);
}

    .consent-banner__text a {
        color: var(--color-gold);
        text-decoration: underline;
        text-underline-offset: 2px;
    }

.consent-banner__actions {
    display: flex;
    gap: 10px;
}

    .consent-banner__actions button {
        font: inherit;
        font-size: 0.88rem;
        font-weight: 600;
        border-radius: 999px;
        padding: 8px 18px;
        cursor: pointer;
    }

.consent-banner__accept {
    border: 0;
    background: var(--color-off-white);
    color: var(--color-teal);
}

    .consent-banner__accept:hover {
        background: #fff;
    }

.consent-banner__decline {
    border: 1px solid rgba(244, 241, 234, 0.4);
    background: transparent;
    color: var(--color-off-white);
}

    .consent-banner__decline:hover {
        border-color: var(--color-off-white);
    }

@media (max-width: 640px) {
    .consent-banner {
        left: 12px;
        right: 12px;
        width: auto;
        bottom: calc(12px + env(safe-area-inset-bottom));
    }

    /* Keep WhatsApp and back-to-top reachable above the strip. */
    html.consent-open .floating-whatsapp,
    html.consent-open .back-to-top {
        translate: 0 calc(-1 * var(--consent-h, 0px));
        transition: translate 0.3s ease;
    }
}

@media (prefers-reduced-motion: reduce) {
    .consent-banner {
        transition: none;
        transform: none;
    }
}