body {
    padding-top: 0.5rem;
}

/* contact.html's form error banner - same shape/weight as theme.css's own
   .form-success, just in an error color instead of a success one (that
   class itself is a static "hidden unless .show is added" component this
   app doesn't use that way; a plain th:if-rendered .form-error/.form-info
   is simpler for a form that's re-rendered server-side on every submit
   rather than shown/hidden client-side). */
.form-error {
    background: #fbe7e7;
    color: #9a2e2e;
    padding: 13px 16px;
    border-radius: 10px;
    margin-bottom: 18px;
    font-size: 14px;
}

.form-info {
    background: #e7f3e8;
    color: #2e6740;
    padding: 13px 16px;
    border-radius: 10px;
    margin-bottom: 18px;
    font-size: 14px;
}

/* login.html's session-timeout notice - informational, not an error, so a
   distinct amber tone rather than reusing .form-error's red. */
.form-warning {
    background: #fbf1de;
    color: #8a5a12;
    padding: 13px 16px;
    border-radius: 10px;
    margin-bottom: 18px;
    font-size: 14px;
}

/* The CAPTCHA image + its "get a new one" control, inside a .field so it
   lines up with the rest of the form. */
.captcha-row {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
}

.captcha-row img {
    border-radius: 10px;
    display: block;
}

.captcha-refresh {
    background: none;
    border: none;
    padding: 0;
    font-size: 12px;
    color: var(--terracotta-dark, #9d4e30);
    text-decoration: underline;
    cursor: pointer;
}

/* contact.html's form sits inside .section-dark (a two-column layout with
   the "Book a Consultation" copy), and .section-dark sets color:#fff at
   the section level (theme.css) - that cascades straight into the white
   .form-card underneath it, making its labels/legends/plain text render
   white-on-white (invisible, though still present in the DOM - this is
   what "the form fields have no labels" turned out to be). Field
   labels/inputs already had their own explicit colors from theme.css and
   were fine; it was everything else inheriting the section's white that
   needed resetting back to normal ink here. */
.form-card {
    color: var(--ink, #1b2b32);
}

/* index.html hero: full-bleed looping background video, sized to exactly
   one viewport so the whole hero is visible with no scrolling needed on
   any device (100svh - "small viewport height" - avoids the classic
   mobile-browser-chrome 100vh overflow/scroll issue; the plain 100vh
   above it is the fallback for browsers that don't support svh yet, since
   an unsupported value is simply ignored rather than breaking the rule).
   .hero2's own min-height/overflow-hidden/color:#fff (theme.css) still
   apply here - only the things that are actually different (the video
   itself, its dark overlay for text contrast, and the single-column
   layout replacing the old two-column copy+slider grid) are added below. */
.hero-video {
    position: relative;
    min-height: 100vh;
    min-height: 100svh;
    display: flex;
    align-items: center;
}

.hero-video-bg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    z-index: 0;
    /* Fills the gap before the video has any frame to show (no poster
       image any more - see .hero-video-loading below) with a brand-navy
       background instead of a blank/white flash. */
    background-color: var(--navy, #0b1f3a);
}

/* Loading indicator shown in place of the old poster image, while the
   video is still buffering its first frame - hidden (index.html's script)
   the moment the video actually starts playing, or on error. Same
   sliding-highlight indeterminate-progress visual as the map's loading bar
   on home.do, for consistency. */
.hero-video-loading {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 3;
    width: 220px;
    height: 4px;
    border-radius: 2px;
    background: rgba(255, 255, 255, .25);
    overflow: hidden;
    opacity: 1;
    transition: opacity .3s ease;
}

.hero-video-loading-hidden {
    opacity: 0;
    pointer-events: none;
}

.hero-video-loading-bar {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 40%;
    border-radius: 2px;
    background: var(--terracotta, #d97a4d);
    animation: hero-video-loading-slide 1s ease-in-out infinite;
}

@keyframes hero-video-loading-slide {
    0% {
        left: -40%;
    }
    100% {
        left: 100%;
    }
}

.hero-video-overlay {
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(11, 20, 30, .4), rgba(11, 20, 30, .74));
    z-index: 1;
}

.hero-video-inner {
    position: relative;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 32px;
    padding-top: 120px;
}

.hero-video-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 24px;
    margin-top: 34px;
}

#searchResults {
    max-height: 300px;
    overflow-y: auto;
}

/* index.html's "Our Process" panel (replaces the old testimonial quote
   card, same visual weight/position as its .quote-card neighbour, but
   without that class's decorative giant quotation mark - not appropriate
   for a numbered step list). A diagonal gradient (rather than a flat
   fill), a decorative corner ring (the same motif theme.css's own
   .menu-panel-intro::after uses, for visual consistency with the rest of
   the site) and a connecting vertical line behind the circular step
   markers give it more depth than the original flat card. */
