/* ==========================================================================
   0. PALETTES
   Four surfaces from the province itself, each measured against WCAG 2.1
   before it shipped — see _themes.py, which fails the build if a pair drops
   below the bar. The stylesheet below never names a colour: it names a role.
   ========================================================================== */

:root,
:root[data-theme="laterite"] {
    --bg: #F6EFE4;
    --bg-raised: #FFFAF2;
    --bg-sunk: #EDE2D2;
    --ink: #241A12;
    --ink-soft: #4A3829;
    --ink-faint: #6B5745;
    --accent: #A6432A;
    --accent-ink: #FFFFFF;
    --line: #CBB79E;
    --accent-rgb: 166, 67, 42;
    --ink-rgb: 36, 26, 18;
    --verified-rgb: 31, 107, 69;
    --reported-rgb: 138, 91, 18;
    --contested-rgb: 166, 67, 42;
    --derived-rgb: 28, 94, 122;
    --surface-rgb: 26, 18, 10;
    --shade-rgb: 246, 239, 228;
    --tier-verified: #1F6B45;
    --tier-reported: #8A5B12;
    --tier-contested: #A6432A;
    --tier-derived: #1C5E7A;
    color-scheme: light;
}

:root[data-theme="highland"] {
    --bg: #EDF1EE;
    --bg-raised: #FAFCFA;
    --bg-sunk: #E0E7E2;
    --ink: #14201B;
    --ink-soft: #33453C;
    --ink-faint: #556A60;
    --accent: #0F6B4F;
    --accent-ink: #FFFFFF;
    --line: #B6C6BC;
    --accent-rgb: 15, 107, 79;
    --ink-rgb: 20, 32, 27;
    --verified-rgb: 15, 107, 79;
    --reported-rgb: 122, 84, 16;
    --contested-rgb: 163, 63, 38;
    --derived-rgb: 21, 94, 124;
    --surface-rgb: 10, 26, 20;
    --shade-rgb: 237, 241, 238;
    --tier-verified: #0F6B4F;
    --tier-reported: #7A5410;
    --tier-contested: #A33F26;
    --tier-derived: #155E7C;
    color-scheme: light;
}

:root[data-theme="canopy"] {
    --bg: #0D1A15;
    --bg-raised: #16281F;
    --bg-sunk: #081210;
    --ink: #EDF4EF;
    --ink-soft: #C4D4C9;
    --ink-faint: #9DB2A4;
    --accent: #E08A67;
    --accent-ink: #1A0E08;
    --line: #2E4438;
    --accent-rgb: 224, 138, 103;
    --ink-rgb: 237, 244, 239;
    --verified-rgb: 111, 203, 159;
    --reported-rgb: 233, 185, 121;
    --contested-rgb: 232, 137, 106;
    --derived-rgb: 143, 203, 230;
    --surface-rgb: 255, 255, 255;
    --shade-rgb: 8, 18, 16;
    --tier-verified: var(--tier-verified);
    --tier-reported: var(--tier-reported);
    --tier-contested: #E8896A;
    --tier-derived: var(--tier-derived);
    color-scheme: dark;
}

:root[data-theme="ember"] {
    --bg: #08090A;
    --bg-raised: #141618;
    --bg-sunk: #000000;
    --ink: #FFFFFF;
    --ink-soft: #DCE2E6;
    --ink-faint: #AEB8BF;
    --accent: #FF9E5E;
    --accent-ink: #1A0C03;
    --line: #333A3F;
    --accent-rgb: 255, 158, 94;
    --ink-rgb: 255, 255, 255;
    --verified-rgb: 91, 227, 155;
    --reported-rgb: 255, 201, 107;
    --contested-rgb: 255, 145, 120;
    --derived-rgb: 127, 212, 245;
    --surface-rgb: 255, 255, 255;
    --shade-rgb: 0, 0, 0;
    --tier-verified: #5BE39B;
    --tier-reported: #FFC96B;
    --tier-contested: #FF9178;
    --tier-derived: #7FD4F5;
    color-scheme: dark;
}

/* Auto: follow the device. A phone that has already decided it is night
   should not be argued with. */
@media (prefers-color-scheme: dark) {
    :root[data-theme="auto"] {
        --bg: #0D1A15;
        --bg-raised: #16281F;
        --bg-sunk: #081210;
        --ink: #EDF4EF;
        --ink-soft: #C4D4C9;
        --ink-faint: #9DB2A4;
        --accent: #E08A67;
        --accent-ink: #1A0E08;
        --line: #2E4438;
        --accent-rgb: 224, 138, 103;
        --ink-rgb: 237, 244, 239;
        --verified-rgb: 111, 203, 159;
        --reported-rgb: 233, 185, 121;
        --contested-rgb: 232, 137, 106;
        --derived-rgb: 143, 203, 230;
        --surface-rgb: 255, 255, 255;
        --shade-rgb: 8, 18, 16;
        --tier-verified: var(--tier-verified);
        --tier-reported: var(--tier-reported);
        --tier-contested: #E8896A;
        --tier-derived: var(--tier-derived);
        color-scheme: dark;
    }
}
@media (prefers-color-scheme: light) {
    :root[data-theme="auto"] {
        --bg: #F6EFE4;
        --bg-raised: #FFFAF2;
        --bg-sunk: #EDE2D2;
        --ink: #241A12;
        --ink-soft: #4A3829;
        --ink-faint: #6B5745;
        --accent: #A6432A;
        --accent-ink: #FFFFFF;
        --line: #CBB79E;
        --accent-rgb: 166, 67, 42;
        --ink-rgb: 36, 26, 18;
        --verified-rgb: 31, 107, 69;
        --reported-rgb: 138, 91, 18;
        --contested-rgb: 166, 67, 42;
        --derived-rgb: 28, 94, 122;
        --surface-rgb: 26, 18, 10;
        --shade-rgb: 246, 239, 228;
        --tier-verified: #1F6B45;
        --tier-reported: #8A5B12;
        --tier-contested: #A6432A;
        --tier-derived: #1C5E7A;
        color-scheme: light;
    }
}

/* ==========================================================================
   1. CORE BIOME VARIABLES (The Environment)
   ========================================================================== */
   :root {
    /* Legacy names kept as aliases so every existing rule keeps working while
       the palette underneath it changes. New code should use the role tokens
       above: --bg, --ink, --accent, --line. */
    --canopy-deep: var(--bg);
    --canopy-mid: var(--bg-raised);
    --terracotta: var(--accent);
    --mist: var(--ink);

    --glass-bg: rgba(var(--surface-rgb), 0.04);
    --glass-border: var(--line);
    --glass-blur: blur(16px);

    --font-heading: 'Playfair Display', serif;
    --font-data: 'Inter', sans-serif;

    --text-hero: clamp(2.5rem, 6vw + 1rem, 6rem);
    --text-h2: clamp(1.75rem, 3vw + 0.5rem, 3rem);
    --text-body: clamp(1rem, 1vw + 0.5rem, 1.125rem);

    --radius-soft: 12px;
    --radius-organic: 24px;

    /* The fixed header's height. Every sticky offset on the site is derived
       from this rather than guessed, so they cannot drift apart. */
    --header-h: 4.6rem;
}

/* ==========================================================================
   2. GLOBAL RESETS & FOUNDATION
   ========================================================================== */
*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html {
    scroll-behavior: smooth;
}

/* Anchor targets must clear the fixed header (and, on the Data Hub, the sticky
   topic nav) — otherwise jumping to a section buries its heading underneath. */
section[id],
nav[id],
main[id] {
    scroll-margin-top: 1.5rem;
}

@media (min-width: 768px) {
    section[id],
    nav[id],
    main[id] {
        scroll-margin-top: 6.5rem;
    }

    .hub-layout section[id] {
        scroll-margin-top: 7rem; /* clears the fixed header */
    }
}

body.biome-theme {
    background-color: var(--bg);
    color: var(--ink);
    font-family: var(--font-data);
    font-size: var(--text-body);
    line-height: 1.6;
    overflow-x: hidden;
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
    font-family: var(--font-heading);
    font-weight: 400;
    line-height: 1.2;
}

a {
    text-decoration: none;
    color: inherit;
}

.text-terracotta { color: var(--terracotta); }

/* ==========================================================================
   3. REUSABLE UI COMPONENTS
   ========================================================================== */
/* The core frosted glass effect used across cards and navigation */
.glass-panel {
    background: var(--glass-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    border: 1px solid var(--glass-border);
}

/* ==========================================================================
   4. LAYOUT STRUCTURE (Mobile-First approach)
   ========================================================================== */
/* Hide desktop nav on small screens */
.nav-desktop { display: none; }

/* Mobile Bottom Bar Setup */
.nav-mobile {
    position: fixed;
    bottom: 0;
    left: 0;
    width: 100%;
    display: flex;
    justify-content: space-around;
    padding: 1rem 0;
    z-index: 1000;
    border-top: 1px solid var(--glass-border);
    border-top-left-radius: var(--radius-organic);
    border-top-right-radius: var(--radius-organic);
}

/* Hero Section Base */
.hero-cinematic {
    position: relative;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 2rem;
}

.hero-content {
    position: relative;
    z-index: 10;
}

.fluid-title {
    font-size: var(--text-hero);
    letter-spacing: 2px;
}

/* The Portals Grid (Defaults to stacked on mobile, side-by-side on desktop) */
.portal-grid {
    display: grid;
    grid-template-columns: 1fr; /* Single column on mobile */
    gap: 1.5rem;
    padding: 2rem;
    max-width: 1400px;
    margin: 0 auto;
}

/* --- ADAPTIVE INTELLIGENCE (Desktop Breakpoint) --- */
@media (min-width: 768px) {
    /* Hide mobile bottom bar, reveal desktop mega-menu */
    .nav-mobile { display: none; }

    .nav-desktop {
        display: flex;
        justify-content: space-between;   /* exactly two children: logo | actions */
        align-items: center;
        gap: 1.5rem;
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        /* 4rem of side padding starved the nav at 1024px and forced the items
           to bunch. Scale it with the viewport instead. */
        padding: 1rem clamp(1.25rem, 3.5vw, 3.5rem);
        z-index: 1000;
        border-bottom: 1px solid var(--glass-border);
    }

    /* Portals wrap gracefully to fit however many cards exist (2, 4, 5...) */
    .portal-grid {
        grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
        padding: 4rem;
    }
}

/* ==========================================================================
   5. NAVIGATION — DESKTOP MEGA-MENU
   ========================================================================== */
.nav-logo {
    font-family: var(--font-heading);
    font-size: 1.5rem;
    letter-spacing: 0.04em;
}

/* Everything to the right of the logo travels together, so the header stays a
   two-part composition however many controls get added to it later. */
.nav-actions {
    display: flex;
    align-items: center;
    gap: clamp(0.85rem, 1.6vw, 1.75rem);
    min-width: 0;
}

.nav-links {
    display: flex;
    align-items: center;
    /* was a flat 2.5rem, which overflowed the bar on a 1024px laptop */
    gap: clamp(1rem, 2vw, 2.25rem);
    min-width: 0;
}

.nav-item {
    position: relative;
    font-family: var(--font-data);
    font-size: 0.95rem;
    padding: 0.25rem 0;
}

.nav-item::after {
    content: '';
    position: absolute;
    left: 0;
    bottom: -2px;
    width: 0;
    height: 1.5px;
    background: var(--terracotta);
    transition: width 0.3s ease;
}

.nav-item:hover::after { width: 100%; }

.nav-item-wrap { position: relative; }

.btn-terracotta {
    background: var(--terracotta);
    color: var(--canopy-deep);
    font-family: var(--font-data);
    font-weight: 600;
    font-size: 0.9rem;
    padding: 0.65rem 1.4rem;
    border-radius: var(--radius-organic);
    transition: transform 0.25s ease, box-shadow 0.25s ease;
}

.btn-terracotta:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 20px rgba(var(--accent-rgb), 0.35);
}

.mega-panel {
    position: absolute;
    top: calc(100% + 1.25rem);
    left: 50%;
    width: 640px;
    padding: 1.75rem;
    border-radius: var(--radius-organic);
    background: var(--canopy-mid);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transform: translateX(-50%) translateY(-12px);
    transition: opacity 0.35s ease, transform 0.35s ease, visibility 0.35s;
    z-index: 10;
}

/* Invisible bridge across the 1.25rem gap between the nav item and the panel.
   Without it the pointer leaves :hover mid-traversal, the panel loses
   pointer-events, and the click falls through to the panel underneath. */
.mega-panel::before {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: -1.5rem;
    height: 1.5rem;
}

/* Only the panel JS has explicitly opened is interactive and on top. Relying on
   :hover alone let both overlapping panels stay in the hit-testing stack. */
.mega-panel.is-open {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: translateX(-50%) translateY(0);
    z-index: 30;
}

/* No-JS fallback: hover still reveals the panel if the script never runs. */
.no-js .nav-item-wrap:hover .mega-panel {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: translateX(-50%) translateY(0);
    z-index: 30;
}

.mega-panel__grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1.25rem;
}

.mega-card { color: inherit; }

.mega-card__thumb {
    width: 100%;
    aspect-ratio: 4 / 3;
    border-radius: var(--radius-soft);
    background: linear-gradient(135deg, var(--canopy-mid), var(--terracotta));
    margin-bottom: 0.6rem;
}

.mega-card__title {
    font-family: var(--font-heading);
    font-size: 1rem;
    font-weight: 400;
    margin-bottom: 0.25rem;
}

.mega-card__desc {
    font-family: var(--font-data);
    font-size: 0.8rem;
    line-height: 1.4;
    color: var(--mist);
    opacity: 0.75;
}

/* Data Hub mega-panel: 6 data categories (no thumbnails, text-first) */
.mega-panel--categories {
    width: 620px;
}

.mega-panel__grid--categories {
    grid-template-columns: repeat(2, 1fr);
    gap: 0.5rem 1.75rem;
}

.category-link {
    display: block;
    padding: 0.85rem 0;
    color: inherit;
    border-bottom: 1px solid var(--glass-border);
}

.mega-panel__grid--categories .category-link:nth-last-child(-n+1),
.mega-panel__grid--categories .category-link:nth-last-child(-n+2) {
    border-bottom: none;
}

.category-link__title {
    font-family: var(--font-heading);
    font-size: 0.95rem;
    font-weight: 400;
    margin-bottom: 0.3rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.category-link__desc {
    font-family: var(--font-data);
    font-size: 0.75rem;
    line-height: 1.5;
    color: var(--mist);
    opacity: 0.7;
}

.category-link__badge {
    font-family: var(--font-data);
    font-size: 0.6rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    background: rgba(var(--reported-rgb), 0.18);
    color: var(--tier-reported);
}

/* Generic small sourcing/caveat note, reused wherever a stat needs one */
.stat-note {
    display: block;
    font-family: var(--font-data);
    font-size: 0.65rem;
    color: var(--mist);
    opacity: 0.6;
    line-height: 1.5;
    margin-top: 0.4rem;
    text-align: left;
}

/* Coming Soon placeholder sections (atlas.html) */
.coming-soon-block {
    padding: 2.5rem;
    border-radius: var(--radius-organic);
    text-align: center;
}

.coming-soon-block__title {
    font-size: 1.2rem;
    margin-bottom: 0.5rem;
}

.coming-soon-block__desc {
    font-family: var(--font-data);
    font-size: 0.85rem;
    color: var(--mist);
    opacity: 0.7;
    max-width: 480px;
    margin: 0 auto;
    line-height: 1.6;
}

/* Sourced info cards: Infrastructure & Social Services sections */
.info-card-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.5rem;
}

.info-card {
    position: relative;
    padding: 1.75rem;
    border-radius: var(--radius-organic);
}

.info-card .stat-tier {
    position: static;
    display: inline-block;
    margin-bottom: 0.75rem;
}

.info-card__title {
    font-size: 1.05rem;
    margin-bottom: 0.6rem;
}

.info-card__body {
    font-family: var(--font-data);
    font-size: 0.88rem;
    line-height: 1.65;
    color: var(--mist);
    opacity: 0.85;
    margin-bottom: 0.75rem;
}

.info-card__source {
    font-family: var(--font-data);
    font-size: 0.7rem;
    color: var(--mist);
    opacity: 0.55;
}

@media (min-width: 768px) {
    .info-card-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* Administrative district cards */
.district-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.25rem;
}

.district-card {
    padding: 1.5rem;
    border-radius: var(--radius-organic);
}

.district-card .stat-tier {
    position: static;
    display: inline-block;
    margin-bottom: 0.6rem;
}

.district-card--total {
    border-color: var(--terracotta);
}

.district-card__title {
    font-size: 1.05rem;
    margin-bottom: 0.2rem;
}

.district-card__meta {
    font-family: var(--font-data);
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--terracotta);
    margin-bottom: 0.6rem;
}

.district-card__desc {
    font-family: var(--font-data);
    font-size: 0.85rem;
    line-height: 1.6;
    color: var(--mist);
    opacity: 0.8;
}

@media (min-width: 768px) {
    .district-grid {
        grid-template-columns: repeat(3, 1fr);
    }
}

/* Compliance checklist (business.html) */
.checklist {
    list-style: none;
    padding: 0.5rem;
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
}

.checklist__item {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    font-family: var(--font-data);
    font-size: 0.9rem;
    line-height: 1.6;
    color: var(--mist);
    padding: 0.75rem;
    border-radius: var(--radius-soft);
    background: rgba(var(--surface-rgb), 0.02);
}

/* ==========================================================================
   16. KNOWLEDGE HUB — 5-STAGE NAV, 11-TOPIC GRID, DEEP-READ SECTION
   ========================================================================== */
/* Data Hub hero */
.hub-hero {
    padding: 2.5rem 2rem 1.5rem;
    max-width: 820px;
    margin: 0 auto;
}

.hub-hero__eyebrow {
    font-family: var(--font-data);
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--terracotta);
    margin-bottom: 0.75rem;
}

.hub-hero__title {
    font-size: var(--text-hero);
    margin-bottom: 1rem;
}

.hub-hero__subtitle {
    font-family: var(--font-data);
    font-size: 0.95rem;
    line-height: 1.75;
    color: var(--mist);
    opacity: 0.8;
    max-width: 620px;
    margin-bottom: 1.5rem;
}

.hub-hero__legend {
    display: flex;
    gap: 1.5rem;
    flex-wrap: wrap;
}

@media (min-width: 768px) {
    .hub-hero { padding: 3.5rem 4rem 2rem; }
}

/* ==========================================================================
   VERTICAL SECTION RAIL — fixed to the left edge, always reachable.
   It never scrolls away and never covers the text: the reader's current
   section keeps its label visible at all times, while the rest stay as dots
   until you hover (or tap on touch). Any section is one click away from
   anywhere on the page, with no scrolling up or down.
   ========================================================================== */
/* ---- Anchoring -------------------------------------------------------------
   Previously the rail was centred on the viewport (top: 50% / translateY(-50%))
   with a max-height of 78vh. That is fine for a page with three entries. The
   Data Hub has twenty-one: at 78vh the panel ran from roughly 11vh to 89vh,
   which put its top entries underneath the fixed header (z-index 1000 against
   the rail's 900) and left it scrolling internally against a header it could
   not clear. Same CSS, completely different behaviour depending on how many
   links a page happened to have — which is exactly the bug.

   The fix is to stop centring on the viewport and instead centre inside the
   band of space that is actually available: below the header, above the
   bottom margin. `top` + `bottom` + `height: fit-content` + `margin-block:
   auto` centres a short rail in that band and makes a long one fill it
   exactly, never exceeding it. A 2-item rail and a 21-item rail now behave
   identically, and neither can reach the header.
   -------------------------------------------------------------------------- */
.section-rail {
    position: fixed;
    left: 0;                    /* flush to the left edge of the viewport */
    top: var(--rail-top, 5rem);
    bottom: 1.5rem;
    height: fit-content;
    margin-block: auto;         /* centres within the top/bottom band */
    transform: none;
    z-index: 900;
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    max-height: calc(100vh - var(--rail-top, 5rem) - 1.5rem);
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
    padding: 0.55rem 0.4rem;
    border-radius: 0 var(--radius-organic) var(--radius-organic) 0;
    background: rgba(var(--shade-rgb), 0.62);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border: 1px solid var(--glass-border);
    border-left: none;
    transition: background 0.3s ease;
}

.section-rail::-webkit-scrollbar { width: 0; }

.section-rail:hover,
.section-rail.is-expanded {
    background: rgba(var(--shade-rgb), 0.9);
}

.rail-item {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.34rem 0.3rem;
    border-radius: 999px;
    color: var(--mist);
    text-decoration: none;
}

.rail-item__dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: rgba(var(--surface-rgb), 0.3);
    flex-shrink: 0;
    transition: background 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease;
}

.rail-item__label {
    font-family: var(--font-data);
    font-size: 0.72rem;
    line-height: 1.2;
    white-space: nowrap;
    max-width: 0;
    overflow: hidden;
    opacity: 0;
    transition: max-width 0.35s ease, opacity 0.3s ease;
}

.rail-item:hover .rail-item__dot {
    background: var(--terracotta);
    transform: scale(1.35);
}

.rail-item:hover .rail-item__label { opacity: 1; }

/* The section you're actually reading */
.rail-item.is-current .rail-item__dot {
    background: var(--terracotta);
    transform: scale(1.4);
    box-shadow: 0 0 0 4px rgba(var(--accent-rgb), 0.18);
}

.rail-item.is-current .rail-item__label {
    opacity: 1;
    color: var(--terracotta);
    font-weight: 600;
}

/* ---- Phones: a full labelled sidebar would eat most of a 390px screen, so
   the rail collapses to a slim strip — but it still carries the word
   "SECTIONS" down its side, so it's never an unexplained row of dots. One tap
   opens the labelled list over a scrim. ---- */
@media (max-width: 767px) {
    .section-rail::before {
        content: "SECTIONS";
        writing-mode: vertical-rl;
        transform: rotate(180deg);
        align-self: center;
        font-family: var(--font-data);
        font-size: 0.52rem;
        font-weight: 600;
        letter-spacing: 0.18em;
        color: var(--terracotta);
        margin-bottom: 0.5rem;
        padding-bottom: 0.5rem;
        border-bottom: 1px solid var(--glass-border);
    }

    .section-rail.is-expanded::before { display: none; }

    /* Above the scrim (880), and still below the header (1000). The rail's
       own base z-index is 900, so this must not drop below 881 — it used to
       be set to 890 which is fine, but the value is written relative to the
       scrim deliberately, so the two cannot drift apart. */
    .section-rail.is-expanded {
        z-index: 901;
    }

    .section-rail.is-expanded .rail-item__label {
        max-width: 165px;
        opacity: 0.9;
    }
}

/* ---- Tablets and small laptops: room enough for permanent labels, just in a
   narrower column than the full desktop sidebar. ---- */
@media (min-width: 768px) and (max-width: 1199px) {
    /* Rail is 5.5rem wide, border-box, so 5.5rem is the whole thing. The
       gutter is 7.5rem, leaving a clear 2rem of air between the rail's right
       edge and the first character of any heading. */
    .hub-layout--railed { --rail-gutter: 7.5rem; }

    .section-rail {
        width: 5.5rem;
        padding: 0.45rem 0.3rem;
        align-items: stretch;
    }

    .rail-item {
        padding: 0.26rem 0.24rem;
        gap: 0.32rem;
        border-radius: var(--radius-soft);
    }

    .rail-item:hover { background: rgba(var(--surface-rgb), 0.05); }
    .rail-item.is-current { background: rgba(var(--accent-rgb), 0.12); }

    .rail-item__dot { width: 5px; height: 5px; }

    .rail-item__label {
        max-width: 100%;
        opacity: 0.7;
        white-space: normal;
        overflow-wrap: anywhere;
        font-size: 0.53rem;
        line-height: 1.22;
        letter-spacing: 0;
    }
}

/* ---- 1200px and up: the rail becomes a permanent labelled sidebar sitting
   in its own reserved gutter. Nothing overlaps, nothing needs hovering, and
   every destination is readable at a glance. ---- */
@media (min-width: 1200px) {
    /* Rail is 5.75rem wide (border-box, padding included). Content starts at
       8rem, so there is a deliberate 2.25rem of empty space between the rail
       and the first character of a heading — enough that a long title like
       "Land and terrain" reads as sitting in its own column, not squeezed
       against the navigation. */
    .hub-layout--railed { --rail-gutter: 8rem; }

    .section-rail {
        padding: 0.5rem 0.34rem;
        width: 5.75rem;
        align-items: stretch;
    }

    .rail-item {
        padding: 0.28rem 0.26rem;
        gap: 0.34rem;
        border-radius: var(--radius-soft);
        transition: background 0.25s ease, transform 0.25s var(--spring);
    }

    .rail-item:hover { background: rgba(var(--surface-rgb), 0.05); }

    .rail-item.is-current {
        background: rgba(var(--accent-rgb), 0.14);
        box-shadow: inset 2px 0 0 var(--terracotta);
    }

    .rail-item__dot { width: 5px; height: 5px; }

    .rail-item__label {
        max-width: 100%;
        opacity: 0.72;
        white-space: normal;
        overflow-wrap: anywhere;
        font-size: 0.56rem;
        line-height: 1.25;
        letter-spacing: 0;
    }
}


/* External items sit below a divider and carry an arrow in their label. They
   otherwise look and behave exactly like on-page items — the only real
   difference is that scrollspy can never mark them "current", because the
   section they point at lives on another page. */

.rail-divider {
    height: 1px;
    margin: 0.4rem 0.3rem;
    background: var(--glass-border);
}

/* Phones: slim strip flush to the edge */
@media (max-width: 767px) {
    .hub-layout--railed { --rail-gutter: 3.25rem; }

    .section-rail {
        padding: 0.45rem 0.3rem;
        max-height: calc(100vh - var(--rail-top, 5rem) - 4.5rem);
        bottom: 4.5rem;   /* clears the mobile bottom nav bar */
    }

    .rail-item { padding: 0.3rem 0.2rem; }
}

@media print {
    .section-rail { display: none; }
}

/* ---- Rail / content coexistence -------------------------------------------
   The rail is fixed, so it takes no space in flow and would sit on top of the
   text. Only the Data Hub carries a rail, so only that page reserves a gutter
   for it — wide enough for the collapsed rail at every breakpoint, so the two
   never overlap. `--rail-gutter` keeps the reservation and the rail's own
   geometry tied to a single number.
   -------------------------------------------------------------------------- */
.hub-layout--railed {
    --rail-gutter: 3.75rem;
}

/* Header clearance. The desktop header is fixed at z-index 1000, so the rail
   has to begin below it rather than trying to out-stack it. */
:root { --rail-top: 5rem; }

@media (min-width: 768px) { :root { --rail-top: 6.75rem; } }

.hub-layout--railed .register-section,
.hub-layout--railed .atlas-section,
.hub-layout--railed .hub-hero,
.hub-layout--railed .guide-section,
.hub-layout--railed .journeys-section,
.hub-layout--railed .stats-section,
.hub-layout--railed .gallery-section,
.hub-layout--railed .accordion-section,
.hub-layout--railed .portal-grid {
    padding-left: var(--rail-gutter);
}

/* NOTE: no blanket `min-width: 768px` gutter override here. The tablet and
   desktop gutters are set in the rail's own breakpoint blocks above, each
   sized to that breakpoint's actual rail width. A later blanket rule would
   win on source order and silently under-reserve the gutter, which is what
   used to push the rail on top of the section headings. */


/* While the rail is expanded it needs more room than the gutter reserves.
   On wide screens it opens into the page margin and covers nothing. On narrow
   screens it is an explicit, user-initiated overlay, so a scrim makes it read
   as a temporary layer and gives a large tap target to dismiss it. */
.rail-scrim {
    position: fixed;
    inset: 0;
    z-index: 880;
    background: rgba(var(--shade-rgb), 0.55);
    backdrop-filter: blur(2px);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.3s ease, visibility 0.3s;
}

.rail-scrim.is-visible {
    opacity: 1;
    visibility: visible;
}

@media (min-width: 768px) {
    /* Labels are permanent from here up, so nothing ever expands — no scrim */
    .rail-scrim { display: none; }
}

