/* ============================================================
 * geoweave-shell.css — shell-owned styles.
 *
 * Introduced by the UI composition extraction (ADR-0021). Contains
 * all styles for surfaces the shell owns: three-column page layout,
 * sidebar (nav, brand, footer), center-column card scaffold, project
 * card (list + compact + layer panel), workflow card and stage
 * buttons, export card, error strip, and modal chrome (header,
 * stepper indicator, body/footer scaffold, buttons).
 *
 * Extended 2026-07-16 (Hotspot Finder slice Commit 1) with shared
 * step-content classes for extracted helpers: gwDemoFilterSurface,
 * gwCityPicker, gwZipGeocoder. See the "SHARED STEP-CONTENT
 * HELPERS" section at the bottom.
 *
 * NOT here: step-content styling that varies per tool. Tool-specific
 * styles (file dropzone, column mapping table, geocode progress feed,
 * review summary, review name input, error list) stay in the tool's
 * own CSS.
 *
 * Loaded AFTER geoweave-tokens.css and BEFORE any tool-specific CSS.
 * All rules verbatim from upload-geocode.css (pre-extraction). Any
 * divergence is a regression.
 * ============================================================ */

* { box-sizing: border-box; }

html, body {
    height: 100%;
    margin: 0;
    overflow: hidden;
    font-family: var(--font-primary);
    color: var(--color-text-primary);
    background: var(--color-bg-page);
}

