/* ==========================================================================
   Leadspanic — AI-native Linear-style theme
   Single stylesheet, mobile-first, dark-default with light toggle.
   Every class name used by app.js is defined here.
   ========================================================================== */

/* ---------- 1. Design tokens ---------- */
:root {
    /* ============================================================
       "Private Bank" design system -- the ONLY theme (light ivory,
       navy ink, oxblood brand, forest-green positives, brass warn).
       Spec: docs/design/private-bank/README.md -> Design tokens.
       Pre-redesign variable NAMES are kept so every existing var()
       reference keeps resolving; their VALUES are remapped here.
       (Rollback copy: styles.css.pre-redesign.)
       ============================================================ */

    /* Fonts */
    --font-display: 'Space Grotesk', system-ui, sans-serif;
    --font-body:    'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --font-mono:    'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;

    /* Private Bank palette (spec names) */
    --bg-outside:   #e6e0d2;   /* outside the app frame */
    --bg-app:       #f7f4ec;   /* ivory */
    --bg-sidebar:   #efeadf;
    --surface-3:    #efe9dc;   /* stat tiles, inset boxes */
    --map-bg:       #ebe5d7;
    --neutral-cell: #ddd5c3;
    --line:         rgba(20,33,61,.11);
    --line-strong:  rgba(20,33,61,.18);
    --ink:          #14213d;
    --ink-2:        #2c3a52;
    --ink-3:        #4b5363;
    --ink-4:        #6b6558;
    --ink-5:        #7d7668;
    --brand:        #8c2f39;   /* oxblood */
    --brand-hover:  #5e1f27;
    --good:         #1f6b4a;   /* forest green */
    --warn:         #a87a26;   /* brass */
    --persona-1: #2f7d5b; --persona-2: #3d5a80; --persona-3: #a87a26;
    --persona-4: #2b6c8f; --persona-5: #9a4f7a; --persona-6: #8c2f39;
    --persona-7: #b8673a; --persona-8: #6b5b95; --persona-9: #3f8f86;

    /* Brand & signal. Legacy names (--coral, --lime, ...) now carry the
       Private Bank hues: coral -> oxblood, lime -> forest green, amber -> brass. */
    --coral:      #8c2f39;
    --coral-tint: #a8454f;
    --coral-deep: #5e1f27;
    --lime:       #1f6b4a;
    --lime-deep:  #17543a;
    --amber:      #a87a26;
    --sky:        #2b6c8f;
    --indigo:     #3d5a80;

    /* Brand aliases */
    --brand-500: #8c2f39;
    --brand-400: #a8454f;
    --brand-600: #5e1f27;
    --brand-grad:  linear-gradient(135deg, #8c2f39 0%, #7a2831 100%);
    --accent-grad: linear-gradient(135deg, #1f6b4a 0%, #17543a 100%);

    /* Semantic */
    --success: #1f6b4a;
    --warning: #a87a26;
    --danger:  #8c2f39;
    --info:    #2b6c8f;

    /* Surfaces */
    --canvas:        #f7f4ec;
    --bg-page:       #f7f4ec;
    --topbar:        #efeadf;
    --bg-surface:    #fffdf8;
    --card:          #fffdf8;
    --surface:       #fffdf8;
    --surface-2:     #f1ece1;
    --bg-surface-2:  #f1ece1;
    --bg-input:      #f1ece1;
    --inset:         #efe9dc;
    --ring-track:    #ddd5c3;

    /* Ink */
    --text-primary:  #14213d;
    --text-secondary:#2c3a52;
    --text-muted:    #4b5363;
    --text-faint:    #6b6558;

    /* Borders */
    --border:        rgba(20,33,61,.11);
    --border-strong: rgba(20,33,61,.18);
    --border-focus:  rgba(140,47,57,.45);
    --focus-ring:    0 0 0 3px rgba(140,47,57,.18);

    /* Shadows / glass / glows */
    --shadow-sm: 0 1px 2px rgba(20,33,61,0.10);
    --shadow-md: 0 6px 24px rgba(20,33,61,0.12);
    --shadow-lg: 0 16px 50px -20px rgba(20,33,61,0.22);
    --shadow-card:  0 2px 12px rgba(20,33,61,0.08);
    --shadow-frame: 0 40px 90px -30px rgba(20,33,61,0.22);
    --shadow-toast: 0 16px 40px -12px rgba(20,33,61,0.30);
    --glow-coral: 0 10px 26px -6px rgba(140,47,57,0.5);
    --glow-lime:  0 10px 26px -6px rgba(31,107,74,0.64);
    --glass:      rgba(255,253,248,0.86);
    --glass-stroke: rgba(20,33,61,0.11);

    --nav-bg: rgba(255,253,248,0.94);
    --nav-text: #4b5363;
    --sheet-bg: #fffdf8;

    /* Canvas subsystem */
    --panel:    #fffdf8;
    --bg:       #f7f4ec;
    --accent:   #8c2f39;
    --header-h: 0px;     /* desktop: old header + tab row are hidden (sidebar shell). Mobile re-sets it. */

    /* Radii */
    --radius-xs: 7px;
    --radius-sm: 11px;
    --radius-md: 14px;
    --radius-lg: 18px;
    --radius-xl: 20px;

    --ease: cubic-bezier(.2,.7,.2,1);

    /* Aliases for names the workspace pages and some renderers use */
    --text: #14213d; --text-2: #2c3a52; --muted: #4b5363; --faint: #6b6558;
    --page: #f7f4ec; --input: #f1ece1; --card-2: #f1ece1; --red: #8c2f39;
    --paper: #fffdf8; --coral-2: #a8454f;

    color-scheme: light;
}

/* ---------- 2. Reset ---------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
/* The `hidden` attribute must always win. Author `display:` rules (e.g.
   .canvas-qc/.canvas-compare using display:flex) otherwise override the UA
   [hidden]{display:none}, leaving an element that JS toggled off still
   rendered — a fixed/inset:0 overlay like #canvasCompare then swallows every
   click and scroll. Keep this before component rules so `el.hidden = true`
   is authoritative everywhere. */
[hidden] { display: none !important; }
html, body { height: 100%; }
html {
    /* Prevent iOS rubber-band / scroll-chaining from revealing adjacent
       tab content underneath. Body-only overflow:hidden isn't enough on
       Safari. */
    overflow: hidden;
    overscroll-behavior: none;
}
body {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-feature-settings: "cv02","cv03","cv04","cv11";
    -webkit-font-smoothing: antialiased;
    background: var(--bg-page);
    color: var(--text-primary);
    line-height: 1.5;
    overflow: hidden; /* tab content manages its own scroll */
    overscroll-behavior: none;
    /* NOTE: intentionally NOT using position:fixed on body — it creates a
       new stacking context that makes z-index comparisons with Leaflet
       internals unreliable. html{overflow:hidden} handles iOS rubber-band. */
}
img, svg { display: block; max-width: 100%; }
/* Leaflet's SVG renderer draws into 0-width panes, so the `svg{max-width:100%}`
   reset above was clamping those <svg> elements to 0 width — hiding any
   SVG-rendered vector layer (e.g. the Find Similar markers, which force an SVG
   renderer regardless of the map's preferCanvas setting). Exempt Leaflet SVGs. */
.leaflet-container svg, .leaflet-pane svg { max-width: none; max-height: none; }
button { font: inherit; cursor: pointer; border: 0; background: transparent; color: inherit; -webkit-appearance: none; appearance: none; }
input, select, textarea { font: inherit; color: inherit; }
a { color: var(--brand-500); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Ambient background — faint coral depth over the near-black canvas */
body::before {
    content: "";
    position: fixed; inset: 0; z-index: -1;
    background: radial-gradient(900px 520px at 12% -8%, rgba(140,47,57,0.06), transparent 62%);
    pointer-events: none;
}

/* ---------- Panic motion keyframes ---------- */
@keyframes lp-pulse   { 0%{transform:translate(-50%,-50%) scale(1);opacity:.5} 70%{transform:translate(-50%,-50%) scale(2.6);opacity:0} 100%{opacity:0} }
@keyframes lp-blink   { 0%,100%{opacity:1} 50%{opacity:.25} }
@keyframes lp-rise    { 0%{opacity:0;transform:translateY(14px)} 100%{opacity:1;transform:translateY(0)} }
@keyframes lp-float   { 0%,100%{transform:translateY(0)} 50%{transform:translateY(-5px)} }
@keyframes lp-shimmer { 0%{background-position:200% 0} 100%{background-position:-200% 0} }
@keyframes lp-sweep   { 0%{transform:rotate(0)} 100%{transform:rotate(360deg)} }
.lp-rise { animation: lp-rise .38s cubic-bezier(.2,.7,.2,1) both; }

/* ---------- 3. Header ---------- */
header {
    display: flex; align-items: center; justify-content: space-between;
    gap: 18px;
    padding: 12px 18px;
    background: var(--topbar);
    border-bottom: 1px solid var(--border);
    position: sticky; top: 0; z-index: 50;
}
/* Home-screen/standalone PWA mode only (viewport-fit=cover + a
   black-translucent status bar means content is expected to paint under
   it, and it's on us to pad below the notch/Dynamic Island) -- a normal
   Safari tab already reserves that space via its own chrome and never
   matches display-mode:standalone, so this cannot affect regular
   browsing.
   --standalone-top-inset mirrors exactly how much taller this padding
   makes the header, so .tab-content's mobile height calc() can subtract
   it — otherwise every tab's content runs that many pixels under the
   fixed bottom nav in the installed PWA. It stays 0px outside standalone,
   which is what the earlier --mobile-header-h attempt got wrong (it
   changed the shared value in ALL modes and opened a gap above the
   bottom nav in regular browsing). */
:root { --standalone-top-inset: 0px; }
@media (display-mode: standalone) {
    :root { --standalone-top-inset: env(safe-area-inset-top); }
    header { padding-top: calc(12px + env(safe-area-inset-top)); }
}
header .brand { display: flex; align-items: center; gap: 10px; }
header .brand-mark {
    width: 30px; height: 30px; border-radius: 9px;
    background: var(--coral);
    display: grid; place-items: center;
    box-shadow: 0 0 22px rgba(140,47,57,0.5);
    color: #fffdf8; font-weight: 800; font-size: 17px;
    font-family: var(--font-display);
}
header h1 {
    font-family: var(--font-display);
    font-size: 1.05rem; font-weight: 700; letter-spacing: -0.01em;
    color: var(--text-primary);
}
header h1 .brand-accent { color: var(--coral); }
header p { display: none; }

header .header-actions { display: flex; align-items: center; gap: 8px; }
.icon-btn {
    width: 34px; height: 34px; border-radius: 9px;
    display: grid; place-items: center;
    background: var(--bg-input);
    color: var(--text-secondary);
    border: 1px solid var(--border);
    transition: background .18s var(--ease), color .18s var(--ease), transform .18s var(--ease);
}
.icon-btn:hover { background: var(--bg-surface-2); color: var(--text-primary); }
.icon-btn:active { transform: scale(.96); }
.avatar-btn {
    width: 34px; height: 34px; border-radius: 9px;
    background: var(--coral);
    display: grid; place-items: center;
    color: #fffdf8; font-weight: 700; font-size: 13px;
    font-family: var(--font-display);
    cursor: pointer; user-select: none;
    transition: filter .15s var(--ease), transform .15s var(--ease);
}
.avatar-btn:hover { filter: brightness(1.08); }
.avatar-btn:active { transform: scale(.96); }
#darkModeIcon { width: 18px; height: 18px; }

/* ---------- 4. Desktop tab bar ---------- */
.tabs {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 12px 18px 12px;
    background: var(--bg-page);
    border-bottom: 1px solid var(--border);
    overflow-x: auto;
    scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }

.tabs-primary,
.tabs-secondary { display: flex; align-items: center; gap: 6px; }

.tabs-divider {
    width: 1px;
    align-self: stretch;
    background: var(--border);
    margin: 4px 8px;
    flex-shrink: 0;
}

.tab-btn {
    position: relative;
    display: inline-flex; align-items: center; gap: 7px;
    padding: 7px 14px;
    font-family: var(--font-display);
    font-size: 12.5px; font-weight: 600;
    color: #9a9aa6;
    border-radius: 9px;
    white-space: nowrap;
    transition: color .15s var(--ease), background .15s var(--ease);
}
.tab-btn .tab-ic { width: 15px; height: 15px; stroke: currentColor; fill: none; flex-shrink: 0; }
.tab-btn:hover { color: var(--text-primary); background: var(--bg-input); }
.tab-btn.active { color: #fffdf8; background: var(--coral); }
.tab-btn.active .tab-ic { stroke: #fffdf8; }

.tab-btn--sec {
    padding: 7px 12px;
    font-size: 12px; border-radius: 9px;
    color: var(--text-muted);
}
.tab-btn--sec .tab-ic { width: 13px; height: 13px; }
.tab-btn--sec:hover { background: var(--bg-input); color: var(--text-primary); }
.tab-btn--sec.active { background: var(--coral); color: #fffdf8; }
.tab-btn--sec.active .tab-ic { stroke: #fffdf8; }


/* ---------- 4b. Mobile sub-nav (chip row) ---------- */
.mobile-subnav {
    display: none;
    gap: 6px;
    padding: 7px 12px;
    background: var(--bg-surface);
    border-bottom: 1px solid var(--border);
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}
.mobile-subnav::-webkit-scrollbar { display: none; }
/* Single-tab groups (Map, Ask) render no chips — don't show an empty bar. */
.mobile-subnav:empty { display: none !important; }

.msn-chip {
    flex-shrink: 0;
    padding: 5px 12px;
    font-size: 12px; font-weight: 500;
    color: var(--text-secondary);
    background: var(--bg-surface-2);
    border-radius: 999px;
    border: 0; cursor: pointer;
    transition: background .15s var(--ease), color .15s var(--ease);
    font-family: inherit;
}
.msn-chip:active { transform: scale(.97); }
.msn-chip.active {
    background: var(--brand-500);
    color: #fff;
}


/* ---------- 4c. Mobile bottom nav (3 groups) ---------- */
.mobile-bottom-nav {
    display: none;
    position: fixed; left: 0; right: 0; bottom: 0;
    background: var(--nav-bg);
    backdrop-filter: saturate(140%) blur(10px);
    -webkit-backdrop-filter: saturate(140%) blur(10px);
    border-top: 1px solid var(--border);
    z-index: 40;
    padding-bottom: env(safe-area-inset-bottom);
}
.mobile-bottom-nav { display: none; align-items: stretch; }

.mobile-nav-btn {
    flex: 1;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 2px;
    padding: 8px 4px 10px;
    color: var(--nav-text);
    position: relative;
    background: none; border: 0; cursor: pointer;
    font-family: inherit;
    transition: color .15s var(--ease);
}
.mobile-nav-btn svg { width: 20px; height: 20px; stroke: currentColor; fill: none; }
.mobile-nav-label { font-size: 12.5px; font-weight: 600; letter-spacing: 0.01em; }
.mobile-nav-btn.active { color: var(--brand-500); }
.mobile-nav-btn.active::before {
    content: ""; position: absolute; top: 0; left: 22%; right: 22%;
    height: 2px; border-radius: 0 0 3px 3px; background: var(--brand-grad);
}

/* ---------- 5. Tab content shells ---------- */
.tab-content { display: none; height: calc(100dvh - var(--header-h)); position: relative; overflow: hidden; }
.tab-content.active { display: flex; animation: fade .22s var(--ease); }
/* Belt-and-suspenders: if anything ever tries to show an inactive tab
   (overridden display via JS error, stacking context issues, etc.), this
   keeps it hidden so siblings can't bleed through. */
.tab-content:not(.active) { display: none !important; }
/* The Plan tab is a single centered form that can grow taller than the
   viewport (form + results). The default .tab-content overflow:hidden clips
   it with no inner scroll container, so let the pane itself scroll.
   (switchTab forces inline display:flex, so only overflow is overridden here.) */
#plan-tab.active { overflow-y: auto; -webkit-overflow-scrolling: touch; }
@keyframes fade { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

/* ---------- 5b. Canvas tab layout ---------- */
.canvas-layout { display: flex; gap: 14px; height: calc(100dvh - var(--header-h, 120px)); padding: 14px 18px 18px; box-sizing: border-box; }
/* .canvas-sheet only becomes a real box on mobile portrait (see the
   #canvas-tab .canvas-sheet block below). Everywhere else — desktop,
   landscape, tablet — display:contents promotes .canvas-rail/.canvas-scorecard
   to be genuine flex items of .canvas-layout alongside .canvas-map-wrap,
   preserving the original 3-column flex layout with zero markup dependency.
   Same technique as Score's .score-sheet. */
.canvas-sheet { display: contents; }
.canvas-rail {
    width: 240px; flex: none; overflow-y: auto; padding: 14px;
    background: var(--panel, #14141b); border: 1px solid var(--border, rgba(255,255,255,.09));
    border-radius: 14px;
}
.canvas-map-wrap {
    flex: 1; position: relative; border-radius: 14px; overflow: hidden;
    background: var(--bg, #08080b); border: 1px solid var(--border, rgba(255,255,255,.07));
}
.canvas-map { position: absolute; inset: 0; }
.canvas-scorecard {
    width: 300px; flex: none; overflow-y: auto; padding: 14px;
    background: var(--panel, #14141b); border: 1px solid var(--border, rgba(255,255,255,.09));
    border-radius: 14px;
}
.canvas-plan-stats { display: flex; gap: 14px; margin: 8px 0 14px; }
.canvas-plan-stats .cstat { flex: none; background: transparent; padding: 0; }
.cstat b { display: block; font-family: 'Space Grotesk', sans-serif; font-weight: 700; font-size: 18px; }
.cstat span { font-size: 12px; color: var(--text-muted, #8a8a99); opacity: 1; }
.canvas-add-btn { width: 100%; margin-top: 10px; padding: 10px; border: 0; border-radius: 9px; background: var(--brand-500, #8c2f39); color: #fffdf8; font-weight: 700; cursor: pointer; }
.canvas-camplist { display: flex; flex-direction: column; gap: 7px; }
.canvas-camprow {
    display: flex; flex-direction: column; gap: 2px;
    padding: 9px 11px; border-radius: 8px; cursor: pointer;
    background: var(--bg-input, #0d0d12);
    border-left: 3px solid var(--border-strong, rgba(255,255,255,.14));
}
.canvas-camprow.active { background: rgba(140,47,57,.14); }
.canvas-camprow .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 600; }
.canvas-camprow .sub { font-size: 12px; color: var(--text-muted, #8a8a99); }
@media (max-width: 900px) {
    /* Map-primary one-column flow: campaign strip on top, map fills, scorecard below. */
    .canvas-layout { flex-direction: column; height: 100%; }
    .canvas-rail { width: auto; order: 1; max-height: 34vh; border-right: 0; border-bottom: 1px solid var(--border, #2a3550); }
    .canvas-map-wrap { order: 2; flex: 1 1 auto; min-height: 42vh; }
    .canvas-scorecard { width: auto; order: 3; max-height: 42vh; border-left: 0; border-top: 1px solid var(--border, #2a3550); }
    .canvas-camplist { display: flex; flex-wrap: wrap; gap: 6px; }
    .canvas-camprow { flex: 1 1 46%; }
    /* NOTE: .canvas-qc and .cmp-* mobile overrides live at the END of the file,
       after their base definitions, so they win without needing !important. */
}

/* ---------- 6. Shared components ---------- */
.container, .score-container, .compare-container, .ask-container { display: flex; width: 100%; height: 100%; }

.sidebar, .score-sidebar, .ask-sidebar, .compare-inputs, .library-list-pane {
    width: 360px;
    max-width: 100%;
    flex-shrink: 0;
    background: var(--bg-surface);
    border-right: 1px solid var(--border);
    overflow-y: auto;
    padding: 1rem 1.1rem 2rem;
}

h3 {
    font-size: 0.95rem; font-weight: 700; letter-spacing: -0.01em;
    margin-bottom: 0.5rem; color: var(--text-primary);
}
h4 {
    font-size: 0.8rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.06em;
    color: var(--text-muted); margin: 0.6rem 0 0.4rem;
}
label {
    display: block;
    font-size: 0.78rem; font-weight: 600;
    color: var(--text-secondary);
    margin-top: 0.55rem; margin-bottom: 0.3rem;
}

input[type="text"], input[type="number"], input[type="search"], input[type="email"], select, textarea {
    width: 100%;
    padding: 0.6rem 0.75rem;
    background: var(--bg-input);
    color: var(--text-primary);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font-size: 0.88rem;
    transition: border-color .18s var(--ease), box-shadow .18s var(--ease), background .18s var(--ease);
}
input:focus, select:focus, textarea:focus {
    outline: none;
    border-color: var(--brand-500);
    box-shadow: 0 0 0 3px rgba(140,47,57,0.18);
}
input::placeholder { color: var(--text-muted); }

select[multiple] {
    padding: 0.3rem;
    min-height: 100px;
}
select[multiple] option { padding: 0.35rem 0.5rem; border-radius: 6px; }

input[type="range"] {
    -webkit-appearance: none; appearance: none;
    width: 100%; height: 4px;
    background: var(--border); border-radius: 2px;
}
input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    width: 18px; height: 18px; border-radius: 50%;
    background: var(--brand-500); cursor: pointer;
    box-shadow: 0 0 0 4px rgba(140,47,57,0.2);
}
input[type="range"]::-moz-range-thumb {
    width: 18px; height: 18px; border-radius: 50%;
    background: var(--brand-500); cursor: pointer; border: 0;
}

input[type="file"] { display: none; }
.file-label {
    display: inline-block;
    padding: 0.5rem 0.8rem;
    background: var(--bg-surface-2);
    border: 1px dashed var(--border-strong);
    color: var(--text-secondary);
    border-radius: var(--radius-sm);
    font-size: 0.82rem;
    cursor: pointer;
    transition: border-color .18s var(--ease), color .18s var(--ease);
}
.file-label:hover { border-color: var(--brand-500); color: var(--brand-500); }

/* ---------- 7. Buttons ---------- */
button:not(.tab-btn):not(.icon-btn):not(.mobile-nav-btn):not(.bm-btn):not(.ask-example):not(.close-btn):not(.pwa-install-dismiss):not(.lib-seg-btn):not(.find-similar-btn):not(.li-tool-btn):not(.li-panel-close):not(.mc-mobile-tabs button):not(.layer-toggle-item button):not(.wh-profile-btn):not(.collapsible-toggle):not(.ms-row):not(.canvas-ws-btn):not(.canvas-sc-rescore):not(.canvas-sc-edit):not(.canvas-sc-del):not(.map-empty-chip):not(.score-export-btn):not(.map-error-edit-btn):not(.more-item):not(.profile-cta-secondary):not(.lpw-choice-card):not(.lpw-btn-coral):not(.lpw-btn-lime):not(.lpw-btn-ghost):not(.lpw-back):not(.lpw-teaser-toggle):not(.use-location-btn) {
    padding: 0.7rem 1rem;
    background: var(--coral);
    color: #fffdf8; font-weight: 700; font-size: 0.88rem;
    font-family: var(--font-display);
    border-radius: var(--radius-sm);
    box-shadow: var(--glow-coral);
    transition: transform .14s var(--ease), box-shadow .14s var(--ease), filter .14s var(--ease), opacity .14s var(--ease);
}
button:not(.tab-btn):not(.icon-btn):not(.mobile-nav-btn):not(.bm-btn):not(.ask-example):not(.close-btn):not(.pwa-install-dismiss):not(.lib-seg-btn):not(.find-similar-btn):not(.li-tool-btn):not(.li-panel-close):not(.mc-mobile-tabs button):not(.layer-toggle-item button):not(.wh-profile-btn):not(.collapsible-toggle):not(.ms-row):not(.canvas-ws-btn):not(.canvas-sc-rescore):not(.canvas-sc-edit):not(.canvas-sc-del):not(.map-empty-chip):not(.score-export-btn):not(.map-error-edit-btn):not(.more-item):not(.profile-cta-secondary):not(.lpw-choice-card):not(.lpw-btn-coral):not(.lpw-btn-lime):not(.lpw-btn-ghost):not(.lpw-back):not(.lpw-teaser-toggle):not(.use-location-btn):hover { transform: translateY(-1px); box-shadow: 0 14px 30px -8px rgba(140,47,57,0.55); filter: brightness(1.06); }
button:not(.tab-btn):not(.icon-btn):not(.mobile-nav-btn):not(.bm-btn):not(.ask-example):not(.close-btn):not(.pwa-install-dismiss):not(.lib-seg-btn):not(.find-similar-btn):not(.li-tool-btn):not(.li-panel-close):not(.mc-mobile-tabs button):not(.layer-toggle-item button):not(.wh-profile-btn):not(.collapsible-toggle):not(.ms-row):not(.canvas-ws-btn):not(.canvas-sc-rescore):not(.canvas-sc-edit):not(.canvas-sc-del):not(.map-empty-chip):not(.score-export-btn):not(.map-error-edit-btn):not(.more-item):not(.profile-cta-secondary):not(.lpw-choice-card):not(.lpw-btn-coral):not(.lpw-btn-lime):not(.lpw-btn-ghost):not(.lpw-back):not(.lpw-teaser-toggle):not(.use-location-btn):active { transform: scale(.98); }
button:disabled { opacity: .55; cursor: not-allowed; }
/* Lime buttons read as a muddy olive at the generic .55 disabled opacity
   (green desaturates harder than coral against a near-black bg) — keep them
   recognizably lime while still signaling "not ready yet". */
#report-pdf-btn:disabled { opacity: .85; filter: saturate(.55) brightness(.85); }

.gps-btn, .wh-locate-btn, .compare-btn, .run-btn, .wh-go-btn, .li-run-btn {
    width: 100%;
    margin-top: 0.4rem;
}

/* Secondary style for Leaf/small buttons */
.btn-secondary {
    background: var(--bg-surface-2) !important;
    color: var(--text-primary) !important;
    box-shadow: none !important;
    border: 1px solid var(--border) !important;
}

/* ---------- 8. Map tab ---------- */
.search-section, .whos-here-section, .upload-section {
    padding: 0.9rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    margin-bottom: 0.8rem;
    background: var(--bg-surface);
}
.search-section { background: linear-gradient(180deg, rgba(140,47,57,0.06), transparent 80%); }

.search-bar { display: flex; gap: 0.4rem; margin-top: 0.35rem; position: relative; }
.search-bar input { flex: 1; }
.search-bar button { flex-shrink: 0; }

/* "Use my location" secondary action under the primary search bar */
.use-location-btn {
    display: inline-flex; align-items: center; gap: 0.4rem;
    margin-top: 0.5rem;
    padding: 0.5rem 0.8rem;
    font-size: 0.82rem; font-weight: 600;
    color: var(--brand-500);
    background: var(--bg-surface-2);
    border: 1px solid var(--border);
    border-radius: 10px;
    cursor: pointer;
    transition: border-color .15s, color .15s, background .15s;
}
.use-location-btn:hover { border-color: var(--brand-500); }
.use-location-btn svg { flex-shrink: 0; }
.use-location-btn:disabled { opacity: 0.6; cursor: default; }
@media (hover: none) and (pointer: coarse) {
    .use-location-btn { padding: 0.6rem 0.9rem; font-size: 0.88rem; }
}

/* Address autocomplete dropdown (type-ahead suggestions) */
.addr-suggest {
    position: absolute;
    top: calc(100% + 4px); left: 0; right: 0;
    z-index: 60;
    display: none;
    max-height: 320px; overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    background: var(--bg-surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    box-shadow: 0 12px 30px rgba(0,0,0,0.35);
}
.addr-suggest.open { display: block; }
.addr-suggest-item {
    padding: 0.55rem 0.7rem;
    cursor: pointer;
    border-bottom: 1px solid var(--border);
}
.addr-suggest-item:last-child { border-bottom: none; }
.addr-suggest-item:hover, .addr-suggest-item.active { background: var(--bg-surface-2); }
.addr-suggest-item .addr-line1 { color: var(--text-primary); font-weight: 600; font-size: 0.85rem; line-height: 1.25; }
.addr-suggest-item .addr-line2 { color: var(--text-muted); font-size: 0.76rem; margin-top: 1px; }
.search-hint, .whos-here-hint, .csv-format-hint {
    margin-top: 0.4rem;
    font-size: 0.78rem;
    color: var(--text-muted);
}
.section-divider {
    text-align: center;
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--text-muted);
    margin: 0.6rem 0;
    position: relative;
}
.section-divider::before, .section-divider::after {
    content: ""; position: absolute; top: 50%; width: 25%; height: 1px; background: var(--border);
}
.section-divider::before { left: 0; }
.section-divider::after { right: 0; }

.whos-here-coords {
    font-size: 0.78rem; color: var(--text-muted); margin-top: 0.3rem;
    font-family: ui-monospace, 'SF Mono', Menlo, monospace;
}
.wh-radius-row { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.5rem; }
.wh-radius-row label { margin: 0; font-size: 0.75rem; }
.wh-radius-row input[type="range"] { flex: 1; }
.wh-radius-val { font-size: 0.75rem; font-weight: 600; color: var(--brand-500); min-width: 40px; text-align: right; }

.wh-results { margin-top: 0.6rem; }

/* Summary stat row */
.summary-bar {
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem;
    margin: 0.6rem 0;
}
.summary-stat {
    padding: 0.55rem 0.4rem;
    background: var(--bg-surface-2);
    border-radius: var(--radius-sm);
    text-align: center;
    font-size: 0.76rem; color: var(--text-muted);
    text-transform: uppercase; letter-spacing: 0.06em;
}
.summary-stat .num {
    font-size: 1.1rem; font-weight: 700; color: var(--text-primary);
    letter-spacing: -0.02em;
}

.customer-list { margin-top: 0.5rem; }
.customer-item {
    padding: 0.55rem 0.7rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    margin-bottom: 0.35rem;
    background: var(--bg-surface);
    cursor: pointer;
    transition: border-color .16s var(--ease), transform .16s var(--ease);
}
.customer-item:hover { border-color: var(--brand-500); transform: translateX(2px); }
.customer-name { font-size: 0.82rem; font-weight: 600; }
.customer-address { font-size: 0.78rem; color: var(--text-muted); }
.customer-persona { font-size: 0.78rem; color: var(--brand-500); margin-top: 0.2rem; font-weight: 500; }

/* First-run empty state for the map results (design 4b) */
.results-empty { padding: 1.6rem 0.8rem; text-align: center; color: var(--text-muted); }
.results-empty-icon { width: 44px; height: 44px; margin: 0 auto 0.7rem; display: grid; place-items: center; border-radius: 12px; background: rgba(140,47,57,0.1); color: var(--coral); }
.results-empty-icon svg { width: 22px; height: 22px; }
.results-empty p { font-size: 0.82rem; line-height: 1.5; margin: 0; }

#map, .li-map, .score-map, .ask-map, .compare-map-pane {
    flex: 1;
    height: 100%;
    min-height: 300px;
    background: var(--canvas);
}
.score-map, .ask-map { position: relative; }
#map { position: relative; }
/* Map hero overlays (design 1a): spotlight vignette + live SCANNING chip.
   Children of #map — Leaflet appends its panes alongside them and never
   clears foreign children, so these survive map init/redraws. */
.map-spotlight {
    position: absolute; inset: 0; pointer-events: none; z-index: 450;
    background: radial-gradient(120% 130% at 54% 46%, transparent 0%, transparent 34%, rgba(8,8,11,0.55) 82%);
}
.map-scan-chip {
    position: absolute; top: 12px; left: 12px; z-index: 680; pointer-events: none;
    display: flex; align-items: center; gap: 8px;
    background: rgba(247,244,236,0.92); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
    border: 1px solid var(--border); border-radius: 10px; padding: 7px 11px;
    font-family: var(--font-mono); font-size: 13px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-secondary);
}
.map-scan-chip .scan-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--lime); box-shadow: 0 0 8px var(--lime); animation: lp-blink 1.4s infinite; }
@media (max-width: 900px) { .map-scan-chip { display: none; } }

/* First-run / empty state (design 4b) — shown until the user searches an
   address, drops a Who's Here pin, or runs a CSV analysis. */
.map-empty-state {
    position: absolute; inset: 0; z-index: 700;
    display: flex; align-items: center; justify-content: center;
    background: rgba(235,229,215,.72);
    padding: 16px;
}
.map-empty-state.hidden { display: none; }
.map-empty-card {
    width: min(420px, 100%);
    background: var(--panel, #14141b);
    border: 1px solid var(--border);
    border-radius: 16px;
    padding: 32px;
    display: flex; flex-direction: column; align-items: center; text-align: center;
    box-shadow: 0 30px 70px -30px rgba(20,33,61,.3);
}
.map-empty-icon {
    width: 64px; height: 64px; border-radius: 18px;
    background: rgba(140,47,57,.12); border: 1px solid rgba(140,47,57,.3);
    display: grid; place-items: center; margin-bottom: 20px;
    color: var(--brand-500);
}
.map-empty-title { font-family: 'Space Grotesk', sans-serif; font-weight: 700; font-size: 22px; letter-spacing: -.01em; margin-bottom: 8px; }
.map-empty-sub { font-size: 15px; line-height: 1.6; color: var(--text-muted); max-width: 340px; margin: 0 0 20px; }
.map-empty-row { display: flex; gap: 9px; width: 100%; max-width: 360px; margin-bottom: 16px; }
.map-empty-row input { flex: 1; }
.map-empty-chips { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }
.map-empty-chip {
    font-size: 14px; font-weight: 500; color: var(--text-secondary);
    border: 1px solid var(--border-strong); border-radius: 20px; padding: 8px 14px;
    background: transparent; cursor: pointer;
}
.map-empty-chip:hover { border-color: var(--brand-500); color: var(--brand-500); }
@media (max-width: 900px) {
    .map-empty-card { padding: 24px; }
    .map-empty-title { font-size: 19px; }
}

/* Address-not-found state (design 4c) — shares .map-empty-state layout,
   swaps the icon tint to amber and drops in a warning glyph. */
.map-error-icon { background: rgba(168,122,38,.12); border-color: rgba(168,122,38,.35); color: var(--amber); }
.map-error-edit-btn {
    background: transparent; border: 1px solid var(--border-strong);
    color: var(--text-secondary); font-weight: 600; font-size: 12.5px;
    padding: 10px 18px; border-radius: 10px; cursor: pointer;
}
.map-error-edit-btn:hover { border-color: var(--brand-500); color: var(--brand-500); }

.legend {
    position: absolute;
    right: 16px;
    bottom: 16px;
    background: var(--glass);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border: 1px solid var(--glass-stroke);
    border-radius: var(--radius-md);
    padding: 0.7rem 0.9rem;
    box-shadow: var(--shadow-md);
    max-width: 240px;
    max-height: 55vh;
    overflow-y: auto;
    font-size: 0.78rem;
    z-index: 500;
}
.legend h4 { margin: 0 0 0.4rem; color: var(--coral-tint); letter-spacing: 0.08em; }
.legend-item { display: flex; align-items: center; gap: 0.5rem; padding: 0.18rem 0; }
.legend-color { width: 12px; height: 12px; border-radius: 3px; flex-shrink: 0; }

/* Layer toggle */
.layer-toggle-item {
    display: flex; align-items: center; gap: 0.55rem;
    padding: 0.5rem 0.7rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    margin-bottom: 0.35rem;
    background: var(--bg-surface);
    cursor: pointer;
    transition: border-color .16s var(--ease);
}
.layer-toggle-item:hover { border-color: var(--brand-500); }
.layer-toggle-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--brand-500); }

/* Status / error / loading */
.status {
    padding: 0.55rem 0.75rem;
    background: var(--bg-surface-2);
    border-radius: var(--radius-sm);
    font-size: 0.78rem;
    margin: 0.45rem 0;
    color: var(--text-secondary);
    display: none;
}
.status:not(:empty) { display: block; }
.error-message {
    padding: 0.55rem 0.75rem;
    background: rgba(140,47,57,0.12);
    color: var(--coral-tint);
    border-radius: var(--radius-sm);
    font-size: 0.82rem;
    margin: 0.45rem 0;
    display: none;
    border: 1px solid rgba(140,47,57,0.32);
}
.error-message:not(:empty) { display: block; }

/* "You're standing in" — the tract the pin sits inside. This is the answer
   for the point, and it deliberately outranks the radius stats below it:
   headlining the area's most-common persona is what made Who's Here read as
   disagreeing with Look Up Any Address. */
.wh-here-card {
    margin-top: 0.6rem;
    padding: 0.7rem 0.75rem;
    background: var(--bg-surface-2);
    border: 1px solid var(--brand-500);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: border-color .14s var(--ease), background .14s var(--ease);
}
.wh-here-card:hover { background: var(--bg-surface); }
.wh-here-label {
    font-size: 0.76rem; color: var(--text-muted);
    text-transform: uppercase; letter-spacing: 0.06em;
}
.wh-here-name {
    display: flex; align-items: center; gap: 0.45rem;
    font-size: 0.95rem; font-weight: 700; color: var(--text-primary);
    margin-top: 0.2rem;
}
.wh-here-badges { font-size: 0.78rem; color: var(--text-secondary); margin-top: 0.2rem; }
.wh-here-card .wh-profile-btn { margin-top: 0.5rem; }

/* Radius scope header — makes it unambiguous that everything under it
   describes the AREA, not the pin. */
.wh-area-head {
    margin-top: 0.85rem;
    font-size: 0.76rem; color: var(--text-muted);
    text-transform: uppercase; letter-spacing: 0.06em;
}

/* Who's Here summary cards */
.wh-summary-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 0.4rem; margin-top: 0.5rem; }
.wh-summary-wide { grid-column: 1 / -1; }
.wh-summary-card .value.wh-value-sm { font-size: 0.85rem; line-height: 1.25; }
.wh-persona-item.is-here { border-color: var(--brand-500); }
.wh-summary-card {
    padding: 0.55rem;
    background: var(--bg-surface-2);
    border-radius: var(--radius-sm);
    text-align: center;
}
.wh-summary-card .label { font-size: 0.76rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.06em; }
.wh-summary-card .value { font-size: 1.05rem; font-weight: 700; color: var(--text-primary); }
.wh-persona-list { margin-top: 0.5rem; }
.wh-persona-item {
    display: flex; align-items: center; gap: 0.5rem;
    padding: 0.4rem 0.55rem;
    background: var(--bg-surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    margin-bottom: 0.3rem;
}
.wh-persona-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.wh-persona-info { flex: 1; min-width: 0; }
.wh-persona-name { font-size: 0.8rem; font-weight: 600; color: var(--text-primary); }
.wh-persona-count { font-size: 0.78rem; color: var(--text-muted); }
.wh-profile-btn {
    padding: 0.25rem 0.55rem;
    background: var(--bg-surface-2);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    border-radius: 6px;
    font-size: 0.78rem;
    transition: border-color .14s var(--ease), color .14s var(--ease);
}
.wh-profile-btn:hover { border-color: var(--brand-500); color: var(--brand-500); }

/* ---------- 9. Lead Score tab ---------- */
.business-model-seg {
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.3rem;
    margin: 0.3rem 0 0.5rem;
}
.bm-btn {
    padding: 0.45rem 0.3rem;
    background: var(--bg-surface-2);
    color: var(--text-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font-size: 0.78rem; font-weight: 600;
    transition: all .14s var(--ease);
}
.bm-btn:hover { border-color: var(--brand-500); color: var(--brand-500); }
.bm-btn.active {
    background: var(--coral);
    color: #fffdf8;
    border-color: transparent;
    box-shadow: 0 4px 12px rgba(140,47,57,0.35);
}

.lead-score-summary-card {
    padding: 0.75rem;
    background: var(--bg-surface-2);
    border-radius: var(--radius-md);
    margin-top: 0.6rem;
    font-size: 0.82rem;
}
.lead-score-summary-card .big {
    font-size: 1.8rem; font-weight: 800; letter-spacing: -0.02em;
    background: var(--brand-grad); -webkit-background-clip: text; background-clip: text; color: transparent;
}

.lead-tract-row {
    padding: 0.5rem 0.1rem;
    margin-bottom: 9px;
    cursor: pointer;
}
.lead-tract-top { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; font-size: 13px; margin-bottom: 4px; }
.lead-tract-nm { color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lead-tract-score { flex: none; font-family: 'Space Grotesk', sans-serif; }
.lead-score-bar-track { height: 5px; background: var(--bg-input); border-radius: 3px; overflow: hidden; }
.lead-score-bar-fill { height: 100%; border-radius: 3px; }
.lead-tract-badge {
    padding: 0.18rem 0.45rem;
    border-radius: 999px;
    font-size: 0.76rem;
    font-weight: 700;
    background: var(--brand-grad);
    color: white;
}

/* ---------- Score an Area: ranked-results panel (design 2a) ---------- */
.score-map-chip {
    position: absolute; top: 12px; left: 12px; z-index: 680;
    background: rgba(247,244,236,.92); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
    border: 1px solid var(--border); border-radius: 10px; padding: 8px 12px;
    font-family: var(--font-mono); font-size: 13px; font-weight: 600; color: var(--lime);
}
.score-results {
    width: 260px; flex: none;
    background: var(--panel, #14141b);
    border: 1px solid var(--border);
    border-radius: 14px;
    margin: 14px 14px 14px 0;
    padding: 14px;
    overflow-y: auto;
}
.score-results-h { font-family: 'Space Grotesk', sans-serif; font-weight: 700; font-size: 13px; margin-bottom: 10px; }
.score-results-empty { font-size: 0.78rem; color: var(--text-muted); line-height: 1.5; }
.score-export-btn {
    width: 100%; margin-top: 12px; padding: 9px;
    background: transparent; border: 1px solid var(--border-strong);
    color: var(--text-secondary); font-weight: 600; font-size: 13px; border-radius: 9px;
    cursor: pointer;
}
.score-export-btn:hover { border-color: var(--brand-500); color: var(--brand-500); }

/* ---------- Find Lookalikes: ranked-results list (design 2c) ---------- */
.ll-tract-row { padding: 0.5rem 0.1rem; margin-bottom: 9px; cursor: pointer; }
.ll-tract-top { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; font-size: 13px; margin-bottom: 4px; }
.ll-tract-nm { color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ll-tract-pop { flex: none; font-family: 'Space Grotesk', sans-serif; color: var(--lime); }
.ll-pop-bar-track { height: 5px; background: var(--bg-input); border-radius: 3px; overflow: hidden; }
.ll-pop-bar-fill { height: 100%; border-radius: 3px; background: var(--lime); }

.lead-component-bar {
    margin-top: 0.3rem;
}
.lcb-label { font-size: 0.78rem; color: var(--text-muted); margin-bottom: 0.15rem; display: flex; justify-content: space-between; }
.lcb-track { height: 5px; background: var(--bg-surface-2); border-radius: 3px; overflow: hidden; }
.lcb-fill { height: 100%; background: var(--brand-grad); border-radius: 3px; transition: width .3s var(--ease); }
.lcb-val { font-weight: 600; color: var(--text-primary); }
.lead-component-note { margin-top: 0.35rem; font-size: 0.74rem; color: var(--text-muted); font-style: italic; }

/* Score — first-run empty state (design 4d) */
.score-empty { padding: 1.4rem 0.6rem 0.6rem; text-align: center; }
.score-empty-bars { display: flex; align-items: flex-end; justify-content: center; gap: 5px; height: 44px; margin-bottom: 0.9rem; }
.score-empty-bars span { width: 18px; border-radius: 5px 5px 3px 3px; opacity: 0.9; }
.score-empty-bars span:nth-child(1) { background: var(--coral); height: 28px; }
.score-empty-bars span:nth-child(2) { background: var(--amber); height: 44px; }
.score-empty-bars span:nth-child(3) { background: var(--lime);  height: 20px; }
.score-empty-bars span:nth-child(4) { background: var(--sky);   height: 36px; }
.score-empty-bars span:nth-child(5) { background: var(--indigo);height: 24px; }
.score-empty h4 { font-family: var(--font-display); font-size: 1rem; color: var(--text-primary); margin: 0 0 0.35rem; }
.score-empty p { font-size: 0.8rem; color: var(--text-muted); line-height: 1.5; margin: 0; }

/* ---------- 10. Market Comparison tab (design 2b) ---------- */
.compare-container { flex-direction: column; padding: 0 18px 18px; }
.compare-inputs {
    width: 100%;
    border-right: 0;
    border-bottom: 0;
    padding: 16px 0 6px;
    display: flex; flex-wrap: wrap; gap: 12px;
    align-items: flex-end;
    overflow-y: visible;
}
.compare-input-group { flex: 1; min-width: 180px; display: flex; flex-direction: column; gap: 5px; }
.compare-input-group label {
    margin: 0; font-size: 12.5px; font-weight: 600; color: var(--text-secondary);
    text-transform: uppercase; letter-spacing: .05em;
}
.compare-input-group input, .compare-input-group select { width: 100%; }
.compare-input-group--a label { color: var(--coral-tint); }
.compare-input-group--a input { border-color: rgba(140,47,57,.35); }
.compare-input-group--b label { color: #7c8cff; }
.compare-input-group--b input { border-color: rgba(124,140,255,.35); }

.compare-btn { flex: 0 0 auto; align-self: stretch; }

#mc-recommendation {
    padding: 11px 15px; margin: 10px 0; border-radius: 11px; font-size: 12.5px;
    color: var(--text-primary);
}
#mc-recommendation.mc-rec-winner {
    background: linear-gradient(90deg, rgba(140,47,57,.16), rgba(140,47,57,.03));
    border: 1px solid rgba(140,47,57,.28);
}
#mc-recommendation.mc-rec-tie {
    background: var(--bg-surface-2);
    border: 1px solid var(--border);
}

.mc-mobile-tabs { display: none; }

.compare-row { display: flex; gap: 14px; height: 480px; }
.compare-maps {
    flex: 1;
    display: flex; flex-direction: column;
    gap: 8px;
    min-width: 0;
    background: transparent;
}
.compare-map-pane { display: block; width: 100%; flex: 1; min-height: 0; position: relative; box-sizing: border-box; border-radius: 12px; overflow: hidden; }
.compare-map-pane--a { border: 1px solid rgba(140,47,57,.3); }
.compare-map-pane--b { border: 1px solid rgba(124,140,255,.3); }
.compare-map-label {
    position: absolute; top: 10px; left: 10px; z-index: 680;
    background: rgba(247,244,236,.92); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
    border-radius: 8px; padding: 4px 9px;
    font-family: var(--font-mono); font-size: 12px; font-weight: 600; letter-spacing: .04em;
    pointer-events: none;
}
.compare-map-label--a { color: var(--coral-tint); }
.compare-map-label--b { color: #a7b2ff; }

.compare-results { display: flex; gap: 14px; }
.compare-card {
    flex: none; width: 260px; height: 100%;
    background: var(--panel, #14141b); border: 1px solid var(--border);
    border-radius: 14px; padding: 14px;
    display: flex; flex-direction: column; align-items: center;
    overflow-y: auto;
}
.compare-table-card { width: 250px; align-items: stretch; }
.compare-card-title {
    font-family: 'Space Grotesk', sans-serif; font-weight: 700; font-size: 13px;
    align-self: flex-start; margin-bottom: 10px;
}
.compare-chart-container { width: 100%; }
.compare-table { font-size: 0.82rem; width: 100%; }
.compare-table table { width: 100%; border-collapse: collapse; }
.compare-table th, .compare-table td { padding: 0.4rem 0.6rem; text-align: left; border-bottom: 1px solid var(--border); }
.compare-table th { font-size: 0.78rem; text-transform: uppercase; color: var(--text-muted); letter-spacing: 0.06em; }

/* ---------- 11. Lead Intelligence tab ---------- */
.li-layout { flex-direction: row; }
.li-map { position: absolute; inset: 0; z-index: 1; }

.li-top-banner {
    position: absolute;
    top: 12px; left: 50%; transform: translateX(-50%);
    display: flex; gap: 0.3rem;
    padding: 0.3rem;
    background: var(--glass);
    backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
    border: 1px solid var(--glass-stroke);
    border-radius: 999px;
    box-shadow: var(--shadow-md);
    z-index: 20;
    max-width: calc(100% - 24px);
}
.li-tool-btn {
    padding: 0.5rem 0.9rem;
    font-size: 0.82rem; font-weight: 600;
    color: var(--text-secondary);
    border-radius: 999px;
    transition: all .16s var(--ease);
    white-space: nowrap;
}
.li-tool-btn:hover { background: var(--bg-surface-2); color: var(--text-primary); }
.li-tool-btn.active { background: var(--coral); color: #fffdf8; box-shadow: 0 4px 14px rgba(140,47,57,0.3); }
.li-label-short { display: none; }

.li-panel {
    position: absolute;
    top: 0; right: 0; bottom: 0;
    width: 380px;
    max-width: 100%;
    background: var(--bg-surface);
    border-left: 1px solid var(--border);
    box-shadow: -10px 0 30px rgba(0,0,0,0.1);
    transform: translateX(100%);
    transition: transform .28s var(--ease);
    z-index: 15;
    display: flex; flex-direction: column;
}
.li-panel.open { transform: translateX(0); }
.li-panel-header {
    padding: 0.9rem 1rem;
    display: flex; align-items: center; justify-content: space-between;
    border-bottom: 1px solid var(--border);
    background: var(--bg-surface);
    position: sticky; top: 0; z-index: 1;
}
.li-panel-close {
    width: 32px; height: 32px; border-radius: 8px;
    font-size: 1.4rem; color: var(--text-secondary);
}
.li-panel-close:hover { background: var(--bg-surface-2); color: var(--text-primary); }
.li-panel-body { padding: 1rem; overflow-y: auto; flex: 1; }
.li-section { margin-bottom: 0.75rem; padding-bottom: 0.75rem; border-bottom: 1px solid var(--border); }
.li-section:last-child { border-bottom: 0; }
.li-results { margin-top: 0.8rem; }

/* ---------- 12. Report tab ---------- */
.report-layout { display: none; flex-direction: column; overflow-y: auto; }
.report-layout.active { display: flex; }
.report-form {
    max-width: 720px;
    margin: 1.5rem auto;
    padding: 1.4rem;
    background: var(--bg-surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    width: calc(100% - 2rem);
}
.report-form h3 { font-size: 1.1rem; margin-bottom: 0.3rem; }
#report-output {
    max-width: 900px;
    margin: 0 auto 3rem;
    padding: 0 1rem;
    width: 100%;
}
.report-output, .report-metric-row {
    background: var(--bg-surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 0.9rem 1rem;
    margin-bottom: 0.7rem;
}
.report-metric {
    display: flex; justify-content: space-between; align-items: center;
    padding: 0.35rem 0;
    font-size: 0.88rem;
}
.report-metric .label { color: var(--text-secondary); }
.report-metric .value { font-weight: 700; color: var(--text-primary); }

/* Report renders as a LIGHT printable document (design 2f) and is the
   html2canvas/jsPDF capture target, so keep it paper-light regardless of the
   dark app. Scope everything to #report-output. */
#report-output { color: #1c1b18; }
#report-output .report-output,
#report-output .report-metric-row {
    background: #f7f6f2;
    border: 1px solid #e6e1d6;
    color: #1c1b18;
    box-shadow: 0 6px 22px -12px rgba(0,0,0,0.6);
}
#report-output .report-metric .label { color: #5b564c; }
#report-output .report-metric .value { color: #1c1b18; }

/* ---------- 13. Ask tab ---------- */
/* Desktop (design 2g): chat column + full-bleed #ask-map on the right.
   The map is DESKTOP-ONLY — the mobile and landscape-phone blocks below
   hide .ask-map and let the chat column own the whole tab. */
.ask-container { flex-direction: row; }
/* Darker chat column so answer cards + user bubbles pop (design 2g) */
.ask-sidebar { background: var(--bg-page); }
.ask-input-group { display: flex; gap: 0.4rem; margin-top: 0.5rem; }
.ask-input-group input { flex: 1; }
.ask-examples h4 { margin-top: 1rem; }
.ask-example {
    display: block; width: 100%; text-align: left;
    padding: 0.55rem 0.7rem;
    background: var(--bg-surface-2);
    border: 1px solid var(--border);
    color: var(--text-primary);
    font-size: 0.8rem;
    border-radius: var(--radius-sm);
    margin-bottom: 0.35rem;
    transition: border-color .14s var(--ease), transform .14s var(--ease);
}
.ask-example:hover { border-color: var(--brand-500); transform: translateX(2px); }
.ask-results {
    margin-top: 0.8rem;
    display: flex; flex-direction: column;
    font-size: 0.82rem;
    min-height: 80px;
}
/* Ask — chat conversation (design 2g) */
.ask-msg-user {
    align-self: flex-end; max-width: 88%; margin: 0 0 10px auto;
    background: var(--coral); color: #fffdf8; font-weight: 600;
    padding: 8px 12px; border-radius: 13px 13px 3px 13px; font-size: 0.82rem; line-height: 1.4;
}
.ask-answer-card {
    background: var(--card); border: 1px solid var(--border);
    border-radius: 13px 13px 13px 3px; padding: 12px 14px; margin-bottom: 12px;
    animation: lp-rise .3s var(--ease) both;
}
.ask-answer-headline {
    font-family: var(--font-display); font-weight: 700; font-size: 0.95rem;
    color: var(--lime); margin-bottom: 8px; line-height: 1.3;
}
.ask-result-count {
    font-family: var(--font-mono); font-size: 0.76rem; letter-spacing: 0.05em;
    color: var(--text-muted); text-transform: uppercase; margin-bottom: 8px;
}
.ask-result-list { display: flex; flex-direction: column; gap: 5px; }
.ask-result-row {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    padding: 7px 9px; background: var(--inset); border: 1px solid var(--border); border-radius: 9px;
}
.arr-main { min-width: 0; }
.arr-name { display: block; font-size: 0.8rem; font-weight: 600; color: var(--text-primary); }
.arr-detail { display: block; font-size: 0.78rem; color: var(--text-muted); margin-top: 1px; }
.arr-score { flex: none; font-family: var(--font-mono); font-weight: 600; font-size: 0.8rem; color: var(--lime); }
.ask-result-more { font-size: 0.78rem; color: var(--text-muted); padding: 6px 2px 0; }
/* Headline figures from object-shaped RPC results (e.g. get_whos_here). auto-fit
   so it reads as 2 columns on a phone and 3-4 on desktop without a breakpoint. */
.ask-stat-grid {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(108px, 1fr));
    gap: 6px; margin-bottom: 10px;
}
.ask-stat {
    background: var(--inset); border: 1px solid var(--border);
    border-radius: 9px; padding: 8px 9px; min-width: 0;
}
.ask-stat-num {
    font-family: var(--font-mono); font-weight: 600; font-size: 0.95rem;
    color: var(--lime); line-height: 1.2; overflow-wrap: anywhere;
}
.ask-stat-lbl {
    font-size: 0.76rem; letter-spacing: 0.04em; text-transform: uppercase;
    color: var(--text-muted); margin-top: 2px; line-height: 1.25;
}
.ask-group-title {
    font-family: var(--font-mono); font-size: 0.76rem; letter-spacing: 0.05em;
    text-transform: uppercase; color: var(--text-secondary);
    margin: 12px 0 6px; padding-top: 10px; border-top: 1px solid var(--border);
}
/* Grounded answers: prose, a quiet receipt of the figures it relied on, and
   a notice variant for refusals (calm, not an error). */
.ask-answer-prose { font-size: 0.88rem; line-height: 1.55; color: var(--text-primary); margin: 0; overflow-wrap: anywhere; }
.ask-facts { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--border); }
.ask-facts-title {
    font-family: var(--font-mono); font-size: 0.76rem; letter-spacing: 0.05em;
    text-transform: uppercase; color: var(--text-muted); margin-bottom: 6px;
}
.ask-fact {
    display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
    padding: 4px 0; font-size: 0.8rem; line-height: 1.35;
}
.ask-fact-lbl { color: var(--text-muted); min-width: 0; overflow-wrap: anywhere; }
.ask-fact-val { flex: none; max-width: 55%; text-align: right; font-family: var(--font-mono); font-weight: 600; color: var(--text-primary); overflow-wrap: anywhere; }
.ask-answer-notice { background: var(--inset); border-left: 3px solid var(--warn); }
.ask-answer-notice .ask-answer-prose { color: var(--text-secondary); }
.ask-answer-pre {
    background: var(--inset); border: 1px solid var(--border); border-radius: 9px;
    padding: 10px; font-family: var(--font-mono); font-size: 0.78rem; color: var(--text-secondary);
    overflow: auto; max-height: 280px; margin: 0; white-space: pre-wrap; word-break: break-word;
}

/* ---------- 14. Library tab ---------- */
.library-layout { flex-direction: row; }
.library-list-pane { padding: 0.8rem 0.9rem 2rem; }
.library-seg {
    display: grid; grid-template-columns: repeat(3, 1fr);
    gap: 0.25rem;
    padding: 0.25rem;
    background: var(--bg-surface-2);
    border-radius: 10px;
    margin-bottom: 0.6rem;
}
.lib-seg-btn {
    padding: 0.45rem 0.3rem;
    font-size: 0.76rem; font-weight: 600;
    color: var(--text-secondary);
    border-radius: 7px;
    white-space: nowrap;
    transition: background .14s var(--ease), color .14s var(--ease);
}
.lib-seg-btn:hover { color: var(--text-primary); }
.lib-seg-btn.active { background: var(--brand-500); color: #fffdf8; box-shadow: none; }

#library-search { margin-bottom: 0.6rem; }
.library-cards { list-style: none; }
.library-card {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 0.7rem 0.85rem;
    background: var(--bg-surface);
    border: 1px solid var(--border);
    border-radius: 11px;
    margin-bottom: 7px;
    cursor: pointer;
    transition: border-color .14s var(--ease), transform .14s var(--ease);
}
.library-card:hover { border-color: var(--brand-500); transform: translateY(-1px); }
.library-card.active { border-color: var(--brand-500); box-shadow: 0 0 0 3px rgba(140,47,57,0.18); }
.library-color-bar { width: 9px; height: 34px; border-radius: 4px; flex: none; }
.library-card-title { font-size: 0.88rem; font-weight: 700; color: var(--text-primary); }
.library-card-sub { font-size: 0.78rem; color: var(--text-muted); margin-top: 0.15rem; }
.library-chip {
    display: inline-block;
    padding: 0.18rem 0.5rem;
    background: var(--bg-surface-2);
    color: var(--text-secondary);
    border-radius: 999px;
    font-size: 0.76rem;
    font-weight: 600;
    margin-right: 0.3rem;
    margin-top: 0.3rem;
}
.library-empty {
    padding: 2rem 1rem;
    text-align: center;
    color: var(--text-muted);
    font-size: 0.88rem;
}
.library-detail {
    flex: 1;
    overflow-y: auto;
    padding: 1.4rem 1.8rem 3rem;
    background: var(--bg-page);
}
.library-bars { margin-top: 0.6rem; }
.library-bar-row { margin-bottom: 0.4rem; }
.library-bar-label {
    font-size: 0.75rem;
    display: flex; justify-content: space-between;
    color: var(--text-secondary); margin-bottom: 0.2rem;
}
.library-bar-pct { font-weight: 700; color: var(--text-primary); }
.library-bar-inner { height: 6px; background: var(--bg-surface-2); border-radius: 3px; overflow: hidden; }
.library-bar-fill { height: 100%; background: var(--brand-grad); border-radius: 3px; }

/* ---------- Library persona hero (2H design) ---------- */
.persona-hero {
    width: 100%;
    height: 96px;
    border-radius: 12px;
    position: relative;
    overflow: hidden;
    margin-bottom: 16px;
    background-image: radial-gradient(circle at 30% 40%, rgba(255,255,255,.18) 2px, transparent 2px);
    background-size: 15px 15px;
}
.persona-hero-pop {
    position: absolute; bottom: 11px; left: 14px;
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 700; font-size: 30px;
    color: rgba(11,11,15,.85);
}
.persona-name {
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 700; font-size: 24px;
    letter-spacing: -.01em;
    margin-bottom: 8px;
}
.persona-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.persona-tag {
    font-size: 12.5px; font-weight: 600;
    padding: 4px 10px; border-radius: 20px;
    background: rgba(20,33,61,.06); color: var(--text-muted);
}
.persona-portrait {
    font-size: 13px; line-height: 1.65; color: #c2c2cc;
    margin: 0 0 18px; max-width: 560px;
}
.persona-stats-grid {
    display: grid; grid-template-columns: repeat(4, 1fr);
    gap: 10px; max-width: 560px; margin-bottom: 18px;
}
.persona-stat {
    background: var(--inset); border: 1px solid rgba(20,33,61,.08);
    border-radius: 10px; padding: 11px;
}
.persona-stat-value { font-family: 'Space Grotesk', sans-serif; font-weight: 700; font-size: 18px; }
.persona-stat-label { font-size: 12px; color: #8a8a99; }
.persona-traits-title {
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 700; font-size: 12.5px; margin-bottom: 9px;
}
.persona-traits { display: flex; flex-direction: column; gap: 7px; margin-bottom: 8px; }
.persona-trait-row { display: flex; gap: 9px; font-size: 12px; color: var(--text-secondary); }
.persona-trait-arrow { flex: none; }

.profile-section {
    padding: 1rem 1.1rem;
    background: var(--bg-surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    margin-bottom: 0.8rem;
}
.profile-section h3 { font-size: 0.88rem; margin-bottom: 0.5rem; font-family: 'Space Grotesk', sans-serif; }

.tag-cloud { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.tag {
    padding: 0.2rem 0.55rem;
    border-radius: 999px;
    font-size: 0.78rem;
    font-weight: 600;
}
.tag-good { background: rgba(31,107,74,0.14); color: #1f6b4a; border: 1px solid rgba(31,107,74,0.28); }
.tag-bad  { background: rgba(140,47,57,0.14); color: #a8454f; border: 1px solid rgba(140,47,57,0.28); }

.do-item, .dont-item, .channel-item, .headline-item {
    padding: 0.5rem 0.7rem;
    background: var(--bg-surface-2);
    border-radius: var(--radius-sm);
    font-size: 0.82rem;
    margin-bottom: 0.35rem;
}
.do-item::before { content: "✓  "; color: var(--success); font-weight: 700; }
.dont-item::before { content: "✕  "; color: var(--danger); font-weight: 700; }

.collapsible-toggle {
    width: 100%; text-align: left;
    padding: 0.6rem 0.8rem;
    background: var(--bg-surface-2);
    color: var(--text-primary);
    border-radius: var(--radius-sm);
    font-weight: 600; font-size: 0.85rem;
    margin-top: 0.5rem;
    display: flex; justify-content: space-between; align-items: center;
}
.collapsible-toggle::after { content: "▾"; color: var(--text-muted); }
.collapsible-toggle.active::after { content: "▴"; }
.collapsible-content { display: none; padding: 0.8rem 0.1rem; }
.collapsible-content.open { display: block; }

/* ---------- 15. Group badges ---------- */
.group-badges { display: flex; gap: 0.4rem; margin-top: 0.3rem; flex-wrap: wrap; }
.group-badge {
    padding: 0.2rem 0.55rem;
    background: var(--bg-surface-2);
    border: 1px solid var(--border);
    border-radius: 999px;
    font-size: 0.76rem;
    font-weight: 600;
    color: var(--text-secondary);
}
#profile-lifemode-badge { background: rgba(124,140,255,.16); border-color: transparent; color: #a7b2ff; }
#profile-urbanization-badge { background: rgba(20,33,61,.06); border-color: transparent; color: var(--text-muted); }

/* ---------- 15b. Profile panel hero extra (design 1a) ---------- */
.profile-eyebrow {
    display: flex; align-items: center; gap: 7px;
    font-family: var(--font-mono); font-size: 12.5px; font-weight: 600;
    letter-spacing: .06em; text-transform: uppercase; color: var(--brand-500);
    margin-bottom: 10px;
}
.profile-eyebrow .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--brand-500); flex: none; }
.profile-panel-header h2 { font-family: 'Space Grotesk', sans-serif; font-size: 1.5rem; line-height: 1.1; }
.profile-hero-extra { padding: 0 1.2rem; }
.profile-hero-extra:empty { padding: 0; }
.profile-portrait { font-size: 0.82rem; line-height: 1.6; color: var(--text-secondary); margin: 0.8rem 0 0.9rem; }
.profile-stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 14px; }
.profile-cta-primary {
    width: 100%; margin-bottom: 8px; padding: 13px;
    display: flex; align-items: center; justify-content: center; gap: 8px;
}
.profile-cta-secondary {
    width: 100%; margin-bottom: 12px; padding: 10px;
    background: transparent; border: 1px solid var(--border-strong);
    color: var(--text-secondary); font-weight: 600; font-size: 0.78rem; border-radius: var(--radius-sm);
    cursor: pointer;
}
.profile-cta-secondary:hover { border-color: var(--brand-500); color: var(--brand-500); }

/* ---------- 16. Find similar ---------- */
.find-similar-section {
    padding: 0.8rem;
    background: var(--bg-surface-2);
    border-radius: var(--radius-md);
    margin-top: 0.7rem;
}
.find-similar-btn {
    width: 100%;
    padding: 0.5rem 0.8rem;
    background: var(--coral);
    color: #fffdf8;
    border-radius: var(--radius-sm);
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.82rem;
    margin-top: 0.45rem;
}

/* ---------- 17. Profile slide-in ---------- */
.profile-overlay {
    position: fixed; inset: 0;
    background: rgba(20,33,61,0.38);
    opacity: 0;
    visibility: hidden;
    transition: opacity .22s var(--ease), visibility .22s var(--ease);
    /* Sit just below the profile panel itself (9500) but above Leaflet (1000) */
    z-index: 9499;
}
.profile-overlay.open,
.profile-overlay.visible { opacity: 1; visibility: visible; }
.profile-panel {
    position: fixed; top: 0; right: 0;
    width: 480px; max-width: 100vw;
    /* Height must track the *visible* viewport, not the taller layout
       viewport. On mobile Safari/Chrome a fixed top:0/bottom:0 box is sized
       to the layout viewport, so the bottom of the scrolling body falls
       behind the browser chrome and the last content can't be scrolled into
       view. 100dvh (with a vh fallback) keeps the panel exactly one visible
       viewport tall — matching the dvh convention used across this app. */
    height: 100vh;
    height: 100dvh;
    background: var(--bg-surface);
    border-left: 1px solid var(--border);
    box-shadow: -20px 0 60px rgba(0,0,0,0.25);
    transform: translateX(100%);
    transition: transform .3s var(--ease);
    /* Above Leaflet (1000) and the More sheet (9000+) — profile panel must
       always be top-most so opening it from any tab works. */
    z-index: 9500;
    display: flex; flex-direction: column;
    /* Respect the safe-areas (notch / rounded corner / home indicator). The
       bottom inset keeps the last scrollable line clear of the iOS home bar. */
    padding-right: env(safe-area-inset-right);
    padding-top: env(safe-area-inset-top);
    padding-bottom: env(safe-area-inset-bottom);
}
.profile-panel.open,
.profile-panel.visible { transform: translateX(0); }
.profile-panel-header {
    padding: 1.2rem 1.2rem 0.8rem;
    border-bottom: 1px solid var(--border);
    position: relative;
    background: linear-gradient(180deg, rgba(140,47,57,0.10), transparent 80%);
}
.profile-panel-header h2 {
    font-size: 1.25rem; font-weight: 700; letter-spacing: -0.01em;
    padding-right: 2rem;
}
/* flex:1 + min-height:0 lets the body shrink below its content height and own
   its own scrollbar (without min-height:0 a flex child defaults to its content
   height and overflows the panel instead of scrolling internally). */
.profile-panel-body { padding: 1.2rem; overflow-y: auto; -webkit-overflow-scrolling: touch; flex: 1; min-height: 0; }
.close-btn {
    position: absolute; top: 0.9rem; right: 0.9rem;
    width: 36px; height: 36px; border-radius: 10px;
    font-size: 1.3rem; color: var(--text-primary);
    background: var(--bg-surface-2);
    border: 1px solid var(--border);
}
.close-btn:hover { color: var(--brand-500); border-color: var(--brand-500); }
@media (hover: none) and (pointer: coarse) {
    .close-btn { width: 44px; height: 44px; }
}

/* ---------- 18. Loading overlay ---------- */
.loading-overlay {
    position: fixed; inset: 0;
    background: rgba(8,8,11,0.74);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    display: none;
    align-items: center; justify-content: center;
    flex-direction: column; gap: 1.1rem;
    z-index: 9999;
    color: var(--text-primary);
}
.loading-overlay.active { display: flex; }
/* Radar sweep (design 4a): concentric rings + coral core + rotating wedge */
.spinner {
    position: relative;
    width: 84px; height: 84px;
    border-radius: 50%;
    border: 1.5px solid rgba(140,47,57,0.18);
    background: radial-gradient(circle at center, #8c2f39 0 4px, rgba(140,47,57,0.14) 5px 6px, transparent 7px);
}
.spinner::before {
    content: ""; position: absolute; inset: 16px; border-radius: 50%;
    border: 1.5px solid rgba(140,47,57,0.22);
}
.spinner::after {
    content: ""; position: absolute; inset: -1px; border-radius: 50%;
    background: conic-gradient(from 0deg, rgba(140,47,57,0) 300deg, rgba(140,47,57,0.55) 360deg);
    -webkit-mask: radial-gradient(circle, transparent 0 33%, #000 34%);
            mask: radial-gradient(circle, transparent 0 33%, #000 34%);
    animation: lp-sweep 1.4s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.loading-text { font-family: var(--font-mono); font-size: 0.8rem; font-weight: 600; letter-spacing: 0.06em; color: var(--lime); }

/* ---------- 19. (removed) legacy 3-group mobile nav + old More menu ----------
   The canonical mobile bottom nav + chips live in section 4c (.mobile-bottom-nav,
   .mobile-nav-btn, .mobile-nav-label, .msn-chip). The Model B "More" overflow
   sheet is defined near the mobile sheet host (.more-sheet / .more-item).
   The old .mobile-group-*, .mgc-chip, #mobileMoreMenu and .mobile-more-* rules
   were dead (no HTML/JS references) and were removed. */

/* PWA install */
.pwa-install-banner {
    position: fixed; left: 12px; right: 12px;
    /* Sit above the mobile bottom nav (~64px + safe-area) so it doesn't
       overlap or get covered; on desktop bottom nav is hidden so 16px is fine. */
    bottom: calc(72px + env(safe-area-inset-bottom));
    display: flex; align-items: center; gap: 0.8rem;
    padding: 0.7rem 0.9rem;
    background: var(--glass);
    backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
    border: 1px solid var(--glass-stroke);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    z-index: 60;
}
.pwa-install-banner[hidden] { display: none !important; }
@media (min-width: 901px) {
    .pwa-install-banner { bottom: 16px; }
}
.pwa-install-text { flex: 1; font-size: 0.9rem; }
.pwa-install-text strong { display: block; margin-bottom: 0.1rem; }
.pwa-install-actions { display: flex; gap: 0.3rem; align-items: center; }
#pwaInstallBtn { padding: 0.45rem 0.8rem; font-size: 0.9rem; min-height: 44px; }
.pwa-install-dismiss {
    width: 32px; height: 32px; border-radius: 8px;
    color: var(--text-secondary);
    font-size: 1.2rem;
    background: transparent;
    border: 0;
    cursor: pointer;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: color .15s var(--ease), background .15s var(--ease);
    flex-shrink: 0;
}
.pwa-install-dismiss:hover { color: var(--text-primary); background: var(--bg-surface-2); }
.pwa-install-dismiss:active { transform: scale(.95); }

/* ---------- 20. Skeletons ---------- */
.skeleton {
    background: linear-gradient(90deg, var(--bg-surface-2) 0%, var(--border) 50%, var(--bg-surface-2) 100%);
    background-size: 200% 100%;
    animation: shimmer 1.4s infinite;
    border-radius: 6px;
}
@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
.skeleton-heading { height: 14px; width: 60%; margin-bottom: 0.5rem; }
.skeleton-text { height: 10px; width: 100%; margin-bottom: 0.35rem; }
.skeleton-avatar { width: 36px; height: 36px; border-radius: 50%; }
.skeleton-card { padding: 0.7rem; background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius-sm); margin-bottom: 0.4rem; }
.skeleton-row { display: flex; align-items: center; gap: 0.6rem; }

/* ---------- 21. Toast notifications ---------- */
.toast-container {
    position: fixed;
    top: 80px; right: 16px;
    display: flex; flex-direction: column; gap: 0.4rem;
    z-index: 9998;
    pointer-events: none;
}
.toast {
    pointer-events: auto;
    padding: 0.7rem 0.95rem;
    background: var(--bg-surface);
    border: 1px solid var(--border);
    border-left: 3px solid var(--text-muted);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-toast);
    font-size: 0.82rem;
    color: var(--text-primary);
    min-width: 240px; max-width: 340px;
    animation: toastIn .28s var(--ease);
    display: flex; align-items: flex-start; gap: 0.55rem;
}
.toast.success { border-left-color: var(--lime); }
.toast.error   { border-left-color: var(--coral); }
.toast.info    { border-left-color: var(--sky); }
.toast.warning { border-left-color: var(--amber); }
@keyframes toastIn { from { transform: translateX(20px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes sheetUp { from { transform: translateY(100%); } to { transform: none; } }

/* ---------- 22. Onboarding tour ---------- */
.tour-overlay {
    position: fixed; inset: 0;
    background: rgba(20,33,61,0.42);
    z-index: 9000;
    display: flex; align-items: center; justify-content: center;
    animation: fade .25s var(--ease);
}
.tour-card {
    width: min(460px, calc(100% - 2rem));
    padding: 1.4rem;
    background: var(--bg-surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
}
.tour-card h3 { font-size: 1.1rem; margin-bottom: 0.4rem; }
.tour-card p { font-size: 0.9rem; color: var(--text-secondary); line-height: 1.55; }
.tour-dots { display: flex; gap: 0.3rem; margin: 1rem 0 0.8rem; }
.tour-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--border); }
.tour-dot.active { background: var(--brand-500); width: 18px; border-radius: 4px; }
.tour-footer { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; }
.tour-skip {
    padding: 0.5rem 0.8rem;
    color: var(--text-muted);
    font-size: 0.82rem;
}

/* ---------- 23. Utility ---------- */
.hidden { display: none !important; }
.flex { display: flex; }
.grid { display: grid; }

/* Geocode confirmation note — injected inline next to address inputs by
   geocodeForCoords(). Must stay in normal flow: an earlier re-skin styled
   this as a fixed full-screen modal, which turned every Report/Plan geocode
   into a permanent click-blocking overlay. */
.geocode-confirm {
    font-size: 0.78rem;
    color: #1f6b4a;
    margin: 0.3rem 0 0.5rem;
}

/* Mobile sheet host */
.mobile-sheet-backdrop {
    position: fixed; inset: 0;
    background: rgba(20,33,61,0.4);
    z-index: 65;
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s var(--ease);
}
.mobile-sheet-backdrop.active {
    opacity: 1;
    pointer-events: auto;
    animation: fade .22s var(--ease);
}

/* ===== Mobile "More" overflow sheet ===== */
/* (removed) Model B "More" overflow sheet — the More group now renders
   Library / Build a PDF as ordinary .msn-chip buttons like every other
   multi-tab group. */

/* ---------- 24. Responsive breakpoints ---------- */
@media (max-width: 900px) {
    :root {
        --mobile-header-h: 52px;
        --mobile-subnav-h: 40px;
        --mobile-bottomnav-h: 64px;
        --mobile-sidebar-maxh: 27vh;
    }

    .tabs { display: none; }
    .mobile-subnav { display: flex; }
    .mobile-bottom-nav {
        display: flex;
        position: fixed; bottom: 0; left: 0; right: 0;
        /* Must beat Leaflet (.leaflet-top/.leaflet-bottom = z-index 1000).
           Otherwise map controls/tiles render on top of the nav. */
        z-index: 1001;
        /* Solid background — blur makes map tiles bleed through on iOS */
        background: var(--bg-surface);
    }
    .tab-content { height: calc(100dvh - var(--standalone-top-inset) - var(--mobile-header-h) - var(--mobile-subnav-h) - var(--mobile-bottomnav-h) - env(safe-area-inset-bottom)); }
    body.has-pwa-banner .mobile-bottom-nav { box-shadow: 0 -2px 16px rgba(0,0,0,0.12); }

    /* Hide the floating persona legend on mobile — takes too much space
       and duplicates info already shown in the sidebar persona panel. */
    .legend { display: none !important; }

    /* Keep Leaflet's bottom-corner controls (attribution, zoom) above the
       map tiles but clearly BELOW the bottom nav */
    .leaflet-bottom { z-index: 500 !important; }

    .compare-maps { grid-template-columns: 1fr; }
    .compare-map-pane { display: none; }
    .compare-map-pane.active { display: block; }
    .mc-mobile-tabs {
        display: flex;
        padding: 0.3rem 0.8rem;
        background: var(--bg-surface);
        border-bottom: 1px solid var(--border);
        gap: 0.3rem;
    }
    .mc-mobile-tabs button {
        flex: 1;
        padding: 0.5rem;
        background: var(--bg-surface-2);
        color: var(--text-secondary);
        border-radius: var(--radius-sm);
        font-weight: 600;
        font-size: 0.82rem;
    }
    .mc-mobile-tabs button.active {
        background: var(--brand-grad);
        color: white;
    }

    .container, .score-container, .ask-container, .library-layout {
        flex-direction: column;
    }
    .sidebar, .score-sidebar, .ask-sidebar, .library-list-pane {
        width: 100%;
        max-height: 55%;
        border-right: 0;
        border-bottom: 1px solid var(--border);
    }
    #map, .score-map, .ask-map, .library-detail {
        min-height: 45%;
    }

    .li-panel { width: 100%; }
    .li-label-full { display: none; }
    .li-label-short { display: inline; }

    .legend {
        right: max(10px, env(safe-area-inset-right));
        bottom: calc(80px + env(safe-area-inset-bottom));
        max-width: min(200px, calc(100vw - 40px));
    }
}

@media (max-width: 520px) {
    /* Keep the safe-area top inset in the shorthand — a bare "padding" here
       would otherwise clobber the standalone header's padding-top (line ~189)
       on a phone PWA, dropping the notch/Dynamic-Island clearance and letting
       the header slide under it. --standalone-top-inset is 0 outside standalone,
       so normal mobile Safari is unaffected. */
    header { padding: calc(0.6rem + var(--standalone-top-inset)) 0.9rem 0.6rem; }
    header h1 { font-size: 0.95rem; }
    .mobile-nav-btn { font-size: 0.76rem; padding: 0.35rem 0.4rem; }
    .mobile-nav-btn svg { width: 18px; height: 18px; }
    .report-form { padding: 1rem; margin: 0.8rem auto; }
    .tab-content { height: calc(100dvh - var(--standalone-top-inset) - var(--mobile-header-h) - var(--mobile-subnav-h) - var(--mobile-bottomnav-h)); }
}

/* Touch targets on mobile — WCAG 2.5.5 target size is 44×44px */
@media (hover: none) and (pointer: coarse) {
    button, .tab-btn, .mobile-nav-btn, .lib-seg-btn, .bm-btn, .icon-btn, .ask-example, .li-tool-btn, .file-label, .wh-profile-btn, .pwa-install-dismiss,
    .ms-trigger, .ms-row, .canvas-camprow {
        min-height: 44px;
    }
    .icon-btn, .pwa-install-dismiss {
        min-width: 44px;
    }
    /* Small pill controls read fine a touch shorter than 44px; keep rows tidy. */
    .msn-chip, .canvas-vtab, .canvas-vtab-add, .canvas-vtab-del { min-height: 36px; }
    /* Keyboard / switch-control focus indicator — critical for a11y */
    :focus-visible {
        outline: 2px solid var(--brand-500);
        outline-offset: 2px;
    }
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* ==========================================================================
   MOBILE LAYOUT HARDENING (controls-first, bounded maps)
   These rules override earlier ones only on mobile viewports so that
   every tab behaves the same: controls visible at top, map/content
   below with a firm height cap.  Root cause this fixes:
     - Maps were carrying min-height:300px on mobile which squeezed sidebars.
     - .compare-inputs could wrap unbounded and steal all vertical space.
     - .library-detail was being treated as a "map" via the shared rule.
     - data-sheet-state was present in HTML but had no CSS.
   ========================================================================== */
@media (max-width: 900px) {
    /* 1. Make every tab a simple top-to-bottom column with guaranteed stacking */
    .container,
    .score-container,
    .ask-container,
    .library-layout,
    .compare-container,
    .li-layout {
        display: flex;
        flex-direction: column;
        height: 100%;
        width: 100%;
        overflow: hidden;
    }

    /* Every other tab wraps its .*-container INSIDE a .tab-content, so the
       height:100% above fills the already-bounded tab. #library-tab is the
       exception: it carries BOTH .tab-content AND .library-layout on one
       element, so that height:100% resolves against the full-viewport app
       shell and overrides .tab-content's bounded height. The tab then runs
       taller than the screen and its .library-detail child (where a selected
       persona profile renders) spills below the bottom nav — so the end of a
       profile can't be scrolled into view. Re-bind it to the visible viewport
       (id+class specificity beats the bare .library-layout rule). */
    #library-tab.library-layout {
        height: calc(100dvh - var(--standalone-top-inset) - var(--mobile-header-h) - var(--mobile-subnav-h) - var(--mobile-bottomnav-h) - env(safe-area-inset-bottom));
    }

    /* 2. Kill the 300px map floor on mobile — the biggest culprit */
    #map,
    .li-map,
    .score-map,
    .ask-map,
    .compare-map-pane {
        min-height: 0 !important;
        height: auto;
    }

    /* 3. Force sidebars FIRST (order 1) with hard size caps,
          force maps SECOND (order 2) to fill remaining space. */
    .sidebar,
    .score-sidebar,
    .ask-sidebar,
    .library-list-pane,
    .compare-inputs {
        order: 1;
        flex: 0 1 auto;
        width: 100%;
        max-height: var(--mobile-sidebar-maxh);
        min-height: 0;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
        border-right: 0;
        border-bottom: 1px solid var(--border);
        padding: 0.6rem 0.85rem;
        position: relative;
    }

    /* Scroll indicator — sticky chevron badge pinned at bottom of the
       scroll viewport so users know there's more content below the fold. */
    .sidebar::after,
    .score-sidebar::after,
    .ask-sidebar::after,
    .library-list-pane::after,
    .compare-inputs::after {
        content: 'Scroll ↓';
        position: sticky;
        bottom: 6px;
        left: 50%;
        display: block;
        width: max-content;
        margin: 6px auto -4px;
        padding: 4px 10px;
        font-size: 0.76rem;
        font-weight: 600;
        letter-spacing: 0.02em;
        color: #fff;
        background: var(--accent, #4f46e5);
        border-radius: 999px;
        box-shadow: 0 2px 8px rgba(0,0,0,0.25);
        pointer-events: none;
        opacity: 0.92;
        animation: lp-scroll-hint 1.4s ease-in-out infinite;
    }

    @keyframes lp-scroll-hint {
        0%,100% { transform: translateY(0); opacity: 0.85; }
        50%     { transform: translateY(3px); opacity: 1; }
    }

    /* Ask and Library no longer need the "Scroll ↓" nudge: Ask's sidebar is
       a single full-height chat column (no independent height cap since the
       map was removed from that tab), and Library's list pane already has
       its own visible scrollbar/segmented control making the affordance
       redundant. Score's sheet host got the same treatment when it moved to
       a draggable bottom sheet (see the #score-tab override further down). */
    #ask-tab .ask-sidebar::after,
    #library-tab .library-list-pane::after {
        display: none;
    }

    .sidebar h3,
    .score-sidebar h3,
    .ask-sidebar h3,
    .library-list-pane h3 {
        font-size: 0.85rem;
        margin-bottom: 0.4rem;
    }

    .sidebar input,
    .sidebar button:not(.ms-trigger),
    .score-sidebar input,
    .score-sidebar button:not(.ms-trigger),
    .ask-sidebar input,
    .ask-sidebar button:not(.ms-trigger),
    .library-list-pane input,
    .library-list-pane button:not(.ms-trigger),
    .compare-inputs input,
    .compare-inputs button:not(.ms-trigger) {
        height: 34px;
        font-size: 0.82rem;
    }

    .sidebar p,
    .score-sidebar p,
    .ask-sidebar p,
    .library-list-pane p {
        font-size: 0.74rem;
        line-height: 1.4;
    }

    /* These hint lines sit under multi-selects that get replaced by the
       chip-picker trigger button on every viewport (enhanceAllMultiSelects
       runs everywhere, not just mobile) — the chip trigger is taller than
       the native <select> these hints' negative top margins were tuned
       for, so on mobile they read as cramped against the button above
       them. .ms-kbd-hint ("Hold Ctrl/Cmd...") is also just wrong on
       mobile — there's no keyboard multi-select gesture on a touch chip
       picker — so it's hidden outright rather than re-spaced. */
    .ms-kbd-hint { display: none !important; }
    .ms-field-hint { margin: 0.35rem 0 0.6rem !important; }

    #map,
    .score-map,
    .ask-map,
    .li-map,
    .compare-maps {
        order: 2;
        flex: 1 1 auto;
        width: 100%;
        height: auto;
        max-height: none;
        min-height: 240px;
    }

    /* Score an Area ranked-results panel stacks below the map on mobile */
    .score-results {
        order: 3;
        width: auto;
        max-height: 34vh;
        margin: 0;
        border-radius: 0;
        border-left: 0; border-right: 0; border-bottom: 0;
        border-top: 1px solid var(--border);
    }

    /* 4. Library detail is NOT a map — treat it like a result pane */
    .library-detail {
        order: 2;
        flex: 1 1 auto;
        width: 100%;
        min-height: 40vh;
        max-height: 55vh;
        overflow-y: auto;
    }

    /* Ask map is desktop-only (design 2g) — on mobile the chat column is
       the whole tab, so hide the map pane and let the chat fill the
       available height instead of being capped like a sidebar that sits
       above a map. */
    #ask-tab .ask-map { display: none; }
    #ask-tab .ask-sidebar {
        max-height: none;
        flex: 1 1 auto;
        border-bottom: 0;
    }

    /* 5. Compare tab specifics: inputs stay at top, A/B switcher visible,
          maps sit below the switcher, results scroll.
          .compare-row is a desktop-only 3-column wrapper (maps | radar | table);
          on mobile it's collapsed out of the box model so .compare-maps and
          .compare-results go back to being direct flex children of
          .compare-container, keeping their existing order:3 / order:4 rules. */
    .compare-row { display: contents; }
    .compare-inputs {
        padding: 0.7rem 0.9rem;
        gap: 0.5rem;
    }
    .compare-input-group { flex: 1 1 46%; min-width: 0; }
    .compare-input-group[style*="120px"],
    .compare-input-group[style*="140px"],
    .compare-input-group[style*="240px"] {
        flex: 1 1 46% !important;
    }
    .compare-btn { flex: 1 1 100%; align-self: stretch; }
    .mc-mobile-tabs { order: 2; flex: 0 0 auto; }
    .compare-maps {
        order: 3;
        display: block;              /* override grid from desktop */
        height: 42vh;
    }
    .compare-map-pane { width: 100%; height: 100%; }
    .compare-map-pane.active { display: block; }
    .compare-map-pane:not(.active) { display: none; }
    .compare-results { order: 4; flex-direction: column; }
    .compare-card, .compare-table-card { width: 100%; height: auto; }

    /* 6. Lead Intelligence (analyze) on mobile:
          the banner + panel are absolutely positioned over the map on desktop.
          On mobile we need the banner to be reachable and the panel to be a sheet. */
    #analyze-tab .li-map {
        position: relative;          /* override inset: 0 absolute on mobile */
        inset: auto;
        order: 2;
        height: 42vh;
    }
    .li-top-banner {
        position: static;            /* no longer overlay */
        transform: none;
        order: 1;
        align-self: center;
        margin: 0.5rem auto;
        max-width: calc(100% - 18px);
    }
    .li-panel {
        position: fixed;             /* bottom sheet on mobile */
        left: 0; right: 0; top: auto; bottom: 0;
        width: 100%;
        max-height: 75vh;
        transform: translateY(100%);
        border-left: 0;
        border-top: 1px solid var(--border);
        border-top-left-radius: 20px;
        border-top-right-radius: 20px;
        box-shadow: 0 -18px 60px rgba(0,0,0,0.35);
    }
    .li-panel.open { transform: translateY(0); }

    /* 7. Ensure the mobile-sheet-host marker never collapses to zero
          (defensive — in case JS toggles data-sheet-state before CSS loads) */
    .mobile-sheet-host[data-sheet-state="closed"] { display: block; }
}

/* ==========================================================================
   Short-phone tweak: viewports under 520px are tight, so we trade a bit
   of map height for sidebar breathing room.
   ========================================================================== */
@media (max-width: 520px) {
    .sidebar,
    .score-sidebar,
    .ask-sidebar,
    .library-list-pane,
    .compare-inputs {
        max-height: var(--mobile-sidebar-maxh);
    }
    #map, .score-map, .ask-map, .li-map, .compare-maps,
    .compare-map-pane, .library-detail {
        height: auto;
        flex: 1 1 auto;
        min-height: 240px;
        max-height: none;
    }
    .compare-input-group { flex: 1 1 100%; }
}

/* ===== Campaign Canvas — quick-create floating form ===== */
/* Capped to the canvas and scrollable: #canvas-tab clips overflow and the page
   doesn't scroll, so on short viewports (e.g. 1080p at 125% scaling) an uncapped
   form hid its Save/Cancel buttons below the edge. */
.canvas-qc { position: absolute; top: 16px; left: 50%; transform: translateX(-50%); z-index: 1200; width: min(360px, 90%); max-height: calc(100% - 32px); overflow-y: auto; overscroll-behavior: contain; background: var(--panel, #141c2e); border: 1px solid var(--border, #2a3550); border-radius: 12px; padding: 14px 16px; box-shadow: 0 12px 40px -10px rgba(20,33,61,.3); display: flex; flex-direction: column; gap: 8px; }
.canvas-qc > * { flex-shrink: 0; }   /* scroll when capped; don't squash the fields */
.canvas-qc h4 { margin: 0 0 4px; }
.canvas-qc label { display: flex; flex-direction: column; gap: 3px; font-size: 12px; }
.canvas-qc input, .canvas-qc textarea, .canvas-qc select { padding: 6px 8px; border-radius: 6px; border: 1px solid var(--border, #2a3550); background: var(--bg, #0b1220); color: inherit; }
.canvas-qc-actions { display: flex; gap: 8px; margin-top: 6px; }
.canvas-qc-actions button { flex: 1; padding: 8px; border: 0; border-radius: 7px; background: #8c2f39; color: #fff; font-weight: 600; cursor: pointer; }
.canvas-qc-actions button.secondary { background: transparent; border: 1px solid var(--border, #2a3550); color: inherit; }
.canvas-qc-hint { margin: 2px 0 0; font-size: 12px; color: #fca5a5; min-height: 14px; }

/* ===== Phase 2 — scorecard breakdown ===== */
.canvas-sc-score { display: flex; align-items: center; gap: 12px; margin: 12px 0 8px; }
.canvas-ring { width: 54px; height: 54px; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: #fff; font-weight: 700; font-size: 17px; }
.canvas-ring--strong { background: #1f6b4a; } .canvas-ring--moderate { background: #a87a26; } .canvas-ring--weak { background: #8c2f39; }
.canvas-sc-band { font-weight: 600; }
.canvas-sub { margin: 7px 0; }
.canvas-sub-t { display: flex; justify-content: space-between; font-size: 12px; margin-bottom: 3px; }
.canvas-track { height: 6px; border-radius: 4px; background: rgba(148,163,184,.2); overflow: hidden; }
.canvas-track i { display: block; height: 100%; background: #64748b; }
.canvas-mix { margin: 12px 0; padding: 9px 10px; border-radius: 9px; background: rgba(148,163,184,.08); }
.canvas-mix-h { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; opacity: .6; margin-bottom: 7px; }
.canvas-mixrow { display: flex; align-items: center; gap: 6px; margin-bottom: 5px; font-size: 13px; }
.canvas-mixname { width: 90px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.canvas-mixbar { flex: 1; height: 6px; border-radius: 4px; background: rgba(148,163,184,.2); overflow: hidden; }
.canvas-mixbar i { display: block; height: 100%; background: #7c8cff; }
.canvas-mixpct { width: 32px; text-align: right; opacity: .7; }
.canvas-nudge { margin: 10px 0; padding: 10px 11px; border-radius: 9px; background: rgba(31,107,74,.10); border: 1px solid rgba(31,107,74,.3); font-size: 12px; line-height: 1.4; }
.canvas-why { font-size: 13px; opacity: .8; margin: 6px 0; }
.canvas-prov { font-size: 12px; opacity: .5; margin-top: 8px; line-height: 1.4; }
.canvas-sc-scoring, .canvas-sc-scoreerr, .canvas-sc-scoreph { font-size: 12px; opacity: .7; margin: 12px 0; }
.canvas-sc-actions { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
.canvas-sc-actions > button { width: 100%; }
.canvas-sc-actions-row { display: flex; gap: 8px; }
.canvas-sc-rescore, .canvas-sc-edit, .canvas-sc-del { flex: 1; min-width: 0; white-space: nowrap; padding: 8px 6px; border-radius: 8px; background: transparent; border: 1px solid var(--border,#2a3550); color: inherit; font-weight: 600; font-size: 0.85rem; cursor: pointer; }
.canvas-sc-rescore:hover, .canvas-sc-edit:hover { background: rgba(20,33,61,.08); }
.canvas-sc-del { color: #ff8a7a; border-color: rgba(140,47,57,.4); }
.canvas-sc-del:hover { background: rgba(140,47,57,.12); }
.canvas-sc-gen { background: linear-gradient(135deg,#a23a45,#8c2f39); border: 0; color: #fffdf8; font-weight: 700; }
.canvas-genname { font-weight: 700; margin: 8px 0 2px; }
.canvas-genprompt { font-size: 13px; opacity: .75; margin: 4px 0; line-height: 1.4; font-style: italic; }
.canvas-genflag { font-size: 13px; margin: 6px 0; padding: 6px 8px; border-radius: 7px; background: rgba(245,158,11,.12); border: 1px solid rgba(245,158,11,.35); color: #fbbf24; }
.canvas-vtabs { display: flex; gap: 5px; flex-wrap: wrap; margin: 6px 0 10px; }
.canvas-vtab { display: inline-flex; align-items: center; gap: 5px; padding: 4px 9px; border-radius: 20px; border: 1px solid var(--border,#2a3550); background: transparent; color: inherit; cursor: pointer; font-size: 13px; }
.canvas-vtab.active { background: #8c2f39; border-color: #8c2f39; color: #fff; }
.canvas-vtab-s { font-weight: 700; opacity: .85; }
.canvas-vtab-add, .canvas-vtab-del { padding: 4px 8px; opacity: .8; }
.canvas-nudge-act { margin: 6px 0 2px; padding: 6px 10px; border-radius: 7px; border: 1px dashed rgba(31,107,74,.5); background: transparent; color: #1f6b4a; cursor: pointer; font-size: 13px; }

/* ===== Canvas compare-variants modal ===== */
.canvas-compare { position: fixed; inset: 0; z-index: 3000; display: flex; align-items: center; justify-content: center; }
.cmp-backdrop { position: absolute; inset: 0; background: rgba(20,33,61,.4); }
.cmp-panel { position: relative; z-index: 1; width: min(94vw, 1100px); max-height: 88vh; overflow: hidden; display: flex; flex-direction: column; background: var(--panel,#141c2e); border: 1px solid var(--border,#2a3550); border-radius: 14px; box-shadow: 0 24px 70px -20px rgba(20,33,61,.35); }
.cmp-top { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; border-bottom: 1px solid var(--border,#2a3550); }
.cmp-top h3 { margin: 0; font-size: 15px; }
.cmp-close { background: transparent; border: 0; color: inherit; font-size: 18px; cursor: pointer; opacity: .7; }
.cmp-cols { display: flex; gap: 12px; overflow-x: auto; padding: 16px; }
.cmp-col { flex: 0 0 240px; background: var(--bg,#0b1220); border: 1px solid var(--border,#2a3550); border-radius: 10px; padding: 12px; }
.cmp-col.active { border-color: #8c2f39; box-shadow: 0 0 0 1px #8c2f39 inset; }
.cmp-h { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.cmp-label { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 50%; border: 1px solid var(--border,#2a3550); font-weight: 700; font-size: 12px; }
.cmp-label.active { background: #8c2f39; border-color: #8c2f39; color: #fff; }
.cmp-target { font-size: 13px; opacity: .8; }
.cmp-ring { width: 46px; height: 46px; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: #fff; font-weight: 700; font-size: 15px; margin: 4px 0; }
.cmp-band { font-size: 13px; font-weight: 600; margin-bottom: 8px; }
.cmp-noscore { font-size: 13px; opacity: .6; margin: 8px 0; }
.cmp-sub { margin: 5px 0; }
.cmp-sub-t { display: flex; justify-content: space-between; font-size: 12.5px; margin-bottom: 2px; }
.cmp-hl { font-weight: 700; font-size: 12.5px; margin: 10px 0 4px; line-height: 1.25; }
.cmp-body { font-size: 13px; opacity: .85; line-height: 1.35; margin-bottom: 5px; }
.cmp-offer { font-size: 13px; opacity: .8; margin-bottom: 5px; }
.cmp-cd { font-size: 12px; font-style: italic; opacity: .6; line-height: 1.35; margin-bottom: 8px; }
.cmp-activate { width: 100%; padding: 6px; border: 1px solid var(--border,#2a3550); border-radius: 7px; background: transparent; color: inherit; cursor: pointer; font-size: 13px; }
.canvas-vtab-cmp { border-style: dashed; opacity: .85; }
.canvas-sc-imgwrap { width: 100%; aspect-ratio: 3/2; border-radius: 10px; overflow: hidden; margin-bottom: 10px; background: rgba(148,163,184,.08); display: flex; align-items: center; justify-content: center; font-size: 12px; opacity: .9; }
.canvas-sc-imgwrap.loading { animation: cmppulse 1.4s ease-in-out infinite; }
.canvas-sc-imgwrap.err { color: #8c2f39; }
.canvas-sc-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.canvas-sc-img-btn { background: #8c2f39; border: 0; color: #fffdf8; font-weight: 600; }
.cmp-img { width: 100%; aspect-ratio: 3/2; object-fit: cover; border-radius: 8px; margin-bottom: 8px; }
/* Meta images are 1152x1440 (4:5): show them whole, not cropped to 3:2. */
.canvas-sc-imgwrap.is-portrait { aspect-ratio: 4/5; max-width: 320px; margin-left: auto; margin-right: auto; }
.cmp-img.is-portrait { aspect-ratio: 4/5; }
@keyframes cmppulse { 0%,100% { opacity:.5 } 50% { opacity:1 } }

.canvas-ws-btn { width: 100%; margin-top: 7px; padding: 10px; border: 1px dashed rgba(31,107,74,.4); border-radius: 9px; background: transparent; color: #1f6b4a; cursor: pointer; font-size: 12px; font-weight: 600; }
.canvas-ws-btn.on { background: rgba(31,107,74,.15); }
.ws-pop-h { font-weight: 700; color: #059669; }
.ws-none { opacity: .7; font-size: 13px; margin: 2px 0 6px; }
/* Literal colours, not theme vars: Leaflet renders popups on a white wrapper in
   both themes, so these are read against white regardless of --amber & co. The
   app's display amber (#a87a26) is ~1.9:1 on white and unreadable at 11px --
   this darker amber clears AA. Matches .ws-pop-h, which is likewise literal. */
.ws-measured { font-size: 13px; font-weight: 600; color: #059669; margin: 2px 0 0; }
.ws-estimated { font-size: 13px; font-weight: 600; color: #b45309; margin: 2px 0 0; }

/* ===== Custom bottom-sheet multi-select ===== */
.ms-native-hidden { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); opacity: 0; pointer-events: none; }
.ms-trigger { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; width: 100%; min-height: 44px; padding: 7px 10px; background: var(--bg-input); border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text-primary); font-family: inherit; font-size: 0.85rem; text-align: left; cursor: pointer; transition: border-color .15s var(--ease); }
.ms-trigger:hover { border-color: var(--border-focus); }
.ms-trigger .ms-ph { color: rgba(11,11,15,.6); }
.ms-trigger::after { content: "+ add"; margin-left: auto; padding: 3px 9px; border: 1px dashed rgba(11,11,15,.35); border-radius: 999px; font-size: 0.78rem; font-weight: 600; color: rgba(11,11,15,.75); }
.ms-trigger:disabled { opacity: 0.5; cursor: not-allowed; }
.ms-trigger:disabled::after { display: none; }
.ms-chip { display: inline-flex; align-items: center; gap: 5px; padding: 3px 9px; background: rgba(20,33,61,.08); color: #14213d; border: 1px solid rgba(11,11,15,.24); border-radius: 999px; font-size: 0.78rem; font-weight: 600; }
.ms-chip i { font-style: normal; font-weight: 700; opacity: .9; }
.ms-sheet { position: fixed; inset: 0; z-index: 2000; visibility: hidden; }
.ms-sheet.open { visibility: visible; }
.ms-backdrop { position: absolute; inset: 0; background: rgba(20,33,61,.4); opacity: 0; transition: opacity .2s var(--ease); }
.ms-sheet.open .ms-backdrop { opacity: 1; }
.ms-panel { position: absolute; left: 0; right: 0; bottom: 0; max-height: 80vh; display: flex; flex-direction: column; background: var(--bg-surface); border-top-left-radius: 18px; border-top-right-radius: 18px; padding-bottom: env(safe-area-inset-bottom); transform: translateY(100%); transition: transform .24s var(--ease); box-shadow: 0 -18px 60px rgba(0,0,0,.35); }
.ms-sheet.open .ms-panel { transform: none; }
.ms-grab { width: 40px; height: 4px; border-radius: 2px; background: var(--border); margin: 8px auto 6px; }
.ms-head { display: flex; align-items: center; justify-content: space-between; padding: 4px 14px 8px; }
.ms-head h4 { margin: 0; font-size: 0.95rem; }
.ms-done { padding: 6px 14px; font-size: 0.85rem; }
.ms-search { margin: 0 12px 8px; height: 40px; }
.ms-list { display: flex; flex-direction: column; gap: 6px; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 0 8px 8px; }
.ms-row { display: flex; align-items: center; gap: 10px; width: 100%; min-height: 46px; padding: 0 12px; background: var(--bg-input); border: 1px solid var(--border); border-radius: 10px; color: var(--text-primary); font-family: inherit; font-weight: 500; font-size: 0.9rem; text-align: left; cursor: pointer; transition: border-color .14s var(--ease), background .14s var(--ease); }
.ms-row:hover { border-color: var(--border-focus); }
.ms-row:active { background: var(--bg-surface-2); }
.ms-row.sel { background: rgba(140,47,57,.12); border-color: var(--brand-500); }
.ms-check { width: 20px; height: 20px; background: var(--bg-surface); border: 2px solid var(--border-strong); border-radius: 6px; flex: none; position: relative; }
.ms-row.sel .ms-check { background: var(--brand-500); border-color: var(--brand-500); }
.ms-row.sel .ms-check::after { content: ""; position: absolute; left: 6px; top: 2px; width: 5px; height: 10px; border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg); }
.ms-empty { padding: 12px; color: var(--text-muted); font-size: 0.85rem; }
/* Desktop (fine pointer, wide): the picker is a centered modal, not a bottom
   sheet. Mobile / touch keeps the sheet defined above. */
@media (min-width: 1025px) and (pointer: fine) {
    /* Visibility is driven by .ms-sheet (hidden/visible); the panel stays fully
       opaque and centered, with a subtle scale pop on open. */
    .ms-panel {
        left: 50%; right: auto; bottom: auto; top: 50%;
        transform: translate(-50%, -50%) scale(0.97);
        width: min(440px, 92vw); max-height: 68vh;
        border: 1px solid var(--border); border-radius: 16px;
        box-shadow: var(--shadow-lg);
        opacity: 1;
        transition: transform .2s var(--ease);
    }
    .ms-sheet.open .ms-panel { transform: translate(-50%, -50%) scale(1); }
    .ms-grab { display: none; }
}

/* ===== Plan a Campaign: reflowing input rows ===== */
.plan-row { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.plan-col { flex: 1 1 140px; min-width: 0; }
/* Full-width stacking only on the tightest phones; 360/375/390 stay 2-up. */
@media (max-width: 340px) { .plan-col { flex: 1 1 100%; } }
@media (max-width: 520px) { #plan-audit-map, #plan-expand-map { height: 46vh !important; } }

/* ===== Rendered result tables: scroll horizontally instead of overflowing ===== */
/* Scoped to the wide multi-column result containers (Compare metrics, Penetration,
   Lookalike/Campaign, Report). Simple 2-col market-card tables are untouched. */
@media (max-width: 600px) {
  #mc-table table,
  #pen-results table,
  #report-output table,
  #ll-results table,
  #pc-results table {
    display: block;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    white-space: nowrap;
    max-width: 100%;
    font-size: 0.78rem;
  }
}
.ws-seed { padding: 5px 9px; border: 0; border-radius: 6px; background: #10b981; color: #04130d; font-weight: 600; cursor: pointer; }

/* ===== Library segmented control: fit 3 pills on tight phones (fixes 320px overflow) =====
   Base is display:grid repeat(3,1fr); 1fr can't shrink below the nowrap label, so the
   3rd pill overflowed. minmax(0,1fr) lets columns shrink; label may wrap to 2 lines. */
@media (max-width: 400px) {
  .library-seg { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 3px; }
  .lib-seg-btn { font-size: 0.76rem; padding: 6px 2px; white-space: normal; line-height: 1.15; }
}

/* ===== Canvas mobile: quick-create + compare modal (placed after base defs so
   these overrides win without !important) ===== */
@media (max-width: 900px) {
  /* Quick-create form docks to the bottom instead of floating mid-map. */
  .canvas-qc { top: auto; bottom: 12px; left: 12px; right: 12px; transform: none; width: auto; max-height: 70vh; overflow-y: auto; padding-bottom: calc(14px + env(safe-area-inset-bottom)); }
  /* Compare-variants modal: fit width + horizontally swipeable columns. */
  .cmp-panel { width: 94vw; max-height: 88vh; }
  .cmp-cols { padding: 12px; gap: 10px; padding-bottom: calc(12px + env(safe-area-inset-bottom)); }
  .cmp-col { flex: 0 0 78vw; }
}

/* ===== Cross-cutting: landscape phones, tablets, safe areas ===== */
/* Landscape phones: the viewport is wide but short, so stacking vertically
   crushes the map. Go side-by-side (sidebar left, map right) to use the width. */
@media (max-height: 480px) and (orientation: landscape) {
  :root { --mobile-header-h: 44px; }
  /* Same standalone-inset preservation as the portrait rule above. */
  header { padding: calc(0.35rem + var(--standalone-top-inset)) 0.9rem 0.35rem; }
  .container, .score-container, .ask-container {
    flex-direction: row;
  }
  .sidebar, .score-sidebar, .ask-sidebar {
    order: 0; width: 44%; max-width: 320px; height: 100%; max-height: none;
    border-bottom: 0; border-right: 1px solid var(--border);
  }
  #map, .score-map, .ask-map {
    order: 1; height: 100%; min-height: 0; flex: 1 1 auto;
  }
  /* Ask map is desktop-only — landscape phones stay chat-only, so hide the
     map and let the chat column use the full width instead of the 44%
     split meant for a sidebar-next-to-map layout. */
  #ask-tab .ask-map { display: none; }
  #ask-tab .ask-sidebar {
    width: 100%; max-width: 720px; margin: 0 auto;
    border-right: 0;
  }
  /* These panes keep the reduced-height stack (less common in landscape). */
  .library-list-pane, .compare-inputs { max-height: 48vh; }
  .canvas-rail { max-height: 40vh; }
}
/* Tablets (521–900px): give maps more height; forms already reflow with the extra room. */
@media (min-width: 521px) and (max-width: 900px) {
  #map, .score-map, .ask-map, .li-map, .compare-maps { min-height: 46vh; }
  .canvas-map-wrap { min-height: 50vh; }
}
/* Safe-area clearance so the Lookalikes bottom-sheet content clears the home bar. */
@media (max-width: 900px) {
  .li-panel-body { padding-bottom: calc(16px + env(safe-area-inset-bottom)); }
}

/* ===== Mobile map result: draggable bottom half-sheet (design 3a) =====
   Portrait phones only (landscape uses the side-by-side rule above). Scoped to
   the Map tab: the map fills the pane; the sidebar floats as a sheet the user
   drags between peek / half / full via the grab handle. */
.sheet-grab { display: none; }
@media (max-width: 900px) and (orientation: portrait) {
  /* Map tab has no sub-nav chips (single-tab group), so reclaim that reserved
     ~40px band — the map + sheet fill right down to the bottom nav. */
  #map-tab.tab-content { height: calc(100dvh - var(--standalone-top-inset) - var(--mobile-header-h) - var(--mobile-bottomnav-h) - env(safe-area-inset-bottom)); }
  #map-tab .container { display: block; position: relative; height: 100%; overflow: visible; }
  #map-tab #map { position: absolute; inset: 0; height: 100%; min-height: 0; border-radius: 0; }
  #map-tab .legend { display: none !important; }

  #map-tab .sidebar.mobile-sheet-host {
    position: absolute; left: 0; right: 0; bottom: 0; order: 0;
    width: auto; max-width: none; max-height: none;
    z-index: 900;
    background: var(--sheet-bg);
    border: 0; border-top: 1px solid var(--border);
    border-radius: 18px 18px 0 0;
    box-shadow: 0 -20px 50px -14px rgba(0,0,0,.6);
    padding: 24px 1.1rem calc(1.4rem + env(safe-area-inset-bottom));
    overflow-y: auto; -webkit-overflow-scrolling: touch;
    transition: height .3s var(--ease);
    touch-action: pan-y;
  }
  #map-tab .sidebar[data-sheet-state="peek"] { height: 96px; }
  #map-tab .sidebar[data-sheet-state="half"] { height: 46vh; }
  #map-tab .sidebar[data-sheet-state="full"] { height: calc(100% - 24px); }
  #map-tab .sidebar[data-sheet-state="closed"] { height: 96px; }

  #map-tab .sheet-grab {
    display: flex; justify-content: center;
    position: sticky; top: 0; z-index: 3;
    margin: -24px -1.1rem 10px; padding: 9px 0 7px;
    background: var(--sheet-bg);
    cursor: grab; touch-action: none;
  }
  #map-tab .sheet-grab:active { cursor: grabbing; }
  #map-tab .sheet-grab span { width: 42px; height: 5px; border-radius: 3px; background: var(--border-strong); }
}

/* ===== Score tab structural fix (2026-07-17 incident) =====
   The first mobile-sheet attempt made .score-container itself BOTH the
   positioning context AND the sheet host, with .score-map as its DOM
   child. That's wrong on two counts, confirmed on a real device (not
   just computed-style checks, which don't reveal this): position:absolute
   on .score-map resolved against .score-container (its nearest positioned
   ancestor) instead of the tab, confining the map to the sheet's own small
   box; the position:fixed follow-up fixed the sizing in this pane's test
   browser but produced a blank map on real iOS Safari (a fixed-position
   descendant deep inside a scrolling/transitioning ancestor is a known
   WebKit trouble spot this pane's Chromium-based tooling can't catch).

   Fix: introduce .score-sheet as a real DOM wrapper around ONLY
   .score-sidebar + .score-results (mirrors #map-tab's own structure,
   where .container is a plain positioning context and .sidebar/#map are
   two independent siblings sharing it). .score-sheet carries
   mobile-sheet-host/data-sheet-state now, not .score-container.
   .score-container itself is unpositioned on desktop and a plain
   position:relative context on mobile — .score-sheet and .score-map are
   siblings inside it, so position:absolute on EITHER one resolves against
   the same shared ancestor. No position:fixed anywhere, no ancestor-
   stacking-context guessing required.

   Desktop keeps its original 3-column visual (sidebar | map | results)
   despite .score-sheet's new wrapper via display:contents (promotes
   .score-sidebar/.score-results to be genuine flex items of
   .score-container) + explicit order values, since DOM order is now
   sidebar, results, map (map moved to be .score-sheet's sibling) rather
   than the original sidebar, map, results. */
.score-sheet { display: contents; }

/* ===== Mobile Score tab: draggable bottom sheet (design 2a extended) =====
   Same peek/half/full mechanism as the Map tab (ux.js's generalized
   initMapSheet), but scoped to #score-tab and with two real differences:
     1. Score sits in the 3-tab "Analyze" mobile nav group, so its sub-nav
        chip row (Score/Compare/Lookalikes) stays visible — unlike Map,
        this block does NOT override #score-tab.tab-content's height, so it
        keeps inheriting the generic calc() that reserves --mobile-subnav-h.
     2. Score has a third pane (.score-results, the ranked-tract list) that
        Map doesn't. .score-sheet wraps .score-sidebar + .score-results as
        one unit; .score-map is its sibling. Both bind to the same
        positioned .score-container ancestor — same pattern as Map's
        .container/.sidebar/#map, just with one extra layer for the third
        pane. */
@media (max-width: 900px) and (orientation: portrait) {
  #score-tab .score-container {
    position: relative;
  }
  #score-tab .score-map {
    position: absolute; inset: 0; height: 100%; min-height: 0; border-radius: 0;
  }
  #score-tab .score-sheet {
    display: flex; flex-direction: column;
    position: absolute; left: 0; right: 0; bottom: 0;
    width: auto; max-width: none; max-height: none;
    z-index: 900;
    background: var(--sheet-bg);
    border: 0; border-top: 1px solid var(--border);
    border-radius: 18px 18px 0 0;
    box-shadow: 0 -20px 50px -14px rgba(0,0,0,.6);
    padding: 0 1.1rem calc(1.4rem + env(safe-area-inset-bottom));
    overflow-y: auto; -webkit-overflow-scrolling: touch;
    transition: height .3s var(--ease);
    touch-action: pan-y;
  }
  #score-tab .score-sheet[data-sheet-state="peek"] { height: 96px; }
  #score-tab .score-sheet[data-sheet-state="half"] { height: 46vh; }
  #score-tab .score-sheet[data-sheet-state="full"] { height: calc(100% - 24px); }
  #score-tab .score-sheet[data-sheet-state="closed"] { height: 96px; }

  /* Map's grab uses a negative top margin to pull itself into the sheet
     host's own 24px top padding (host and content are the same element
     there). Score's host has zero top padding instead (kept clean since
     .score-sidebar/.score-results are separate children below it) — so the
     24px top space the grab needs lives in the grab's own padding-top
     instead of a shared container inset. Net visual result is the same. */
  #score-tab .sheet-grab {
    display: flex; justify-content: center;
    position: sticky; top: 0; z-index: 3;
    margin: 0 -1.1rem 10px; padding: 24px 0 7px;
    background: var(--sheet-bg);
    cursor: grab; touch-action: none;
    flex: none;
  }
  #score-tab .sheet-grab:active { cursor: grabbing; }
  #score-tab .sheet-grab span { width: 42px; height: 5px; border-radius: 3px; background: var(--border-strong); }

  /* .score-sidebar and .score-results become plain stacked flex children of
     the sheet — undo the general hardening block's independent caps/order/
     borders/absolute-adjacent styling, since the sheet itself now owns
     scrolling and sizing. */
  #score-tab .score-sidebar {
    order: 0; flex: 0 0 auto;
    width: auto; max-width: none; max-height: none;
    min-height: 0; overflow: visible;
    border: 0; padding: 0.6rem 0 0;
    position: static;
  }
  #score-tab .score-sidebar::after { display: none; } /* "Scroll ↓" hint — not needed, the sheet isn't independently capped */
  #score-tab .score-results {
    order: 0; flex: 0 0 auto;
    width: auto; max-width: none; max-height: none;
    margin: 0.6rem 0 0; padding: 0;
    border: 0; border-top: 1px solid var(--border);
    border-radius: 0;
    overflow: visible;
    padding-top: 0.6rem;
  }
}

/* Desktop: .score-sheet is display:contents (see base rule above), so
   .score-sidebar/.score-results are genuine flex items of .score-container
   alongside .score-map — restore the original left-to-right visual order
   (sidebar | map | results) since DOM order is now sidebar, results, map.
   Scoped to min-width:901px (this file's own desktop cutoff, matching the
   max-width:900px used throughout) rather than left unscoped: the mobile
   hardening and landscape blocks already set their own order values on
   these same elements at equal specificity as a bare rule would, and while
   an ID-scoped #score-tab rule happens to numerically agree with both
   today, scoping this to desktop only keeps that from being a coincidence
   future edits could silently break. */
@media (min-width: 901px) {
  #score-tab .score-sidebar { order: 1; }
  #score-tab .score-map { order: 2; }
  #score-tab .score-results { order: 3; }
}

/* ===== Mobile Canvas/Coverage tab: draggable bottom sheet =====
   Same mechanism as Map/Score (ux.js's generalized initMapSheet, wired in
   the Canvas effort's Task 1). #canvas-tab already has position:relative
   from the base .tab-content rule, so — unlike Score, which needed an
   extra .score-container wrapper — .canvas-sheet and .canvas-map-wrap can
   bind directly to #canvas-tab as siblings with zero new wrapper elements.
   .canvas-qc and #canvasCompare are untouched here (out of scope, already
   have their own working mobile treatment) and are unaffected since they
   stay outside .canvas-sheet. */
@media (max-width: 900px) and (orientation: portrait) {
  #canvas-tab .canvas-map-wrap {
    position: absolute; inset: 0;
    flex: none;
    border-radius: 0; min-height: 0;
  }
  #canvas-tab .canvas-sheet {
    display: flex; flex-direction: column;
    position: absolute; left: 0; right: 0; bottom: 0;
    width: auto; max-width: none; max-height: none;
    z-index: 900;
    background: var(--sheet-bg);
    border: 0; border-top: 1px solid var(--border);
    border-radius: 18px 18px 0 0;
    box-shadow: 0 -20px 50px -14px rgba(0,0,0,.6);
    padding: 0 1.1rem calc(1.4rem + env(safe-area-inset-bottom));
    overflow-y: auto; -webkit-overflow-scrolling: touch;
    transition: height .3s var(--ease);
    touch-action: pan-y;
  }
  #canvas-tab .canvas-sheet[data-sheet-state="peek"] { height: 96px; }
  #canvas-tab .canvas-sheet[data-sheet-state="half"] { height: 46vh; }
  #canvas-tab .canvas-sheet[data-sheet-state="full"] { height: calc(100% - 24px); }
  #canvas-tab .canvas-sheet[data-sheet-state="closed"] { height: 96px; }

  #canvas-tab .sheet-grab {
    display: flex; justify-content: center;
    position: sticky; top: 0; z-index: 3;
    margin: 0 -1.1rem 10px; padding: 24px 0 7px;
    background: var(--sheet-bg);
    cursor: grab; touch-action: none;
    flex: none;
  }
  #canvas-tab .sheet-grab:active { cursor: grabbing; }
  #canvas-tab .sheet-grab span { width: 42px; height: 5px; border-radius: 3px; background: var(--border-strong); }

  /* .canvas-rail and .canvas-scorecard become plain stacked flex children
     of the sheet — undo the general hardening block's independent
     order/max-height/border/width overrides, since the sheet itself now
     owns scrolling and sizing. */
  #canvas-tab .canvas-rail {
    order: 0; flex: 0 0 auto;
    width: auto; max-width: none; max-height: none;
    min-height: 0; overflow: visible;
    border: 0; padding: 0.6rem 0 0;
    position: static;
  }
  #canvas-tab .canvas-scorecard {
    order: 0; flex: 0 0 auto;
    width: auto; max-width: none; max-height: none;
    margin: 0.6rem 0 0; padding: 0.6rem 0 0;
    border: 0; border-top: 1px solid var(--border);
    border-radius: 0;
    overflow: visible;
  }
  #canvas-tab .canvas-camplist { flex-wrap: nowrap; flex-direction: column; }
  #canvas-tab .canvas-camprow { flex: none; }
}

/* Desktop: .canvas-sheet is display:contents (see base rule above), so
   .canvas-rail/.canvas-scorecard are genuine flex items of .canvas-layout
   alongside .canvas-map-wrap — restore the original left-to-right visual
   order (rail | map | scorecard) since DOM order is now rail, scorecard,
   map-wrap (see the markup restructure that introduced .canvas-sheet). */
@media (min-width: 901px) {
  #canvas-tab .canvas-rail { order: 1; }
  #canvas-tab .canvas-map-wrap { order: 2; }
  #canvas-tab .canvas-scorecard { order: 3; }
}

/* ---------- Accessibility (WCAG 2.1 AA) ---------- */
/* 2.4.1 Bypass Blocks: visible only on keyboard focus. */
.lp-skip {
    position: absolute; left: 8px; top: -48px; z-index: 10000;
    background: var(--lime); color: #fffdf8; font-weight: 700;
    padding: 10px 16px; border-radius: 0 0 10px 10px; text-decoration: none;
    transition: top .15s var(--ease, ease);
}
.lp-skip:focus { top: 0; }

/* Section headings were <h3> under the <h1> with no <h2> between them, so the
   outline skipped a level (1.3.1). They are <h2> now; this keeps the visual
   weight they had, since the default h2 is 24px against the old 15.2px. */
.tab-content h2 { font-size: 0.95rem; font-weight: 700; margin: 0 0 8px; }
/* Former <h4> sub-headings, promoted to <h3> to close an h2 -> h4 skip.
   Keeps their smaller visual weight. */
.tab-content h3 { font-size: 0.82rem; font-weight: 700; margin: 0 0 6px; }

/* 1.4.3: dark-at-60%-alpha placeholder text on the coral chip measured
   3.33:1. Full opacity takes it past 4.5:1 and reads as intended. */
.ms-ph { color: var(--text-muted) !important; }

/* Leaflet ships its attribution link at #0078a8, which is 3.13:1 on the
   attribution box. Recolour rather than hide it -- the attribution is
   required by the tile licence. */
.leaflet-control-attribution a { color: #0b4f6c !important; text-decoration: underline; }

/* AI paywall call-to-action (401 sign in / 402 upgrade / locked creative).
   Large type on purpose: most buyers are 45-65. */
.lp-paywall-card { border: 1px solid rgba(140,47,57,.45); background: rgba(140,47,57,.08); border-radius: 12px; padding: 16px 18px; margin: 10px 0; }
.lp-paywall-card p { margin: 0 0 12px; font-size: 16px; line-height: 1.5; color: var(--text-primary); }
.lp-paywall-cta { display: inline-block; background: #8c2f39; color: #fffdf8; font-weight: 700; font-size: 16px; text-decoration: none; padding: 10px 18px; border-radius: 10px; }
.lp-paywall-cta:hover, .lp-paywall-cta:focus { background: var(--brand-hover); }

/* ===== Readability for owners 45-65 (2026-10-02) =====
   One place to tune it: a slightly larger base size (every rem grows ~6%),
   brighter muted text, and visible keyboard focus everywhere. Sizes under
   12px were raised to a 12-13px floor in-place above. */
html { font-size: 106.25%; }
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
    outline: 3px solid var(--lime); outline-offset: 2px; border-radius: 6px;
}
/* "My plan" in the app header: the Local Growth Plan entry point. */
.my-plan-link {
    display: inline-flex; align-items: center; min-height: 40px; padding: 0 14px; margin-right: 8px;
    border-radius: 10px; border: 1px solid rgba(31,107,74,.45); color: var(--lime);
    font-weight: 700; font-size: 0.9rem; text-decoration: none; white-space: nowrap;
}
.my-plan-link:hover { background: rgba(31,107,74,.08); }


/* ===== Private Bank: light maps ===== */
.leaflet-container { background: var(--map-bg); font-family: var(--font-body); }
/* map-utils.js tags the OSM fallback tiles .lp-tiles-darken and injects an
   invert() filter for the old dark theme. Neutralise it and warm the tiles. */
.leaflet-tile-pane .lp-tiles-darken, .lp-tiles-darken { filter: sepia(.22) saturate(.55) brightness(1.02) contrast(.95) !important; }
.leaflet-popup-content-wrapper, .leaflet-popup-tip { background: var(--surface); color: var(--ink); }

/* ===== Private Bank: overrides for inline styles that app.js writes =====
   app.js (frozen) emits a few inline colours chosen for the old dark theme.
   Re-map them here so nothing renders light-on-light. */
[style*="color:#f4f4f6"] { color: var(--text-primary) !important; }
[style*="color:#b6ff3a"] { color: var(--good) !important; }
[style*="color:#8c2f39"] { color: var(--brand) !important; }
[style*="color:#ffb020"] { color: var(--warn) !important; }
[style*="color:#a7b2ff"] { color: var(--indigo) !important; }
[style*="background:#8c2f39"] { background: var(--brand) !important; color: #fffdf8 !important; }
[style*="background:#0d0d12"] { background: var(--inset) !important; border-color: var(--border) !important; }

/* Multi-select trigger: the generic button rule gave it the brand fill (dark text
   on coral in the old theme). On ivory it is a plain input-style field. */
button.ms-trigger { background: var(--bg-input) !important; color: var(--text-primary) !important; box-shadow: none !important; border: 1px solid var(--border-strong) !important; }
.ms-trigger .ms-ph { color: var(--text-muted) !important; }

/* Off-canvas panels: their drop shadow bled into the viewport edge on the light theme. */
.li-panel:not(.open), .profile-panel:not(.visible) { box-shadow: none; }