/* ==========================================================================
   19. MACRO INVESTMENT CARD · LEGAL TIMELINE · COMMUNITY HUB · DATA GAPS
   ========================================================================== */

/* ---- Task A: 2026 Economic Outlook / macro-investment card ---- */
.macro-card {
    position: relative;
    padding: 2rem 1.75rem;
    border-radius: var(--radius-organic);
    border-left: 3px solid var(--terracotta);
    overflow: hidden;
}

.macro-card__flag {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-family: var(--font-data);
    font-size: 0.62rem;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--terracotta);
    margin-bottom: 0.9rem;
}

.macro-card__flag::before {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--terracotta);
    box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.2);
}

.macro-card__title {
    font-family: var(--font-heading);
    font-size: clamp(1.3rem, 2.4vw, 1.9rem);
    color: var(--mist);
    margin-bottom: 0.5rem;
    line-height: 1.25;
}

.macro-card__lede {
    font-family: var(--font-data);
    font-size: 0.9rem;
    line-height: 1.7;
    color: var(--mist);
    opacity: 0.85;
    max-width: 62ch;
    margin-bottom: 1.5rem;
}

.macro-figures {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1rem;
    margin-bottom: 1.5rem;
}

@media (min-width: 768px) {
    .macro-figures { grid-template-columns: repeat(4, 1fr); }
}

.macro-figure {
    padding: 1rem;
    border-radius: var(--radius-soft);
    background: rgba(var(--surface-rgb), 0.03);
    border: 1px solid var(--glass-border);
}

.macro-figure__value {
    font-family: var(--font-heading);
    font-size: 1.5rem;
    color: var(--terracotta);
    display: block;
    line-height: 1.1;
}

.macro-figure__label {
    font-family: var(--font-data);
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--mist);
    opacity: 0.7;
    margin-top: 0.4rem;
    display: block;
    line-height: 1.4;
}

/* ---- Extensible user-data buffer, reused across every component ---- */
.data-buffer {
    margin-top: 1.5rem;
    padding: 1.1rem 1.25rem;
    border-radius: var(--radius-soft);
    border: 1px dashed rgba(var(--accent-rgb), 0.45);
    background: rgba(var(--accent-rgb), 0.05);
}

.data-buffer__title {
    font-family: var(--font-data);
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--terracotta);
    margin-bottom: 0.45rem;
}

.data-buffer__hint {
    font-family: var(--font-data);
    font-size: 0.8rem;
    line-height: 1.6;
    color: var(--mist);
    opacity: 0.7;
}

/* ---- Task B: foundational legal timeline ---- */
.legal-timeline {
    width: 100%;
    border-collapse: collapse;
    font-family: var(--font-data);
}

.legal-timeline th {
    text-align: left;
    padding: 0.85rem 1rem;
    font-size: 0.66rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--terracotta);
    border-bottom: 1px solid var(--glass-border);
    white-space: nowrap;
}

.legal-timeline td {
    padding: 1rem;
    font-size: 0.85rem;
    line-height: 1.6;
    color: var(--mist);
    border-bottom: 1px solid var(--glass-border);
    vertical-align: top;
}

.legal-timeline tbody tr:last-child td { border-bottom: none; }
.legal-timeline tbody tr:hover { background: rgba(var(--surface-rgb), 0.02); }

.legal-timeline__year {
    font-family: var(--font-heading);
    font-size: 1rem;
    color: var(--terracotta);
    white-space: nowrap;
}

.legal-timeline__name { font-weight: 600; }

.legal-timeline__era {
    display: inline-block;
    font-size: 0.58rem;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    padding: 0.12rem 0.5rem;
    border-radius: 999px;
    margin-top: 0.4rem;
}

.era--foundational { background: rgba(var(--reported-rgb), 0.16); color: var(--tier-reported); }
.era--conservation { background: rgba(var(--verified-rgb), 0.16); color: var(--tier-verified); }
.era--administrative { background: rgba(var(--accent-rgb), 0.16); color: var(--terracotta); }

.legal-timeline tr.row--buffer td {
    border: 1px dashed rgba(var(--accent-rgb), 0.4);
    background: rgba(var(--accent-rgb), 0.04);
    font-size: 0.78rem;
    opacity: 0.85;
}

@media (max-width: 767px) {
    .legal-timeline th:nth-child(4),
    .legal-timeline td:nth-child(4) { display: none; }
}

/* ---- Task C: Community Hub ---- */
.org-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.25rem;
}

@media (min-width: 768px) {
    .org-grid { grid-template-columns: repeat(2, 1fr); }
}

.org-card {
    padding: 1.5rem;
    border-radius: var(--radius-organic);
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.org-card__head {
    display: flex;
    align-items: baseline;
    gap: 0.6rem;
    flex-wrap: wrap;
}

.org-card__abbr {
    font-family: var(--font-heading);
    font-size: 1.15rem;
    color: var(--terracotta);
}

.org-card__name {
    font-family: var(--font-data);
    font-size: 0.78rem;
    color: var(--mist);
    opacity: 0.75;
}

.org-card__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem 0.9rem;
    font-family: var(--font-data);
    font-size: 0.66rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--mist);
    opacity: 0.6;
}

.org-card__body {
    font-family: var(--font-data);
    font-size: 0.85rem;
    line-height: 1.65;
    color: var(--mist);
    opacity: 0.85;
}

.org-card__link {
    font-family: var(--font-data);
    font-size: 0.78rem;
    color: var(--terracotta);
    border-bottom: 1px solid rgba(var(--accent-rgb), 0.4);
    align-self: flex-start;
}

/* Verification module (form) */
.verify-form {
    padding: 1.75rem;
    border-radius: var(--radius-organic);
    display: flex;
    flex-direction: column;
    gap: 1.4rem;
}

.field__label {
    display: block;
    font-family: var(--font-data);
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--terracotta);
    margin-bottom: 0.6rem;
}

.toggle-row {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.6rem;
}

@media (min-width: 640px) {
    .toggle-row { grid-template-columns: repeat(3, 1fr); }
}

.toggle-opt { position: relative; }

.toggle-opt input {
    position: absolute;
    opacity: 0;
    width: 100%;
    height: 100%;
    cursor: pointer;
    margin: 0;
}

.toggle-opt__face {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.85rem 1rem;
    border-radius: var(--radius-soft);
    border: 1px solid var(--glass-border);
    background: rgba(var(--surface-rgb), 0.03);
    font-family: var(--font-data);
    font-size: 0.82rem;
    color: var(--mist);
    transition: border-color 0.25s ease, background 0.25s ease, color 0.25s ease;
}

.toggle-opt input:hover + .toggle-opt__face { border-color: rgba(var(--accent-rgb), 0.5); }

.toggle-opt input:checked + .toggle-opt__face {
    border-color: var(--terracotta);
    background: rgba(var(--accent-rgb), 0.12);
    color: var(--terracotta);
    font-weight: 600;
}

.toggle-opt input:focus-visible + .toggle-opt__face {
    outline: 2px solid var(--terracotta);
    outline-offset: 2px;
}

.field__input,
.field__select,
.field__textarea {
    width: 100%;
    padding: 0.8rem 0.95rem;
    border-radius: var(--radius-soft);
    background: rgba(var(--surface-rgb), 0.04);
    border: 1px solid var(--glass-border);
    color: var(--mist);
    font-family: var(--font-data);
    font-size: 0.88rem;
}

.field__textarea { min-height: 120px; resize: vertical; }

.field__input:focus,
.field__select:focus,
.field__textarea:focus {
    outline: none;
    border-color: var(--terracotta);
}

.field__select option { background: var(--canopy-mid); color: var(--mist); }

.field__file {
    display: block;
    padding: 1rem;
    border-radius: var(--radius-soft);
    border: 1px dashed var(--glass-border);
    background: rgba(var(--surface-rgb), 0.02);
    font-family: var(--font-data);
    font-size: 0.8rem;
    color: var(--mist);
    opacity: 0.8;
    cursor: pointer;
}

.field__hint {
    font-family: var(--font-data);
    font-size: 0.7rem;
    color: var(--mist);
    opacity: 0.55;
    margin-top: 0.45rem;
    line-height: 1.5;
}

.form-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.2rem;
}

@media (min-width: 640px) {
    .form-grid--2 { grid-template-columns: repeat(2, 1fr); }
}

/* Ledger feed */
.ledger-list {
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
}

.ledger-item {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.5rem;
    padding: 1.1rem 1.25rem;
    border-radius: var(--radius-soft);
}

.ledger-item__top {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    flex-wrap: wrap;
}

.ledger-item__ref {
    font-family: var(--font-data);
    font-size: 0.66rem;
    letter-spacing: 0.06em;
    color: var(--mist);
    opacity: 0.5;
}

.ledger-item__where {
    font-family: var(--font-data);
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--terracotta);
}

.ledger-item__body {
    font-family: var(--font-data);
    font-size: 0.86rem;
    line-height: 1.6;
    color: var(--mist);
    opacity: 0.88;
}

.ledger-badge {
    font-family: var(--font-data);
    font-size: 0.58rem;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    padding: 0.18rem 0.6rem;
    border-radius: 999px;
    margin-left: auto;
    white-space: nowrap;
}

.badge--accepted { background: rgba(var(--verified-rgb), 0.18); color: var(--tier-verified); }
.badge--review   { background: rgba(var(--reported-rgb), 0.18); color: var(--tier-reported); }
.badge--rejected { background: rgba(var(--accent-rgb), 0.18); color: var(--terracotta); }
.badge--sourcing { background: rgba(var(--surface-rgb), 0.08); color: var(--mist); }

/* ---- Task D: data gaps callout ---- */
.gaps-callout {
    padding: 2rem 1.75rem;
    border-radius: var(--radius-organic);
    border: 1px solid rgba(var(--reported-rgb), 0.35);
    background: rgba(var(--reported-rgb), 0.05);
}

.gaps-callout__title {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    font-family: var(--font-heading);
    font-size: 1.25rem;
    color: var(--tier-reported);
    margin-bottom: 0.5rem;
}

.gaps-list {
    list-style: none;
    counter-reset: gap;
    padding: 0;
    margin: 1.25rem 0 0;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.gaps-list li {
    counter-increment: gap;
    position: relative;
    padding-left: 2.4rem;
    font-family: var(--font-data);
    font-size: 0.86rem;
    line-height: 1.65;
    color: var(--mist);
    opacity: 0.88;
}

.gaps-list li::before {
    content: counter(gap);
    position: absolute;
    left: 0;
    top: 0;
    width: 1.6rem;
    height: 1.6rem;
    border-radius: 50%;
    background: rgba(var(--reported-rgb), 0.16);
    color: var(--tier-reported);
    font-size: 0.72rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
}

.gaps-list strong { color: var(--mist); opacity: 1; }

/* ==========================================================================
   18. DATA VISUALISATION — hand-rolled SVG + CSS charts (no chart library)
   ========================================================================== */
.chart-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.5rem;
    margin-bottom: 2rem;
}

@media (min-width: 768px) {
    .chart-grid--2 { grid-template-columns: repeat(2, 1fr); }
}

.chart-card {
    padding: 1.5rem;
    border-radius: var(--radius-organic);
}

.chart-card__title {
    font-family: var(--font-heading);
    font-size: 1.05rem;
    color: var(--mist);
    margin-bottom: 0.3rem;
}

.chart-card__sub {
    font-family: var(--font-data);
    font-size: 0.75rem;
    color: var(--mist);
    opacity: 0.6;
    margin-bottom: 1.25rem;
    line-height: 1.5;
}

.chart-card__source {
    font-family: var(--font-data);
    font-size: 0.68rem;
    color: var(--mist);
    opacity: 0.5;
    margin-top: 1rem;
    line-height: 1.5;
}

/* --- Horizontal bar rows (crops, district comparison, budgets) --- */
.bar-row {
    display: grid;
    grid-template-columns: 92px 1fr auto;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.7rem;
    font-family: var(--font-data);
    font-size: 0.78rem;
}

.bar-row__label {
    color: var(--mist);
    opacity: 0.85;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.bar-row__track {
    height: 20px;
    border-radius: 4px;
    background: rgba(var(--surface-rgb), 0.05);
    overflow: hidden;
}

.bar-row__fill {
    height: 100%;
    border-radius: 4px;
    background: linear-gradient(90deg, var(--terracotta), var(--accent));
    width: 0;
    transition: width 1.1s cubic-bezier(0.22, 1, 0.36, 1);
}

.bar-row__fill--alt {
    background: linear-gradient(90deg, #2E7D5B, var(--tier-verified));
}

.bar-row__fill--muted {
    background: rgba(var(--surface-rgb), 0.16);
}

.bar-row__value {
    color: var(--mist);
    font-weight: 600;
    white-space: nowrap;
    font-size: 0.75rem;
}

@media (min-width: 768px) {
    .bar-row { grid-template-columns: 120px 1fr auto; font-size: 0.82rem; }
}

/* --- Donut / ring chart --- */
.donut-wrap {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    flex-wrap: wrap;
}

.donut {
    flex-shrink: 0;
    width: 150px;
    height: 150px;
    transform: rotate(-90deg);
}

.donut__seg {
    fill: none;
    stroke-width: 15;
    stroke-linecap: butt;
    transition: stroke-dasharray 1.2s cubic-bezier(0.22, 1, 0.36, 1);
}

.donut__center {
    font-family: var(--font-heading);
    fill: var(--mist);
}

.legend {
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
    font-family: var(--font-data);
    font-size: 0.8rem;
}

.legend__item {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    color: var(--mist);
}

.legend__swatch {
    width: 11px;
    height: 11px;
    border-radius: 3px;
    flex-shrink: 0;
}

.legend__value {
    opacity: 0.65;
    margin-left: 0.15rem;
}

/* --- Column chart (population over time) --- */
.column-chart {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 0.6rem;
    height: 190px;
    padding-top: 1rem;
}

.column {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    height: 100%;
    gap: 0.5rem;
}

.column__bar {
    width: 100%;
    max-width: 46px;
    border-radius: 5px 5px 0 0;
    background: linear-gradient(180deg, var(--terracotta), #8E4632);
    height: 0;
    transition: height 1.1s cubic-bezier(0.22, 1, 0.36, 1);
}

.column__bar--now {
    background: linear-gradient(180deg, var(--tier-verified), #2E7D5B);
}

.column__value {
    font-family: var(--font-data);
    font-size: 0.68rem;
    font-weight: 600;
    color: var(--mist);
    white-space: nowrap;
}

.column__label {
    font-family: var(--font-data);
    font-size: 0.68rem;
    color: var(--mist);
    opacity: 0.6;
}

/* 11-topic grid */
.topic-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0.85rem;
}

.topic-card {
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 1.1rem 0.75rem;
    border-radius: var(--radius-soft);
    font-family: var(--font-data);
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--mist);
    transition: border-color 0.3s ease, color 0.3s ease, transform 0.3s ease, background 0.3s ease;
}

.topic-card:hover {
    border-color: var(--terracotta);
    color: var(--terracotta);
    transform: translateY(-3px);
}

.topic-card.is-current {
    border-color: var(--terracotta);
    color: var(--terracotta);
    background: rgba(var(--accent-rgb), 0.1);
}

@media (min-width: 768px) {
    .topic-grid {
        grid-template-columns: repeat(4, 1fr);
    }
}

/* Deep-read typography */
.deep-read {
    max-width: 760px;
    margin: 0 auto;
}

.deep-read__text {
    font-family: var(--font-data);
    font-size: 1rem;
    line-height: 1.85;
    color: var(--mist);
    opacity: 0.9;
    margin-bottom: 1.25rem;
}

.deep-read__text:last-child {
    margin-bottom: 0;
}

/* 4 key highlights row */
.highlight-row {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    max-width: 760px;
    margin: 2.5rem auto 0;
    padding-top: 2rem;
    border-top: 1px solid var(--glass-border);
}

.highlight-item {
    display: flex;
    align-items: center;
    gap: 0.9rem;
}

.highlight-item__icon {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: rgba(var(--accent-rgb), 0.12);
    color: var(--terracotta);
    display: flex;
    align-items: center;
    justify-content: center;
}

.highlight-item__icon svg {
    width: 20px;
    height: 20px;
}

.highlight-item__text {
    font-family: var(--font-data);
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--mist);
}

@media (min-width: 768px) {
    .highlight-row {
        flex-direction: row;
        flex-wrap: wrap;
        justify-content: space-between;
    }

    .highlight-item {
        flex: 1 1 22%;
    }
}

.checklist__mark {
    flex-shrink: 0;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: rgba(var(--verified-rgb), 0.2);
    color: var(--tier-verified);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.75rem;
    font-weight: 700;
}

@media (max-width: 767px) {
    .mega-panel--categories { width: min(320px, 85vw); }
    .mega-panel__grid--categories { grid-template-columns: 1fr; }
}

/* ==========================================================================
   6. NAVIGATION — MOBILE BOTTOM BAR & OVERLAY
   ========================================================================== */
.mobile-nav-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.25rem;
    background: none;
    border: none;
    font-family: var(--font-data);
    font-size: 0.7rem;
    color: var(--mist);
    flex: 1;
}

.mobile-nav-item.active,
.mobile-nav-item[aria-expanded="true"] {
    color: var(--terracotta);
}

.mobile-nav-icon {
    width: 22px;
    height: 22px;
}

@media (min-width: 768px) {
    .mobile-menu-overlay { display: none; }
}

.mobile-menu-overlay {
    position: fixed;
    inset: 0;
    z-index: 1100;
    background: rgba(var(--shade-rgb), 0.7);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1.5rem;
    transform: translateY(100%);
    visibility: hidden;
}

.mobile-menu-overlay__close {
    position: absolute;
    top: 1.5rem;
    right: 1.5rem;
    font-size: 2rem;
    background: none;
    border: none;
    color: var(--mist);
}

.mobile-menu-overlay__links {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1.5rem;
}

.mobile-menu-overlay__link {
    font-family: var(--font-heading);
    font-size: 1.6rem;
    color: var(--mist);
}

.mobile-menu-overlay__link--cta {
    color: var(--terracotta);
}

.mobile-menu-overlay__divider {
    font-family: var(--font-data);
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--terracotta);
    opacity: 0.85;
    margin-top: 0.5rem;
}

.mobile-menu-overlay__link--small {
    font-family: var(--font-data);
    font-size: 1rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    justify-content: center;
}

/* ==========================================================================
   7. HERO — CINEMATIC PARALLAX LAYER
   ========================================================================== */
.hero-cinematic {
    overflow: hidden;
}

/* The hero is always night, whatever palette the reader has chosen.
   The whole opening depends on a light being struck in the dark — a candle on
   a cream page is not a candle. So the hero pins the dark tokens locally
   rather than inheriting them, and the warm ambers in the wick animation stay
   literal: they are a light SOURCE, not a surface, and a flame is the same
   colour in every theme. */
.hero-cinematic {
    --bg: #0D1A15;
    --bg-raised: #16281F;
    --bg-sunk: #081210;
    --ink: #EDF4EF;
    --ink-soft: #C4D4C9;
    --ink-faint: #9DB2A4;
    --line: #2E4438;
    --surface-rgb: 255, 255, 255;
    --shade-rgb: 8, 18, 16;
    --ink-rgb: 237, 244, 239;
    background-color: #0D1A15;
    color: #EDF4EF;
}

.hero-media-layer {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 120vh;
    z-index: 1;
    background: linear-gradient(160deg, var(--canopy-mid), var(--canopy-deep));
    will-change: transform;
}

.hero-media-layer::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, var(--canopy-deep) 0%, transparent 45%, transparent 70%, var(--canopy-deep) 100%);
    pointer-events: none;
}

.hero-content {
    will-change: transform, opacity;
}

.fluid-subtitle {
    font-family: var(--font-data);
    font-size: var(--text-body);
    color: var(--mist);
    opacity: 0.8;
    margin-top: 1rem;
    letter-spacing: 0.02em;
}

.organic-divider {
    position: absolute;
    bottom: -1px;
    left: 0;
    width: 100%;
    z-index: 5;
    line-height: 0;
}

.organic-divider svg {
    display: block;
    width: 100%;
    height: 90px;
}

.organic-divider .shape-fill {
    fill: var(--canopy-deep);
}

/* ==========================================================================
   8. PROVINCIAL STATS — GLASSMORPHIC DATA GRID
   ========================================================================== */
.stats-section {
    padding: 2rem;
    max-width: 1400px;
    margin: 0 auto;
}

.stats-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.5rem;
}

.stat-card {
    position: relative;
    padding: 2rem 1.5rem;
    border-radius: var(--radius-organic);
    text-align: center;
    transition: transform 0.35s ease, border-color 0.35s ease;
}

.stat-tier {
    position: absolute;
    top: 0.85rem;
    right: 0.85rem;
    padding: 0.15rem 0.55rem;
    border-radius: 999px;
    font-family: var(--font-data);
    font-size: 0.6rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.stat-tier--verified {
    background: rgba(var(--verified-rgb), 0.18);
    color: var(--tier-verified);
}

.stat-tier--reported {
    background: rgba(var(--reported-rgb), 0.18);
    color: var(--tier-reported);
}

.stat-tier--contested {
    background: rgba(var(--accent-rgb), 0.18);
    color: var(--terracotta);
}

/* Fourth tier. Verified/Reported/Contested all describe where a figure was
   FOUND; Derived describes a figure that was COMPUTED here and exists in no
   source. It gets its own colour because the reader's question about it is
   different — not "who said this" but "how was this worked out" — and every
   Derived figure on the site is accompanied by its method. */
.stat-tier--derived {
    background: rgba(var(--derived-rgb), 0.16);
    color: var(--tier-derived);
}

.stat-card:hover {
    transform: translateY(-5px);
    border-color: var(--terracotta);
}

.counter,
.stat-unit {
    font-family: var(--font-heading);
    font-size: var(--text-h2);
    color: var(--mist);
}

.stat-label {
    font-family: var(--font-data);
    font-size: 0.9rem;
    color: var(--terracotta);
    margin-top: 0.5rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

.stat-source {
    font-family: var(--font-data);
    font-size: 0.7rem;
    color: var(--mist);
    opacity: 0.55;
    margin-top: 0.5rem;
}

@media (min-width: 768px) {
    .stats-section { padding: 4rem; }
    .stats-grid { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 2rem; }
}

/* Source Legend */
.source-legend {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 1.5rem 2.5rem;
    margin-top: 2rem;
    padding: 1.25rem 1.75rem;
    border-radius: var(--radius-organic);
}

.source-legend__item {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    max-width: 280px;
}

.source-legend__dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
    transform: translateY(-1px);
}

.source-legend__dot--verified { background: var(--tier-verified); }
.source-legend__dot--reported { background: var(--tier-reported); }
.source-legend__dot--contested { background: var(--terracotta); }
.source-legend__dot--derived   { background: var(--tier-derived); }

.source-legend__label {
    font-family: var(--font-data);
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--mist);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    flex-shrink: 0;
}

.source-legend__desc {
    font-family: var(--font-data);
    font-size: 0.75rem;
    color: var(--mist);
    opacity: 0.65;
    line-height: 1.5;
}

/* ==========================================================================
   9. GALLERY — IMMERSIVE MASONRY
   ========================================================================== */
.gallery-section {
    padding: 2rem;
    max-width: 1400px;
    margin: 0 auto;
}

.gallery-header {
    text-align: center;
    margin-bottom: 2rem;
}

.gallery-title {
    font-size: var(--text-h2);
}

.gallery-masonry {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

.gallery-item {
    position: relative;
    overflow: hidden;
    border-radius: var(--radius-soft);
    break-inside: avoid;
    -webkit-column-break-inside: avoid;
}

.gallery-item img {
    display: block;
    width: 100%;
    height: auto;
    transition: transform 0.5s ease;
    background: var(--canopy-mid);
}

.gallery-item figcaption {
    position: absolute;
    left: 0.75rem;
    right: 0.75rem;
    bottom: 0.75rem;
    padding: 0.75rem 1rem;
    border-radius: var(--radius-soft);
    font-family: var(--font-heading);
    font-size: 1rem;
    color: var(--mist);
}

@media (min-width: 768px) {
    .gallery-masonry {
        display: block;
        columns: 3;
        column-gap: 1.5rem;
    }

    .gallery-item {
        margin-bottom: 1.5rem;
        width: 100%;
    }

    .gallery-item figcaption {
        opacity: 0;
        transform: translateY(100%);
        transition: opacity 0.4s ease, transform 0.4s ease;
    }

    .gallery-item:hover img {
        transform: scale(1.03);
    }

    .gallery-item:hover figcaption {
        opacity: 1;
        transform: translateY(0);
    }
}

/* ==========================================================================
   10. INTERACTIVE MASCOT — MONDUL
   ========================================================================== */
#mascot-wrapper {
    position: fixed;
    right: 1.25rem;
    bottom: calc(88px + 0.75rem); /* clears the mobile bottom bar */
    z-index: 1200;
}

.mascot-trigger {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    background: var(--glass-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    border: 1px solid var(--glass-border);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    box-shadow: 0 8px 24px rgba(var(--shade-rgb), 0.25);
}

.mascot-robot {
    width: 48px;
    height: 55px;
    overflow: visible;
}

/* The mascot trigger is a touch larger so the taller robot sits comfortably */
.mascot-trigger {
    width: 72px;
    height: 72px;
}

.mascot-dialogue {
    position: absolute;
    right: 0;
    bottom: calc(100% + 1rem);
    width: min(280px, 80vw);
    padding: 1.25rem;
    border-radius: var(--radius-organic);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

.mascot-dialogue__text {
    font-family: var(--font-data);
    font-size: 0.9rem;
    color: var(--mist);
    line-height: 1.5;
    padding-right: 1.5rem;
}

.mascot-dialogue__close {
    position: absolute;
    top: 0.5rem;
    right: 0.75rem;
    background: none;
    border: none;
    color: var(--mist);
    font-size: 1.25rem;
    cursor: pointer;
}

@media (min-width: 768px) {
    #mascot-wrapper {
        bottom: 2rem;
    }
}

@media (max-width: 767px) {
    .mascot-dialogue {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        width: 100%;
        border-radius: var(--radius-organic) var(--radius-organic) 0 0;
        padding: 2rem 1.5rem calc(2rem + env(safe-area-inset-bottom));
    }

    .mascot-dialogue__text {
        font-size: 1rem;
        padding-right: 2rem;
    }
}

/* ==========================================================================
   11. PROVINCIAL INTELLIGENCE HUB — ATLAS & LEGAL REGISTER
   ========================================================================== */
.hub-layout {
    padding-top: 6rem;   /* clears the fixed mobile top of the page */
    padding-bottom: 6rem; /* clears the mobile bottom nav bar */
}

.atlas-section,
.register-section {
    padding: 2rem;
    max-width: 1400px;
    margin: 0 auto;
}

.atlas-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.5rem;
}

.atlas-map-wrap {
    border-radius: var(--radius-organic);
    overflow: hidden;
    aspect-ratio: 4 / 3;
}

.mapbox-container {
    width: 100%;
    height: 100%;
    min-height: 500px;
    border-radius: var(--radius-soft);
    overflow: hidden;
}

/* De-emphasize Mapbox's default branding so it doesn't clash with the dark theme */
.mapboxgl-ctrl-logo,
.mapboxgl-ctrl-attrib {
    opacity: 0.35;
    filter: grayscale(1);
}

.mapboxgl-ctrl-attrib.mapboxgl-compact {
    background-color: rgba(var(--shade-rgb), 0.6) !important;
}

.mapboxgl-popup-content {
    background: var(--canopy-mid) !important;
    color: var(--mist) !important;
    border-radius: var(--radius-soft) !important;
    font-family: var(--font-data) !important;
}

.mapboxgl-popup-tip {
    border-top-color: var(--canopy-mid) !important;
}

.map-marker {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--terracotta);
    border: 2px solid var(--mist);
    cursor: pointer;
    box-shadow: 0 0 0 4px rgba(var(--accent-rgb), 0.25);
}