.gw-ic {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.gw-ic svg { display: block; }

.hidden { display: none !important; }

/* ============================================================
 * THREE-COLUMN LAYOUT
 * ============================================================ */
.gw-sidebar {
    position: fixed;
    top: 0; left: 0; bottom: 0;
    width: 200px;
    z-index: 100;
    background: var(--color-bg-surface);
    border-right: 1px solid var(--color-border-default);
    display: flex;
    flex-direction: column;
    overflow-y: auto;
}

.gw-column {
    position: fixed;
    top: 0; bottom: 0;
    left: 200px;
    width: 240px;
    z-index: 50;
    background: var(--color-bg-page);
    border-right: 1px solid var(--color-border-default);
    overflow-y: auto;
    padding: 10px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.gw-map-zone {
    position: fixed;
    top: 0; right: 0; bottom: 0;
    left: 440px;
    z-index: 0;
}
#map { width: 100%; height: 100%; }

.gw-map-status {
    position: absolute;
    left: 50%; top: 50%;
    transform: translate(-50%, -50%);
    z-index: 1;
    font-size: 13px;
    color: var(--color-text-tertiary);
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    padding: 8px 14px;
    box-shadow: var(--shadow-sm);
}
.gw-map-status.hidden { display: none; }

/* ============================================================
 * SIDEBAR
 * ============================================================ */
.gw-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 16px 16px 12px;
    font-size: 17px;
    font-weight: 700;
    color: var(--color-text-primary);
    text-decoration: none;
    border-bottom: 1px solid var(--color-border-default);
}
.gw-brand .gw-ic { color: var(--color-action-primary); }

.gw-nav {
    flex: 1;
    padding: 8px 10px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.gw-nav-section-label {
    font-size: 11px;
    font-weight: 700;
    color: var(--color-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 14px 10px 6px;
}

.gw-nav-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 9px 10px;
    border-radius: var(--radius-md);
    font-size: 14px;
    font-weight: 500;
    color: var(--color-text-primary);
    text-decoration: none;
    transition: background var(--transition-fast);
    min-width: 0;
}
.gw-nav-item:hover { background: var(--color-bg-subtle); }
.gw-nav-item.active {
    background: var(--color-action-primary);
    color: var(--color-action-text);
}
.gw-nav-item .gw-ic { width: 20px; color: inherit; }

.gw-nav-item-label {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ADR-0045: requires-gated nav items — grayed, not hidden; the
   native title carries the reason, so pointer-events must stay on
   (pointer-events:none would suppress the tooltip). Navigation is
   prevented by GeoShell's delegated click handler. */
.gw-nav-item.gw-nav-disabled,
.gw-nav-item.gw-nav-disabled .gw-ic { color: var(--color-text-tertiary); }
.gw-nav-item.gw-nav-disabled { cursor: not-allowed; opacity: 0.6; }
.gw-nav-item.gw-nav-disabled:hover { background: transparent; }
.gw-nav-item-legacy { color: var(--color-text-tertiary); }
.gw-nav-item-legacy .gw-ic { color: var(--color-text-tertiary); }
.gw-nav-item-legacy:hover { color: var(--color-text-secondary); }
.gw-nav-item-legacy:hover .gw-ic { color: var(--color-text-secondary); }

/* Workflows nav section (ADR-0030 Claims 3/4). Entries are <button>s —
   selection is a project mutation, not navigation — so reset button
   chrome to match the anchor-based .gw-nav-item look. Inert in
   Commit 1; Commit 3 adds the delegated click handler and the
   .gw-nav-workflow-active indicator. */
.gw-nav-workflow {
    width: 100%;
    border: 0;
    background: transparent;
    /* font-family only — the `font:` SHORTHAND would reset size and
       weight to inherited values, and this rule sits later than
       .gw-nav-item at equal specificity, stomping its 14px/500.
       Buttons don't inherit family by default; size/weight/color
       come from .gw-nav-item like every other nav entry. */
    font-family: inherit;
    text-align: left;
    cursor: pointer;
}
.gw-nav-workflow .gw-ic:not([data-icon]) { width: 20px; }
.gw-nav-workflow-none { color: var(--color-text-tertiary); }
.gw-nav-workflow-none:hover { color: var(--color-text-secondary); }
.gw-nav-workflow-active {
    background: var(--color-action-primary);
    color: var(--color-action-text);
}
.gw-nav-workflow-active:hover { background: var(--color-action-primary); }
.gw-nav-workflow-active .gw-ic { color: inherit; }

.gw-sidebar-footer {
    margin-top: auto;
    padding: 12px 14px 14px;
    border-top: 1px solid var(--color-border-default);
    display: flex;
    flex-direction: column;
    gap: 2px;
    font-size: 12px;
}
.gw-identity-account {
    font-weight: 600;
    color: var(--color-text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.gw-identity-email {
    color: var(--color-text-tertiary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.gw-close-btn {
    margin-top: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 7px 10px;
    font-size: 12px;
    font-weight: 600;
    font-family: inherit;
    color: var(--color-text-secondary);
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background var(--transition-fast);
}
.gw-close-btn:hover { background: var(--color-bg-subtle); }
.gw-close-btn .gw-ic { width: 15px; }

/* ============================================================
 * MIDDLE COLUMN — card scaffold + region-specific
 * ============================================================ */
.gw-column-title { padding: 2px 4px 4px; }
.gw-column-title h1 {
    font-size: 20px;
    font-weight: 700;
    margin: 0 0 2px;
}
.gw-column-title p {
    font-size: 12px;
    color: var(--color-text-secondary);
    margin: 0;
}

.gw-btn-new-project {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 9px 12px;
    background: var(--color-action-primary);
    color: var(--color-action-text);
    border: 1px solid var(--color-action-primary);
    border-radius: var(--radius-sm);
    font-size: 12px;
    font-weight: 700;
    font-family: inherit;
    cursor: pointer;
    transition: filter var(--transition-fast);
}
.gw-btn-new-project:hover { filter: brightness(1.15); }
.gw-btn-new-project .gw-ic { width: 14px; }

.gw-card {
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
}
.gw-section-label {
    padding: 8px 12px;
    font-size: 11px;
    font-weight: 700;
    color: var(--color-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-bottom: 1px solid var(--color-border-default);
}
.gw-placeholder {
    padding: 14px 12px;
    font-size: 12px;
    color: var(--color-text-tertiary);
}

#gw-secondary-cards {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* Project card states */
.gw-project-current {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    border-bottom: 1px solid var(--color-border-subtle);
    cursor: pointer;
    transition: background var(--transition-fast);
    min-width: 0;
}
.gw-project-current:hover { background: var(--color-bg-muted); }
.gw-project-current-name {
    flex: 1;
    min-width: 0;
    font-size: 13px;
    font-weight: 700;
    color: var(--color-text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.gw-project-current .gw-ic { color: var(--color-text-tertiary); }

/* Button-only row (collapse-picker affordance). The text header this
   class once styled was removed in the duplicate-header fix — the
   region label is the scaffold's static .gw-section-label. */
.gw-project-list-header {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding: 8px 12px 6px;
}
.gw-project-list-header .gw-icon-btn { width: 22px; height: 22px; }

.gw-project-list { display: flex; flex-direction: column; }

.gw-project-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px 12px;
    border-top: 1px solid var(--color-border-subtle);
    cursor: pointer;
    transition: background var(--transition-fast);
    min-width: 0;
}
.gw-project-row:hover { background: var(--color-bg-muted); }
.gw-project-row.is-current { background: var(--color-bg-subtle); }
.gw-project-row-name {
    flex: 1;
    min-width: 0;
    font-size: 12px;
    font-weight: 600;
    color: var(--color-text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.gw-project-row.is-current .gw-project-row-name {
    color: var(--color-action-primary);
    font-weight: 700;
}

/* Layer panel */
.gw-layer-panel-label {
    padding: 8px 12px 4px;
    font-size: 11px;
    font-weight: 700;
    color: var(--color-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.gw-layer-list { display: flex; flex-direction: column; }
.gw-layer-row {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 4px 8px; /* 6 -> 4: two-line rows (ADR-0052) grow ~10px, not 16 */
    border-top: 1px solid var(--color-border-subtle);
    min-width: 0;
}
.gw-layer-row:hover { background: var(--color-bg-muted); }
.gw-layer-type { color: var(--color-text-tertiary); flex-shrink: 0; }
.gw-layer-type .gw-ic { width: 14px; }
/* Layer name slot (ADR-0052): two stacked lines — the derived kind
   ("Cluster Targets") in small secondary type over the stored anchor
   ("riverside cafe orders") in the previous single-line styling. Both
   ellipsize independently; the wrapper stays the fit-layer click target
   and carries the composed title tooltip. */
.gw-layer-name {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    cursor: pointer;
    padding: 2px 4px;
    border-radius: 4px;
}
.gw-layer-kind,
.gw-layer-anchor {
    display: block;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.gw-layer-kind {
    font-size: 11px;
    font-weight: 500;
    color: var(--color-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    line-height: 1.2;
}
.gw-layer-anchor {
    font-size: 12px;
    font-weight: 500;
    color: var(--color-text-primary);
    line-height: 1.3;
}
.gw-layer-name:hover .gw-layer-anchor { color: var(--color-action-primary); }
.gw-layer-row.is-hidden .gw-layer-anchor,
.gw-layer-row.is-hidden .gw-layer-kind,
.gw-layer-row.is-hidden .gw-layer-type { color: var(--color-text-tertiary); }

/* Layer-row action cluster (layer-order slice, 2026-08-19).
   Base rule applies everywhere; the collapse below is capability-
   gated so touch devices keep today's always-visible row. */
.gw-layer-actions {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}

/* Hover-reveal: hover-capable fine pointers collapse the action
   cluster until the row is hovered or holds keyboard focus. The eye
   (toggle-vis) sits outside .gw-layer-actions and stays pinned — a
   hidden layer must look hidden without hovering. Width-collapse
   (not opacity) so the name reclaims the space at rest; collapsed
   buttons remain keyboard-focusable so :focus-within can reveal;
   pointer-events guards stray clicks on collapsed controls. */
@media (hover: hover) and (pointer: fine) {
    .gw-layer-row .gw-layer-actions {
        width: 0;
        overflow: hidden;
        pointer-events: none;
    }
    .gw-layer-row:hover .gw-layer-actions,
    .gw-layer-row:focus-within .gw-layer-actions {
        width: auto;
        overflow: visible;
        pointer-events: auto;
    }
}

/* Icon buttons */
.gw-icon-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    padding: 0;
    background: none;
    border: none;
    border-radius: 4px;
    color: var(--color-text-tertiary);
    cursor: pointer;
    transition: background var(--transition-fast), color var(--transition-fast);
    flex-shrink: 0;
}
.gw-icon-btn:hover {
    background: var(--color-bg-subtle);
    color: var(--color-text-secondary);
}
.gw-icon-btn:disabled { color: var(--color-border-strong); cursor: default; }
.gw-icon-btn:disabled:hover { background: none; color: var(--color-border-strong); }
.gw-icon-btn.danger:hover { color: var(--color-danger); background: var(--color-danger-bg); }
.gw-icon-btn .gw-ic { width: 14px; }

/* Workflow stages */
.gw-stage {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 12px;
    border-bottom: 1px solid var(--color-border-subtle);
    font-size: 12px;
    text-decoration: none;
    color: var(--color-text-primary);
    background: none;
    border-left: none; border-right: none; border-top: none;
    width: 100%;
    text-align: left;
    font-family: inherit;
    cursor: pointer;
    transition: background var(--transition-fast);
}
.gw-stage:last-child { border-bottom: none; }
.gw-stage:hover { background: var(--color-bg-muted); }
.gw-stage .gw-ic { width: 18px; color: var(--color-text-tertiary); }
.gw-stage-label { font-weight: 600; }
.gw-stage-meta { margin-left: auto; color: var(--color-text-tertiary); display: flex; }
.gw-stage-meta .gw-ic { width: 14px; }
.gw-stage-ready .gw-ic { color: var(--color-text-primary); }
.gw-stage-ready .gw-stage-label { font-weight: 700; }
.gw-stage-coming-soon { cursor: default; color: var(--color-text-tertiary); }
.gw-stage-coming-soon:hover { background: none; }
.gw-stage-coming-soon .gw-ic { color: var(--color-border-strong); }
/* Locked — requirements unmet (ADR-0029 Claims 4 and 5). Muted like
   coming-soon, but cursor and hover are deliberately RETAINED: locked
   stages stay clickable for cross-tool navigation, and `cursor: default`
   is this sheet's signal for genuinely-unclickable. Legacy used
   `opacity: 0.45`; this sheet expresses stage state through color, not
   opacity, so it follows the shipped idiom instead. */
.gw-stage-locked .gw-stage-label { font-weight: 600; color: var(--color-text-tertiary); }
.gw-stage-locked .gw-ic { color: var(--color-border-strong); }
.gw-stage-soon-tag {
    margin-left: auto;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--color-text-tertiary);
}
/* Missing-requirement tag on a locked stage. Same shape as the Soon
   pill so the two read as siblings; not uppercased, because it carries
   a layer-type name ("Needs circles") rather than a status word. */
.gw-stage-need-tag {
    margin-left: auto;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--color-text-tertiary);
    white-space: nowrap;
}

/* Export.
   JSON is live (re-hosted). HTML and CSV are genuinely unbuilt and
   stay disabled — the base rule below assumes nothing about state;
   :disabled and :not(:disabled) diverge. */
.gw-export-row {
    display: flex;
    gap: 4px;
    padding: 8px 12px;
}
.gw-export-btn {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    padding: 8px 4px;
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-sm);
    font-size: 10px;
    font-weight: 700;
    font-family: inherit;
    transition: background var(--transition-fast), color var(--transition-fast);
}
.gw-export-btn .gw-ic { width: 20px; }

.gw-export-btn:not(:disabled) {
    color: var(--color-text-primary);
    cursor: pointer;
    opacity: 1;
}
.gw-export-btn:not(:disabled):hover {
    background: var(--color-bg-subtle);
    border-color: var(--color-border-strong);
}

.gw-export-btn:disabled {
    color: var(--color-text-tertiary);
    cursor: not-allowed;
    opacity: 0.6;
}

/* Dashboard publish pair (push-options slice v2; relaid 2026-09-14,
   owner request): side-by-side half-width text buttons under their
   own "Push Hyper Targets" section label — the export row stays
   three icon-columns wide. flex-direction: row is stated though it
   is the default, because the class name says col: .gw-push-col is
   historical from the stacked layout and load-bearing (enabler
   selector in geoweave-shell.js and the scaffold markup), so the
   name outlives the layout. Same enable/disable lifecycle as the
   row (GeoShell._updateExportButtons). */
.gw-push-col {
    display: flex;
    flex-direction: row;
    gap: 4px;
    padding: 0 12px 8px;
}
.gw-push-btn {
    flex: 1;
    padding: 8px 10px;
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-sm);
    font-size: 11px;
    font-weight: 700;
    font-family: inherit;
    transition: background var(--transition-fast), color var(--transition-fast);
}
.gw-push-btn:not(:disabled) {
    color: var(--color-text-primary);
    cursor: pointer;
    opacity: 1;
}
.gw-push-btn:not(:disabled):hover {
    background: var(--color-bg-subtle);
    border-color: var(--color-border-strong);
}
.gw-push-btn:disabled {
    color: var(--color-text-tertiary);
    cursor: not-allowed;
    opacity: 0.6;
}

/* Error strip */
.gw-error-strip {
    position: fixed;
    top: 12px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 300;
    max-width: 480px;
    padding: 10px 16px;
    background: var(--color-danger-bg);
    border: 1px solid var(--color-danger);
    color: var(--color-danger);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md);
    font-size: 13px;
    font-weight: 600;
}

/* Unlock notifications (unlock-notify slice, 2026-09-07, ADR-0045
   amendment). Toast stack top-right + sidebar unlock residue.
   Finite by design (2026-09-06 review 51:00-53:26): the pulse runs
   3 cycles then rests; toasts self-dismiss at 6s; the dot persists
   until first hover/click (GeoShell strips it). */
#gw-toasts {
    position: fixed;
    top: 12px;
    right: 12px;
    z-index: 300;
    display: flex;
    flex-direction: column;
    gap: 8px;
    pointer-events: none;
}
.gw-toast {
    pointer-events: auto;
    display: flex;
    align-items: flex-start;
    gap: 10px;
    width: 280px;
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    padding: 10px 10px 10px 0;
    cursor: pointer;
    overflow: hidden;
}
.gw-toast-accent {
    align-self: stretch;
    width: 4px;
    flex-shrink: 0;
    background: var(--color-success);
    border-radius: var(--radius-md) 0 0 var(--radius-md);
}
.gw-toast-body { flex: 1; min-width: 0; padding: 1px 0; }
.gw-toast-title { font-size: 13px; font-weight: 600; }
.gw-toast-sub {
    font-size: 12px;
    color: var(--color-text-secondary);
    margin-top: 2px;
}
.gw-toast-close {
    border: 0;
    background: transparent;
    color: var(--color-text-tertiary);
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
    padding: 0 4px;
    flex-shrink: 0;
}
.gw-toast-close:hover { color: var(--color-text-primary); }
.gw-toast-out { opacity: 0; transition: opacity 0.3s ease; }

.gw-nav-unlock-dot {
    /* unlock-enhance (2026-09-09, D1): 6px -> 8px for presence; the
       dot itself now moves — 5 cycles of scale + jiggle, then rests
       static until hover clears it (finite per the 2026-09-06
       review preference; engagement, not time, is the true end). */
    width: 8px;
    height: 8px;
    border-radius: var(--radius-full);
    background: var(--color-success);
    flex-shrink: 0;
}
@media (prefers-reduced-motion: no-preference) {
    .gw-toast { animation: gwToastIn 0.22s ease; }
    @keyframes gwToastIn {
        from { opacity: 0; transform: translateY(-6px); }
        to   { opacity: 1; transform: translateY(0); }
    }
    .gw-nav-unlocked { animation: gwUnlockPulse 0.9s ease 5; }
    @keyframes gwUnlockPulse {
        0%, 100% { background: transparent; }
        50%      { background: var(--color-success-bg); }
    }
    /* v2 (2026-09-09): CONTINUOUS until hover clears it — the
       owner's original spec ("disappearing when moused over" = the
       engagement is the end); v1's 5-cycle cap on the dot was a
       misread of a background-pulse adjustment, and a dot that
       rests after 4.5s is invisible to anyone who looks later —
       the exact problem this slice exists to fix. Punchier travel
       (1.5×, ±1.5px) so the motion reads at sidebar distance.
       Supersedes the finite-motion preference (2026-09-06 review)
       for the DOT only, by owner spec; the background pulse stays
       finite at 5. */
    .gw-nav-unlocked .gw-nav-unlock-dot {
        animation: gwUnlockDotLive 1.1s ease-in-out infinite;
    }
    @keyframes gwUnlockDotLive {
        0%, 100% { transform: scale(1) translateY(0); }
        25%      { transform: scale(1.5) translateY(-1.5px); }
        50%      { transform: scale(1.1) translateY(1.5px); }
        75%      { transform: scale(1.4) translateY(-0.5px); }
    }
}

/* ============================================================
 * MODAL CHROME — pinned to left:0 at 440px; covers sidebar + column.
 * Map to the right remains interactive per scoping Decision 14.
 *
 * Tool step content lives in the tool's own stylesheet.
 * ============================================================ */
.gw-modal {
    position: fixed;
    top: 0; left: 0; bottom: 0;
    width: 440px;
    z-index: 200;
    background: var(--color-bg-surface);
    box-shadow: var(--shadow-lg);
    display: flex;
    flex-direction: column;
    animation: gwModalIn 0.22s ease;
}
@keyframes gwModalIn {
    from { opacity: 0; transform: translateX(-16px); }
    to   { opacity: 1; transform: translateX(0); }
}

.gw-modal-header {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 20px 20px 14px;
    border-bottom: 1px solid var(--color-border-default);
    flex-shrink: 0;
}
.gw-modal-icon {
    width: 40px;
    height: 40px;
    background: var(--color-bg-subtle);
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-action-primary);
    flex-shrink: 0;
}
.gw-modal-title-block { flex: 1; min-width: 0; }
.gw-modal-title {
    font-size: 18px;
    font-weight: 700;
    color: var(--color-action-primary);
    margin: 0;
}
.gw-modal-subtitle {
    font-size: 13px;
    color: var(--color-text-secondary);
    margin: 2px 0 0;
}
.gw-modal-close {
    width: 32px;
    height: 32px;
    background: none;
    border: 1px solid var(--color-border-default);
    border-radius: 8px;
    color: var(--color-text-secondary);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: inherit;
    flex-shrink: 0;
    transition: background var(--transition-fast);
}
.gw-modal-close:hover { background: var(--color-bg-subtle); }

.gw-modal-stepper {
    display: flex;
    align-items: center;
    padding: 12px 20px;
    border-bottom: 1px solid var(--color-border-subtle);
    flex-shrink: 0;
    gap: 6px;
}
.gw-step-node {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    font-weight: 700;
    color: var(--color-text-tertiary);
    letter-spacing: 0.02em;
    text-transform: uppercase;
}
.gw-step-node-num {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--color-bg-subtle);
    color: var(--color-text-secondary);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    font-weight: 700;
}
.gw-step-node.done .gw-step-node-num {
    background: var(--color-success-bg);
    color: var(--color-success);
}
.gw-step-node.active {
    color: var(--color-text-primary);
}
.gw-step-node.active .gw-step-node-num {
    background: var(--color-action-primary);
    color: var(--color-action-text);
}
.gw-step-divider {
    flex: 1;
    height: 1px;
    background: var(--color-border-default);
    min-width: 12px;
}

.gw-modal-body {
    flex: 1;
    overflow-y: auto;
    padding: 20px;
}

.gw-modal-footer {
    display: flex;
    gap: 8px;
    padding: 14px 20px;
    border-top: 1px solid var(--color-border-default);
    flex-shrink: 0;
    justify-content: space-between;
}
.gw-modal-btn {
    padding: 9px 18px;
    /* ADR-0044 D10: subtle-bg + strong border at rest — the prior
       surface-bg/default-border pair vanished against the white modal
       footer (2026-09-02 review: Back button "kind of lost"). Applies
       to every non-primary modal button uniformly. */
    background: var(--color-bg-subtle);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    font-size: 13px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    color: var(--color-text-primary);
    transition: background var(--transition-fast);
}
.gw-modal-btn:hover:not(:disabled) { background: var(--color-bg-muted); }
.gw-modal-btn:disabled { opacity: 0.5; cursor: default; }
.gw-modal-btn.primary {
    background: var(--color-action-primary);
    color: var(--color-action-text);
    border-color: var(--color-action-primary);
}
.gw-modal-btn.primary:hover:not(:disabled) {
    background: var(--color-action-primary);
    color: var(--color-action-text);
    border-color: var(--color-action-primary);
    filter: brightness(1.15);
}
.gw-modal-btn.danger {
    background: var(--color-bg-surface);
    color: var(--color-danger);
    border-color: var(--color-danger);
}
.gw-modal-btn.danger:hover:not(:disabled) { background: var(--color-danger-bg); }

/* ============================================================
 * SHARED STEP-CONTENT HELPERS
 *
 * Extracted from find-similar.css by Hotspot Finder slice Commit 1
 * (2026-07-16). Rules that previously used the `.fs-*` prefix in
 * find-similar.css are moved here with the `.gw-demo-*`,
 * `.gw-city-picker-*`, and `.gw-zip-geocoder-*` prefixes so any
 * tool consuming the extracted helpers (gwDemoFilterSurface,
 * gwCityPicker, gwZipGeocoder) picks up the same visual language.
 *
 * See hotspot-finder-slice-scoping-<TS>.md Decision 5 for the
 * extraction rationale and posture-B group-filter design.
 * ============================================================ */

/* --- gwDemoFilterSurface: sliders (key + additional) --- */

.gw-demo-filter-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
}

.gw-demo-filter-chk {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    cursor: pointer;
}

.gw-demo-filter-label {
    font-size: 12px;
    flex: 1;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.gw-demo-filter-value {
    font-size: 12px;
    font-weight: 600;
    text-align: right;
    min-width: 70px;
    color: var(--color-text-primary);
}

.gw-demo-filter-slider {
    width: calc(100% - 22px);
    margin: 0 0 2px 22px;
    height: 4px;
    cursor: pointer;
    display: block;
}

/* BG slice D1 (2026-09-08): the input's own background is the fill
   gradient (painted by gwDemoFilterSurface's paintSlider — bandFor
   is the single band source). appearance:none makes that background
   the visible track; thumbs restyled to stay visible on it; Firefox
   track/progress neutralized so the gradient is the only fill. */
.gw-demo-filter-slider,
.gw-demo-group-slot-slider {
    -webkit-appearance: none;
    appearance: none;
    border-radius: 2px;
    background: #d1d5db;   /* pre-paint fallback; JS overrides */
}
.gw-demo-filter-slider::-webkit-slider-thumb,
.gw-demo-group-slot-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: #ffffff;
    border: 2px solid #6b7280;
    cursor: pointer;
}
.gw-demo-filter-slider::-moz-range-thumb,
.gw-demo-group-slot-slider::-moz-range-thumb {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: #ffffff;
    border: 2px solid #6b7280;
    cursor: pointer;
}
.gw-demo-filter-slider::-moz-range-track,
.gw-demo-group-slot-slider::-moz-range-track { background: transparent; }
.gw-demo-filter-slider::-moz-range-progress,
.gw-demo-group-slot-slider::-moz-range-progress { background: transparent; }

.gw-demo-filter-slider:disabled {
    opacity: 0.35;
    cursor: default;
}

.gw-demo-filter-range {
    font-size: 10px;
    color: var(--color-text-secondary);
    margin: -2px 0 4px 22px;
}

/* --- gwDemoFilterSurface: additional-filters collapsible --- */

.gw-demo-additional-toggle {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 12px;
    color: var(--color-action-primary);
    cursor: pointer;
    margin: 8px 0;
    background: none;
    border: none;
    padding: 0;
}

.gw-demo-additional-toggle:hover {
    text-decoration: underline;
}

.gw-demo-additional-body {
    display: none;
}

.gw-demo-additional-body.open {
    display: block;
}

/* --- gwDemoFilterSurface: match mode + tolerance --- */

.gw-demo-radio-group {
    display: flex;
    gap: 12px;
    margin-bottom: 8px;
}

.gw-demo-radio-label {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 13px;
    cursor: pointer;
}

.gw-demo-radio-label input[type="radio"] {
    margin: 0;
}

.gw-demo-tolerance-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
}

.gw-demo-tolerance-slider {
    flex: 1;
    height: 4px;
}

.gw-demo-tolerance-val {
    font-size: 12px;
    font-weight: 600;
    min-width: 40px;
    text-align: right;
}

/* --- gwDemoFilterSurface: group filters (Occupation/Industry) --- */

.gw-demo-group-panel {
    margin-top: 12px;
    padding: 8px;
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-sm);
    background: var(--color-bg-subtle);
}

.gw-demo-group-header {
    font-size: 12px;
    font-weight: 700;
    color: var(--color-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-bottom: 6px;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.gw-demo-group-logic {
    display: flex;
    gap: 6px;
    font-size: 11px;
    font-weight: 500;
    text-transform: none;
    letter-spacing: 0;
    color: var(--color-text-tertiary);
}

.gw-demo-group-logic-label {
    display: flex;
    align-items: center;
    gap: 3px;
    cursor: pointer;
}

.gw-demo-group-slot {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-bottom: 6px;
}

.gw-demo-group-slot-select {
    width: 100%;
    padding: 4px 6px;
    border: 1px solid var(--color-border-default);
    border-radius: 4px;
    font-size: 12px;
    background: var(--color-bg-surface);
    color: var(--color-text-primary);
}

.gw-demo-group-slot-slider-row {
    display: flex;
    align-items: center;
    gap: 6px;
}

.gw-demo-group-slot-slider {
    flex: 1;
    height: 4px;
}

.gw-demo-group-slot-value {
    font-size: 12px;
    font-weight: 600;
    min-width: 42px;
    text-align: right;
}

.gw-demo-group-slot-remove {
    background: none;
    border: none;
    color: var(--color-text-tertiary);
    cursor: pointer;
    padding: 0 4px;
    font-size: 14px;
    line-height: 1;
}

.gw-demo-group-slot-remove:hover {
    color: var(--color-danger);
}

.gw-demo-group-add {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    color: var(--color-action-primary);
    cursor: pointer;
    background: none;
    border: none;
    padding: 2px 0;
}

.gw-demo-group-add:disabled {
    color: var(--color-text-tertiary);
    cursor: default;
}

/* --- gwCityPicker --- */

.gw-city-picker-select {
    width: 100%;
    padding: 6px 8px;
    border: 1px solid var(--color-border-default);
    border-radius: 6px;
    font-size: 13px;
    background: var(--color-bg-surface);
    color: var(--color-text-primary);
}

/* --- gwZipGeocoder --- */

.gw-zip-geocoder-row {
    display: flex;
    gap: 6px;
}

.gw-zip-geocoder-input {
    flex: 1;
    padding: 6px 8px;
    border: 1px solid var(--color-border-default);
    border-radius: 6px;
    font-size: 13px;
    background: var(--color-bg-surface);
    color: var(--color-text-primary);
}

.gw-zip-geocoder-btn {
    padding: 6px 12px;
    border: 1px solid var(--color-border-default);
    border-radius: 6px;
    font-size: 12px;
    cursor: pointer;
    background: var(--color-bg-surface);
    color: var(--color-text-primary);
    font-family: inherit;
}

.gw-zip-geocoder-btn:hover:not(:disabled) {
    background: var(--color-bg-subtle);
}

.gw-zip-geocoder-btn:disabled {
    opacity: 0.5;
    cursor: default;
}

/* --- gwLocationPicker (location-picker slice, 2026-08-23) --- */

.gw-loc-picker-select {
    width: 100%;
    padding: 6px 8px;
    border: 1px solid var(--color-border-default);
    border-radius: 6px;
    font-size: 13px;
    background: var(--color-bg-surface);
    color: var(--color-text-primary);
}

.gw-loc-picker-empty {
    font-size: 12px;
    color: var(--color-text-secondary);
    padding: 6px 0;
}

.gw-loc-picker-minis {
    display: flex;
    gap: 6px;
    margin: 6px 0 0;
}

.gw-loc-picker-mini {
    background: none;
    border: 1px solid var(--color-border-default);
    border-radius: 4px;
    font-size: 11px;
    padding: 1px 7px;
    cursor: pointer;
    color: var(--color-text-secondary);
    font-family: inherit;
}

.gw-loc-picker-mini:hover {
    color: var(--color-action-primary);
    border-color: var(--color-action-primary);
}

.gw-loc-picker-list {
    max-height: 320px;
    overflow-y: auto;
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-sm);
    background: var(--color-bg-surface);
    margin-top: 6px;
}

.gw-loc-picker-row {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    box-sizing: border-box;
    padding: 6px 8px;
    border: none;
    border-bottom: 1px solid var(--color-border-subtle);
    background: none;
    font-size: 13px;
    text-align: left;
    cursor: pointer;
    color: var(--color-text-primary);
    font-family: inherit;
}

.gw-loc-picker-row:last-child {
    border-bottom: none;
}

.gw-loc-picker-row:hover {
    background: var(--color-bg-subtle);
}

.gw-loc-picker-name {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.gw-loc-picker-sub {
    font-size: 11px;
    color: var(--color-text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.gw-loc-picker-add {
    margin-top: 6px;
    padding: 6px 12px;
    border: 1px solid var(--color-border-default);
    border-radius: 6px;
    font-size: 12px;
    cursor: pointer;
    background: var(--color-bg-surface);
    color: var(--color-text-primary);
    font-family: inherit;
}

.gw-loc-picker-add:hover:not(:disabled) {
    background: var(--color-bg-subtle);
}

.gw-loc-picker-add:disabled {
    opacity: 0.5;
    cursor: default;
}

/* ============================================================
 * Responsive — three-column collapses on narrower viewports.
 * ============================================================ */
@media (max-width: 1199px) {
    .gw-sidebar { width: 180px; }
    .gw-column  { left: 180px; width: 220px; }
    .gw-map-zone { left: 400px; }
    .gw-modal   { width: 400px; }
}
@media (max-width: 767px) {
    .gw-column  { left: 0; width: 100%; z-index: 60; }
    .gw-map-zone { left: 0; }
    .gw-sidebar { width: 100%; z-index: 120; }
    .gw-modal   { width: 100%; z-index: 250; }
}


/* ============================================================
 * Shared step-content styles (routing slice, ADR-0031 Commit 2)
 *
 * Markup rendered by GwHelpers (gwFileDropZone, gwGeocodeLoop,
 * gwLayerNameField, gate markup) and by multiple tools' step
 * content. Moved here from upload-geocode.css / order-cluster.css,
 * which previously carried duplicated copies; values are the
 * upload-geocode originals. Tool-specific deviations are scoped
 * overrides in the tool's own CSS (see order-cluster.css's
 * .oc-section .gw-result-feed).
 * ============================================================ */

.gw-modal-dropzone {
    border: 2px dashed var(--color-border-strong);
    border-radius: var(--radius-lg);
    padding: 40px 24px;
    text-align: center;
    cursor: pointer;
    background: var(--color-bg-muted);
    transition: background 0.2s, border-color 0.2s;
}

.gw-modal-dropzone:hover,
.gw-modal-dropzone.drag-active {
    border-color: var(--color-text-tertiary);
    background: var(--color-bg-subtle);
}

.gw-modal-dropzone-icon {
    width: 52px;
    height: 52px;
    background: var(--color-bg-subtle);
    border-radius: var(--radius-lg);
    margin: 0 auto 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-text-tertiary);
}

.gw-modal-dropzone-title {
    font-size: 14px;
    font-weight: 600;
    color: var(--color-text-secondary);
    margin: 0;
}

.gw-modal-dropzone-sub {
    font-size: 12px;
    color: var(--color-text-tertiary);
    margin: 6px 0 18px;
}

.gw-modal-dropzone-badge {
    display: inline-block;
    padding: 4px 12px;
    border-radius: var(--radius-full);
    background: var(--color-bg-subtle);
    font-size: 11px;
    font-weight: 600;
    color: var(--color-text-secondary);
    letter-spacing: 0.02em;
}

.gw-template-link {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    margin-top: 12px;
    background: var(--color-bg-subtle);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-sm);
    text-decoration: none;
    color: var(--color-text-primary);
    font-size: 12px;
    font-weight: 600;
    transition: background var(--transition-fast);
}

.gw-template-link:hover { background: var(--color-bg-muted); }

.gw-template-link .gw-ic { width: 14px; color: var(--color-text-secondary); }

.gw-gate {
    padding: 20px 4px;
    text-align: center;
}

.gw-gate-icon {
    width: 52px;
    height: 52px;
    margin: 0 auto 14px;
    background: var(--color-bg-subtle);
    border-radius: var(--radius-lg);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-action-primary);
}

.gw-gate-title {
    font-size: 15px;
    font-weight: 700;
    color: var(--color-text-primary);
    margin: 0 0 6px;
}

.gw-gate-desc {
    font-size: 13px;
    color: var(--color-text-secondary);
    margin: 0 0 20px;
    line-height: 1.5;
}

.gw-progress {
    margin-bottom: 14px;
}

.gw-progress-bar {
    width: 100%;
    height: 8px;
    background: var(--color-bg-subtle);
    border-radius: var(--radius-full);
    overflow: hidden;
    margin-bottom: 6px;
}

.gw-progress-fill {
    height: 100%;
    background: var(--color-action-primary);
    transition: width 0.18s ease;
    width: 0%;
}

.gw-progress-label {
    font-size: 12px;
    color: var(--color-text-secondary);
}

.gw-result-feed {
    max-height: 320px;
    overflow-y: auto;
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-sm);
    background: var(--color-bg-surface);
}

.gw-result-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    border-top: 1px solid var(--color-border-subtle);
    font-size: 11px;
}

.gw-result-row:first-child { border-top: none; }

.gw-result-status {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
}

.gw-result-status.ok { background: var(--color-success); }

.gw-result-status.err { background: var(--color-danger); }

.gw-result-query {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--color-text-primary);
}

.gw-result-note {
    color: var(--color-text-tertiary);
    font-size: 10px;
    max-width: 45%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex-shrink: 0;
}

.gw-name-input-block { margin-bottom: 12px; }

.gw-name-label {
    display: block;
    font-size: 12px;
    font-weight: 600;
    color: var(--color-text-secondary);
    margin-bottom: 4px;
}

.gw-name-input {
    width: 100%;
    padding: 9px 12px;
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-sm);
    font-family: inherit;
    font-size: 13px;
    color: var(--color-text-primary);
    background: var(--color-bg-surface);
}

