/* ═══════════════════════════════════════════
   KERBSIDE — Styles
   Mobile-first, vendor-focused
   Brand: "Citrus" — lime + ink on sage
   ═══════════════════════════════════════════ */

:root {
    /* ─── Citrus palette ───
       Lime carries primary actions and ALWAYS takes ink text on top — never
       white, which is unreadable on it. Clay is reserved for destructive
       actions, the error toast and the closed state. */
    --lime:      #B9E03C;
    --lime-dk:   #A3C82E;
    --lime-bg:   rgba(185, 224, 60, 0.16);
    --ink:       #1E2A17;
    --body:      #414A38;
    --muted:     #6A7060;
    --faint:     #98A18A;
    --tint:      #F3F6EC;
    --line:      #E7EBDE;
    --line-2:    #D5DCC7;
    --sage:      #E4E7DC;
    --sage-2:    #EAEDE2;
    --sage-3:    #C9D1BB;
    --stone:     #C3CBB6;
    --clay:      #E2664B;
    --clay-dk:   #C24A31;
    --open:      #5A8F2B;
    --white:     #ffffff;

    --photo-placeholder: linear-gradient(160deg, #D5DCC7, #B9C3A8);

    --radius:      18px;   /* inputs, buttons, inset panels, photo slots */
    --radius-lg:   26px;   /* cards, modals, popups, floating bars */
    --radius-sm:   12px;   /* icon tiles */
    --radius-pill: 999px;

    --font: 'Bricolage Grotesque', system-ui, -apple-system, sans-serif;
    --mono: 'DM Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

    --shadow:        0 8px 28px rgba(30, 42, 23, 0.10);   /* floating header */
    --shadow-card:   0 14px 40px rgba(30, 42, 23, 0.14);  /* cards, popups */
    --shadow-lg:     0 16px 44px rgba(30, 42, 23, 0.18);  /* modals, bars */
    --shadow-lime:   0 8px 24px rgba(163, 200, 46, 0.45); /* the FAB */
    --ring:          0 0 0 3px rgba(185, 224, 60, 0.28);
    --ring-err:      0 0 0 3px rgba(226, 102, 75, 0.14);

    /* ─── Legacy aliases ───
       The old purple/slate names are still referenced from inline styles
       inside JS template strings (vendor.js writes `color:var(--slate-500)`
       in about twenty places). Mapping them here means a missed reference
       renders in the new brand rather than in purple. Do not add new uses. */
    --purple:    var(--lime);
    --purple-dk: var(--lime-dk);
    --purple-lt: var(--lime-dk);
    --purple-bg: var(--lime-bg);
    --green:     var(--open);
    --red:       var(--clay);
    --slate-900: var(--ink);
    --slate-800: var(--ink);
    --slate-700: var(--body);
    --slate-500: var(--muted);
    --slate-400: var(--faint);
    --slate-300: var(--line-2);
    --slate-200: var(--line);
    --slate-100: var(--tint);
}

*, *::before, *::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html, body {
    width: 100%;
    height: 100%;
    overflow: hidden;
    font-family: var(--font);
    background: var(--sage);
    color: var(--ink);
    -webkit-font-smoothing: antialiased;
}

.hidden { display: none !important; }

/* Shared type helpers */
.eyebrow {
    font: 500 10px/1 var(--mono);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted);
}

/* ─── MAP ─── */
#map {
    position: absolute;
    inset: 0;
    /* NO z-index here, deliberately. A positioned element with a z-index
       creates a stacking context, which traps every Mapbox popup and marker
       inside it — so a tall popup could never rise above #header (z-index 10)
       and got hidden behind it. #map is first in the DOM, so it still paints
       underneath everything without needing a z-index. */
}

/* ─── MAP ATTRIBUTION (required — do not hide) ─── */
/* Mapbox's terms require the logo AND the text credit, and state the logo
   "cannot be hidden, removed, or styled". The credit string already contains
   "© OpenStreetMap", which satisfies OSM's ODbL for both the map tiles and the
   suburb list in CONFIG.AREAS — one control covers everything.
   Font size and colour MAY be adjusted; the logo may not. */
.mapboxgl-ctrl-attrib {
    font-size: 10px;
}

.mapboxgl-ctrl-attrib a {
    color: var(--muted);
}

/* Keep the credit and logo clear of the iPhone home indicator in standalone.
   SCOPED TO #map on purpose: env() is viewport-relative, not element-relative,
   so an unscoped rule also shifts the small picker map inside the modal — where
   there is no home indicator to avoid — and its controls float off the corner. */
#map .mapboxgl-ctrl-bottom-left,
#map .mapboxgl-ctrl-bottom-right {
    margin-bottom: env(safe-area-inset-bottom, 0px);
}

/* ─── HEADER ───
   One floating pill over the map: brand, search, and the right-hand slot —
   the vendor's open/closed pill and stall emoji, or the customer's GPS and
   account buttons. The goods filters float underneath as separate pills. */
#header {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 10;
    /* env() adds the iPhone notch / status bar inset when launched as an
       installed app. Falls back to 0 in a normal browser tab. */
    padding: calc(12px + env(safe-area-inset-top, 0px)) 12px 12px;
    pointer-events: none;
}

#header-bar {
    max-width: 560px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 8px 8px 9px;
    background: var(--white);
    border: 1px solid transparent;
    border-radius: var(--radius-pill);
    box-shadow: var(--shadow);
    pointer-events: auto;
    transition: border-color 0.2s, box-shadow 0.2s;
}

/* The whole bar takes the focus ring, not the bare input — the input has no
   border of its own, so a ring on it would float in the middle of the pill. */
#header-bar:focus-within {
    border-color: var(--lime-dk);
    box-shadow: var(--shadow), var(--ring);
}

#brand-mark {
    width: 36px;
    height: 36px;
    border-radius: var(--radius-sm);
    background: var(--lime);
    color: var(--ink);
    font-weight: 800;
    font-size: 15px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

#search-wrap {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 9px;
}

#search-icon {
    color: var(--faint);
    flex-shrink: 0;
}

#search-input {
    flex: 1;
    min-width: 0;
    height: 36px;
    padding: 0;
    border: none;
    background: none;
    outline: none;
    font-family: var(--font);
    font-size: 14px;
    color: var(--ink);
}

#search-input::placeholder { color: var(--faint); }
#search-input::-webkit-search-cancel-button { display: none; }

