/* ==========================================================================
   1. GLOBAL DEFAULTS & BASE STYLES
   ========================================================================== */
* { 
    box-sizing: border-box; 
}

body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    background-color: #141414;
    color: #ffffff;
    margin: 0;
    padding: 40px 20px;
    display: flex;
    justify-content: center;
    align-items: flex-start;
    min-height: 100vh;
}

/* Helper Class */
.hidden { 
    display: none !important; 
}

/* ==========================================================================
   2. REUSABLE CORE COMPONENTS (Cards, Badges, Buttons)
   ========================================================================== */
.horizon-card {
    background-color: #252525;
    box-shadow: 0 10px 30px rgba(0,0,0,0.5);
    border-radius: 12px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    height: fit-content;
    width: 100%;
}

/* Map-Specific Card Palette Variance */
#map-container .horizon-card {
    background-color: #ffffff;
}

/* Ad slot — reserves layout space so it doesn't shift once the ad or
   patron-gating check resolves. */
.ad-slot {
    min-height: 250px;
    margin: 15px 0 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
}
.ad-slot-hidden {
    display: none;
}

/* Site-wide ad kill switch. Set to "none" to hide all ads; set back to
   "flex" (or remove this rule) to re-enable them. */
.ad-slot {
    display: none;
}

.filter-panel {
    color: #2525259f !important;
    background-color: white !important; 
}