.gw-name-input:focus {
    outline: none;
    border-color: var(--color-action-primary);
    box-shadow: 0 0 0 3px rgba(31, 41, 55, 0.10);
}

/* ============================================================
 * CONTENT OVERLAY (ADR-0035) — page-scoped informational surface
 * over the map zone ONLY. The zone is z 0 (see the z-ladder at the
 * top of this file), so these children can never paint over the
 * column (50), sidebar (100), or modal (200) — mutual exclusion
 * with the modal is behavioral (GeoShell dismisses on activate),
 * not visual. Internal z 10 clears #map and .gw-map-status (z 1).
 * Mobile ≤767px: the full-width column covers the map zone,
 * overlay included — known and accepted (Commit 0 findings Q0.8).
 * Tokens: only names already in use in this file; card radius 12px
 * matches .gw-modal-icon's literal.
 * ============================================================ */
.gw-content-overlay {
    position: absolute;
    inset: 0;
    z-index: 10;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(31, 41, 55, 0.45);
    animation: gwOverlayIn 0.18s ease;
}
@keyframes gwOverlayIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}
.gw-content-overlay-card {
    width: min(720px, calc(100% - 48px));
    max-height: calc(100% - 48px);
    overflow: auto;
    background: var(--color-bg-surface);
    border-radius: 12px;
    box-shadow: var(--shadow-lg);
    padding: 20px 24px 24px;
}
.gw-content-overlay-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
}
.gw-content-overlay-head h2 {
    font-size: 18px;
    font-weight: 700;
    margin: 0 0 10px;
}
.gw-content-overlay-card video {
    display: block;
    width: 100%;
    border-radius: var(--radius-sm);
    background: #000;
}
.gw-content-overlay-body {
    font-size: 14px;
    line-height: 1.55;
    color: var(--color-text-secondary);
}
.gw-content-overlay-body p { margin: 0 0 10px; }
.gw-content-overlay-body p:last-child { margin-bottom: 0; }
/* Footer (ADR-0053): remember-dismissal checkbox left, Close right.
   Rendered only for versioned registry entries. Checkbox row borrows
   .gw-exp-row's shape; Close is a plain .gw-modal-btn. */
