/* NC Tax Foreclosures - "Real Estate Modern" Design
   Mobile-first responsive design with dark mode support */

/* ============================================
   CSS Custom Properties (Design Tokens)
   ============================================ */
:root {
    /* Colors - Teal-based warm palette */
    --color-primary: #0d9488;
    --color-primary-light: #14b8a6;
    --color-primary-dark: #0f766e;
    --color-accent: #0891b2;
    --color-accent-light: #22d3ee;

    --color-success: #16a34a;
    --color-warning: #d97706;
    --color-error: #dc2626;

    --color-bg: #f8fafa;
    --color-bg-secondary: #ffffff;
    --color-bg-tertiary: #f1f5f4;

    --color-text: #111827;
    --color-text-secondary: #4b5563;
    --color-text-muted: #6b7280;

    --color-border: #e5e7eb;
    --color-border-dark: #d1d5db;

    /* Spacing */
    --space-xs: 0.25rem;
    --space-sm: 0.5rem;
    --space-md: 1rem;
    --space-lg: 1.5rem;
    --space-xl: 2rem;
    --space-2xl: 3rem;

    /* Typography */
    --font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
    --font-size-xs: 0.75rem;
    --font-size-sm: 0.875rem;
    --font-size-base: 1rem;
    --font-size-lg: 1.125rem;
    --font-size-xl: 1.25rem;
    --font-size-2xl: 1.5rem;
    --font-size-3xl: 2rem;

    /* Borders */
    --border-radius-sm: 0.375rem;
    --border-radius-md: 0.5rem;
    --border-radius-lg: 0.75rem;
    --border-radius-xl: 1rem;
    --border-radius-full: 9999px;

    /* Shadows */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.06);
    --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.08);

    /* Transitions */
    --transition-fast: 150ms ease;
    --transition-normal: 250ms ease;

    /* Touch targets */
    --min-touch-target: 44px;

    /* Status colors */
    --status-active: #16a34a;
    --status-upcoming: #2563eb;
    --status-future: #7c3aed;
    --status-finished: #6b7280;
    --status-redeemed: #dc2626;
    --status-pending: #d97706;

    /* "Ending soon" urgency band — barely-there warm tint so the rail
       reads as a distinct zone without shouting. Derived from
       --color-error to match the urgent day-badge. */
    --urgent-rail-bg: rgba(220, 38, 38, 0.04);
    --urgent-rail-border: rgba(220, 38, 38, 0.16);
}

/* ============================================
   Dark Mode
   ============================================ */
@media (prefers-color-scheme: dark) {
    :root {
        --color-primary: #2dd4bf;
        --color-primary-light: #5eead4;
        --color-primary-dark: #14b8a6;
        --color-accent: #22d3ee;
        --color-accent-light: #67e8f9;

        --color-bg: #0f1419;
        --color-bg-secondary: #1a2332;
        --color-bg-tertiary: #243040;

        --color-text: #f1f5f9;
        --color-text-secondary: #cbd5e1;
        --color-text-muted: #94a3b8;

        --color-border: #2d3a4a;
        --color-border-dark: #3d4f63;

        --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
        --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.4);
        --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.5);

        /* Lighter red base (red-400) — a #dc2626 tint disappears into
           the dark background at low alpha. */
        --urgent-rail-bg: rgba(248, 113, 113, 0.08);
        --urgent-rail-border: rgba(248, 113, 113, 0.22);
    }
}

/* ============================================
   Reset & Base Styles
   ============================================ */
*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html {
    font-size: 16px;
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
}

body {
    font-family: var(--font-family);
    font-size: var(--font-size-base);
    line-height: 1.6;
    color: var(--color-text);
    background-color: var(--color-bg);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* Safe area padding for notched devices */
@supports (padding: max(0px)) {
    body {
        padding-left: max(0px, env(safe-area-inset-left));
        padding-right: max(0px, env(safe-area-inset-right));
    }
}

/* ============================================
   Offline Banner
   ============================================ */
.offline-banner {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    background-color: var(--color-warning);
    color: white;
    text-align: center;
    padding: var(--space-sm) var(--space-md);
    font-size: var(--font-size-sm);
    font-weight: 600;
    z-index: 1000;
    transform: translateY(0);
    transition: transform var(--transition-normal);
}

.offline-banner.hidden {
    transform: translateY(-100%);
}

/* ============================================
   App Header - Clean White
   ============================================ */
.app-header {
    background: var(--color-bg-secondary);
    border-bottom: 1px solid var(--color-border);
    padding: var(--space-md) var(--space-lg);
    padding-top: calc(var(--space-md) + env(safe-area-inset-top, 0px));
    position: sticky;
    top: 0;
    z-index: 100;
}

.header-content {
    max-width: 1400px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--space-sm);
}

.header-content h1 {
    font-size: var(--font-size-xl);
    font-weight: 700;
    color: var(--color-primary);
    margin-bottom: 0;
}

.header-content .subtitle {
    display: none;
}

/* ============================================
   Main Content
   ============================================ */
.main-content {
    flex: 1;
    padding: var(--space-md);
    max-width: 1400px;
    margin: 0 auto;
    width: 100%;
}

/* ============================================
   Category Tabs - Pill Style
   ============================================ */
.category-tabs {
    display: flex;
    gap: var(--space-sm);
    margin-bottom: var(--space-md);
    padding: var(--space-xs) 0;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    background: transparent;
    box-shadow: none;
    border-radius: 0;
}

.category-tabs::-webkit-scrollbar {
    display: none;
}

.tab-btn {
    flex: 0 0 auto;
    min-height: 36px;
    padding: var(--space-xs) var(--space-md);
    font-size: var(--font-size-sm);
    font-weight: 500;
    color: var(--color-text-secondary);
    background-color: var(--color-bg-secondary);
    border: 1px solid var(--color-border);
    border-radius: var(--border-radius-full);
    cursor: pointer;
    transition: all var(--transition-fast);
    white-space: nowrap;
}

.tab-btn:hover {
    background-color: var(--color-bg-tertiary);
    border-color: var(--color-primary);
    color: var(--color-primary);
}

.tab-btn.active {
    background-color: var(--color-primary);
    color: white;
    border-color: var(--color-primary);
    font-weight: 600;
}

/* ============================================
   Tag Filter Row (Phase 2)
   ============================================ */
.tag-filter-section {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    margin-bottom: var(--space-md);
    padding: var(--space-xs) var(--space-sm);
    background: #eff6ff;
    border: 1px solid #bfdbfe;
    border-radius: var(--border-radius-md);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}
.tag-filter-section.hidden { display: none; }

.tag-filter-label {
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: #1e3a8a;
    flex-shrink: 0;
}

.tag-filter-chips {
    display: flex;
    gap: 8px;
    flex-wrap: nowrap;
}