/* ==========================================================================
   12. DISCOVER — CINEMATIC HEADER, JOURNEYS GRID & 3D PARALLAX
   ========================================================================== */
.cinematic-header {
    position: relative;
    height: 100vh;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
}

.cinematic-bg {
    position: absolute;
    top: 50%;
    left: 50%;
    min-width: 100%;
    min-height: 100%;
    width: auto;
    height: auto;
    transform: translate(-50%, -50%);
    object-fit: cover;
    z-index: 1;
}

.cinematic-overlay {
    position: absolute;
    inset: 0;
    z-index: 2;
    background: linear-gradient(180deg, rgba(var(--shade-rgb), 0.55) 0%, rgba(var(--shade-rgb), 0.25) 40%, rgba(var(--shade-rgb), 0.75) 100%);
}

.cinematic-content {
    position: relative;
    z-index: 3;
    padding: 2rem;
}

.cinematic-title {
    font-size: var(--text-hero);
    letter-spacing: 2px;
}

.cinematic-subtitle {
    font-family: var(--font-data);
    font-size: var(--text-body);
    color: var(--mist);
    opacity: 0.85;
    margin-top: 1rem;
    max-width: 480px;
    margin-left: auto;
    margin-right: auto;
}

/* Curated Journeys */
.journeys-section {
    padding: 2rem;
    max-width: 1400px;
    margin: 0 auto;
}

.journeys-title {
    font-size: var(--text-h2);
    text-align: center;
    margin-bottom: 2rem;
}

.journeys-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.5rem;
}

/* Lighter-blur glass variant for content cards, per spec */
.glass-panel-light {
    background: rgba(var(--surface-rgb), 0.05);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid var(--glass-border);
    transition: transform 0.35s ease, box-shadow 0.35s ease, border-color 0.35s ease;
}

.journey-card {
    border-radius: var(--radius-organic);
    overflow: hidden;
}

.journey-card:hover {
    transform: translateY(-6px);
    border-color: var(--terracotta);
    box-shadow: 0 12px 32px rgba(var(--accent-rgb), 0.25);
}

.journey-card__media {
    aspect-ratio: 16 / 10;
    background: linear-gradient(135deg, var(--canopy-mid), var(--terracotta));
}

.journey-card__body {
    padding: 1.5rem;
}

.journey-card__title {
    font-size: 1.15rem;
    margin-bottom: 0.5rem;
}

.journey-card__desc {
    font-family: var(--font-data);
    font-size: 0.85rem;
    color: var(--mist);
    opacity: 0.75;
    line-height: 1.5;
    margin-bottom: 0.75rem;
}

.journey-card__meta {
    font-family: var(--font-data);
    font-size: 0.75rem;
    color: var(--terracotta);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

@media (min-width: 768px) {
    .journeys-section { padding: 4rem; }
    .journeys-grid { grid-template-columns: repeat(3, 1fr); }
}

/* 3D Parallax Depth Section */
.parallax-depth-section {
    position: relative;
    min-height: 90vh;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}

.parallax-depth__bg {
    position: absolute;
    inset: -10% 0;
    z-index: 1;
    background: linear-gradient(160deg, var(--canopy-mid), var(--canopy-deep));
}

.parallax-depth__text {
    position: relative;
    z-index: 2;
    max-width: 640px;
    padding: 2rem;
    text-align: center;
}

.parallax-depth__text h2 {
    font-size: var(--text-h2);
    margin-bottom: 1rem;
}

.parallax-depth__text p {
    font-family: var(--font-data);
    font-size: var(--text-body);
    color: var(--mist);
    opacity: 0.8;
    line-height: 1.7;
}

.parallax-depth__foreground {
    position: absolute;
    inset: -15% -5%;
    z-index: 3;
    pointer-events: none;
    background: radial-gradient(ellipse at 20% 30%, rgba(var(--accent-rgb), 0.18), transparent 55%),
                radial-gradient(ellipse at 80% 75%, rgba(var(--verified-rgb), 0.18), transparent 55%);
    /* Swap with a transparent PNG (e.g. an isolated pine branch) via background-image later */
}

/* ==========================================================================
   13. GLOBAL FOOTER
   ========================================================================== */
.global-footer {
    background: #060D0A; /* darker than --canopy-deep, closes out the page */
    border: none;
    border-top: 1px solid var(--glass-border);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    padding: 3rem 2rem 2rem;
}

.footer-grid {
    display: flex;
    flex-direction: column;
    gap: 2.5rem;
    max-width: 1400px;
    margin: 0 auto;
    text-align: center;
}

.footer-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
}

.footer-logo {
    font-family: var(--font-heading);
    font-size: 1.3rem;
    color: var(--mist);
    letter-spacing: 0.04em;
}

.footer-mission,
.footer-copyright,
.footer-disclaimer {
    font-family: var(--font-data);
    font-size: 0.8rem;
    color: var(--mist);
    opacity: 0.7;
    line-height: 1.6;
    max-width: 320px;
}

.footer-col__title {
    font-family: var(--font-data);
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--terracotta);
    margin-bottom: 0.25rem;
}

.footer-links {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.footer-link {
    font-family: var(--font-data);
    font-size: 0.85rem;
    color: var(--mist);
    opacity: 0.7;
    transition: opacity 0.25s ease, color 0.25s ease;
}

.footer-link:hover {
    opacity: 1;
    color: var(--terracotta);
}

@media (max-width: 767px) {
    .global-footer {
        padding-bottom: 80px; /* clears the fixed mobile bottom bar */
    }
}

@media (min-width: 768px) {
    .global-footer {
        padding: 4rem 4rem 3rem;
    }

    .footer-grid {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: 3rem;
        text-align: left;
    }

    .footer-col {
        align-items: flex-start;
    }

    .footer-mission,
    .footer-disclaimer {
        max-width: none;
    }
}

/* ==========================================================================
   14. IMAGE ASSET INTEGRATION
   ========================================================================== */

/* Layout support so the portal background images are actually visible
   (the portal-card/portal-bg pairing was left unstyled until now) */
.portal-card {
    position: relative;
    overflow: hidden;
    border-radius: var(--radius-organic);
    min-height: 360px;
    display: flex;
    align-items: flex-end;
}

.portal-bg {
    position: absolute;
    inset: 0;
    z-index: 1;
    background-size: cover;
    background-position: center;
    transition: transform 0.6s ease;
}

.portal-card:hover .portal-bg {
    transform: scale(1.05);
}

.portal-content {
    position: relative;
    z-index: 2;
    padding: 2rem;
}

.portal-nature {
    background-image: linear-gradient(180deg, rgba(var(--shade-rgb), 0.15) 0%, rgba(var(--shade-rgb), 0.85) 100%), url('images/gallery-4.jpg');
    background-size: cover;
    background-position: center;
}

.portal-data {
    background-image: linear-gradient(180deg, rgba(var(--shade-rgb), 0.15) 0%, rgba(var(--shade-rgb), 0.85) 100%), url('images/gallery-3.jpg');
    background-size: cover;
    background-position: center;
}

.bg-waterfall {
    background-image: url('images/gallery-2.jpg');
    background-size: cover;
    background-position: center;
}

.bg-pine {
    background-image: url('images/gallery-1.jpg');
    background-size: cover;
    background-position: center;
}

.portal-living {
    background-image: linear-gradient(180deg, rgba(var(--shade-rgb), 0.15) 0%, rgba(var(--shade-rgb), 0.85) 100%), url('images/gallery-5.jpg');
    background-size: cover;
    background-position: center;
}

.portal-business {
    background-image: linear-gradient(160deg, var(--canopy-mid), var(--canopy-deep));
}

.portal-takepart {
    background-image: linear-gradient(160deg, var(--terracotta), var(--canopy-deep));
}

/* Legal register: disputed-data styling used by the new rows below */
.register-flag {
    display: inline-block;
    margin-left: 0.5rem;
    padding: 0.15rem 0.6rem;
    border-radius: 999px;
    background: rgba(var(--accent-rgb), 0.18);
    color: var(--terracotta);
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    vertical-align: middle;
}

.register-note {
    display: block;
    font-family: var(--font-data);
    font-size: 0.75rem;
    color: var(--mist);
    opacity: 0.65;
    margin-top: 0.35rem;
    line-height: 1.5;
}

.register-row--disputed td:first-child {
    box-shadow: inset 3px 0 0 var(--terracotta);
}

/* ==========================================================================
   15. GLASSMORPHIC ACCORDION
   ========================================================================== */
.accordion-section {
    padding: 2rem;
    max-width: 900px;
    margin: 0 auto;
}

.accordion-section__title {
    font-size: var(--text-h2);
    text-align: center;
    margin-bottom: 2rem;
}

.accordion-item + .accordion-item {
    margin-top: 1rem;
}

.accordion-header {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 1.25rem 1.5rem;
    border-radius: var(--radius-organic);
    font-family: var(--font-heading);
    font-size: 1.05rem;
    color: var(--mist);
    cursor: pointer;
    transition: border-color 0.3s ease;
}

.accordion-header[aria-expanded="true"] {
    border-color: var(--terracotta);
}

.accordion-icon {
    font-family: var(--font-data);
    font-size: 1.3rem;
    color: var(--terracotta);
    transition: transform 0.35s ease;
    flex-shrink: 0;
    margin-left: 1rem;
}

.accordion-header[aria-expanded="true"] .accordion-icon {
    transform: rotate(45deg);
}

.accordion-panel {
    height: 0;
    overflow: hidden;
}

.accordion-panel__inner {
    padding: 1.5rem 1.75rem 0.5rem;
}

.accordion-panel__inner p {
    font-family: var(--font-data);
    font-size: 0.9rem;
    line-height: 1.7;
    color: var(--mist);
    opacity: 0.85;
    margin-bottom: 1rem;
}

.accordion-panel__inner p:last-child {
    margin-bottom: 0;
}

.accordion-panel__inner h3 {
    font-family: var(--font-heading);
    font-size: 1rem;
    font-weight: 400;
    color: var(--terracotta);
    margin: 1.25rem 0 0.5rem;
}

.accordion-panel__inner h3:first-child {
    margin-top: 0;
}

.accordion-panel__inner ul {
    list-style: none;
    margin: 0 0 1rem;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.accordion-panel__inner li {
    position: relative;
    padding-left: 1.25rem;
    font-family: var(--font-data);
    font-size: 0.88rem;
    line-height: 1.6;
    color: var(--mist);
    opacity: 0.85;
}

.accordion-panel__inner li::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0.55em;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--terracotta);
}

@media (min-width: 768px) {
    .accordion-section { padding: 4rem; }
}

.atlas-layers__title {
    font-size: 1.1rem;
    margin-bottom: 1rem;
}

.layer-toggle-row {
    display: flex;
    gap: 0.75rem;
    overflow-x: auto;
    padding-bottom: 0.5rem;
    -webkit-overflow-scrolling: touch;
}

.layer-toggle {
    flex: 0 0 auto;
    padding: 0.6rem 1.1rem;
    border-radius: var(--radius-organic);
    font-family: var(--font-data);
    font-size: 0.85rem;
    color: var(--mist);
    white-space: nowrap;
    cursor: pointer;
    transition: border-color 0.3s ease, color 0.3s ease;
}

.layer-toggle.is-active {
    border-color: var(--terracotta);
    color: var(--terracotta);
    background: rgba(var(--accent-rgb), 0.12);
}

/* ==========================================================================
   20c. HERO — METAMORPHOSIS
   --------------------------------------------------------------------------
   The switch and its label draw themselves together into a point of light
   and go out, leaving the lit word and the site behind them.

   Two decisions worth stating, because they drive most of the code below:

   Nothing here moves the word: throwing the switch changes its luminance and
   nothing else. The switch is the only thing that transforms.
   ========================================================================== */
.hero-content { position: relative; }

/* ---- The word: light rises inside the letters, nothing moves ---- */
.hero-title .ltr {
    display: inline-block;
    opacity: 0;
    will-change: opacity, filter;
}

.is-lit .hero-title .ltr {
    animation: wick-up 3.4s cubic-bezier(0.38, 0.05, 0.24, 1) both;
    animation-delay: calc(0.3s + var(--l) * 95ms);
}

@keyframes wick-up {
    0%   { opacity: 0;    filter: brightness(0.25); }
    30%  { opacity: 0.22; filter: brightness(0.45); }
    62%  { opacity: 0.62; filter: brightness(0.75); }
    100% { opacity: 1;    filter: brightness(1); }
}

/* --- Returning within the same browser session -----------------------------
   The word is already lit and the switch is already gone. No 3.4s wick-up to
   sit through, no stagger, no fade: the visitor has seen the performance and
   now just wants the site. Overrides the animations rather than removing the
   classes, so the two states share one set of rules.
   -------------------------------------------------------------------------- */
.is-lit-now .hero-title .ltr {
    animation: none !important;
    opacity: 1;
    filter: none;
}

.is-lit-now .hero-sub {
    animation: none !important;
    opacity: 1;
}

.is-lit-now .lightswitch {
    display: none;
}

.hero-sub { opacity: 0; }
.is-lit .hero-sub { animation: sub-glow 2.4s ease both; animation-delay: 2.4s; }
@keyframes sub-glow { from { opacity: 0; } to { opacity: 1; } }

/* ==========================================================================
   0 · THE SWITCH
   --------------------------------------------------------------------------
   It is not a control that gets dismissed. Throwing it warms the contacts,
   and then the switch body and its label draw themselves together into the
   point of light — the control the visitor touched is consumed by the act of
   using it.
   ========================================================================== */
.lightswitch {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.95rem;
    z-index: 15;
    transform-origin: 50% 50%;
    animation: switch-arrive 1.6s cubic-bezier(0.16, 1, 0.3, 1) 0.35s both;
}

@keyframes switch-arrive {
    from { opacity: 0; transform: translate(-50%, calc(-50% + 14px)) scale(0.94); filter: blur(4px); }
    to   { opacity: 1; transform: translate(-50%, -50%) scale(1); filter: blur(0); }
}

.lightswitch__btn { background: none; border: none; cursor: pointer; padding: 0; }

.lightswitch__track {
    display: block;
    width: 76px;
    height: 38px;
    border-radius: 999px;
    background: rgba(var(--surface-rgb), 0.06);
    border: 1px solid var(--glass-border);
    position: relative;
    transition: background 0.5s ease, border-color 0.5s ease, box-shadow 0.5s ease;
}

.lightswitch__knob {
    position: absolute;
    top: 3px;
    left: 3px;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: #7C8C85;
    transition: transform 0.7s var(--spring), background 0.7s ease, box-shadow 0.7s ease, opacity 0.5s ease;
}

.lightswitch__btn:hover .lightswitch__track { border-color: rgba(var(--accent-rgb), 0.6); }

.lightswitch__hint {
    font-family: var(--font-data);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.24em;
    color: var(--mist);
    opacity: 0.5;
    animation: hint-breathe 2.8s ease-in-out infinite;
}

@keyframes hint-breathe { 0%, 100% { opacity: 0.32; } 50% { opacity: 0.78; } }

/* --- Warming: contacts close, heat fills the track --- */
.lightswitch.is-warming .lightswitch__track {
    animation: track-warm 1.2s cubic-bezier(0.3, 0, 0.2, 1) forwards;
}

@keyframes track-warm {
    0%   { background: rgba(var(--surface-rgb), 0.06); border-color: var(--glass-border);
           box-shadow: 0 0 0 0 rgba(255,196,140,0); }
    100% { background: rgba(255, 178, 110, 0.52); border-color: rgba(255, 206, 150, 1);
           box-shadow: 0 0 60px -6px rgba(255, 200, 140, 0.9); }
}

.lightswitch.is-warming .lightswitch__knob {
    transform: translateX(38px);
    background: #FFE6BE;
    box-shadow: 0 0 30px 8px rgba(255, 214, 164, 0.9);
}

/* --- The switch becomes a point of light.
       The track squashes and rounds into a body; the label letters are pulled
       inward as their tracking collapses, and both blur out at the same
       moment it goes out. --- */
.lightswitch.is-becoming .lightswitch__track {
    animation: track-to-body 1.6s cubic-bezier(0.5, 0, 0.25, 1) forwards;
}

@keyframes track-to-body {
    0%   { width: 76px; height: 38px; border-radius: 999px;
           background: rgba(255,190,120,0.5);
           box-shadow: 0 0 60px -6px rgba(255,200,140,0.9);
           transform: rotate(0deg); filter: brightness(1); }
    42%  { width: 58px; height: 42px; border-radius: 56px / 46px;
           background: linear-gradient(150deg, #F0B15C 0%, #C4642F 55%, #8E3F24 100%);
           box-shadow: 0 0 70px -4px rgba(255,214,168,0.95);
           transform: rotate(-4deg); filter: brightness(1.5); }
    /* Hold fully opaque here, then collapse: the switch does not linger,
       so the two overlap instead of leaving a frame where neither is solid. */
    68%  { width: 46px; height: 44px; border-radius: 46px / 44px;
           background: linear-gradient(150deg, #FFE3B4 0%, #F0B15C 55%, #C4642F 100%);
           box-shadow: 0 0 90px 4px rgba(255,238,206,1);
           transform: rotate(2deg); opacity: 1; filter: brightness(2.8); }
    /* Ends as almost pure light, then nothing.
       "cool into being" animation starts — so the hand-off has no seam. */
    100% { width: 40px; height: 42px; border-radius: 44px / 42px;
           background: #FFF4DF;
           box-shadow: 0 0 110px 10px rgba(255,244,223,0.95);
           transform: rotate(7deg); opacity: 0; filter: brightness(4.4) blur(2px); }
}

.lightswitch.is-becoming .lightswitch__knob { opacity: 0; transform: translateX(30px) scale(0.4); }

/* The label is drawn in rather than blown apart — it is being absorbed */
.lightswitch.is-becoming .lightswitch__hint {
    animation: hint-absorb 1.1s cubic-bezier(0.5, 0, 0.3, 1) forwards;
}

@keyframes hint-absorb {
    0%   { opacity: 0.6; letter-spacing: 0.24em; filter: blur(0);   transform: scale(1); }
    55%  { opacity: 0.45; letter-spacing: 0.02em; filter: blur(1px); transform: scale(0.8); }
    100% { opacity: 0;   letter-spacing: -0.18em; filter: blur(5px); transform: scale(0.35); }
}

.lightswitch.is-spent { opacity: 0; pointer-events: none; }

/* ==========================================================================
   1b · THE LOCKOUT — nothing works until the light is on
   --------------------------------------------------------------------------
   The hero asks the visitor to do exactly one thing. Until they do it, the
   rest of the site should not be available: no scrolling, no navigation, no
   mascot, no links. Three mechanisms, because any one of them alone leaves a
   way through:

     · a fixed transparent veil above everything, which absorbs pointer events
     · overflow:hidden on html and body, which stops wheel and touch scrolling
     · `inert` on every region outside the hero, which stops keyboard access
       (Tab, Enter) and removes them from the accessibility tree

   The switch itself is lifted above the veil so it stays clickable. All of it
   is applied and removed from JS, so a visitor with JavaScript disabled is
   never trapped behind a veil that nothing can dismiss.
   ========================================================================== */
/* NO VEIL.

   There used to be a fixed transparent overlay here to absorb clicks. It could
   never have worked: `.hero-content` carries `position: relative; z-index: 10`,
   which makes it a STACKING CONTEXT, so the switch's own z-index is resolved
   inside that context and can never rise above 10 against the page. The veil at
   z-index 1100 therefore sat on top of the one control the visitor is asked to
   use, and swallowed every click.

   It is also unnecessary. `visibility: hidden` on the gated regions already
   blocks pointer events and keyboard focus, `inert` removes them from the
   accessibility tree, and `overflow: hidden` locks scrolling. Deleting the veil
   removes the trap rather than patching around it. */

/* --- Everything else is not dimmed, it is ABSENT ---------------------------
   On first open the visitor should see one thing: the switch, alone on a dark
   field. No logo, no menu, no Search button, no mascot, no headline — nothing
   to read and nothing to click. The switch is the key, so it has to be the
   only object in the room.

   `visibility: hidden` rather than `display: none` on purpose: hidden elements
   keep their box, so the layout is already settled when they appear and
   nothing jumps as the site comes up. It also keeps them out of the
   accessibility tree, which matches the `inert` applied alongside it.
   -------------------------------------------------------------------------- */
body.is-pre-lit .nav-desktop,
body.is-pre-lit .nav-mobile,
body.is-pre-lit .mascot-dock,
body.is-pre-lit #mascot-wrapper,
body.is-pre-lit #mascot-trigger,
body.is-pre-lit .scroll-progress,
body.is-pre-lit .section-rail,
body.is-pre-lit footer,
body.is-pre-lit main > section:not(.hero-cinematic),
body.is-pre-lit .hero-cinematic > *:not(.hero-content),
body.is-pre-lit .organic-divider {
    opacity: 0;
    visibility: hidden;
}

/* The site comes up gently once the switch is thrown — the chrome arrives a
   beat after the word, so the word is what you notice first. */
/* Note: .section-rail is deliberately NOT in this list. It carries its own
   transition for the hero stow behaviour, and a second shorthand here would
   replace it — the rail would snap into place instead of sliding. */
/* #mascot-dialogue is deliberately NOT in this list.

   It was, and that made the question box take about two and a half seconds to
   appear. GSAP animates the panel open by writing inline opacity, and this
   rule made the browser transition every one of those writes over 1.4s after
   a 1.2s delay — so a 0.14s open became a 2.6s crawl. The panel is nested
   inside #mascot-wrapper, which is already hidden before the light is on, so
   it needs neither the transition nor its own pre-lit rule.

   Same failure as the section rail: a CSS transition quietly re-timing a
   property that JS is trying to drive. Worth checking for whenever something
   animated by script feels slower than the duration says it should be. */
.nav-desktop, .nav-mobile, .mascot-dock, #mascot-wrapper, #mascot-trigger,
.scroll-progress, footer, .organic-divider {
    transition: opacity 1.4s ease 1.2s, visibility 1.4s ease 1.2s;
}

main > section:not(.hero-cinematic) {
    transition: opacity 1.2s ease 0.9s, visibility 1.2s ease 0.9s;
}

/* No-JS / reduced motion: the word is simply lit, and no creature appears */
.no-js .hero-title .ltr,
.no-js .hero-sub { opacity: 1; filter: none; }
.no-js .lightswitch { display: none; }

@media (prefers-reduced-motion: reduce) {
    .hero-title .ltr { opacity: 1; filter: none; animation: none !important; }
    .hero-sub { opacity: 1; animation: none !important; }
    .lightswitch { display: none; }
}

/* ==========================================================================
   20d. SECTION RAIL — absent over the hero
   --------------------------------------------------------------------------
   A full-bleed hero is a single statement; a table of contents pinned beside
   it is noise, and it competes with the one thing the visitor is meant to do
   (throw the switch). The rail belongs to the content, so it arrives with the
   content — it slides in once the hero has been scrolled past, and slides
   back out if the visitor returns to the top.
   ========================================================================== */
.section-rail.is-stowed {
    opacity: 0;
    transform: translateX(-115%);
    pointer-events: none;
    visibility: hidden;
}

.section-rail {
    transition: background 0.3s ease,
                opacity 0.45s ease,
                transform 0.55s cubic-bezier(0.16, 1, 0.3, 1),
                visibility 0.55s;
}

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

/* ==========================================================================
   21. SPATIAL SECTION TRANSITIONS — macOS-style "absorb / emerge"
   --------------------------------------------------------------------------
   Only transform, opacity and filter are touched. No width/height/margin, so
   the browser never re-lays-out the heavy commune and legal tables mid-flight.
   ========================================================================== */
:root {
    /* Overshoots slightly past 1 then settles — the Apple "physical" feel */
    --spring: cubic-bezier(0.175, 0.885, 0.32, 1.275);
    /* No overshoot, for the recede — things fall away, they don't bounce away */
    --absorb: cubic-bezier(0.4, 0, 0.2, 1);
    --dur-exit: 260ms;
    --dur-enter: 620ms;
}

/* Sections are their own compositing + containment scope so a transform on one
   can never force the rest of the document to re-layout. */
main section[id],
main .district-explorer {
    transform-origin: 50% 40%;
    /* NOT `contain: paint` — that clips descendants to the padding box and
       would cut off the card hover glow. Layout + style gives the isolation
       we need without the clipping. */
    contain: layout style;
}

/* ---- THE EXIT: absorbed backward into the screen ---- */
.is-exiting {
    animation: absorb-back var(--dur-exit) var(--absorb) both;
    pointer-events: none;   /* nothing clickable while it's receding */
    will-change: transform, opacity, filter;
}

@keyframes absorb-back {
    from {
        transform: scale(1) translate3d(0, 0, 0);
        opacity: 1;
        filter: blur(0px);
    }
    to {
        transform: scale(0.95) translate3d(0, 8px, 0);
        opacity: 0.35;
        /* Deliberately small — blur is the one expensive property here, and a
           heavy value over a large data table costs real frames. 3px reads as
           depth without the cost. */
        filter: blur(3px);
    }
}

/* ---- THE ENTRANCE: springs forward into sharp focus ---- */
.is-entering {
    animation: emerge-forward var(--dur-enter) var(--spring) both;
    will-change: transform, opacity, filter;
}

@keyframes emerge-forward {
    0% {
        transform: scale(0.94) translate3d(0, 18px, 0);
        opacity: 0;
        filter: blur(4px);
    }
    55% {
        opacity: 1;
        filter: blur(0px);
    }
    100% {
        transform: scale(1) translate3d(0, 0, 0);
        opacity: 1;
        filter: blur(0px);
    }
}

/* Drop the compositing hint the moment the animation is done */
.is-exiting,
.is-entering { backface-visibility: hidden; }

section[id]:not(.is-exiting):not(.is-entering) { will-change: auto; }

/* ---- Native View Transitions, where the browser has them ---- */
@supports (view-transition-name: none) {
    ::view-transition-old(root) {
        animation: absorb-back var(--dur-exit) var(--absorb) both;
    }
    ::view-transition-new(root) {
        animation: emerge-forward var(--dur-enter) var(--spring) both;
    }
}

/* Reduced motion: no spatial choreography at all */
@media (prefers-reduced-motion: reduce) {
    .is-exiting,
    .is-entering {
        animation: none !important;
        opacity: 1 !important;
        transform: none !important;
        filter: none !important;
    }
    ::view-transition-old(root),
    ::view-transition-new(root) { animation: none !important; }
}

/* ==========================================================================
   22. IMAGE SYSTEM — attribution, lazy loading, graceful empty state
   --------------------------------------------------------------------------
   Almost every freely-licensed photo (CC BY / CC BY-SA) legally REQUIRES
   visible credit. This system makes the credit part of the component, so an
   image can't be added without one.
   ========================================================================== */
.figure-credited {
    position: relative;
    margin: 0;
    border-radius: var(--radius-soft);
    overflow: hidden;
    background: linear-gradient(160deg, var(--canopy-mid), var(--canopy-deep));
}

.figure-credited img {
    display: block;
    width: 100%;
    height: auto;
    opacity: 0;
    transform: scale(1.03);
    transition: opacity 0.7s var(--ease-out-expo), transform 1.1s var(--ease-out-expo);
}

.figure-credited img.is-loaded {
    opacity: 1;
    transform: scale(1);
}

/* Credit strip — always visible, because attribution isn't decoration */
.figure-credit {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 0.5rem 0.7rem;
    font-family: var(--font-data);
    font-size: 0.62rem;
    line-height: 1.4;
    color: var(--mist);
    background: linear-gradient(transparent, rgba(var(--shade-rgb), 0.88));
    opacity: 0.85;
}

.figure-credit a { color: var(--mist); text-decoration: underline; }
.figure-credit__licence { color: var(--terracotta); font-weight: 600; }

/* Shown when the image file isn't present yet */
.img-placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    aspect-ratio: 4 / 3;
    padding: 1.5rem;
    text-align: center;
    border: 1px dashed rgba(var(--accent-rgb), 0.4);
    border-radius: var(--radius-soft);
    background: rgba(var(--accent-rgb), 0.04);
}

.img-placeholder__icon { color: var(--terracotta); opacity: 0.65; }

.img-placeholder__name {
    font-family: var(--font-data);
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--terracotta);
}