.gw-content-overlay-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 16px;
    padding-top: 14px;
    border-top: 1px solid var(--color-border-default);
}
.gw-content-overlay-remember {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    color: var(--color-text-secondary);
    cursor: pointer;
    user-select: none;
}
.gw-content-overlay-remember input { margin: 0; flex: none; }

/* Export picker (project-export slice Commit 2).
   Panel created lazily by geoweave-shell.js inside the Export card,
   after .gw-export-row. One checkbox row per layer; shading toggle in
   HTML mode only; confirm/cancel actions ride the column delegation. */
.gw-export-picker {
    padding: 8px 12px 10px;
    border-top: 1px solid var(--color-border-default);
}
.gw-exp-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 3px 0;
    font-size: 12px;
    color: var(--color-text-primary);
    cursor: pointer;
    user-select: none;
}
.gw-exp-row input {
    margin: 0;
    flex: none;
}
.gw-exp-name {
    flex: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.gw-exp-type {
    flex: none;
    font-size: 10px;
    font-weight: 700;
    color: var(--color-text-tertiary);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}
.gw-exp-shading {
    margin-top: 4px;
    padding-top: 6px;
    border-top: 1px dashed var(--color-border-default);
}
.gw-exp-actions {
    display: flex;
    gap: 4px;
    margin-top: 8px;
}
.gw-exp-btn {
    flex: 1;
    padding: 6px 4px;
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-sm);
    font-size: 11px;
    font-weight: 700;
    font-family: inherit;
    color: var(--color-text-primary);
    cursor: pointer;
    transition: background var(--transition-fast), color var(--transition-fast);
}
.gw-exp-btn:not(:disabled):hover {
    background: var(--color-bg-subtle);
    border-color: var(--color-border-strong);
}
.gw-exp-btn:disabled {
    color: var(--color-text-tertiary);
    cursor: not-allowed;
    opacity: 0.6;
}