.tag-filter-chip {
    flex: 0 0 auto;
    padding: 4px 12px;
    background: white;
    border: 1px solid #bfdbfe;
    border-radius: 9999px;
    font-size: 0.85rem;
    color: #1e3a8a;
    cursor: pointer;
    user-select: none;
    transition: all var(--transition-fast);
    white-space: nowrap;
}
.tag-filter-chip:hover { background: #dbeafe; }
.tag-filter-chip.active {
    background: #1e3a8a;
    color: white;
    border-color: #1e3a8a;
}
.tag-filter-chip .chip-count {
    margin-left: 4px;
    opacity: 0.7;
    font-size: 0.75rem;
}

/* ============================================
   Drive-by triage badges (backlog #8)
   ============================================ */
/* Card-footer badge showing the triage:skip/visit/bid decision written
   by triage.html. Shared by index and watchlist card renderers. */
.triage-badge {
    flex: 0 0 auto;
    padding: 2px 10px;
    border-radius: var(--border-radius-full);
    font-size: var(--font-size-xs);
    font-weight: 600;
    white-space: nowrap;
    border: 1px solid transparent;
}
.triage-badge.triage-bid {
    background: rgba(22, 163, 74, 0.12);
    color: var(--color-success);
    border-color: var(--color-success);
}
.triage-badge.triage-visit {
    background: rgba(217, 119, 6, 0.12);
    color: var(--color-warning);
    border-color: var(--color-warning);
}
.triage-badge.triage-skip {
    background: rgba(107, 114, 128, 0.12);
    color: var(--color-text-muted);
    border-color: var(--color-border-dark);
}

/* Card-footer note badge (notes v2) — marks rows where the signed-in
   user has a saved note (utils.js noteBadgeHtml; full text in the title
   attribute). Accent tint so it reads as "yours", not a listing status. */
.note-badge {
    flex: 0 0 auto;
    padding: 2px 10px;
    border-radius: var(--border-radius-full);
    font-size: var(--font-size-xs);
    font-weight: 600;
    white-space: nowrap;
    background: rgba(8, 145, 178, 0.10);
    color: var(--color-accent);
    border: 1px solid var(--color-accent);
}

/* ============================================
   Saved Searches Row (Phase 4a)
   ============================================ */
.saved-searches-section {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    margin-bottom: var(--space-md);
    padding: var(--space-xs) var(--space-sm);
    background: #f0fdf4;
    border: 1px solid #bbf7d0;
    border-radius: var(--border-radius-md);
    flex-wrap: wrap;
}

.saved-searches-label {
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: #14532d;
    flex-shrink: 0;
}

.saved-searches-chips {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    flex: 1 1 auto;
    min-width: 0;
}

.saved-search-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 4px 4px 12px;
    background: white;
    border: 1px solid #bbf7d0;
    border-radius: 9999px;
    font-size: 0.85rem;
    color: #14532d;
    cursor: pointer;
    user-select: none;
    transition: all var(--transition-fast);
    white-space: nowrap;
}
.saved-search-chip:hover { background: #dcfce7; }

.saved-search-name { font-weight: 500; }

.saved-search-bell,
.saved-search-delete {
    background: transparent;
    border: none;
    padding: 2px 6px;
    font-size: 0.9rem;
    line-height: 1;
    cursor: pointer;
    color: inherit;
    border-radius: 9999px;
    transition: background var(--transition-fast);
}
.saved-search-bell:hover { background: #fef3c7; }
.saved-search-delete {
    font-size: 1.1rem;
    color: #991b1b;
}
.saved-search-delete:hover { background: #fee2e2; }

.save-search-btn {
    flex-shrink: 0;
    padding: 4px 12px;
    background: white;
    border: 1px dashed #86efac;
    border-radius: 9999px;
    font-size: 0.85rem;
    color: #14532d;
    cursor: pointer;
    transition: all var(--transition-fast);
    white-space: nowrap;
}
.save-search-btn:hover {
    background: #dcfce7;
    border-style: solid;
}

/* ============================================
   Filters Section
   ============================================ */
.filters-section {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
    margin-bottom: var(--space-lg);
    padding: var(--space-md);
    background-color: var(--color-bg-secondary);
    border-radius: var(--border-radius-xl);
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--color-border);
}

.filters-row {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-sm);
}

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

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

/* Primary filter row holds 5 controls (county/type/status/search/sort);
   give each its own column on wide screens so the row never wraps and
   the filter block stays one row tall above the listings. */
@media (min-width: 1200px) {
    .filters-row-primary {
        grid-template-columns: repeat(5, 1fr);
    }
}

/* "More Filters" disclosure: dot on the button whenever a collapsed
   filter is actively constraining results. */
#more-filters-btn.has-active::after {
    content: '';
    display: inline-block;
    width: 8px;
    height: 8px;
    margin-left: 6px;
    border-radius: 50%;
    background: var(--color-primary);
    vertical-align: middle;
}

/* ============================================
   Urgency rail ("Ending soon")
   ============================================ */
.urgent-rail {
    margin-bottom: var(--space-sm);
    padding: var(--space-md);
    background: var(--urgent-rail-bg);
    border: 1px solid var(--urgent-rail-border);
    border-left: 3px solid var(--color-error);
    border-radius: var(--border-radius-lg);
}

.urgent-rail-header {
    display: flex;
    align-items: baseline;
    gap: var(--space-sm);
    margin-bottom: var(--space-sm);
}

.urgent-rail-title {
    font-size: var(--font-size-lg);
    color: var(--color-text);
}

/* Red count pill between the title and the "closing within N days"
   sub-line: "[6] auctions closing within 5 days". */
.urgent-rail-count {
    background: var(--color-error);
    color: #ffffff;
    font-size: var(--font-size-xs);
    font-weight: 600;
    line-height: 1.5;
    padding: 0 0.5rem;
    border-radius: var(--border-radius-full);
}

.urgent-rail-sub {
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
}

.urgent-rail-track {
    display: flex;
    gap: var(--space-md);
    overflow-x: auto;
    padding-bottom: var(--space-sm);
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
}

.urgent-rail-track .property-card-link {
    flex: 0 0 300px;
    scroll-snap-align: start;
}

/* ============================================
   Detail slide-over (desktop)
   ============================================ */
.detail-slideover {
    position: fixed;
    inset: 0;
    z-index: 1000;
}

.detail-slideover[hidden] {
    display: none !important;
}

.detail-slideover-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(15, 23, 42, 0.45);
}

.detail-slideover-panel {
    position: absolute;
    top: 0;
    right: 0;
    height: 100%;
    width: min(760px, 92vw);
    display: flex;
    flex-direction: column;
    background: var(--color-bg);
    box-shadow: -12px 0 40px rgba(0, 0, 0, 0.25);
    animation: slideover-in 0.22s ease-out;
}

@keyframes slideover-in {
    from { transform: translateX(40px); opacity: 0.4; }
    to   { transform: translateX(0);    opacity: 1; }
}

.detail-slideover-bar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: var(--space-sm) var(--space-md);
    border-bottom: 1px solid var(--color-border);
    background: var(--color-bg-secondary);
}

.detail-slideover-close {
    background: none;
    border: none;
    font-size: var(--font-size-base);
    font-weight: 600;
    color: var(--color-text);
    cursor: pointer;
    padding: var(--space-xs) var(--space-sm);
    border-radius: var(--border-radius-md);
}

.detail-slideover-close:hover {
    background: var(--color-bg-tertiary);
}

.detail-slideover-open-full {
    font-size: var(--font-size-sm);
    color: var(--color-primary);
    text-decoration: none;
}

.detail-slideover-open-full:hover {
    text-decoration: underline;
}

.detail-slideover-frame {
    flex: 1;
    width: 100%;
    border: none;
}