#search-clear {
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    border: none;
    border-radius: 50%;
    background: var(--tint);
    color: var(--muted);
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.2s, color 0.2s;
}

#search-clear:hover { background: var(--line); color: var(--ink); }

#header-actions {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
}

/* Round, to sit inside the pill without fighting its curve. */
.icon-btn {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border: 1px solid var(--line);
    background: var(--white);
    color: var(--body);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    flex-shrink: 0;
    transition: background 0.2s, color 0.2s, border-color 0.2s;
}

.icon-btn:hover {
    background: var(--tint);
    color: var(--ink);
}

.icon-btn.active {
    background: var(--lime);
    color: var(--ink);
    border-color: var(--lime);
}

/* A signed-in vendor's account button becomes their stall emoji, ringed —
   the same glyph as their map pin and their profile avatar. */
#profile-btn.has-emoji {
    font-size: 18px;
    line-height: 1;
    background: var(--white);
    border: 2px solid var(--lime-dk);
}

/* ─── VENDOR OPEN/CLOSED ───
   The pill is the switch: no separate track and thumb, which at this size
   read as clutter next to the emoji. */
.status-pill {
    display: flex;
    align-items: center;
    gap: 7px;
    height: 36px;
    padding: 0 14px;
    border: 1px solid var(--line);
    border-radius: var(--radius-pill);
    background: var(--tint);
    font-family: var(--font);
    cursor: pointer;
    transition: background 0.2s, border-color 0.2s;
}

.status-pill:hover { background: var(--line); }

#vendor-status-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--stone);
    flex-shrink: 0;
    transition: background 0.3s, box-shadow 0.3s;
}

#vendor-status-dot.open {
    background: var(--open);
    box-shadow: 0 0 8px rgba(90, 143, 43, 0.5);
}

#vendor-status-label {
    font-size: 13px;
    font-weight: 700;
    color: var(--faint);
    transition: color 0.3s;
}

#vendor-status-label.open { color: var(--open); }

.status-pill[aria-checked="true"] {
    background: var(--lime-bg);
    border-color: rgba(163, 200, 46, 0.45);
}

/* ─── SEARCH PANEL ───
   Areas are pick-one (a stall has one area); goods are pick-many. Both write
   into the same selection the filter pills use, so the two stay in step. */
#search-panel {
    max-width: 560px;
    margin: 8px auto 0;
    background: var(--white);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
    pointer-events: auto;
    max-height: min(62vh, 520px);
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: none;
}

#search-panel::-webkit-scrollbar { display: none; }

.sp-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 12px 14px;
    background: var(--tint);
    border-bottom: 1px solid var(--line);
}

.sp-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px;
    border: none;
    border-radius: var(--radius-pill);
    font-family: var(--font);
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
}

.sp-chip.area { background: var(--ink); color: var(--white); }
.sp-chip.goods { background: var(--lime); color: var(--ink); }
.sp-chip .sp-chip-x { font-size: 15px; line-height: 1; opacity: 0.75; }
.sp-chip:hover .sp-chip-x { opacity: 1; }

.sp-section-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 14px 16px 6px;
}

.sp-section-label,
.sp-section-hint {
    font: 500 10px/1 var(--mono);
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.sp-section-label { color: var(--muted); }
.sp-section-hint { color: var(--faint); }

.sp-row {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 11px 16px;
    border: none;
    border-top: 1px solid var(--tint);
    background: none;
    font-family: var(--font);
    text-align: left;
    cursor: pointer;
    transition: background 0.15s;
}

.sp-row:hover { background: var(--lime-bg); }
.sp-row.selected { background: var(--lime-bg); }

.sp-row-icon {
    width: 34px;
    height: 34px;
    border-radius: 11px;
    background: var(--tint);
    color: var(--body);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 17px;
    line-height: 1;
    flex-shrink: 0;
}

.sp-row:hover .sp-row-icon { background: var(--white); }

.sp-row-copy {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.sp-row-title {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 14px;
    font-weight: 600;
    color: var(--ink);
}

.sp-row-sub {
    font-size: 12px;
    color: var(--faint);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Open/closed dot beside a stall name in the panel. */
.sr-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    display: inline-block;
    flex-shrink: 0;
}

.sr-dot.open { background: var(--open); }
.sr-dot.closed { background: var(--stone); }

.sp-count {
    font: 500 12px/1 var(--mono);
    color: var(--muted);
    flex-shrink: 0;
}

.sp-goods {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 8px 16px 14px;
}

.sp-good {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 9px 14px;
    border: 1px solid var(--line);
    border-radius: var(--radius-pill);
    background: var(--tint);
    font-family: var(--font);
    font-size: 14px;
    font-weight: 600;
    color: var(--body);
    cursor: pointer;
    transition: background 0.2s, color 0.2s, border-color 0.2s;
}

.sp-good:hover { background: var(--line); }

.sp-good.selected {
    background: var(--lime);
    border-color: var(--lime);
    color: var(--ink);
}

.sp-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 14px;
    background: var(--tint);
    border-top: 1px solid var(--line);
    position: sticky;
    bottom: 0;
}

.sp-foot-count {
    font: 500 12px/1.4 var(--mono);
    color: var(--muted);
}

.sp-apply {
    flex-shrink: 0;
    padding: 11px 18px;
    border: none;
    border-radius: var(--radius-pill);
    background: var(--ink);
    color: var(--white);
    font-family: var(--font);
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
    transition: background 0.2s;
}

.sp-apply:hover { background: #2C3D22; }
.sp-apply:disabled { opacity: 0.45; cursor: default; }

.sp-empty {
    padding: 18px 16px;
    text-align: center;
    font-size: 13px;
    color: var(--faint);
}

/* ─── FILTER PILLS ───
   Separate floating pills under the bar rather than a strip inside it, so the
   map reads as the surface everything sits on. All 20 categories, scrolling
   sideways — nothing hidden behind a "More". */
#filter-scroll {
    max-width: 560px;
    margin: 10px auto 0;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    pointer-events: auto;
    /* The pills carry their own shadow, which the scroller would clip. */
    padding: 4px 0 8px;
}

#filter-scroll::-webkit-scrollbar { display: none; }

#filter-track {
    display: flex;
    gap: 8px;
    width: max-content;
    padding: 0 2px;
}