.img-placeholder__hint {
    font-family: var(--font-data);
    font-size: 0.66rem;
    color: var(--mist);
    opacity: 0.6;
    line-height: 1.5;
    max-width: 30ch;
}

/* Explains what the selected layer actually shows */
.map-layer-note {
    margin-top: 0.9rem;
    padding: 0.8rem 0.95rem;
    border-radius: var(--radius-soft);
    background: rgba(var(--surface-rgb), 0.03);
    border-left: 2px solid var(--terracotta);
    font-family: var(--font-data);
    font-size: 0.78rem;
    line-height: 1.6;
    color: var(--mist);
    opacity: 0.85;
}

.map-layer-note strong { color: var(--terracotta); }

/* Shown in place of the map when no Mapbox token is configured */
.map-fallback {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    height: 100%;
    min-height: 320px;
    padding: 2rem;
    text-align: center;
    color: var(--mist);
    background:
        radial-gradient(ellipse at 30% 20%, rgba(var(--accent-rgb), 0.10), transparent 60%),
        linear-gradient(160deg, var(--canopy-mid), var(--canopy-deep));
}

.map-fallback svg { color: var(--terracotta); opacity: 0.8; }

.map-fallback__title {
    font-family: var(--font-heading);
    font-size: 1.05rem;
    color: var(--mist);
}

.map-fallback__body {
    font-family: var(--font-data);
    font-size: 0.8rem;
    line-height: 1.6;
    opacity: 0.75;
    max-width: 42ch;
}

.map-fallback code {
    font-size: 0.74rem;
    padding: 0.1rem 0.35rem;
    border-radius: 4px;
    background: rgba(var(--surface-rgb), 0.08);
    color: var(--terracotta);
}

.register-title {
    font-size: var(--text-h2);
    margin-bottom: 1.5rem;
}

.register-table-wrap {
    border-radius: var(--radius-organic);
    overflow-x: auto;
    padding: 0.5rem;
}

.register-table {
    width: 100%;
    border-collapse: collapse;
    font-family: var(--font-data);
}

.register-table th,
.register-table td {
    text-align: left;
    padding: 1rem;
    font-size: 0.9rem;
    color: var(--mist);
    border-bottom: 1px solid var(--glass-border);
}

.register-table th {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--terracotta);
    font-weight: 600;
}

.register-table tbody tr:last-child td {
    border-bottom: none;
}

@media (min-width: 768px) {
    .hub-layout {
        padding-top: 8rem;
        padding-bottom: 3rem;
    }

    .atlas-section,
    .register-section {
        padding: 4rem;
    }

    .atlas-grid {
        grid-template-columns: 2fr 1fr;
        align-items: start;
    }

    .layer-toggle-row {
        flex-direction: column;
        overflow-x: visible;
    }
}

@media (max-width: 767px) {
    /* Keep only Title/Subject visible — Instrument Type, Date, Source hidden */
    .register-table th:nth-child(1),
    .register-table th:nth-child(3),
    .register-table th:nth-child(4),
    .register-table td:nth-child(1),
    .register-table td:nth-child(3),
    .register-table td:nth-child(4) {
        display: none;
    }
}

/* ==========================================================================
   17. WORLD-CLASS POLISH — GRAIN, CURSOR GLOW, PAGE ENTRY, PREMIUM DEPTH
   ========================================================================== */

/* Fine film-grain texture over the whole page — the single biggest cheap
   upgrade toward a "premium" rather than "flat gradient" feel. */
body.biome-theme::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 9998;
    pointer-events: none;
    opacity: 0.035;
    mix-blend-mode: overlay;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}

/* Page-entry fade so navigating between pages never feels like a hard cut.
   The keyframe is a safety net: if JS is blocked/slow, the page still
   reveals itself on its own after ~1.2s rather than staying blank. */
@keyframes force-reveal { to { opacity: 1; } }

body.biome-theme {
    opacity: 0;
    animation: force-reveal 0.6s 0.7s ease forwards;
}

body.biome-theme.is-ready {
    animation: none;
    opacity: 1;
    transition: opacity 0.5s ease;
}

/* Slightly richer glass-panel depth + a subtle terracotta glow on hover,
   applied globally so every card in the site benefits without extra markup */
.glass-panel,
.glass-panel-light {
    box-shadow: 0 4px 24px rgba(var(--shade-rgb), 0.18);
    transition: box-shadow 0.4s ease, border-color 0.4s ease, transform 0.4s ease;
}

.stat-card:hover,
.info-card:hover,
.district-card:hover,
.journey-card:hover,
.attraction-card:hover {
    box-shadow: 0 16px 40px rgba(var(--shade-rgb), 0.3), 0 0 0 1px rgba(var(--accent-rgb), 0.15);
}

/* Smoother, more premium reveal-on-scroll used by [data-reveal] elements */
[data-reveal] {
    opacity: 0;
    transform: translateY(24px);
}

/* ==========================================================================
   17a. DISTRICT & COMMUNE EXPLORER (Deep administrative drill-down)
   ========================================================================== */
.district-explorer {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.district-acc {
    border-radius: var(--radius-organic);
    overflow: hidden;
}

.district-acc__header {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 1.25rem 1.5rem;
    background: transparent;
    border: none;
    cursor: pointer;
    text-align: left;
    color: var(--mist);
}

.district-acc__name {
    font-family: var(--font-heading);
    font-size: 1.15rem;
}

.district-acc__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1rem;
    margin-top: 0.35rem;
    font-family: var(--font-data);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--terracotta);
    opacity: 0.85;
}

.district-acc__icon {
    flex-shrink: 0;
    font-family: var(--font-data);
    font-size: 1.3rem;
    color: var(--terracotta);
    transition: transform 0.35s ease;
}

.district-acc__header[aria-expanded="true"] .district-acc__icon {
    transform: rotate(45deg);
}

.district-acc__panel {
    height: 0;
    overflow: hidden;
}

.district-acc__inner {
    padding: 0 1.5rem 1.75rem;
}

.district-acc__summary {
    font-family: var(--font-data);
    font-size: 0.88rem;
    line-height: 1.7;
    color: var(--mist);
    opacity: 0.85;
    margin-bottom: 1.25rem;
}

.commune-table-wrap {
    overflow-x: auto;
    border-radius: var(--radius-soft);
}

.commune-table {
    width: 100%;
    min-width: 480px;
    border-collapse: collapse;
    font-family: var(--font-data);
}

.commune-table th,
.commune-table td {
    text-align: left;
    padding: 0.7rem 0.85rem;
    font-size: 0.82rem;
    color: var(--mist);
    border-bottom: 1px solid var(--glass-border);
    white-space: nowrap;
}

.commune-table th {
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--terracotta);
    font-weight: 600;
}

.commune-table tbody tr:last-child td { border-bottom: none; }
.commune-table tbody tr:hover { background: rgba(var(--surface-rgb), 0.02); }

.district-acc__potential {
    margin-top: 1.25rem;
    padding: 1rem 1.25rem;
    border-radius: var(--radius-soft);
    background: rgba(var(--accent-rgb), 0.06);
    border-left: 3px solid var(--terracotta);
}

.district-acc__potential-title {
    font-family: var(--font-data);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--terracotta);
    margin-bottom: 0.4rem;
}

.district-acc__potential-text {
    font-family: var(--font-data);
    font-size: 0.85rem;
    line-height: 1.6;
    color: var(--mist);
    opacity: 0.85;
}

/* ==========================================================================
   17b. TOURISM VISITOR GUIDE — attractions, seasons, costs, practical grid
   ========================================================================== */
.guide-section {
    padding: 2rem;
    max-width: 1400px;
    margin: 0 auto;
}

.guide-section__title {
    font-size: var(--text-h2);
    margin-bottom: 0.5rem;
}

.guide-section__intro {
    font-family: var(--font-data);
    font-size: 0.9rem;
    color: var(--mist);
    opacity: 0.75;
    max-width: 640px;
    margin-bottom: 2rem;
    line-height: 1.6;
}

/* Attractions grid */
.attraction-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.5rem;
}

.attraction-card {
    border-radius: var(--radius-organic);
    padding: 1.5rem;
}

.attraction-card__title {
    font-size: 1.05rem;
    margin-bottom: 0.4rem;
}

.attraction-card__meta {
    font-family: var(--font-data);
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--terracotta);
    margin-bottom: 0.75rem;
}

.attraction-card__body {
    font-family: var(--font-data);
    font-size: 0.85rem;
    line-height: 1.65;
    color: var(--mist);
    opacity: 0.85;
}

@media (min-width: 768px) {
    .guide-section { padding: 4rem; }
    .attraction-grid { grid-template-columns: repeat(2, 1fr); }
}

/* Season timeline */
.season-timeline {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 0.5rem;
    border-radius: var(--radius-organic);
    padding: 1.5rem;
    overflow-x: auto;
}

.season-block {
    padding: 1rem 0.5rem;
    border-radius: var(--radius-soft);
    text-align: center;
}

.season-block--best { background: rgba(var(--verified-rgb), 0.12); }
.season-block--shoulder { background: rgba(var(--reported-rgb), 0.1); }
.season-block--wet { background: rgba(var(--accent-rgb), 0.1); }

.season-block__months {
    font-family: var(--font-data);
    font-weight: 700;
    font-size: 0.8rem;
    color: var(--mist);
    margin-bottom: 0.25rem;
}

.season-block__label {
    font-family: var(--font-data);
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--mist);
    opacity: 0.7;
}

@media (max-width: 767px) {
    .season-timeline { grid-template-columns: repeat(4, minmax(120px, 1fr)); }
}

/* Practical info grid + cost table */
.practical-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.25rem;
}

@media (min-width: 768px) {
    .practical-grid { grid-template-columns: repeat(3, 1fr); }
}

.cost-table-wrap {
    border-radius: var(--radius-organic);
    overflow-x: auto;
    padding: 0.5rem;
}

.cost-table {
    width: 100%;
    border-collapse: collapse;
    font-family: var(--font-data);
}

.cost-table th,
.cost-table td {
    text-align: left;
    padding: 0.85rem 1rem;
    font-size: 0.85rem;
    color: var(--mist);
    border-bottom: 1px solid var(--glass-border);
}

.cost-table th {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--terracotta);
}

.cost-table tbody tr:last-child td { border-bottom: none; }

/* ==========================================================================
   17c. SMART MASCOT — quick-chips, input, tier badges, typing indicator
   ========================================================================== */
.mascot-dialogue {
    width: min(340px, 85vw);
    max-height: min(70vh, 520px);
    overflow-y: auto;
}

/* THE bug that made the mascot look dead: the dialogue is pointer-events:none
   by default, and GSAP's autoAlpha only animates opacity + visibility — it never
   restores pointer-events. So the panel appeared but every click and keystroke
   fell straight through it. The open/close code already maintains aria-hidden,
   so keying off that re-enables interaction on all pages with no JS change. */
.mascot-dialogue[aria-hidden="false"] {
    pointer-events: auto;
}

.mascot-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-top: 0.9rem;
}

.mascot-chip {
    font-family: var(--font-data);
    font-size: 0.7rem;
    padding: 0.4rem 0.75rem;
    border-radius: 999px;
    background: rgba(var(--surface-rgb), 0.05);
    border: 1px solid var(--glass-border);
    color: var(--mist);
    cursor: pointer;
    transition: border-color 0.25s ease, color 0.25s ease;
}

.mascot-chip:hover {
    border-color: var(--terracotta);
    color: var(--terracotta);
}

.mascot-answer-tier {
    display: inline-block;
    font-family: var(--font-data);
    font-size: 0.58rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    margin-bottom: 0.5rem;
}

/* ==========================================================================
   20. MOTION SYSTEM — pure CSS. JS only adds/removes classes.
   --------------------------------------------------------------------------
   Tuning knobs. Change these and the whole platform's feel changes with it.
   ========================================================================== */
:root {
    --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
    --ease-out-back: cubic-bezier(0.34, 1.4, 0.64, 1);
    --dur-fast: 0.28s;
    --dur-base: 0.6s;
    --dur-slow: 0.9s;
    --stagger: 70ms;      /* gap between items in a staggered wave */
}

/* --------------------------------------------------------------------------
   KEYFRAMES
   -------------------------------------------------------------------------- */
@keyframes fade-up {
    from { opacity: 0; transform: translate3d(0, 26px, 0); }
    to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

@keyframes logo-in {
    0%   { opacity: 0; transform: translate3d(-14px, 0, 0); letter-spacing: 0.3em; }
    60%  { opacity: 1; }
    100% { opacity: 1; transform: translate3d(0, 0, 0); letter-spacing: 0.04em; }
}

@keyframes ripple-out {
    from { transform: scale(0);   opacity: 0.45; }
    to   { transform: scale(2.4); opacity: 0; }
}

@keyframes ledger-drop {
    0%   { opacity: 0; transform: translate3d(0, -18px, 0) scale(0.98); }
    60%  { opacity: 1; }
    100% { opacity: 1; transform: translate3d(0, 0, 0) scale(1); }
}

@keyframes focus-glow {
    0%, 100% { box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.14); }
    50%      { box-shadow: 0 0 0 5px rgba(var(--accent-rgb), 0.22); }
}

/* --------------------------------------------------------------------------
   TIER 1 — CINEMATIC ENTRANCE
   The logo animates on load; hero children stagger via the --i index that JS
   writes onto each element.
   -------------------------------------------------------------------------- */
.boot-logo {
    animation: logo-in 1.1s var(--ease-out-expo) both;
}

.boot-item {
    opacity: 0;
    transform: translate3d(0, 22px, 0);
}

.is-booted .boot-item {
    animation: fade-up var(--dur-slow) var(--ease-out-expo) both;
    animation-delay: calc(0.25s + var(--i, 0) * 120ms);
}

/* --------------------------------------------------------------------------
   TIER 2 — SCROLL REVEALS
   `.reveal` is the resting (hidden) state; `.is-visible` is added by the
   IntersectionObserver. --i staggers grid children into a wave.
   -------------------------------------------------------------------------- */
.reveal {
    opacity: 0;
    transform: translate3d(0, 26px, 0);
    transition:
        opacity var(--dur-base) var(--ease-out-expo),
        transform var(--dur-base) var(--ease-out-expo);
    transition-delay: calc(var(--i, 0) * var(--stagger));
    will-change: opacity, transform;
}

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

/* Table rows come in from the side — reads as data loading, not content sliding */
.reveal--row {
    transform: translate3d(-16px, 0, 0);
    transition-delay: calc(var(--i, 0) * 45ms);
}

.reveal--row.is-visible { transform: translate3d(0, 0, 0); }

/* Once revealed, drop will-change so we're not holding GPU layers forever */
.reveal.is-visible { will-change: auto; }

/* --------------------------------------------------------------------------
   TIER 3 — MICRO-INTERACTIONS
   -------------------------------------------------------------------------- */
/* Ripple ink injected by JS at the click point */
.ripple-ink {
    position: absolute;
    border-radius: 50%;
    background: rgba(var(--surface-rgb), 0.35);
    pointer-events: none;
    animation: ripple-out 0.6s var(--ease-out-expo) forwards;
}

.btn-terracotta,
.mascot-browse-btn,
.topic-card,
.rail-item,
.mascot-chip { overflow: hidden; }

/* Glowing border + lift on interactive surfaces */
.chart-card,
.info-card,
.org-card,
.attraction-card,
.macro-card,
.ledger-item,
.district-card,
.journey-card,
.stat-card {
    transition:
        transform var(--dur-fast) var(--ease-out-expo),
        box-shadow var(--dur-fast) ease,
        border-color var(--dur-fast) ease;
}

.chart-card:hover,
.info-card:hover,
.org-card:hover,
.attraction-card:hover,
.ledger-item:hover,
.district-card:hover,
.stat-card:hover {
    transform: scale(1.02);
    border-color: rgba(var(--accent-rgb), 0.5);
    box-shadow:
        0 12px 34px rgba(var(--shade-rgb), 0.34),
        0 0 0 1px rgba(var(--accent-rgb), 0.22),
        0 0 22px -6px rgba(var(--accent-rgb), 0.4);
}

/* Buttons: gradient shift on hover, compress on press */
.btn-terracotta {
    background-image: linear-gradient(100deg, var(--terracotta) 0%, var(--accent) 50%, var(--terracotta) 100%);
    background-size: 220% 100%;
    background-position: 0% 0;
    transition: background-position 0.55s ease, transform var(--dur-fast) var(--ease-out-back), box-shadow var(--dur-fast) ease;
}

.btn-terracotta:hover {
    background-position: 100% 0;
    transform: translateY(-2px) scale(1.02);
    box-shadow: 0 10px 26px rgba(var(--accent-rgb), 0.4);
}

.btn-terracotta:active { transform: translateY(0) scale(0.98); }

/* Nav links: underline grows from the left */
.nav-item::after { transition: width var(--dur-fast) var(--ease-out-expo); }
.nav-item:hover  { color: var(--terracotta); transition: color var(--dur-fast) ease; }

/* --------------------------------------------------------------------------
   TIER 4 — FORM FOCUS & LEDGER FEED
   -------------------------------------------------------------------------- */
.field__input,
.field__select,
.field__textarea,
.mascot-input {
    transition:
        border-color var(--dur-fast) ease,
        background var(--dur-fast) ease,
        box-shadow var(--dur-fast) ease;
}

.field__input:focus,
.field__select:focus,
.field__textarea:focus,
.mascot-input:focus {
    border-color: var(--terracotta);
    background: rgba(var(--accent-rgb), 0.07);
    animation: focus-glow 2.2s ease-in-out infinite;
}

/* The whole field lifts slightly when focused within */
.field:focus-within .field__label { color: var(--accent); }

.field__file { transition: border-color var(--dur-fast) ease, background var(--dur-fast) ease; }
.field__file:hover {
    border-color: var(--terracotta);
    background: rgba(var(--accent-rgb), 0.06);
}

/* New ledger entries drop in from above, then settle */
.ledger-item--incoming {
    opacity: 0;
    border-color: rgba(var(--accent-rgb), 0.55);
}

.ledger-item--incoming.is-landed {
    animation: ledger-drop 0.7s var(--ease-out-back) both;
}

/* ==========================================================================
   20b. MOTION — scroll progress, hover lift, link underlines
   ========================================================================== */
.scroll-progress {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 2px;
    z-index: 2000;
    background: linear-gradient(90deg, var(--terracotta), var(--tier-reported));
    transform: scaleX(0);
    transform-origin: 0 50%;
    pointer-events: none;
}

/* Inline links get an animated underline instead of a static one */
.info-card__body a,
.chart-card__source a,
.deep-read__text a,
.register-note a,
.stat-note a {
    color: var(--terracotta);
    background-image: linear-gradient(var(--terracotta), var(--terracotta));
    background-size: 0% 1px;
    background-position: 0 100%;
    background-repeat: no-repeat;
    transition: background-size 0.35s ease;
    padding-bottom: 1px;
}

.info-card__body a:hover,
.chart-card__source a:hover,
.deep-read__text a:hover,
.register-note a:hover,
.stat-note a:hover {
    background-size: 100% 1px;
}

/* Bars and donuts ease rather than snap */
.bar-row__fill { transition: width 1.2s cubic-bezier(0.22, 1, 0.36, 1); }
.column__bar   { transition: height 1.2s cubic-bezier(0.22, 1, 0.36, 1); }

/* Respect the OS setting — no motion means no motion */
@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;
    }
    .scroll-progress { display: none; }
    [data-reveal] { opacity: 1 !important; transform: none !important; }
}

/* Browse-all-topics control + directory */
.mascot-browsebar { margin-top: 0.6rem; }

.mascot-browse-btn {
    width: 100%;
    padding: 0.55rem 0.8rem;
    border-radius: var(--radius-soft);
    background: rgba(var(--accent-rgb), 0.12);
    border: 1px solid rgba(var(--accent-rgb), 0.35);
    color: var(--terracotta);
    font-family: var(--font-data);
    font-size: 0.75rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.25s ease;
}

.mascot-browse-btn:hover { background: rgba(var(--accent-rgb), 0.22); }

.mascot-dirgroup {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: 0.9rem;
}

.mascot-dirgroup__label {
    width: 100%;
    font-family: var(--font-data);
    font-size: 0.58rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--terracotta);
    margin-bottom: 0.1rem;
}

/* Site-index answers get their own badge tone */
.mascot-answer-tier--site { background: rgba(var(--verified-rgb), 0.14); color: var(--tier-verified); }

/* Follow-up / "try instead" suggestions under an answer */
.mascot-followups {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    align-items: center;
    margin-top: 0.85rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--glass-border);
}

.mascot-followups__label {
    width: 100%;
    font-family: var(--font-data);
    font-size: 0.58rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--terracotta);
    margin-bottom: 0.15rem;
}

.mascot-answer-tier--verified { background: rgba(var(--verified-rgb), 0.18); color: var(--tier-verified); }
.mascot-answer-tier--reported { background: rgba(var(--reported-rgb), 0.18); color: var(--tier-reported); }
.mascot-answer-tier--contested { background: rgba(var(--accent-rgb), 0.18); color: var(--terracotta); }
.mascot-answer-tier--derived { background: rgba(var(--derived-rgb), 0.16); color: var(--tier-derived); }

/* ── Computed answers ─────────────────────────────────────────────────────
   When Mondul works a figure out rather than reciting one, it shows the
   ranking it used. A number with its neighbours around it is far harder to
   misread than a number on its own. */
.mdk-bars {
    display: grid;
    gap: 0.3rem;
    margin-top: 0.7rem;
}

.mdk-bar {
    display: grid;
    grid-template-columns: minmax(72px, 34%) 1fr auto;
    align-items: center;
    gap: 0.5rem;
    font-family: var(--font-data);
    font-size: 0.72rem;
    color: rgba(var(--ink-rgb), 0.72);
}

.mdk-bar__l { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.mdk-bar__t {
    height: 7px;
    border-radius: 999px;
    background: rgba(var(--surface-rgb), 0.07);
    overflow: hidden;
}

.mdk-bar__f {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: rgba(var(--derived-rgb), 0.5);
}

.mdk-bar__v { white-space: nowrap; font-variant-numeric: tabular-nums; }

.mdk-bar.is-hi { color: var(--ink); }
.mdk-bar.is-hi .mdk-bar__f { background: var(--terracotta); }

.mdk-list {
    margin: 0.6rem 0 0;
    padding-left: 1.05rem;
    font-family: var(--font-data);
    font-size: 0.76rem;
    line-height: 1.65;
    color: rgba(var(--ink-rgb), 0.75);
}

.mascot-answer-link {
    display: inline-block;
    margin-top: 0.6rem;
    font-family: var(--font-data);
    font-size: 0.75rem;
    color: var(--terracotta);
    border-bottom: 1px solid rgba(var(--accent-rgb), 0.4);
}

.mascot-form {
    display: flex;
    gap: 0.5rem;
    margin-top: 1rem;
}

.mascot-input {
    flex: 1;
    padding: 0.6rem 0.85rem;
    border-radius: var(--radius-soft);
    background: rgba(var(--surface-rgb), 0.05);
    border: 1px solid var(--glass-border);
    color: var(--mist);
    font-family: var(--font-data);
    font-size: 0.85rem;
}

.mascot-input::placeholder { color: var(--mist); opacity: 0.45; }

.mascot-submit {
    flex-shrink: 0;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    background: var(--terracotta);
    color: var(--canopy-deep);
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.mascot-typing {
    display: inline-flex;
    gap: 3px;
    padding: 0.4rem 0;
}

.mascot-typing span {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--terracotta);
    opacity: 0.5;
    animation: mascot-typing-bounce 1s infinite ease-in-out;
}

.mascot-typing span:nth-child(2) { animation-delay: 0.15s; }
.mascot-typing span:nth-child(3) { animation-delay: 0.3s; }

@keyframes mascot-typing-bounce {
    0%, 60%, 100% { transform: translateY(0); opacity: 0.4; }
    30% { transform: translateY(-4px); opacity: 1; }
}



/* ==========================================================================
   GIS MAPS — inline SVG drawn from the provincial FeatureServer
   --------------------------------------------------------------------------
   These carry their own presentation attributes (fill, font-size) rather than
   relying on these classes alone. A map that depends on an external stylesheet
   breaks the moment the SVG is opened, exported or rendered anywhere else —
   and this site ships an offline copy where that matters.
   ========================================================================== */
.gis-map-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.75rem;
}

@media (min-width: 900px) {
    .gis-map-grid { grid-template-columns: 1fr 1fr; }
}

.gis-figure {
    margin: 0;
    padding: 1rem;
    border-radius: var(--radius-organic);
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
}

.gis-figure__cap {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    margin-bottom: 0.85rem;
}

.gis-figure__cap strong { font-size: 1rem; color: var(--mist); }

/* A caption that sits BELOW its map, for figures where the map is the claim
   and the words are the method note. .gis-figure__cap is the other case: a
   title above a map that is illustrating something already stated. The tier
   chip inside is inline here, not absolutely positioned as it is on a card. */
.gis-figure__note {
    margin-top: 0.9rem;
    font-family: var(--font-data);
    font-size: 0.82rem;
    line-height: 1.6;
    color: rgba(var(--ink-rgb), 0.66);
}

.gis-figure__note .stat-tier {
    position: static;
    display: inline-block;
    margin-right: 0.4rem;
    vertical-align: 1px;
}

.gis-figure__cap span {
    font-family: var(--font-data);
    font-size: 0.76rem;
    opacity: 0.72;
}

.gis-map {
    display: block;
    width: 100%;
    height: auto;
    border-radius: var(--radius-soft);
    background: #0E1A16;
}

.gis-figure .info-card__source { margin-top: 0.85rem; }


/* ==========================================================================
   THE INTELLIGENT MAP
   --------------------------------------------------------------------------
   Layer toggles and a hover readout over one inline SVG. No map library and
   no tile service: the whole thing is markup plus about forty lines of JS,
   which is why it still works in the offline copy of the site.
   ========================================================================== */
.imap {
    padding: 1rem;
    border-radius: var(--radius-organic);
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
}

.imap__bar {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1rem;
    margin-bottom: 0.9rem;
    align-items: center;
}

/* Thirteen loose pills read as a wall. Grouping them by what they DO — pick a
   base, add areas, add lines, add places — turns the bar into an explanation
   of how the map is built. */
.imap__group {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    padding: 0.35rem 0.55rem;
    border-radius: var(--radius-soft);
    background: rgba(var(--surface-rgb), 0.025);
    border: 1px solid var(--glass-border);
}

.imap__group-label {
    font-family: var(--font-data);
    font-size: 0.6rem;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--terracotta);
    margin-right: 0.15rem;
    opacity: 0.85;
}

/* The layer groups are SVG <g> elements. `hidden` on an SVG element is honoured
   by the browser's UA stylesheet in practice, but this page also has to run
   from a zip opened straight off disk, so the rule is stated rather than
   assumed. */
.imap-layer[hidden] { display: none; }

/* The base layers are a radio group: the active one is the map you are
   looking at, so it reads as selected rather than merely enabled. */
.imap-toggle[role="radio"][aria-checked="true"] {
    background: rgba(var(--accent-rgb), 0.3);
    box-shadow: inset 0 0 0 1px rgba(244, 228, 214, 0.25);
}