/* Lock page scroll behind the open panel. */
body.slideover-open {
    overflow: hidden;
}

.filter-group {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
}

.filter-group label {
    font-size: var(--font-size-xs);
    font-weight: 600;
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.filter-select,
.filter-input,
.search-input {
    min-height: var(--min-touch-target);
    padding: var(--space-sm) var(--space-md);
    font-size: var(--font-size-base);
    border: 1px solid var(--color-border);
    border-radius: var(--border-radius-lg);
    background-color: var(--color-bg);
    color: var(--color-text);
    width: 100%;
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.filter-select:focus,
.filter-input:focus,
.search-input:focus {
    outline: none;
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px rgba(13, 148, 136, 0.15);
}

.filters-actions {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-top: var(--space-sm);
    border-top: 1px solid var(--color-border);
}

.results-count {
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
    font-weight: 500;
}

.btn {
    min-height: var(--min-touch-target);
    padding: var(--space-sm) var(--space-lg);
    font-size: var(--font-size-sm);
    font-weight: 600;
    border-radius: var(--border-radius-lg);
    cursor: pointer;
    transition: all var(--transition-fast);
    border: none;
}

.btn-primary {
    background-color: var(--color-primary);
    color: white;
}

.btn-primary:hover {
    background-color: var(--color-primary-dark);
}

.btn-secondary {
    background-color: var(--color-bg-tertiary);
    color: var(--color-text);
    border: 1px solid var(--color-border);
}

.btn-secondary:hover {
    border-color: var(--color-primary);
    color: var(--color-primary);
}

/* ============================================
   Stats Section - Inline Strip
   ============================================ */
.stats-section {
    display: flex;
    gap: var(--space-sm);
    margin-bottom: var(--space-lg);
    padding: var(--space-sm) 0;
}

.stat-card {
    flex: 1;
    background-color: var(--color-bg-secondary);
    border-radius: var(--border-radius-lg);
    padding: var(--space-sm) var(--space-md);
    text-align: center;
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--color-border);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-sm);
}

.stat-value {
    font-size: var(--font-size-xl);
    font-weight: 700;
    color: var(--color-primary);
}

.stat-label {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-weight: 600;
}

/* ============================================
   Properties Section
   ============================================ */
.properties-section {
    margin-bottom: var(--space-xl);
}

.section-title {
    font-size: var(--font-size-lg);
    font-weight: 700;
    margin-bottom: var(--space-md);
    color: var(--color-text);
}

.properties-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
}

/* `display: flex` above wins over the [hidden] attribute's default
   `display: none`. The Map View toggle relies on [hidden] to swap
   between list and map, so we restore the spec behavior explicitly. */
.properties-list[hidden],
.map-host[hidden],
.nofix-section[hidden],
.map-legend[hidden],
.view-toggle[hidden],
.filters-advanced[hidden],
.urgent-rail[hidden] {
    display: none !important;
}

/* ============================================
   Property Card - Modern Real Estate Style
   ============================================ */
.property-card {
    background-color: var(--color-bg-secondary);
    border-radius: var(--border-radius-xl);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--color-border);
    transition: box-shadow var(--transition-fast), transform var(--transition-fast);
    cursor: pointer;
    position: relative;
}

.property-card:hover {
    box-shadow: var(--shadow-lg);
    transform: translateY(-2px);
}

.property-card:active {
    transform: translateY(0);
}

/* Status color strip at top of card */
.card-status-strip {
    height: 4px;
    width: 100%;
}

/* Street View thumbnail under the status strip. The wrap keeps a fixed
   height while the image streams in (no layout shift); onerror removes
   the whole wrap so a failed load collapses back to the text-only card. */
.card-thumb-wrap {
    height: 150px;
    background: var(--color-bg-tertiary);
    overflow: hidden;
}

.card-thumb {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.card-status-strip.status-active { background: var(--status-active); }
.card-status-strip.status-upcoming { background: var(--status-upcoming); }
.card-status-strip.status-future { background: var(--status-future); }
.card-status-strip.status-finished { background: var(--status-finished); }
.card-status-strip.status-redeemed { background: var(--status-redeemed); }
.card-status-strip.status-pending { background: var(--status-pending); }

/* Top row: county + actions */
.card-top-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: var(--space-md) var(--space-md) 0;
}

.card-top-actions {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
}

/* Days until sale badge */
.days-badge {
    font-size: var(--font-size-xs);
    font-weight: 700;
    padding: 2px 10px;
    border-radius: var(--border-radius-full);
    background: var(--color-bg-tertiary);
    color: var(--color-text-secondary);
}

.days-badge.urgent {
    background: #fef2f2;
    color: var(--color-error);
    animation: pulse-soft 2s ease-in-out infinite;
}

.days-badge.soon {
    background: #fffbeb;
    color: var(--color-warning);
}

/* Deal label chip (replaces the old numeric score badge). Users see the
   label, never a number; the title attribute carries the evidence line. */
.score-badge {
    font-size: var(--font-size-xs);
    font-weight: 600;
    padding: 2px 10px;
    border-radius: var(--border-radius-full);
    background: var(--color-bg-tertiary);
    color: var(--color-text-secondary);
    white-space: nowrap;
}

/* The user's OWN grade, shown in place of the site's computed one. Keeps the
   per-label colour so the grade still reads at a glance, and adds a ring in
   the label's own colour (currentColor, so it works on every deal-* variant
   and in both themes without a second rule) plus a leading check in the
   markup. The tooltip always names the site's read, so the two can never be
   confused for one another. */
.score-badge.is-my-rating {
    box-shadow: inset 0 0 0 1.5px currentColor;
}

.score-badge.deal-strong {
    background: #ecfdf5;
    color: #065f46;
}

.score-badge.deal-watch {
    background: #fffbeb;
    color: #92400e;
}

.score-badge.deal-thin {
    background: var(--color-bg-tertiary);
    color: var(--color-text-secondary);
}

/* Contradictory town/ZIP/county in the listing's source data
   (properties.location_flag): imagery is suppressed and this line warns
   the user. Same amber scheme as the other caution badges so it reads
   in light and dark mode alike. .no-building-note shares it: the county
   reports building values but records none for that parcel
   (properties.no_building_flag), so the deal grades against county land
   value and this line says to verify before bidding. .flood-note shares
   it too: FEMA maps the point in an elevated flood-risk zone
   (properties.flood_zone / flood_sfha), so check insurance cost. And
   .derived-note: the upset deadline was computed from the statute because
   the source publishes the date a bid WAS upset, not a deadline
   (property_snapshots.upset_deadline_is_derived) — the line names the
   basis and says to confirm it with the clerk. */
.location-flag-note,
.no-building-note,
.derived-note,
.flood-note {
    font-size: var(--font-size-xs);
    font-weight: 600;
    color: #92400e;
    background: #fef3c7;
    border: 1px solid #fbbf24;
    border-radius: var(--border-radius-sm, 6px);
    padding: 4px 10px;
    margin: 4px 0 6px;
}

.score-badge.deal-verify {
    background: #f5f3ff;
    color: #5b21b6;
}

/* Neutral data states: quiet outline, deliberately NOT a verdict color. */
.score-badge.deal-nodata,
.score-badge.deal-nobids {
    background: transparent;
    border: 1px solid var(--color-border);
    color: var(--color-text-secondary);
    font-weight: 500;
}