.filter-btn {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 8px 14px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--line);
    background: var(--white);
    box-shadow: 0 4px 14px rgba(30, 42, 23, 0.10);
    font-size: 13px;
    font-family: var(--font);
    font-weight: 600;
    color: var(--body);
    cursor: pointer;
    transition: background 0.2s, color 0.2s, border-color 0.2s;
    white-space: nowrap;
}

.filter-btn:hover { background: var(--tint); }

.filter-btn.active {
    background: var(--lime);
    color: var(--ink);
    border-color: var(--lime);
}

/* ─── EDIT LOCATION BAR ─── */
#edit-location-bar {
    position: absolute;
    bottom: calc(100px + env(safe-area-inset-bottom, 0px));
    left: 50%;
    transform: translateX(-50%);
    z-index: 10;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 18px;
    background: var(--white);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    font-size: 14px;
    font-weight: 500;
    color: var(--body);
    white-space: nowrap;
}

.bar-btn {
    padding: 9px 16px;
    border-radius: var(--radius);
    border: 1px solid var(--line);
    background: var(--tint);
    font-size: 13px;
    font-family: var(--font);
    font-weight: 700;
    color: var(--body);
    cursor: pointer;
    transition: background 0.2s;
}

.bar-btn:hover {
    background: var(--line);
}

.bar-btn.primary {
    background: var(--lime);
    color: var(--ink);
    border-color: var(--lime);
}

.bar-btn.primary:hover {
    background: var(--lime-dk);
}

/* ─── DIRECTIONS INFO BAR ─── */
#directions-info {
    position: fixed;
    bottom: calc(24px + env(safe-area-inset-bottom, 0px));
    left: 50%;
    transform: translateX(-50%);
    z-index: 10;
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 13px 20px;
    background: var(--white);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    font-size: 14px;
    font-weight: 600;
    color: var(--ink);
    white-space: nowrap;
}

#directions-info button {
    background: none;
    border: none;
    color: var(--faint);
    font-size: 14px;
    cursor: pointer;
    font-family: var(--font);
    font-weight: 600;
}

#directions-info button:hover { color: var(--ink); }

/* ─── FAB ─── */
#fab-join {
    position: fixed;
    bottom: calc(24px + env(safe-area-inset-bottom, 0px));
    left: 50%;
    transform: translateX(-50%);
    z-index: 10;
    padding: 14px 28px;
    border-radius: var(--radius-pill);
    border: none;
    background: var(--lime);
    color: var(--ink);
    font-size: 15px;
    font-family: var(--font);
    font-weight: 700;
    cursor: pointer;
    box-shadow: var(--shadow-lime);
    white-space: nowrap;
    transition: transform 0.3s ease, opacity 0.3s ease, box-shadow 0.3s ease;
    touch-action: pan-y;
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
    -webkit-tap-highlight-color: transparent;
}

#fab-join:hover {
    transform: translateX(-50%) translateY(-2px);
    box-shadow: 0 12px 32px rgba(163, 200, 46, 0.5);
}

#fab-join:active {
    transform: translateX(-50%) scale(0.97);
}

#fab-join.dismissing {
    transform: translateX(-50%) translateY(120px);
    opacity: 0;
}

/* ─── MODAL ─── */
#modal-backdrop {
    position: fixed;
    inset: 0;
    z-index: 100;
    background: rgba(30, 42, 23, 0.45);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}

#modal {
    position: fixed;
    inset: 0;
    z-index: 101;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    pointer-events: none;
}

#modal-content {
    width: 100%;
    max-width: 440px;
    max-height: 90vh;
    overflow-y: auto;
    background: var(--white);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    pointer-events: auto;
    scrollbar-width: none;
}

#modal-content::-webkit-scrollbar { display: none; }

/* Modal internal styles */
.modal-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    padding: 20px 22px 0;
}

.modal-title {
    font-size: 21px;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--ink);
    display: flex;
    align-items: center;
    gap: 10px;
}

.modal-close {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    border: none;
    background: var(--tint);
    color: var(--muted);
    font-size: 19px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: background 0.2s, color 0.2s;
}

.modal-close:hover {
    background: var(--line);
    color: var(--ink);
}

.modal-body {
    padding: 16px 22px 22px;
}

/* ─── FORM ELEMENTS ─── */
.form-group {
    margin-bottom: 14px;
}

.form-label {
    display: block;
    font: 500 10px/1 var(--mono);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted);
    margin-bottom: 6px;
}

.form-label-hint {
    font-family: var(--mono);
    font-weight: 400;
    color: var(--faint);
    text-transform: none;
    letter-spacing: 0.02em;
}

.form-input {
    width: 100%;
    height: 46px;
    padding: 0 14px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    font-size: 14px;
    font-family: var(--font);
    color: var(--ink);
    background: var(--white);
    outline: none;
    transition: border-color 0.2s, box-shadow 0.2s;
}

.form-input:focus {
    border-color: var(--lime-dk);
    box-shadow: var(--ring);
}

.form-input::placeholder { color: var(--faint); }

textarea.form-input {
    resize: none;
    height: auto;
    min-height: 84px;
    padding: 12px 14px;
    line-height: 1.5;
}

.form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}

.field-hint {
    margin-top: 6px;
    font-size: 11.5px;
    color: var(--faint);
    line-height: 1.45;
}

/* An error that belongs to one field sits under that field, not in a toast —
   "that email is already registered" is useless if you can't see which box it
   is about. */
.form-input.is-invalid {
    border-color: var(--clay);
    box-shadow: var(--ring-err);
}

.field-error {
    margin-top: 6px;
    font-size: 12px;
    font-weight: 500;
    color: var(--clay-dk);
    line-height: 1.45;
}

/* Read-only value display (mobile / email on the contact screen) */
.profile-field {
    margin-bottom: 14px;
}

.profile-field:last-child { margin-bottom: 0; }

.profile-field-label {
    font: 500 10px/1 var(--mono);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted);
    margin-bottom: 6px;
}

.profile-field-value {
    height: 46px;
    display: flex;
    align-items: center;
    padding: 0 14px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    font-size: 14px;
    color: var(--ink);
}

/* ─── TAG / CHIP PICKER ─── */
.tag-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.tag-btn {
    padding: 10px 14px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--line);
    background: var(--tint);
    font-size: 14px;
    font-family: var(--font);
    font-weight: 600;
    color: var(--body);
    cursor: pointer;
    transition: background 0.2s, color 0.2s, border-color 0.2s;
}