.imap-toggle {
    font-family: var(--font-data);
    font-size: 0.7rem;
    letter-spacing: 0.04em;
    padding: 0.4rem 0.7rem;
    border-radius: 999px;
    cursor: pointer;
    color: var(--mist);
    background: rgba(var(--surface-rgb), 0.04);
    border: 1px solid var(--glass-border);
    transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.imap-toggle:hover { border-color: rgba(var(--accent-rgb), 0.55); }

.imap-toggle.is-on {
    background: rgba(var(--accent-rgb), 0.22);
    border-color: var(--terracotta);
    color: var(--ink);
}

.imap__stage { position: relative; }

.imap-svg {
    display: block;
    width: 100%;
    height: auto;
    border-radius: var(--radius-soft);
    background: #0E1A16;
}

/* Every feature is hoverable and focusable */
.imap-ft { cursor: pointer; transition: fill-opacity 0.15s ease, stroke-width 0.15s ease; }
.imap-ft:hover, .imap-ft:focus { fill-opacity: 0.92; stroke-width: 2.4; outline: none; }

.imap__tip {
    position: absolute;
    z-index: 5;
    max-width: 260px;
    padding: 0.6rem 0.75rem;
    border-radius: var(--radius-soft);
    background: rgba(8, 16, 13, 0.95);
    border: 1px solid var(--glass-border);
    pointer-events: none;
    font-size: 0.78rem;
    line-height: 1.4;
    color: var(--mist);
}

.imap__tip strong { display: block; color: var(--ink); }

.imap__tip em {
    display: block;
    font-style: normal;
    font-family: var(--font-data);
    font-size: 0.66rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    opacity: 0.65;
    margin-bottom: 0.25rem;
}

.imap__readout {
    margin: 0.8rem 0 0;
    font-size: 0.82rem;
    min-height: 2.4em;
    color: var(--mist);
    opacity: 0.85;
}

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


/* ── Ask the data ─────────────────────────────────────────────────────────
   A question box that computes. Deliberately plain: the interesting thing is
   the answer and the ranking under it, not the chrome around the input. */
.askbox { padding: 1.25rem 1.35rem; border-radius: var(--radius-organic); }

.askbox__form { display: flex; gap: 0.5rem; flex-wrap: wrap; }

.askbox__input {
    flex: 1 1 260px;
    min-width: 0;
    padding: 0.7rem 0.9rem;
    border-radius: var(--radius-soft);
    background: rgba(var(--shade-rgb), 0.28);
    border: 1px solid var(--glass-border);
    color: var(--mist);
    font-family: var(--font-data);
    font-size: 0.9rem;
}

.askbox__input:focus { outline: none; border-color: var(--terracotta); }
.askbox__input::placeholder { color: rgba(var(--ink-rgb), 0.35); }

.askbox__go {
    padding: 0.7rem 1.15rem;
    border-radius: var(--radius-soft);
    border: 1px solid var(--terracotta);
    background: rgba(var(--accent-rgb), 0.22);
    color: var(--ink);
    font-family: var(--font-data);
    font-size: 0.82rem;
    cursor: pointer;
    transition: background 0.2s ease;
}

.askbox__go:hover { background: rgba(var(--accent-rgb), 0.38); }

.askbox__chips { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.8rem; }

.askbox__chip {
    padding: 0.32rem 0.62rem;
    border-radius: 999px;
    border: 1px solid var(--glass-border);
    background: rgba(var(--surface-rgb), 0.035);
    color: rgba(var(--ink-rgb), 0.72);
    font-family: var(--font-data);
    font-size: 0.68rem;
    cursor: pointer;
    transition: border-color 0.2s ease, color 0.2s ease;
}

.askbox__chip:hover { border-color: rgba(var(--accent-rgb), 0.6); color: var(--ink); }

.askbox__hint {
    margin: 0.7rem 0 0;
    font-family: var(--font-data);
    font-size: 0.7rem;
    color: rgba(var(--ink-rgb), 0.42);
}

.askbox__out:empty { display: none; }

.askbox__answer {
    position: relative;
    margin-top: 1rem;
    padding: 1rem 1.1rem;
    border-radius: var(--radius-soft);
    background: rgba(var(--shade-rgb), 0.22);
    border: 1px solid var(--glass-border);
    border-left: 3px solid var(--tier-derived);
    font-size: 0.92rem;
    line-height: 1.65;
    color: var(--mist);
}

.askbox__answer .stat-tier { position: static; display: inline-block; margin-right: 0.45rem; vertical-align: 1px; }
.askbox__answer--none { border-left-color: rgba(var(--ink-rgb), 0.25); color: rgba(var(--ink-rgb), 0.7); font-size: 0.86rem; }

.askbox__src {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem 1rem;
    align-items: baseline;
    margin: 0.75rem 0 0;
    font-family: var(--font-data);
    font-size: 0.72rem;
}

.askbox__src a { color: var(--terracotta); text-decoration: none; }
.askbox__src a:hover { text-decoration: underline; }
.askbox__ms { color: rgba(var(--ink-rgb), 0.35); }

.visually-hidden {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}


/* ── Theme picker ─────────────────────────────────────────────────────────
   Deliberately in the header on every page, not buried in settings: the
   person who most needs it is standing in the sun right now. */
.theme-picker { position: relative; }

.theme-picker__btn {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.42rem 0.7rem;
    border-radius: 999px;
    border: 1px solid var(--line);
    background: rgba(var(--surface-rgb), 0.05);
    color: var(--ink-soft);
    font-family: var(--font-data);
    font-size: 0.74rem;
    cursor: pointer;
    transition: border-color 0.2s ease, color 0.2s ease;
}

.theme-picker__btn:hover { border-color: var(--accent); color: var(--ink); }
.theme-picker__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

@media (max-width: 900px) { .theme-picker__label { display: none; } }

.theme-picker__menu {
    position: absolute;
    top: calc(100% + 0.55rem);
    right: 0;
    z-index: 1400;
    width: min(19rem, calc(100vw - 2rem));
    padding: 0.75rem;
    border-radius: var(--radius-soft);
    background: var(--bg-raised);
    border: 1px solid var(--line);
    box-shadow: 0 18px 44px rgba(var(--shade-rgb), 0.35);
}

.theme-picker__menu[hidden] { display: none; }

.theme-picker__title,
.theme-picker__note {
    margin: 0 0 0.5rem;
    font-family: var(--font-data);
    font-size: 0.66rem;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--accent);
}

.theme-picker__note {
    margin: 0.6rem 0 0;
    text-transform: none;
    letter-spacing: 0;
    font-size: 0.68rem;
    color: var(--ink-faint);
    line-height: 1.5;
}

.theme-opt {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    width: 100%;
    padding: 0.5rem 0.55rem;
    border-radius: var(--radius-soft);
    border: 1px solid transparent;
    background: none;
    color: var(--ink);
    font-family: var(--font-data);
    font-size: 0.82rem;
    text-align: left;
    cursor: pointer;
}

.theme-opt:hover { background: rgba(var(--surface-rgb), 0.06); }
.theme-opt.is-on { border-color: var(--accent); background: rgba(var(--accent-rgb), 0.1); }
.theme-opt:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.theme-opt__t { display: flex; flex-direction: column; line-height: 1.3; }
.theme-opt__t em { font-style: normal; font-size: 0.68rem; color: var(--ink-faint); margin-top: 0.1rem; }

/* The swatch shows the actual surface and its accent, so the choice is made
   by looking rather than by reading a name. */
.theme-opt__sw {
    position: relative;
    flex: none;
    width: 26px; height: 26px;
    border-radius: 8px;
    border: 1px solid var(--line);
    overflow: hidden;
}

.theme-opt__sw i {
    position: absolute;
    right: 3px; bottom: 3px;
    width: 9px; height: 9px;
    border-radius: 50%;
}

.theme-opt__sw--auto {
    background: linear-gradient(135deg, #F6EFE4 0 50%, #0D1A15 50% 100%);
    border-color: var(--line);
}

/* Maps carry their own dark cartography, so on a light palette they keep a
   dark well around them rather than glowing out of the page. */
:root[data-theme="laterite"] .gis-figure,
:root[data-theme="highland"] .gis-figure,
:root[data-theme="laterite"] .imap__stage,
:root[data-theme="highland"] .imap__stage {
    background: #0E1A16;
    border-radius: var(--radius-soft);
    padding: 0.5rem;
}

:root[data-theme="laterite"] .gis-figure figcaption,
:root[data-theme="highland"] .gis-figure figcaption {
    color: rgba(237, 244, 239, 0.78);
}


/* ── The Data Hub console ─────────────────────────────────────────────────
   One chooser, one panel. Applied only when the script has built it, so a
   reader without JavaScript still gets the whole page and every anchor still
   resolves. */
.hub-layout.is-console .section-rail { display: none; }

.console {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.25rem;
    align-items: start;
    margin-top: 1.5rem;
}

@media (min-width: 980px) {
    .console { grid-template-columns: 17.5rem minmax(0, 1fr); gap: 2rem; }
    .console__nav { position: sticky; top: 6.5rem; max-height: calc(100vh - 8rem); display: flex; flex-direction: column; }
    .console__list { overflow-y: auto; }
}

.console__nav {
    padding: 0.85rem;
    border-radius: var(--radius-organic);
    background: var(--bg-raised);
    border: 1px solid var(--line);
}

.console__search { margin-bottom: 0.6rem; }

.console__filter {
    width: 100%;
    padding: 0.55rem 0.7rem;
    border-radius: var(--radius-soft);
    border: 1px solid var(--line);
    background: rgba(var(--surface-rgb), 0.05);
    color: var(--ink);
    font-family: var(--font-data);
    font-size: 0.82rem;
}

.console__filter:focus { outline: none; border-color: var(--accent); }
.console__filter::placeholder { color: var(--ink-faint); }

.console__group {
    margin: 0.85rem 0 0.3rem;
    font-family: var(--font-data);
    font-size: 0.62rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--accent);
}

.console__group:first-of-type { margin-top: 0.15rem; }
.console__group[hidden], .console__item[hidden] { display: none; }

.console__item {
    display: block;
    width: 100%;
    padding: 0.5rem 0.6rem;
    margin-bottom: 0.15rem;
    border: 1px solid transparent;
    border-radius: var(--radius-soft);
    background: none;
    color: var(--ink-soft);
    font-family: var(--font-data);
    font-size: 0.84rem;
    line-height: 1.35;
    text-align: left;
    cursor: pointer;
    transition: background 0.16s ease, color 0.16s ease, border-color 0.16s ease;
}

.console__item:hover { background: rgba(var(--surface-rgb), 0.06); color: var(--ink); }
.console__item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.console__item.is-on {
    background: rgba(var(--accent-rgb), 0.12);
    border-color: var(--accent);
    color: var(--ink);
    font-weight: 600;
}

.console__item-t { display: block; }
.console__item-h { display: block; margin-top: 0.12rem; font-size: 0.68rem; color: var(--ink-faint); }
.console__item.is-on .console__item-h { color: var(--ink-soft); }

.console__nav.is-empty .console__list::after {
    content: 'No topic matches that.';
    display: block;
    padding: 0.6rem;
    font-family: var(--font-data);
    font-size: 0.78rem;
    color: var(--ink-faint);
}

/* Exactly one panel at a time. Without JS none of this applies and the whole
   page reads as it always did. */
.hub-layout.is-console .console__stage > section.register-section:focus { outline: none; }

.console__stage { min-width: 0; }

/* On a phone the chooser sits above the panel, so it must not push the content
   off the screen. Cap it and let it scroll; the filter stays put above it. */
@media (max-width: 979px) {
    .console__nav { position: sticky; top: 0.5rem; z-index: 20; }
    .console__list { max-height: 42vh; overflow-y: auto; -webkit-overflow-scrolling: touch; }
    .console__item { font-size: 0.88rem; padding: 0.6rem; }   /* a comfortable tap target */
}

@media (prefers-reduced-motion: no-preference) {
    .hub-layout.is-console .console__stage > section.is-active {
        animation: consoleIn 0.28s var(--ease-out-expo, ease) both;
    }
}

@keyframes consoleIn {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}


/* ── Header polish and the mobile theme control ───────────────────────────
   The desktop bar hides below 768px, so the phone gets its own way in: one
   more item in the bottom bar that cycles the palettes. Cycling rather than
   opening a menu, because a bottom bar is thumb territory and a five-item
   popover there is a fight. */
.nav-desktop .btn-terracotta { white-space: nowrap; }

/* At the awkward width where the mega-menu labels and the button and the
   picker all want room, drop the picker's word and keep its dot. */
@media (min-width: 768px) and (max-width: 1080px) {
    .nav-desktop { padding-top: 0.85rem; padding-bottom: 0.85rem; }
    .nav-links { font-size: 0.9rem; }
    .nav-desktop .btn-terracotta { padding: 0.5rem 1rem; font-size: 0.82rem; }
}

.mobile-nav-item[data-theme-cycle] {
    border: none;
    background: none;
    font: inherit;
    color: inherit;
    cursor: pointer;
}

/* A control in the thumb zone needs a real target, not a 20px icon. */
.nav-mobile .mobile-nav-item {
    min-height: 44px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.2rem;
}

/* Give the fixed bottom bar somewhere to sit so it never covers the last
   paragraph on a page. */
@media (max-width: 767px) {
    body.biome-theme { padding-bottom: 4.75rem; }
}

/* Focus that is actually visible, in every palette. The old outline inherited
   a colour that vanished on the light ones. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
[tabindex]:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 4px;
}


/* ==========================================================================
   OVERALL POLISH
   Small things, all of them felt rather than noticed, and all of them worse
   on a phone than on the laptop a site is usually designed on.
   ========================================================================== */

/* 1. MEASURE. Prose that runs the full width of a laptop is tiring to read;
      the eye loses the line on the way back. Cap the paragraph, not the page,
      so tables and maps still get the whole width. */
.register-section > p,
.register-section > ol,
.register-section > ul,
.info-card__body,
.chart-card__source {
    max-width: 68ch;
}

/* 2. TABLES ON A PHONE. A ten-column table in a 360px viewport can only
      scroll sideways — but it has to LOOK scrollable, or nobody tries. */
.register-table-wrap,
.commune-table-wrap,
.cost-table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    background:
        linear-gradient(to right, var(--bg) 30%, rgba(var(--shade-rgb), 0)) left / 40px 100% no-repeat,
        linear-gradient(to left,  var(--bg) 30%, rgba(var(--shade-rgb), 0)) right / 40px 100% no-repeat;
    background-attachment: local, local;
}

@media (max-width: 640px) {
    .register-table th,
    .register-table td { padding: 0.6rem 0.7rem; font-size: 0.82rem; }
    /* the first column is the row's identity — keep it in view while the rest
       scrolls past it */
    .register-table th:first-child,
    .register-table td:first-child {
        position: sticky;
        left: 0;
        background: var(--bg);
        z-index: 1;
    }
}

/* 3. TYPE ON SMALL SCREENS. The fluid scale bottoms out a little tight for
      long reading at arm's length in bright light. */
@media (max-width: 640px) {
    body.biome-theme { font-size: 1.02rem; line-height: 1.68; }
    .register-title { line-height: 1.25; }
}

/* 4. MOTION. Everything that moves must be able to stop. */
@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;
    }
}

/* 5. PRINT. An atlas that cannot be printed is not much of an atlas. In print
      there is no chooser and no chrome — every panel opens, and the maps go
      on white. */
@media print {
    :root { --bg: #FFFFFF; --bg-raised: #FFFFFF; --ink: #111111; --ink-soft: #333333;
            --ink-faint: #555555; --line: #BBBBBB; --accent: #8A3A22;
            --surface-rgb: 0, 0, 0; --shade-rgb: 255, 255, 255; }
    .nav-desktop, .nav-mobile, .section-rail, .console__nav, .theme-picker,
    #mascot-wrapper, .scroll-progress, .askbox__chips, .hero-cinematic { display: none !important; }
    .hub-layout.is-console .console__stage > section.register-section { display: block !important; }
    .console { display: block; }
    .gis-figure, .imap__stage { background: #FFFFFF !important; padding: 0 !important; }
    .register-section { break-inside: avoid-page; page-break-inside: avoid; }
    a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 0.7em; color: #555; }
}

/* 6. SKIP LINK. First stop for a keyboard, and it was missing. */
.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 2000;
    padding: 0.75rem 1.1rem;
    border-radius: 0 0 var(--radius-soft) 0;
    background: var(--accent);
    color: var(--accent-ink);
    font-family: var(--font-data);
    font-size: 0.9rem;
}

.skip-link:focus {
    left: 0;
}


/* ── Self-audit ───────────────────────────────────────────────────────────
   A disagreement is not an error state to be styled in alarm red; it is the
   most interesting row on the page. So the failing rows are the ones that get
   the emphasis, and the passing ones sit quietly. */
.audit__lead { max-width: 68ch; margin-bottom: 1.1rem; }

.audit__grid { display: grid; gap: 0.75rem; }

.audit__row {
    padding: 0.95rem 1.1rem;
    border-radius: var(--radius-soft);
    background: var(--bg-raised);
    border: 1px solid var(--line);
    border-left: 3px solid var(--ink-faint);
}

.audit__row--pass { border-left-color: var(--tier-verified); }
.audit__row--fail { border-left-color: var(--tier-contested); background: rgba(var(--contested-rgb), 0.07); }
.audit__row--note { border-left-color: var(--tier-reported); }

.audit__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.6rem; }

.audit__state {
    font-family: var(--font-data);
    font-size: 0.6rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    padding: 0.18rem 0.5rem;
    border-radius: 999px;
}

.audit__row--pass .audit__state { background: rgba(var(--verified-rgb), 0.16); color: var(--tier-verified); }
.audit__row--fail .audit__state { background: rgba(var(--contested-rgb), 0.18); color: var(--tier-contested); }
.audit__row--note .audit__state { background: rgba(var(--reported-rgb), 0.16); color: var(--tier-reported); }

.audit__claim { font-size: 0.98rem; font-weight: 600; color: var(--ink); }

.audit__nums {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem 1.4rem;
    margin-top: 0.5rem;
    font-family: var(--font-data);
    font-size: 0.8rem;
    color: var(--ink-soft);
}

.audit__nums b { color: var(--ink); font-variant-numeric: tabular-nums; }
.audit__gap { color: var(--ink-faint); }
.audit__row--fail .audit__gap { color: var(--tier-contested); font-weight: 600; }

.audit__note { margin: 0.55rem 0 0; max-width: 68ch; font-size: 0.84rem; line-height: 1.6; color: var(--ink-faint); }


/* Spatial Plan charts: drawn from the document's own tables, so they inherit
   the palette rather than carrying the dark cartography the maps need. */
.psp-chart { display: block; width: 100%; height: auto; }
.psp-chart text { fill: var(--ink-soft); }

:root[data-theme="laterite"] .gis-figure:has(.psp-chart),
:root[data-theme="highland"] .gis-figure:has(.psp-chart) {
    background: var(--bg-raised);
    border: 1px solid var(--line);
}
:root[data-theme="laterite"] .gis-figure:has(.psp-chart) figcaption,
:root[data-theme="highland"] .gis-figure:has(.psp-chart) figcaption { color: var(--ink-faint); }


/* ── Data Hub opening ─────────────────────────────────────────────────────
   The complaint was that the topic chooser could not be seen without
   scrolling. The cause was the hero: a title on the site-wide hero scale
   (up to 6rem) plus a full paragraph plus a legend, which is most of a
   laptop screen before the tool even starts. On the Hub the hero becomes a
   label — one line of title, one line of text, legend alongside. */
.hub-hero--compact {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1rem 2rem;
    max-width: none;
    padding: 1.1rem clamp(1rem, 3vw, 2.5rem) 0.9rem;
}

.hub-hero--compact .hub-hero__lede { min-width: 0; }
.hub-hero--compact .hub-hero__eyebrow { margin-bottom: 0.3rem; }

.hub-hero--compact .hub-hero__title {
    font-size: clamp(1.6rem, 2.6vw + 0.5rem, 2.5rem);
    margin-bottom: 0.35rem;
    line-height: 1.15;
}

.hub-hero--compact .hub-hero__subtitle {
    font-size: 0.9rem;
    line-height: 1.55;
    margin-bottom: 0;
    max-width: 56ch;
    color: var(--ink-soft);
    opacity: 1;
}

.hub-hero--compact .hub-hero__legend { gap: 0.9rem; padding-bottom: 0.2rem; }

@media (min-width: 768px) {
    .hub-hero--compact { padding: 1.4rem clamp(1.25rem, 3.5vw, 3.5rem) 1rem; }
}

/* The console starts immediately under it, and the chooser pins itself below
   the fixed header once you scroll. */
.hub-layout.is-console { padding-top: calc(var(--header-h) + 0.5rem); }
.console { margin-top: 0.75rem; }

@media (min-width: 980px) {
    .console__nav {
        top: calc(var(--header-h) + 0.75rem);
        max-height: calc(100vh - var(--header-h) - 2rem);
    }
}

/* On a phone there is no fixed header, so the chooser pins to the very top.
   It stays compact until you interact with it — a filter field and a scroll
   list is enough; the full list can wait until it is asked for. */
@media (max-width: 979px) {
    .hub-layout.is-console { padding-top: 0.5rem; }
    .console__nav { top: 0; border-radius: 0 0 var(--radius-organic) var(--radius-organic); }
    .console__list { max-height: 38vh; }
}

/* A hint that the list scrolls, since a cut-off item is the only other clue. */
.console__list {
    scrollbar-width: thin;
    mask-image: linear-gradient(to bottom, #000 calc(100% - 18px), transparent 100%);
}


/* ── Plan map sheets ──────────────────────────────────────────────────────
   Scanned cartography, so it keeps a white mount in every palette: these
   sheets were drawn for paper and their own white is part of the map. */
.psp-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 1.1rem;
}

.psp-sheet {
    margin: 0;
    border-radius: var(--radius-soft);
    border: 1px solid var(--line);
    background: var(--bg-raised);
    overflow: hidden;
}

.psp-sheet__link {
    display: block;
    background: #FFFFFF;
    line-height: 0;
}

.psp-sheet img {
    width: 100%;
    height: auto;
    display: block;
    transition: transform 0.35s var(--ease-out-expo, ease);
}

.psp-sheet__link:hover img { transform: scale(1.03); }
.psp-sheet__link:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.psp-sheet figcaption {
    display: block;
    padding: 0.7rem 0.8rem 0.8rem;
    font-family: var(--font-data);
    font-size: 0.8rem;
    line-height: 1.5;
    color: var(--ink);
}

.psp-sheet figcaption strong { color: var(--accent); margin-right: 0.35rem; }
.psp-sheet figcaption span {
    display: block;
    margin-top: 0.3rem;
    font-size: 0.72rem;
    color: var(--ink-faint);
}

/* ============================================================
   PLAN SHEET VIEWER
   A Spatial Plan raster as a base layer, with the Atlas's own vector
   geometry cloned on top of it. The sheets are busy, printed documents;
   everything the viewer draws over them therefore carries a light halo,
   otherwise a dark boundary line vanishes into dark forest green.
   ============================================================ */
.pmv { margin-top: 1.25rem; }