/* Location-context chip (market tier) — context, not a grade. */
.market-chip {
    font-size: var(--font-size-xs);
    font-weight: 500;
    padding: 2px 10px;
    border-radius: var(--border-radius-full);
    border: 1px solid var(--color-border);
    color: var(--color-text-secondary);
    white-space: nowrap;
}

@keyframes pulse-soft {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.7; }
}

/* County badge */
.property-county {
    display: inline-block;
    font-size: var(--font-size-xs);
    font-weight: 700;
    color: var(--color-primary-dark);
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

/* Property address */
.property-address {
    font-size: var(--font-size-lg);
    font-weight: 700;
    color: var(--color-text);
    padding: var(--space-xs) var(--space-md);
    line-height: 1.3;
}

/* Price/bid row */
.card-price-row {
    display: flex;
    /* Up to three value blocks now (bid / Zestimate / tax value) — wrap
       instead of clipping when a narrow card can't fit them side by side. */
    flex-wrap: wrap;
    gap: var(--space-lg);
    padding: var(--space-sm) var(--space-md);
    align-items: flex-end;
}

.card-bid,
.card-zestimate {
    display: flex;
    flex-direction: column;
}

.card-bid-label {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.card-bid-value {
    font-size: var(--font-size-2xl);
    font-weight: 800;
    color: var(--color-text-muted);
    line-height: 1.2;
}

.card-bid-value.has-bid {
    color: var(--color-success);
}

.card-zestimate-value {
    font-size: var(--font-size-lg);
    font-weight: 700;
    color: var(--color-primary);
    line-height: 1.2;
}

/* Details row */
.card-details-row {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-xs);
    padding: var(--space-sm) var(--space-md);
    margin: 0 var(--space-md);
    border-top: 1px solid var(--color-border);
    border-bottom: 1px solid var(--color-border);
}

.card-detail {
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.card-detail-label {
    font-size: 0.65rem;
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-weight: 600;
}

.card-detail-value {
    font-size: var(--font-size-sm);
    font-weight: 500;
    color: var(--color-text);
}

/* Card footer */
.card-footer {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    padding: var(--space-sm) var(--space-md) var(--space-md);
}

/* Status badge */
.property-status {
    font-size: var(--font-size-xs);
    padding: 3px 10px;
    border-radius: var(--border-radius-full);
    font-weight: 600;
}

.property-status.status-active {
    background-color: rgba(22, 163, 74, 0.1);
    color: var(--status-active);
}

.property-status.status-upcoming {
    background-color: rgba(37, 99, 235, 0.1);
    color: var(--status-upcoming);
}

.property-status.status-future {
    background-color: rgba(124, 58, 237, 0.1);
    color: var(--status-future);
}

.property-status.status-finished {
    background-color: rgba(107, 114, 128, 0.1);
    color: var(--status-finished);
}

.property-status.status-redeemed {
    background-color: rgba(220, 38, 38, 0.1);
    color: var(--status-redeemed);
}

.property-status.status-pending {
    background-color: rgba(217, 119, 6, 0.1);
    color: var(--status-pending);
}

/* Property type badge */
.property-type-badge {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    background-color: var(--color-bg-tertiary);
    padding: 2px var(--space-sm);
    border-radius: var(--border-radius-sm);
}

/* Property card links */
.property-card-link {
    text-decoration: none;
    color: inherit;
    display: block;
}

.property-card-link:hover .property-card {
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg);
    border-color: var(--color-primary);
}

/* ============================================
   Skeleton Loading
   ============================================ */
.skeleton-card {
    background: var(--color-bg-secondary);
    border-radius: var(--border-radius-xl);
    overflow: hidden;
    border: 1px solid var(--color-border);
}

.skeleton-strip {
    height: 4px;
    background: var(--color-border);
}

.skeleton-body {
    padding: var(--space-md);
}

.skeleton-line {
    height: 14px;
    background: linear-gradient(90deg, var(--color-bg-tertiary) 25%, var(--color-border) 50%, var(--color-bg-tertiary) 75%);
    background-size: 200% 100%;
    animation: shimmer 1.5s infinite;
    border-radius: var(--border-radius-sm);
    margin-bottom: var(--space-sm);
}

.skeleton-line.short { width: 30%; }
.skeleton-line.medium { width: 70%; }
.skeleton-line.long { width: 90%; height: 20px; }
.skeleton-line.price { width: 40%; height: 28px; margin-top: var(--space-sm); }

.skeleton-row {
    display: flex;
    gap: var(--space-md);
    margin-top: var(--space-sm);
}

.skeleton-row .skeleton-line {
    flex: 1;
}

@keyframes shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* ============================================
   Loading State
   ============================================ */
.loading-placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: var(--space-2xl);
    color: var(--color-text-muted);
}

.spinner {
    width: 40px;
    height: 40px;
    border: 3px solid var(--color-border);
    border-top-color: var(--color-primary);
    border-radius: 50%;
    animation: spin 1s linear infinite;
    margin-bottom: var(--space-md);
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

/* Empty State */
.empty-state {
    text-align: center;
    padding: var(--space-2xl);
    color: var(--color-text-muted);
}

.empty-state-icon {
    font-size: 3rem;
    margin-bottom: var(--space-md);
}

/* ============================================
   Footer
   ============================================ */
.app-footer {
    background-color: var(--color-bg-secondary);
    border-top: 1px solid var(--color-border);
    padding: var(--space-md);
    padding-bottom: calc(var(--space-md) + env(safe-area-inset-bottom, 0px));
    text-align: center;
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
}

/* ============================================
   Tablet Breakpoint (640px+)
   ============================================ */
@media (min-width: 640px) {
    .header-content h1 {
        font-size: var(--font-size-2xl);
    }

    .main-content {
        padding: var(--space-lg);
    }

    .filters-section {
        flex-direction: row;
        flex-wrap: wrap;
    }

    .filter-group {
        flex: 1;
        min-width: 180px;
    }

    .stat-card {
        padding: var(--space-md);
    }

    .stat-value {
        font-size: var(--font-size-2xl);
    }


    .card-details-row {
        grid-template-columns: repeat(3, 1fr);
    }
}

/* ============================================
   Desktop Breakpoint (1024px+)
   ============================================ */
@media (min-width: 1024px) {
    .properties-list {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
    }

    .stat-value {
        font-size: var(--font-size-3xl);
    }
}

/* ============================================
   Utility Classes
   ============================================ */
.hidden {
    display: none !important;
}

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

/* Focus visible for keyboard navigation */
:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

/* Reduced motion preference */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

/* ============================================
   Checkbox Dropdown Filters
   ============================================ */
.checkbox-dropdown {
    position: relative;
    width: 100%;
}

.dropdown-toggle {
    width: 100%;
    padding: var(--space-sm) var(--space-md);
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--border-radius-lg);
    cursor: pointer;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.9rem;
    color: var(--color-text);
    transition: border-color var(--transition-fast);
}

.dropdown-toggle:hover {
    border-color: var(--color-primary);
}

.dropdown-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1;
    text-align: left;
}

.dropdown-arrow {
    font-size: 0.65rem;
    margin-left: var(--space-sm);
    transition: transform var(--transition-fast);
}

.checkbox-dropdown.open .dropdown-arrow {
    transform: rotate(180deg);
}