.tag-btn:hover { background: var(--line); }

.tag-btn.selected {
    background: var(--lime);
    color: var(--ink);
    border-color: var(--lime);
}

.tag-count {
    display: block;
    margin-top: 12px;
    font-size: 13px;
    font-weight: 600;
    color: var(--faint);
}

/* ─── PROFILE MAP IN MODAL ─── */
#profile-map-container {
    width: 100%;
    height: 200px;
    border-radius: var(--radius);
    border: 1px solid var(--line);
    background: var(--sage-2);
    overflow: hidden;
    position: relative;
}

#profile-map-container .mapboxgl-map {
    width: 100%;
    height: 100%;
}

.map-status {
    text-align: center;
    font-size: 12px;
    color: var(--faint);
    margin-top: 8px;
}

/* ─── BUTTONS ─── */
.btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    min-height: 50px;
    padding: 12px 16px;
    border-radius: var(--radius);
    border: none;
    font-size: 16px;
    font-family: var(--font);
    font-weight: 700;
    cursor: pointer;
    transition: background 0.2s, opacity 0.2s;
    text-align: center;
}

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

.btn-primary:hover { background: var(--lime-dk); }
.btn-primary:disabled {
    opacity: 0.4;
    cursor: not-allowed;
    background: var(--lime);
}

.btn-outline {
    background: var(--tint);
    color: var(--body);
    border: 1px solid var(--line);
    font-size: 15px;
    min-height: 48px;
}

.btn-outline:hover { background: var(--line); }

.btn-danger {
    background: rgba(226, 102, 75, 0.10);
    color: var(--clay-dk);
    border: 1px solid rgba(226, 102, 75, 0.28);
    font-size: 15px;
    min-height: 48px;
}

.btn-danger:hover { background: rgba(226, 102, 75, 0.16); }

.btn-row {
    display: flex;
    gap: 12px;
    margin-top: 20px;
}

.btn-row .btn { flex: 1; }

.btn-sm {
    min-height: 42px;
    padding: 10px 16px;
    font-size: 14px;
}

.actions-stack {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-top: 20px;
}

/* ─── STEPPED REGISTRATION ───
   Three screens in one modal. The step head, progress bar and footer are
   shared; only .step-body changes between steps. */
.step-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 16px 18px 0;
}

.step-back {
    width: 26px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    background: none;
    color: var(--ink);
    cursor: pointer;
    padding: 0;
    flex-shrink: 0;
}

.step-back:disabled { opacity: 0; pointer-events: none; }

.step-count {
    font: 500 10px/1 var(--mono);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--faint);
}

/* Balances the back button so the step counter stays optically centred. */
.step-head-spacer {
    width: 26px;
    flex-shrink: 0;
}

.step-bar {
    display: flex;
    gap: 5px;
    padding: 14px 18px 0;
}

.step-bar-seg {
    flex: 1;
    height: 4px;
    border-radius: 99px;
    background: var(--line);
    transition: background 0.3s;
}

.step-bar-seg.done { background: var(--lime); }