.pmv__pick { display: flex; flex-wrap: wrap; gap: 0.55rem 1.4rem; margin-bottom: 1rem; }
.pmv__pick-group { display: flex; flex-direction: column; gap: 0.35rem; }
.pmv__pick-label {
    font-family: var(--font-data); font-size: 0.6rem; letter-spacing: 0.14em;
    text-transform: uppercase; color: var(--ink-faint);
}
.pmv__pick-row { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.pmv-pick {
    font-family: var(--font-data); font-size: 0.68rem; letter-spacing: 0.03em;
    padding: 0.38rem 0.68rem; border-radius: 999px; cursor: pointer;
    color: var(--ink-soft); background: rgba(var(--surface-rgb), 0.05);
    border: 1px solid var(--line); transition: background var(--dur-fast), border-color var(--dur-fast);
}
.pmv-pick:hover { border-color: rgba(var(--accent-rgb), 0.6); }
.pmv-pick[aria-pressed="true"] {
    background: rgba(var(--accent-rgb), 0.24); border-color: var(--accent); color: var(--ink);
}

.pmv__body { display: grid; grid-template-columns: minmax(0, 1fr) 250px; gap: 1.1rem; align-items: start; }
@media (max-width: 860px) { .pmv__body { grid-template-columns: minmax(0, 1fr); } }

.pmv__stage {
    position: relative; overflow: hidden; border-radius: var(--radius-soft);
    background: var(--bg-sunk); border: 1px solid var(--line);
    touch-action: none; cursor: grab;
}
.pmv__stage.is-drag { cursor: grabbing; }
.pmv__svg { display: block; width: 100%; height: auto; }

/* The raster sits underneath everything and is the only thing that fades. */
.pmv-img { display: none; }
.pmv-img.is-on { display: block; }

/* Vector overlays. Two passes per layer: a pale halo, then the line itself.
   One pass is not enough — these sheets have dark greens, dark browns and
   white all in the same frame, so no single stroke colour stays legible. */
.pmv__vec g { pointer-events: none; }
.pmv__vec path, .pmv__vec polyline, .pmv__vec polygon { fill: none !important; }
.pmv__vec .pmv-halo path, .pmv__vec .pmv-halo polyline, .pmv__vec .pmv-halo polygon {
    stroke: rgba(255, 255, 255, 0.85) !important;
}
.pmv__vec circle { stroke: rgba(255, 255, 255, 0.9); stroke-width: 1.1; }
.pmv__vec text { display: none; }

.pmv__hit path { fill: transparent; stroke: none; pointer-events: all; cursor: crosshair; }
.pmv__hit .is-hot { fill: rgba(var(--accent-rgb), 0.28); }

.pmv__swipe line { stroke: #fff; stroke-width: 2.5; filter: drop-shadow(0 0 2px rgba(0,0,0,.6)); }
.pmv__swipe circle { fill: #fff; stroke: rgba(0,0,0,.45); stroke-width: 1.5; cursor: ew-resize; }

.pmv__zoom { position: absolute; right: 0.6rem; bottom: 0.6rem; display: flex; flex-direction: column; gap: 0.3rem; }
.pmv-z {
    width: 30px; height: 30px; border-radius: 8px; cursor: pointer; font-size: 0.95rem; line-height: 1;
    color: var(--ink); background: rgba(var(--surface-rgb), 0.82); border: 1px solid var(--line);
    backdrop-filter: blur(6px);
}
.pmv-z:hover { border-color: var(--accent); }
.pmv-z--wide { width: auto; padding: 0 0.5rem; font-family: var(--font-data); font-size: 0.6rem; letter-spacing: 0.08em; text-transform: uppercase; }

.pmv__side { display: flex; flex-direction: column; gap: 1rem; }
.pmv__field { display: flex; flex-direction: column; gap: 0.4rem; }
.pmv__label {
    font-family: var(--font-data); font-size: 0.6rem; letter-spacing: 0.14em;
    text-transform: uppercase; color: var(--ink-faint);
}
.pmv__field input[type="range"] { width: 100%; accent-color: var(--accent); }
.pmv__field select {
    font-family: var(--font-data); font-size: 0.72rem; padding: 0.4rem 0.5rem;
    border-radius: 8px; color: var(--ink); background: var(--bg-raised); border: 1px solid var(--line);
}
.pmv__hint { font-size: 0.66rem; color: var(--ink-faint); margin: 0; }
.pmv__layers { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.pmv-layer {
    font-family: var(--font-data); font-size: 0.64rem; padding: 0.3rem 0.55rem;
    border-radius: 999px; cursor: pointer; color: var(--ink-soft);
    background: rgba(var(--surface-rgb), 0.05); border: 1px solid var(--line);
}
.pmv-layer:hover { border-color: rgba(var(--accent-rgb), 0.6); }
.pmv-layer.is-on { background: rgba(var(--accent-rgb), 0.22); border-color: var(--accent); color: var(--ink); }
.pmv__read {
    font-size: 0.74rem; line-height: 1.5; color: var(--ink-soft); min-height: 4.5rem;
    padding: 0.6rem 0.7rem; border-radius: 10px; background: var(--bg-sunk); border: 1px solid var(--line);
}
.pmv__read strong { color: var(--ink); }
.pmv__prov { font-size: 0.62rem; line-height: 1.5; color: var(--ink-faint); margin: 0; }

/* ============================================================
   HOMEPAGE GALLERY CARDS
   Seven photographs were referenced and none existed, so the front page
   opened with seven "file missing" placeholders. These cards replace them
   with facts the Atlas can cite. They inherit the theme through the same
   custom properties as everything else, so they follow all four palettes.
   ============================================================ */
.gallery-item--card { overflow: hidden; border-radius: var(--radius-soft); }
.gcard {
    display: block; width: 100%; height: auto;
    --g0: rgba(var(--accent-rgb), 0.85);
    --g1: rgba(var(--accent-rgb), 0.34);
    --g2: rgba(var(--ink-rgb), 0.46);
    --g3: rgba(var(--ink-rgb), 0.80);
    --sky0: rgba(var(--accent-rgb), 0.16);
    --sky1: rgba(var(--accent-rgb), 0.38);
    background: var(--bg-sunk);
}
.gcard .gpanel { fill: var(--bg-raised); }
.gcard .gname {
    font-family: var(--font-heading); font-size: 19px; fill: var(--ink);
}
.gcard .gf {
    font-family: var(--font-data); font-size: 12.5px; fill: var(--ink-soft);
}
.gcard .gtier {
    font-family: var(--font-data); font-size: 10px; letter-spacing: 0.12em;
    text-transform: uppercase;
}
.gcard .gtier--verified { fill: rgb(var(--accent-rgb)); }
.gcard .gtier--reported { fill: rgb(var(--reported-rgb)); }
.gcard .gtier--derived  { fill: rgb(var(--derived-rgb)); }
.gallery-item--card figcaption span { display: block; opacity: 0.72; font-size: 0.72rem; }
@media (prefers-reduced-motion: no-preference) {
    .gallery-item--card .gscene { transition: transform 600ms var(--ease-out-expo); }
    .gallery-item--card:hover .gscene { transform: scale(1.04); }
}

/* Map sheets the project does not hold. Previously these were <img> tags
   pointing at files that have never existed, so three cards in the map record
   rendered as broken images. The slot now says so plainly and keeps the
   buffer for a real scan. */
.sheet-slot {
    display: flex; flex-direction: column; align-items: center; gap: 0.35rem;
    margin: 0.75rem 0; padding: 0.9rem; border-radius: var(--radius-soft);
    background: var(--bg-sunk); border: 1px solid var(--line); color: var(--ink-faint);
}
.sheet-slot svg { width: 100%; max-width: 320px; height: auto; }
.sheet-slot__label {
    font-family: var(--font-data); font-size: 0.72rem; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--ink-soft);
}
.sheet-slot__hint { font-size: 0.68rem; line-height: 1.5; text-align: center; }

/* ============================================================
   DATA HUB FILTER
   The chooser now ranks, answers and filters by content, so it needs room to
   say why a result is there. Everything below is additive to .console.
   ============================================================ */
.console__facets {
    display: flex; flex-wrap: wrap; gap: 0.3rem; margin: 0.5rem 0 0.35rem;
}
.console__facet {
    font-family: var(--font-data); font-size: 0.62rem; letter-spacing: 0.04em;
    padding: 0.26rem 0.5rem; border-radius: 999px; cursor: pointer;
    color: var(--ink-soft); background: rgba(var(--surface-rgb), 0.05);
    border: 1px solid var(--line);
}
.console__facet:hover { border-color: rgba(var(--accent-rgb), 0.6); }
.console__facet.is-on {
    background: rgba(var(--accent-rgb), 0.22); border-color: var(--accent); color: var(--ink);
}
.console__answer {
    margin: 0.45rem 0 0.2rem; padding: 0.6rem 0.7rem; border-radius: 10px;
    background: var(--bg-sunk); border: 1px solid var(--line);
    font-size: 0.76rem; line-height: 1.55; color: var(--ink-soft);
}
.console__answer strong { color: var(--ink); }
.console__answer a { color: var(--accent); }
.console__answer-tag {
    display: block; font-family: var(--font-data); font-size: 0.56rem;
    letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-faint);
    margin-bottom: 0.3rem;
}
.console__answer table, .console__answer .bar { display: none; }
.console__count {
    margin: 0.2rem 0 0.35rem; font-family: var(--font-data); font-size: 0.6rem;
    letter-spacing: 0.06em; color: var(--ink-faint);
}
.console__item-holds {
    display: block; font-family: var(--font-data); font-size: 0.58rem;
    letter-spacing: 0.05em; color: var(--ink-faint); margin-top: 0.18rem;
}
.console__item-why {
    display: block; font-family: var(--font-data); font-size: 0.56rem;
    letter-spacing: 0.05em; color: rgb(var(--accent-rgb)); margin-top: 0.1rem;
}
.console__item-why:empty { display: none; }
/* When results are ranked, the group headings are meaningless — hide the gaps
   they leave behind so the list reads as one ordered set. */
.console__nav.is-ranked .console__group { display: none; }
.console__nav.is-empty .console__list::after {
    content: 'Nothing matches. Try a broader word, or clear the content filters.';
    display: block; padding: 0.7rem 0.2rem; font-size: 0.72rem; color: var(--ink-faint);
}

/* Legal chronology from Open Development Cambodia. Rows are tinted by who
   received the land, because the same instrument type both erodes the
   protected estate and formalises indigenous title, and a single colour would
   flatten that into one story. */
.odc-chart { display: block; width: 100%; height: auto; border-radius: var(--radius-soft); }
.odc-table td:first-child { white-space: nowrap; font-family: var(--font-data); font-size: 0.72rem; }
.odc-table tr.odc-community { background: rgba(46, 125, 91, 0.10); }
.odc-table tr.odc-families  { background: rgba(192, 138, 46, 0.09); }
.odc-table tr.odc-establish { background: rgba(62, 107, 138, 0.10); }
.odc-dot { cursor: help; }
.odc-dot:hover { fill-opacity: 1; }

/* The 41-year forest series. Figures the source cannot support are greyed
   rather than deleted: removing them would hide the instability, and printing
   them plain would assert something the data does not. */
.odcf-chart { display: block; width: 100%; height: auto; border-radius: var(--radius-soft); }
.odcf-table td.is-soft { opacity: 0.45; font-style: italic; }
/* The land-claims reconciliation. */
.claims-chart { display: block; width: 100%; height: auto; border-radius: var(--radius-soft); }

/* Visitor arrivals against the Master Plan. Derived rows are dimmed rather
   than dropped: the 2022 half-year is real arithmetic on published
   percentages, but it is not a measurement and must not read like one. */
.tour-chart { display: block; width: 100%; height: auto; border-radius: var(--radius-soft); margin: 1.2rem 0; }
.tour-table td.tour-src { font-size: 0.72rem; line-height: 1.45; color: var(--ink-faint); max-width: 22rem; }
.tour-table tr.is-soft td:not(.tour-src) { opacity: 0.55; font-style: italic; }
.tour-table tr.is-target td { border-top: 2px solid var(--line); font-weight: 600; }

/* Source line inside a reconciliation cell, so a figure and its provenance
   stay together when the table wraps on a narrow screen. */
.data-table .fig-src { display: block; font-size: 0.68rem; color: var(--ink-faint); margin-top: 0.15rem; }

/* The how-to video. The player is deliberately not the whole section: the
   six rules sit beside it in text, so somebody who will never press play
   still leaves with the same six things. */
.howto-section { padding: clamp(3rem, 7vw, 6rem) 0; }
.howto-head { max-width: 62ch; margin-bottom: 2.2rem; }
.howto-title { font-family: var(--font-display); font-size: clamp(1.9rem, 4vw, 2.7rem); margin: 0 0 0.7rem; }
.howto-sub { color: var(--ink-faint); font-size: 0.98rem; line-height: 1.65; margin: 0; }
.howto-grid { display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr); gap: 2rem; align-items: start; }
@media (max-width: 900px) { .howto-grid { grid-template-columns: 1fr; } }
.vid { width: 100%; height: auto; display: block; border-radius: var(--radius-soft);
       background: #0D1A15; border: 1px solid var(--line); }
.howto-note { font-size: 0.78rem; color: var(--ink-faint); margin: 0.6rem 0 0; }
.vid-chaps { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 1rem; }
.vid-chap { display: inline-flex; align-items: baseline; gap: 0.5rem; cursor: pointer;
            background: var(--bg-sunk); border: 1px solid var(--line); color: var(--ink-soft);
            border-radius: 999px; padding: 0.32rem 0.8rem; font: inherit; font-size: 0.76rem;
            transition: border-color .18s ease, color .18s ease, background .18s ease; }
.vid-chap:hover { border-color: var(--accent); color: var(--ink); }
.vid-chap.is-now { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.vid-chap__n { font-family: var(--font-data); opacity: 0.65; }
.vid-chap__at { font-family: var(--font-data); opacity: 0.65; }
.howto-rules__h { font-family: var(--font-display); font-size: 1.05rem; margin: 0 0 1rem; }
.vid-rules { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.9rem; }
.vid-rule { display: flex; gap: 0.85rem; align-items: flex-start; }
.vid-rule__n { flex: 0 0 1.7rem; height: 1.7rem; border-radius: 50%; display: grid; place-items: center;
               background: var(--bg-sunk); border: 1px solid var(--line); color: var(--accent);
               font-family: var(--font-data); font-size: 0.76rem; }
.vid-rule div { display: grid; gap: 0.15rem; }
.vid-rule strong { font-size: 0.92rem; }
.vid-rule span { font-size: 0.82rem; color: var(--ink-faint); line-height: 1.55; }
.howto-cta { display: inline-block; margin-top: 1.4rem; font-size: 0.85rem; color: var(--accent);
             text-decoration: none; border-bottom: 1px solid rgba(var(--accent-rgb), 0.45); }
.howto-tr { margin-top: 2rem; border-top: 1px solid var(--line); padding-top: 1rem; }
.howto-tr > summary { cursor: pointer; font-size: 0.88rem; color: var(--ink-soft); }
.vid-tr { columns: 2; column-gap: 2.4rem; margin-top: 1.2rem; max-width: 1100px; }
@media (max-width: 760px) { .vid-tr { columns: 1; } }
.vid-tr__h { break-after: avoid; font-family: var(--font-display); font-size: 0.9rem;
             margin: 1.1rem 0 0.35rem; color: var(--ink); }
.vid-tr__at { font-family: var(--font-data); font-size: 0.72rem; color: var(--ink-faint); margin-left: 0.5rem; }
.vid-tr p { font-size: 0.83rem; line-height: 1.6; color: var(--ink-faint); margin: 0 0 0.5rem; }
.vid-tr__meta { break-inside: avoid; border-left: 2px solid var(--line); padding-left: 0.9rem; margin-top: 1.4rem; }

/* ==[ trip-planner ]== */
/* ==========================================================================
   The trip planner. Computed in the browser from the page's own data.
   ========================================================================== */
.trip-wrap { padding: 1.4rem; }
/* The controls are grouped in the order a trip is actually decided: when,
   who, how you get there, what you came for, what you can spend. Thirteen
   fields in one undifferentiated grid is a form, not a conversation. */
.trip-groups { display: grid; gap: 0.9rem; margin-bottom: 1.2rem; }
.trip-g { border: 1px solid var(--line); border-radius: 12px; padding: 0.5rem 1rem 0.9rem;
          margin: 0; min-width: 0; background: color-mix(in srgb, var(--bg-sunk) 55%, transparent); }
.trip-g__l { display: flex; align-items: center; gap: 0.5rem; padding: 0 0.35rem;
             font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase;
             color: var(--ink-soft); font-weight: 600; }
.trip-g__l > span { display: inline-flex; align-items: center; justify-content: center;
             width: 1.25rem; height: 1.25rem; border-radius: 50%; background: var(--accent);
             color: var(--accent-ink); font-size: 0.66rem; font-weight: 700;
             letter-spacing: 0; }
.trip-g__f { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
             gap: 0.9rem 1.3rem; margin-top: 0.6rem; }
@media (min-width: 60rem) {
  .trip-groups { grid-template-columns: 1fr 1fr; align-items: start; }
  .trip-g:nth-child(4) { grid-column: 1 / -1; }
}
.trip-controls { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
                 gap: 1rem 1.4rem; margin-bottom: 1.1rem; }
.trip-f { display: grid; gap: 0.35rem; font-size: 0.78rem; color: var(--ink-faint); }
.trip-f > span { text-transform: uppercase; letter-spacing: 0.09em; font-size: 0.66rem; }
.trip-f select, .trip-f input[type="range"] { width: 100%; }
.trip-f select { background: var(--bg-sunk); color: var(--ink); border: 1px solid var(--line);
                 border-radius: 8px; padding: 0.45rem 0.6rem; font: inherit; font-size: 0.85rem; }
.trip-f input[type="range"] { accent-color: var(--accent); }
.trip-f input[type="number"] { background: var(--bg-sunk); color: var(--ink);
                 border: 1px solid var(--line); border-radius: 8px; padding: 0.45rem 0.6rem;
                 font: inherit; font-size: 0.85rem; width: 100%; }
.trip-f__n { font-size: 0.66rem; line-height: 1.4; color: var(--ink-faint); opacity: 0.8; }
.trip-f input[type="date"] { background: var(--bg-sunk); color: var(--ink);
                 border: 1px solid var(--line); border-radius: 8px; padding: 0.4rem 0.6rem;
                 font: inherit; font-size: 0.85rem; width: 100%; }
.trip-f input.is-bad { border-color: #E0895F; }

/* The places someone refuses to miss. Twenty-nine checkboxes is a lot to show
   unasked, so it opens on request. */
.trip-must { margin-bottom: 1rem; border: 1px solid var(--line); border-radius: 12px;
             padding: 0.6rem 0.9rem; background: var(--bg-sunk); }
.trip-must > summary { cursor: pointer; font-size: 0.8rem; color: var(--ink-soft);
                       font-weight: 600; }
.trip-must__n { color: var(--accent); font-weight: 700; }
.trip-must__i { font-size: 0.7rem; color: var(--ink-faint); line-height: 1.5;
                margin: 0.5rem 0 0.6rem; max-width: 46rem; }
.trip-must__g { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
                gap: 0.2rem 0.9rem; max-height: 15rem; overflow-y: auto; padding-right: 0.4rem; }
.trip-must__c { display: flex; gap: 0.45rem; align-items: baseline; font-size: 0.76rem;
                color: var(--ink-soft); cursor: pointer; padding: 0.15rem 0; }
.trip-must__c input { accent-color: var(--accent); }
.trip-must__c small { color: var(--ink-faint); opacity: 0.75; margin-left: 0.3rem; }
.trip-checks { display: flex; flex-wrap: wrap; gap: 0.6rem 1.6rem; margin: 0.9rem 0 0; }
.trip-c { display: flex; gap: 0.5rem; align-items: flex-start; font-size: 0.8rem;
          color: var(--ink-soft); max-width: 24rem; cursor: pointer; }
.trip-c input { margin-top: 0.25rem; accent-color: var(--accent); }
.trip-c small { display: block; font-size: 0.68rem; color: var(--ink-faint); line-height: 1.45; }

/* ---------------------------------------------------------------------------
   The receipt, as a poster.

   It began as a monospace till roll, which is honest and joyless. What a
   visitor actually carries around a province for four days should be quick to
   read at arm's length: big numbers first, then the days, then the money, then
   the two things you need when something goes wrong.

   Two rules keep it from being merely decorative:

     * The five day colours are the same five, in the same order, that the
       route is drawn in on the map. Day three on paper is the colour of day
       three on screen.
     * Colour never carries meaning on its own. Every coloured band also has a
       border, a weight change or a label, because plenty of people will print
       this in black and white on a guesthouse printer.

   The palette is fixed rather than themed. A printout is a document, not a
   page, and it should not change colour because someone picked dark mode.
   --------------------------------------------------------------------------- */
.trip-receipt { display: none; }
.trip-receipt.is-open { display: block; margin: 1.4rem auto 0; max-width: 44rem; }
.trip-preview { background: transparent; border: 1px solid var(--line); border-radius: 999px;
    color: var(--ink-soft); font: inherit; font-size: 0.78rem; padding: 0.4rem 1rem;
    cursor: pointer; }
.trip-preview:hover { border-color: var(--accent); color: var(--ink); }

.r-poster {
    --r-ink: #16211C; --r-soft: #4A5B54; --r-faint: #7C8B84;
    --r-paper: #FFFFFF; --r-tint: #F4F7F5; --r-line: #D7E0DB;
    --r-green: #1F7A5C; --r-amber: #B8791A; --r-amber-bg: #FDF4E3;
    --r-red: #B33A2B; --r-red-bg: #FCEDEA;
    background: var(--r-paper); color: var(--r-ink); border: 1px solid var(--r-line);
    border-radius: 10px; overflow: hidden;
    font-family: var(--font-body, system-ui, sans-serif); font-size: 0.82rem; line-height: 1.5;
}

/* --- banner --- */
.r-top { background: var(--r-green); color: #fff; padding: 1.1rem 1.3rem 1rem; text-align: center; }
.r-top__k { margin: 0; font-size: 0.62rem; letter-spacing: 0.28em; text-transform: uppercase;
            opacity: 0.85; }
.r-top__b { margin: 0.15rem 0 0.2rem; font-size: 1.7rem; line-height: 1; font-weight: 800;
            letter-spacing: 0.16em; }
.r-top__w { margin: 0; font-size: 0.82rem; font-weight: 600; opacity: 0.95; }

/* --- the four numbers --- */
.r-tiles { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
           background: var(--r-line); border-bottom: 1px solid var(--r-line); }
.r-tile { background: var(--r-paper); padding: 0.75rem 0.5rem; text-align: center; }
.r-tile b { display: block; font-size: 1.15rem; font-weight: 800; letter-spacing: -0.01em; }
.r-tile span { display: block; font-size: 0.6rem; letter-spacing: 0.13em; text-transform: uppercase;
               color: var(--r-faint); margin-top: 0.15rem; }
.r-tile.is-money { background: var(--r-tint); }
.r-tile.is-money b { color: var(--r-green); }

/* --- how you chose to travel --- */
.r-chips { display: flex; flex-wrap: wrap; gap: 0.3rem; padding: 0.7rem 1.1rem;
           border-bottom: 1px solid var(--r-line); background: var(--r-tint); }
.r-chip { border: 1px solid var(--r-line); background: var(--r-paper); border-radius: 999px;
          padding: 0.14rem 0.6rem; font-size: 0.66rem; font-weight: 600; color: var(--r-soft); }

/* --- the map, on paper --- */
.r-map { margin: 0; padding: 0.9rem 1.1rem 0.2rem; border-bottom: 1px solid var(--r-line); }
.r-map svg { width: 100%; height: auto; max-height: 30rem; display: block;
             border: 1px solid var(--r-line); border-radius: 6px; background: #FBFCFB; }
/* The map is drawn for a dark panel. On paper it becomes ink: pale land, dark
   coast, and the route colours left exactly as they are, because those are the
   one thing carrying meaning.
   Only the first rect is the backdrop — an earlier version repainted every
   rect in the drawing, which would have wiped any legend swatch with it. */
.r-map svg > rect:first-child { fill: #FBFCFB; }
.r-map svg .tm-ring, .r-map svg .tour-ring { stroke: #C9D5CE; }
.r-map svg text { fill: #16211C; }
.r-map figcaption, .r-map > figcaption { margin-top: 0.4rem; font-size: 0.62rem;
             color: var(--r-faint); line-height: 1.4; }
.r-bnote { display: block; margin-top: 0.3rem; padding-top: 0.3rem;
             border-top: 1px solid var(--r-line); font-size: 0.58rem; line-height: 1.45; }

/* --- the days --- */
.r-days { padding: 0.9rem 1.1rem 0.2rem; }
.r-day { border-left: 4px solid var(--rc, var(--r-green)); padding: 0 0 0.7rem 0.8rem;
         margin-bottom: 0.9rem; }
.r-day__h { display: flex; align-items: center; gap: 0.45rem; flex-wrap: wrap; }
.r-day__n { display: inline-flex; align-items: center; justify-content: center;
            width: 1.4rem; height: 1.4rem; border-radius: 50%; background: var(--rc, var(--r-green));
            color: #fff; font-weight: 800; font-size: 0.76rem; }
.r-day__t { font-size: 0.86rem; font-weight: 800; }
.r-day__d { font-size: 0.74rem; color: var(--r-soft); }
.r-day__k { margin-left: auto; font-size: 0.6rem; letter-spacing: 0.11em; text-transform: uppercase;
            font-weight: 700; color: var(--rc, var(--r-green)); border: 1px solid currentColor;
            border-radius: 999px; padding: 0.08rem 0.5rem; }
.r-day__p { margin: 0.35rem 0 0; font-size: 0.72rem; color: var(--r-soft); line-height: 1.5; }
.r-day__f { margin: 0.4rem 0 0; font-size: 0.68rem; color: var(--r-faint); font-weight: 600; }

.r-stops { list-style: none; margin: 0.45rem 0 0; padding: 0; }
.r-stop { display: grid; grid-template-columns: 3.4rem 1fr auto; gap: 0.6rem;
          align-items: baseline; padding: 0.28rem 0; border-top: 1px dotted var(--r-line); }
.r-stop:first-child { border-top: 0; }
.r-stop__t { font-weight: 800; font-size: 0.76rem; font-variant-numeric: tabular-nums; }
.r-stop__t i { display: block; font-style: normal; font-weight: 500; font-size: 0.64rem;
               color: var(--r-faint); }
.r-stop__n { font-weight: 600; }
.r-stop__b { display: inline-block; font-style: normal; font-size: 0.58rem; font-weight: 700;
             letter-spacing: 0.07em; text-transform: uppercase; margin-left: 0.4rem;
             padding: 0.06rem 0.4rem; border-radius: 3px;
             background: var(--r-amber-bg); color: var(--r-amber); }
.r-stop__b--pa { background: #E8F3EE; color: var(--r-green); }
.r-stop__k { font-size: 0.8rem; font-weight: 800; color: var(--r-soft);
             font-variant-numeric: tabular-nums; }
.r-stop__k i { font-style: normal; font-weight: 500; font-size: 0.6rem; color: var(--r-faint);
               margin-left: 0.12rem; }

/* --- money --- */
.r-h3 { margin: 0 0 0.5rem; font-size: 0.66rem; letter-spacing: 0.18em; text-transform: uppercase;
        font-weight: 800; color: var(--r-green); }
.r-h3--warn { color: var(--r-amber); }
.r-h3--sos { color: var(--r-red); }
.r-cost { padding: 0.8rem 1.1rem 1rem; border-top: 2px solid var(--r-ink); }
.r-row { display: flex; align-items: baseline; gap: 0.35rem; padding: 0.16rem 0; }
.r-row__l { font-weight: 600; }
.r-row__d { flex: 1 1 auto; border-bottom: 1px dotted var(--r-line); transform: translateY(-0.18em); }
.r-row__v { font-weight: 700; font-variant-numeric: tabular-nums; }
.r-grand { display: flex; justify-content: space-between; align-items: baseline;
           background: var(--r-green); color: #fff; border-radius: 6px;
           padding: 0.5rem 0.8rem; margin-top: 0.6rem; }
.r-grand__l { font-size: 0.7rem; letter-spacing: 0.18em; text-transform: uppercase; font-weight: 700; }
.r-grand__v { font-size: 1.3rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.r-each { text-align: right; font-size: 0.76rem; font-weight: 700; color: var(--r-soft);
          margin-top: 0.3rem; }
.r-verdict { margin: 0.5rem 0 0; font-size: 0.74rem; font-weight: 700; padding: 0.35rem 0.6rem;
             border-radius: 5px; border-left: 3px solid; }
.r-verdict--over { background: var(--r-red-bg); color: var(--r-red); border-color: var(--r-red); }
.r-verdict--under { background: #E8F3EE; color: var(--r-green); border-color: var(--r-green); }

/* --- warnings --- */
.r-warns { padding: 0.8rem 1.1rem; background: var(--r-amber-bg);
           border-top: 1px solid var(--r-line); }
.r-warns ul { margin: 0; padding-left: 1rem; }
.r-warns li { font-size: 0.72rem; line-height: 1.55; margin-bottom: 0.35rem; color: #4A3A16; }

/* --- emergency --- */
.r-sos { padding: 0.8rem 1.1rem; background: var(--r-red-bg); border-top: 1px solid var(--r-line); }
.r-sos__g { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
            gap: 0.4rem 0.9rem; }
.r-sos__i b { display: block; font-size: 0.95rem; font-weight: 800; color: var(--r-red);
              font-variant-numeric: tabular-nums; }
.r-sos__i span { display: block; font-size: 0.62rem; color: #6B3A32; line-height: 1.35; }

/* --- footer --- */
.r-foot { padding: 0.8rem 1.1rem 1rem; border-top: 1px solid var(--r-line);
          background: var(--r-tint); }
.r-foot p { margin: 0; font-size: 0.64rem; line-height: 1.5; color: var(--r-faint); }
.r-foot__b { margin-top: 0.4rem !important; text-align: center; font-weight: 700;
             letter-spacing: 0.1em; text-transform: uppercase; font-size: 0.58rem !important; }

/* Does it fit the money you have? Named savings, not a shrug. */
.trip-verdict { border-radius: 12px; padding: 0.9rem 1.1rem; margin-bottom: 1.1rem;
                border: 1px solid var(--line); }
.trip-verdict h4 { margin: 0 0 0.35rem; font-size: 0.95rem; }
.trip-verdict p { margin: 0 0 0.4rem; font-size: 0.78rem; color: var(--ink-soft); }
.trip-verdict ul { margin: 0; padding-left: 1.1rem; font-size: 0.8rem; color: var(--ink-soft); }
.trip-verdict li { margin-bottom: 0.2rem; }
.trip-verdict--over { border-color: color-mix(in srgb, #E0895F 55%, var(--line)); }
.trip-verdict--under { border-color: color-mix(in srgb, #6FCB9F 45%, var(--line)); }

/* What was left out, and why. */
.trip-out-of { margin: 1.2rem 0; border: 1px solid var(--line); border-radius: 12px;
               padding: 0.75rem 1rem; background: var(--bg-sunk); }
.trip-out-of summary { cursor: pointer; font-size: 0.82rem; color: var(--ink-soft); }
.trip-out-of ul { margin: 0.6rem 0 0.4rem; padding-left: 1.1rem; font-size: 0.78rem;
                  color: var(--ink-faint); line-height: 1.6; }
.trip-out-of > p { margin: 0; font-size: 0.7rem; color: var(--ink-faint); opacity: 0.8; }
.trip-f output { font-family: var(--font-data); font-size: 0.85rem; color: var(--accent); }
.trip-ints { display: flex; gap: 0.8rem; align-items: baseline; flex-wrap: wrap;
             padding-bottom: 1.1rem; border-bottom: 1px solid var(--line); margin-bottom: 1.2rem; }
.trip-ints__l { font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.09em;
                color: var(--ink-faint); }
.trip-ints__c { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.trip-int { background: var(--bg-sunk); border: 1px solid var(--line); color: var(--ink-soft);
            border-radius: 999px; padding: 0.3rem 0.8rem; font: inherit; font-size: 0.78rem;
            cursor: pointer; transition: all .16s ease; }
.trip-int:hover { border-color: var(--accent); color: var(--ink); }
.trip-int.is-on { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.trip-split { display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); gap: 1.4rem;
              align-items: start; }
@media (max-width: 1000px) { .trip-split { grid-template-columns: 1fr; } }
.trip-mapwrap { position: sticky; top: 5rem; }
@media (max-width: 1000px) { .trip-mapwrap { position: static; } }
#trip-map { display: block; width: 100%; height: auto; border-radius: var(--radius-soft);
            border: 1px solid var(--line); }
.trip-mapnote { font-size: 0.7rem; color: var(--ink-faint); margin: 0.6rem 0 0; }
.trip-heads { display: grid; grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
              gap: 0.7rem; margin-bottom: 1.2rem; }
.trip-head { background: var(--bg-sunk); border: 1px solid var(--line);
             border-top: 3px solid var(--accent); border-radius: 4px 12px 12px 12px;
             padding: 0.8rem 0.9rem; display: grid; gap: 0.15rem; }
.trip-head__v { font-family: var(--font-display); font-size: 1.5rem; color: var(--ink);
                line-height: 1.1; }
.trip-head__l { font-size: 0.72rem; color: var(--ink-soft); }
.trip-head__s { font-size: 0.66rem; color: var(--ink-faint); }
.trip-warn { border: 1px solid rgba(var(--reported-rgb), 0.55); border-left: 3px solid var(--tier-reported);
             border-radius: var(--radius-soft); padding: 0.9rem 1.1rem; margin-bottom: 1.2rem; }
.trip-warn h4 { margin: 0 0 0.5rem; font-size: 0.8rem; text-transform: uppercase;
                letter-spacing: 0.09em; color: var(--tier-reported); }
.trip-warn ul { margin: 0; padding-left: 1.1rem; }
.trip-warn li { font-size: 0.8rem; line-height: 1.6; color: var(--ink-soft); margin-bottom: 0.4rem; }
.trip-days { display: grid; gap: 0.7rem; margin-bottom: 1.4rem; }
.trip-day { background: var(--bg-sunk); border: 1px solid var(--line); border-radius: 10px;
            padding: 0.85rem 1rem; }
.trip-day__n { font-family: var(--font-data); font-size: 0.66rem; letter-spacing: 0.1em;
               text-transform: uppercase; color: var(--accent); }
.trip-day__t { font-family: var(--font-display); font-size: 1rem; margin: 0.2rem 0 0.3rem; }
.trip-day__m { font-family: var(--font-data); font-size: 0.72rem; color: var(--ink-faint); margin: 0 0 0.5rem; }
.trip-day__b { font-size: 0.8rem; line-height: 1.55; color: var(--ink-soft); margin: 0; }
.trip-day__l { margin: 0.4rem 0 0; padding-left: 1.1rem; }
.trip-day__l li { font-size: 0.82rem; line-height: 1.5; margin-bottom: 0.35rem; color: var(--ink); }
.trip-day__l li span { display: block; font-family: var(--font-data); font-size: 0.7rem;
                       color: var(--ink-faint); }
.trip-cost h4, .trip-two h4 { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.09em;
                              color: var(--ink-faint); margin: 0 0 0.6rem; }
.trip-cost__d { display: block; font-size: 0.72rem; color: var(--ink-faint); margin-top: 0.15rem; }
.trip-cost__n { text-align: right; font-family: var(--font-data); white-space: nowrap; }
.trip-cost__t td { border-top: 2px solid var(--line); font-size: 1.05rem; }
.trip-cost__f { font-size: 0.72rem; color: var(--ink-faint); margin: 0.7rem 0 1.4rem; }
.trip-two { display: grid; grid-template-columns: 1fr 1fr; gap: 1.4rem; margin-bottom: 1rem; }
@media (max-width: 620px) { .trip-two { grid-template-columns: 1fr; } }
.trip-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.45rem; }
.trip-list li { font-size: 0.8rem; color: var(--ink-soft); }
.trip-list li span { display: block; font-size: 0.68rem; color: var(--ink-faint); }
.trip-month { font-size: 0.8rem; line-height: 1.6; color: var(--ink-soft);
              border-left: 2px solid var(--line); padding-left: 0.9rem; margin: 0; }
.trip-empty { font-size: 0.9rem; color: var(--ink-faint); padding: 2rem 0; }
.trip-actions { display: flex; gap: 1rem; align-items: center; flex-wrap: wrap;
                margin-top: 1.4rem; padding-top: 1.1rem; border-top: 1px solid var(--line); }
.trip-print { background: var(--accent); color: var(--accent-ink); border: none;
              border-radius: 999px; padding: 0.55rem 1.3rem; font: inherit; font-size: 0.85rem;
              font-weight: 600; cursor: pointer; }
.trip-actions__n { font-size: 0.72rem; color: var(--ink-faint); }
.trip-as td.trip-as__v { font-family: var(--font-data); white-space: nowrap; }
.trip-as .stat-tier { position: static; display: inline-block; }
/* ---------------------------------------------------------------------------
   Printing.

   The first attempt did not work at all, and the reason is worth keeping. It
   opened with

       body.is-printing-plan > *:not(#trip-print-host) { display: none }

   naming an element that was never built. Because :not(#id) carries the
   specificity of an id, that rule scored (1,1,1) and beat every later rule
   trying to show the receipt again — both !important, so specificity decided
   it. The result was a print job with nothing on it.

   What happens now has no specificity contest in it: the poster is cloned
   into a sheet that is a direct child of <body>, and printing hides body's
   other children. One rule, one level, and the sheet is a real element.

   print-color-adjust is set because a browser will otherwise drop the
   backgrounds to save ink, which would take the banner, the total and the
   emergency panel down to white-on-white.
   --------------------------------------------------------------------------- */
#trip-print-sheet { display: none; }

@media print {
    body.is-printing-plan > *:not(#trip-print-sheet) { display: none !important; }
    body.is-printing-plan #trip-print-sheet { display: block !important; }

    #trip-print-sheet .r-poster {
        border: 0; border-radius: 0; font-size: 9.6pt; line-height: 1.45;
        -webkit-print-color-adjust: exact; print-color-adjust: exact;
    }
    #trip-print-sheet .r-top { padding: 10mm 8mm 8mm; }
    #trip-print-sheet .r-top__b { font-size: 24pt; }
    #trip-print-sheet .r-tile b { font-size: 13pt; }
    #trip-print-sheet .r-grand__v { font-size: 15pt; }

    /* Nothing should be split across a page in a way that loses its meaning. */
    #trip-print-sheet .r-map { page-break-inside: avoid; break-inside: avoid; }
    #trip-print-sheet .r-map svg { max-height: 92mm; }
    #trip-print-sheet .r-day,
    #trip-print-sheet .r-stop,
    #trip-print-sheet .r-grand,
    #trip-print-sheet .r-sos,
    #trip-print-sheet .r-warns li { page-break-inside: avoid; break-inside: avoid; }
    #trip-print-sheet .r-h3,
    #trip-print-sheet .r-day__h { page-break-after: avoid; break-after: avoid; }

    @page { margin: 12mm; }
}

@media print {
    body.is-printing-plan main, body.is-printing-plan #trip,
    body.is-printing-plan .trip-wrap { display: block !important; }
    body.is-printing-plan #trip > *:not(.trip-wrap) { display: none !important; }
    body.is-printing-plan .trip-wrap > *:not(.trip-receipt) { display: none !important; }
    body.is-printing-plan .trip-receipt { display: block !important; border: 0;
        background: #fff; color: #000; max-width: none; margin: 0; padding: 0;
        font-family: ui-monospace, "SFMono-Regular", Menlo, monospace; font-size: 10pt; }
    body.is-printing-plan .trip-receipt .r-dots { border-bottom-color: #999; }
    body.is-printing-plan .trip-receipt .r-rule { border-top-color: #999; }
    body.is-printing-plan .trip-receipt .r-t,
    body.is-printing-plan .trip-receipt .r-x,
    body.is-printing-plan .trip-receipt .r-sub,
    body.is-printing-plan .trip-receipt .r-foot,
    body.is-printing-plan .trip-receipt .r-h2 { color: #444; }
    body.is-printing-plan .r-day { page-break-after: avoid; }
    body.is-printing-plan .r-stop { page-break-inside: avoid; }
    @page { margin: 14mm; }
}
@media print {
    .section-rail, .trip-controls, .trip-groups, .trip-checks, .trip-ints, .trip-actions, .trip-mapwrap { display: none !important; }
    .trip-split { grid-template-columns: 1fr; }
    body { background: #fff; color: #000; }
}
/* ==[ /trip-planner ]== */

/* ==[ guide ]== */
/* Bunong culture. Cards rather than a wall of prose, because a visitor reads
   this standing in a guesthouse the night before, not at a desk. */
.cult-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(17.5rem, 1fr)); gap: 1rem; }
.cult { padding: 1.2rem 1.3rem; border-left: 3px solid rgba(var(--accent-rgb), 0.55); }
.cult__t { font-family: var(--font-display); font-size: 1.02rem; margin: 0 0 0.55rem; }
.cult__b { font-size: 0.85rem; line-height: 1.65; margin: 0 0 0.7rem; color: var(--ink-soft); }
.cult__s { font-size: 0.79rem; line-height: 1.55; margin: 0; color: var(--ink-faint);
           padding-top: 0.6rem; border-top: 1px dashed var(--line); }

/* Live facet counts. A chip that would empty the list disables itself rather
   than letting the reader walk into a blank screen with no explanation. */
.tp-chip { display: inline-flex; align-items: baseline; gap: 0.4rem; }
.tp-chip__n { font-family: var(--font-data); font-size: 0.68rem; opacity: 0.6; }
.tp-chip.is-on .tp-chip__n { opacity: 0.85; }
.tp-chip.is-empty { opacity: 0.32; cursor: not-allowed; border-style: dashed; }
.tp-chip.is-empty:hover { border-color: var(--line); color: var(--ink-soft); }

/* Directory cards carry a kind, so a glance sorts a waterfall from a bed. */
.tp-card__type { font-size: 0.62rem; letter-spacing: 0.12em; text-transform: uppercase;
                 padding: 0.16rem 0.5rem; border-radius: 999px; border: 1px solid var(--line);
                 color: var(--ink-faint); }
.tp-card--see .tp-card__type   { color: var(--tier-derived); border-color: rgba(var(--derived-rgb), 0.5); }
.tp-card--do .tp-card__type    { color: var(--tier-verified); border-color: rgba(var(--verified-rgb), 0.5); }
.tp-card--sleep .tp-card__type { color: var(--tier-reported); border-color: rgba(var(--reported-rgb), 0.5); }
.tp-card--eat .tp-card__type   { color: var(--accent); border-color: rgba(var(--accent-rgb), 0.5); }
.tp-card__t { margin: 0.5rem 0 0.2rem; }
.tp-card__d { font-family: var(--font-data); font-size: 0.72rem; color: var(--ink-soft);
              margin: 0 0 0.45rem; }

/* The planner's map. Pins and cards share an index, so selecting either
   selects the other; the map is not decoration next to the list, it is the
   same 29 rows drawn differently. */
.tp-split { display: grid; grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); gap: 1.2rem; align-items: start; }
@media (max-width: 1000px) { .tp-split { grid-template-columns: 1fr; } }
.tp-mapwrap { padding: 1rem; position: sticky; top: 5rem; }
@media (max-width: 1000px) { .tp-mapwrap { position: static; } }
.tour-map { display: block; width: 100%; height: auto; border-radius: var(--radius-soft); }
.tm-pin { cursor: pointer; }
.tm-pin .tm-dot { transition: r .16s ease, stroke-width .16s ease; }
.tm-pin:hover .tm-dot, .tm-pin:focus .tm-dot { r: 6.5; stroke: var(--accent); stroke-width: 2; }
.tm-pin:focus { outline: none; }
.tm-pin.is-sel .tm-dot { r: 7.5; stroke: var(--accent); stroke-width: 2.4; }
.tp-mapnote { font-size: 0.72rem; line-height: 1.55; color: var(--ink-faint); margin: 0.7rem 0 0; }
.tp-mapnote__d { color: var(--tier-derived); }
.tp-card { cursor: pointer; }
.tp-card.is-sel { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }
.tp-card__geo { margin: 0 0 0.4rem; font-family: var(--font-data); font-size: 0.7rem; }
.tp-card__geo a { color: var(--ink-faint); text-decoration: none; border-bottom: 1px dotted var(--line); }
.tp-card__geo a:hover { color: var(--accent); border-bottom-color: var(--accent); }
.t-dist td:nth-child(3), .t-dist td:nth-child(4) { font-family: var(--font-data); white-space: nowrap; }
.t-dist td .stat-tier { position: static; display: inline-block; margin-left: 0.35rem; }
.t-emg td.emg-num { font-family: var(--font-data); font-weight: 600; color: var(--accent); white-space: nowrap; }

/* The directory folds shut until asked for. Sixty-six cards at once is a wall,
   not an index.

   The fold has to be a class rather than the hidden attribute: [hidden] is
   display:none at specificity (0,1,0), .tp__grid sets display:grid at the same
   specificity, and the later rule wins. Setting el.hidden = true therefore did
   exactly nothing, which is why the button appeared to be dead. */
.tp__grid.is-folded { display: none !important; }
.tp__head { display: flex; align-items: baseline; justify-content: space-between;
            gap: 1rem; flex-wrap: wrap; }
.tp__toggle { background: var(--accent); border: 1px solid var(--accent); border-radius: 999px;
              color: var(--accent-ink); font: inherit; font-size: 0.78rem; font-weight: 600;
              padding: 0.4rem 1rem; cursor: pointer; white-space: nowrap;
              transition: filter 0.15s ease, transform 0.15s ease; }
.tp__toggle:hover { filter: brightness(1.08); transform: translateY(-1px); }
.tp__toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* Trip planner and the expanded Visitor Guide. Cards stay in the DOM and are
   hidden with the `hidden` attribute rather than removed, so the whole
   inventory is in the page source with JavaScript off. */
.tp { padding: 1.4rem; }
.tp__bar { display: flex; gap: 0.6rem; margin-bottom: 1rem; }
.tp__q { flex: 1; background: var(--bg-sunk); border: 1px solid var(--line); color: var(--ink);
         border-radius: var(--radius-soft); padding: 0.62rem 0.9rem; font: inherit; font-size: 0.9rem; }
.tp__q:focus { outline: none; border-color: var(--accent); }
.tp__clear, .tp__reset-inline { background: none; border: 1px solid var(--line); color: var(--ink-soft);
         border-radius: var(--radius-soft); padding: 0.5rem 0.9rem; font: inherit; font-size: 0.82rem; cursor: pointer; }
.tp__clear:hover, .tp__reset-inline:hover { border-color: var(--accent); color: var(--ink); }
.tp-facet { display: flex; gap: 0.8rem; align-items: baseline; margin-bottom: 0.55rem; flex-wrap: wrap; }
.tp-facet__l { flex: 0 0 10.5rem; font-size: 0.74rem; text-transform: uppercase;
               letter-spacing: 0.08em; color: var(--ink-faint); }
.tp-facet__c { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.tp-chip { background: var(--bg-sunk); border: 1px solid var(--line); color: var(--ink-soft);
           border-radius: 999px; padding: 0.28rem 0.75rem; font: inherit; font-size: 0.78rem;
           cursor: pointer; transition: border-color .16s ease, background .16s ease, color .16s ease; }
.tp-chip:hover { border-color: var(--accent); color: var(--ink); }
.tp-chip.is-on { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.tp__count { font-size: 0.78rem; color: var(--ink-faint); margin: 0.9rem 0 0.8rem; }
.tp__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(15.5rem, 1fr)); gap: 0.85rem; }
.tp__empty { font-size: 0.86rem; color: var(--ink-faint); margin-top: 1rem; }
.tp-card { background: var(--bg-sunk); border: 1px solid var(--line); border-radius: var(--radius-soft);
           padding: 0.95rem 1rem; position: relative; }
.tp-card[hidden] { display: none; }
.tp-card__top { display: flex; justify-content: space-between; align-items: flex-start; gap: 0.5rem; }
.tp-card__t { font-family: var(--font-display); font-size: 0.98rem; margin: 0 0 0.15rem; }
.tp-card__top .stat-tier { position: static; flex: 0 0 auto; }
.tp-card__km { font-size: 0.86rem; color: var(--ink-soft); margin: 0 0 0.35rem; }
.tp-card__meta { font-size: 0.74rem; color: var(--ink-faint); margin: 0 0 0.5rem; }
.tp-card__d { font-family: var(--font-data); }
.tp-card__note { font-size: 0.78rem; line-height: 1.55; color: var(--ink-soft); margin: 0 0 0.5rem; }
.tp-card__note--thin { color: var(--ink-faint); font-style: italic; }
.tp-card__src { font-size: 0.68rem; color: var(--ink-faint); margin: 0; }
.op-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr)); gap: 1rem; }
.op-card { padding: 1.2rem 1.3rem; }
.op-kind { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.09em; color: var(--accent); }
.op-name { font-family: var(--font-display); font-size: 1.08rem; margin: 0.3rem 0 0.2rem; }
.op-where { font-size: 0.78rem; color: var(--ink-faint); margin: 0 0 0.25rem; }
.op-price { font-family: var(--font-data); font-size: 0.8rem; color: var(--accent);
            margin: 0 0 0.7rem; }
.op-model { font-size: 0.85rem; line-height: 1.6; margin: 0 0 0.7rem; }
.op-flags { display: flex; flex-wrap: wrap; gap: 0.35rem; margin: 0 0 0.7rem; }
.op-flag { font-size: 0.7rem; border: 1px solid var(--line); border-radius: 999px;
           padding: 0.16rem 0.6rem; color: var(--ink-faint); }
.op-flag--good { border-color: rgba(var(--verified-rgb), 0.6); color: var(--tier-verified); }
.op-book { font-size: 0.8rem; color: var(--ink-soft); margin: 0 0 0.6rem; }
.op-src { font-size: 0.68rem; color: var(--ink-faint); margin: 0; }
.op-src .stat-tier { position: static; display: inline-block; margin-right: 0.4rem; }
.notice--plain { border: 1px solid var(--line); border-left: 3px solid var(--accent);
                 border-radius: var(--radius-soft); padding: 1rem 1.2rem; margin-bottom: 1.6rem; }
.notice--plain p { font-size: 0.85rem; line-height: 1.65; margin: 0; color: var(--ink-soft); }
.t-table td.t-src, .cost-table td.t-src { font-size: 0.7rem; color: var(--ink-faint); }
.t-months tr.is-wet td { background: rgba(var(--ink-rgb), 0.04); }
.itin-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr)); gap: 1rem; }
.itin { padding: 1.2rem 1.3rem; }
.itin__d { font-family: var(--font-data); font-size: 0.72rem; color: var(--accent);
           text-transform: uppercase; letter-spacing: 0.08em; }
.itin__t { font-family: var(--font-display); font-size: 1.02rem; margin: 0.3rem 0 0.7rem; }
.itin__l { margin: 0 0 0.8rem; padding-left: 1.1rem; }
.itin__l li { font-size: 0.82rem; line-height: 1.55; margin-bottom: 0.4rem; }
.itin__f { font-size: 0.76rem; color: var(--ink-faint); margin: 0; font-style: italic; }
.prac-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: 1rem; }
.prac { border-left: 2px solid var(--line); padding-left: 0.95rem; }
.prac__t { font-family: var(--font-display); font-size: 0.92rem; margin: 0 0 0.3rem; }
.prac__b { font-size: 0.82rem; line-height: 1.6; color: var(--ink-soft); margin: 0 0 0.35rem; }
.prac__s { font-size: 0.66rem; color: var(--ink-faint); margin: 0; }
/* ==[ /guide ]== */

/* ==[ guide-rail ]== */
/* The Visitor Guide rail is grouped now. Sixteen undifferentiated links is a
   list, not navigation, and four of them pointed at sections a later one had
   already superseded. */
.rail-group { display: block; font-size: 0.62rem; letter-spacing: 0.13em;
              text-transform: uppercase; color: var(--ink-faint); opacity: 0.75;
              margin: 0.9rem 0 0.3rem; padding-left: 0.1rem; }
.rail-group:first-child { margin-top: 0; }
.section-rail .rail-group + .rail-item { margin-top: 0; }
/* ==[ /guide-rail ]== */

/* ==[ guide-cards ]== */
/* ==========================================================================
   Visitor Guide: header composition and typed directory cards
   ========================================================================== */

/* --- the cinematic header ------------------------------------------------
   The background loop puts the province on the right, so the words go left.
   Centred, they sat on top of the map outline. */
#cinematic-header { justify-content: flex-start; text-align: left; }
#cinematic-header .cinematic-content {
    max-width: min(46rem, 56%);
    margin-left: clamp(1.5rem, 7vw, 7rem);
    padding-right: 2rem;
}
#cinematic-header .cinematic-title { text-wrap: balance; }
/* A scrim under the words as well as in the video, so the title survives
   whatever frame it lands on. */
#cinematic-header .cinematic-overlay {
    background:
        linear-gradient(90deg, rgba(var(--shade-rgb), 0.82) 0%,
                        rgba(var(--shade-rgb), 0.62) 42%,
                        rgba(var(--shade-rgb), 0.10) 68%,
                        rgba(var(--shade-rgb), 0.25) 100%),
        linear-gradient(180deg, rgba(var(--shade-rgb), 0.55) 0%,
                        rgba(var(--shade-rgb), 0.15) 45%,
                        rgba(var(--shade-rgb), 0.80) 100%);
}
@media (max-width: 820px) {
    /* No room for a two-column composition: darken everything and centre. */
    #cinematic-header { justify-content: center; text-align: center; }
    #cinematic-header .cinematic-content { max-width: 100%; margin-left: 0; padding: 2rem; }
    #cinematic-header .cinematic-overlay {
        background: linear-gradient(180deg, rgba(var(--shade-rgb), 0.72) 0%,
                                    rgba(var(--shade-rgb), 0.55) 50%,
                                    rgba(var(--shade-rgb), 0.85) 100%);
    }
}

/* --- typed directory cards ----------------------------------------------
   Four kinds, four identities. The accent, the notched corner and the glyph
   all carry the same signal, so it survives colour-blindness and greyscale. */
.tp__grid { grid-template-columns: repeat(auto-fill, minmax(16.5rem, 1fr)); gap: 1rem; }

.tp-card {
    --tpc: var(--ink-faint);
    position: relative;
    display: flex;
    flex-direction: column;
    background:
        linear-gradient(160deg, rgba(var(--ink-rgb), 0.045) 0%, transparent 55%),
        var(--bg-sunk);
    border: 1px solid var(--line);
    border-top: 3px solid var(--tpc);
    border-radius: 4px 14px 14px 14px;
    padding: 1rem 1.05rem 0.9rem;
    transition: transform .18s ease, border-color .18s ease, box-shadow .18s ease;
    overflow: hidden;
}
.tp-card::after {
    /* A soft wash of the type colour, bottom-right, so a glance sorts the grid. */
    content: "";
    position: absolute;
    right: -38%;
    bottom: -55%;
    width: 84%;
    aspect-ratio: 1;
    border-radius: 50%;
    background: var(--tpc);
    opacity: 0.06;
    pointer-events: none;
}
.tp-card:hover { transform: translateY(-3px); border-color: var(--tpc);
                 box-shadow: 0 10px 26px -18px rgba(0, 0, 0, 0.9); }
.tp-card.is-sel { border-color: var(--tpc); box-shadow: 0 0 0 1px var(--tpc) inset; }

.tp-card--see   { --tpc: #6FA8DC; }
.tp-card--do    { --tpc: #6FCB9F; }
.tp-card--sleep { --tpc: #E9B979; }
.tp-card--eat   { --tpc: #E0895F; }

/* Type chip: glyph + word, in the card's own colour. */
.tp-card__type {
    display: inline-flex; align-items: center; gap: 0.35rem;
    font-size: 0.6rem; letter-spacing: 0.14em; text-transform: uppercase;
    font-weight: 700; color: var(--tpc);
    border: 1px solid var(--tpc); border-radius: 999px;
    padding: 0.2rem 0.6rem 0.2rem 0.5rem; background: rgba(var(--ink-rgb), 0.04);
}
.tp-card__type::before {
    content: ""; width: 0.62rem; height: 0.62rem; flex: 0 0 auto;
    background: currentColor;
    -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
    -webkit-mask-size: contain; mask-size: contain;
}
/* map pin */
.tp-card--see .tp-card__type::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2a7 7 0 0 0-7 7c0 5 7 13 7 13s7-8 7-13a7 7 0 0 0-7-7zm0 9.5A2.5 2.5 0 1 1 12 6a2.5 2.5 0 0 1 0 5.5z'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2a7 7 0 0 0-7 7c0 5 7 13 7 13s7-8 7-13a7 7 0 0 0-7-7zm0 9.5A2.5 2.5 0 1 1 12 6a2.5 2.5 0 0 1 0 5.5z'/%3E%3C/svg%3E");
}
/* compass / activity */
.tp-card--do .tp-card__type::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20zm3.5 6.5-2.1 5-5 2.1 2.1-5 5-2.1z'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20zm3.5 6.5-2.1 5-5 2.1 2.1-5 5-2.1z'/%3E%3C/svg%3E");
}
/* bed */
.tp-card--sleep .tp-card__type::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3 7h2v6h14a3 3 0 0 1 3 3v4h-2v-3H4v3H2V7h1zm5 1a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5z'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3 7h2v6h14a3 3 0 0 1 3 3v4h-2v-3H4v3H2V7h1zm5 1a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5z'/%3E%3C/svg%3E");
}
/* cup */
.tp-card--eat .tp-card__type::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M4 4h13v4h2a3 3 0 0 1 0 6h-2v2a4 4 0 0 1-4 4H8a4 4 0 0 1-4-4V4zm13 6v2h2a1 1 0 0 0 0-2h-2z'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M4 4h13v4h2a3 3 0 0 1 0 6h-2v2a4 4 0 0 1-4 4H8a4 4 0 0 1-4-4V4zm13 6v2h2a1 1 0 0 0 0-2h-2z'/%3E%3C/svg%3E");
}

.tp-card__top { display: flex; justify-content: space-between; align-items: center;
                gap: 0.5rem; margin-bottom: 0.55rem; }
.tp-card__t { font-family: var(--font-display); font-size: 1.02rem; line-height: 1.25;
              margin: 0 0 0.15rem; color: var(--ink); }
.tp-card__km { font-size: 0.84rem; color: var(--tpc); margin: 0 0 0.3rem; opacity: 0.92; }
.tp-card__meta { font-size: 0.72rem; letter-spacing: 0.02em; color: var(--ink-faint);
                 margin: 0 0 0.5rem; text-transform: uppercase; }
.tp-card__d { font-family: var(--font-data); font-size: 0.75rem; color: var(--ink-soft);
              margin: 0 0 0.55rem; padding: 0.3rem 0.5rem; border-radius: 6px;
              background: rgba(var(--ink-rgb), 0.05); display: inline-block; }
.tp-card__note { font-size: 0.79rem; line-height: 1.55; color: var(--ink-soft);
                 margin: 0 0 0.6rem; flex: 1; }
.tp-card__note--thin { color: var(--ink-faint); font-style: italic; }
.tp-card__geo { margin: 0 0 0.45rem; }
.tp-card__src { font-size: 0.65rem; color: var(--ink-faint); margin: 0;
                padding-top: 0.5rem; border-top: 1px dashed var(--line); }
.tp-card__top .stat-tier { position: static; flex: 0 0 auto; }
/* ==[ /guide-cards ]== */

/* ==[ reveal ]== */
/* Reveal-on-scroll must never be the reason content cannot be read. Anyone who
   has asked for reduced motion gets the content, not the animation. */
@media (prefers-reduced-motion: reduce) {
    [data-reveal] { opacity: 1 !important; transform: none !important; }
}
/* ==[ /reveal ]== */

/* ==[ map-boundary ]== */
/* The boundary notice. Every province map draws Mondulkiri's eastern edge,
   which is the international boundary with Viet Nam, and none of these outlines
   is a survey. Stated plainly under every one of them, in both languages. */
.map-boundary { display: flex; gap: 0.55rem; align-items: flex-start;
                margin: 0.55rem 0 0; padding: 0.5rem 0.7rem;
                border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--line));
                border-left-width: 3px; border-radius: 7px;
                background: color-mix(in srgb, var(--bg-sunk) 70%, transparent); }
.map-boundary__i { flex: 0 0 auto; display: inline-flex; align-items: center;
                justify-content: center; width: 1.05rem; height: 1.05rem;
                border-radius: 50%; background: var(--accent); color: var(--accent-ink);
                font-size: 0.66rem; font-weight: 800; margin-top: 0.1rem; }
.map-boundary__t { font-size: 0.68rem; line-height: 1.5; color: var(--ink-faint); }
.map-boundary__km { display: block; margin-top: 0.28rem; font-size: 0.7rem;
                line-height: 1.65; opacity: 0.9; }
@media print { .map-boundary { border-color: #999; background: transparent; }
               .map-boundary__t { color: #333; } }
/* ==[ /map-boundary ]== */

/* ==[ place-filter ]== */
/* The place filter on the District & Commune Explorer. */
.pf { padding: 1.1rem 1.2rem; margin-bottom: 1.5rem; }
.pf__row { display: grid; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
           gap: 0.9rem 1.2rem; align-items: end; margin-bottom: 0.9rem; }
.pf__f { display: grid; gap: 0.3rem; font-size: 0.78rem; color: var(--ink-faint); }
.pf__f > span { text-transform: uppercase; letter-spacing: 0.09em; font-size: 0.64rem; }
.pf__f select { background: var(--bg-sunk); color: var(--ink); border: 1px solid var(--line);
           border-radius: 8px; padding: 0.45rem 0.6rem; font: inherit; font-size: 0.84rem;
           width: 100%; }
.pf__f select:disabled { opacity: 0.5; }
.pf__n { font-size: 0.64rem; line-height: 1.4; opacity: 0.8; }
.pf__clear { align-self: end; background: transparent; border: 1px solid var(--line);
           border-radius: 999px; color: var(--ink-soft); font: inherit; font-size: 0.76rem;
           padding: 0.42rem 0.9rem; cursor: pointer; height: 2.1rem; }
.pf__status { font-size: 0.76rem; color: var(--ink-faint); margin: 0 0 0.9rem; }
.pf__sync { font-size: 0.68rem; color: var(--ink-faint); opacity: 0.85; margin: 0 0 0.7rem;
            border-left: 2px solid var(--line); padding-left: 0.6rem; }

.pf-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
           gap: 0.6rem; }
.pf-tile { text-align: left; background: var(--bg-sunk); border: 1px solid var(--line);
           border-radius: 10px; padding: 0.7rem 0.85rem; cursor: pointer; color: var(--ink-soft);
           font: inherit; display: grid; gap: 0.16rem; transition: border-color 0.15s ease,
           transform 0.15s ease; }
.pf-tile:hover { border-color: var(--accent); transform: translateY(-1px); }
.pf-tile b { font-size: 0.95rem; color: var(--ink); }
.pf-tile span { font-size: 0.7rem; color: var(--ink-faint); }
.pf-tile__pa { color: var(--accent) !important; font-weight: 600; }

.pf-card { background: var(--bg-sunk); border: 1px solid var(--line); border-radius: 10px;
           padding: 0.9rem 1rem; }
.pf-card h4 { margin: 0 0 0.7rem; font-size: 1.05rem; }
.pf-card__k { display: block; font-size: 0.7rem; font-weight: 400; color: var(--ink-faint);
           margin-top: 0.15rem; }
.pf-card__p { font-size: 0.78rem; line-height: 1.6; color: var(--ink-soft); margin: 0.7rem 0 0; }
.pf-card__p--warn { border-left: 3px solid var(--accent); padding-left: 0.7rem; }
.pf-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
           gap: 0.5rem 1rem; }
.pf-s { border-top: 1px solid var(--line); padding-top: 0.4rem; }
.pf-s__l { display: block; font-size: 0.64rem; text-transform: uppercase; letter-spacing: 0.09em;
           color: var(--ink-faint); }
.pf-s__v { font-size: 1.1rem; font-weight: 700; color: var(--ink);
           font-variant-numeric: tabular-nums; }
.pf-s__v i { font-style: normal; font-size: 0.7rem; font-weight: 500; color: var(--ink-faint);
           margin-left: 0.2rem; }

.pf-list { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.9rem; }
.pf-chip { background: var(--bg-panel, transparent); border: 1px solid var(--line);
           border-radius: 999px; color: var(--ink-soft); font: inherit; font-size: 0.76rem;
           padding: 0.28rem 0.75rem; cursor: pointer; display: inline-flex; gap: 0.4rem;
           align-items: baseline; }
.pf-chip:hover { border-color: var(--accent); color: var(--ink); }
.pf-chip span { font-size: 0.66rem; color: var(--ink-faint); }
.pf-kh { font-weight: 400; color: var(--ink-faint); font-size: 0.86em; }
.pf-tile .pf-kh { font-size: 0.78rem; }
.pf-card h4 .pf-kh { font-size: 0.8rem; margin-left: 0.35rem; }

/* An accordion folded away by the filter, not by the reader. */
.district-acc.is-hidden { display: none !important; }
/* ==[ /place-filter ]== */

/* ==[ names ]== */
/* The name glossary. One spelling is used across the site; this is where the
   others live, so a reader holding a provincial document can still find the
   page they need. */
.nm { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
      gap: 0.5rem 1.4rem; margin: 1rem 0 0; }
.nm-i { border-top: 1px solid var(--line); padding-top: 0.45rem; }
.nm-i b { display: block; font-size: 0.9rem; }
.nm-i .nm-kh { font-weight: 400; color: var(--ink-faint); margin-left: 0.3rem; }
.nm-i span { display: block; font-size: 0.7rem; color: var(--ink-faint); line-height: 1.5; }

.nm-wrap { border: 1px solid var(--line); border-radius: 12px; padding: 0.7rem 1rem;
           margin-bottom: 1.2rem; background: var(--bg-sunk); }
.nm-wrap > summary { cursor: pointer; font-size: 0.82rem; font-weight: 600;
           color: var(--ink-soft); }
/* ==[ /names ]== */


/* ==[ hub-onebar ]== */
/* The Data Hub's one filter.

   It replaced a strip of five widgets — a mode switch, a search box, three
   place menus and a row of chips — because five controls in a column is not
   one filter, whatever the heading above them says. This is a single field:
   what you have chosen sits inside it as chips, what you can choose next drops
   below it with a count, and an empty field means the whole hub. */
.onebar { position: relative; margin-bottom: 0.6rem; }
.onebar__field { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem;
    background: var(--bg-sunk); border: 1px solid var(--line); border-radius: 12px;
    padding: 0.4rem 0.5rem; transition: border-color 0.15s ease; }
.onebar__field:focus-within { border-color: var(--accent); }
.onebar__chips { display: contents; }
.onebar__chip { display: inline-flex; align-items: center; gap: 0.3rem;
    background: var(--accent); color: var(--accent-ink); border-radius: 999px;
    padding: 0.15rem 0.3rem 0.15rem 0.55rem; font-size: 0.74rem; font-weight: 600; }
.onebar__chip-k { font-size: 0.56rem; text-transform: uppercase; letter-spacing: 0.1em;
    opacity: 0.75; }
.onebar__x { background: transparent; border: 0; color: inherit; cursor: pointer;
    font-size: 0.9rem; line-height: 1; padding: 0 0.25rem; opacity: 0.8; }
.onebar__x:hover { opacity: 1; }
.onebar__input { flex: 1 1 9rem; min-width: 7rem; background: transparent; border: 0;
    color: var(--ink); font: inherit; font-size: 0.82rem; padding: 0.25rem; outline: none; }
.onebar__clear { background: transparent; border: 0; color: var(--ink-faint); font: inherit;
    font-size: 0.7rem; cursor: pointer; padding: 0 0.35rem; }
.onebar__clear:hover { color: var(--ink); }

.onebar__menu { position: absolute; z-index: 40; left: 0; right: 0; top: calc(100% + 0.3rem);
    max-height: 22rem; overflow-y: auto; background: var(--bg-panel, var(--bg-sunk));
    border: 1px solid var(--line); border-radius: 12px; padding: 0.35rem;
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.35); }
.onebar__g { margin: 0.35rem 0 0.15rem; padding: 0 0.45rem; font-size: 0.58rem;
    letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-faint); }
.onebar__o { display: flex; align-items: baseline; gap: 0.5rem; width: 100%;
    background: transparent; border: 0; border-radius: 8px; color: var(--ink-soft);
    font: inherit; font-size: 0.78rem; text-align: left; padding: 0.3rem 0.45rem;
    cursor: pointer; }
.onebar__o:hover, .onebar__o:focus-visible { background: var(--bg-sunk); color: var(--ink); }
.onebar__o-l { flex: 1 1 auto; }
.onebar__kh { color: var(--ink-faint); font-size: 0.9em; }
.onebar__o-s { color: var(--ink-faint); font-size: 0.66rem; white-space: nowrap; }
.onebar__o-n { color: var(--accent); font-weight: 700; font-size: 0.7rem;
    font-variant-numeric: tabular-nums; }

/* Where you are. The list used to light whatever you last clicked and then go
   stale as soon as you scrolled; now it follows the reading line down the page.
   A left bar rather than only a tint, so the position is legible at a glance
   and does not depend on colour alone. */
.console__item[aria-current="true"] { position: relative; }
.console__item[aria-current="true"]::before {
    content: ""; position: absolute; left: 0; top: 12%; bottom: 12%; width: 3px;
    border-radius: 0 3px 3px 0; background: var(--accent); }
.console__item[aria-current="true"] .console__item-t { color: var(--ink); }
@media (prefers-reduced-motion: no-preference) {
    .console__item { transition: background-color 0.18s ease, border-color 0.18s ease; }
}

/* The hub is one scroll. Panels the bar has ruled out are removed from it;
   with an empty bar nothing is ruled out. */
.hub-layout.is-console .console__stage > section.register-section { display: block; }
.hub-layout.is-console .console__stage > section.register-section[hidden] { display: none; }
.hub-layout.is-console .console__stage > section.register-section + section.register-section {
    border-top: 1px solid var(--line); margin-top: 2.6rem; padding-top: 2.6rem; }
/* ==[ /hub-onebar ]== */

/* ==[ data-panels ]== */
/* ---- data tables -------------------------------------------------------
   Modelled on .commune-table, with one deliberate difference: these tables
   carry a column of prose ("Which to use, and why"), so cells align to the
   top rather than the middle and text is allowed to wrap. Aligning a short
   label to the middle of a six-line paragraph is what made these rows read
   as empty.                                                              */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch;
              border: 1px solid var(--line); border-radius: var(--radius-soft);
              background: var(--bg-sunk); margin: 1.3rem 0; }
.data-table { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
/* Below this the columns collide; the wrapper scrolls instead of crushing. */
.table-wrap > .data-table { min-width: 44rem; }
.data-table th { font-family: var(--font-data); font-size: 0.64rem; font-weight: 600;
                 text-transform: uppercase; letter-spacing: 0.08em; color: var(--accent);
                 text-align: left; vertical-align: bottom; white-space: nowrap;
                 padding: 0.7rem 0.85rem; border-bottom: 1px solid var(--line); }
.data-table td { padding: 0.65rem 0.85rem; vertical-align: top; line-height: 1.6;
                 color: var(--ink-soft); border-bottom: 1px solid var(--line); }
.data-table tbody tr:last-child td { border-bottom: none; }
.data-table tbody tr:hover { background: rgba(var(--surface-rgb), 0.03); }
.data-table td strong, .data-table td b { color: var(--ink); font-weight: 600; }
/* Figures line up column-wise only if the digits are the same width. */
.data-table td { font-variant-numeric: tabular-nums; }
/* A figure, and under it who published it. Classed spans are left alone:
   the Tier column holds .tier-badge and must stay a pill. */
.data-table td > span:not([class]) { display: block; font-family: var(--font-data);
                 font-size: 0.68rem; color: var(--ink-faint); margin-top: 0.2rem;
                 font-variant-numeric: normal; }
/* The totals row, where a table has one. */
.data-table tfoot td, .data-table tr.is-total td { font-weight: 700; color: var(--ink);
                 border-top: 1px solid var(--line); }

/* ---- stat cards --------------------------------------------------------
   .stat-card had padding and a hover transform but no surface to sit on and
   no rules for its three children, so a card was three inline spans of body
   text floating in the middle of the column.                             */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
             gap: 1rem; }
.stat-card { background: var(--bg-sunk); border: 1px solid var(--line);
             padding: 1.5rem 1.25rem; }
.stat-card__value { display: block; font-family: var(--font-data); font-weight: 700;
             font-size: clamp(1.65rem, 3.2vw, 2.25rem); line-height: 1.1;
             letter-spacing: -0.01em; color: var(--ink); }
.stat-card__label { display: block; margin-top: 0.55rem; font-size: 0.84rem;
             font-weight: 600; line-height: 1.45; color: var(--ink); }
.stat-card__note { display: block; margin-top: 0.45rem; font-size: 0.75rem;
             line-height: 1.6; color: var(--ink-faint); }

/* ---- tier badges -------------------------------------------------------
   The honesty system's whole point is that a reader can see at a glance where
   a figure came from. Unstyled, the badge was indistinguishable from the
   sentence after it, so a source line opened "Verified Reported Sources:" --
   two badges and a word, read as three words. .stat-tier, the older name for
   the same idea, was styled; this one never was. Same colours, so the two
   spellings cannot drift apart visually.                                  */
.tier-badge { display: inline-block; padding: 0.12rem 0.5rem; border-radius: 999px;
              font-family: var(--font-data); font-size: 0.6rem; font-weight: 600;
              text-transform: uppercase; letter-spacing: 0.07em; white-space: nowrap;
              margin-right: 0.4rem; }
.tier-badge--verified { background: rgba(var(--verified-rgb), 0.18); color: var(--tier-verified); }
.tier-badge--reported { background: rgba(var(--reported-rgb), 0.18); color: var(--tier-reported); }
.tier-badge--derived  { background: rgba(var(--derived-rgb),  0.16); color: var(--tier-derived); }
.tier-badge--contested{ background: rgba(var(--contested-rgb), 0.18); color: var(--tier-contested); }
/* Several badges in a row means several tiers in one panel; the last one
   still needs air before the sentence starts. */
.tier-badge + .tier-badge { margin-left: -0.15rem; }

/* ---- the source line ---------------------------------------------------
   Every panel opens with one. It is apparatus, not argument, so it reads as
   a margin note rather than as the first paragraph.                       */
.stat-note--source { border-left: 2px solid var(--line); padding-left: 0.9rem;
                     line-height: 1.65; }

/* ---- sub-headings and plain lists inside a register section ------------
   A panel long enough to need a second-level heading needs it to look like
   one: an <h3> with no rule inherits a size that sits between the section
   title and the body text by accident rather than by design.            */
.register-sub { font-family: var(--font-display); font-size: 1.12rem; font-weight: 600;
                color: var(--ink); margin: 2rem 0 0.6rem; }
.pf-list-plain { list-style: none; margin: 0.8rem 0 0; padding: 0; display: grid;
                 gap: 0.7rem; max-width: 900px; }
.pf-list-plain > li { font-size: 0.85rem; line-height: 1.65; color: var(--ink-soft);
                 border-left: 2px solid var(--line); padding-left: 0.9rem; }
.pf-list-plain > li strong { color: var(--ink); }

/* ---- odds and ends whose siblings were styled and they were not -------- */
.tp-chip__l { font-size: inherit; }
.vid-chap__t { font-weight: 600; }
.portal-title { font-family: var(--font-display); font-size: clamp(1.3rem, 2.6vw, 1.7rem);
                margin: 0 0 0.4rem; color: var(--ink); }
.portal-description { font-size: 0.88rem; line-height: 1.6; color: var(--ink-faint);
                margin: 0 0 1rem; }
.portal-action { display: inline-block; font-size: 0.82rem; font-weight: 600;
                letter-spacing: 0.02em; }
/* ==[ /data-panels ]== */

/* ==[ investment register ]== ------------------------------------------------
   A filterable table on a page that otherwise has none. The controls sit above
   the scroll container rather than inside it, so that on a narrow screen the
   table scrolls sideways and the filters stay put — the alternative is a
   reader losing the reset button by scrolling to column six.              */
.ireg { padding: 0; overflow: hidden; }
.ireg__controls { display: grid; gap: 0.75rem; padding: 1rem 1.1rem 0.85rem;
                  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
                  border-bottom: 1px solid var(--line); }
.ireg__field { display: flex; flex-direction: column; gap: 0.3rem; min-width: 0; }
.ireg__field--search { grid-column: 1 / -1; }
@media (min-width: 46rem) { .ireg__field--search { grid-column: span 2; } }
.ireg__label { font-family: var(--font-data); font-size: 0.6rem; font-weight: 600;
               text-transform: uppercase; letter-spacing: 0.08em; color: var(--accent); }
.ireg__search, .ireg__select {
    width: 100%; font: inherit; font-size: 0.82rem; color: var(--ink);
    background: var(--bg-raised); border: 1px solid var(--line); border-radius: 6px;
    padding: 0.42rem 0.6rem; min-width: 0; }
.ireg__search:focus-visible, .ireg__select:focus-visible, .ireg__chip:focus-visible,
.ireg__reset:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ireg__bar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.75rem;
             padding: 0.6rem 1.1rem; border-bottom: 1px solid var(--line);
             background: rgba(var(--surface-rgb), 0.03); }
.ireg__chips { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.ireg__chip { font-family: var(--font-data); font-size: 0.6rem; font-weight: 600;
              text-transform: uppercase; letter-spacing: 0.07em; cursor: pointer;
              padding: 0.2rem 0.62rem; border-radius: 999px; color: var(--ink-faint);
              background: transparent; border: 1px solid var(--line); }
.ireg__chip[aria-pressed="true"] { background: var(--accent); color: var(--accent-ink);
                                   border-color: var(--accent); }
.ireg__count { margin: 0 0 0 auto; font-family: var(--font-data); font-size: 0.68rem;
               color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.ireg__reset { font-family: var(--font-data); font-size: 0.62rem; font-weight: 600;
               text-transform: uppercase; letter-spacing: 0.07em; cursor: pointer;
               color: var(--accent); background: transparent; border: none; padding: 0.2rem 0; }
/* 26rem keeps roughly eight rows in view, which is enough to see a filter work
   without the section swallowing the page at fifty-odd entries. */
.ireg__scroll { max-height: 26rem; overflow: auto; }
.ireg__table { min-width: 52rem; }
.ireg__table thead th { position: sticky; top: 0; z-index: 1; background: var(--bg-raised);
                        box-shadow: inset 0 -1px 0 var(--line); }
.ireg__note { display: block; font-size: 0.72rem; line-height: 1.5; color: var(--ink-faint);
              margin-top: 0.2rem; max-width: 24rem; }
.ireg__src { display: block; font-family: var(--font-data); font-size: 0.66rem;
             line-height: 1.45; color: var(--ink-faint); margin-top: 0.25rem; }
.ireg__empty { margin: 0; padding: 1.4rem 1.1rem; font-size: 0.82rem; color: var(--ink-faint); }
.ireg__row[hidden] { display: none; }
/* ==[ /investment register ]== */

/* ==[ google earth and satellite ]== ----------------------------------------
   The satellite panel is inert until asked. Everything below styles the two
   states of that panel and the link rows, in theme variables only — this site
   ships six palettes and a hard-coded colour is correct in exactly one.   */
.gsat { margin: 1.6rem 0 0; padding: 0; }
.gsat__frame { position: relative; aspect-ratio: 16 / 10; border: 1px solid var(--line);
               border-radius: 10px; overflow: hidden; background: var(--bg-sunk); }
@media (max-width: 34rem) { .gsat__frame { aspect-ratio: 4 / 3; } }
.gsat__map { width: 100%; height: 100%; border: 0; display: block; }
.gsat__idle { position: absolute; inset: 0; display: flex; flex-direction: column;
              align-items: flex-start; justify-content: center; gap: 0.5rem;
              padding: clamp(1rem, 3vw, 2rem); }
.gsat__label { margin: 0; font-family: var(--font-display); font-size: 1.15rem; color: var(--ink); }
.gsat__blurb { margin: 0; font-size: 0.85rem; line-height: 1.6; color: var(--ink-soft); max-width: 34rem; }
.gsat__go { margin-top: 0.35rem; cursor: pointer; font: inherit; font-size: 0.8rem;
            font-weight: 600; letter-spacing: 0.02em; color: var(--accent-ink);
            background: var(--accent); border: 0; border-radius: 999px;
            padding: 0.5rem 1.1rem; }
.gsat__go:hover { filter: brightness(1.08); }
.gsat__go:focus-visible, .ge__dl:focus-visible, .geolinks a:focus-visible {
            outline: 2px solid var(--accent); outline-offset: 2px; }
.gsat__note { margin: 0.3rem 0 0; font-size: 0.72rem; line-height: 1.55;
              color: var(--ink-faint); max-width: 40rem; }
.gsat__links { display: flex; flex-wrap: wrap; gap: 0.4rem 1rem; padding: 0.6rem 0.1rem 0;
               font-family: var(--font-data); font-size: 0.72rem; }
.gsat__links a { color: var(--accent); font-weight: 600; }

.geolinks { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 0.45rem;
            font-family: var(--font-data); font-size: 0.68rem; }
.geolinks__label { color: var(--ink-faint); }
.geolinks a { color: var(--accent); font-weight: 600; white-space: nowrap; }
.geolinks a + a::before { content: " b7"; color: var(--ink-faint); margin-right: 0.45rem;
                          font-weight: 400; }

.ge__note { display: block; font-size: 0.74rem; line-height: 1.5; color: var(--ink-faint);
            margin-top: 0.2rem; max-width: 30rem; }
.ge__table td:nth-child(2) { white-space: nowrap; font-family: var(--font-data); font-size: 0.76rem; }
.ge__dl { display: inline-block; white-space: nowrap; font-family: var(--font-data);
          font-size: 0.7rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase;
          color: var(--accent); border: 1px solid var(--line); border-radius: 999px;
          padding: 0.28rem 0.75rem; }
.ge__dl:hover { border-color: var(--accent); }
/* ==[ /google earth and satellite ]== */

/* ==[ contrast ]== -----------------------------------------------------------
   Every value below is computed by _contrast.py against the surface it is
   actually painted on, not chosen by eye. Re-run that script after changing
   any theme colour; it prints the achieved ratio for each pair.

   The pattern being corrected throughout is a light token with an opacity on
   top of it. Opacity is removed and the token itself carries the colour, so
   the contrast is a property of the palette rather than of a filter.        */

/* The apparatus type: source lines, notes, rail group headings. These carried
   opacity 0.6-0.75 and failed at 3.5-4.3:1. */
.stat-note, .rail-group, .ireg__note, .ireg__src, .ge__note, .gsat__note,
.chart-card__sub, .chart-card__source, .stat-card__note, .info-card__source,
.vid-chap__n, .vid-chap__at, .field__hint, .toggle-opt__face,
.rail-item__label, .org-card__name, .org-card__meta,
.stat-note > span:not([class]),
.data-table td > span:not([class]), .prac__b, .itin__f {
    opacity: 1;
}
/* The same muted-apparatus type, given a token that clears AA rather than a
   near-black at 60%. */
.stat-note, .rail-group, .ireg__note, .ireg__src, .ge__note, .gsat__note,
.chart-card__sub, .chart-card__source, .stat-card__note, .info-card__source,
.vid-chap__n, .vid-chap__at, .field__hint, .ireg__chip, .ireg__count, .geolinks__label,
.stat-note > span:not([class]),
.data-table td > span:not([class]) { color: var(--ink-muted); }
/* Rail labels sat at 0.72 and org names at 0.75; the muted reading now comes
   from the token, so an inactive item is still quiet but still legible. */
.rail-item__label { color: var(--ink-muted); }
.rail-item:hover .rail-item__label { color: var(--ink); }
.org-card__name { color: var(--ink); }
/* The meta row faded its children through the parent's own opacity, so the
   spans measured as compliant while rendering at 4.16:1. */
.org-card__meta { color: var(--ink-muted); }
.toggle-opt__face { color: var(--ink); }
/* The checked toggle paints the accent on a 12% accent tint. Same problem as
   the active rail item, so it takes the same solved ink. */
.toggle-opt input:checked + .toggle-opt__face { color: var(--rail-current-ink); }

html[data-theme="laterite"] {
  --ink-muted: #5D4C3C;
  --tier-verified: #1F6B45;
  --tier-verified-ink: #14472E;
  --tier-reported: #8A5B12;
  --tier-reported-ink: #57390B;
  --tier-contested: #A6432A;
  --tier-contested-ink: #6A2B1B;
  --tier-derived: #1C5E7A;
  --tier-derived-ink: #144255;
  --rail-current-ink: #742F1D;
}

@media (prefers-color-scheme: light) {
  html[data-theme="auto"] {
    --ink-muted: #5D4C3C;
    --tier-verified: #1F6B45;
    --tier-verified-ink: #14472E;
    --tier-reported: #8A5B12;
    --tier-reported-ink: #57390B;
    --tier-contested: #A6432A;
    --tier-contested-ink: #6A2B1B;
    --tier-derived: #1C5E7A;
    --tier-derived-ink: #144255;
    --rail-current-ink: #742F1D;
  }
}

html[data-theme="highland"] {
  --ink-muted: #4A5C54;
  --tier-verified: #0F6B4F;
  --tier-verified-ink: #0B503B;
  --tier-reported: #7A5410;
  --tier-reported-ink: #5E410C;
  --tier-contested: #A33F26;
  --tier-contested-ink: #772E1C;
  --tier-derived: #155E7C;
  --tier-derived-ink: #114B63;
  --rail-current-ink: #0C5841;
}

html[data-theme="canopy"] {
  --ink-muted: #9DB2A4;
  --tier-verified: #5BE39B;
  --tier-verified-ink: #5BE39B;
  --tier-reported: #FFC96B;
  --tier-reported-ink: #FFC96B;
  --tier-contested: #E8896A;
  --tier-contested-ink: #EB9A7F;
  --tier-derived: #7FD4F5;
  --tier-derived-ink: #7FD4F5;
  --rail-current-ink: #E18C6A;
}

@media (prefers-color-scheme: dark) {
  html[data-theme="auto"] {
    --ink-muted: #9DB2A4;
    --tier-verified: #5BE39B;
    --tier-verified-ink: #5BE39B;
    --tier-reported: #FFC96B;
    --tier-reported-ink: #FFC96B;
    --tier-contested: #E8896A;
    --tier-contested-ink: #EB9A7F;
    --tier-derived: #7FD4F5;
    --tier-derived-ink: #7FD4F5;
    --rail-current-ink: #E18C6A;
  }
}

html[data-theme="ember"] {
  --ink-muted: #AEB8BF;
  --tier-verified: #5BE39B;
  --tier-verified-ink: #5BE39B;
  --tier-reported: #FFC96B;
  --tier-reported-ink: #FFC96B;
  --tier-contested: #FF9178;
  --tier-contested-ink: #FF9178;
  --tier-derived: #7FD4F5;
  --tier-derived-ink: #7FD4F5;
  --rail-current-ink: #FF9E5E;
}


/* Badges paint their ink token rather than the raw tier hue, and the tint is
   raised slightly so the pill still reads as a pill at the darker ink. */
.tier-badge--verified  { background: rgba(var(--verified-rgb),  0.22); color: var(--tier-verified-ink); }
.tier-badge--reported  { background: rgba(var(--reported-rgb),  0.22); color: var(--tier-reported-ink); }
.tier-badge--derived   { background: rgba(var(--derived-rgb),   0.22); color: var(--tier-derived-ink); }
.tier-badge--contested { background: rgba(var(--contested-rgb), 0.22); color: var(--tier-contested-ink); }
.stat-tier--verified   { color: var(--tier-verified-ink); }
.stat-tier--reported   { color: var(--tier-reported-ink); }
.stat-tier--derived    { color: var(--tier-derived-ink); }
.stat-tier--contested  { color: var(--tier-contested-ink); }
.rail-item.is-current .rail-item__label { color: var(--rail-current-ink); }

/* THE FOOTER BUG. The footer slab is dark in every theme, but it paints with
   --mist and --terracotta, which alias --ink and --accent. On the light themes
   that is near-black text on a near-black slab: 1.09:1, invisible. The footer
   is given its own light-on-dark scale, scoped so nothing else is touched. */
.global-footer {
    --mist: #E8EDE9;
    --terracotta: #F0A184;
}
.global-footer .footer-mission,
.global-footer .footer-copyright,
.global-footer .footer-disclaimer,
.global-footer .footer-link { color: #C9D2CC; opacity: 1; }
.global-footer .footer-logo { color: #F2F6F3; }
.global-footer .footer-col__title { color: #F0A184; }
.global-footer .footer-link:hover { color: #F5B69E; }

/* Focus is visible everywhere, on one ring, including for keyboard users who
   arrive by tab rather than by pointer. */
a:focus-visible, button:focus-visible, select:focus-visible,
input:focus-visible, summary:focus-visible, [tabindex]:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 3px;
}

/* Anyone who has asked their system for less movement gets it. */
@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;
    }
    [data-reveal] { opacity: 1 !important; transform: none !important; }
}
/* ==[ /contrast ]== */