.process-card {
    background: linear-gradient(145deg, var(--terracotta-dark, #9d4e30), #7c3c22);
    color: #fff;
    border-radius: 28px;
    padding: 48px 44px;
    position: relative;
    overflow: hidden;
    box-shadow: 0 28px 70px rgba(27, 20, 15, .28);
}

.process-card::after {
    content: "";
    position: absolute;
    width: 220px;
    height: 220px;
    border-radius: 50%;
    right: -90px;
    bottom: -110px;
    border: 1px solid rgba(255, 255, 255, .12);
    box-shadow: 0 0 0 34px rgba(255, 255, 255, .025);
}

.process-card-eyebrow {
    font: 800 11px "Manrope", sans-serif;
    text-transform: uppercase;
    letter-spacing: .14em;
    color: rgba(255, 255, 255, .7);
    margin-bottom: 28px;
    position: relative;
    z-index: 1;
}

.process-steps {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 24px;
    position: relative;
    z-index: 1;
}

.process-steps::before {
    content: "";
    position: absolute;
    top: 18px;
    bottom: 18px;
    left: 17px;
    width: 2px;
    background: rgba(255, 255, 255, .18);
}

.process-steps li {
    display: flex;
    align-items: flex-start;
    gap: 18px;
    position: relative;
}

.process-step-number {
    flex: 0 0 auto;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: rgba(255, 255, 255, .14);
    border: 1.5px solid rgba(255, 255, 255, .4);
    display: grid;
    place-items: center;
    font: 800 12px "Manrope", sans-serif;
    box-shadow: 0 6px 16px rgba(0, 0, 0, .22);
}

.process-steps strong {
    display: block;
    font: 700 17px "Manrope", sans-serif;
    margin-bottom: 4px;
}

.process-steps small {
    display: block;
    font-size: 13px;
    line-height: 1.5;
    color: rgba(255, 255, 255, .72);
}

/* index.html's "Technology Partners" logo strip: a continuously
   auto-scrolling row of real vendor logos (self-hosted CC0-licensed Simple
   Icons SVGs - see resources/vendor/eightysevenpins/images/logos/), muted
   grayscale by default and revealed in full color on hover. The track's
   12 items are the 6 logos doubled (see index.html's comment on that
   markup) so translateX(-50%) loops seamlessly with no visible seam or
   jump; the animation pauses on hover so a logo can actually be read
   before it scrolls on. */
.logo-marquee {
    overflow: hidden;
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
    mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

.logo-marquee-track {
    display: flex;
    align-items: center;
    width: max-content;
    gap: 72px;
    animation: logo-marquee-scroll 28s linear infinite;
}

.logo-marquee:hover .logo-marquee-track {
    animation-play-state: paused;
}

.logo-marquee-item {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 60px;
    width: 184px;
}

.logo-marquee-item img {
    display: block;
    max-height: 46px;
    max-width: 150px;
    width: auto;
    height: auto;
    object-fit: contain;
    filter: none;
    transition: filter .3s ease;
}

.logo-marquee-item:hover img {
    filter: grayscale(0) opacity(1);
}

@keyframes logo-marquee-scroll {
    from {
        transform: translateX(0);
    }
    to {
        transform: translateX(-50%);
    }
}

/* Respects a user's OS-level "reduce motion" preference by simply showing
   the logos in full color, static, rather than forcing the scroll. */
@media (prefers-reduced-motion: reduce) {
    .logo-marquee-track {
        animation: none;
    }

    .logo-marquee-item img {
        filter: none;
    }
}

/* industries.html: alternates each sector's .article-feature (image +
   copy card, from theme.css) left/right down the page instead of every
   row repeating the same image-left layout - added via this class on
   every second section. Grid items (not just flex items) respect the
   "order" property, so swapping which child renders first is enough to
   flip the visual side without needing separate markup per direction. */
.article-feature-reverse {
    grid-template-columns: .9fr 1.1fr;
}

.article-feature-reverse img {
    order: 2;
}

.article-feature-reverse .article-feature-copy {
    order: 1;
}

@media (max-width: 900px) {
    .article-feature-reverse {
        grid-template-columns: 1fr;
    }
}

/* industries.html polish: a large, faint "01"-"06" watermark behind each
   row's copy (reusing the nav mega-menu's own "numbered list" visual
   language, just scaled way up), an icon badge overlaid on the photo's
   corner tying the illustration-icon language from elsewhere on the site
   to a real photo, and a subtle zoom on hover so the row feels
   interactive rather than static. counter-reset lives on <main> (set once
   per page) so counter-increment on each .article-feature numbers them
   01-06 automatically - no per-row number in the markup to keep in sync. */
main {
    counter-reset: industry;
}

.article-feature {
    transition: box-shadow .35s var(--ease, ease), transform .35s var(--ease, ease);
}

.article-feature:hover {
    box-shadow: 0 32px 80px rgba(27, 43, 50, .18);
}

.article-feature img {
    transition: transform .6s var(--ease, ease);
}

.article-feature:hover img {
    transform: scale(1.045);
}

.article-feature-copy {
    counter-increment: industry;
    position: relative;
    overflow: hidden;
}

.article-feature-copy::before {
    content: counter(industry, decimal-leading-zero);
    position: absolute;
    top: -34px;
    right: 28px;
    font: 800 168px "Manrope", sans-serif;
    color: var(--sand, #ead9c4);
    opacity: .55;
    line-height: 1;
    z-index: 0;
    pointer-events: none;
}

.article-feature-copy > * {
    position: relative;
    z-index: 1;
}

.article-feature-icon {
    position: absolute;
    left: 24px;
    bottom: 24px;
    width: 52px;
    height: 52px;
    border-radius: 16px;
    background: rgba(255, 253, 249, .94);
    color: var(--terracotta-dark, #9d4e30);
    display: grid;
    place-items: center;
    box-shadow: 0 14px 32px rgba(8, 24, 30, .28);
}

.article-feature-icon svg {
    width: 26px;
    height: 26px;
}

/* .article-feature is position:relative already (theme.css) - the icon
   badge positions against it directly. */
.article-feature {
    position: relative;
}

/* Small, unobtrusive photo credit for the one industries.html photo
   that's CC BY-SA (not public domain/CC0) and so requires attribution -
   theme.css has no existing "photo credit" component, so this is new. */
.photo-credit {
    position: absolute;
    right: 10px;
    bottom: 8px;
    z-index: 1;
    font-size: 10px;
    color: rgba(255, 255, 255, .85);
    background: rgba(11, 20, 30, .45);
    padding: 3px 8px;
    border-radius: 999px;
    text-decoration: none;
}

.photo-credit:hover {
    color: #fff;
    background: rgba(11, 20, 30, .65);
}

@media (max-width: 900px) {
    .article-feature-copy::before {
        font-size: 100px;
        right: 16px;
    }
}

/* Footer grew a 5th "Quick Links" column (Book a Consultation/Contact
   Us/Log In) alongside theme.css's original Brand/About/Services/
   Industries four; widen the grid to fit it without shrinking the others
   too far. */
.footer-grid {
    grid-template-columns: 1.2fr .7fr .7fr .8fr .8fr;
}

/* eightysevenpins wordmark logo (index.html header/offcanvas/footer).
   58px/43px = 64px/48px reduced by 10%. */
.brand-logo {
    height: 58px;
    width: auto;
    display: block;
}

/* Kept legible on mobile (matches theme.css's own max-width:1080px
   breakpoint for the nav) - still smaller than the 58px desktop size so it
   doesn't crowd the header row, but not so small it's hard to read. */
@media (max-width: 1080px) {
    .brand-logo {
        height: 43px;
    }
}

/* Brand colors on the functional (Bootstrap-navbar) pages - theme.css's
   :root variables (loaded before this file) don't touch Bootstrap's own
   .navbar/.bg-dark class, so this brings the navbar in line with the same
   navy used everywhere else instead of Bootstrap's default dark gray. */
.navbar.bg-dark {
    background-color: var(--navy) !important;
}

/* theme.css's .site-header reserves 40px of top offset for the source
   template's topbar ("New York . London . Dubai" / hello@elvaris.com),
   which this app doesn't have - without this override that space is just
   blank padding above the logo/nav. The .scrolled state and the mobile
   breakpoint already set top:0 themselves, so this only affects the
   normal desktop/unscrolled header. A tiny 2px gap is kept (rather than
   flush 0) so the header isn't touching the very edge of the viewport. */
.site-header {
    top: 7px;
}

/* home.html: logo/search/Welcome-Help-Logout header + a map filling the
   rest of the viewport. */
html, body.app-body {
    height: 100%;
    margin: 0;
    padding-top: 0;
}

.app-body {
    display: flex;
    flex-direction: column;
}

.app-header {
    flex: 0 0 auto;
    position: relative;
    background: var(--navy);
    display: flex;
    align-items: center;
    gap: 20px;
    padding: 12px 24px;
    flex-wrap: wrap;
}

.app-header .brand-logo {
    height: 40px;
}

.app-header-welcome {
    color: #fff;
    font: 600 15px "Manrope", sans-serif;
    text-decoration: none;
    white-space: nowrap;
    cursor: default;
}

/* Welcome line with the server's date (DD MMM YYYY, rendered by
   Thymeleaf from the server clock) in smaller, quieter type beneath it. */
.app-header-user {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
}

.app-header-date {
    color: rgba(255, 255, 255, .7);
    font: 500 12px "DM Sans", sans-serif;
    white-space: nowrap;
    cursor: default;
}

.app-body .app-header-date {
    color: rgba(11, 31, 58, .55);
}

.app-header .header-action {
    margin-left: auto;
}

/* home.do's own white/light-gray colour scheme - scoped to .app-body (only
   ever set on home.html's <body>) rather than changed on the shared
   .app-header/.app-header-welcome rules above, which every other page
   (index/login/profile/admin/...) also uses and keeps its navy header. */
.app-body .app-header {
    background: #fff;
    border-bottom: 1px solid #e5e5e5;
}

.app-body .app-header-welcome {
    color: var(--navy, #0b1f3a);
}

/* Admin/Help/Logout on home.do's header: icon-only circular buttons
   replacing the old text btn-light/btn-primary buttons - nav.admin/
   nav.help/nav.logout still name the action via aria-label/title, just not
   as visible button text any more. */
.header-icon-btn {
    width: 38px;
    height: 38px;
    border-radius: 50%;
    border: 1px solid rgba(11, 31, 58, .12);
    background: #f4f5f6;
    color: var(--navy, #0b1f3a);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    flex-shrink: 0;
}

.header-icon-btn svg {
    width: 19px;
    height: 19px;
}

.header-icon-btn:hover {
    background: var(--sand-2, #f3e9dc);
    border-color: rgba(11, 31, 58, .25);
}

/* home.do's own language switcher - same select-with-?lang=xx-options
   pattern as .lang-switcher on index.html/login.html (see home.html's
   header), just re-themed to sit on home.do's light header instead of
   that one's navy one, rather than reusing .lang-switcher's own white-on-
   navy colours directly. */
.header-lang-switcher {
    appearance: none;
    -webkit-appearance: none;
    background-color: #f4f5f6;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230b1f3a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m8 10 4 4 4-4'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 12px;
    border: 1px solid rgba(11, 31, 58, .12);
    border-radius: 999px;
    color: var(--navy, #0b1f3a);
    cursor: pointer;
    font: 600 13px "DM Sans", sans-serif;
    height: 38px;
    padding: 0 30px 0 16px;
    flex-shrink: 0;
}

.header-lang-switcher:hover {
    background-color: var(--sand-2, #f3e9dc);
}

/* Positioned wrapper so the toolbar and status bar below can overlay
   directly on top of the map rather than sitting in normal page flow. */
.app-map-wrap {
    position: relative;
    flex: 1 1 auto;
    width: 100%;
    /* Belt-and-suspenders: flex-grow alone should stretch this to fill
       the remaining column height, but a flex item with no content and
       no explicit size is a classic zero-height trap in some layout
       edge cases - min-height guarantees the map is visible either way. */
    min-height: 480px;
}

.app-map {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    transition: left .25s ease, right .25s ease;
}

/* Pinning a side panel (leftPanelPin/rightPanelPin, see home.html) docks
   it instead of letting it float over the map - the map's own box shrinks
   to make room, rather than the panel just overlaying whatever's
   underneath it. #map's own specificity (an ID) is enough to override the
   left/right/width set by .app-map above without !important. Only applied
   while the corresponding panel is actually open (mapWrap only ever
   carries lhs-pinned/rhs-pinned together with lhs-open/rhs-open - see
   setupPanelPin/closeLeftPanel/closeRightPanel).
   width must be overridden back to auto here: .app-map sets width:100% as
   its normal (unpinned) explicit width, and for an absolutely positioned
   box with left, width AND right all specified, width/left win and right
   is silently ignored - so left:434px alone did shift the box's left edge
   but left its width at a full 100% of the container, overflowing off the
   right instead of actually shrinking. auto lets the browser solve width
   from left+right instead, which is what should actually happen here. */
.app-map-wrap.lhs-pinned #map {
    /* 54px rail + 380px panel, matching .app-map-wrap.lhs-open .map-statusbar. */
    left: 434px;
    width: auto;
}

.app-map-wrap.rhs-pinned #map {
    /* 54px rail + 280px panel, matching .app-map-wrap.rhs-open .map-statusbar. */
    right: 334px;
    width: auto;
}

/* Toolbar overlaid on top of the map: the top-panel toggle on the left,
   zoom/locate/full-screen buttons grouped on the right. The search box is
   a separate floating overlay (.map-search-overlay below), not part of
   this row. */
.map-toolbar {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 50px;
    z-index: 10;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 12px;
    background: rgba(255, 255, 255, .92);
    border-bottom: 1px solid rgba(11, 31, 58, .08);
    box-shadow: 0 1px 4px rgba(11, 31, 58, .06);
}

.map-toolbar-actions {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}

/* Thin vertical divider between button groups (Home | zoom/locate/
   fullscreen | measurement tools) - a fixed-height span rather than a
   border on one of the buttons, so it reads as a separator between groups
   regardless of which buttons end up adjacent to it. */
.map-toolbar-separator {
    width: 1px;
    height: 20px;
    background: rgba(11, 31, 58, .15);
    flex-shrink: 0;
}

/* Every toolbar button (Pan, Home, Select, Zoom, Locate, Fullscreen,
   the measurement tools, Clear, Print, Save PNG) is the same size - was
   previously split between 32px (Pan/measurement tools) and a separate
   38px "-lg" variant (Home/Select/Zoom/Locate/Fullscreen), which read as
   inconsistent; unified to the larger size so the whole toolbar matches. */
.map-toolbar-btn {
    width: 38px;
    height: 38px;
    border-radius: 8px;
    border: 1px solid rgba(11, 31, 58, .14);
    background: rgba(11, 31, 58, .04);
    color: var(--navy, #0b1f3a);
    font-size: 16px;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    flex-shrink: 0;
}

.map-toolbar-btn svg {
    width: 21px;
    height: 21px;
}

.map-toolbar-btn:hover {
    background: rgba(11, 31, 58, .1);
}

/* Measurement tool buttons only - shows which one (if any) is currently
   active, matching the LHS rail's .active treatment. */
.map-toolbar-btn.active {
    background: rgba(201, 117, 77, .16);
    border-color: var(--terracotta, #c9754d);
    color: var(--terracotta-dark, #9d4e30);
}

/* Address search: a standalone floating control, top-center, below (not
   inside) the toolbar - see AddressSearchController/api/address/
   autocomplete.do, backed by the GNAF/Elasticsearch address index (see
   tools/gnaf/README.md). White background + rounded corners as asked,
   distinct from the toolbar's dark glass so it reads as its own control
   rather than a toolbar button group. */
.map-address-search {
    position: absolute;
    top: 62px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 10;
    width: 456px; /* 380px + 20% */
    max-width: calc(100% - 24px);
    transition: left .25s ease;
}

/* When a panel is pinned (docked - see .lhs-pinned/.rhs-pinned #map
   above), the visible map area is no longer the full width, so "centered"
   needs to mean centered within what's actually left of it, not the whole
   .app-map-wrap - otherwise the search box would visibly sit off-centre
   over the now-smaller map. Each shift is half of the corresponding
   pinned offset (434px/334px, both already used above), since shrinking
   the visible area by X on one side moves its centre by X/2. */
.app-map-wrap.lhs-pinned .map-address-search {
    left: calc(50% + 217px);
}

.app-map-wrap.rhs-pinned .map-address-search {
    left: calc(50% - 167px);
}

.app-map-wrap.lhs-pinned.rhs-pinned .map-address-search {
    left: calc(50% + 50px);
}

.map-address-search-input {
    box-sizing: border-box;
    width: 100%;
    border: none;
    border-radius: 999px;
    background: #fff;
    color: #17272d;
    padding: 12px 20px;
    font: 14px "DM Sans", sans-serif;
    box-shadow: 0 4px 18px rgba(0, 0, 0, .22);
    outline: 0;
}

.map-address-search-input:focus {
    box-shadow: 0 4px 18px rgba(0, 0, 0, .28), 0 0 0 2px var(--terracotta, #c9754d);
}

.map-address-search-results {
    list-style: none;
    margin: 6px 0 0;
    padding: 4px;
    max-height: 260px;
    overflow-y: auto;
    background: #fff;
    border-radius: 14px;
    box-shadow: 0 10px 28px rgba(0, 0, 0, .25);
}

.map-address-search-result {
    /* border is always reserved (transparent when not selected) so the
       1px border added on hover/selection below doesn't shift the row's
       size/position by 2px when it appears. */
    padding: 10px 14px;
    border: 1px solid transparent;
    border-radius: 10px;
    font: 13px "DM Sans", sans-serif;
    color: #17272d;
    cursor: pointer;
}

/* Alternating light blue rows, distinct from the terracotta brand accent
   used elsewhere - a deliberately different, cooler palette just for this
   results list, as asked. */
.map-address-search-result:nth-child(odd) {
    background: #eaf4fb;
}

.map-address-search-result:nth-child(even) {
    background: #ffffff;
}

/* Selected (keyboard Up/Down highlight, see addressSearchResults' JS) or
   hovered - a visible border around the row, on top of a slightly
   stronger blue fill so it reads clearly against either zebra stripe. */
.map-address-search-result:hover,
.map-address-search-result.map-address-search-result-active {
    background: #cfe8fa;
    border-color: #4a90c4;
}

/* "No address found" - not a real, clickable result, so no zebra fill,
   no hover/selection state, and a lighter/italic treatment to read as
   informational rather than an option to pick. */
.map-address-search-no-results {
    background: #fff !important;
    border-color: transparent !important;
    color: #6b7a80;
    font-style: italic;
    cursor: default;
}

/* Sliding side panels - anchored between the toolbar and the status bar,
   hidden off-canvas until .open is toggled on their edge tab. */
.map-side-panel {
    position: absolute;
    top: 50px;
    /* Touches the bottom of the map area, like the LHS icon rail - the
       status bar already shifts its left/right edge clear of whichever
       panel is open (see .app-map-wrap.lhs-open/.rhs-open below), so
       there's no need to leave a gap above it here too. */
    bottom: 0;
    width: 280px;
    max-width: 80%;
    z-index: 20;
    background: #fff;
    box-shadow: 0 0 24px rgba(0, 0, 0, .25);
    display: flex;
    flex-direction: column;
    transition: transform .25s ease;
}

.map-side-panel-left {
    /* Sits to the right of the 54px-wide LHS icon rail (.lhs-rail) rather
       than flush against the map's own edge. 100px wider than the base
       .map-side-panel width (280px) - the Layers panel's rows (toggle +
       name + type icon + more-options button, plus the opacity slider
       that can reveal underneath) need more room than the Basemap panel's
       one dropdown ever did. */
    left: 54px;
    width: 380px;
    transform: translateX(-100%);
}

.map-side-panel-left.open {
    transform: translateX(0);
}

.map-side-panel-right {
    /* Sits to the left of the 54px-wide RHS icon rail (.rhs-rail), mirroring
       .map-side-panel-left's own left:54px against the LHS rail. */
    right: 54px;
    transform: translateX(100%);
}

.map-side-panel-right.open {
    transform: translateX(0);
}

/* LHS/RHS icon rails: narrow, always-visible strips of icon buttons flush
   against the map's left/right edge, matching the Esri-style "icon rail
   expands a side panel" pattern. Spans the same vertical extent as the
   side panels themselves (below the toolbar, above the status bar) so it
   reads as part of the same overlay system. White/light-gray, matching
   home.do's overall colour scheme (see .map-toolbar above). */
.lhs-rail,
.rhs-rail {
    position: absolute;
    top: 50px;
    bottom: 0;
    z-index: 22;
    width: 54px;
    background: rgba(255, 255, 255, .96);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 10px 0;
    overflow-y: auto;
}

.lhs-rail {
    left: 0;
    border-right: 1px solid rgba(11, 31, 58, .08);
}

.rhs-rail {
    right: 0;
    border-left: 1px solid rgba(11, 31, 58, .08);
}

.lhs-rail-btn,
.rhs-rail-btn {
    position: relative;
    flex-shrink: 0;
    width: 42px;
    height: 42px;
    border: none;
    border-radius: 10px;
    background: transparent;
    color: rgba(11, 31, 58, .55);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}

.lhs-rail-btn svg,
.rhs-rail-btn svg {
    width: 22px;
    height: 22px;
}

.lhs-rail-btn:hover,
.rhs-rail-btn:hover {
    background: rgba(11, 31, 58, .06);
    color: var(--navy, #0b1f3a);
}

.lhs-rail-btn.active,
.rhs-rail-btn.active {
    background: rgba(201, 117, 77, .14);
    color: var(--terracotta-dark, #9d4e30);
}

/* Flush against the rail's own inner edge (the button sits centered in the
   54px rail, 6px in from each side) - matches the reference design's
   selected-icon accent bar. */
.lhs-rail-btn.active::before,
.rhs-rail-btn.active::before {
    content: "";
    position: absolute;
    top: 6px;
    bottom: 6px;
    width: 3px;
    background: var(--terracotta, #c9754d);
}

.lhs-rail-btn.active::before {
    left: -6px;
    border-radius: 0 3px 3px 0;
}

.rhs-rail-btn.active::before {
    right: -6px;
    border-radius: 3px 0 0 3px;
}

.map-side-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    border-bottom: 1px solid #e5e5e5;
    font: 600 14px "Manrope", sans-serif;
    color: var(--navy, #0b1f3a);
}

.map-side-panel-header-actions {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-shrink: 0;
}

.map-side-panel-close {
    border: none;
    background: none;
    font-size: 20px;
    line-height: 1;
    color: #888;
    cursor: pointer;
}

/* Pin button - docks the panel (see .lhs-pinned/.rhs-pinned #map above)
   instead of leaving it as a floating overlay. */
.map-side-panel-pin-btn {
    border: none;
    background: none;
    padding: 0;
    width: 18px;
    height: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #999;
    cursor: pointer;
}

.map-side-panel-pin-btn svg {
    width: 16px;
    height: 16px;
}

.map-side-panel-pin-btn:hover {
    color: var(--navy, #0b1f3a);
}

.map-side-panel-pin-btn[aria-pressed="true"] {
    color: var(--terracotta, #c9754d);
}

.map-side-panel-body {
    padding: 16px;
    overflow-y: auto;
    font: 14px "DM Sans", sans-serif;
    color: #666;
}

/* Basemap switcher, at the top of the right panel's body. */
.map-basemap-switcher {
    margin-bottom: 12px;
}

.map-basemap-switcher label {
    display: block;
    font: 600 12px "Manrope", sans-serif;
    color: var(--navy, #0b1f3a);
    margin-bottom: 4px;
}

/* Layers panel look (also the Favorites list, which reuses .map-tree): a
   light, flat list in the style of Google My Maps / ArcGIS Online. Groups
   are plain bold headings with a layer count; each layer row reads
   [type swatch] name ... [eye] [more]. The on/off switch is restyled as an
   eye icon (open = on the map, struck through = hidden) and moved to the
   right, and hidden layers are greyed out. The drag grip, star and more-
   options appear on hover (pointer devices only). Purely visual: every
   element the tree JS builds and listens on is unchanged, only reordered
   with flex `order` - .map-tree-leaf-icons is display: contents so its
   children line up in the row itself. */

/* Search box used both for the layer tree and the site-search panel
   section - icon sits on the right. */
.map-tree-search-wrap {
    position: relative;
    margin-bottom: 12px;
}

.map-tree-search {
    width: 100%;
    height: 36px;
    border: 1px solid transparent;
    border-radius: 8px;
    background: #f1f3f5;
    color: var(--navy, #0b1f3a);
    padding: 0 36px 0 12px;
    font: 13.5px "DM Sans", sans-serif;
    outline: 0;
    transition: border-color .15s ease, background .15s ease, box-shadow .15s ease;
}

.map-tree-search::placeholder {
    color: #8a96a3;
}

.map-tree-search:focus {
    background: #fff;
    border-color: var(--teal, #1a9c86);
    box-shadow: 0 0 0 3px rgba(26, 156, 134, .15);
}

.map-tree-search-icon {
    position: absolute;
    top: 50%;
    right: 12px;
    transform: translateY(-50%);
    width: 16px;
    height: 16px;
    color: #8a96a3;
    pointer-events: none;
}

/* Collapsible layer tree. */
.map-tree,
.map-tree ul {
    list-style: none;
    margin: 0;
    padding: 0;
}

.map-tree-group {
    padding: 4px 0;
}

.map-tree-group + .map-tree-group {
    border-top: 1px solid #eef1f4;
}

/* Group heading: [caret] Name (count) ............ [eye] */
.map-tree-group-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 6px 6px 2px;
    border-radius: 8px;
}

.map-tree-group-row:hover {
    background: #f4f6f8;
}

.map-tree-group-name {
    order: 1;
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font: 600 13.5px "DM Sans", sans-serif;
    color: var(--navy, #0b1f3a);
}

.map-tree-group-count {
    order: 2;
    flex-shrink: 0;
    margin-right: auto;
    min-width: 20px;
    height: 18px;
    padding: 0 6px;
    border-radius: 999px;
    background: #eef1f4;
    color: #5b6b7b;
    font: 600 11px "DM Sans", sans-serif;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.map-tree-group-row > .map-toggle {
    order: 3;
}

/* The folder glyph on a group row adds nothing the heading doesn't say. */
.map-tree-group-row .map-tree-leaf-icons {
    display: none;
}

.map-tree-toggle {
    flex-shrink: 0;
    width: 24px;
    height: 24px;
    border: none;
    border-radius: 6px;
    background: none;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #8a96a3;
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
}

.map-tree-toggle:hover {
    background: #e8edf2;
    color: var(--navy, #0b1f3a);
}

.map-tree-caret {
    width: 16px;
    height: 16px;
    transition: transform .15s ease;
}

.map-tree-toggle[aria-expanded="false"] .map-tree-caret {
    transform: rotate(-90deg);
}

/* Eye toggle - the same .map-toggle switch the Settings panel uses
   (hidden <input> + .map-toggle-track), redrawn only inside the tree as
   an eye icon via a CSS mask: struck-through grey eye when the layer is
   hidden, open teal eye when it's on, a paler teal eye for a group whose
   layers are only partly on (indeterminate). */
.map-tree .map-toggle {
    width: 26px;
    height: 26px;
}

.map-tree .map-toggle-track,
.map-tree .map-toggle input:checked + .map-toggle-track,
.map-tree .map-toggle input:indeterminate + .map-toggle-track {
    border-radius: 6px;
    background: transparent;
}

.map-tree .map-toggle:hover .map-toggle-track {
    background: #e8edf2;
}

.map-tree .map-toggle-track::before,
.map-tree .map-toggle input:checked + .map-toggle-track::before {
    top: 5px;
    left: 5px;
    width: 16px;
    height: 16px;
    border-radius: 0;
    box-shadow: none;
    transform: none;
    background: #9aa5b1;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9.9 4.24A9.1 9.1 0 0 1 12 4c7 0 10 8 10 8a13.2 13.2 0 0 1-1.67 2.68'/%3E%3Cpath d='M6.61 6.61A13.5 13.5 0 0 0 2 12s3 8 10 8a9.7 9.7 0 0 0 5.39-1.61'/%3E%3Cpath d='M14.12 14.12a3 3 0 1 1-4.24-4.24'/%3E%3Cline x1='2' y1='2' x2='22' y2='22'/%3E%3C/svg%3E") center / 16px no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9.9 4.24A9.1 9.1 0 0 1 12 4c7 0 10 8 10 8a13.2 13.2 0 0 1-1.67 2.68'/%3E%3Cpath d='M6.61 6.61A13.5 13.5 0 0 0 2 12s3 8 10 8a9.7 9.7 0 0 0 5.39-1.61'/%3E%3Cpath d='M14.12 14.12a3 3 0 1 1-4.24-4.24'/%3E%3Cline x1='2' y1='2' x2='22' y2='22'/%3E%3C/svg%3E") center / 16px no-repeat;
}

.map-tree .map-toggle input:checked + .map-toggle-track::before,
.map-tree .map-toggle input:indeterminate + .map-toggle-track::before {
    background: var(--teal, #1a9c86);
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 12s3.5-8 10-8 10 8 10 8-3.5 8-10 8S2 12 2 12z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E") center / 16px no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 12s3.5-8 10-8 10 8 10 8-3.5 8-10 8S2 12 2 12z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E") center / 16px no-repeat;
}

.map-tree .map-toggle input:indeterminate + .map-toggle-track::before {
    opacity: .55;
}

/* Top-nav language switcher (index.html/login.html header) - a plain,
   dependency-free <select> rather than a custom mega-menu-style dropdown,
   matching the pattern already used on login.html's own language picker. */
.lang-switcher {
    appearance: none;
    -webkit-appearance: none;
    background-color: rgba(255, 255, 255, .12);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m8 10 4 4 4-4'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 14px center;
    background-size: 12px;
    border: 1px solid rgba(255, 255, 255, .3);
    border-radius: 999px;
    color: #fff;
    cursor: pointer;
    font: 600 13px "DM Sans", sans-serif;
    min-height: 46px;
    padding: 10px 34px 10px 18px;
}

.lang-switcher:hover {
    background-color: rgba(255, 255, 255, .2);
}

.lang-switcher option {
    color: var(--navy, #1b2b32);
}

@media (max-width: 1080px) {
    .header-action .lang-switcher {
        display: none;
    }
}

/* Mobile equivalent, shown inside the offcanvas menu instead. */
.lang-switcher-mobile {
    appearance: none;
    -webkit-appearance: none;
    background-color: var(--sand-2, #f3e9dc);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231b2b32' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m8 10 4 4 4-4'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 14px center;
    background-size: 12px;
    border: 1px solid var(--line, #e4d7c4);
    border-radius: 10px;
    color: var(--navy, #1b2b32);
    cursor: pointer;
    font: 600 14px "DM Sans", sans-serif;
    padding: 12px 34px 12px 16px;
    width: 100%;
}


/* Modern toggle switch (replaces the old plain checkbox) - the <input> is
   visually hidden but stays in the DOM and keeps driving all the normal
   checked/change/:checked behavior everything else listens for. */
.map-toggle {
    flex-shrink: 0;
    position: relative;
    display: inline-block;
    width: 30px;
    height: 18px;
    cursor: pointer;
}

.map-toggle input:focus-visible + .map-toggle-track {
    box-shadow: 0 0 0 3px rgba(26, 156, 134, .25);
}

.map-toggle input {
    position: absolute;
    inset: 0;
    margin: 0;
    opacity: 0;
    cursor: pointer;
}

.map-toggle-track {
    position: absolute;
    inset: 0;
    border-radius: 999px;
    background: #cfd6de;
    transition: background .15s ease, box-shadow .15s ease;
}

.map-toggle-track::before {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 2px rgba(16, 24, 40, .25);
    transition: transform .15s ease;
}

.map-toggle input:checked + .map-toggle-track {
    background: var(--teal, #1a9c86);
}

.map-toggle input:checked + .map-toggle-track::before {
    transform: translateX(12px);
}

.map-toggle input:indeterminate + .map-toggle-track {
    background: rgba(26, 156, 134, .5);
}

.map-tree-leaf {
    font: 13px "DM Sans", sans-serif;
}

/* Layer row: [type swatch] name ... [star] [eye] [download] [more], with
   the drag grip floating in the indent on the left. */
.map-tree-leaf-row {
    position: relative;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 4px 4px 30px;
    border-radius: 8px;
    transition: background .12s ease;
}

.map-tree-leaf-row:hover {
    background: #f4f6f8;
}

.map-tree-leaf-expanded .map-tree-leaf-row {
    background: #f4f6f8;
    border-radius: 8px 8px 0 0;
}

.map-tree-leaf-name {
    order: 1;
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: #8a96a3;
    transition: color .12s ease;
}

.map-tree-leaf-row:has(.map-layer-checkbox:checked) .map-tree-leaf-name {
    color: var(--navy, #0b1f3a);
    font-weight: 500;
}

.map-tree-leaf-icons {
    display: contents;
    color: #8a96a3;
}

.map-tree-icon {
    width: 16px;
    height: 16px;
}

/* Geometry-type icon as a small swatch tile at the start of the row -
   teal-tinted while the layer is on, grey while it's hidden. */
.map-tree-leaf-icons > svg.map-tree-icon {
    order: 0;
    flex-shrink: 0;
    box-sizing: border-box;
    width: 24px;
    height: 24px;
    padding: 4px;
    border-radius: 6px;
    background: #eef1f4;
    color: #9aa5b1;
    transition: background .12s ease, color .12s ease;
}

.map-tree-leaf-row:has(.map-layer-checkbox:checked) .map-tree-leaf-icons > svg.map-tree-icon {
    background: rgba(26, 156, 134, .12);
    color: var(--teal, #1a9c86);
}

.map-tree-leaf-row > .map-toggle {
    order: 3;
}

.map-tree-star-btn {
    order: 2;
}

.map-tree-kml-btn {
    order: 4;
}

.map-tree-more-btn {
    order: 5;
}

/* Drag handle (see leafLi.draggable in home.html) - a visual affordance
   only, since the whole row is draggable, not just this icon; floats in
   the row's left indent. */
.map-tree-grip {
    position: absolute;
    left: 8px;
    top: 50%;
    transform: translateY(-50%);
    width: 14px;
    color: #b4bdc7;
    cursor: grab;
}

.map-tree-leaf-dragging {
    opacity: .4;
}

.map-tree-leaf-dragging .map-tree-grip {
    cursor: grabbing;
}

.map-tree-more-btn,
.map-tree-kml-btn,
.map-tree-star-btn {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border: none;
    border-radius: 6px;
    background: none;
    padding: 0;
    color: #8a96a3;
    cursor: pointer;
    transition: background .12s ease, color .12s ease, opacity .12s ease;
}

.map-tree-more-btn:hover,
.map-tree-kml-btn:hover,
.map-tree-star-btn:hover {
    background: #e8edf2;
    color: var(--navy, #0b1f3a);
}

.map-tree-more-btn:focus-visible,
.map-tree-kml-btn:focus-visible,
.map-tree-star-btn:focus-visible {
    outline: 2px solid var(--teal, #1a9c86);
    outline-offset: 1px;
}

/* Quiet rows until hovered: grip, star (unless starred), download and
   more-options only show on hover/focus, on devices that can hover. The
   swatch and eye always stay - they're the row's state, not actions. */
@media (hover: hover) {
    .map-tree-grip,
    .map-tree-more-btn,
    .map-tree-kml-btn,
    .map-tree-star-btn[aria-pressed="false"] {
        opacity: 0;
    }

    .map-tree-leaf-row:hover .map-tree-grip,
    .map-tree-leaf-row:hover .map-tree-more-btn,
    .map-tree-leaf-row:hover .map-tree-kml-btn,
    .map-tree-leaf-row:hover .map-tree-star-btn,
    .map-tree-leaf-row:focus-within .map-tree-more-btn,
    .map-tree-leaf-row:focus-within .map-tree-kml-btn,
    .map-tree-leaf-row:focus-within .map-tree-star-btn,
    .map-tree-leaf-expanded .map-tree-more-btn {
        opacity: 1;
    }
}

.map-tree-star-btn[aria-pressed="true"] {
    color: var(--terracotta, #c9754d);
}

.map-tree-star-btn[aria-pressed="true"] .map-tree-star {
    fill: currentColor;
}

/* Per-layer opacity slider, revealed under a leaf row when its three-dot
   button is clicked (see .map-tree-leaf-expanded) - joined to the row
   above it as one shaded block, aligned with the layer name. */
.map-tree-opacity {
    display: none;
    align-items: center;
    gap: 10px;
    padding: 2px 12px 10px 62px;
    background: #f4f6f8;
    border-radius: 0 0 8px 8px;
}

.map-tree-leaf-expanded .map-tree-opacity {
    display: flex;
}

.map-tree-opacity label {
    flex-shrink: 0;
    font: 600 10.5px "DM Sans", sans-serif;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: #6b7886;
}

.map-opacity-slider {
    flex: 1 1 auto;
    accent-color: var(--teal, #1a9c86);
}

/* Legend panel section. */
.legend-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.legend-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 2px;
    color: var(--navy, #0b1f3a);
}

.legend-swatch {
    flex-shrink: 0;
    width: 18px;
    height: 18px;
    border-radius: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.legend-swatch-vector {
    background: rgba(192, 57, 43, .18);
    border: 2px solid #c0392b;
}

.legend-swatch-img {
    max-width: 100%;
    max-height: 100%;
}

.legend-empty {
    color: rgba(11, 31, 58, .5);
    font-size: 13px;
}

.map-tree-hidden {
    display: none;
}

/* Progress bar, bottom center of the map, just above the status bar -
   visible only while tiles are actively loading (zoom, pan, basemap
   switch). */
.map-progress {
    position: absolute;
    bottom: 33px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 12;
    width: 160px;
    height: 4px;
    border-radius: 2px;
    background: rgba(255, 255, 255, .35);
    overflow: hidden;
    opacity: 0;
    transition: opacity .2s ease, left .25s ease;
    pointer-events: none;
}

/* Re-centred on the visible strip of map between whichever side panels are
   open (same 434px/334px edges as .map-statusbar below): the midpoint
   shifts by half of the extra width each open panel covers beyond its
   54px rail. */
.app-map-wrap.lhs-open .map-progress {
    left: calc(50% + 190px);
}

.app-map-wrap.rhs-open .map-progress {
    left: calc(50% - 140px);
}

.app-map-wrap.lhs-open.rhs-open .map-progress {
    left: calc(50% + 50px);
}

.map-progress.active {
    opacity: 1;
}

.map-progress-bar {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 40%;
    border-radius: 2px;
    background: var(--navy, #0b1f3a);
    animation: map-progress-slide 1s ease-in-out infinite;
}

@keyframes map-progress-slide {
    0% {
        left: -40%;
    }
    100% {
        left: 100%;
    }
}

/* Coordinate readout, bottom edge of the map ("BSB" - bottom status bar) -
   translucent white now (was translucent navy), matching home.do's
   white/light-gray colour scheme, so it stays legible without covering
   much of the map underneath. Its left/right edges stay clear of the LHS/
   RHS icon rails at all times (both rails now run the full height of the
   map, touching the bottom edge - see .lhs-rail/.rhs-rail) and shift in
   further still when a side panel is open (.app-map-wrap.lhs-open/
   .rhs-open, toggled by the rail-click handling in home.html). Same
   transition timing as the panels themselves so it visually moves in step
   with them. */
.map-statusbar {
    position: absolute;
    bottom: 0;
    left: 54px;
    right: 54px;
    height: 25px;
    z-index: 10;
    background: rgba(255, 255, 255, .85);
    color: var(--navy, #0b1f3a);
    /* Slightly smaller than most of the app's UI text - the three
       coordinate groups together (Lat/Lon, GDA2020, Easting/Northing) run
       long, and this is a live-updating readout rather than content
       someone needs to select/read character-by-character. */
    font: 11px "DM Sans", sans-serif;
    line-height: 25px;
    padding: 0 12px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    pointer-events: none;
    transition: left .25s ease, right .25s ease;
}

.app-map-wrap.lhs-open .map-statusbar {
    /* 54px rail + 380px panel. */
    left: 434px;
}

.app-map-wrap.rhs-open .map-statusbar {
    /* 54px rail + 280px panel. */
    right: 334px;
}

/* OpenLayers' scale bar defaults to bottom:8px/left:8px, which would sit
   under the 25px status bar and behind the LHS icon rail - nudge it up and
   right to clear both. */
.ol-scale-line {
    bottom: 33px;
    left: 62px;
}

/* Measurement tool tooltips (see the measure* functions in home.html) - a
   floating label that follows the sketch while drawing (plain terracotta-
   on-navy), then freezes as a small pointer-topped callout (inverted, sand-
   on-terracotta) once the shape is finished, visually distinct from the
   "still drawing" state. */
/* Sits directly on the measured line/edge, rotated (via an inline
   transform: rotate(), set in JS - see labelPlacementForSegment in
   home.html) to follow that segment's own angle, rather than floating
   above a fixed point - no arrow/pointer needed any more since the label
   IS the thing it's labelling, not a callout pointing at it. */
.measure-tooltip {
    position: relative;
    background: rgba(11, 31, 58, .9);
    color: #fff;
    border-radius: 4px;
    padding: 3px 8px;
    font: 600 12px "DM Sans", sans-serif;
    white-space: nowrap;
    pointer-events: none;
}

.measure-tooltip-static {
    background: rgba(201, 117, 77, .92);
}

/* Rectangle tool's per-side length labels - same idea as .measure-tooltip
   but smaller, so four of them (one per edge) plus the area total don't
   visually overwhelm a small rectangle. */
.measure-tooltip-edge {
    padding: 1px 6px;
    font-size: 10px;
}

/* Mobile layout: side panels go near-full-width instead of a fixed 380px/
   280px (which would either overflow a phone screen or leave barely any
   map visible beside it), toolbar buttons wrap onto a second row instead
   of overflowing off-screen now that there are nine of them, and the
   status bar is allowed to wrap onto multiple lines - showing all five
   coordinate groups in full is more useful on a device than silently
   ellipsis-truncating most of them, which is what happens at this width
   with the desktop single-line layout. */
@media (max-width: 760px) {
    .map-side-panel {
        width: calc(100% - 54px);
        max-width: none;
    }

    .map-side-panel-left {
        width: calc(100% - 54px);
    }

    .map-toolbar {
        height: auto;
        min-height: 50px;
        flex-wrap: wrap;
        padding: 6px 10px;
    }

    .map-toolbar-btn {
        width: 36px;
        height: 36px;
    }

    /* The toolbar wraps to two rows at this width (see .map-toolbar
       above), so a fixed offset that clears the desktop single-row
       toolbar isn't enough here - pushed down further and narrowed so it
       reliably sits below the wrapped toolbar instead of overlapping it. */
    .map-address-search {
        top: 108px;
        width: calc(100% - 24px);
    }

    .map-statusbar {
        height: auto;
        min-height: 25px;
        line-height: 1.5;
        white-space: normal;
        overflow: visible;
        text-overflow: clip;
        padding: 4px 10px;
        font-size: 10px;
    }

    /* A side panel covers the whole map up to the rail here, so there's no
       narrower visible strip to re-centre on - stay at the map's centre. */
    .app-map-wrap.lhs-open .map-progress,
    .app-map-wrap.rhs-open .map-progress,
    .app-map-wrap.lhs-open.rhs-open .map-progress {
        left: 50%;
    }

    .app-map-wrap.lhs-open .map-statusbar {
        /* The side panel already covers the full width up to the rail on
           mobile (see .map-side-panel-left above), so there's no sliver of
           map left for the status bar to sit beside - hide it rather than
           overlapping the open panel. */
        display: none;
    }
}

/* Draw panel (LHS rail) - geometry-type buttons, then the fill/stroke
   style controls, then Save Custom Layer/Reset. Seven tool buttons now
   (Point/Line/Polygon/Freehand/Circle/Rectangle/Square) - flex instead of
   the old 3-column grid, each button shrunk down so all seven fit on one
   row instead of wrapping to a second one. */
.map-draw-tools {
    display: flex;
    flex-wrap: nowrap;
    gap: 4px;
    padding: 14px 16px 4px;
}

.map-draw-tool-btn {
    flex: 1 1 0;
    min-width: 0;
    height: 32px;
    border-radius: 7px;
    border: 1px solid rgba(11, 31, 58, .16);
    background: rgba(11, 31, 58, .03);
    color: rgba(11, 31, 58, .75);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}

.map-draw-tool-btn svg {
    width: 15px;
    height: 15px;
}

.map-draw-tool-btn:hover {
    background: rgba(11, 31, 58, .1);
    color: var(--navy, #0b1f3a);
}

.map-draw-tool-btn.active {
    background: var(--terracotta, #c9754d);
    border-color: var(--terracotta, #c9754d);
    color: #fff;
}

.map-draw-style {
    padding: 12px 16px;
    border-top: 1px solid rgba(11, 31, 58, .1);
    border-bottom: 1px solid rgba(11, 31, 58, .1);
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.map-draw-style-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    font-size: 13px;
    color: rgba(11, 31, 58, .8);
}

.map-draw-style-row input[type="color"] {
    width: 36px;
    height: 26px;
    padding: 0;
    border: 1px solid rgba(11, 31, 58, .25);
    border-radius: 6px;
    background: none;
    cursor: pointer;
}

.map-draw-style-row select {
    width: auto;
    background-color: #fff;
    color: var(--navy, #0b1f3a);
    border-color: rgba(11, 31, 58, .25);
}

/* Save Custom Layer + Reset, side by side (Reset offers a confirm modal -
   see drawResetConfirmModal in home.html - before it clears anything). */
.map-draw-actions {
    display: flex;
    gap: 8px;
    margin: 14px 16px 0;
}

.map-draw-save-btn,
.map-draw-reset-btn {
    flex: 1 1 0;
    margin: 0;
}

/* Layer Details panel (LHS rail) - one card per currently-visible layer. */
.map-details-list {
    list-style: none;
    margin: 0;
    padding: 8px 16px;
}

.map-details-item {
    padding: 10px 0;
    border-bottom: 1px solid rgba(11, 31, 58, .12);
}

.map-details-item:last-child {
    border-bottom: none;
}

.map-details-item-heading {
    font: 600 14px "Manrope", sans-serif;
    color: var(--navy, #0b1f3a);
    margin-bottom: 4px;
}

.map-details-item-row {
    display: flex;
    gap: 6px;
    font-size: 12px;
    color: rgba(11, 31, 58, .65);
}

.map-details-item-label {
    font-weight: 600;
    flex-shrink: 0;
    color: rgba(11, 31, 58, .9);
}

/* Settings panel (LHS rail) - currently just the default-zoom-on-login
   address field (see #defaultZoomAddressInput in home.html). */
.map-settings-label {
    display: block;
    font: 600 12px "Manrope", sans-serif;
    color: var(--navy, #0b1f3a);
    margin-bottom: 4px;
}

.map-settings-hint {
    margin: 0 0 12px;
    font-size: 12px;
    color: rgba(11, 31, 58, .55);
}

/* Reuses .map-address-search-result/.map-address-search-no-results for
   the row styling (neither sets its own position, only their old parent
   .map-address-search-results did) - just a plain in-flow list here
   instead of that one's floating-over-the-map positioning. */
.map-settings-address-results {
    list-style: none;
    margin: 8px 0 0;
    padding: 4px;
    max-height: 220px;
    overflow-y: auto;
    background: #fff;
    border: 1px solid rgba(11, 31, 58, .12);
    border-radius: 10px;
}

/* Set/Clear, side by side - same look as .map-draw-actions (Save Custom
   Layer/Reset in the Draw panel): exactly one is ever enabled at a time
   (see syncDefaultZoomButtons in home.html), the other just sits greyed
   out via the browser's own default :disabled treatment. */
.map-settings-actions {
    display: flex;
    gap: 8px;
    /* Bottom margin (not just top) - room below the buttons before the
       Pin toggles start, rather than those two sections crowding
       together. */
    margin: 10px 0 18px;
}

.map-settings-set-btn,
.map-settings-clear-btn {
    flex: 1 1 0;
    margin: 0;
}

/* Pin left/right panel toggles. Only the FIRST row gets the divider
   (separating the whole toggle group from the address field/buttons
   above) - both rows used to carry border-top, which put a second,
   redundant line directly between the two toggles themselves.
   :first-of-type doesn't work here (it matches the first <div> among ALL
   div siblings sharing this parent, not the first div specifically
   carrying this class - .map-settings-actions above is also a <div> and
   already claims that slot) - the adjacent-sibling combinator below reads
   as "any row immediately preceded by another row", which is exactly (and
   only) the second one. */
.map-settings-toggle-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 10px 0;
    border-top: 1px solid rgba(11, 31, 58, .1);
    font-size: 13px;
    color: rgba(11, 31, 58, .8);
}

.map-settings-toggle-row + .map-settings-toggle-row {
    border-top: none;
}

/* Layers / Layer details / Settings (LHS panel) typeface: Inter, a neutral
   UI face designed for dense interface text, replacing the Manrope
   (headings, group names, labels) + DM Sans (body) mix these sections used
   to have - one family, with weight alone carrying the hierarchy. Only
   font-family is overridden, so every rule above keeps its own size and
   weight; the descendant selectors outrank those single-class rules. The
   panel header is shared by every LHS section, so it changes with them. */
.map-side-panel-left .map-side-panel-header,
.lhs-panel-section[data-panel-section="layers"],
.lhs-panel-section[data-panel-section="layers"] *,
.lhs-panel-section[data-panel-section="details"],
.lhs-panel-section[data-panel-section="details"] *,
.lhs-panel-section[data-panel-section="settings"],
.lhs-panel-section[data-panel-section="settings"] * {
    font-family: "Inter", "Segoe UI", system-ui, sans-serif;
    letter-spacing: -0.005em;
}

/* Tippy.js custom "chalk" theme (see initTooltips() in home.html) - a
   dark chalkboard-slate bubble with white text, following Tippy's own
   documented custom-theme pattern (a .tippy-box[data-theme~='name'] rule
   plus one per-placement arrow-colour rule) rather than one of its
   bundled theme stylesheets. */
.tippy-box[data-theme~='chalk'] {
    background-color: #36454f;
    color: #fff;
    font: 500 12px "DM Sans", sans-serif;
}

.tippy-box[data-theme~='chalk'][data-placement^='top'] > .tippy-arrow::before {
    border-top-color: #36454f;
}

.tippy-box[data-theme~='chalk'][data-placement^='bottom'] > .tippy-arrow::before {
    border-bottom-color: #36454f;
}

.tippy-box[data-theme~='chalk'][data-placement^='left'] > .tippy-arrow::before {
    border-left-color: #36454f;
}

.tippy-box[data-theme~='chalk'][data-placement^='right'] > .tippy-arrow::before {
    border-right-color: #36454f;
}

/* Top logo bar's brand mark, recoloured to navy for home.do specifically
   (scoped to .app-body, only ever set on home.html's <body> - every other
   page keeps the shared SVG file's own cream/sand colour, appropriate for
   their navy header). A <span> with a CSS mask (not an <img src="...svg">
   the way every other page still renders it) - masking is how a single-
   colour SVG gets recoloured via CSS without forking the shared file
   itself: background-color supplies the actual colour, and the SVG (via
   mask-image) only ever controls which pixels are visible, not what
   colour they are. Sized to the SVG's own aspect ratio (407.25 x 93.75)
   at the existing 40px logo height. */
.app-body .brand-logo-navy {
    display: inline-block;
    width: 174px;
    height: 40px;
    background-color: var(--navy, #0b1f3a);
    -webkit-mask-image: url("../vendor/eightysevenpins/images/eightysevenpins-logo.svg");
    mask-image: url("../vendor/eightysevenpins/images/eightysevenpins-logo.svg");
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-position: left center;
    mask-position: left center;
}

/* Basemap radio group (RHS panel) - replaces the old <select>. */
.map-basemap-radio-group {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.map-basemap-radio-row {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 13px;
    color: var(--navy, #0b1f3a);
    cursor: pointer;
}

.map-basemap-radio-row input[type="radio"] {
    accent-color: var(--terracotta, #c9754d);
    width: 16px;
    height: 16px;
    margin: 0;
    cursor: pointer;
}

.map-basemap-radio-row-disabled {
    color: rgba(11, 31, 58, .4);
    cursor: not-allowed;
}

.map-basemap-radio-row-disabled input[type="radio"] {
    cursor: not-allowed;
}

/* Admin section (admin-users.html/admin-layers.html/admin-address-
   search.html) - same header as home.do (.app-body/.app-header/
   .brand-logo-navy/.header-icon-btn/.header-lang-switcher, all reused
   as-is, not redefined here) plus a persistent left sidebar replacing the
   old plain Bootstrap navbar-dark. .admin-shell mirrors .app-map-wrap's
   own "fills the rest of the viewport below the header" flex role, just
   for a sidebar+content layout instead of a map. */
.admin-shell {
    position: relative;
    flex: 1 1 auto;
    width: 100%;
    min-height: 480px;
    display: flex;
}

.admin-sidebar {
    flex: 0 0 auto;
    width: 240px;
    background: #fff;
    border-right: 1px solid rgba(11, 31, 58, .08);
    padding: 20px 0;
    overflow-y: auto;
}

.admin-sidebar-link {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 22px;
    font: 600 14px "Manrope", sans-serif;
    color: rgba(11, 31, 58, .68);
    text-decoration: none;
    border-left: 3px solid transparent;
}

.admin-sidebar-link svg {
    width: 19px;
    height: 19px;
    flex-shrink: 0;
}

.admin-sidebar-link:hover {
    background: rgba(11, 31, 58, .04);
    color: var(--navy, #0b1f3a);
}

.admin-sidebar-link.active {
    background: rgba(201, 117, 77, .1);
    border-left-color: var(--terracotta, #c9754d);
    color: var(--terracotta-dark, #9d4e30);
}

.admin-content {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 32px;
    background: #f7f8f9;
}

.admin-content h4 {
    color: var(--navy, #0b1f3a);
    font-family: "Manrope", sans-serif;
}

.admin-content .card {
    border: 1px solid rgba(11, 31, 58, .1);
    box-shadow: none;
}

.admin-content .card-header {
    background: #fff;
    font: 600 14px "Manrope", sans-serif;
    color: var(--navy, #0b1f3a);
    border-bottom: 1px solid rgba(11, 31, 58, .1);
}

@media (max-width: 760px) {
    .admin-shell {
        flex-direction: column;
    }

    .admin-sidebar {
        width: 100%;
        border-right: none;
        border-bottom: 1px solid rgba(11, 31, 58, .08);
        padding: 8px 0;
    }
}

/* Legal pages (privacy / terms / security) + footer legal links */
.footer-legal { display: flex; gap: 18px; flex-wrap: wrap; }
.footer-legal a { color: rgba(255,255,255,.72); transition: .25s; }
.footer-legal a:hover { color: #fff; }
.legal-content { }
.legal-content h2 { margin: 36px 0 12px; font-size: 22px; }
.legal-content h2:first-of-type { margin-top: 8px; }
.legal-content h3 { margin: 22px 0 8px; font-size: 17px; }
.legal-content p, .legal-content li { color: var(--muted); line-height: 1.75; }
.legal-content ul { margin: 0 0 16px; padding-left: 20px; }
.legal-content li { margin-bottom: 6px; }
.legal-updated { font-size: 13px; color: var(--muted); margin-bottom: 6px; }
.legal-note { font-size: 13px; font-style: italic; margin-bottom: 20px; }
/* Footer disclaimer + "Made with <heart> in Melbourne" */
.footer-disclaimer { border-top: 1px solid rgba(255,255,255,.08); }
.footer-disclaimer .container { padding-top: 22px; padding-bottom: 22px; }
.footer-disclaimer p { font-size: 12px; line-height: 1.7; color: rgba(255,255,255,.5); margin: 0; max-width: 960px; }
.footer-tagline { display: inline-flex; align-items: center; gap: 5px; }
.footer-heart { color: #e2674a; vertical-align: -2px; }
/* Refined, professional buttons */
.btn { min-height: 50px; padding: 0 26px; border-radius: 10px; font-weight: 600; letter-spacing: .01em; }
.btn::before { display: none; }
.btn-primary { background: linear-gradient(135deg, var(--terracotta), var(--terracotta-dark)); box-shadow: 0 8px 20px rgba(157,78,48,.22); }
.btn-primary:hover { background: var(--terracotta-dark); transform: translateY(-2px); box-shadow: 0 12px 26px rgba(157,78,48,.30); }
.btn-light { background:#fff; box-shadow: 0 6px 18px rgba(7,22,28,.10), inset 0 0 0 1px rgba(23,39,45,.10); }
.btn-light:hover { background:#fff; transform: translateY(-2px); box-shadow: 0 10px 24px rgba(7,22,28,.16); }
.header-action .btn { min-height: 44px; border-radius: 9px; }

/* Technology partner tiles (typographic wordmark wall; swap in official SVGs when available) */
.partner-grid { display:grid; grid-template-columns: repeat(auto-fit, minmax(150px,1fr)); gap:14px; }
.partner-tile { display:flex; align-items:center; justify-content:center; min-height:84px; padding:16px; border:1px solid var(--line); border-radius:14px; background:#fff; font:700 18px 'Manrope',sans-serif; color:var(--navy); letter-spacing:-.01em; text-align:center; transition:.25s; }
.partner-tile:hover { border-color: var(--terracotta); box-shadow: 0 10px 24px rgba(7,22,28,.08); transform: translateY(-2px); }
.partner-tile img { max-height:40px; max-width:140px; }

/* Feature bullet lists on service/industry pages */
.feature-points { list-style:none; margin:24px 0 0; padding:0; display:grid; gap:12px; }
.feature-points li { position:relative; padding-left:30px; line-height:1.65; color:var(--muted); }
.feature-points li::before { content:""; position:absolute; left:0; top:7px; width:14px; height:14px; border-radius:50%; background:var(--terracotta); box-shadow:0 0 0 4px rgba(201,117,77,.14); }

/* Vacancy list (careers) */
.vacancy { border:1px solid var(--line); border-radius:14px; padding:20px 22px; background:#fff; margin-bottom:14px; }
.vacancy h3 { margin:0 0 4px; font-size:18px; }
.vacancy .vacancy-loc { font-size:13px; color:var(--muted); margin-bottom:8px; display:block; }

/* Mobile hero: give the copy/actions breathing room so the Learn More
   button is not flush against the bottom edge of the viewport. */
@media (max-width: 768px) {
    .hero-video-inner { padding-top: 104px; padding-bottom: 76px; }
}
/* ---- IBM Plex (IBM's open-source typeface, SIL OFL) as the primary font ---- */
body { font-family: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif; }
h1, h2, h3, h4, h5, h6,
.btn, .eyebrow, .brand, .nav-links a, .mega-link strong, .mega-link small,
.premium-card h3, .footer h4, .lead,
input, select, textarea, button {
    font-family: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
}
.serif { font-family: 'IBM Plex Serif', Georgia, 'Times New Roman', serif; }
/* Footer country / region selector (IBM-style) */
.footer-country { display:flex; align-items:center; gap:8px; }
.footer-country-icon { width:16px; height:16px; color:rgba(255,255,255,.6); flex:none; }
.footer-country-select { background:transparent; color:rgba(255,255,255,.82); border:1px solid rgba(255,255,255,.22); border-radius:8px; padding:7px 10px; font:500 13px 'IBM Plex Sans',sans-serif; cursor:pointer; }
.footer-country-select:hover { border-color:rgba(255,255,255,.45); }
.footer-country-select option { color:#1b2b32; }
/* Custom language / region switcher: a trigger that opens a slide-down
   overlay (progressive enhancement of the native select above, which is
   hidden once JS upgrades it - see theme.js). */
.footer-country.es-enhanced .footer-country-select { display:none; }
.footer-country.es-enhanced > .footer-country-icon { display:none; }
.es-lang-trigger {
    display:inline-flex; align-items:center; gap:9px; cursor:pointer;
    background:transparent; color:rgba(255,255,255,.82);
    border:1px solid rgba(255,255,255,.22); border-radius:8px;
    padding:7px 12px; font:500 13px 'IBM Plex Sans',sans-serif;
    transition:border-color .2s, color .2s;
}
.es-lang-trigger:hover { border-color:rgba(255,255,255,.45); color:#fff; }
.es-lang-trigger > svg { width:16px; height:16px; flex:none; opacity:.7; }
.es-lang-trigger .es-lang-chev { width:13px; height:13px; opacity:.6; }
/* Header (top-menu) variant - replaces the raw .lang-switcher pill. */
.es-lang-trigger.es-nav {
    background:rgba(255,255,255,.12); border:1px solid rgba(255,255,255,.3);
    color:#fff; border-radius:999px; min-height:46px; padding:10px 18px;
    font:600 13px 'IBM Plex Sans',sans-serif;
}
.es-lang-trigger.es-nav:hover { background:rgba(255,255,255,.2); border-color:rgba(255,255,255,.45); color:#fff; }
.es-lang-trigger.es-nav > svg { opacity:.85; }
@media (max-width:1080px){ .header-action .es-lang-trigger.es-nav { display:none; } }
/* Mobile (offcanvas) variant - replaces the raw .lang-switcher-mobile. */
.es-lang-trigger.es-nav-mobile {
    width:100%; justify-content:flex-start; margin-top:6px;
    background:var(--sand-2,#f3e9dc); border:none; color:var(--navy,#1b2b32);
    border-radius:12px; min-height:48px; padding:12px 16px;
    font:600 14px 'IBM Plex Sans',sans-serif;
}
.es-lang-trigger.es-nav-mobile:hover { color:var(--navy,#1b2b32); background:#efe3d2; }
.es-lang-trigger.es-nav-mobile > svg { opacity:.7; }
.es-lang-overlay { position:fixed; inset:0; z-index:1400; display:flex; align-items:flex-start; justify-content:center; }
.es-lang-overlay[hidden] { display:none; }
.es-lang-backdrop { position:absolute; inset:0; background:rgba(8,16,20,.55); opacity:0; transition:opacity .28s ease; }
.es-lang-panel {
    position:relative; width:100%; max-width:560px;
    background:#fff; color:#16242b; border-radius:0 0 18px 18px;
    box-shadow:0 24px 60px rgba(0,0,0,.28);
    transform:translateY(-100%); transition:transform .32s cubic-bezier(.22,.61,.36,1);
    padding:24px 26px 30px; max-height:88vh; overflow:auto;
    padding-left:max(26px, env(safe-area-inset-left, 0px)); padding-right:max(26px, env(safe-area-inset-right, 0px));
}
.es-lang-overlay.es-open .es-lang-backdrop { opacity:1; }
.es-lang-overlay.es-open .es-lang-panel { transform:translateY(0); }
.es-lang-head { display:flex; align-items:center; justify-content:space-between; gap:16px; }
.es-lang-head h2 { font:600 20px 'IBM Plex Sans',sans-serif; margin:0; letter-spacing:-.01em; color:#16242b; }
.es-lang-sub { font:400 13px 'IBM Plex Sans',sans-serif; color:#5e6b70; margin:4px 0 18px; }
.es-lang-close { background:none; border:none; cursor:pointer; color:#5e6b70; padding:6px; border-radius:8px; line-height:0; flex:none; }
.es-lang-close:hover { background:#eef1f0; color:#16242b; }
.es-lang-close svg { width:20px; height:20px; }
.es-lang-list { display:grid; grid-template-columns:1fr 1fr; gap:10px; }
.es-lang-opt {
    display:flex; align-items:center; gap:12px; text-align:left; cursor:pointer;
    background:#fff; border:1px solid #e3e6e5; border-radius:12px; padding:11px 14px;
    font:500 14px 'IBM Plex Sans',sans-serif; color:#16242b; transition:border-color .18s, background .18s;
}
.es-lang-opt:hover { border-color:#c9754d; background:#faf6f3; }
.es-lang-opt.es-current { border-color:#c9754d; box-shadow:inset 0 0 0 1px #c9754d; }
.es-lang-flag { width:26px; height:18px; border-radius:3px; flex:none; overflow:hidden; box-shadow:0 0 0 1px rgba(0,0,0,.1); }
.es-lang-flag svg { display:block; width:100%; height:100%; }
.es-lang-opt b { font-weight:600; display:block; }
.es-lang-opt small { display:block; color:#5e6b70; font-size:12px; font-weight:400; }
@media (max-width:520px){ .es-lang-list{ grid-template-columns:1fr; } }
@media (prefers-reduced-motion: reduce){ .es-lang-panel, .es-lang-backdrop { transition:none; } }