.step-intro {
    padding: 22px 18px 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.step-title {
    font-size: 22px;
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.05;
    color: var(--ink);
}

.step-sub {
    font-size: 14px;
    line-height: 1.45;
    color: var(--body);
}

.step-body {
    padding: 18px 18px 0;
}

.step-foot {
    margin-top: 22px;
    padding: 18px;
    border-top: 1px solid var(--line);
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.step-foot-note {
    text-align: center;
    font-size: 14px;
    font-weight: 600;
    color: var(--faint);
}

/* ─── PROFILE HOME ─── */
.profile-head {
    padding: 18px 18px 0;
    display: flex;
    align-items: center;
    gap: 12px;
}

/* The stall's goods emoji, not initials — the same glyph as its map pin. */
.profile-avatar {
    width: 52px;
    height: 52px;
    border-radius: var(--radius-pill);
    background: var(--tint);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 26px;
    line-height: 1;
    flex-shrink: 0;
}

.profile-head-copy {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.profile-head-name {
    font-size: 22px;
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.05;
    color: var(--ink);
    word-break: break-word;
}

.profile-head-area {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    color: var(--faint);
}

.profile-head-area svg {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
}

/* Inset panel holding show-on-map and share */
.profile-panel {
    margin: 18px 18px 0;
    padding: 14px 16px;
    border-radius: var(--radius);
    background: var(--tint);
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.panel-row {
    display: flex;
    align-items: center;
    gap: 12px;
}

.panel-row + .panel-row {
    border-top: 1px solid var(--line);
    padding-top: 12px;
}

.panel-row-copy {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.panel-row-title {
    font-size: 15px;
    font-weight: 700;
    color: var(--ink);
}

.panel-row-sub {
    font-size: 13px;
    line-height: 1.3;
    color: var(--faint);
    transition: color 0.3s;
}

.panel-row-sub.on { color: var(--open); }

.share-tile {
    width: 40px;
    height: 40px;
    border-radius: 14px;
    border: none;
    background: var(--lime);
    color: var(--ink);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    flex-shrink: 0;
    transition: background 0.2s;
}

.share-tile:hover { background: var(--lime-dk); }

/* The install card sits between the panel and the list, so it carries the
   modal's own side gutter rather than inheriting one. */
.install-slot:not(:empty) {
    padding: 16px 18px 0;
}

/* Section list — each row opens its own sub-screen */
.prof-list {
    padding: 20px 18px 0;
}

.prof-list-head {
    font: 500 10px/1 var(--mono);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--faint);
    margin-bottom: 6px;
}

.prof-row {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 15px 0;
    border: none;
    border-bottom: 1px solid var(--line);
    background: none;
    font-family: var(--font);
    text-align: left;
    cursor: pointer;
}

.prof-row:hover .prof-row-title { color: var(--open); }

.prof-row-copy {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.prof-row-title {
    font-size: 15px;
    font-weight: 600;
    color: var(--ink);
    transition: color 0.2s;
}

.prof-row-sub {
    font-size: 13px;
    color: var(--faint);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.prof-row-chevron {
    color: var(--faint);
    flex-shrink: 0;
}

.prof-foot {
    padding: 16px 18px 20px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.prof-legal {
    text-align: center;
    margin-top: 4px;
    font-size: 12px;
    color: var(--faint);
}

/* ─── PROFILE SUB-SCREEN ─── */
.sub-header {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 16px 18px;
    border-bottom: 1px solid var(--line);
}

.sub-back {
    width: 26px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    background: none;
    color: var(--ink);
    cursor: pointer;
    padding: 0;
    flex-shrink: 0;
}

.sub-title {
    flex: 1;
    min-width: 0;
    font-size: 17px;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--ink);
}

.sub-save {
    border: none;
    background: none;
    font-family: var(--font);
    font-size: 14px;
    font-weight: 700;
    color: var(--body);
    cursor: pointer;
    padding: 4px 2px;
    flex-shrink: 0;
    transition: color 0.2s, opacity 0.2s;
}

.sub-save:hover { color: var(--ink); }
.sub-save:disabled { color: var(--faint); opacity: 0.7; cursor: default; }

.sub-body {
    padding: 18px;
}

.sub-note {
    font-size: 14px;
    line-height: 1.45;
    color: var(--body);
    margin-bottom: 14px;
}

/* ─── INSET TOGGLE ROW (inside a sub-screen) ─── */
.toggle-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    border-radius: var(--radius);
    background: var(--tint);
}

.toggle-copy {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.toggle-title {
    font-size: 15px;
    font-weight: 700;
    color: var(--ink);
}

.toggle-sub {
    font-size: 13px;
    line-height: 1.3;
    color: var(--faint);
}

.mini-toggle {
    position: relative;
    width: 46px;
    height: 27px;
    border-radius: var(--radius-pill);
    border: none;
    background: var(--line-2);
    cursor: pointer;
    transition: background 0.3s;
    padding: 0;
    flex-shrink: 0;
}

.mini-toggle[aria-checked="true"] {
    background: var(--lime);
}

.mini-toggle:disabled {
    opacity: 0.6;
    cursor: default;
}

.mini-toggle-thumb {
    position: absolute;
    top: 3px;
    left: 3px;
    width: 21px;
    height: 21px;
    border-radius: 50%;
    background: var(--white);
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
    transition: transform 0.3s, background 0.3s;
}

.mini-toggle[aria-checked="true"] .mini-toggle-thumb {
    transform: translateX(19px);
    background: var(--ink);
    box-shadow: none;
}

/* ─── PHOTO GRID (profile) ─── */
.photo-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
}

.photo-slot {
    aspect-ratio: 4/3;
    border-radius: var(--radius);
    overflow: hidden;
    position: relative;
}

.photo-slot.filled {
    background: var(--photo-placeholder);
}

.photo-slot.filled img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.photo-remove {
    position: absolute;
    top: 7px;
    right: 7px;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: none;
    background: rgba(30, 42, 23, 0.55);
    color: var(--white);
    font-size: 15px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    transition: background 0.2s;
}

.photo-remove:hover {
    background: var(--clay);
}

.photo-slot.empty {
    border: 2px dashed var(--line-2);
    background: var(--tint);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s;
}

.photo-slot.empty:hover {
    border-color: var(--lime-dk);
    background: var(--lime-bg);
}

.photo-add-icon {
    font-size: 24px;
    color: var(--faint);
    font-weight: 300;
    line-height: 1;
}

.photo-add-label {
    font-size: 11px;
    color: var(--faint);
    font-weight: 500;
}

/* ─── MAPBOX POPUP ─── */

/* Above the header (10) so a popup with photos is never clipped behind it,
   but below the modal layer (100). */
.mapboxgl-popup {
    z-index: 12;
}

/* Markers stay under the header — only the open popup rises above it. */
.mapboxgl-marker {
    z-index: 3;
}

.mapboxgl-popup-content {
    border-radius: var(--radius-lg) !important;
    padding: 0 !important;
    box-shadow: var(--shadow-card) !important;
    overflow: hidden;
    min-width: 260px;
}

.mapboxgl-popup-close-button {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.92) !important;
    color: var(--ink);
    font-size: 19px;
    line-height: 1;
    right: 14px;
    top: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.mapboxgl-popup-close-button:hover {
    color: var(--ink);
    background: var(--white) !important;
}

.popup-inner {
    font-family: var(--font);
    position: relative;   /* scroll origin for revealing the Details section */
    /* A stall with a long blurb can expand taller than the screen. Cap the
       card and scroll it internally rather than letting it run off the map.
       This is the pre-JS default; capPopupHeight() in map.js replaces it with
       the space the header actually leaves, which changes between the customer
       and vendor bars. The close button is a sibling, so it stays put while
       this scrolls. */
    max-height: min(calc(100vh - 190px), 560px);
    overflow-y: auto;
    /* Reaching the end of the card must not start scrolling the page behind
       it — on a phone that reads as the map lurching. */
    overscroll-behavior: contain;
    scrollbar-width: thin;
}

/* ─── POPUP PHOTOS ─── */
.popup-photos {
    position: relative;
    background: var(--sage-2);
}

.popup-track {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
}

.popup-track::-webkit-scrollbar { display: none; }

.popup-slide {
    flex: 0 0 100%;
    scroll-snap-align: start;
}

.popup-slide img {
    width: 100%;
    /* 150, not 172: on a 640px-tall phone every pixel here comes straight off
       the slack that keeps the Details button still when the card expands. */
    height: 150px;
    object-fit: cover;
    display: block;
}

.popup-dots {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 8px;
    display: flex;
    justify-content: center;
    gap: 5px;
    pointer-events: none;
}

.popup-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.5);
    transition: background 0.2s;
}

.popup-dot.active { background: var(--white); }

/* The status chip sits on the photo when there is one. With no photo it falls
   back to .popup-status inline beside the stall name — no placeholder block,
   because a fake photo area is worse than none. */
.popup-photo-status {
    position: absolute;
    left: 16px;
    bottom: 14px;
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 7px 14px;
    border-radius: var(--radius-pill);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.popup-photo-status .popup-status-dot {
    width: 7px;
    height: 7px;
}

.popup-photo-status.open {
    background: var(--lime);
    color: var(--ink);
}

.popup-photo-status.open .popup-status-dot { background: var(--ink); }

.popup-photo-status.closed {
    background: var(--white);
    color: var(--clay);
}

.popup-photo-status.closed .popup-status-dot { background: var(--clay); }

.popup-body {
    padding: 0 0 4px;
}

.popup-header {
    padding: 16px 20px 6px;
}

.popup-name {
    font-size: 22px;
    font-weight: 700;
    letter-spacing: -0.025em;
    color: var(--ink);
    line-height: 1.05;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 9px;
}

/* Inline status — the no-photo fallback, and the owner's hidden card. */
.popup-status {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    padding: 5px 11px;
    border-radius: var(--radius-pill);
}

.popup-status-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    display: inline-block;
    flex-shrink: 0;
}

.popup-status.open {
    background: var(--lime);
    color: var(--ink);
}

.popup-status.open .popup-status-dot { background: var(--ink); }

.popup-status.closed {
    background: var(--tint);
    color: var(--clay);
}

.popup-status.closed .popup-status-dot { background: var(--clay); }

/* Owner-only badge when the stall is hidden from the map */
.popup-hidden-badge {
    display: inline-flex;
    align-items: center;
    padding: 4px 10px;
    border-radius: var(--radius-pill);
    background: var(--tint);
    color: var(--muted);
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

/* ─── POPUP META LINE ───
   "Mitchells Plain · Barber Shop · Hair & Beauty" on a single line. Goods are
   capped at 2 (CONFIG.MAX_GOODS), so this rarely truncates — but when it does,
   an ellipsis reads better than a second line opening with a separator. */
.popup-subline {
    display: flex;
    align-items: center;
    gap: 7px;
    margin-top: 7px;
    min-width: 0;
}

.popup-pin {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    color: var(--faint);
}

.popup-meta {
    font-size: 14px;
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* With no photo the close button sits in the header's top-right corner, so the
   name row has to keep clear of it. */
.popup-inner.no-photo .popup-header {
    padding-right: 58px;
}

.popup-actions {
    padding: 12px 20px 14px;
    display: flex;
    gap: 9px;
}

/* Three labelled buttons do not fit a 300px card. When Directions and WhatsApp
   are both present the row goes symbols-only: three equal taps, each carrying
   its meaning in colour and shape — clay arrow, lime WhatsApp, tint share. With
   only one action there is room for its label, so it keeps it.
   The label is hidden rather than dropped from the markup, so screen readers
   still read "Directions" and "WhatsApp". */
.popup-actions.crowded { gap: 10px; }

.popup-actions.crowded .popup-btn-label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.popup-actions.crowded .popup-btn {
    padding: 0;
    gap: 0;
}

.popup-actions.crowded .popup-btn-dir svg,
.popup-actions.crowded .popup-btn-wa svg {
    width: 19px;
    height: 19px;
}

/* All three share the width equally. Three small tiles would match the mockup
   more literally, but on a phone a 97px target beats a 46px one and the row
   still reads as three equal taps. */
.popup-actions.crowded .popup-btn-share-icon {
    flex: 1;
    width: auto;
}

.popup-btn {
    flex: 1;
    /* Without this a flex item refuses to shrink below its content width, so
       the row overflows instead of sharing the space out — which is exactly how
       the share button disappeared. */
    min-width: 0;
    height: 46px;
    padding: 0 12px;
    border: none;
    border-radius: var(--radius);
    font-weight: 700;
    font-size: 15px;
    font-family: var(--font);
    /* WhatsApp is an <a>, Directions is a <button>. Without this the WhatsApp
       label picked up the browser's default underline and the two buttons
       didn't match. */
    text-decoration: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    transition: filter 0.2s;
}

.popup-btn:hover { filter: brightness(0.94); }

/* Clay carries Directions, lime carries WhatsApp. The icons inherit
   currentColor, so the pairing is set here and nowhere else. */
.popup-btn-dir {
    background: var(--clay);
    color: var(--white);
}

.popup-btn-wa {
    background: var(--lime);
    color: var(--ink);
}

.popup-btn-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Compact share button. flex: none so it is never the thing that gives way —
   it is the smallest target on the row and the easiest to lose. */
.popup-btn-share-icon {
    width: 46px;
    flex: 0 0 46px;
    background: var(--tint);
    color: var(--body);
}

.popup-btn-share-icon:hover {
    background: var(--line);
}

/* ─── POPUP DETAILS DISCLOSURE ───
   Blurb, payments and socials live in here. The collapsed card carries only
   what someone needs in order to decide whether they want the stall at all. */
.popup-details {
    border-top: 1px solid var(--line);
}

.popup-details-toggle {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 12px 20px;
    background: none;
    border: none;
    font-family: var(--font);
    font-size: 13px;
    font-weight: 600;
    color: var(--body);
    cursor: pointer;
    text-align: left;
}

.popup-details-toggle:hover { color: var(--ink); }
.popup-details.open .popup-details-toggle { color: var(--ink); }

.popup-details-chevron {
    flex-shrink: 0;
    color: var(--faint);
    transition: transform 0.22s ease;
}

.popup-details.open .popup-details-chevron { transform: rotate(180deg); }

/* 0fr → 1fr animates to the content's natural height without measuring it in
   JS. Browsers that don't animate the transition still collapse and expand
   correctly, so this degrades to an instant toggle rather than to a bug. */
.popup-details-body {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 0.22s ease;
}

.popup-details.open .popup-details-body {
    grid-template-rows: 1fr;
}

.popup-details-inner {
    overflow: hidden;
    min-height: 0;
}

.popup-details.open .popup-details-inner {
    /* No max-height here: the whole card is the scroll container (see
       .popup-inner). Two nested scroll areas meant a phone drag could catch
       the wrong one. */
    padding: 0 20px 18px;
}

.popup-detail-desc {
    font-size: 14px;
    line-height: 1.5;
    color: var(--body);
    margin: 0 0 14px;
    text-wrap: pretty;
}

.popup-detail-group + .popup-detail-group { margin-top: 14px; }

.popup-detail-label {
    font: 500 10px/1 var(--mono);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--faint);
    margin-bottom: 6px;
}

.popup-detail-value {
    font-size: 14px;
    font-weight: 500;
    color: var(--ink);
    line-height: 1.4;
}

.popup-socials-row {
    display: flex;
    flex-wrap: wrap;
    gap: 7px;
}

.popup-social-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: var(--radius-sm);
    background: var(--tint);
    color: var(--body);
    text-decoration: none;
    transition: background 0.2s, color 0.2s;
    flex-shrink: 0;
}

.popup-social-icon svg {
    width: 17px;
    height: 17px;
    display: block;
}

.popup-social-icon:hover {
    background: var(--line);
    color: var(--ink);
}

/* ─── PROFILE SOCIAL INPUTS (SVG icons) ─── */
.social-grid {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.social-input-wrap {
    position: relative;
}

.social-icon {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    width: 17px;
    height: 17px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--faint);
    pointer-events: none;
    transition: color 0.2s;
}

.social-icon svg {
    width: 17px;
    height: 17px;
    display: block;
}

.social-input-wrap:focus-within .social-icon {
    color: var(--lime-dk);
}

.social-input {
    padding-left: 42px !important;
}

/* ─── MAPBOX MARKER ───
   The emoji IS the marker — no plate, no teardrop behind it. The goods glyph
   is the stall's identity here, in the search panel and on its profile. */
.vendor-marker {
    position: relative;
    width: 38px;
    height: 38px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: transform 0.2s;
}

.vendor-marker-emoji {
    font-size: 30px;
    line-height: 1;
    /* The map underneath is pale and busy; without this the emoji floats. */
    text-shadow: 0 2px 6px rgba(30, 42, 23, 0.35);
}

.vendor-marker:hover {
    transform: scale(1.15);
}

.vendor-marker.closed {
    opacity: 0.25;
    filter: grayscale(1);
}

/* Logged-in vendor's own pin — a lime ring so they can tell themselves apart
   from similar stalls nearby. Never rendered for other viewers. */
.vendor-marker.own::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: var(--white);
    border: 3px solid var(--lime-dk);
    box-shadow: 0 3px 10px rgba(163, 200, 46, 0.45);
}

.vendor-marker.own .vendor-marker-emoji {
    position: relative;
    font-size: 22px;
    text-shadow: none;
}

.vendor-marker.own.closed {
    opacity: 0.55;
    filter: grayscale(0.5);
}

/* Own pin while hidden from customers — dashed ring, no shadow */
.vendor-marker.own.self-hidden::before {
    background: var(--tint);
    border-style: dashed;
    border-color: var(--faint);
    box-shadow: none;
}

/* Draggable edit marker */
.edit-marker {
    width: 30px;
    height: 42px;
    cursor: grab;
}

.edit-marker:active { cursor: grabbing; }

/* ─── ADD TO HOME SCREEN CARD ─── */
.install-card {
    position: relative;
    background: var(--tint);
    border: 1px solid rgba(163, 200, 46, 0.40);
    border-radius: var(--radius);
    padding: 14px;
    margin-bottom: 12px;
}

.install-head {
    display: flex;
    align-items: center;
    gap: 12px;
    padding-right: 22px;
}

.install-icon {
    width: 42px;
    height: 42px;
    border-radius: var(--radius-sm);
    overflow: hidden;
    flex-shrink: 0;
    box-shadow: 0 2px 8px rgba(163, 200, 46, 0.35);
}

.install-icon img {
    width: 100%;
    height: 100%;
    display: block;
}

.install-copy {
    min-width: 0;
    flex: 1;
}

.install-title {
    font-size: 14px;
    font-weight: 700;
    color: var(--ink);
    line-height: 1.25;
}

.install-sub {
    font-size: 12px;
    color: var(--muted);
    margin-top: 3px;
}

.install-btn {
    flex-shrink: 0;
    padding: 10px 18px;
    border: none;
    border-radius: 14px;
    background: var(--lime);
    color: var(--ink);
    font-family: var(--font);
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
    transition: background 0.2s;
}

.install-btn:hover { background: var(--lime-dk); }
.install-btn:disabled { opacity: 0.6; cursor: default; }

/* iOS: manual Share → Add to Home Screen steps */
.install-steps {
    list-style: none;
    margin-top: 14px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* Hanging indent: the number sits in the gutter so wrapped text lines up
   under the text rather than under the number. */
.install-steps li {
    position: relative;
    padding-left: 30px;
    font-size: 13px;
    line-height: 1.5;
    color: var(--body);
}

.install-step-n {
    position: absolute;
    left: 0;
    top: 0;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--white);
    border: 1px solid rgba(163, 200, 46, 0.45);
    color: var(--body);
    font-size: 11px;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.install-chip {
    display: inline-flex;
    align-items: center;
    vertical-align: middle;
    gap: 5px;
    padding: 3px 9px;
    border-radius: 10px;
    background: var(--white);
    border: 1px solid var(--line);
    font-size: 12px;
    font-weight: 600;
    color: var(--body);
}

.install-chip svg {
    width: 13px;
    height: 13px;
    display: block;
    flex-shrink: 0;
}

.install-chip .ios-share { color: var(--body); }

.install-dismiss {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 24px;
    height: 24px;
    border: none;
    background: none;
    color: var(--faint);
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
}

.install-dismiss:hover {
    background: var(--lime-bg);
    color: var(--body);
}

.install-note {
    margin-top: 12px;
    font-size: 11.5px;
    line-height: 1.5;
    color: var(--muted);
}

.install-note strong { color: var(--body); }

.install-help {
    display: block;
    width: 100%;
    margin-top: 10px;
    padding: 0;
    border: none;
    background: none;
    font-family: var(--font);
    font-size: 12px;
    font-weight: 600;
    color: var(--body);
    text-decoration: underline;
    text-align: left;
    cursor: pointer;
}

.install-help:hover { color: var(--ink); }

.install-manual { margin-top: 4px; }

/* ─── SPOTS REMAINING (registration cap) ─── */
.spots-note {
    display: inline-block;
    padding: 6px 13px;
    border-radius: var(--radius-pill);
    background: var(--lime-bg);
    color: var(--ink);
    border: 1px solid rgba(163, 200, 46, 0.40);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.01em;
    margin-bottom: 16px;
}

/* ─── TERMS ─── */
.terms-box {
    max-height: 150px;
    overflow-y: auto;
    padding: 14px 16px;
    background: var(--tint);
    border-radius: var(--radius);
    font-size: 13px;
    color: var(--muted);
    line-height: 1.6;
    margin-bottom: 12px;
}

.terms-check {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    font-size: 13px;
    line-height: 1.45;
    color: var(--body);
    margin-bottom: 16px;
}

.terms-check input[type="checkbox"] {
    margin-top: 2px;
    accent-color: var(--lime);
    width: 20px;
    height: 20px;
    flex-shrink: 0;
}

.terms-link {
    color: var(--body);
    text-decoration: underline;
    cursor: pointer;
    background: none;
    border: none;
    font: inherit;
    padding: 0;
}

.terms-link:hover { color: var(--ink); }

/* ─── PASSWORD TOGGLE ─── */
.pw-wrap {
    position: relative;
}

.pw-input {
    padding-right: 48px !important;
}

.pw-toggle {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    width: 34px;
    height: 34px;
    border: none;
    background: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--faint);
}

.pw-toggle:hover { color: var(--body); }

/* ─── AREA PICKER ─── */
select.form-input {
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2398A18A' stroke-width='2.4' stroke-linecap='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 14px center;
    background-size: 16px;
    padding-right: 40px;
    cursor: pointer;
}

select.form-input option[disabled] {
    color: var(--faint);
    font-size: 11px;
}

.area-picker { position: relative; }

.area-input.area-invalid {
    border-color: var(--clay);
    box-shadow: var(--ring-err);
}

.area-results {
    position: absolute;
    top: calc(100% + 5px);
    left: 0;
    right: 0;
    z-index: 30;
    max-height: 220px;
    overflow-y: auto;
    background: var(--white);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    scrollbar-width: none;
}

.area-results::-webkit-scrollbar { display: none; }

.area-option {
    display: block;
    width: 100%;
    padding: 11px 15px;
    border: none;
    border-bottom: 1px solid var(--tint);
    background: none;
    text-align: left;
    font-family: var(--font);
    font-size: 14px;
    color: var(--body);
    cursor: pointer;
}

.area-option:last-child { border-bottom: none; }

.area-option:hover {
    background: var(--lime-bg);
    color: var(--ink);
    font-weight: 500;
}

.area-empty {
    padding: 14px;
    text-align: center;
    font-size: 13px;
    color: var(--faint);
}

/* One-tap suggestion from the pin — never auto-applied */
.area-suggest-slot:empty { display: none; }

.area-suggest {
    display: block;
    width: 100%;
    margin-top: 8px;
    padding: 10px 14px;
    border: 1px dashed rgba(163, 200, 46, 0.55);
    border-radius: var(--radius);
    background: var(--lime-bg);
    font-family: var(--font);
    font-size: 12.5px;
    font-weight: 500;
    color: var(--body);
    text-align: left;
    cursor: pointer;
    transition: background 0.2s;
}

.area-suggest:hover { background: rgba(185, 224, 60, 0.28); }
.area-suggest strong { font-weight: 800; color: var(--ink); }

/* ─── TOAST ─── */
#toast {
    position: fixed;
    bottom: calc(24px + env(safe-area-inset-bottom, 0px));
    left: 50%;
    transform: translateX(-50%);
    z-index: 200;
    padding: 12px 24px;
    border-radius: var(--radius);
    background: var(--lime);
    color: var(--ink);
    font-size: 14px;
    font-weight: 700;
    font-family: var(--font);
    box-shadow: var(--shadow-lg);
    animation: toastIn 0.3s ease-out;
}

#toast.error {
    background: var(--clay);
    color: var(--white);
}