.card-header {
    background: linear-gradient(to right, #ec008c, #f15a24);
    padding: 14px;
    border-bottom: 4px solid #ffffff;
    display: flex;
    justify-content: space-between;
    align-items: center;
    position: relative;
}

.card-body {
    padding: 20px;
}

/* Accordion behavior for card sections (e.g. Following / Driver Directory) */
.card-header.accordion-toggle {
    cursor: pointer;
}
.section-arrow {
    font-size: 1rem;
    color: #ffffff;
    transition: transform 0.25s ease;
    margin-left: 8px;
    display: inline-block;
}
.accordion-card:not(.is-open) .card-body {
    display: none;
}
.accordion-card:not(.is-open) .section-arrow {
    transform: rotate(-90deg);
}

.horizon-badge {
    background-color: #a6ce39;
    color: #000000;
    font-size: 1.125rem;
    font-weight: 900;
    padding: 2px 10px;
    text-transform: uppercase;
    transform: skewX(-5deg);
    letter-spacing: -0.5px;
    display: inline-block;
}

/* Map Info Badge Variance */
.info-box-badge {
    font-size: 1.5rem;
    letter-spacing: -1px;
}

/* Form Controls */
.form-group { 
    margin-bottom: 15px; 
}
.form-group label {
    display: block;
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    margin-bottom: 6px;
    color: #ddd;
}
.form-group input, 
.form-group textarea,
.search-input {
    width: 100%;
    padding: 12px;
    background-color: #333;
    border: 1px solid #444;
    color: white;
    border-radius: 6px;
    font-size: 0.8125rem;
}
.form-group textarea {
    resize: vertical;
    min-height: 60px;
    max-height: 10rem;
    font-family: inherit;
}
.form-group input:focus, 
.form-group textarea:focus,
.search-input:focus { 
    outline: none; 
    border-color: #ec008c; 
}

/* Buttons */
.btn {
    padding: 12px 24px;
    font-size: 0.8125rem;
    font-weight: bold;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    text-transform: uppercase;
    text-decoration: none;
    display: inline-block;
    text-align: center;
    width: 100%;
}
.btn-primary { 
    background: linear-gradient(to right, #ec008c, #f15a24); 
    color: white; 
}
.btn-secondary { 
    background-color: transparent; 
    color: #ec008c; 
    text-decoration: underline; 
    margin-top: 10px; 
}
.btn-sm {
    padding: 6px 12px;
    font-size: 0.6875rem;
    font-weight: bold;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    text-transform: uppercase;
    margin-top: 8px;
    width: auto;
}

/* ==========================================================================
   3. MODULE SPECIFIC: DRIVER SEARCH MODULE
   ========================================================================== */
.search-container {
    width: 100%;
    max-width: 900px;
    display: flex;
    flex-direction: column;
    gap: 25px;
}
.search-bar {
    display: flex;
    gap: 10px;
    margin-bottom: 10px;
}
.search-bar .search-input {
    flex-grow: 1;
    font-size: 0.875rem;
}
.info-text { 
    font-size: 0.75rem; 
    color: #777; 
    margin-top: -4px; 
    margin-bottom: 15px;
}
.loading-spinner { 
    text-align: center; 
    color: #aaa; 
    padding: 20px; 
    font-size: 0.875rem;
}

/* Follow System Actions */
.btn-follow-action {
    width: 100%;
    margin-bottom: 20px;
    font-size: 0.75rem;
    letter-spacing: 0.5px;
    transition: background 0.2s ease;
}
.btn-follow { background-color: #310f90; color: #eee95a; border: 1px solid #eee95a; }
.btn-follow:hover { background-color: #4216bd; }
.btn-unfollow { background-color: #222; color: #aaa; border: 1px solid #444; }
.btn-unfollow:hover { background-color: #c91818; color: white; border-color: #c91818; }

/* Driver Card Rows */
.drivers-stack {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-top: 10px;
}
.driver-row-card {
    background-color: #1a1a1a;
    border-radius: 8px;
    border-left: 4px solid #310f90;
    cursor: pointer;
    transition: all 0.2s ease-in-out;
    overflow: hidden;
}
.driver-row-card:hover {
    border-left-color: #ec008c;
    background-color: #202020;
}
.driver-row-card.patreon-betatester { border: 4px solid #ac6ad0; }
.driver-row-card.patreon-blue { border: 2px solid #abd9ff; }
.driver-row-card.patreon-pink { border: 4px solid #ec008c; }
.driver-row-card.patreon-owner { border: 4px solid #ffffff; }
.driver-row-card.patreon-gold {
    border: 6px solid #ffd700;
    animation: gold-pulse 2.2s ease-in-out infinite;
}
.driver-row-card.patreon-blue:hover { border-color: #abd9ff; }
.driver-row-card.patreon-pink:hover { border-color: #ec008c; }
.driver-row-card.patreon-gold:hover { border-color: #ffd700; }
.driver-row-card.patreon-owner:hover { border-color: #ffffff; }

/* News feed cards: a very light tint of the post author's patreon colour.
   Uses an inset box-shadow (rather than background-color) so it layers on
   top of the existing background and survives the :hover background change
   above, and stays clipped to the card's border-radius. */
.driver-row-card.patreon-tint-betatester { box-shadow: inset 0 0 0 999px rgba(172, 106, 208, 0.07); }
.driver-row-card.patreon-tint-blue { box-shadow: inset 0 0 0 999px rgba(171, 217, 255, 0.07); }
.driver-row-card.patreon-tint-pink { box-shadow: inset 0 0 0 999px rgba(236, 0, 140, 0.07); }
.driver-row-card.patreon-tint-gold { box-shadow: inset 0 0 0 999px rgba(255, 215, 0, 0.07); }
.driver-row-card.patreon-tint-owner { box-shadow: inset 0 0 0 999px rgba(255, 255, 255, 0.06); }

@keyframes gold-pulse {
    0%, 100% { box-shadow: 0 0 6px 0px rgba(255, 215, 0, 0.4); }
    50%      { box-shadow: 0 0 18px 4px rgba(255, 215, 0, 0.8); }
}
@media (prefers-reduced-motion: reduce) {
    .driver-row-card.patreon-gold { animation: none; }
}
.driver-summary {
    padding: 16px 20px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    user-select: none;
}
.driver-tag { font-weight: bold; font-size: 1rem; color: #ffffff; }
.patreon-badge { font-size: 0.6875rem; font-weight: normal; margin-left: 8px; }
.patreon-badge-betatester { color: #ac6ad0; }
.patreon-badge-blue { color: #abd9ff; }
.patreon-badge-pink { color: #ec008c; }
.patreon-badge-gold { color: #ffd700; }
.patreon-badge-owner { animation: owner-text-pulse 2.2s ease-in-out infinite; }

@keyframes owner-text-pulse {
    0%, 100% { color: #ffffff; }
    50%      { color: #ffd700; }
}
@media (prefers-reduced-motion: reduce) {
    .patreon-badge-owner { animation: none; color: #ffd700; }
}

/* Steering-wheel icon shown next to usernames on pages that don't already
   render a full text badge (see driversearch.js/.patreon-badge above). Reuses
   the same .patreon-badge-* colour classes via currentColor. */
.patreon-wheel-icon { display: inline-flex; margin-left: 4px; vertical-align: middle; cursor: default; }
.patreon-wheel-icon svg { width: 16.8px; height: 16.8px; display: block; transform: rotate(180deg); }

/* Shared hover pop-up for .patreon-wheel-icon (see core.js), appended to
   <body> and positioned with fixed coordinates so it isn't clipped by any
   overflow:hidden card it happens to hover over. */
.patreon-wheel-tooltip {
    display: none;
    position: fixed;
    transform: translate(-50%, -100%);
    background: #111;
    color: #fff;
    padding: 4px 8px;
    border-radius: 4px;
    font-size: 0.6875rem;
    white-space: nowrap;
    pointer-events: none;
    z-index: 3000;
    border: 1px solid rgba(255, 255, 255, 0.15);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
}

.driver-stats { display: flex; align-items: center; gap: 15px; }
.driver-follow-stat { font-size: 0.8125rem; color: #aaa; }
.driver-follow-stat b { color: #fff; }

/* Dynamic Hue Level Indicator */
.driver-level {
    --level-hue: 0; 
    display: inline-block;
    min-width: 65px;
    padding: 4px 8px;
    text-align: center;
    font-family: 'Arial Black', sans-serif;
    font-size: 1rem;
    font-weight: 900;
    color: #111111;
    background: linear-gradient(
        to right, 
        hsl(var(--level-hue), 70%, 50%) 0%, 
        hsl(var(--level-hue), 0%, 85%) 50%, 
        hsl(var(--level-hue), 70%, 50%) 100%
    );
    border: 1px solid hsl(var(--level-hue), 20%, 50%);
    box-shadow: 
        inset 0 1px 0 rgba(255, 255, 255, 0.8), 
        0 1px 2px rgba(0, 0, 0, 0.4);
}

/* Expanded Card Sections */
.driver-expanded-content {
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.4s cubic-bezier(0, 1, 0, 1);
    background-color: #222222;
    border-top: 1px solid #333;
}
.driver-row-card.is-open .driver-expanded-content {
    max-height: 2000px;
    transition: max-height 0.6s ease-in-out;
}
.expanded-inner { padding: 20px; }
.section-label {
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    color: #aaa;
    letter-spacing: 1px;
    margin-bottom: 12px;
    border-bottom: 1px solid #333;
    padding-bottom: 4px;
}
.social-link-btn { width: 100%; margin-top: 5px; }
.instagram-embed-wrapper {
    margin-top: 12px;
    border-radius: 8px;
    overflow: hidden;
    background-color: #000;
}
.instagram-embed-frame {
    width: 100%;
    height: 580px;
    border: none;
    display: block;
}

@media (max-width: 480px) {
    .instagram-embed-frame {
        height: 350px;
    }
}

.carousel-btn {
    position: absolute; top: 50%; transform: translateY(-50%); background: rgba(0, 0, 0, 0.6);
    color: #fff; border: none; font-size: 0.625rem; padding: 4px 6px; cursor: pointer; user-select: none; z-index: 2;
}

/* Journey Grid Reel */
.public-journey-reel {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
    margin-bottom: 10px;
}
@media (max-width: 600px) {
    .public-journey-reel { grid-template-columns: 1fr; }
}

/* News Feed Post Photos */
.feed-photo-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
    margin-top: 10px;
    width: 100%;
}
.feed-photo-grid img {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    border-radius: 6px;
}
@media (max-width: 480px) {
    .feed-photo-grid { grid-template-columns: repeat(2, 1fr); }
}

/* News Feed Upvote Button */
.feed-upvote-btn {
    padding: 10px 16px;
    font-size: 0.9375rem;
    font-weight: bold;
    border-radius: 6px;
    cursor: pointer;
    transition: background 0.2s ease, border-color 0.2s ease;
}

/* News Feed Comment Form */
.feed-comment-form {
    display: flex;
    gap: 8px;
}
@media (max-width: 480px) {
    .feed-comment-form {
        flex-direction: column;
    }
    .feed-comment-form button {
        width: 100%;
    }
}
.public-reel-photo {
    position: relative;
    aspect-ratio: 16 / 9;
    background: #111;
    border-radius: 4px;
    overflow: hidden;
}
.public-reel-photo img { width: 100%; height: 100%; object-fit: cover; }
.public-photo-caption {
    position: absolute; bottom: 0; left: 0; right: 0;
    background: linear-gradient(transparent, rgba(0,0,0,0.9));
    font-size: 0.625rem; color: #a6ce39; font-weight: 800; padding: 6px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Responsive Overrides for Driver Cards */
@media (max-width: 650px) {
    .driver-summary {
        flex-direction: column;
        align-items: flex-start;
        gap: 10px;
    }
    .driver-stats {
        width: 100%;
        justify-content: space-between;
        gap: 8px;
    }
    .driver-follow-stat {
        font-size: 0.75rem;
    }
}



/* ==========================================================================
   4. MODULE SPECIFIC: DRIVER DASHBOARD & PROFILE MODULE
   ========================================================================== */
.dashboard-container {
    width: 100%;
    max-width: 1200px;
    display: grid;
    grid-template-columns: 1fr;
    gap: 25px;
}
@media (min-width: 1024px) {
    .dashboard-container { grid-template-columns: 350px 1fr; }
    .garage-card-panel { grid-column: 1 / span 2; }
}
.welcome-text { font-size: 0.75rem; color: #aaa; margin-bottom: 15px; word-break: break-all; }
.xp-pill {
    display: inline-block; background-color: #310f90; color: #eee95a;
    padding: 4px 12px; border-radius: 20px; font-weight: bold; font-size: 0.8125rem; margin-bottom: 20px;
}
.accordion-header {
    background-color: #1a1a1a; border: 1px solid #333; padding: 12px 15px; border-radius: 6px;
    cursor: pointer; font-weight: bold; font-size: 0.875rem; color: #ffffff; display: flex;
    justify-content: space-between; align-items: center; user-select: none;
    transition: background-color 0.2s ease; margin: 0 auto 15px auto; max-width: 600px;
}
.accordion-header:hover { background-color: #222; }
.accordion-content { max-height: 0; overflow: hidden; transition: max-height 0.3s cubic-bezier(0, 1, 0, 1); max-width: 600px; margin: 0 auto; }
.accordion-content.open { max-height: 1000px; transition: max-height 0.5s ease-in-out; }

.car-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 20px; margin-top: 20px; }

.reorder-active .vcard { cursor: grab; position: relative; }
.reorder-active .vcard:active { cursor: grabbing; }
.reorder-active .vcard::after {
    content: '☰ Drag to Reorder'; position: absolute; top: 8px; left: 8px;
    background: rgba(0,0,0,0.75); color: #ffffff; font-size: 0.6875rem; font-weight: bold; padding: 4px 8px; border-radius: 4px; pointer-events: none; z-index: 10;
}
.vcard.dragging { opacity: 0.4; transform: scale(0.98); }

/* Vehicle card — full-photo hero design (shared by owner garage grid + public garage view) */
.vcard-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 20px; margin-bottom: 20px; }
.vcard {
    --glow: #ec008c;
    position: relative;
    border-radius: 14px;
    cursor: pointer;
}
.vcard-inner {
    position: relative;
    border-radius: 13px;
    border: 1px solid #232A35;
    overflow: hidden;
    background: #0D1016;
    transition: transform 0.12s ease-out, border-color 0.25s;
    box-shadow: 0 20px 40px -20px rgba(0,0,0,0.6);
    height: 100%;
    display: flex;
    flex-direction: column;
}
/* Stable hover lift (not mouse-tracked): settles before a click lands, so it can't
   shift the img/button between mousedown and mouseup and swallow the click. */
.vcard:hover .vcard-inner { border-color: var(--glow); transform: scale(1.015); }
.vcard-photo-wrap {
    position: relative;
    height: 210px;
    overflow: hidden;
    background: #0B0E13;
    flex-shrink: 0;
}
.vcard-photo-wrap img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.vcard-vignette {
    position: absolute;
    inset: 0;
    background:
        radial-gradient(ellipse 120% 90% at 50% 40%, transparent 40%, rgba(6,8,11,0.55) 100%),
        linear-gradient(180deg, rgba(6,8,11,0.15) 0%, transparent 30%, rgba(6,8,11,0.75) 100%);
    pointer-events: none;
}
.vcard-ring {
    position: absolute;
    inset: -1px;
    box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--glow) 55%, transparent);
    opacity: 0;
    transition: opacity 0.25s;
    pointer-events: none;
}
.vcard:hover .vcard-ring { opacity: 1; }
.vcard-glare {
    position: absolute;
    inset: 0;
    background: radial-gradient(circle 160px at var(--gx,50%) var(--gy,30%), rgba(255,255,255,0.16), transparent 60%);
    pointer-events: none;
    mix-blend-mode: overlay;
}
.vcard-details {
    padding: 13px 16px 16px;
    border-top: 1px solid #1B212B;
    flex-grow: 1;
    display: flex;
    flex-direction: column;
}
.vcard-title {
    color: #F5F6F8;
    font-size: 1rem;
    font-weight: 600;
    margin: 0 0 6px;
    letter-spacing: 0.01em;
}
.vcard-desc {
    color: #8A94A3;
    font-size: 0.8125rem;
    line-height: 1.5;
    margin: 0;
}

.edit-input, .edit-textarea { width: 100%; padding: 8px; margin-bottom: 8px; background-color: #2b2b2b; border: 1px solid #ec008c; color: white; border-radius: 4px; font-size: 0.8125rem; }
.edit-textarea { resize: vertical; max-height: 10rem; font-family: inherit; }
/* Ensure the container allows absolute positioning for the button */

.edit-photo-manager {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 5px;
}

.edit-photo-thumb {
    position: relative;
    width: 60px;
    height: 60px;
    border-radius: 4px;
    overflow: visible; /* Allows the X button to slightly pop out */
}

.edit-photo-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 4px;
}

/* Make the delete overlay look like a physical clickable close button */
.photo-delete-overlay {
    position: absolute;
    top: -5px;
    right: -5px;
    background: #ff4d4d;
    color: white;
    border: none;
    border-radius: 50%;
    width: 18px;
    height: 18px;
    font-size: 0.75rem;
    line-height: 16px;
    text-align: center;
    cursor: pointer;
    font-weight: bold;
    box-shadow: 0 2px 4px rgba(0,0,0,0.3);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10;
}

.photo-delete-overlay:hover {
    background: #ff1a1a;
    transform: scale(1.1);
}
.carousel-container { position: relative; width: 100%; background-color: #1a1a1a; border-radius: 8px; overflow: hidden; aspect-ratio: 16 / 9; }
.carousel-track { display: flex; width: 100%; height: 100%; transition: transform 0.4s ease-out; }
.carousel-slide { min-width: 100%; height: 100%; position: relative; }
.carousel-slide img { width: 100%; height: 100%; object-fit: cover; }
.slide-caption { position: absolute; bottom: 0; left: 0; right: 0; background: linear-gradient(transparent, rgba(0,0,0,0.85)); padding: 15px; color: #fff; }
.slide-location { font-weight: 800; font-size: 0.875rem; margin-bottom: 2px; color: #a6ce39; }
.btn-left { left: 10px; }
.btn-right { right: 10px; }
.no-data { text-align: center; color: #666; font-size: 0.8125rem; padding: 30px; }

/* ==========================================================================
   5. MODULE SPECIFIC: MAP & INTERACTIVE PLOTTER MODULE
   ========================================================================== */
/* Main Map Element Canvas */
#map {
    height: 80vh;
    width: 100%;
    /* Dark ground under the MapLibre basemap (js/pages/map.js addBasemap), so
       the moment before the style loads — and a device with no WebGL, which
       gets no basemap at all — reads as the dark map rather than Leaflet's
       default #ddd. The id outranks leaflet.css's .leaflet-container. */
    background: #141414;
    box-shadow: 0 4px 15px rgba(0,0,0,0.1);
    cursor: url('https://images.squarespace-cdn.com/content/5f0800ad122ca1020e15689c/14806726-9b93-4832-9f12-2098dc9484dc/Cursor.png?content-type=image%2Fpng') 64 64, auto;
}

[id^="photo-preview-"] img {
    max-width: 100%;
    height: auto;
    border: 2px solid #ffffff;
}

/* Opening loader over the map (js/pages/map.js, beginMapLoading). Covers the
   map AND #map-controls-panel (z 1000) and the search results (1001), so a
   half-drawn map is not usable by accident before the user chooses "Open
   Anyway". Sits below the mobile bottom sheet and the floating widgets.
   .is-done fades it and drops pointer events at once; JS then adds .hidden. */
.map-loading {
    position: absolute;
    inset: 0;
    z-index: 1100;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    background: #141414;
    opacity: 1;
    transition: opacity 0.4s ease;
}
.map-loading.is-done {
    opacity: 0;
    pointer-events: none;
}
.map-loading-card {
    width: 100%;
    max-width: 360px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    text-align: center;
}
.map-loading-title {
    font-size: 1rem;
    font-weight: bold;
    color: #fff;
    letter-spacing: 0.5px;
}
.map-loading-status {
    font-size: 0.75rem;
    color: #aaa;
    min-height: 2.4em;
}
.map-loading-skip {
    align-self: center;
    margin-top: 0;
}
@media (prefers-reduced-motion: reduce) {
    .map-loading { transition: none; }
}

#map-controls-panel {
    position: absolute;
    top: 94px;
    right: 10px;
    z-index: 1000;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 8px;
}

.filter-panel {
    padding: 8px;
    border-radius: 4px;
}

/* Map Filter Dropdown (replaces old Map Mode select) */
.map-filter-panel {
    position: relative;
    padding: 0;
}

.map-filter-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    width: auto;
    height: 30px;
    padding: 8px;
    font-weight: bold;
    font-size: 0.75rem;
    background-color: white;
    color: #2525259f;
    border: none;
    border-radius: 4px;
    box-shadow: 0 1px 5px rgba(0,0,0,0.65);
    cursor: pointer;
}
.map-filter-toggle:hover { background-color: #f4f4f4; }
.map-filter-arrow {
    font-size: 0.6rem;
    transition: transform 0.15s ease;
}
.map-filter-toggle[aria-expanded="true"] .map-filter-arrow {
    transform: rotate(180deg);
}

.map-filter-dropdown {
    display: none;
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    min-width: 190px;
    background-color: white;
    border-radius: 4px;
    box-shadow: 0 1px 5px rgba(0,0,0,0.65);
    padding: 8px;
    z-index: 1001;
}
.map-filter-dropdown.is-open { display: block; }

.map-filter-bulk-actions {
    display: flex;
    justify-content: space-between;
    gap: 8px;
    padding-bottom: 6px;
    margin-bottom: 6px;
    border-bottom: 1px solid #eee;
}
.map-filter-bulk-btn {
    background: none;
    border: none;
    padding: 0;
    font-size: 0.6875rem;
    font-weight: bold;
    color: #2525259f;
    text-decoration: underline;
    cursor: pointer;
}
.map-filter-bulk-btn:hover { color: #252525; }

.map-filter-options {
    display: flex;
    flex-direction: column;
    gap: 4px;
    max-height: 260px;
    overflow-y: auto;
}
.map-filter-option {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.75rem;
    color: #252525;
    cursor: pointer;
    padding: 2px 0;
}
.map-filter-option input[type="checkbox"] {
    cursor: pointer;
}

/* Map Search Box
   Styled in the white Leaflet-control idiom of .map-filter-toggle /
   .map-filter-dropdown next to it, NOT the site's dark .search-input (§2) —
   that one is #333 on a page body and would read as a foreign object dropped
   into the map's control stack. Same 30px height, 0.75rem bold, 4px radius and
   shadow as its two neighbours. */
.map-search-panel {
    position: relative;
}
.map-search-input {
    width: 200px;
    height: 30px;
    /* Right padding clears the × button. */
    padding: 8px 26px 8px 8px;
    box-sizing: border-box;
    font-size: 0.75rem;
    font-weight: bold;
    background-color: white;
    color: #252525;
    border: none;
    border-radius: 4px;
    box-shadow: 0 1px 5px rgba(0,0,0,0.65);
}
.map-search-input::placeholder {
    color: #2525259f;
    font-weight: normal;
}
.map-search-clear {
    position: absolute;
    top: 0;
    right: 0;
    width: 24px;
    height: 30px;
    padding: 0;
    background: none;
    border: none;
    font-size: 1rem;
    font-weight: bold;
    line-height: 30px;
    color: #2525259f;
    cursor: pointer;
}
.map-search-clear:hover { color: #252525; }

.map-search-results {
    display: none;
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    min-width: 240px;
    max-height: 300px;
    overflow-y: auto;
    background-color: white;
    border-radius: 4px;
    box-shadow: 0 1px 5px rgba(0,0,0,0.65);
    padding: 4px;
    /* Matches .map-filter-dropdown — above the 1000 on #map-controls-panel. */
    z-index: 1001;
}
.map-search-results.is-open { display: block; }

.map-search-group {
    font-size: 0.625rem;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: #2525259f;
    padding: 6px 8px 4px;
    border-bottom: 1px solid #eee;
    margin-bottom: 2px;
}
.map-search-group:not(:first-child) { margin-top: 6px; }

.map-search-result {
    display: block;
    width: 100%;
    text-align: left;
    padding: 6px 8px;
    background: none;
    border: none;
    border-radius: 3px;
    cursor: pointer;
}
.map-search-result:hover,
.map-search-result.is-active { background-color: #f4f4f4; }
.map-search-name {
    display: block;
    font-size: 0.75rem;
    font-weight: bold;
    color: #252525;
}
.map-search-sub {
    display: block;
    font-size: 0.6875rem;
    color: #2525259f;
}
.map-search-empty {
    padding: 8px;
    font-size: 0.75rem;
    color: #2525259f;
}

/* "Show My Location" Button */
.locate-control-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: auto;
    height: 30px;
    padding: 8px;
    font-weight: bold;
    font-size: 0.75rem;
    background-color: white !important;
    color: #2525259f !important; 
    text-decoration: underline;
    border-radius: 4px;
    box-shadow: 0 1px 5px rgba(0,0,0,0.65);
    cursor: pointer;
}
.locate-control-btn:hover { background-color: #f4f4f4; }
.locate-control-btn[aria-disabled="true"] {
    opacity: 0.5;
    pointer-events: none;
}

/* "You Are Here" Marker — 40% smaller than the previous 6x size (net scale
   0.6x); iconSize/iconAnchor in js/pages/map.js are kept in sync with this.
   The white ring (border) is capped at 6px — half its old 12px — rather than
   shrinking proportionally with the rest. */
.user-location-dot-icon { position: relative; width: 72px; height: 72px; }
.user-location-dot {
    position: absolute;
    top: 18px; left: 18px;
    width: 36px; height: 36px;
    border-radius: 50%;
    background: linear-gradient(135deg, #ec008c, #f15a24);
    border: 6px solid #fff;
    box-shadow: 0 3.6px 14.4px rgba(0,0,0,0.4);
    z-index: 2;
}
.user-location-pulse {
    position: absolute;
    top: 0; left: 0;
    width: 72px; height: 72px;
    border-radius: 50%;
    background: rgba(236, 0, 140, 0.35);
    animation: userLocationPulse 2s ease-out infinite;
    z-index: 1;
}
@keyframes userLocationPulse {
    0%   { transform: scale(0.4); opacity: 0.8; }
    100% { transform: scale(1.8); opacity: 0; }
}

/* Auth Hub Overlay Positioned Inside Map Container */
.auth-card {
    position: absolute;
    top: 20px;
    right: 20px;
    z-index: 1000; 
    width: 300px;
    box-shadow: 0 4px 15px rgba(0,0,0,0.3);
    background-color: #2525259f !important;
    color: white !important; 
}
.auth-user-badge {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.8125rem;
    font-weight: 700;
    color: white !important;
}
.logout-link {
    color: #ec008c;
    cursor: pointer;
    font-size: 0.6875rem;
    text-decoration: underline;
}

/* Customizing the Leaflet "Details" Popup Framework */
.custom-popup .leaflet-popup-content-wrapper {
    padding: 0;
    border-radius: 12px;
    width: 350px !important; 
}
.leaflet-popup-content { line-height: 1; }
.custom-popup .leaflet-popup-content_wrapper { border: none; }
.leaflet-popup-content-wrapper, .leaflet-popup-tip {
    background: none;
    color: #333;
    box-shadow: none;
}
.leaflet-container a.leaflet-popup-close-button {
    top: 25px;
    right: 10px;
}

/* Info Box Typography Elements (White Card Background Overrides) */
.info-box .horizon-card {
    width: 100%;
    background-color: #ffffff;
    box-shadow: 0 10px 30px rgba(0,0,0,0.5);
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
.info-box .card-body { padding: 16px; color: #000000; }
.info-box h3 { margin: 0 0 10px 0; font-size: 1.2rem; color: #333; }
.info-box h2 { margin: 0 0 10px 0; }
.info-box p { font-size: 0.95rem; color: #666; margin-bottom: 15px; line-height: 1.4; }
.info-box img { width: 100%; }

/* Google Maps Route Direction Button */
.info-box .directions-btn {
    display: inline-block;
    width: 100%;
    text-align: center;
    background-color: #4285F4;
    color: #ffffff !important;
    padding: 10px 0;
    font-size: 0.9rem;
    font-weight: 600;
    text-decoration: none;
    box-sizing: border-box;
    transition: background-color 0.2s ease;
}
.info-box .directions-btn:hover { background-color: #357ae8; }

/* Interactive Map Markers Styling */
.leaflet-marker-icon {
    transition: width 0.3s ease, height 0.3s ease, margin-left 0.3s ease, margin-top 0.3s ease;
    filter: drop-shadow(2px 4px 6px rgba(0,0,0,0.3));
}
.leaflet-interactive:hover .leaflet-popup-icon { transform: scale(1.2); }

/* Cluster marker icon (combined markers when zoomed out) */
.custom-cluster-icon { cursor: pointer; }
.custom-cluster-icon .cluster-icon-inner { position: relative; width: 100%; height: 100%; }
.custom-cluster-icon .cluster-icon-img { width: 100%; height: 100%; object-fit: contain; display: block; }
.custom-cluster-icon .cluster-count-badge {
    position: absolute;
    bottom: -0.5rem;
    right: -0.5rem;
    min-width: 1.25rem;
    height: 1.25rem;
    padding: 0 0.3125rem;
    border-radius: 0.625rem;
    background: #ec008c;
    color: #fff;
    font-size: 0.6875rem;
    font-weight: bold;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 0.0625rem 0.1875rem rgba(0,0,0,0.4);
    border: 0.125rem solid #fff;
    box-sizing: border-box;
}

/* Location marker icon (visited-state badge) */
.custom-location-icon { cursor: pointer; }
.custom-location-icon .location-icon-inner { position: relative; width: 100%; height: 100%; }
.custom-location-icon .location-icon-img { width: 100%; height: 100%; object-fit: contain; display: block; }
.custom-location-icon .location-icon-img.location-icon-visited { filter: saturate(20%); }
.custom-location-icon .location-visited-badge {
    position: absolute;
    bottom: -0.25rem;
    right: -0.25rem;
    width: 1.25rem;
    height: 1.25rem;
    border-radius: 50%;
    background: #2e7d32;
    color: #fff;
    font-size: 0.75rem;
    font-weight: bold;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 0.0625rem 0.1875rem rgba(0,0,0,0.4);
    border: 0.125rem solid #fff;
    box-sizing: border-box;
}

/* --- Bonus board collectibles ---------------------------------------------
   Sized by the L.divIcon in buildBonusBoardMarker (js/pages/map.js). Its base
   and hover sizes are deliberately equal, so there is no grow-on-open rule
   here to match — the shared .leaflet-marker-icon transition and drop-shadow
   above already apply. */

/* Cluster of boards, zoomed out. Layout comes from .custom-cluster-icon above;
   only the badge needs scaling, because a board pin is 44px where a venue pin
   is 100px and the shared badge would cover most of it.

   No .is-taken / .is-mine variant exists on purpose — see
   buildBonusBoardClusterIcon for why a state-tinted cluster would go stale. */
.bonus-board-cluster-icon .cluster-count-badge {
    bottom: -0.25rem;
    right: -0.25rem;
    min-width: 1rem;
    height: 1rem;
    padding: 0 0.25rem;
    border-radius: 0.5rem;
    font-size: 0.5625rem;
    border-width: 0.09375rem;
}
/* Sampled views put a "+" here instead of a count (see
   buildBonusBoardClusterIcon). It is DRAWN as two bars rather than set as text,
   because as text it sits off-centre in the bubble, and by an amount nothing
   here controls — it depends on which font the device happens to resolve:

     * Vertically. `align-items: center` centres the line box, not the ink, so
       where the plus lands depends on that font's glyph metrics. Measured at
       this badge's 9px: Liberation/Arial put it 0.5px HIGH, DejaVu 0.5px LOW —
       ~3% of a 16px badge, in opposite directions. The gap widens with size
       (1px and 5.5px respectively at 100px), so it is a metric difference, not
       a rounding artefact.
     * Horizontally. The advance width swings from 5.26px (Arial) to 7.54px
       (DejaVu) for the same 9px "+". The content box here is only ~5px, so a
       wide glyph grows the badge past its 16px min-width and the "circle"
       renders as an oval.
     * And at 9px a single thin "+" is a faint speck either way. Digits carry
       that size because there are two or three of them.

   Two absolutely positioned bars sidestep all of it: they centre on the badge's
   padding box, which is the true centre of the circle since the border is
   uniform, and font-size: 0 means no glyph advance, so the bubble is always
   exactly 16x16. Verified at 0.00px offset on both axes. The "+" text node
   stays in the DOM for assistive tech. */
.bonus-board-cluster-icon .cluster-count-badge.is-plus {
    font-size: 0;
}
.bonus-board-cluster-icon .cluster-count-badge.is-plus::before,
.bonus-board-cluster-icon .cluster-count-badge.is-plus::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: currentColor;
    border-radius: 0.03125rem;
}
.bonus-board-cluster-icon .cluster-count-badge.is-plus::before {
    width: 0.4375rem;
    height: 0.09375rem;
}
.bonus-board-cluster-icon .cluster-count-badge.is-plus::after {
    width: 0.09375rem;
    height: 0.4375rem;
}
/* The pin is now the <img> itself (L.icon), not a div wrapping one.
   Leaflet sets width/height inline from iconSize.

   filter: none is the point of this rule. The shared .leaflet-marker-icon above
   puts a drop-shadow on EVERY marker, and drop-shadow is a gaussian blur: it
   forces each pin onto its own rasterized layer and re-composites it on every
   pan and zoom frame. Harmless for a few dozen venues, the dominant cost for
   hundreds of boards once they stop clustering — and it scales with pin area,
   so a larger pin image makes it worse. Bake the shadow into the PNG instead.

   The inherited motion transition is deliberately LEFT ALONE. Only the blur is
   the expensive part; a transition on width/height costs almost nothing next to
   it, and boards should move like every other marker on the map. */
.leaflet-marker-icon.bonus-board-icon,
.leaflet-marker-icon.bonus-board-cluster-icon {
    filter: none;
    object-fit: contain;
    display: block;
}

/* Held by somebody else right now: tinted grey, at FULL opacity. A faded pin
   reads as "loading" or "disabled" and is easy to miss against the map; a solid
   grey one still says plainly that it is out of play, and stays visible enough
   to be worth noting for when it frees up. */
.leaflet-marker-icon.bonus-board-icon.is-taken {
    filter: grayscale(100%);
}

/* Held by you — on cooldown, or waiting for another driver to take a turn.
   Gold, because "I got this one" deserves to look like a prize rather than a
   disabled control.

   Tinting a full-colour image gold takes the long way round, and every step
   feeds the next, so do not reorder or drop one:

     grayscale(100%)   flatten the pin's own colours to a neutral ramp
     sepia(100%)       map that ramp onto a warm brown, hue ~39°, low chroma
     brightness(0.4)   pull it DOWN first — the non-obvious one. This creates
                       the headroom that lets the next step multiply chroma
                       hard without any channel reaching 1.0, and it is
                       clipping that wrecks a tint: clipped channels drag the
                       hue toward pure yellow, and unevenly, so the pin ends
                       up two different colours light-to-dark.
     saturate(390%)    now push the chroma up, with room to do it
     hue-rotate(13deg) carry that ~39° the rest of the way to gold's 50.6°
     brightness(1.9)   undo the earlier dip

   Measured against #FFD700 this holds hue 50.2°-50.6° at 95-100% saturation
   across the whole tonal range, clipping only in the brightest highlights —
   which is what metal is supposed to do. The pin's own shading survives, which
   is the point of tinting rather than masking a flat silhouette.

   To tune brightness, change the LAST brightness() on its own. Touching
   saturate() or hue-rotate() by itself will pull the hue off gold. */
.leaflet-marker-icon.bonus-board-icon.is-mine {
    filter: grayscale(100%) sepia(100%) brightness(0.4) saturate(390%) hue-rotate(13deg) brightness(1.9);
}

/* Everything below is scoped to .info-box, and has to be. The popup card is
   WHITE (.info-box .horizon-card), not the site's dark card, and two rules in
   that block outrank an unscoped .bonus-board-* class:

     .info-box p  (0,1,1)  beats  .bonus-board-xp  (0,1,0)
       — which is why the XP line was grey with a 15px margin under it, and
         why the status lines carried the same gap.

   Leaflet's own .leaflet-container a (0,1,1) likewise beats .btn-primary
   (0,1,0) and painted the supporter link #0078A8 on the gradient. The existing
   .directions-btn solves that with an !important colour; these follow suit
   rather than inventing a second approach. */

/* Filled on popupopen by renderBonusBoardSlot(); empty in the bound popup
   markup. Needs no styling of its own — listed so the hook is greppable. */
.bonus-board-slot { }

.info-box .bonus-board-xp {
    color: #f15a24;
    font-size: 1.25rem;
    font-weight: 800;
    /* No bottom margin: the slot below supplies its own spacing, and .info-box p
       was adding 15px on top of the card's 16px padding. */
    margin: 4px 0 0 0;
}

.info-box .bonus-board-collect-btn {
    background: linear-gradient(to right, #ec008c, #f15a24);
    color: #ffffff !important;
    width: 100%;
    border: none;
    padding: 10px;
    cursor: pointer;
    font: inherit;
    font-weight: 600;
}
.info-box .bonus-board-collect-btn:disabled {
    opacity: 0.6;
    cursor: default;
}

/* Dark on white. The unscoped version of this was #bdbdbd, i.e. invisible. */
.info-box .bonus-board-status {
    color: #555555;
    font-size: 0.8125rem;
    line-height: 1.35;
    text-align: center;
    margin: 0;
    padding: 10px 14px;
}

/* The supporter pitch, for signed-out and non-patron viewers. Padding sits here
   rather than on the children so the block collapses to one tidy stack instead
   of the pile of stacked <p> margins it was. */
.info-box .bonus-board-locked {
    padding: 12px 14px 14px;
    text-align: center;
}
.info-box .bonus-board-locked-title {
    color: #1a1a1a;
    font-size: 0.9375rem;
    font-weight: 700;
    margin: 0 0 4px 0;
}
.info-box .bonus-board-locked p {
    color: #555555;
    font-size: 0.8125rem;
    line-height: 1.35;
    margin: 0 0 10px 0;
}
/* Matches .btn/.btn-primary elsewhere on the site; only the colour needs
   forcing, to get out from under Leaflet's link rule. */
.info-box .bonus-board-locked .btn {
    color: #ffffff !important;
    text-decoration: none;
    width: 100%;
}

.festival-text { color: #ffffff; font-size: 0.6875rem; font-weight: bold; letter-spacing: 5px; margin-top: 4px; padding-left: 4px; }
.yellow-ring { width: 36px; height: 20px; }
.title-row { display: flex; justify-content: space-between; align-items: flex-start; }
.circuit-title { font-size: 1.75rem; font-weight: 800; letter-spacing: -0.5px; max-width: 80%; }
.race-type { font-size: 1.125rem; font-weight: 800; margin-top: 2px; }
.description { font-size: 0.9375rem; font-weight: 500; line-height: 1.3; color: #1a1a1a; margin-top: 6px; }
@media (min-width: 769px) {
    .event-description {
        max-height: calc(1.3em * 7);
        overflow-y: auto;
        padding-right: 6px;
    }
}

/* Map Card Restrictions Segment */
.restriction-section { margin-top: 14px; }
.restriction-label { background-color: #000000; color: #ffffff; font-size: 0.9375rem; font-weight: 900; padding: 3px 8px; display: inline-block; text-transform: uppercase; }
.restriction-details { background-color: #eceff1; display: flex; align-items: center; padding: 8px; margin-top: 4px; }
.restriction-text { font-size: 1rem; font-weight: 800; margin-left: 10px; }

/* "Your Journey" Checkpoint Sections */
.notes-section { background: linear-gradient(to right, #ec008c, #f15a24); }
.journey-toggle {
    display: flex; justify-content: space-between; align-items: center;
    cursor: pointer; user-select: none; padding: 0; background: none;
    border: none; width: 100%; text-align: left;
}
.journey-toggle .notes-label {
    background-color: transparent; color: #ffffff; font-size: 0.9375rem;
    font-weight: 900; padding: 3px 8px; display: inline-block; text-transform: uppercase;
}
.journey-toggle .journey-arrow { font-size: 0.8125rem; color: white; transition: transform 0.25s ease; margin-left: 8px; display: inline-block; }
.journey-toggle.is-open .journey-arrow { transform: rotate(180deg); }

.journey-body { display: none; margin-top: 10px; color: white; }
.journey-body.is-open { display: block; }
.journey-body img { max-height: 150px; width: auto; }

/* ── Mobile Bottom Sheet (Google Maps Style Layout) ── */
#mobile-bottom-sheet {
    display: none;
    position: fixed; bottom: 0; left: 0; right: 0; z-index: 9999;
    max-height: 85vh; overflow-y: auto; background: #fff;
    border-radius: 20px 20px 0 0; box-shadow: 0 -4px 24px rgba(0,0,0,0.25);
    transform: translateY(100%); transition: transform 0.35s cubic-bezier(0.32, 0.72, 0, 1);
    -webkit-overflow-scrolling: touch;
}
#mobile-bottom-sheet.is-open { transform: translateY(0); }
#mobile-bottom-sheet::before { content: ''; display: block; width: 40px; height: 4px; background: #ccc; border-radius: 2px; margin: 10px auto 4px; }
#mobile-sheet-close { position: sticky; top: 0; float: right; margin: 0 12px 0 0; background: none; border: none; font-size: 1.375rem; line-height: 1; cursor: pointer; color: #555; z-index: 1; padding: 4px 6px; }

#mobile-sheet-overlay { display: none; position: fixed; inset: 0; z-index: 9998; background: rgba(0,0,0,0.35); }
#mobile-sheet-overlay.is-open { display: block; }

/* Mobile Map Responsiveness Overrides */
@media (max-width: 768px) {
    .leaflet-popup {
        display: none !important; /* Forces Leaflet pins to use our bottom drawer on smaller screens */
    }

    #map-controls-panel {
    top: 84px;
}

    body.logged-out #map-controls-panel {
    top: 209px;
}

    /* The control stack is right-aligned under Leaflet's zoom control, so on a
       narrow screen the search box has to give ground while the results list
       stays readable — hence a narrower input but a dropdown allowed to run
       nearly the full width.

       The 16px font-size is load-bearing, not taste: iOS Safari zooms the
       viewport in whenever a focused field's computed font-size is under
       16px, and it never zooms back out on blur. Anywhere else on the site
       that is survivable — the page scrolls, so you can pinch back. Here it
       is not: the map page does not scroll, so finishing a search leaves the
       user magnified over this control stack in the top-right corner with the
       map off screen. 16px is the exact threshold, so mobile drops the
       0.75rem (12px) of the base rule and pays for it in width instead. The
       tempting one-line alternative — maximum-scale=1 in the viewport meta —
       would fix it by killing pinch zoom for the whole site, which trades a
       map bug for an accessibility regression. Keep this in px, not rem: the
       threshold is an absolute 16 CSS pixels and does not follow the user's
       root font-size. Vertical padding shrinks so the taller text still fits
       the 30px height the neighbouring controls align to. */
    .map-search-input {
        width: 170px;
        font-size: 16px;
        padding: 4px 26px 4px 8px;
    }

    /* Same trap, same page: popup HTML is cloned into the bottom sheet on
       mobile (see the popupopen handler in js/pages/map.js), so the visit
       notes textarea is a real mobile field — and it carries no font-size of
       its own, which means the UA default of ~13px. */
    #mobile-bottom-sheet textarea,
    #mobile-bottom-sheet input[type="text"] {
        font-size: 16px;
    }

    .map-search-results {
        min-width: 220px;
        max-width: calc(100vw - 20px);
    }
}



/* ==========================================================================
   ROUTE SELECTION AUTOMATIC NEON GLOW ENGINE
   ========================================================================== */
/* Targets the SVG path elements automatically when injected into the DOM by Leaflet */
.glowing-route-vector path {
    animation: neonFadeIn 0.8s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

/* Keyframe definition handles base values and final state overrides cleanly */
@keyframes neonFadeIn {
    from {
        stroke-opacity: 0 !important;
        filter: drop-shadow(0px 0px 0px rgba(255, 102, 0, 0));
    }
    to {
        stroke-opacity: 0.95 !important;
        filter: drop-shadow(0px 0px 6px rgba(255, 102, 0, 0.95)) 
                drop-shadow(0px 0px 2px rgba(255, 150, 0, 0.6));
    }
}

/* Hide the floating widgets until the intro gate/video has finished. The mobile
   topbar quest icon (navbar.html) opens the same widget #quests-placeholder
   hides above, so it's included here too — otherwise it would be a dead tap
   while the widget underneath stays hidden. */
body.gate-active #radio-placeholder,
body.gate-active #quests-placeholder,
body.gate-active #horizon-chat-widget,
body.gate-active .quest-nav-btn {
    display: none;
}

/* ==========================================================================
   6. MODULE SPECIFIC: HORIZON FLOATING CHAT WIDGET
   ========================================================================== */
.chat-widget {
    position: fixed;
    bottom: 20px;
    right: 20px;
    z-index: 9999;
    font-family: inherit;
    transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Active/Expanded View State */
.chat-widget:not(.mini) {
    width: 350px;
    height: 400px;
}
.chat-widget:not(.mini) .chat-window-inner {
    opacity: 1;
    pointer-events: auto;
    transform: scale(1);
}
.chat-widget:not(.mini) .chat-mini-trigger {
    opacity: 0;
    pointer-events: none;
    transform: scale(0.8);
}

/* Collapsed Small Square Button State */
.chat-widget.mini {
    width: 65px;
    height: 65px;
}
.chat-widget.mini .chat-window-inner {
    opacity: 0;
    pointer-events: none;
    transform: scale(0.85);
}
.chat-widget.mini .chat-mini-trigger {
    opacity: 1;
    pointer-events: auto;
    transform: scale(1);
}

/* Square Button Style */
.chat-mini-trigger {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: #13131386;
    border: 2px solid #ffffff;
    border-radius: 8px;
    color: white;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    font-weight: 900;
    font-size: 0.6875rem;
    letter-spacing: 0.5px;
    cursor: pointer;
    box-shadow: 0 6px 16px rgba(0,0,0,0.4);
    transition: all 0.2s ease, transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}
.chat-mini-trigger:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 20px rgba(236,0,140,0.3);
}

/* Container for the real Chat Window content */
.chat-window-inner {
    width: 100%;
    height: 100%;
    background-color: #1a1a1a;
    border: 2px solid white;
    border-radius: 10px;
    box-shadow: 0 10px 25px rgba(0,0,0,0.6);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    transform-origin: bottom right;
    transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Header styling matching the Horizon aesthetic */
.chat-header {
    background: #13131386;
    padding: 12px;
    cursor: pointer;
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-bottom: 2px solid white;
    user-select: none;
}
.chat-title { font-weight: 900; font-size: 0.8125rem; letter-spacing: 0.5px; color: white; }
#chat-toggle-icon { font-size: 0.6875rem; color: #ec008c; }

/* Main body layouts */
.chat-body {
    display: flex;
    flex-direction: column;
    flex-grow: 1;
    background-color: #181818;
    height: calc(100% - 45px);
}
.chat-logs {
    flex-grow: 1;
    padding: 15px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* Individual Message formats */
.chat-msg-row { font-size: 0.8125rem; line-height: 1.4; word-break: break-word; }
.chat-username { color: #ec008c; font-weight: bold; margin-right: 5px; }
.chat-text { color: #ffffff; }
.chat-system-msg { font-size: 0.6875rem; color: #777; text-align: center; font-style: italic; margin: 4px 0; }

/* Footer / Input systems */
.chat-footer {
    display: flex;
    padding: 10px;
    background-color: #222;
    border-top: 1px solid #333;
    gap: 8px;
}
#chat-input {
    flex-grow: 1;
    background: #111;
    border: 1px solid #444;
    color: #fff;
    padding: 8px;
    border-radius: 4px;
    font-size: 0.8125rem;
}
#chat-input:focus { outline: none; border-color: #ec008c; }
.chat-footer button {
    background-color: #a6ce39;
    color: #000;
    border: none;
    padding: 0 14px;
    font-weight: bold;
    font-size: 0.75rem;
    border-radius: 4px;
    cursor: pointer;
    text-transform: uppercase;
    /* Without this a quick second tap can be taken as a double-tap-to-zoom
       gesture and never become a click. */
    touch-action: manipulation;
}

/* Below 768px — expand as a full-page lightbox, same treatment as the radio and
   quest widgets' <=1650px overlay further down. Chat's own breakpoint is
   narrower than theirs (768px, not 1650px) because its 350x400 panel already
   fits fine down to tablet width — only phone-width viewports need it to go
   fullscreen. No fade choreography here — it just snaps open/closed like the
   image lightbox and the other two widgets do at their own breakpoint. */
@media (max-width: 768px) {
    /* Unlike radio/quest, .chat-widget itself carries a transition (for its
       small-popup scale animation above this breakpoint) — disable it here too,
       on both faces, or collapsing back to mini would animate across the
       full-viewport gap it just snapped open over. */
    .chat-widget,
    .chat-widget .chat-window-inner,
    .chat-widget .chat-mini-trigger {
        transition: none;
    }
    .chat-widget:not(.mini) {
        left: 0;
        top: 0;
        right: 0;
        bottom: 0;
        width: 100%;
        height: 100%;
        transform: none;
        background: rgba(0, 0, 0, 0.9);
        display: flex;
        align-items: center;
        justify-content: center;
    }
    .chat-widget:not(.mini) .chat-window-inner {
        width: min(92vw, 400px);
        height: min(80vh, 520px);
        transform: none;
    }
    /* A literal 16px, not 0.8125rem: iOS Safari zooms the viewport in on focus
       of any smaller field and never zooms back out, which would strand the
       user magnified over this fullscreen overlay. Same fix as the map search
       box — and don't reach for maximum-scale=1 instead, it kills pinch zoom
       site-wide. */
    #chat-input {
        font-size: 16px;
    }
}

/* ==========================================================================
   MODULE SPECIFIC: HORIZON FLOATING RADIO WIDGET
   ========================================================================== */

.radio-widget {
    position: fixed;
    z-index: 9998;
    font-family: inherit;
}

/* Full-height black-to-transparent gradient standing in for a shadow behind
   the radio widget while the map page sits beneath it — only in non-fullscreen
   mode (below 1650px the expanded widget becomes a full-page lightbox and this
   is turned back off further down). Opacity mirrors the widget's own fade —
   visible only once it's expanded and settled, hidden while mini or fading
   (see .fading in js/radio.js), transitioning over the same 0.2s. */
body.page-map::before {
    content: '';
    position: fixed;
    inset: 0;
    width: 1000px;
    background: linear-gradient(to right, rgba(0, 0, 0, 1) 0%, transparent 100%);
    pointer-events: none;
    z-index: 9997;
    opacity: 0;
    transition: opacity 0.2s ease;
}
body.page-map:has(.radio-widget:not(.mini):not(.fading))::before {
    opacity: 1;
}


/* While opening/closing on desktop: force both faces hidden so the
   container can jump to its new position unseen, then fade the new
   face in — see toggleRadioWidget()/radioSetExpanded() in js/radio.js */
.radio-widget.fading .radio-window-inner,
.radio-widget.fading .radio-mini-trigger {
    opacity: 0 !important;
    pointer-events: none !important;
}

/* Expanded state — center-left of viewport */
.radio-widget:not(.mini) {
    left: 20px;
    top: 50%;
    bottom: auto;
    transform: translateY(-50%);
    width: 350px;
    height: 460px;
}
.radio-widget:not(.mini) .radio-window-inner {
    opacity: 1;
    pointer-events: auto;
}
.radio-widget:not(.mini) .radio-mini-trigger {
    opacity: 0;
    pointer-events: none;
}

/* Collapsed state — bottom-right, above chat button */
.radio-widget.mini {
    right: 20px;
    bottom: 95px;
    top: auto;
    left: auto;
    transform: none;
    width: 65px;
    height: 65px;
}
.radio-widget.mini .radio-window-inner {
    opacity: 0;
    pointer-events: none;
}
.radio-widget.mini .radio-mini-trigger {
    opacity: 1;
    pointer-events: auto;
}

/* Mini trigger button — default: transparent bg, gradient border */
.radio-mini-trigger {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: transparent;
    border: none;
    border-radius: 8px;
    color: white;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 3px;
    cursor: pointer;
    overflow: hidden;
    transition: all 0.2s ease, transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Gradient border via mask trick */
.radio-mini-trigger::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 8px;
    padding: 2px;
    background: linear-gradient(135deg, #ec008c, #f15a24);
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    mask-composite: exclude;
    pointer-events: none;
    transition: opacity 0.2s ease;
}
.radio-mini-trigger:hover {
    transform: translateY(-2px);
}
.radio-trigger-icon { font-size: 1.1rem; line-height: 1; position: relative; }
.radio-trigger-label { font-weight: 900; font-size: 0.5625rem; letter-spacing: 0.5px; position: relative; }

/* Mini logo — shown when a station is loaded */
.radio-mini-logo {
    display: none;
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    border-radius: 8px;
}

/* Station-loaded state: show logo, hide text/border */
.has-station .radio-mini-trigger::before { opacity: 0; }
.has-station .radio-mini-trigger .radio-trigger-icon,
.has-station .radio-mini-trigger .radio-trigger-label { display: none; }
.has-station .radio-mini-logo { display: block; }

/* Expanded panel shell — fully transparent, no border */
.radio-window-inner {
    position: absolute;
    width: 350px;
    height: 460px;
    background: transparent;
    border: none;
    box-shadow: none;
    border-radius: 10px;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    transition: opacity 0.2s ease;
}

/* Header — transparent, floating text */
.radio-header {
    background: transparent;
    border-bottom: none;
    padding: 9px 12px;
    cursor: pointer;
    user-select: none;
    display: flex;
    justify-content: flex-start;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
}
.radio-title {
    font-weight: 900;
    font-size: 0.8125rem;
    letter-spacing: 0.5px;
    color: #fff;
    text-shadow: 0 1px 6px rgba(0,0,0,0.9), 0 0 12px rgba(0,0,0,0.6);
}
#radio-toggle-icon {
    font-size: 0.6875rem;
    color: #fff;
    text-shadow: 0 1px 4px rgba(0,0,0,0.8);
}

/* Shared body container for both sub-views */
.radio-body {
    flex: 1;
    display: flex;
    flex-direction: column;
    padding: 8px 12px;
    gap: 8px;
    overflow: hidden;
    background: transparent;
}

/* Station identity row */
.radio-station-identity { display: flex; align-items: center; justify-content: left; }
.radio-logo-img {
    width: 128px;
    height: 128px;
    border-radius: 6px;
    object-fit: contain;
    border: none;
    background: transparent;
    flex-shrink: 0;
    filter: drop-shadow(0 2px 8px rgba(0,0,0,0.6));
}
.radio-station-meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.radio-station-name {
    font-weight: 900;
    font-size: 0.8125rem;
    color: #ffffff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.radio-game-name {
    font-size: 0.6875rem;
    color: #aaa;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Track info */
.radio-track-info { display: flex; flex-direction: column; gap: 4px; }
.radio-song-title {
    font-size: 0.875rem;
    font-weight: bold;
    color: #ec008c;
    background: rgba(40, 40, 40, 0.75);
    padding: 5px 10px;
    border-radius: 4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.radio-artist-name {
    font-size: 0.75rem;
    color: #ffffff;
    background: rgba(40, 40, 40, 0.65);
    padding: 4px 10px;
    border-radius: 4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* YouTube player container */
#radio-yt-container {
    width: 100%;
    flex-shrink: 0;
    border-radius: 6px;
    overflow: hidden;
    background: #000;
}
#radio-yt-container iframe {
    display: block;
    width: 100%;
    height: 168px;
}

/* Station nav controls */
.radio-controls-row { display: flex; gap: 5px; }
.radio-ctrl-btn {
    flex: 1;
    background-color: #252525;
    border: 1px solid #444;
    color: #fff;
    font-size: 0.5625rem;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    padding: 6px 3px;
    border-radius: 4px;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.radio-ctrl-btn:hover { background-color: #333; border-color: #ec008c; color: #ec008c; }
.radio-ctrl-stations { flex: 1.2; }

/* Station list sub-view — needs its own background for readability */
.radio-station-list {
    padding: 0;
    gap: 0;
    background: rgba(15, 15, 15, 0.92);
    border-radius: 10px;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
}
.radio-station-list-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 9px 12px;
    border-bottom: 1px solid #333;
    font-weight: bold;
    font-size: 0.75rem;
    color: #ffffff;
    flex-shrink: 0;
    background: transparent;
}
.radio-close-list-btn {
    background: none;
    border: none;
    color: #aaa;
    font-size: 1rem;
    cursor: pointer;
    padding: 0;
    line-height: 1;
    transition: color 0.15s;
}
.radio-close-list-btn:hover { color: #fff; }

.radio-stations-scroll {
    overflow-y: auto;
    flex: 1;
    padding: 6px;
    display: flex;
    flex-direction: column;
    gap: 3px;
}
.radio-station-empty {
    color: #777;
    font-size: 0.75rem;
    padding: 14px;
    text-align: center;
}
.radio-station-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 10px;
    border-radius: 6px;
    cursor: pointer;
    border: 1px solid transparent;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.radio-station-row:hover { background-color: #252525; border-color: #ec008c; }
.radio-station-row.active { background-color: #252525; border-color: #ffffff; }
.radio-station-row-logo {
    width: 64px;
    height: 32px;
    object-fit: cover;
    flex-shrink: 0;
}
.radio-station-row-meta { min-width: 0; }
.radio-station-row-name {
    font-size: 0.75rem;
    font-weight: bold;
    color: #fff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.radio-station-row-game {
    font-size: 0.625rem;
    color: #aaa;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Below 1650px — expand as a full-page lightbox (same look/feel as .image-lightbox-overlay)
   instead of sliding to the left edge. No fade choreography here — it just
   snaps open/closed like the existing image lightbox. */
@media (max-width: 1650px) {
    .radio-widget:not(.mini) {
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        transform: none;
        background: rgba(0, 0, 0, 0.9);
        display: flex;
        align-items: center;
        justify-content: center;
    }
    .radio-widget .radio-window-inner,
    .radio-widget .radio-mini-trigger {
        transition: none;
    }
    .radio-window-inner {
        width: min(92vw, 400px);
        height: min(80vh, 520px);
    }
    body.page-map::before {
        content: none;
    }
}

body.radio-lightbox-open,
body.quest-lightbox-open,
body.chat-lightbox-open {
    overflow: hidden;
}

/* Below 1650px the expanded radio and quest widgets become full-page overlays at
   z-index 9998, but the chat widget sits at 9999 — so its mini button used to
   float on top of the dimmed overlay. The other widgets collapse themselves via
   fhfr:widget-opened; this covers the gap while that transition runs and any
   route where chat is re-shown underneath. */
body.radio-lightbox-open #horizon-chat-widget,
body.quest-lightbox-open #horizon-chat-widget {
    display: none;
}

/* ==========================================================================
   MODULE SPECIFIC: HORIZON FLOATING QUEST WIDGET
   ==========================================================================
   Deliberately mirrors the radio widget's class contract above: .mini is the
   collapsed state, its absence is expanded, and .fading hides both faces for
   200ms while the container jumps position (see questSetExpanded in
   js/quests.js). Collapsed, the three floating widgets stack up the bottom-right
   corner: chat at 20px, radio at 95px, quests at 170px.
   ========================================================================== */

.quest-widget {
    position: fixed;
    z-index: 9998;
    font-family: inherit;
}

.quest-widget.fading .quest-window-inner,
.quest-widget.fading .quest-mini-trigger {
    opacity: 0 !important;
    pointer-events: none !important;
}

/* Expanded — centre-right, so it never contends with the radio's centre-left */
.quest-widget:not(.mini) {
    right: 20px;
    top: 50%;
    bottom: auto;
    left: auto;
    transform: translateY(-50%);
    width: 350px;
    height: 460px;
}
.quest-widget:not(.mini) .quest-window-inner {
    opacity: 1;
    pointer-events: auto;
}
.quest-widget:not(.mini) .quest-mini-trigger {
    opacity: 0;
    pointer-events: none;
}

/* Collapsed — bottom-right, above the radio button */
.quest-widget.mini {
    right: 20px;
    bottom: 170px;
    top: auto;
    left: auto;
    transform: none;
    width: 65px;
    height: 65px;
}
.quest-widget.mini .quest-window-inner {
    opacity: 0;
    pointer-events: none;
}
.quest-widget.mini .quest-mini-trigger {
    opacity: 1;
    pointer-events: auto;
}

/* Plain white border, matching .chat-mini-trigger, rather than the radio's
   masked gradient ring. The label is the only content now that the flag icon
   is gone, so it centres on its own. */
.quest-mini-trigger {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px solid #ffffff;
    border-radius: 50%;
    background: #1c1c1c;
    color: #fff;
    cursor: pointer;
    transition: opacity 0.2s ease, transform 0.2s ease;
    overflow: visible;
}
.quest-mini-trigger:hover {
    transform: scale(1.06);
}
.quest-trigger-label {
    font-size: 0.625rem;
    letter-spacing: 0.5px;
    font-weight: 900;
}
/* Count of quests waiting to be claimed — same visual language as .notif-badge */
.quest-mini-badge {
    position: absolute;
    top: -2px;
    right: -2px;
    min-width: 20px;
    height: 20px;
    padding: 0 5px;
    border-radius: 10px;
    background: #ec008c;
    color: #fff;
    font-size: 0.7rem;
    font-weight: bold;
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
}

.quest-window-inner {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    border-radius: 12px;
    background: #252525;
    border: 1px solid #3a3a3a;
    overflow: hidden;
    transition: opacity 0.2s ease;
}

.quest-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    background: linear-gradient(to right, #ec008c, #f15a24);
    color: #fff;
    cursor: pointer;
    flex-shrink: 0;
}
.quest-title {
    font-weight: bold;
    letter-spacing: 0.06em;
}

.quest-body {
    flex: 1;
    overflow-y: auto;
    padding: 12px;
}

.quest-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.quest-card {
    display: flex;
    gap: 10px;
    padding: 10px;
    border-radius: 8px;
    background: #1c1c1c;
    border: 1px solid #333;
}
.quest-card.is-complete {
    border-color: #ec008c;
}
.quest-card-icon {
    font-size: 1.3rem;
    line-height: 1.2;
    flex-shrink: 0;
}
.quest-card-main {
    flex: 1;
    min-width: 0;
}
.quest-card-title {
    font-weight: bold;
    font-size: 0.9rem;
    color: #fff;
}
.quest-card-desc {
    font-size: 0.78rem;
    color: #aaa;
    margin: 2px 0 6px;
}
.quest-progress {
    height: 6px;
    border-radius: 3px;
    background: #333;
    overflow: hidden;
}
.quest-progress-fill {
    height: 100%;
    background: linear-gradient(to right, #ec008c, #f15a24);
    transition: width 0.3s ease;
}
.quest-progress-label {
    font-size: 0.7rem;
    color: #888;
    margin-top: 3px;
}

/* Hero variant — the community objective bar on the home page. .quest-progress
   is the only bar primitive in this stylesheet and carries no .quest-card
   ancestor selector, so it's reused rather than duplicated; it's just tuned
   small for the quest widget. */
.quest-progress.is-hero {
    height: 14px;
    border-radius: 7px;
    background: #1c1c1c;
}
.quest-progress.is-hero .quest-progress-fill {
    transition: width 0.6s ease;
}
.quest-card-actions {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    justify-content: space-between;
    gap: 6px;
    flex-shrink: 0;
}
.quest-xp {
    font-size: 0.72rem;
    font-weight: bold;
    color: #f15a24;
    white-space: nowrap;
}
.quest-action {
    white-space: nowrap;
}

/* The community objective card — same shape as .quest-card, but it isn't a
   personal reward, so its corner tag reads as a category label rather than
   an XP figure (contrast with the orange, bold .quest-xp). */
.quest-community-tag {
    color: #888;
    font-weight: bold;
    font-size: 0.65rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
}

/* Non-patron teaser. These cards carry no real quest data — they are static
   placeholders, so there is nothing to read out of the DOM. */
.quest-card.is-locked {
    opacity: 0.75;
}
.quest-blurred {
    filter: blur(4px);
    user-select: none;
}
.quest-locked-cta {
    margin-top: 6px;
    padding: 14px;
    border-radius: 8px;
    background: #1c1c1c;
    border: 1px solid #333;
    text-align: center;
}
.quest-locked-title {
    font-weight: bold;
    color: #fff;
    margin-bottom: 6px;
}
.quest-locked-cta .btn {
    margin-top: 10px;
}

.quest-footer {
    margin-top: 12px;
    text-align: center;
}
.quest-reroll-count {
    font-size: 0.72rem;
    color: #777;
}

/* Check-in button in the map popup — sits directly above "Get Directions" and
   inherits .directions-btn's sizing, so it reads as a peer of it. */
.quest-checkin-btn {
    background: linear-gradient(to right, #ec008c, #f15a24);
    color: #fff;
    width: 100%;
    border: none;
    padding: 10px;
    cursor: pointer;
    font: inherit;
}
.quest-checkin-btn:disabled {
    opacity: 0.6;
    cursor: default;
}

/* Below 1650px — expand as a full-page lightbox, matching the radio widget. */
@media (max-width: 1650px) {
    .quest-widget:not(.mini) {
        right: 0;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        transform: none;
        background: rgba(0, 0, 0, 0.9);
        display: flex;
        align-items: center;
        justify-content: center;
    }
    .quest-widget .quest-window-inner,
    .quest-widget .quest-mini-trigger {
        transition: none;
    }
    .quest-widget:not(.mini) .quest-window-inner {
        position: relative;
        inset: auto;
        width: min(92vw, 400px);
        height: min(80vh, 520px);
    }
}

/* ==========================================================================
   MODULE SPECIFIC: COMMUNITY OBJECTIVE PANEL (home page)
   ==========================================================================
   Deliberately NOT a .horizon-card: that component's .card-header is a
   pink->orange gradient, and the progress bar's fill is the same gradient. A
   header bar directly above the fill makes them compete, so the panel is a
   restrained dark surface and the bar is the only gradient in the block.
   ========================================================================== */

.objective-panel {
    background: #252525;
    border: 1px solid #333;
    border-radius: 12px;
    padding: 22px 24px;
    margin-top: 30px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
    /* The title, description and reward name are admin-authored, so nothing
       guarantees a word that fits. anywhere (unlike break-word) also lowers
       each block's min-content width, so one long word breaks inside the
       panel instead of stretching its flex column past the panel's edge. It
       only ever breaks a word that could not fit otherwise. */
    overflow-wrap: anywhere;
}

.objective-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 12px;
}

.objective-eyebrow {
    font-size: 1.5rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: #ec008c;
    font-weight: bold;
    margin-bottom: 4px;
}

.objective-title {
    font-size: 1.35rem;
    font-weight: bold;
    color: #fff;
    margin: 0;
    line-height: 1.2;
}

.objective-numbers {
    white-space: nowrap;
    text-align: right;
}
.objective-current {
    font-size: 1.35rem;
    font-weight: bold;
    color: #fff;
}
.objective-target {
    font-size: 0.85rem;
    color: #888;
    margin-left: 4px;
}

/* Just the percentage now — the reward moved below the description. */
.objective-meta {
    margin-top: 8px;
    font-size: 0.75rem;
    color: #888;
}

.objective-desc {
    margin: 16px 0 0;
    color: #aaa;
    font-size: 0.9rem;
    line-height: 1.6;
}

/* Reward sits under the description, image and name together, so the payoff
   reads as the conclusion of the pitch rather than a caption to the bar. */
.objective-reward {
    display: flex;
    gap: 14px;
    align-items: center;
    margin-top: 16px;
}
/* contain, not cover: reward art is admin-authored and can be any aspect ratio
   (a wide banner, a tall poster, a square emoji), and cover crops whatever
   doesn't fit the square — it was slicing the sides off non-square images.
   contain fits the whole thing, and the darker background turns the leftover
   space into a deliberate frame rather than a gap. */
.objective-reward-img {
    width: 110px;
    height: 110px;
    object-fit: contain;
    background: #1c1c1c;
    padding: 6px;
    border-radius: 8px;
    flex-shrink: 0;
    border: 1px solid #3a3a3a;
}
/* flex: 1 pins the image to the panel's right edge whatever the length of the
   reward text, so the row reads text-left / image-right like .objective-head
   above it rather than drifting with the copy. */
.objective-reward-name {
    flex: 1;
    color: #f2c14e;
    font-weight: bold;
    font-size: 0.95rem;
}

.objective-cta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    flex-wrap: wrap;
    margin-top: 18px;
    padding-top: 16px;
    border-top: 1px solid #333;
    font-size: 0.85rem;
    color: #bbb;
}
.objective-cta .btn {
    flex-shrink: 0;
    text-decoration: none;
}

/* Target met — the bar stays full and the panel picks up the accent. */
.objective-panel.is-complete {
    border-color: #a6ce39;
}
.objective-panel.is-complete .objective-eyebrow {
    color: #a6ce39;
}

/* The chat/radio/quest widgets are fixed to the bottom-right of the VIEWPORT,
   and this panel is the last thing on the home page — so scrolled to the bottom
   it sits directly beneath them and its right-aligned content (the XP figures,
   the reward name, the CTA button) disappears behind the stack.
   Reserve the widget lane: 65px button + 20px viewport offset + breathing room.
   The same reserve is mirrored on the left so the panel stays centred on the
   page rather than looking trimmed down one side — the left gutter is
   deliberate symmetry, not clearance.
   Above ~1500px the centred 1200px column already clears the widgets by 90px
   or more, so no reserve applies and the panel stays flush with the tile grid.
   Phones (600px and below) swap the side reserve for bottom clearance; see
   there. */
@media (max-width: 1500px) {
    .objective-panel {
        margin-left: 100px;
        margin-right: 100px;
    }
}

@media (max-width: 600px) {
    /* No side reserve on phones. An 85px gutter a side cost 170px of a ~390px
       screen and left ~146px of text width, too narrow for the 24px
       letter-spaced eyebrow: "COMMUNITY" alone is ~200px, so it ran out of the
       panel and dragged the title and XP figures out with it. Nothing here is
       right-aligned (everything below stacks left), so the only thing the
       reserve still protected was the panel's bottom corner sitting under the
       widgets at full scroll — and extra bottom margin does that without
       costing any width. The stack is 160px tall below 768px (chat at 20px,
       radio at 95px, 65px each; the quest button moves to the navbar), and
       the panel already ends 139px above the page bottom (wrapper padding +
       footer), so 48px more leaves the same ~20px clearance the reserve gave. */
    .objective-panel {
        padding: 18px;
        margin-left: 0;
        margin-right: 0;
        margin-bottom: 48px;
    }
    .objective-head {
        flex-direction: column;
        align-items: flex-start;
        gap: 6px;
    }
    .objective-numbers {
        text-align: left;
    }
    /* Stacked rather than side by side — there isn't the width for a 110px
       thumbnail and a line of text abreast. Reward name above, image below. */
    .objective-reward {
        flex-direction: column;
        align-items: flex-start;
        gap: 10px;
    }
    /* flex: 1 is a horizontal stretch on desktop; in a column container it
       would stretch the text block vertically instead. */
    .objective-reward-name {
        flex: none;
    }
    .objective-reward-img {
        width: 100%;
        height: 150px;
    }
    .objective-cta {
        flex-direction: column;
        align-items: flex-start;
    }
}

/* Every date/time input on the site sits on a dark #222 field, but the browser
   drew its calendar icon (and picker popup) for a light page — a black icon on
   near-black, effectively invisible. color-scheme tells it the field is dark. */
input[type="date"],
input[type="datetime-local"] {
    color-scheme: dark;
}

/* "Date..." prefill for the events page's date filter. A date input ignores
   the placeholder attribute: iOS Safari draws an empty one as a blank box, and
   desktop browsers show a bare dd/mm/yyyy. Prefilling today's date instead is
   not an option — the filter is an exact-day match, so it would silently hide
   every event not on today. `required` is there only so an empty value matches
   :invalid (the input is in no form, so nothing ever blocks on it); the text
   rides in a ::before, set in the same font and #757575 as the text
   placeholders beside it. It is laid OVER desktop
   Chrome's dd/mm/yyyy fields, which go transparent rather than display: none —
   those fields are the only focusable part of the control, so removing them
   left a click nothing to focus and a date could no longer be typed. Focus
   drops the text and brings the fields back. Firefox draws no ::before on
   inputs and keeps its native dd/mm/yyyy, which at least isn't blank. */
.date-filter-input {
    position: relative;
}
.date-filter-input:invalid:not(:focus)::before {
    content: attr(data-placeholder);
    color: #757575;
    /* The text inputs' own UA font. Inheriting would pick up the monospace
       Chrome gives a date input's fields. A WebKit/Blink keyword is enough:
       only those engines draw this ::before at all. */
    font: -webkit-small-control;
    position: absolute;
    left: 9px;   /* 8px padding + 1px border, as the inline style sets */
    top: 50%;
    transform: translateY(-50%);
    pointer-events: none;
}
.date-filter-input:invalid:not(:focus)::-webkit-datetime-edit {
    color: transparent;
}

/* Events Feed */
.event-title {
    font-weight: bold;
    font-size: 1.2rem;

}

.event-date {
    font-size: 1rem;
    padding-top: 5px;
    padding-bottom: 5px;
}

.event-location {
    font-size: 0.8333rem;
    color: #aaa;
    padding-bottom: 5px;
}

.event-description {
    font-size: 0.8333rem;
    padding-bottom: 10px;
}

.event-external-link {
    font-size: 0.8333rem;
    }

.event-cost {
    font-weight: bold;
}

@media (max-width: 768px) {
    .event-rsvp-count {
        display: none;
    }
}

/* ==========================================================================
   NAVBAR
   ========================================================================== */
.main-navbar {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    flex-wrap: wrap;
    background-color: #1a1a1a;
    padding: 12px 24px;
    width: 100%;
    box-sizing: border-box;
}

.main-navbar::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -3px;
    height: 3px;
    background: linear-gradient(to right, #ec008c, #f15a24);
}

.navbar-logo {
    display: flex;
    align-items: center;
}

.navbar-logo img {
    height: 40px;
    display: block;
}

.navbar-links {
    display: flex;
    align-items: center;
    gap: 28px;
    flex-wrap: wrap;
}

.navbar-links a {
    color: #ffffff;
    text-decoration: none;
    font-weight: 900;
    font-size: 0.8125rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    transition: color 0.2s ease;
}

.navbar-links a:hover {
    color: #ec008c;
}

.navbar-socials {
    display: flex;
    align-items: center;
    gap: 10px;
}

.navbar-social-icon {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background-color: #252525;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.2s ease, transform 0.2s ease;
}

.navbar-social-icon svg {
    width: 16px;
    height: 16px;
    fill: #ffffff;
}

.navbar-social-icon:hover {
    background: linear-gradient(to right, #ec008c, #f15a24);
    transform: translateY(-2px);
}

.navbar-patreon-btn {
    width: 85px;
    height: 34px;
    border-radius: 17px;
    padding: 4px 8px;
}

.navbar-patreon-btn img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.navbar-login-btn {
    background: linear-gradient(to right, #ec008c, #f15a24);
    color: #fff;
    border: none;
    border-radius: 20px;
    padding: 8px 18px;
    font-weight: 900;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    cursor: pointer;
    white-space: nowrap;
}

.navbar-login-btn:hover {
    opacity: 0.9;
}

.mobile-nav-socials .navbar-patreon-btn {
    width: 100px;
    height: 40px;
    border-radius: 20px;
}

.navbar-hamburger {
    display: none;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 5px;
    width: 34px;
    height: 34px;
    background: none;
    border: none;
    cursor: pointer;
    padding: 0;
}

.navbar-hamburger span {
    display: block;
    width: 22px;
    height: 3px;
    background-color: #ffffff;
    border-radius: 2px;
}

.mobile-nav-overlay {
    position: fixed;
    inset: 0;
    z-index: 2000;
    background-color: #141414;
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 36px;
}

.mobile-nav-overlay.is-open {
    display: flex;
}

.mobile-nav-close {
    position: absolute;
    top: 16px;
    right: 20px;
    background: none;
    border: none;
    color: #ffffff;
    font-size: 2rem;
    line-height: 1;
    cursor: pointer;
}

.mobile-nav-links {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 26px;
}

.mobile-nav-links a {
    color: #ffffff;
    text-decoration: none;
    font-weight: 900;
    font-size: 1.375rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    transition: color 0.2s ease;
}

.mobile-nav-links a:hover {
    color: #ec008c;
}

.mobile-nav-login-btn {
    background: linear-gradient(to right, #ec008c, #f15a24);
    color: #fff;
    border: none;
    border-radius: 24px;
    padding: 14px 28px;
    font-weight: 900;
    font-size: 1.1rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    cursor: pointer;
    margin-top: 12px;
}

.mobile-nav-socials {
    display: flex;
    align-items: center;
    gap: 16px;
}

body.mobile-nav-open {
    overflow: hidden;
}

.notif-bell-btn,
.quest-nav-btn {
    position: relative;
    border: none;
    cursor: pointer;
}

.notif-bell-btn svg,
.quest-nav-btn svg {
    fill: #ffffff;
}

.notif-badge {
    position: absolute;
    top: -4px;
    right: -4px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 8px;
    background: #ec008c;
    color: #fff;
    font-size: 0.625rem;
    font-weight: bold;
    line-height: 16px;
    text-align: center;
}

.navbar-mobile-icons {
    display: none;
    align-items: center;
    gap: 10px;
}

.notif-bell-mobile,
.quest-nav-btn {
    display: none;
}

.notif-dropdown {
    position: absolute;
    top: calc(100% + 12px);
    right: 24px;
    width: 320px;
    max-width: 90vw;
    max-height: 420px;
    overflow-y: auto;
    background: #1f1f1f;
    border: 1px solid #333;
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.5);
    z-index: 2100;
}

.notif-dropdown-header {
    padding: 12px 14px;
    font-weight: 900;
    font-size: 0.8125rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: #ffffff;
    border-bottom: 1px solid #333;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}
.notif-mark-all-read {
    background: none;
    border: none;
    color: #ec008c;
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: none;
    letter-spacing: normal;
    cursor: pointer;
    padding: 0;
}
.notif-mark-all-read:hover { text-decoration: underline; }

.notif-dropdown-list {
    display: flex;
    flex-direction: column;
}

.notif-empty {
    padding: 16px 14px;
    color: #888;
    font-size: 0.8125rem;
}

.notif-row {
    display: block;
    width: 100%;
    text-align: left;
    padding: 10px 14px;
    background: none;
    border: none;
    border-bottom: 1px solid #2a2a2a;
    color: #ddd;
    font-size: 0.8125rem;
    line-height: 1.4;
    cursor: pointer;
}

.notif-row:last-child {
    border-bottom: none;
}

.notif-row:hover {
    background: #262626;
}

.notif-row.unread {
    background: rgba(236, 0, 140, 0.08);
}

.notif-row .notif-row-actor {
    color: #ec008c;
    font-weight: bold;
}

.notif-row .notif-row-time {
    display: block;
    margin-top: 2px;
    color: #888;
    font-size: 0.6875rem;
}

@media (max-width: 768px) {
    .navbar-links,
    .navbar-socials {
        display: none;
    }
    .navbar-hamburger {
        display: flex;
    }
    .navbar-mobile-icons {
        display: flex;
    }
    .notif-bell-mobile,
    .quest-nav-btn {
        display: flex;
    }
    .notif-dropdown {
        right: 12px;
    }

    /* The quest widget's own floating mini button (bottom-right) is replaced by
       .quest-nav-btn above on mobile — the expanded/fullscreen state (the
       widget without .mini) is untouched, so toggleQuestWidget() still opens
       the same fullscreen panel from either trigger. */
    .quest-widget.mini {
        display: none;
    }
}

/* Pages that load the shared navbar (#navbar-placeholder) stack it above
   their content instead of letting the body's centering flex-row push it
   beside the page content. */
body.has-navbar {
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    align-items: stretch;
    padding: 0;
}

body.has-navbar > #navbar-placeholder {
    width: 100%;
    flex-shrink: 0;
}

.page-body-wrapper {
    display: flex;
    justify-content: center;
    align-items: flex-start;
    width: 100%;
    padding: 40px 20px;
    box-sizing: border-box;
}

/* ==========================================================================
   SITE FOOTER
   ========================================================================== */
.site-footer {
    width: 100%;
    padding: 18px 20px 28px;
    text-align: center;
    box-sizing: border-box;
    color: #999;
    font-size: 13px;
}

.site-footer .footer-links {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 6px 14px;
    margin-bottom: 8px;
}

.site-footer a {
    color: #ccc;
    text-decoration: none;
}

.site-footer a:hover {
    color: #ec008c;
    text-decoration: underline;
}

.site-footer .footer-copy {
    color: #777;
}

/* ==========================================================================
   LEGAL / STATIC CONTENT PAGES
   ========================================================================== */
.legal-content {
    max-width: 760px;
    padding: 28px 32px 40px;
    line-height: 1.6;
    color: #e4e4e4;
}

.legal-content h1 {
    margin-top: 0;
    font-size: 26px;
}

.legal-content h2 {
    margin-top: 32px;
    font-size: 19px;
    color: #ffffff;
    border-bottom: 1px solid #3a3a3a;
    padding-bottom: 6px;
}

.legal-content h3 {
    margin-top: 20px;
    font-size: 15px;
    color: #fff;
}

.legal-content p, .legal-content li {
    color: #cfcfcf;
    font-size: 14.5px;
}

.legal-content ul, .legal-content ol {
    padding-left: 22px;
}

.legal-content .legal-meta {
    color: #999;
    font-size: 13px;
    margin-bottom: 24px;
}

.legal-content .legal-callout {
    background: #2f2415;
    border-left: 4px solid #ffffff;
    padding: 12px 16px;
    border-radius: 6px;
    margin: 20px 0;
    font-size: 13.5px;
    color: #e8d8a0;
}

.legal-content a {
    color: #ffffff;
}

/* ==========================================================================
   IMAGE LIGHTBOX
   ========================================================================== */
.image-lightbox-overlay {
    display: none;
    position: fixed;
    z-index: 10000;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0,0,0,0.9);
    align-items: center;
    justify-content: center;
}
.image-lightbox-img {
    max-width: 90vw;
    max-height: 85vh;
    object-fit: contain;
    border-radius: 4px;
    box-shadow: 0 0 30px rgba(0,0,0,0.6);
}
.image-lightbox-close {
    position: absolute;
    top: 20px;
    right: 30px;
    color: white;
    font-weight: bold;
    font-size: 2rem;
    cursor: pointer;
    line-height: 1;
}
.image-lightbox-nav {
    display: none;
    align-items: center;
    justify-content: center;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    background: rgba(0,0,0,0.6);
    color: white;
    border: none;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    cursor: pointer;
    font-size: 1.1rem;
    z-index: 1;
}
.image-lightbox-prev { left: 20px; }
.image-lightbox-next { right: 20px; }

/* ==========================================================================
   MODULE SPECIFIC: SESSION INTRO / SPLASH SCREEN
   ========================================================================== */
.intro-overlay {
    position: fixed;
    inset: 0;
    z-index: 10500;
    background: #000;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: opacity 0.4s ease;
    opacity: 1;
}
.intro-overlay.intro-overlay-hidden {
    opacity: 0;
    pointer-events: none;
}

.intro-stage {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

.intro-overlay.stage-gate .intro-stage-video { display: none; }
.intro-overlay.stage-video .intro-stage-gate { display: none; }

.intro-gate-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 24px;
}

.intro-audio-toggle {
    display: flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    color: #fff;
    font-size: 0.85rem;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.intro-audio-toggle input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.intro-audio-toggle-track {
    position: relative;
    width: 46px;
    height: 24px;
    background: rgba(255, 255, 255, 0.2);
    border-radius: 999px;
    transition: background 0.2s ease;
    flex-shrink: 0;
}

.intro-audio-toggle-track::after {
    content: '';
    position: absolute;
    top: 3px;
    left: 3px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #fff;
    transition: transform 0.2s ease;
}

.intro-audio-toggle input:checked + .intro-audio-toggle-track {
    background: #ffffff;
}

.intro-audio-toggle input:checked + .intro-audio-toggle-track::after {
    transform: translateX(22px);
    background: #000;
}

.intro-gate-btn {
    width: 220px;
    height: 220px;
    border-radius: 50%;
    background: #ffffff;
    color: #000;
    border: none;
    font-weight: bold;
    font-size: 1.1rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    cursor: pointer;
    padding: 20px;
    text-align: center;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
    box-shadow: 0 0 40px rgba(255, 255, 255, 0.4);
}
.intro-gate-btn:hover { transform: scale(1.05); }
.intro-gate-btn:active { transform: scale(0.97); }
.intro-gate-btn:disabled { opacity: 0.5; cursor: default; pointer-events: none; }

.intro-video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    cursor: pointer;
}

.intro-continue-corner {
    position: absolute;
    bottom: 24px;
    left: 24px;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
    pointer-events: none;
    z-index: 1;
}

.intro-continue-logo {
    height: 10rem;
    width: auto;
}

.intro-continue-hint {
    background: rgba(0,0,0,0.75);
    color: white;
    font-size: 1rem;
    font-weight: bold;
    padding: 8px 14px;
    border-radius: 4px;
}

/* Announcement from intro_settings.label, top-right over the video. Same
   paint as .intro-continue-hint so the two read as one family. */
.intro-announcement {
    position: absolute;
    top: 24px;
    right: 24px;
    max-width: min(420px, calc(100% - 48px));
    display: flex;
    align-items: flex-start;
    gap: 10px;
    background: rgba(0,0,0,0.75);
    color: white;
    padding: 10px 8px 10px 14px;
    border-radius: 4px;
    z-index: 1;
    cursor: default;
}

.intro-announcement-text {
    flex: 1;
    min-width: 0;
    font-size: 0.95rem;
    line-height: 1.4;
    white-space: pre-line;
    overflow-wrap: anywhere;
}

.intro-announcement-close {
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    margin: -4px 0;
    background: none;
    border: none;
    color: rgba(255,255,255,0.7);
    font-size: 1.4rem;
    line-height: 1;
    cursor: pointer;
    border-radius: 4px;
}
.intro-announcement-close:hover { color: #fff; background: rgba(255,255,255,0.12); }

@media (max-width: 600px) {
    .intro-announcement {
        top: 12px;
        right: 12px;
        max-width: calc(100% - 24px);
    }
    .intro-announcement-text { font-size: 0.875rem; }
}
.image-lightbox-counter {
    display: none;
    position: absolute;
    bottom: 20px;
    left: 50%;
    transform: translateX(-50%);
    color: white;
    font-size: 0.8125rem;
    font-weight: bold;
    background: rgba(0,0,0,0.6);
    padding: 4px 12px;
    border-radius: 20px;
}
@media (max-width: 600px) {
    .image-lightbox-nav { width: 36px; height: 36px; font-size: 0.9rem; }
    .image-lightbox-prev { left: 8px; }
    .image-lightbox-next { right: 8px; }
}

/* ==========================================================================
   POST LIGHTBOX
   ========================================================================== */
.post-lightbox-overlay {
    display: none;
    position: fixed;
    z-index: 10000;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0,0,0,0.9);
    align-items: center;
    justify-content: center;
    padding: 24px;
    box-sizing: border-box;
    overflow-y: auto;
}
.post-lightbox-card {
    width: 100%;
    max-width: 520px;
    max-height: 85vh;
    overflow-y: auto;
    position: relative;
}
.post-lightbox-close {
    position: absolute;
    top: -36px;
    right: 0;
    color: white;
    font-weight: bold;
    font-size: 2rem;
    cursor: pointer;
    line-height: 1;
}
.post-lightbox-loading {
    color: #aaa;
    padding: 24px;
    text-align: center;
}
@media (max-width: 600px) {
    .post-lightbox-overlay { padding: 12px; }
    .post-lightbox-close { top: -32px; font-size: 1.75rem; }
}

/* ==========================================================================
   LOGIN LIGHTBOX
   ========================================================================== */
.login-lightbox-overlay {
    display: none;
    position: fixed;
    z-index: 10002;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0,0,0,0.9);
    align-items: center;
    justify-content: center;
    padding: 24px;
    box-sizing: border-box;
    overflow-y: auto;
}
.login-lightbox-card {
    width: 100%;
    max-width: 360px;
    max-height: 85vh;
    overflow-y: auto;
    position: relative;
}
.login-lightbox-close {
    position: absolute;
    top: -36px;
    right: 0;
    color: white;
    font-weight: bold;
    font-size: 2rem;
    cursor: pointer;
    line-height: 1;
}
@media (max-width: 600px) {
    .login-lightbox-overlay { padding: 12px; }
    .login-lightbox-close { top: -32px; font-size: 1.75rem; }
}

/* ==========================================================================
   HOME MENU DASHBOARD (FHFR_Home.html)
   ========================================================================== */
.menu-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 5px;
    width: 100%;
    max-width: 1200px;
}

/* Below the desktop breakpoint, .menu-grid falls back to the auto-fit rule above.
   Active Users stays hidden for that whole range (not just <768px) so the tile
   count stays even and the auto-fit grid doesn't strand a lone tile in a row. */
@media (max-width: 1023.98px) {
    .menu-tile[data-area="active"] {
        display: none;
    }
}

/* Desktop: echo the mockup layout (garage/active-users left, map center, radio/friends right, news feed bottom) */
@media (min-width: 1024px) {
    .menu-grid {
        grid-template-columns: 0.3fr 0.6fr 0.6fr 0.6fr 0.6fr 1.1fr 0.5fr;
        grid-template-rows: 130px 260px 130px 130px;
        grid-template-areas:
            ".      active   map      map      map      radio    ."
            "garage garage   map      map      map      friends  friends"
            ".      .        news     news     activity .        ."
            ".      .        news     news     .        .        .";
    }
    .menu-tile[data-area="activity"] {
        align-self: start;
    }
    .menu-tile[data-area="active"]   { grid-area: active; }
    .menu-tile[data-area="garage"]   { grid-area: garage; }
    .menu-tile[data-area="map"]      { grid-area: map; }
    .menu-tile[data-area="radio"]    { grid-area: radio; }
    .menu-tile[data-area="friends"]  { grid-area: friends; }
    .menu-tile[data-area="news"]     { grid-area: news; }
    .menu-tile[data-area="activity"] { grid-area: activity; }
}

.menu-tile {
    position: relative;
    display: flex;
    flex-direction: column;
    background-color: #252525;
    border-radius: 12px;
    border: 3px solid transparent;
    box-shadow: 0 10px 30px rgba(0,0,0,0.5);
    overflow: hidden;
    color: inherit;
    text-decoration: none;
    transition: transform 0.2s ease, border-color 0.2s ease;
}

@media (max-width: 768px) {
    .mobile-unfriendly {
        display: none !important;
    }
}

.menu-tile .tile-label {
    order: 2;
    font-size: 1.6rem;
    font-weight: 900;
    text-transform: uppercase;
    letter-spacing: -0.5px;
    color: #ec008c;
    background-color: #ffffff;
    text-align: center;
    padding: 14px 18px;
}

.menu-tile .tile-body {
    order: 1;
    flex-grow: 1;
    padding: 14px 18px 18px;
    color: #aaa;
    font-size: 0.875rem;
    line-height: 1.4;
}

.menu-tile .tile-stat-number {
    order: 1;
}

.menu-tile .tile-goto {
    order: 3;
}

.menu-tile[data-area="garage"] .tile-body,
.menu-tile[data-area="map"] .tile-body,
.menu-tile[data-area="news"] .tile-body {
    padding: 0;
    position: relative;
}

.menu-tile[data-area="garage"] .tile-body img,
.menu-tile[data-area="map"] .tile-body img,
.menu-tile[data-area="news"] .tile-body img {
    position: absolute;
    inset: 0;
    min-height: 0;
}

.menu-tile .tile-preview-img {
    width: 100%;
    height: 100%;
    min-height: 120px;
    object-fit: cover;
    object-position: center;
    display: block;
}

/* Friends preview chips */
.tile-friend-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: #1a1a1a;
    border-left: 3px solid #310f90;
    border-radius: 6px;
    padding: 4px 10px;
    margin: 0 6px 6px 0;
    color: #ddd;
    font-size: 0.8125rem;
}

/* "GO TO X" footer — hidden until hover */
.menu-tile .tile-goto {
    background: linear-gradient(to right, #ec008c, #f15a24);
    color: #ffffff;
    font-weight: 900;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    text-align: center;
    overflow: hidden;
    max-height: 0;
    opacity: 0;
    padding: 0;
    transition: max-height 0.2s ease, opacity 0.2s ease, padding 0.2s ease;
}

/* Clickable hover state: gradient border + lift + reveal footer */
a.menu-tile:hover {
    transform: translateY(-4px);
    background:
        linear-gradient(#252525, #252525) padding-box,
        linear-gradient(to right, #ec008c, #f15a24) border-box;
    border: 3px solid transparent;
}
a.menu-tile:hover .tile-goto {
    max-height: 60px;
    opacity: 1;
    padding: 12px;
}

/* Non-clickable placeholders (Radio, Active Users) */
.menu-tile.is-placeholder {
    cursor: default;
    opacity: 0.9;
}
.menu-tile.is-placeholder .tile-coming-soon {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: #777;
}
.menu-tile .tile-stat-number {
    font-size: 3rem;
    font-weight: 900;
    color: #ffffff;
    line-height: 1;
    text-align: center;
    padding: 8px 12px 0;
}

/* Active Users: empty body shouldn't push the label away from the number */
.menu-tile[data-area="active"] .tile-body {
    flex-grow: 0;
    padding: 0;
}
.menu-tile[data-area="active"] .tile-label {
    font-size: 1.1rem;
    padding: 10px 8px;
}

/* Radio and Active Users: fully white tiles */
.menu-tile[data-area="radio"],
.menu-tile[data-area="active"] {
    background-color: #ffffff;
}
.menu-tile[data-area="active"] .tile-stat-number {
    color: #ec008c;
}

/* Radio tile: interactive, logo centered */
.menu-tile.is-interactive {
    cursor: pointer;
}
.menu-tile.is-interactive:hover {
    transform: translateY(-4px);
    background:
        linear-gradient(#ffffff, #ffffff) padding-box,
        linear-gradient(to right, #ec008c, #f15a24) border-box;
    border: 3px solid transparent;
}
/* Overlay the goto footer so it doesn't need height budget in the cramped 130px row */
.menu-tile.is-interactive .tile-goto {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
}
.menu-tile.is-interactive:hover .tile-goto {
    max-height: 60px;
    opacity: 1;
    padding: 12px;
}
.menu-tile[data-area="radio"] .tile-body {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 8px 12px;
    min-height: 0;
}
.radio-home-logo {
    max-width: 100%;
    max-height: 52px;
    width: auto;
    height: auto;
    object-fit: contain;
    display: block;
    filter: drop-shadow(0px 0px 20px rgba(0, 0, 0, 1));
}

/* Same breakpoint as .mobile-unfriendly, which hides the radio tile's logo body
   here and leaves just the white label — so the tile's own white background
   (there for the logo) only shows through its 3px transparent border, a white
   ring that made it read 6px larger than its dark-backed neighbours despite an
   identical box. Match theirs, including the hover/tap state, which otherwise
   paints the padding box white again. */
@media (max-width: 768px) {
    .menu-tile[data-area="radio"] {
        background-color: #252525;
    }
    .menu-tile[data-area="radio"].is-interactive:hover {
        background:
            linear-gradient(#252525, #252525) padding-box,
            linear-gradient(to right, #ec008c, #f15a24) border-box;
    }
}

/* SPA Map page — full-viewport layout */
body.page-map {
    height: 100vh;
    overflow: hidden;
}
body.page-map #app-content {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    padding: 0;
}
body.page-map #map-page-content {
    flex: 1 1 auto;
    min-height: 0;
    height: 100%;
}
body.page-map #map {
    height: 100%;
    width: 100%;
}

/* ==========================================================================
   6. SHARED UI FEEDBACK: TOASTS + MODAL DIALOGS (js/ui-feedback.js)
   ========================================================================== */
.fhfr-toast-stack {
    position: fixed;
    bottom: 24px;
    right: 24px;
    z-index: 10000;
    display: flex;
    flex-direction: column;
    gap: 10px;
    max-width: min(360px, calc(100vw - 32px));
}
.fhfr-toast {
    background: #1f1f1f;
    border: 1px solid #333;
    border-left: 4px solid #ffffff;
    border-radius: 8px;
    padding: 12px 14px;
    display: flex;
    align-items: flex-start;
    gap: 10px;
    box-shadow: 0 10px 30px rgba(0,0,0,0.5);
    animation: fhfr-toast-in 0.2s ease;
}
.fhfr-toast-success { border-left-color: #a6ce39; }
.fhfr-toast-error { border-left-color: #ec008c; }
.fhfr-toast-out { animation: fhfr-toast-out 0.2s ease forwards; }
.fhfr-toast-msg {
    flex-grow: 1;
    font-size: 0.8125rem;
    color: #ddd;
    line-height: 1.4;
}
.fhfr-toast-close {
    background: none;
    border: none;
    color: #888;
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    padding: 0;
}
.fhfr-toast-close:hover { color: #fff; }
@keyframes fhfr-toast-in {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: translateY(0); }
}
@keyframes fhfr-toast-out {
    from { opacity: 1; }
    to { opacity: 0; transform: translateY(8px); }
}

.fhfr-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.7);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10001;
    padding: 20px;
}
.fhfr-modal-card {
    background: #252525;
    border-radius: 12px;
    box-shadow: 0 10px 30px rgba(0,0,0,0.5);
    padding: 20px;
    max-width: 400px;
    width: 100%;
}
.fhfr-modal-title {
    font-weight: 900;
    text-transform: uppercase;
    font-size: 0.9375rem;
    color: #ffffff;
    margin-bottom: 10px;
}
.fhfr-modal-message {
    color: #ddd;
    font-size: 0.8125rem;
    line-height: 1.5;
    margin-bottom: 16px;
}
.fhfr-modal-options {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 16px;
}
.fhfr-modal-option {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.8125rem;
    color: #ddd;
    cursor: pointer;
    background: #1f1f1f;
    border: 1px solid #333;
    border-radius: 6px;
    padding: 8px 10px;
}
.fhfr-modal-option input { accent-color: #ec008c; }
.fhfr-modal-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}
.fhfr-modal-actions .btn-sm { margin-top: 0; }

/* ==========================================================================
   MODULE SPECIFIC: FIRST-TIME VISITOR TUTORIAL
   ========================================================================== */
.fhfr-tut-root {
    position: fixed;
    inset: 0;
    z-index: 10300;
}

.fhfr-tut-blocker {
    position: absolute;
    inset: 0;
    z-index: 1;
    background: transparent;
}

.fhfr-tut-spot {
    position: fixed;
    z-index: 2;
    pointer-events: none;
    border-radius: 10px;
    box-shadow: 0 0 0 9999px rgba(0,0,0,0.72), 0 0 0 2px #ec008c, 0 0 16px 2px rgba(236,0,140,0.55);
}
.fhfr-tut-spot.fhfr-tut-spot-hidden {
    box-shadow: 0 0 0 9999px rgba(0,0,0,0.72);
}

.fhfr-tut-card {
    position: fixed;
    z-index: 3;
    top: 0;
    left: 0;
    width: min(340px, calc(100vw - 32px));
    background: #1a1a1a;
    border: 1px solid #333;
    border-radius: 12px;
    box-shadow: 0 10px 30px rgba(0,0,0,0.6);
    padding: 18px;
    color: #fff;
}
.fhfr-tut-card-centered {
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}
.fhfr-tut-card-mobile {
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    max-height: 70vh;
    overflow-y: auto;
    border-radius: 16px 16px 0 0;
}

.fhfr-tut-step-count {
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: #ec008c;
    margin-bottom: 6px;
}
.fhfr-tut-title {
    font-size: 1.0625rem;
    font-weight: 900;
    color: #fff;
    margin: 0 0 10px 0;
}
.fhfr-tut-body {
    font-size: 0.8125rem;
    line-height: 1.55;
    color: #ddd;
}
.fhfr-tut-authnote {
    margin-top: 10px;
    padding: 8px 10px;
    background: #2c1313;
    border: 1px solid #4a1f1f;
    border-radius: 6px;
    font-size: 0.75rem;
    color: #e8b8b8;
}

.fhfr-tut-actions {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    margin-top: 16px;
}
.fhfr-tut-actions-right {
    display: flex;
    gap: 8px;
}
.fhfr-tut-skip {
    background: none;
    border: none;
    padding: 0;
    color: #888;
    font-size: 0.75rem;
    text-decoration: underline;
    cursor: pointer;
}
.fhfr-tut-skip:hover { color: #aaa; }
.fhfr-tut-back,
.fhfr-tut-next {
    padding: 8px 16px;
    font-size: 0.75rem;
    font-weight: bold;
    text-transform: uppercase;
    border: none;
    border-radius: 6px;
    cursor: pointer;
}
.fhfr-tut-back {
    background: #222;
    color: #aaa;
    border: 1px solid #444;
}
.fhfr-tut-next {
    background: linear-gradient(to right, #ec008c, #f15a24);
    color: #fff;
}
.fhfr-tut-back.fhfr-tut-hidden-btn { display: none; }