.dropdown-menu {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--border-radius-lg);
    box-shadow: var(--shadow-lg);
    z-index: 1000;
    margin-top: 4px;
    max-height: 300px;
    display: none;
    flex-direction: column;
}

.checkbox-dropdown.open .dropdown-menu {
    display: flex;
}

.dropdown-search {
    padding: var(--space-sm);
    border-bottom: 1px solid var(--color-border);
}

.dropdown-search-input {
    width: 100%;
    padding: var(--space-xs) var(--space-sm);
    border: 1px solid var(--color-border);
    border-radius: var(--border-radius-sm);
    font-size: 0.85rem;
}

.dropdown-search-input:focus {
    outline: none;
    border-color: var(--color-primary);
}

.dropdown-options {
    overflow-y: auto;
    max-height: 180px;
    padding: var(--space-xs) 0;
}

.dropdown-option {
    display: flex;
    align-items: center;
    padding: var(--space-xs) var(--space-sm);
    cursor: pointer;
    transition: background-color var(--transition-fast);
}

.dropdown-option:hover {
    background-color: var(--color-bg-tertiary);
}

.dropdown-option input[type="checkbox"] {
    margin-right: var(--space-sm);
    width: 16px;
    height: 16px;
    cursor: pointer;
    accent-color: var(--color-primary);
}

.dropdown-option label {
    cursor: pointer;
    flex: 1;
    font-size: 0.85rem;
    user-select: none;
}

.dropdown-actions {
    display: flex;
    gap: var(--space-sm);
    padding: var(--space-sm);
    border-top: 1px solid var(--color-border);
    background: var(--color-bg-secondary);
    border-radius: 0 0 var(--border-radius-lg) var(--border-radius-lg);
}