@keyframes toastIn {
    from { opacity: 0; transform: translateX(-50%) translateY(10px); }
    to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}

/* ─── MAP LOADING OVERLAY ─── */
#map-loading {
    position: fixed;
    inset: 0;
    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(228, 231, 220, 0.7);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
}

#map-loading-inner {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 22px;
    border-radius: var(--radius);
    background: rgba(255, 255, 255, 0.85);
    font-size: 14px;
    font-weight: 600;
    color: var(--muted);
}

.spinner {
    width: 26px;
    height: 26px;
    border: 3px solid var(--line);
    border-top-color: var(--lime-dk);
    border-radius: 50%;
    animation: spin 0.7s linear infinite;
}

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

/* ─── INLINE SPINNER (for buttons) ───
   Primary buttons are lime with ink text, so the spinner is ink — a white
   spinner on lime is invisible. */
.spinner-inline {
    display: inline-block;
    width: 18px;
    height: 18px;
    border: 2px solid rgba(30, 42, 23, 0.25);
    border-top-color: var(--ink);
    border-radius: 50%;
    animation: spin 0.7s linear infinite;
    vertical-align: middle;
    margin-right: 6px;
}

/* Button loading state */
.btn-loading {
    position: relative;
    color: transparent !important;
    pointer-events: none;
}