/* === Layer summary (ADR-0041) — shell-owned read-only modal view === */
.gw-ls-created {
    font-size: 11px;
    color: var(--color-text-tertiary);
    margin-bottom: 8px;
}
.gw-ls-stats {
    display: flex;
    gap: 10px;
    margin-bottom: 10px;
}
.gw-ls-stat {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 8px 6px;
    background: var(--color-bg-subtle);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
}
.gw-ls-stat-num {
    font-size: 18px;
    font-weight: 700;
    color: var(--color-text-primary);
}
.gw-ls-stat-label {
    font-size: 11px;
    color: var(--color-text-secondary);
    margin-top: 2px;
    text-align: center;
}
.gw-ls-detail {
    width: 100%;
    border-collapse: collapse;
    font-size: 12px;
    margin-bottom: 10px;
}
.gw-ls-detail th {
    text-align: left;
    font-weight: 600;
    color: var(--color-text-secondary);
    padding: 4px 10px 4px 0;
    white-space: nowrap;
    vertical-align: top;
    width: 1%;
}
.gw-ls-detail td {
    color: var(--color-text-primary);
    padding: 4px 0;
}
.gw-ls-section-label {
    font-size: 11px;
    font-weight: 700;
    color: var(--color-text-tertiary);
    text-transform: uppercase;
    letter-spacing: 0.02em;
    margin: 10px 0 4px;
}
.gw-ls-list {
    max-height: 260px;
    overflow-y: auto;
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    margin-bottom: 8px;
}
.gw-ls-list-tall { max-height: 340px; }
.gw-ls-row {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding: 5px 10px;
    font-size: 12px;
    border-bottom: 1px solid var(--color-border-default);
}
.gw-ls-row:last-child { border-bottom: none; }
.gw-ls-flyable { cursor: pointer; }
.gw-ls-flyable:hover { background: var(--color-bg-subtle); }
.gw-ls-row-name {
    color: var(--color-text-primary);
    font-weight: 500;
    flex: none;
    max-width: 45%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.gw-ls-row-meta {
    color: var(--color-text-secondary);
    flex: 1;
    min-width: 0;
}
/* When a .gw-ls-row-sites span follows (SC circles rows), the meta strip
   holds its natural width on one line and the sites list takes the slack.
   Without these two rules the sites span (no rule at all before 2026-09-16)
   grabbed min-content width and squeezed meta into a one-token-per-line
   column — the hotels-mode layout bug. */
.gw-ls-row-meta-fixed {
    flex: none;
    white-space: nowrap;
}
.gw-ls-row-sites {
    color: var(--color-text-tertiary);
    font-size: 11px;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    cursor: pointer;
}
.gw-ls-row-sites:hover { text-decoration: underline; }
.gw-ls-row-detail {
    display: none;
    padding: 4px 10px 6px 28px;
    font-size: 11px;
    background: var(--color-bg-subtle);
    border-bottom: 1px solid var(--color-border-default);
}
.gw-ls-row-detail.open { display: block; }
.gw-ls-row-detail:last-child { border-bottom: none; }
.gw-ls-detail-line {
    display: flex;
    justify-content: space-between;
    gap: 8px;
    padding: 1px 0;
    color: var(--color-text-secondary);
}
.gw-ls-detail-line span:first-child {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.gw-ls-detail-line span:last-child {
    flex: none;
    color: var(--color-text-tertiary);
}
.gw-ls-swatch {
    flex: none;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    align-self: center;
    border: 1px solid var(--color-border-default);
}
.gw-ls-cap-note {
    font-size: 11px;
    color: var(--color-text-tertiary);
    margin: -4px 0 8px;
}
.gw-ls-gap {
    font-size: 11px;
    color: var(--color-text-tertiary);
    font-style: italic;
    padding: 6px 8px;
    background: var(--color-bg-subtle);
    border-radius: var(--radius-sm);
    margin-top: 8px;
}