.dropdown-actions button {
    flex: 1;
    padding: var(--space-xs) var(--space-sm);
    font-size: 0.75rem;
    border: 1px solid var(--color-border);
    border-radius: var(--border-radius-sm);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.btn-select-all {
    background: var(--color-primary);
    color: white;
    border-color: var(--color-primary) !important;
}

.btn-select-all:hover {
    opacity: 0.9;
}

.btn-clear-all {
    background: var(--color-bg);
    color: var(--color-text);
}

.btn-clear-all:hover {
    background: var(--color-bg-tertiary);
}

/* ============================================
   Property Detail Page - Enhanced Design
   ============================================ */
.detail-hero {
    background: linear-gradient(135deg, #0f766e 0%, #0d9488 50%, #14b8a6 100%);
    color: white;
    padding: var(--space-xl);
    border-radius: var(--border-radius-xl);
    margin-bottom: var(--space-xl);
    text-align: center;
}

.detail-badges {
    display: flex;
    justify-content: center;
    gap: var(--space-sm);
    margin-bottom: var(--space-md);
}

.card-header {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    padding: var(--space-md) var(--space-lg);
    border-bottom: 1px solid var(--color-border);
}

.card-header h2 {
    font-size: 1.1rem;
    margin: 0;
    color: var(--color-text);
}

/* Card color accents */
.auction-card .card-header {
    background: linear-gradient(90deg, #fef3c7 0%, #fef9c3 100%);
    border-bottom-color: #fcd34d;
}

.demographics-card .card-header {
    background: linear-gradient(90deg, #dcfce7 0%, #d1fae5 100%);
    border-bottom-color: #4ade80;
}

.tax-card .card-header {
    background: linear-gradient(90deg, #f3e8ff 0%, #fae8ff 100%);
    border-bottom-color: #c084fc;
}

.info-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: var(--space-sm) 0;
    border-bottom: 1px solid var(--color-border);
}

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

/* Responsive adjustments */
@media (max-width: 768px) {
    .detail-hero {
        padding: var(--space-lg);
    }

}

/* ============================================
   Watchlist Star Styles
   ============================================ */
.watchlist-star {
    /* Real <button> now (keyboard + screen-reader operable) — strip the
       UA button chrome so it still renders as a bare glyph. */
    background: none;
    border: none;
    font-size: 1.4rem;
    cursor: pointer;
    color: #94a3b8;
    transition: all 0.2s ease;
    padding: 4px;
    line-height: 1;
    user-select: none;
}

.watchlist-star:hover {
    color: #fbbf24;
    transform: scale(1.2);
}

.watchlist-star.starred {
    color: #fbbf24;
}

.watchlist-star.starred:hover {
    color: #f59e0b;
}

/* High-bidder marker on watchlist cards. Outbid-alerts uses this flag
   to render "you've been outbid" vs. the neutral wording in the
   daily email. Dimmed by default, solid gold when active. Auto-cleared
   server-side the moment the bid moves. */
.high-bid-marker {
    font-size: 1.2rem;
    cursor: pointer;
    transition: all 0.2s ease;
    padding: 4px;
    line-height: 1;
    user-select: none;
    opacity: 0.35;
    filter: grayscale(100%);
}
.high-bid-marker:hover {
    opacity: 0.85;
    filter: grayscale(30%);
    transform: scale(1.15);
}
.high-bid-marker.active {
    opacity: 1;
    filter: none;
}
.high-bid-marker.active:hover {
    transform: scale(1.1);
}
/* Card-level indicator so it's visible even when the marker is
   off-screen (e.g., scrolled). Subtle gold outline on the left strip. */
.property-card.is-user-high-bid {
    box-shadow: 0 0 0 2px #fbbf24 inset, var(--card-shadow, 0 1px 3px rgba(0,0,0,0.08));
}
.is-user-high-bid-badge {
    display: inline-block;
    font-size: 0.7rem;
    font-weight: 600;
    color: #92400e;
    background: #fef3c7;
    border: 1px solid #fbbf24;
    border-radius: 10px;
    padding: 1px 8px;
    margin-left: 6px;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

/* ============================================
   Watchlist card notes — indicator + quick-edit
   ============================================ */
/* Excerpt row on cards that carry a note; the whole row opens the
   inline editor. Sits between the details row and the footer. */
.card-note {
    display: flex;
    align-items: flex-start;
    gap: var(--space-sm);
    margin: 0 var(--space-md) var(--space-sm);
    padding: var(--space-sm);
    background-color: var(--color-bg-tertiary);
    border: 1px solid var(--color-border);
    border-radius: var(--border-radius-md);
    font-size: var(--font-size-sm);
    color: var(--color-text-secondary);
    text-align: left;
}
.card-note:hover {
    border-color: var(--color-primary);
}
.card-note-icon {
    flex-shrink: 0;
    line-height: 1.3;
}
.card-note-excerpt {
    flex: 1;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    white-space: pre-line;
    overflow-wrap: anywhere;
    line-height: 1.3;
}
.card-note-edit {
    flex-shrink: 0;
    color: var(--color-text-muted);
}
.card-note:hover .card-note-edit {
    color: var(--color-primary);
}

/* "Add note" chip on cards without one — quiet, right-aligned in the
   footer so note-less cards don't grow an empty box. */
.card-note-add {
    margin-left: auto;
    padding: var(--space-xs) var(--space-sm);
    border-radius: var(--border-radius-full);
    font-size: var(--font-size-xs);
    font-weight: 600;
    color: var(--color-text-muted);
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
}
.card-note-add:hover {
    color: var(--color-primary);
    background-color: var(--color-bg-tertiary);
}

/* Inline editor (replaces the excerpt row while open). cursor:default
   undoes the card's pointer since clicks here don't navigate. */
.card-note-editor {
    margin: 0 var(--space-md) var(--space-sm);
    cursor: default;
}
.card-note-textarea {
    width: 100%;
    box-sizing: border-box;
    min-height: 84px;
    padding: var(--space-sm);
    background-color: var(--color-bg-secondary);
    color: var(--color-text);
    border: 1px solid var(--color-border-dark);
    border-radius: var(--border-radius-md);
    font-family: inherit;
    font-size: var(--font-size-sm);
    line-height: 1.4;
    resize: vertical;
}
.card-note-textarea:focus {
    outline: none;
    border-color: var(--color-primary);
}
.card-note-editor-actions {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    margin-top: var(--space-xs);
}
.card-note-btn {
    min-height: 0;
    padding: var(--space-xs) var(--space-md);
    font-size: var(--font-size-xs);
}
.card-note-hint {
    margin-left: auto;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}

/* Watchlist button in header */
.watchlist-btn {
    background-color: var(--color-primary);
    color: white;
    border: none;
    padding: 8px 16px;
    border-radius: var(--border-radius-lg);
    font-size: 0.875rem;
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    transition: all 0.2s ease;
    margin-top: 0;
}

.watchlist-btn:hover {
    background-color: var(--color-primary-dark);
}

.header-actions {
    display: flex;
    align-items: center;
    gap: 10px;
}

.rehab-btn {
    background-color: rgba(255, 255, 255, 0.12);
    color: var(--color-primary-light, #5eead4);
    border: 1.5px solid var(--color-primary, #0d9488);
    padding: 8px 16px;
    border-radius: var(--border-radius-lg);
    font-size: 0.875rem;
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    transition: all 0.2s ease;
}

.rehab-btn:hover {
    background-color: var(--color-primary, #0d9488);
    color: white;
}

/* ============================================
   Notifications Bell + Panel (Piece 2)

   A bell button lives inside `.header-actions`. Clicking it toggles
   an absolutely-positioned dropdown panel that lists recent alert
   view-models. The badge shows the unread count (hidden at 0). The
   panel is scrollable when the list is long; fixed max-height keeps
   it from running off the bottom of the viewport on short screens.
   ============================================ */
.alerts-bell-wrap {
    position: relative;
    display: inline-flex;
}

.alerts-bell-btn {
    position: relative;
    background: rgba(255, 255, 255, 0.12);
    border: 1.5px solid var(--color-border, #e5e7eb);
    width: 40px;
    height: 40px;
    border-radius: var(--border-radius-full);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    transition: all 0.15s ease;
}

.alerts-bell-btn:hover {
    background: var(--color-bg-tertiary);
    border-color: var(--color-primary);
}

.alerts-bell-icon {
    font-size: 1.1rem;
    line-height: 1;
}

.alerts-bell-badge {
    position: absolute;
    top: -2px;
    right: -4px;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    background: var(--color-error, #dc2626);
    color: white;
    font-size: 0.7rem;
    font-weight: 700;
    border-radius: 9px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    box-shadow: 0 0 0 2px var(--color-bg-secondary, #ffffff);
}

.alerts-bell-badge[hidden] {
    display: none;
}

.alerts-panel {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    width: min(380px, calc(100vw - 24px));
    max-height: min(520px, calc(100vh - 120px));
    background: var(--color-bg-secondary, #ffffff);
    border: 1px solid var(--color-border, #e5e7eb);
    border-radius: var(--border-radius-lg);
    box-shadow: var(--shadow-lg);
    z-index: 200;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.alerts-panel[hidden] {
    display: none;
}

.alerts-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    border-bottom: 1px solid var(--color-border, #e5e7eb);
    background: var(--color-bg-tertiary, #f1f5f4);
    flex: 0 0 auto;
}

.alerts-panel-title {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--color-text, #111827);
}

.alerts-mark-all {
    background: transparent;
    border: none;
    color: var(--color-primary, #0d9488);
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
    padding: 4px 8px;
    border-radius: var(--border-radius-sm);
}

.alerts-mark-all:hover {
    background: rgba(13, 148, 136, 0.08);
}

.alerts-mark-all[hidden] {
    display: none;
}

.alerts-panel-body {
    flex: 1 1 auto;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

.alerts-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.alert-item {
    padding: 12px 16px;
    border-bottom: 1px solid var(--color-border, #e5e7eb);
    cursor: pointer;
    transition: background 0.12s ease;
    background: var(--color-bg-secondary, #ffffff);
}

.alert-item:last-child {
    border-bottom: none;
}

.alert-item:hover {
    background: var(--color-bg-tertiary, #f1f5f4);
}

.alert-item.is-read {
    background: var(--color-bg-secondary, #ffffff);
    opacity: 0.65;
}

.alert-item.is-read:hover {
    opacity: 0.9;
}

.alert-item-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 4px;
}

.alert-kind-badge {
    display: inline-block;
    padding: 2px 8px;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    border-radius: var(--border-radius-full);
    color: white;
}

.alert-badge-outbid    { background: var(--color-error, #dc2626); }
.alert-badge-bid       { background: var(--color-warning, #d97706); }
.alert-badge-deadline  { background: var(--color-accent, #0891b2); }
.alert-badge-status    { background: var(--color-text-muted, #6b7280); }
.alert-badge-stale     { background: #8b5cf6; }
.alert-badge-match     { background: var(--color-primary, #0d9488); }
.alert-badge-other     { background: var(--color-text-muted, #6b7280); }

.alert-time {
    font-size: 0.75rem;
    color: var(--color-text-muted, #6b7280);
}

.alert-title {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--color-text, #111827);
    margin-bottom: 4px;
    line-height: 1.3;
}

.alert-body {
    font-size: 0.8rem;
    color: var(--color-text-secondary, #4b5563);
    line-height: 1.4;
}

.alert-body-line + .alert-body-line {
    margin-top: 2px;
}

.alerts-empty {
    padding: 28px 20px;
    text-align: center;
    color: var(--color-text-muted, #6b7280);
}

.alerts-empty-icon {
    font-size: 1.6rem;
    margin-bottom: 8px;
}

.alerts-empty-sub {
    font-size: 0.8rem;
    margin-top: 6px;
    max-width: 260px;
    margin-left: auto;
    margin-right: auto;
}

/* ---- Piece 3: delivery prefs drawer
 *
 * Lives inside the bell panel body. The header grew a small action
 * cluster (mark-all + gear) so those rules live here too.
 */
.alerts-panel-header-actions {
    display: flex;
    align-items: center;
    gap: 4px;
}

.alerts-settings-btn {
    background: transparent;
    border: none;
    color: var(--color-text-muted, #6b7280);
    font-size: 1rem;
    line-height: 1;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background 0.12s ease, color 0.12s ease;
}

.alerts-settings-btn:hover {
    background: rgba(13, 148, 136, 0.08);
    color: var(--color-primary, #0d9488);
}

.alerts-settings-btn.is-active {
    /* The "gear pressed in" treatment — makes it obvious this is a
     * modal-ish toggle, not just a hover. */
    background: rgba(13, 148, 136, 0.14);
    color: var(--color-primary, #0d9488);
}

.alerts-settings {
    padding: 14px 16px 18px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.alerts-settings-intro {
    font-size: 0.82rem;
    color: var(--color-text-muted, #6b7280);
    line-height: 1.35;
}

.alerts-settings-grid {
    display: flex;
    flex-direction: column;
    /* Separator lines between rows — read order is top-to-bottom. */
    border-top: 1px solid var(--color-border, #e5e7eb);
}

.alerts-settings-row {
    display: grid;
    /* Info column takes remaining width; the two channel toggles are
     * fixed-width so they line up vertically across rows. */
    grid-template-columns: 1fr auto auto;
    column-gap: 10px;
    align-items: center;
    padding: 10px 0;
    border-bottom: 1px solid var(--color-border, #e5e7eb);
}

.alerts-settings-row-info {
    min-width: 0;
}

.alerts-settings-row-label {
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--color-text, #111827);
}

.alerts-settings-row-hint {
    font-size: 0.74rem;
    color: var(--color-text-muted, #6b7280);
    margin-top: 2px;
    line-height: 1.3;
}

.alerts-settings-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.78rem;
    color: var(--color-text-muted, #6b7280);
    cursor: pointer;
    user-select: none;
    padding: 4px 6px;
    border-radius: var(--border-radius-sm);
}

.alerts-settings-toggle:hover {
    background: rgba(13, 148, 136, 0.06);
    color: var(--color-text, #111827);
}

.alerts-settings-toggle input[type="checkbox"] {
    /* Native checkbox — simple & reliable. Teal accent to match the
     * rest of the app's primary color. */
    accent-color: var(--color-primary, #0d9488);
    cursor: pointer;
    margin: 0;
}

/* ============================================
   Map View — shared between map.html (standalone)
   and the in-place List/Map toggle on the index +
   watchlist pages. Originally inlined in map.html;
   moved here so all three hosts share one source.
   ============================================ */

/* Section header — title on the left, view toggle on the right. */
.properties-section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--space-md);
}
.properties-section-header .section-title { margin: 0; }

/* List/Map toggle pill — sits above the property list. */
.view-toggle {
    display: inline-flex;
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border);
    border-radius: var(--border-radius-full);
    padding: 3px;
    margin-bottom: var(--space-md);
    box-shadow: var(--shadow-sm);
}
.view-toggle button {
    border: none;
    background: transparent;
    color: var(--color-text-secondary);
    font: inherit;
    font-size: var(--font-size-sm);
    padding: 6px 14px;
    border-radius: var(--border-radius-full);
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
}
.view-toggle button:hover { color: var(--color-text-primary); }
.view-toggle button.active {
    background: var(--color-primary);
    color: white;
    font-weight: 600;
}

/* Map container — used by all three hosts. Heights are tuned for the
   in-place toggle; the standalone page overrides via inline style. */
.map-host {
    height: 70vh;
    min-height: 480px;
    width: 100%;
    border-radius: var(--border-radius-md);
    border: 1px solid var(--color-border);
    background: #e2e8f0;  /* visible while tiles load */
}

/* ============================================
   Desktop Split View (list + map side-by-side)
   ============================================
   Activated by MapView.bindToggle adding .split-active when its
   splitQuery media query matches (index passes min-width: 1200px).
   The cards scroll with the page while the map stays pinned — the
   Zillow pattern. Below the query the class is absent and the
   List/Map toggle swaps panes exactly as before. */
.properties-section.split-active {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas:
        "header header"
        "legend legend"
        "rail   rail"
        "list   map"
        "nofix  nofix";
    gap: var(--space-md);
    align-items: start;
}

.properties-section.split-active .properties-section-header { grid-area: header; }
.properties-section.split-active .map-legend { grid-area: legend; }
.properties-section.split-active .urgent-rail {
    grid-area: rail;
    min-width: 0;  /* allow the track to overflow-scroll inside the grid */
}
.properties-section.split-active .properties-list {
    grid-area: list;
    /* Half-width pane: let card columns pack by available space instead
       of the fixed 2-up used by the full-width desktop list. */
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}
.properties-section.split-active .map-host {
    grid-area: map;
    position: sticky;
    top: var(--space-md);
    height: calc(100vh - var(--space-md) * 2);
}
.properties-section.split-active .nofix-section { grid-area: nofix; }

/* Leaflet popup styling. */
.leaflet-popup-content { font-family: inherit; margin: 10px 12px; }
.map-popup-address {
    font-weight: 600;
    font-size: 13px;
    color: var(--color-text-primary);
    margin-bottom: 4px;
}
.map-popup-meta { font-size: 12px; color: var(--color-text-secondary); margin: 1px 0; }
.map-popup-link {
    display: inline-block;
    margin-top: 6px;
    color: var(--color-primary);
    font-weight: 500;
    font-size: 12px;
    text-decoration: none;
}
.map-popup-link:hover { text-decoration: underline; }

/* Score legend (icon row above the map). */
.map-legend {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 12px;
    align-items: center;
    font-size: var(--font-size-sm);
    color: var(--color-text-secondary);
    margin-bottom: var(--space-sm);
}
.map-legend .pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 8px;
    border-radius: var(--border-radius-full);
    background: var(--color-bg-tertiary);
}
.map-legend .swatch {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    display: inline-block;
    border: 1.5px solid #fff;
    box-shadow: 0 0 0 1px rgba(0,0,0,.15);
}
.map-legend .swatch.strong { background: #10b981; }
.map-legend .swatch.watch  { background: #f59e0b; }
.map-legend .swatch.thin   { background: #94a3b8; }
.map-legend .swatch.verify { background: #8b5cf6; }
.map-legend .swatch.none   { background: #cbd5e1; }

/* "Not on map" collapsible panel. */
.nofix-section {
    margin-top: var(--space-md);
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border);
    border-radius: var(--border-radius-md);
    overflow: hidden;
}
.nofix-toggle {
    width: 100%;
    padding: 12px 16px;
    text-align: left;
    background: none;
    border: none;
    cursor: pointer;
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-text-primary);
    display: flex;
    align-items: center;
    gap: 8px;
}
.nofix-toggle:hover:not(:disabled) { background: var(--color-bg-tertiary); }
.nofix-toggle:disabled { cursor: default; color: var(--color-text-muted); }
.nofix-toggle .chev { transition: transform .15s; }
.nofix-toggle.expanded .chev { transform: rotate(90deg); }
.nofix-list {
    display: none;
    padding: 0 16px 12px;
    font-size: var(--font-size-sm);
}
.nofix-list.expanded { display: block; }
.nofix-list ul { margin: 0; padding: 0 0 0 18px; max-height: 240px; overflow: auto; }
.nofix-list li { margin: 3px 0; }
.nofix-list a { color: var(--color-primary); text-decoration: none; }
.nofix-list a:hover { text-decoration: underline; }
.nofix-list .nofix-reason { color: var(--color-text-muted); }

.map-error {
    padding: 24px;
    text-align: center;
    background: #fee2e2;
    color: #991b1b;
    border-radius: var(--border-radius-md);
}

/* ============================================
   Incremental card rendering
   ============================================ */
/* Invisible trailing item in the card list (a flex column); an
   IntersectionObserver in app.js watches it and appends the next chunk
   of cards as the user approaches the bottom. Negative margin swallows
   the flex gap the extra item would otherwise add below the last card. */
.render-sentinel {
    height: 1px;
    margin-top: calc(-1 * var(--space-md));
}

/* ============================================
   Mobile layout (phones)
   ============================================ */
/* Nav pills and action buttons stay single-line at every width — in a
   narrow header/toolbar they used to word-wrap into 2–3-line pills. */
.rehab-btn,
.watchlist-btn,
.btn {
    white-space: nowrap;
}

@media (max-width: 640px) {
    /* The sticky header kept ~160px of every viewport occupied on a
       phone; let it scroll away with the page instead. */
    .app-header {
        position: static;
        padding: var(--space-sm) var(--space-md);
        padding-top: calc(var(--space-sm) + env(safe-area-inset-top, 0px));
    }

    /* Compact pills wrapping into tidy rows (no off-screen buttons). */
    .header-actions {
        flex-wrap: wrap;
        gap: 6px;
    }
    .rehab-btn,
    .watchlist-btn {
        padding: 6px 10px;
        font-size: 0.8rem;
    }

    /* Notifications dropdown: anchor to the viewport, not the bell —
       right:0 on the bell wrap ran the panel off the left screen edge. */
    .alerts-panel {
        position: fixed;
        top: max(12px, env(safe-area-inset-top, 0px));
        left: 12px;
        right: 12px;
        width: auto;
        max-height: calc(100vh - 90px);
    }

    /* Stats strip: stack the number over its label so all three cards
       fit the width instead of clipping off-screen. */
    .stats-section {
        gap: 6px;
    }
    .stat-card {
        flex-direction: column;
        gap: 0;
        padding: var(--space-xs) var(--space-sm);
    }
    .stat-value {
        font-size: var(--font-size-lg);
    }

    /* Filter action buttons wrap as whole units; the results count drops
       to its own line instead of squeezing the buttons. */
    .filters-actions {
        flex-wrap: wrap;
        gap: var(--space-sm);
    }
}

/* Two-column filter grid on regular phones (the 1-column stack pushed
   listings ~450px further down). Search keeps a full-width row — it's
   the control you type into; dense flow backfills Sort next to Status
   instead of leaving that cell empty. Tiny screens (<360px) stay
   single-column. */
@media (min-width: 360px) and (max-width: 479px) {
    .filters-row-primary {
        grid-template-columns: repeat(2, 1fr);
        grid-auto-flow: dense;
    }
    .filters-row-primary .filter-group:nth-child(4) {
        grid-column: 1 / -1;
    }
}

/* Recent recorded sales nearby (comps) — property-detail card. The page's
   info-cards are DELIBERATELY white in both themes (page-local styles set
   background: white with literal text colors), so these use matching
   LITERALS, not theme variables — variables would flip to light-on-dark
   values and vanish against the always-white card. The table scrolls inside
   its wrapper on narrow screens; the page never scrolls horizontally. */
#detail-comps { margin-top: var(--space-lg); }
.comps-meta {
    color: #4b5563;
    font-size: var(--font-size-sm);
    margin: 0;
}
/* Source label + as-of date. Its own line on purpose: that pairing is the
   site-wide display standard for every data-derived number, so it should
   read the same way wherever it appears. */
.comps-source {
    color: #6b7280;
    font-size: var(--font-size-xs);
    margin: 2px 0 var(--space-sm);
}
/* The unclassified-county caveat. Amber like the distress badge because it
   carries the same kind of warning, and a literal colour like the rest of this
   card — page cards are WHITE in both themes. */
.comps-caveat {
    color: #92400e;
    background: rgba(217, 119, 6, 0.10);
    border-radius: var(--border-radius-sm);
    padding: var(--space-xs) var(--space-sm);
    font-size: var(--font-size-xs);
    margin: 0 0 var(--space-sm);
}
.comps-table-wrap { overflow-x: auto; }
.comps-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--font-size-sm);
    color: #111827;
}
.comps-table th {
    text-align: left;
    color: #6b7280;
    font-weight: 600;
    padding: var(--space-xs) var(--space-sm);
    border-bottom: 1px solid #d1d5db;
    white-space: nowrap;
}
.comps-table td {
    padding: var(--space-xs) var(--space-sm);
    border-bottom: 1px solid #e5e7eb;
    vertical-align: top;
}
.comps-price { white-space: nowrap; font-weight: 600; }
.comps-distress {
    display: inline-block;
    padding: 0 var(--space-xs);
    border-radius: var(--border-radius-sm);
    background: rgba(217, 119, 6, 0.12);
    color: #b45309;
    font-size: var(--font-size-xs);
    font-weight: 600;
    white-space: nowrap;
    cursor: help;
}
.comps-note {
    color: #6b7280;
    font-size: var(--font-size-xs);
    margin: var(--space-sm) 0 0;
}

/* The disclosure that collapses the sales table. Up to 30 rows render, which
   pushed the rest of the detail page off-screen; the card now opens closed and
   remembers the visitor's choice (js: nctf-comps-open).

   The summary is a <span class="card-header"> + a facts block, NOT just a
   title: the count, the source/as-of line and the unclassified-county caveat
   stay visible in the collapsed state on purpose — they qualify the count,
   which is itself a data-derived claim. Only rows + the reading note fold.

   Page-local literals again (#0d9488 = the app's teal), matching the rest of
   this card: property-detail's info-cards are white in BOTH themes, so theme
   variables here would render light-on-light. The `padding: 0 20px 16px`
   mirrors .card-header/.card-body's own literal 16px/20px in
   property-detail.html so the facts line up under the title. */
.comps-summary {
    cursor: pointer;
    /* Suppress the native triangle in both engines — the chevron on the
       right is the affordance, and two markers read as a rendering bug. */
    list-style: none;
}
.comps-summary::-webkit-details-marker { display: none; }
.comps-summary:focus-visible {
    outline: 2px solid #0d9488;
    outline-offset: -2px;
}
.comps-summary-head { justify-content: space-between; }
.comps-summary-title { flex: 1; }
.comps-toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: #0d9488;
    white-space: nowrap;
}
.comps-chevron {
    display: inline-block;
    transition: transform 0.15s ease;
}
.comps-details[open] .comps-chevron { transform: rotate(180deg); }
/* Real text, swapped by state rather than generated with content: — a
   screen reader and a text search both see the live label. */
.comps-toggle-open { display: none; }
.comps-details[open] .comps-toggle-open { display: inline; }
.comps-details[open] .comps-toggle-closed { display: none; }
.comps-summary-facts {
    display: block;
    padding: 0 20px 16px;
}
/* Phones: the title is the longest card heading on the page, and competing
   with the toggle for ~145px wrapped it onto a third line. Drop the toggle to
   its own row instead — the title gets the full width back. */
@media (max-width: 560px) {
    .comps-summary-head {
        flex-wrap: wrap;
        row-gap: var(--space-xs);
    }
    .comps-summary-title { min-width: 0; }
    .comps-toggle {
        flex: 1 0 100%;
        justify-content: flex-end;
    }
}
/* These three are <p> in the empty-result card and <span> inside the summary
   (a <summary> may not contain block-level flow content in every engine's
   fixup path). Block either way so their margins behave identically. */
.comps-meta,
.comps-source,
.comps-caveat { display: block; }
/* The facts block above already carries the body's top padding. */
.comps-body { padding-top: 0; }