.btn-loading::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 20px;
    height: 20px;
    margin: -10px 0 0 -10px;
    border: 2px solid rgba(30, 42, 23, 0.25);
    border-top-color: var(--ink);
    border-radius: 50%;
    animation: spin 0.7s linear infinite;
}

/* A loading spinner on a clay button needs the opposite treatment. */
.btn-danger .spinner-inline,
.btn-danger.btn-loading::after {
    border-color: rgba(226, 102, 75, 0.3);
    border-top-color: var(--clay-dk);
}

/* ─── RESPONSIVE ─── */
@media (max-width: 480px) {
    #header { padding: calc(8px + env(safe-area-inset-top, 0px)) 8px 8px; }
    #header-bar { gap: 8px; padding: 7px 7px 7px 8px; }
    #search-input { font-size: 15px; }   /* 16px-ish stops iOS zooming on focus */
    #filter-scroll { margin-top: 8px; }
    #edit-location-bar {
        bottom: calc(80px + env(safe-area-inset-bottom, 0px));
        left: 12px;
        right: 12px;
        transform: none;
        justify-content: space-between;
        gap: 8px;
        padding: 12px 14px;
    }
    .popup-name { font-size: 21px; }
}

/* A vendor's right-hand slot carries the open pill AND their emoji, which is
   tight beside a search field on a small phone. Shorten the placeholder rather
   than let the pill squeeze the input to nothing. */
@media (max-width: 380px) {
    #vendor-toggle-wrap ~ #gps-btn { display: none; }
    .status-pill { padding: 0 11px; }
    #vendor-status-label { font-size: 12px; }
}

/* ─── DESKTOP ─── */
@media (min-width: 768px) {
    #header {
        padding: calc(16px + env(safe-area-inset-top, 0px)) 24px 16px;
    }

    #header-bar,
    #search-panel,
    #filter-scroll {
        max-width: 720px;
    }

    .mapboxgl-popup-content {
        min-width: 300px;
    }

    #modal-content {
        max-width: 500px;
    }
}

@media (min-width: 1024px) {
    #header-bar,
    #search-panel,
    #filter-scroll {
        max-width: 800px;
    }
}
