/* =============================================================================
   EMPYREAN INTERNATIONAL — COMPONENT STYLES
   style.css  |  Step 0.1b  |  Refactor Roadmap v1.0
   =============================================================================

   REQUIRES: tokens.css loaded FIRST in <head>

   SECTION MAP
   ───────────
   §0  Global reset & base
   §1  Loading screens
   §2  Layout — app shell, sidebar, main content
   §3  Navigation — sidebar nav items, footer, mobile toggle
   §4  Section headers & search bar
   §5  Status / story bar (WhatsApp-style)
   §6  Base card
   §7  Social feed — impact story cards, action buttons
   §8  Marketplace / property cards
   §9  News list cards
   §10 Dashboard slider cards (news, market, reels, live)
   §11 Stat cards
   §12 Buttons
   §13 Form inputs & labels
   §14 Auth modal & card
   §15 Notification toast
   §16 Live stream — container, controls, overlays, gifts
   §17 Full-screen reel viewer
   §18 Profile — header, picture, tabs, gallery, bio
   §19 Suggested users widget
   §20 Messages / chat
   §21 Cart modal & payment
   §22 KYC form, upload areas, camera modal
   §23 Admin panel — queue items, KYC docs, disbursement
   §24 Dispute & complaint system
   §25 Staking indicators & rewards history
   §26 Settings & monetisation pages
   §27 NGO / grant portal & community tasks
   §28 Business page
   §29 Utility — upload progress, rich text toolbar,
                  drag-scroll, media lightbox, misc
   §30 Animations & keyframes
   §31 Responsive overrides

   ============================================================================= */


/* ═══════════════════════════════════════════════════════════════════════════
   §0  GLOBAL RESET & BASE
   ═══════════════════════════════════════════════════════════════════════════ */

@import url('https://fonts.googleapis.com/css2?family=Manrope:wght@300;400;500;600;700;800&family=Syne:wght@700;800&family=Fraunces:ital,wght@0,600;0,700;1,500&display=swap');

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

html { scroll-behavior: smooth; }

body {
  font-family: var(--font-sans);
  background: var(--background) !important;
  color: var(--text-primary);
  line-height: var(--leading-normal);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body.modal-open { overflow: hidden; }
/* FIX (status upload screen "scrolling page instead of modal" bug):
   .main-content is its own independent scroll container (overflow-y:auto;
   height:100vh) -- locking body.overflow alone does nothing to it, so on
   mobile the page behind a modal kept scrolling instead of the modal's
   own internal .create-status-card scroll area. Lock it too whenever a
   modal is open. */
body.modal-open .main-content { overflow: hidden !important; }

#app-container { display: flex; width: 100%; position: relative; }

/* Animated section reveal */
/* FIX (2026-08-27 — "click a section, everything spills/overlaps"):
   added !important. Without it, any future stray inline style="display:..."
   set on a section by ANY script (e.g. app-fixes.js's own blank-screen
   recovery, before its 2026-08-27 fix) permanently overrides this rule for
   the rest of the page session, since inline styles beat a stylesheet rule
   of equal or lower specificity when the stylesheet rule has no !important
   — regardless of which section is actually supposed to be .active. This
   was the root cause of dashboard content (News & Updates, Reels, Community
   Feed) bleeding through underneath Wallet/Marketplace/etc. after almost
   any unrelated JS error fired elsewhere in the app. See app-fixes.js's
   own _checkAndRecover() fix from the same date for the other half of this. */
.content-section { display: none !important; }
.content-section.active { display: block !important; animation: fadeIn 0.4s ease-in-out; }

/* Layout grids */
.grid-2, .grid-3 { display: grid; gap: var(--gap-md); }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }

/* Scrollbar */
::-webkit-scrollbar { width: 5px; height: 5px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: rgba(10, 14, 39, 0.15); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: rgba(10, 14, 39, 0.25); }


/* ═══════════════════════════════════════════════════════════════════════════
   §1  LOADING SCREENS
   ═══════════════════════════════════════════════════════════════════════════ */

/* — Splash screen (#loading-screen) — */
#loading-screen {
  position: fixed; inset: 0;
  background: var(--g-hero);
  z-index: var(--z-critical);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 20px;
  transition: opacity var(--duration-sluggish) var(--ease-out),
              visibility var(--duration-sluggish) var(--ease-out);
}
#loading-screen.hidden { opacity: 0; visibility: hidden; pointer-events: none; }

.loading-avatar-frame {
  width: 120px; height: 120px; border-radius: var(--radius-full);
  background: rgba(255, 255, 255, 0.15);
  border: 3px solid rgba(255, 255, 255, 0.4);
  display: flex; align-items: center; justify-content: center;
  position: relative; overflow: hidden;
  box-shadow: 0 0 40px rgba(255, 87, 34, 0.5), 0 0 80px rgba(142, 36, 170, 0.3),
              inset 0 0 30px rgba(255, 255, 255, 0.1);
  animation: avatarPulse 2s ease-in-out infinite;
}
.loading-avatar-inner {
  width: 90px; height: 90px; border-radius: var(--radius-full);
  background: linear-gradient(135deg, rgba(255,255,255,0.3) 0%, rgba(255,87,34,0.4) 50%, rgba(142,36,170,0.3) 100%);
  display: flex; align-items: center; justify-content: center;
  font-size: 2.5rem; filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3));
}
.loading-orbit {
  position: absolute; width: 140px; height: 140px;
  border: 2px solid transparent;
  border-top: 2px solid rgba(255, 87, 34, 0.6);
  border-right: 2px solid rgba(255, 255, 255, 0.3);
  border-radius: var(--radius-full); animation: orbit 1.5s linear infinite;
}
.loading-orbit2 {
  position: absolute; width: 160px; height: 160px;
  border: 1px solid transparent;
  border-bottom: 1px solid rgba(255, 255, 255, 0.2);
  border-left: 1px solid rgba(255, 87, 34, 0.3);
  border-radius: var(--radius-full); animation: orbit 2.5s linear infinite reverse;
}
.loading-title {
  color: var(--color-white);
  font-family: var(--font-display);
  font-size: clamp(1rem, 3vw, 1.4rem); font-weight: var(--weight-bold);
  text-align: center; max-width: 320px; line-height: var(--leading-snug);
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); padding: 0 20px;
  /* Gold shimmer applied via keyframe in §30 */
  background: linear-gradient(90deg, var(--accent), var(--accent-bright), #fff, var(--accent-bright), var(--accent));
  background-size: 200% auto;
  -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
  animation: goldTextShimmer 2.5s linear infinite;
}
.app-loading-title { /* alias for JS-generated loading screens */
  font-size: clamp(1rem, 3vw, 1.4rem); font-weight: var(--weight-extrabold);
  background: linear-gradient(90deg, var(--accent), var(--accent-bright), #fff, var(--accent-bright), var(--accent));
  background-size: 200% auto;
  -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
  animation: goldTextShimmer 2.5s linear infinite;
}
.loading-subtitle {
  color: rgba(255, 255, 255, 0.75); font-size: var(--text-sm);
  letter-spacing: var(--tracking-widest); text-transform: uppercase; text-align: center;
}
.loading-progress {
  width: 200px; height: 3px; background: rgba(255, 255, 255, 0.2);
  border-radius: var(--radius-xs); overflow: hidden; margin-top: 10px;
}
.loading-progress-bar {
  height: 100%; border-radius: var(--radius-xs);
  animation: loadProgress 2.5s ease-in-out infinite;
}
/* Gold shimmer variant used on second loading screen */
.loading-bar {
  background: linear-gradient(90deg, var(--color-gold-dark), var(--accent-bright), var(--accent), var(--accent-bright), var(--color-gold-dark));
  background-size: 300% 100%; animation: goldBarShimmer 1.8s linear infinite;
}

/* — App loading screen (#app-loading-screen) —
   2026-07-18: background/atmosphere simplified to match the new
   Empyrean Splash (starfield + glyph) markup in index.html, which now
   owns its own decorative CSS under #app-loading-screen / .emp-splash-*
   in a <style> block scoped to that div. This rule keeps only the
   structural contract every version of the splash has relied on:
   fullscreen fixed overlay, centered flex layout, critical z-index,
   and the opacity transition used to fade it out. The old multi-radial
   ::before glow and .loading-particles dot-field (orange/purple accents
   from the retired crystalline-logo design) are removed below; the new
   design draws its own vignette + animated canvas starfield instead.
   premiumBgShift / bgBreath / particleTwinkle keyframes (further down
   this file) are left in place but are now unused by this rule — kept
   rather than deleted in case any other future screen wants them. */
#app-loading-screen {
  position: fixed; inset: 0;
  background:
    radial-gradient(ellipse at 50% 38%, rgba(43,63,168,0.35) 0%, rgba(10,14,39,0) 55%),
    linear-gradient(160deg, #0D1540 0%, #05070F 70%);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  z-index: var(--z-critical); color: var(--color-white);
  transition: opacity var(--duration-sluggish) var(--ease-in-out); overflow: hidden;
}
#app-loading-screen::before { content: none; }
#app-loading-screen::after { content: none; }

/* — Admin PIN overlay — */
#admin-pin-overlay {
  display: none; position: fixed; inset: 0;
  background: rgba(0, 0, 0, 0.85); z-index: var(--z-critical);
  align-items: center; justify-content: center; flex-direction: column;
}
#admin-pin-overlay.show { display: flex; }
#admin-pin-overlay h3 { color: var(--accent); margin-bottom: 20px; font-size: var(--text-3xl); }
.pin-dots { display: flex; gap: 15px; margin-bottom: 25px; }
.pin-dot { width: 18px; height: 18px; border-radius: var(--radius-full); border: 2px solid var(--accent); background: transparent; transition: var(--transition-base); }
.pin-dot.filled { background: var(--accent); }
#pin-feedback { color: var(--danger); font-size: var(--text-md); margin-bottom: 15px; min-height: 1.2em; }
.pin-keypad { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; max-width: 240px; }
.pin-key { background: rgba(255,255,255,0.1); border: 1px solid rgba(255,255,255,0.2); color: var(--color-white); padding: 15px; border-radius: var(--radius-md); font-size: var(--text-2xl); font-weight: var(--weight-bold); cursor: pointer; transition: var(--transition-base); text-align: center; }
.pin-key:hover { background: rgba(255,255,255,0.2); }
.pin-key.clear { color: var(--danger); }
.pin-key.cancel { color: var(--color-neutral-300); font-size: var(--text-md); }


/* ═══════════════════════════════════════════════════════════════════════════
   §2  LAYOUT — APP SHELL, SIDEBAR, MAIN
   ═══════════════════════════════════════════════════════════════════════════ */

.sidebar {
  width: 270px !important;
  background: var(--g-hero) !important;
  border-right: 1px solid rgba(255, 255, 255, 0.06) !important;
  box-shadow: 4px 0 40px rgba(0, 0, 0, 0.40) !important;
  color: var(--color-white);
  display: flex; flex-direction: column;
  height: calc(var(--app-vh, 1vh) * 100); position: fixed; left: 0; top: 0;
  transition: transform var(--duration-slow) var(--ease-in-out);
  overflow-y: auto; z-index: var(--z-sidebar);
}
.sidebar-header {
  padding: 24px 20px 20px !important;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07) !important;
  position: relative !important; text-align: center;
  display: flex; align-items: center; justify-content: center;
}
.sidebar-header::after {
  content: '';
  position: absolute; bottom: 0; left: 20px; right: 20px; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 213, 0, 0.5), transparent);
}
.sidebar-header h2 {
  font-family: var(--font-ui) !important;
  font-size: var(--text-3xl) !important;
  font-weight: var(--weight-extrabold) !important;
  letter-spacing: 2.5px !important;
  background: linear-gradient(135deg, #ffffff 0%, var(--accent) 60%, var(--accent2) 100%) !important;
  -webkit-background-clip: text !important; -webkit-text-fill-color: transparent !important;
  background-clip: text !important;
}
.sidebar-footer {
  border-top: 1px solid rgba(255, 255, 255, 0.07) !important;
  padding: 16px !important; text-align: center;
}
.sidebar-footer .social-links { display: flex; justify-content: center; gap: 15px; margin-bottom: 15px; }
.sidebar-footer .social-links a { color: rgba(255, 255, 255, 0.5) !important; font-size: var(--text-2xl); transition: var(--transition-color); }
.sidebar-footer .social-links a:hover { color: var(--accent) !important; }
.sidebar-footer a { color: var(--color-white); text-decoration: none; font-weight: var(--weight-bold); }

/* Content overlay for mobile sidebar */
#content-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: var(--z-overlay); }
#content-overlay.show { display: block; }

/* ═══════════════════════════════════════════════════════════════════════════
   FIX (2026-07): mobile drawer content hidden behind the bottom nav bar
   ─────────────────────────────────────────────────────────────────────────
   .sidebar's z-index above relies on var(--z-sidebar), which comes from
   token.css (linked in index.html, but not available to audit here). Whatever
   that resolves to, #mobile-bottom-nav (nav-patch.css) is hardcoded to
   z-index: 9990 !important — a fixed, opaque, full-width white bar at the
   bottom of the screen. On mobile, once the drawer is open, that bar was
   painting ON TOP of the drawer's own last ~60-80px, hiding whatever sits
   there (Sign Out, the social links row, and for guests, the Login/Sign Up
   button) — this looked like "can't scroll to the bottom" because the
   content was there, just visually covered, not because .sidebar wasn't
   scrollable (it already has overflow-y:auto and does scroll).
   Forced above the bottom nav's fixed number here so it wins regardless of
   whatever token.css sets --z-sidebar to. #content-overlay bumped too so the
   dimmed backdrop covers the bottom nav consistently while the drawer's open,
   instead of leaving it undimmed and tappable underneath. Scoped to the same
   ≤992px breakpoint the drawer's slide-in behavior already uses. */
@media (max-width: 992px) {
  .sidebar {
    z-index: 9999 !important;
    /* Give the footer's last rows (Sign Out / social links / Login-Signup)
       breathing room above the 60px bottom nav + safe-area inset, so they
       land in clear scrollable space instead of right at the covered edge. */
    padding-bottom: calc(60px + env(safe-area-inset-bottom, 0px)) !important;
    box-sizing: border-box;
  }
  #content-overlay.show { z-index: 9995 !important; }
}

.main-content {
  margin-left: 270px !important;
  background: var(--background) !important;
  flex-grow: 1; padding: 30px;
  overflow-y: auto; height: calc(var(--app-vh, 1vh) * 100);
  padding-bottom: calc(80px + env(safe-area-inset-bottom, 0px)) !important;
}

/* App logo avatar */
#app-logo-avatar {
  width: 60px; height: 60px; border-radius: var(--radius-full);
  border: 3px solid var(--accent); object-fit: cover; cursor: pointer;
  background: rgba(255,255,255,0.15); display: flex; align-items: center; justify-content: center;
  overflow: hidden; margin: 0 auto 8px auto; transition: var(--transition-transform);
}
#app-logo-avatar img { width:100%; height:100%; object-fit:cover; border-radius: var(--radius-full); }
#app-logo-avatar .logo-placeholder-icon { color: var(--accent); font-size: var(--text-5xl); }
#app-logo-avatar:hover { transform: scale(1.05); }


/* ═══════════════════════════════════════════════════════════════════════════
   §3  NAVIGATION — SIDEBAR NAV ITEMS
   ═══════════════════════════════════════════════════════════════════════════ */

.sidebar-nav { list-style: none; flex-grow: 1; margin-top: 20px; }
.sidebar-nav li a {
  display: flex !important; align-items: center !important;
  padding: 11px 16px !important; margin: 3px 12px !important;
  border-radius: var(--radius-lg) !important;
  color: rgba(255, 255, 255, 0.65) !important;
  font-size: var(--text-base) !important; font-weight: var(--weight-medium) !important;
  letter-spacing: 0.2px !important; border-left: none !important;
  transition: var(--transition-base) !important; text-decoration: none !important; gap: 0 !important;
}
.sidebar-nav li a:hover {
  background: rgba(255, 255, 255, 0.07) !important;
  color: var(--color-white) !important; padding-left: 16px !important; transform: none !important;
}
.sidebar-nav li a.active {
  background: linear-gradient(135deg, rgba(255, 213, 0,0.20), rgba(255, 213, 0,0.05)) !important;
  color: var(--accent) !important; border-left: none !important;
  border-right: 3px solid var(--accent) !important; font-weight: var(--weight-semibold) !important;
  box-shadow: inset 0 0 20px rgba(255, 213, 0, 0.05) !important;
}
.sidebar-nav li a i { width: 30px; font-size: var(--text-xl); margin-right: 10px; }

/* Nav icon box */
.sidebar-nav li a .nav-icon-box {
  width: 34px; height: 34px; border-radius: var(--radius-md);
  background: rgba(255, 255, 255, 0.07);
  display: flex; align-items: center; justify-content: center;
  margin-right: 12px; flex-shrink: 0; transition: var(--transition-base); font-size: var(--text-base);
}
.sidebar-nav li a.active .nav-icon-box {
  background: rgba(255, 213, 0, 0.20); color: var(--accent);
  box-shadow: 0 4px 12px rgba(255, 213, 0, 0.20);
}

/* Sidebar search */
.sidebar-search-container { padding: 10px 20px; border-bottom: 1px solid var(--secondary); }
.sidebar-search-container input {
  width: 100%; padding: 8px 10px; border-radius: var(--radius-sm);
  border: 1px solid rgba(255,255,255,0.3); background: rgba(255,255,255,0.2);
  color: var(--color-white); font-size: var(--text-md);
}
.sidebar-search-container input::placeholder { color: rgba(255, 255, 255, 0.7); }

/* Mobile toggle */
.mobile-menu-toggle {
  display: none; position: fixed; top: 15px; left: 15px;
  font-size: var(--text-4xl); background: var(--color-white) !important;
  color: var(--primary) !important; border: 1px solid var(--border) !important;
  padding: 8px 12px; border-radius: var(--radius-md) !important;
  z-index: var(--z-sticky); cursor: pointer;
  box-shadow: var(--shadow-sm) !important;
}

/* Bottom nav */
.bottom-nav { padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px)) !important; }
.bottom-nav .nav-item,
.bottom-nav a,
.bottom-nav button { min-height: 48px; display: flex; flex-direction: column; align-items: center; justify-content: center; }


/* ═══════════════════════════════════════════════════════════════════════════
   §4  SECTION HEADERS & SEARCH BAR
   ═══════════════════════════════════════════════════════════════════════════ */

.header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 30px; flex-wrap: wrap; gap: 15px; padding: 28px 30px 16px !important; }
.header h1 {
  font-family: var(--font-ui) !important; font-weight: var(--weight-extrabold) !important;
  font-size: var(--text-title) !important; color: var(--primary) !important;
  letter-spacing: var(--tracking-tight) !important;
}
.header-actions { display: flex; align-items: center; gap: 20px; }
.cart-icon-button .cart-item-count {
  background-color: var(--danger-color); color: var(--color-white);
  border-radius: var(--radius-full); padding: 2px 7px; font-size: var(--text-sm); vertical-align: top; margin-left: 5px;
}

.section-search-bar {
  display: flex; align-items: center; gap: 10px;
  background: var(--color-white) !important; border-radius: var(--radius-2xl) !important;
  border: 1.5px solid rgba(10, 14, 39, 0.08) !important;
  padding: 8px 15px; margin-bottom: 20px;
  box-shadow: var(--shadow-xs) !important; transition: var(--transition-base) !important;
}
.section-search-bar:focus-within {
  border-color: var(--secondary) !important;
  box-shadow: 0 0 0 4px rgba(27, 43, 139, 0.08) !important;
}
.section-search-bar i { color: var(--color-neutral-300); }
.section-search-bar input { border: none; outline: none; flex-grow: 1; font-size: var(--text-lg); color: var(--primary) !important; }
#mkt-search-submit-btn {
  flex-shrink: 0; width: 32px; height: 32px; border-radius: var(--radius-full);
  background: var(--secondary, #1B2B8B); color: #fff; border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center; font-size: 0.8rem;
  transition: background 0.18s, transform 0.12s;
}
#mkt-search-submit-btn:hover { background: #2d45c8; }
#mkt-search-submit-btn:active { transform: scale(0.92); }

/* Header Google search box */
.header-search-container {
  width: 100%; margin-bottom: 20px; padding: 15px;
  background: var(--color-white); border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
}


/* ═══════════════════════════════════════════════════════════════════════════
   §5  STATUS / STORY BAR (WhatsApp-style)
   ═══════════════════════════════════════════════════════════════════════════ */

#status-bar-container {
  background: var(--color-white) !important;
  border-bottom: 1px solid var(--border) !important;
  padding: 10px 24px !important;
  box-shadow: 0 2px 12px rgba(10, 14, 39, 0.04) !important;
  position: sticky !important; top: 0 !important;
  z-index: var(--z-banner) !important;
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  display: none;
  transform: translateY(0);
  transition: transform 0.25s ease;
  will-change: transform;
}
#status-bar-container.visible { display: block; }
/* FIX (point #3: "status bar should hide on scroll like Facebook, not stay
   pinned and block the feed"): .status-bar-hidden is toggled by the scroll
   listener in app-status.js based on scroll direction on .main-content —
   scrolling down slides the bar up out of view, scrolling up (or returning
   to the top) slides it back down. Stays `position: sticky` so it still
   docks under the header when visible; only the visibility is animated. */
#status-bar-container.status-bar-hidden { transform: translateY(-100%); }
.status-bar-inner { display: flex; align-items: center; gap: 12px; overflow-x: auto; scrollbar-width: none; padding-bottom: 4px; }
.status-bar-inner::-webkit-scrollbar { display: none; }
.status-item { display: flex; flex-direction: column; align-items: center; gap: 4px; cursor: pointer; flex-shrink: 0; min-width: 60px; }
.status-avatar-ring {
  width: 52px; height: 52px; border-radius: var(--radius-full);
  background: linear-gradient(135deg, var(--flame-color), var(--live-color));
  padding: 2.5px; flex-shrink: 0;
  box-shadow: 0 2px 8px rgba(91, 14, 166, 0.2); transition: var(--transition-transform);
}
.status-avatar-ring:hover { transform: scale(1.08); }
.status-avatar-ring.viewed { background: linear-gradient(135deg, var(--color-neutral-200), var(--color-neutral-350)); }
.status-avatar-ring.add-own { background: var(--g-navy); position: relative; }
.status-avatar-inner { width: 100%; height: 100%; border-radius: var(--radius-full); border: 2px solid var(--color-white); overflow: hidden; background: var(--light-gray); }
.status-avatar-inner img { width: 100%; height: 100%; object-fit: cover; }
.status-add-icon {
  position: absolute; bottom: 0; right: 0; width: 18px; height: 18px; border-radius: var(--radius-full);
  background: var(--accent-color); color: var(--color-white); font-size: 0.7rem;
  display: flex; align-items: center; justify-content: center;
  border: 2px solid var(--color-white); font-weight: var(--weight-bold);
}
.status-username { font-size: 0.7rem; color: var(--text-primary); text-align: center; max-width: 60px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Status viewer modal */
#status-viewer-modal { position: fixed; inset: 0; background: rgba(0,0,0,0.95); z-index: var(--z-live); display: none; align-items: center; justify-content: center; }
#status-viewer-modal.show { display: flex; }
.status-viewer-content { width: min(390px, 100vw); height: min(760px, 100vh); position: relative; background: #111; display: flex; flex-direction: column; border-radius: 0; overflow: hidden; }
.status-progress-bars { display: flex; gap: 3px; padding: 12px; position: absolute; top: 0; left: 0; right: 0; z-index: 2; }
.status-progress-seg { flex: 1; height: 3px; background: rgba(255,255,255,0.35); border-radius: 2px; overflow: hidden; }
.status-progress-seg .fill { height: 100%; background: var(--color-white); width: 0%; transition: width 0.1s linear; }
.status-progress-seg.done .fill { width: 100%; }
.status-top-bar { position: absolute; top: 28px; left: 0; right: 0; z-index: 2; display: flex; align-items: center; padding: 8px 12px; gap: 10px; }
.status-user-mini-avatar { width: 36px; height: 36px; border-radius: var(--radius-full); border: 2px solid rgba(255,255,255,0.7); object-fit: cover; }
.status-media-display { width: 100%; height: 100%; object-fit: contain; max-height: 70vh; background: #000; }
.status-text-overlay { position: absolute; bottom: 80px; left: 0; right: 0; z-index: 2; padding: 20px; background: linear-gradient(transparent, rgba(0,0,0,0.7)); }
.status-reply-bar { position: absolute; bottom: 0; left: 0; right: 0; z-index: 2; padding: 12px; display: flex; gap: 8px; align-items: center; }
.status-reply-bar input { flex: 1; background: rgba(255,255,255,0.15); border: 1px solid rgba(255,255,255,0.3); border-radius: var(--radius-pill); padding: 10px 16px; color: var(--color-white); font-size: var(--text-md); outline: none; }
.status-reply-bar input::placeholder { color: rgba(255,255,255,0.5); }
.status-reply-send { background: var(--accent-color); border: none; border-radius: var(--radius-full); width: 40px; height: 40px; color: var(--color-white); cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: var(--text-xl); }
.status-close-btn { position: absolute; top: 20px; right: 12px; z-index: 10; background: none; border: none; color: var(--color-white); font-size: var(--text-4xl); cursor: pointer; }

/* Status create modal */
#create-status-modal { position: fixed; inset: 0; background: rgba(0,0,0,0.7); z-index: var(--z-toast); display: none; align-items: center; justify-content: center; }
#create-status-modal.show { display: flex; }
.create-status-card { background: var(--color-white); border-radius: var(--radius-lg); padding: 30px; width: min(450px, 95vw); }


/* ═══════════════════════════════════════════════════════════════════════════
   §6  BASE CARD
   ═══════════════════════════════════════════════════════════════════════════ */

.card {
  background: var(--color-white) !important;
  border-radius: var(--radius-3xl) !important;
  border: 1px solid var(--border) !important;
  box-shadow: 0 1px 3px rgba(10,14,39,0.06), 0 4px 16px rgba(10,14,39,0.06) !important;
  overflow: hidden !important;
  transition: box-shadow var(--duration-slow) var(--ease-out),
              transform var(--duration-slow) var(--ease-out) !important;
  margin-bottom: 8px;
}
.card:hover { box-shadow: 0 2px 8px rgba(10,14,39,0.08), 0 8px 32px rgba(10,14,39,0.10) !important; }
.card > h3 { padding: 25px 25px 0 25px; display: flex; justify-content: space-between; align-items: center; }
.card > h3, .card-content > h3, .card-content h3 {
  font-family: var(--font-ui) !important; font-weight: var(--weight-bold) !important;
  color: var(--primary) !important; font-size: var(--text-2xl) !important;
  letter-spacing: var(--tracking-tight) !important;
}
.card-content { padding: 24px !important; }

/* Sponsor CTA banner (Dashboard) — compact, premium navy/gold card.
   The whole card is a tap target that opens the Donor Portal (donor-hub);
   replaces the old oversized, empty-looking flat-green banner. */
.donor-cta-banner {
  cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent;
  overflow: hidden; position: relative; border: 1px solid rgba(255,213,0,0.35);
  /* !important required: the generic .card rule sets
     `background: var(--color-white) !important`, which — since !important
     always beats a non-!important declaration regardless of selector
     specificity — was silently overriding this gradient and leaving the
     white h3/p text invisible against a white card. */
  background: var(--g-giving) !important;
  transition: var(--transition-base);
}
.donor-cta-banner::before {
  content: ""; position: absolute; top: 0; left: 0; width: 4px; height: 100%;
  background: linear-gradient(180deg, var(--color-gold), var(--accent-bright), var(--color-gold));
}
.donor-cta-banner:active { transform: scale(0.985); }
.donor-cta-banner-inner { display: flex; align-items: center; gap: 14px; padding: 14px 16px 14px 18px; }
.donor-cta-icon {
  flex-shrink: 0; width: 38px; height: 38px; border-radius: 50%;
  background: rgba(255,213,0,0.18); border: 1.5px solid rgba(255,213,0,0.55);
  display: flex; align-items: center; justify-content: center;
}
.donor-cta-icon i { color: var(--accent); font-size: 1rem; }
.donor-cta-body { flex: 1; min-width: 0; }
.donor-cta-body h3 { margin: 0 0 3px; color: #fff; font-size: 0.95rem; font-weight: 800; }
.donor-cta-body p { margin: 0; color: rgba(255,255,255,0.75); font-size: 0.78rem; line-height: 1.4; }
.donor-cta-link { display: inline-flex; align-items: center; gap: 6px; margin-top: 6px; color: var(--accent); font-size: 0.74rem; font-weight: 700; }
.donor-cta-link i { font-size: 0.68rem; transition: transform 0.2s; }
.donor-cta-banner:active .donor-cta-link i { transform: translateX(3px); }
.donor-cta-chevron { flex-shrink: 0; color: rgba(255,213,0,0.6); font-size: 0.85rem; }

/* Giving-context scope (2026-07-25): Donor Hub and Grant Portal are
   giving/impact surfaces, not social/live ones, so --primary resolves
   to green here instead of the app-wide blue default. See tokens.css
   §2 co-primary usage rule -- everything below that references
   var(--primary) inherits green automatically, no per-rule edits needed. */
#donor-hub, .gtp-section { --primary: var(--primary-giving); }

/* Donor "Preferred Categories" chip checklist — replaces the native
   <select multiple> which rendered as an unstyled, hard-to-use OS listbox
   (needed Ctrl/Cmd-click or drag-select) that clashed with the app's design. */
.donor-category-checklist { display: flex; flex-wrap: wrap; gap: 8px; padding: 2px 0 4px; }
.donor-category-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 8px 14px;
  border: 1.5px solid rgba(10,14,39,0.12); border-radius: 999px;
  background: var(--color-surface-giving); font-size: 0.8rem; font-weight: var(--weight-semibold);
  color: var(--primary); cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent;
  transition: var(--transition-base);
}
.donor-category-chip input[type="checkbox"] { position: absolute; opacity: 0; width: 0; height: 0; }
.donor-category-chip.checked, .donor-category-chip:has(input:checked) {
  background: var(--primary); border-color: var(--primary); color: #fff;
}

/* Donor "Preferred Categories" dropdown — replaces the chip checklist above,
   which the user found took up too much vertical space as a wrapping grid.
   Custom (not native <select multiple>, which renders as an unstyled OS
   listbox needing Ctrl/Cmd-click) so multiple categories stay easy to pick
   with plain taps, but is collapsed into a single dropdown control. */
.donor-category-dropdown { position: relative; }
.donor-category-trigger {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; padding: 12px 14px; border: 1.5px solid rgba(10,14,39,0.12);
  border-radius: 12px; background: var(--color-white); cursor: pointer;
  font-family: inherit; font-size: 0.88rem; font-weight: var(--weight-semibold);
  color: var(--primary); text-align: left; -webkit-tap-highlight-color: transparent;
  transition: var(--transition-base);
}
.donor-category-trigger:hover { border-color: rgba(10,14,39,0.22); }
.donor-category-dropdown.open .donor-category-trigger {
  border-color: var(--primary); box-shadow: 0 0 0 3px rgba(27,43,139,0.10);
}
.donor-category-trigger-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 0; }
.donor-category-trigger-text.placeholder { color: var(--text-muted); font-weight: var(--weight-regular); }
.donor-category-trigger-icon { flex-shrink: 0; font-size: 0.78rem; color: var(--text-muted); transition: transform 0.2s; }
.donor-category-dropdown.open .donor-category-trigger-icon { transform: rotate(180deg); }
.donor-category-panel {
  display: none; position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: var(--z-dropdown, 50);
  max-height: 280px; overflow-y: auto; background: var(--color-white);
  border: 1px solid rgba(10,14,39,0.1); border-radius: 14px;
  box-shadow: var(--shadow-lg, 0 12px 32px rgba(10,14,39,0.16)); padding: 6px; flex-direction: column; gap: 2px;
}
.donor-category-dropdown.open .donor-category-panel { display: flex; }
.donor-category-option {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 9px;
  font-size: 0.85rem; font-weight: var(--weight-semibold); color: var(--primary);
  cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent;
}
.donor-category-option:hover { background: var(--color-surface-blue); }
.donor-category-option input[type="checkbox"] { position: absolute; opacity: 0; width: 0; height: 0; }
.donor-category-option span { flex: 1; }
.donor-category-option-tick { font-size: 0.72rem; color: var(--primary); opacity: 0; flex-shrink: 0; }
.donor-category-option:has(input:checked) { background: var(--color-surface-blue); }
.donor-category-option:has(input:checked) .donor-category-option-tick { opacity: 1; }

/* Donor wall — public acknowledgment of donors who funded a cause. */
.donor-wall-list { display: flex; flex-direction: column; gap: 10px; padding: 12px 16px 18px; }
.donor-wall-item { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: var(--radius-xl); background: var(--color-surface-blue); }
.donor-wall-avatar { width: 36px; height: 36px; border-radius: 50%; background: rgba(16,185,129,0.15); color: #10B981; display: flex; align-items: center; justify-content: center; flex-shrink: 0; font-size: 0.95rem; }
.donor-wall-info { flex: 1; min-width: 0; }
.donor-wall-name { font-weight: var(--weight-bold); color: var(--primary); font-size: 0.86rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.donor-wall-detail { font-size: 0.75rem; color: var(--text-muted); margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.donor-wall-amount { font-weight: var(--weight-bold); color: #10B981; font-size: 0.82rem; white-space: nowrap; flex-shrink: 0; }

/* ═══════════════════════════════════════════════════════════════════════════
   §6b  DONOR HUB — PREMIUM COMPONENTS
   All icons here are inline SVG (no @font-face/CDN dependency) — the
   Font-Awesome glyphs previously used in this section rendered as blank
   "tofu" boxes for donors on slow/blocked connections (the webfont never
   loaded), which is exactly what was reported as a "broken expansion
   icon." SVG is drawn immediately from markup, so it can't fail this way.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Section header — icon badge + title, used for every donor-hub card so
   the whole section reads as one deliberate system rather than mixed
   ad-hoc icons. */
.dh-header { display: flex; align-items: center; gap: 12px; padding: 22px 22px 4px; }
.dh-header-icon {
  flex-shrink: 0; width: 38px; height: 38px; border-radius: 12px;
  display: flex; align-items: center; justify-content: center;
  background: var(--dh-icon-bg, rgba(14,122,78,0.08));
}
.dh-header-icon svg { width: 19px; height: 19px; }
.dh-header-text { flex: 1; min-width: 0; }
.dh-header-text h3 { margin: 0 !important; padding: 0 !important; font-size: var(--text-xl, 1.05rem) !important; }
.dh-header-text p { margin: 2px 0 0; font-size: 0.78rem; color: var(--text-muted); }
.dh-header-count {
  flex-shrink: 0; font-size: 0.72rem; font-weight: var(--weight-bold); color: var(--primary);
  background: var(--color-surface-blue); padding: 3px 10px; border-radius: 999px;
}

/* Open Requests & Projects — premium thumbnail cards, one grid item per
   sponsorable target. Thumbnail color/icon communicates targetType at a
   glance (urgent SOS vs. planned project) without reading the label. */
.dh-target-grid { display: flex; flex-direction: column; gap: 14px; padding: 14px 16px 18px; }
.donor-target-card {
  border-radius: var(--radius-2xl, 18px); overflow: hidden; background: var(--color-white);
  border: 1px solid var(--border); box-shadow: var(--shadow-xs);
  transition: var(--transition-base);
}
.donor-target-card:active { transform: scale(0.99); }
.dh-target-thumb {
  position: relative; height: 64px; display: flex; align-items: center; padding: 0 16px;
  background: var(--dh-thumb-bg, var(--g-giving));
  overflow: hidden;
}
.dh-target-thumb svg.dh-watermark {
  position: absolute; right: -6px; top: 50%; transform: translateY(-50%);
  width: 72px; height: 72px; opacity: 0.16;
}
.dh-target-thumb-label {
  position: relative; z-index: 1; color: #fff; font-weight: var(--weight-bold);
  font-size: 0.7rem; letter-spacing: 0.06em; text-transform: uppercase;
  display: flex; align-items: center; gap: 6px;
}
.dh-target-thumb-label svg { width: 13px; height: 13px; flex-shrink: 0; }
.dh-target-body { padding: 14px 16px 16px; }
.donor-target-label { font-weight: var(--weight-bold); color: var(--primary); font-size: 0.94rem; line-height: 1.3; margin-bottom: 6px; }
.donor-target-meta {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 0.76rem;
  color: var(--text-muted); text-transform: capitalize; margin-bottom: 10px;
}
.donor-target-meta .dh-pill {
  display: inline-flex; align-items: center; gap: 4px; background: var(--color-surface-blue);
  color: var(--primary); font-weight: var(--weight-semibold); padding: 3px 9px; border-radius: 999px;
  text-transform: capitalize;
}
.donor-target-meta svg { width: 11px; height: 11px; }
.dh-target-footer { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.donor-target-amount { font-size: 0.7rem; color: var(--text-muted); line-height: 1.3; }
.donor-target-amount strong { display: block; font-size: 0.98rem; color: var(--primary); font-weight: var(--weight-extrabold); }
.sponsor-now-btn {
  flex-shrink: 0; display: inline-flex; align-items: center; gap: 6px; border: none; cursor: pointer;
  padding: 10px 16px; border-radius: 999px; font-size: 0.8rem; font-weight: var(--weight-bold);
  color: #fff; background: var(--g-giving);
  box-shadow: 0 4px 14px rgba(14,122,78,0.32); -webkit-tap-highlight-color: transparent;
  transition: var(--transition-base);
}
.sponsor-now-btn:active { transform: scale(0.96); }
.sponsor-now-btn svg { width: 13px; height: 13px; }

/* My Sponsorship Proposals — compact rows with a colored status pill. */
.dh-proposal-list { display: flex; flex-direction: column; gap: 10px; padding: 14px 16px 18px; }
.donor-proposal-row {
  display: flex; align-items: center; gap: 12px; padding: 13px 14px; border-radius: var(--radius-xl, 14px);
  background: var(--color-surface-blue); border: 1px solid var(--border);
}
.donor-proposal-icon {
  flex-shrink: 0; width: 34px; height: 34px; border-radius: 10px; background: rgba(14,122,78,0.08);
  display: flex; align-items: center; justify-content: center;
}
.donor-proposal-icon svg { width: 16px; height: 16px; color: var(--primary); }
.donor-proposal-main { flex: 1; min-width: 0; }
.donor-proposal-label { font-weight: var(--weight-bold); color: var(--primary); font-size: 0.86rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.donor-proposal-amount { font-size: 0.76rem; color: var(--text-muted); margin-top: 1px; font-weight: var(--weight-semibold); }
.donor-proposal-status {
  flex-shrink: 0; font-size: 0.68rem; font-weight: var(--weight-bold); text-transform: uppercase;
  letter-spacing: 0.03em; padding: 4px 10px; border-radius: 999px;
}
.donor-proposal-status.status-pending  { background: rgba(255,213,0,0.18); color: #93712F; }
.donor-proposal-status.status-approved { background: rgba(16,185,129,0.16); color: #0B815A; }
.donor-proposal-status.status-rejected { background: rgba(239,68,68,0.14); color: #B91C1C; }
.donor-proposal-status.status-funded,
.donor-proposal-status.status-completed { background: rgba(14,122,78,0.12); color: var(--primary); }
.fund-proposal-btn {
  flex-shrink: 0; border: none; cursor: pointer; padding: 8px 14px; border-radius: 999px;
  font-size: 0.74rem; font-weight: var(--weight-bold); color: #fff;
  background: var(--g-gold); -webkit-tap-highlight-color: transparent;
}

/* "Messages from Empyrean" — premium CTA card, replaces the plain heart-
   icon button. Matches .donor-cta-banner's navy/gold language so the
   donor hub reads as one system. */
.dh-messages-cta {
  width: 100%; display: flex; align-items: center; gap: 14px; padding: 18px 20px;
  background: var(--g-giving); border: none; cursor: pointer;
  -webkit-tap-highlight-color: transparent; position: relative; overflow: hidden;
}
.dh-messages-cta::before {
  content: ""; position: absolute; top: 0; left: 0; width: 4px; height: 100%;
  background: linear-gradient(180deg, var(--color-gold), var(--accent-bright), var(--color-gold));
}
.dh-messages-icon {
  flex-shrink: 0; width: 42px; height: 42px; border-radius: 50%;
  background: rgba(255,213,0,0.18); border: 1.5px solid rgba(255,213,0,0.55);
  display: flex; align-items: center; justify-content: center; position: relative;
}
.dh-messages-icon svg { width: 20px; height: 20px; color: var(--accent); }
.dh-messages-body { flex: 1; min-width: 0; text-align: left; }
.dh-messages-body h4 { margin: 0 0 2px; color: #fff; font-size: 0.92rem; font-weight: 800; }
.dh-messages-body p { margin: 0; color: rgba(255,255,255,0.7); font-size: 0.76rem; }
.dh-messages-chevron { flex-shrink: 0; color: rgba(255,213,0,0.7); }
.dh-messages-chevron svg { width: 15px; height: 15px; }
#donor-messages-badge {
  position: absolute; top: -3px; right: -3px; background: #EF4444; color: #fff;
  font-size: 0.64rem; font-weight: 800; min-width: 17px; height: 17px; border-radius: 999px;
  align-items: center; justify-content: center; padding: 0 4px; border: 2px solid #0A0E27;
}

/* Expand/collapse chevron used by the Donor Portal Access Notice — inline
   SVG so it can never render as a missing-glyph box. */
.dh-toggle-chevron { width: 13px; height: 13px; display: inline-block; transition: transform 0.25s; }



/* ═══════════════════════════════════════════════════════════════════════════
   §7  SOCIAL FEED — IMPACT STORY CARDS & ACTION BUTTONS
   ═══════════════════════════════════════════════════════════════════════════ */

/* Feed container — premium backdrop: a soft platinum background so each
   post reads as its own elevated card floating on top of it, rather than a
   flat continuous list with only hairline dividers between rows. */
#feed-container {
  border-radius: 0 !important;
  overflow: hidden;
  background: var(--background);
  box-shadow: none !important;
  border-left: none !important;
  border-right: none !important;
  padding: 14px 12px;
}

.impact-story {
  background: var(--color-white);
  border: 1px solid rgba(10, 14, 39, 0.06);
  border-radius: var(--radius-xl) !important;
  margin: 0 0 16px !important;
  box-shadow: 0 6px 20px rgba(10, 14, 39, 0.07), 0 1px 3px rgba(10, 14, 39, 0.05) !important;
  padding: 0; overflow: hidden; position: relative;
  transition: box-shadow var(--duration-slow) var(--ease-out);
}
.impact-story:last-child { margin-bottom: 0 !important; }
.impact-story::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: linear-gradient(90deg, var(--secondary), var(--accent2));
  opacity: 0; transition: opacity var(--duration-slow) var(--ease-out);
}
.impact-story:hover {
  box-shadow: 0 10px 30px rgba(10, 14, 39, 0.10), 0 2px 6px rgba(10, 14, 39, 0.06) !important;
}
.impact-story:hover::before { opacity: 1; }

/* Post title */
.story-post-title { font-size: var(--text-xl); font-weight: var(--weight-bold); color: var(--primary); padding: 10px 16px 0; line-height: var(--leading-snug); }

/* Post header */
.impact-story .story-header { padding: 14px 16px 8px !important; display: flex; align-items: center; margin-bottom: 0; }
.story-header .avatar-placeholder, .story-header .story-user-info strong, .story-header .story-user-info span { cursor: pointer; }
.story-header .story-user-info strong:hover { text-decoration: underline; text-underline-offset: 2px; }

.story-user-info { flex-grow: 1; }
.story-user-info strong { color: var(--primary); font-size: var(--text-lg); font-weight: var(--weight-bold); }
.story-user-info span { font-size: 0.75rem; color: var(--text-muted); display: block; margin-top: 2px; }

/* Post body */
.impact-story .story-content { padding: 8px 16px 10px !important; font-size: var(--text-md); line-height: var(--leading-relaxed); color: #374151; }
.story-content p { white-space: pre-wrap; word-wrap: break-word; }

/* ── Classic ornamental media/text divider ─────────────────────────────────
   A slim, low-opacity gold-tinted hairline marking where the framed media
   ends and the caption begins — refined "premium stationery" separator.
   No shape ornament: the previous rotated-square "diamond" with a glow
   read as a childish star rather than an elegant flourish. Purely
   decorative, purely CSS, so it applies to every card built from this
   shared markup (feed, profile, quotes, business posts) with no JS
   changes needed. */
.impact-story .story-media-container + .story-content {
  position: relative;
  padding-top: 16px !important;
}
.impact-story .story-media-container + .story-content::before {
  content: '';
  position: absolute; top: 7px; left: 0; right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(27,43,139,0.30) 6%, #C9A227 50%, rgba(27,43,139,0.30) 94%, transparent);
}

/* Retweet header */
.retweet-header { font-size: var(--text-md); color: var(--text-muted); margin-bottom: 10px; font-weight: var(--weight-bold); }
.retweet-header i { margin-right: 5px; color: var(--retweet-color); }

/* Media container — even though media renders at full card width, it gets
   its own tiny inset frame (margin + rounded corners + hairline gold-tinted
   border + soft shadow) rather than sitting flush against the card edges. */
.impact-story .story-media-container {
  margin: 14px 14px 0 !important;
  border-radius: 14px !important;
  overflow: hidden;
  border: 1px solid rgba(27, 43, 139, 0.14);
  box-shadow: 0 4px 14px rgba(10, 14, 39, 0.10);
}

/* Slight per-section thumbnail shape variation — same frame, different
   corner treatment, so SOS/crisis/success cards read apart from ordinary
   posts at a glance without changing layout or requiring JS changes. */
.impact-story.sos-request .story-media-container {
  border-radius: 4px 18px 4px 18px !important;
  border-color: rgba(239, 68, 68, 0.22);
}
.impact-story.crisis-report .story-media-container {
  border-radius: 18px 4px 18px 4px !important;
  border-color: rgba(245, 158, 11, 0.22);
}
.impact-story.success-story .story-media-container {
  border-radius: 20px !important;
  border-color: rgba(16, 185, 129, 0.22);
}
/* Sizing is handled per-layout below — no blanket max-height/object-fit here */
.story-media-container { display: grid; gap: 2px; overflow: hidden; border-radius: var(--radius-lg); }
.story-media-container[data-layout="solo"] { grid-template-columns: 1fr; }
.story-media-container[data-layout="duo"] { grid-template-columns: 1fr 1fr; }
.story-media-container[data-layout="trio"] { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; }
.story-media-container[data-layout="trio"] .story-media-item:first-child { grid-row: span 2; }
.story-media-container[data-layout="grid"] { grid-template-columns: 1fr 1fr; }
.story-media-container:not([data-layout]) { grid-template-columns: 1fr; }
.story-media-container[data-nav-target] { cursor: pointer; }

.story-media-item { overflow: hidden; background: transparent; display: flex; align-items: center; justify-content: center; }

/* Solo post: image/video renders at natural proportions, capped at 480px — no black bars, no zoom */
.story-media-container[data-layout="solo"] .story-media-item { display: block; height: auto; max-height: 480px; aspect-ratio: unset; background: transparent; overflow: hidden; }
.story-media-container[data-layout="solo"] .story-media-item img { width: 100%; height: auto; max-height: 480px; object-fit: cover; display: block; background: transparent; }
.story-media-container[data-layout="solo"] .story-media-item video { width: 100%; height: auto; max-height: 480px; min-height: 180px; object-fit: contain; display: block; background: #111; }

/* No-layout fallback (no data-layout set) */
.story-media-container:not([data-layout]) .story-media-item { display: block; height: auto; max-height: 480px; background: transparent; overflow: hidden; }
.story-media-container:not([data-layout]) .story-media-item img { width: 100%; height: auto; max-height: 480px; object-fit: cover; display: block; }
.story-media-container:not([data-layout]) .story-media-item video { width: 100%; height: auto; max-height: 480px; min-height: 180px; object-fit: contain; display: block; background: #111; }

/* Base fallback for img/video inside any media item — overridden by layout-specific rules above */
.story-media-item img, .story-media-item video { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Grid layouts: aspect-ratio gives cells an explicit height, so height:100% is correct */
.story-media-container[data-layout="duo"] .story-media-item { aspect-ratio: 4/5; background: transparent; }
.story-media-container[data-layout="trio"] .story-media-item { aspect-ratio: 1; background: transparent; }
.story-media-container[data-layout="trio"] .story-media-item:first-child { aspect-ratio: unset; height: 100%; }
.story-media-container[data-layout="grid"] .story-media-item { aspect-ratio: 1; background: transparent; }

/* Clickable media */
.story-media-item img, .story-main-image { cursor: zoom-in !important; }
.story-media-item img:hover, .story-main-image:hover { filter: brightness(0.94); transition: filter var(--duration-base) var(--ease-out); }

/* ── MULTI-MEDIA SWIPE (2+ items) ────────────────────────────────────
   Adjustment (2026-08-15): a post with 2+ media items previously laid
   them all out at once via the duo/trio/grid CSS grid rules above. Now
   they scroll horizontally one at a time instead (native scroll-snap —
   no JS needed for the swipe itself), with a small "current/total"
   counter badge overlaid bottom-right (injected by app-fixes.js's
   _empInitMediaSwipeCounter — see that file's "MULTI-MEDIA SWIPE
   COUNTER" block). data-count="1" (solo posts) is explicitly excluded
   via :not() so single-media posts are completely untouched, and every
   selector here adds one more simple selector than its data-layout
   counterpart above, so it wins on specificity alone without needing
   !important, while still living later in the file as a tie-breaker. */
.story-media-container[data-count]:not([data-count="1"]) {
  display: flex;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  position: relative;
}
.story-media-container[data-count]:not([data-count="1"])::-webkit-scrollbar { display: none; height: 0; }
.story-media-container[data-count]:not([data-count="1"]) .story-media-item {
  flex: 0 0 100%;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 420px;
  max-height: 480px;
  aspect-ratio: unset;
  /* FIX (request — "media is too magnified"): the fixed 4/5 portrait box
     combined with object-fit:cover below was cropping a landscape photo
     down to a zoomed-in sliver of it (exactly what the screenshot showed
     — most of the car cut off). Every slide now gets an equal-height
     stage (so the carousel still swipes cleanly, item to item, at a
     consistent height) but the image/video itself is shown at object-fit:
     contain — the FULL photo, never cropped or zoomed — with a neutral
     fill behind it for any letterbox space, same neutral placeholder
     shade already used everywhere else in this app (avatar placeholders,
     gallery items, etc.). */
  background: var(--color-neutral-100);
}
.story-media-container[data-count]:not([data-count="1"]) .story-media-item:first-child {
  aspect-ratio: unset;
  height: 420px;
}
.story-media-container[data-count]:not([data-count="1"]) .story-media-item img,
.story-media-container[data-count]:not([data-count="1"]) .story-media-item video {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

.story-media-counter {
  position: absolute;
  bottom: 10px;
  right: 10px;
  background: rgba(0, 0, 0, 0.62);
  color: #fff;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1;
  padding: 5px 10px;
  border-radius: 20px;
  pointer-events: none;
  z-index: 3;
  letter-spacing: 0.02em;
}

/* YouTube embed */
.story-youtube-embed { position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; background: #000; border-radius: var(--radius-md); margin-bottom: 15px; }
.story-youtube-embed iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }

/* Action bar */
/* ═══════════════════════════════════════════════════════════════════
   ACTION BAR — X / Twitter style
   Layout: [comment N] [retweet N] [like N] [views N] → [bookmark] [share]
   All grey by default, accent colour on hover/active, no bg, no border.
═══════════════════════════════════════════════════════════════════ */
/* ══════════════════════════════════════════════════════════
   X / TWITTER-STYLE ACTION BAR  — pixel-exact replica
   ══════════════════════════════════════════════════════════
   Measured from X's production app (screenshot):
     Icon:       18px × 18px, stroke 1.25px
     Count:      13px / 400 weight / #536471 / tabular
     Gap:        3px icon → count
     Pill pad:   7px top-bottom, 9px left-right
     Row border: 1px rgba(0,0,0,0.08)
*/

/* Row container */
.story-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0;
  padding: 2px 4px 4px;
  margin-top: 2px;
  border-top: 1px solid rgba(0,0,0,0.08);
  background: none;
  overflow: visible;
}

/* Each button */
.action-btn {
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  padding: 0 !important;
  border-radius: 9999px;
  cursor: pointer;
  color: #536471 !important;
  white-space: nowrap;
  flex-shrink: 0;
  text-decoration: none !important;
  border: none !important;
  background: none !important;
  transition: color 0.2s !important;
  -webkit-tap-highlight-color: transparent;
  line-height: 1;
  min-width: 0;
  position: relative;
  -webkit-appearance: none;
}

/* Inner pill */
.action-btn .x-pill {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 7px 9px;
  border-radius: 9999px;
  transition: background 0.2s;
  line-height: 1;
}

/* Icon */
.action-btn i,
.action-btn svg {
  width: 18px !important;
  height: 18px !important;
  flex-shrink: 0;
  transition: transform 0.15s ease;
  display: block;
  color: inherit;
  stroke: currentColor;
  shape-rendering: geometricPrecision;
}

/* Hairline stroke on every SVG child */
.action-btn svg,
.action-btn svg path,
.action-btn svg line,
.action-btn svg polyline,
.action-btn svg circle,
.action-btn svg rect,
.action-btn svg polygon,
.action-btn svg ellipse {
  stroke-width: 1.25 !important;
}

/* Filled sub-elements must not inherit stroke */
.action-btn svg [fill="currentColor"] {
  stroke-width: 0 !important;
  stroke: none !important;
}

/* Count labels — 13px, 400 weight, tabular */
.action-btn span.x-count,
.action-btn .comment-count,
.action-btn .retweet-count,
.action-btn .like-count,
.action-btn .quote-count,
.action-btn .share-count,
.action-btn .download-count,
.action-btn .view-count {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-size: 13px !important;
  font-weight: 400 !important;
  line-height: 1 !important;
  color: inherit;
  min-width: 0;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}

/* Legacy span wrapper */
.action-btn span:not(.x-pill):not(.x-count):not(.comment-count):not(.retweet-count):not(.like-count):not(.quote-count):not(.share-count):not(.download-count):not(.view-count) {
  font-size: 13px;
  font-weight: 400;
  color: inherit;
  font-variant-numeric: tabular-nums;
}

/* Hide zero/empty counts — X hides them */
.action-btn span:empty,
.action-btn span[data-count="0"],
.action-btn span.x-count:empty,
.action-btn .comment-count:empty,
.action-btn .retweet-count:empty,
.action-btn .like-count:empty,
.action-btn .quote-count:empty,
.action-btn .share-count:empty,
.action-btn .download-count:empty,
.action-btn .view-count:empty { display: none !important; }

/* ══════════════════════════════════════════════════════════
   HOVER — X's exact coloured pill highlights
   ══════════════════════════════════════════════════════════ */
.action-btn:hover { background: none !important; }

/* Reply / Comment — X blue */
.comment-btn:hover                           { color: rgb(29,155,240) !important; }
.comment-btn:hover .x-pill                   { background: rgba(29,155,240,0.1); }
.comment-btn:hover svg                       { transform: scale(1.07); }

/* Repost — X green */
.retweet-btn:hover                           { color: rgb(0,186,124) !important; }
.retweet-btn:hover .x-pill                   { background: rgba(0,186,124,0.1); }
.retweet-btn:hover svg                       { transform: scale(1.07); }

/* Like — X magenta */
.like-btn:hover                              { color: var(--engagement) !important; }
.like-btn:hover .x-pill                      { background: rgba(var(--color-pink-rgb), 0.1); }
.like-btn:hover svg                          { transform: scale(1.1); }

/* Quote — X blue */
.quote-btn:hover                             { color: rgb(29,155,240) !important; }
.quote-btn:hover .x-pill                     { background: rgba(29,155,240,0.1); }
.quote-btn:hover svg                         { transform: scale(1.07); }

/* Views — read-only, never interactive */
.view-count-display                          { color: #536471 !important; pointer-events: none !important; cursor: default !important; }
.view-count-display .x-pill                  { padding: 7px 6px; gap: 3px; }

/* Bookmark — X blue */
.bookmark-btn:hover                          { color: rgb(29,155,240) !important; }
.bookmark-btn:hover .x-pill                  { background: rgba(29,155,240,0.1); }

/* Download — X blue */
.download-media-btn:hover                    { color: rgb(29,155,240) !important; }
.download-media-btn:hover .x-pill            { background: rgba(29,155,240,0.1); }

/* Share — X blue */
.share-btn:hover                             { color: rgb(29,155,240) !important; }
.share-btn:hover .x-pill                     { background: rgba(29,155,240,0.1); }
.share-btn:hover svg                         { transform: scale(1.07); }

/* ══════════════════════════════════════════════════════════
   TOGGLED / ACTIVE STATES — exact X colors
   ══════════════════════════════════════════════════════════ */

/* Liked — magenta fill + stroke */
.action-btn.liked                   { color: var(--engagement) !important; }
.action-btn.liked svg               { stroke: var(--engagement) !important; fill: var(--engagement) !important; }
.action-btn.liked span              { color: var(--engagement) !important; }
.action-btn.liked .x-pill           { background: rgba(var(--color-pink-rgb), 0.06); }

/* Retweeted — green */
.action-btn.retweeted               { color: rgb(0,186,124) !important; }
.action-btn.retweeted svg           { stroke: rgb(0,186,124) !important; }
.action-btn.retweeted span          { color: rgb(0,186,124) !important; }
.action-btn.retweeted .x-pill       { background: rgba(0,186,124,0.06); }

/* Bookmarked — blue fill */
.action-btn.bookmarked              { color: rgb(29,155,240) !important; }
.action-btn.bookmarked svg          { stroke: rgb(29,155,240) !important; fill: rgba(29,155,240,0.18) !important; }
.action-btn.bookmarked span         { color: rgb(29,155,240) !important; }
.action-btn.bookmarked .x-pill      { background: rgba(29,155,240,0.06); }

/* Bookmark always pushes to far right */
.action-btn.bookmark-btn,
.action-btn[data-action="bookmark"] { margin-left: auto; }

/* ══════════════════════════════════════════════════════════
   VIEW COUNT DISPLAY (read-only, no pointer)
   ══════════════════════════════════════════════════════════ */
.view-count-display {
  display: inline-flex !important;
  align-items: center;
  gap: 3px;
  padding: 7px 9px;
  color: #536471 !important;
  font-size: 13px;
  pointer-events: none !important;
  cursor: default !important;
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

/* ── New-posts notification pill ── */
#empyrean-new-posts-pill {
  position: fixed;
  top: 70px;
  left: 50%;
  transform: translateX(-50%) translateY(-80px);
  z-index: 9999;
  background: rgb(29,155,240);
  color: #fff;
  border-radius: 9999px;
  padding: 10px 20px;
  font-size: 0.88rem;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 4px 20px rgba(29,155,240,0.35);
  display: flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
  transition: transform 0.3s cubic-bezier(0.34,1.56,0.64,1), opacity 0.25s;
  opacity: 0;
  pointer-events: none;
  user-select: none;
}
#empyrean-new-posts-pill.visible {
  transform: translateX(-50%) translateY(0);
  opacity: 1;
  pointer-events: auto;
}
#empyrean-new-posts-pill i { font-size: 0.85rem; }
.help-now-btn { cursor: pointer !important; }
.help-now-btn:hover { filter: brightness(1.08); transform: translateY(-1px); transition: var(--transition-base); }

/* View counts & timestamps */
.story-timestamp, .like-count, .retweet-count, .comment-count { font-variant-numeric: tabular-nums; }

/* ═══════════════════════════════════════════════════════════════════
   SOS / CRISIS CARD — premium redesign
   Was: plain flat square avatar, hover-only accent bar (invisible on
   mobile, which is most of this app's traffic), a bare text badge, and
   the "amount needed" buried mid-sentence in body text. Redesigned for
   a calmer, more premium/editorial feel that still reads as urgent.
   ═══════════════════════════════════════════════════════════════════ */

/* Persistent color-coded top accent (was opacity:0 until :hover, which
   never fires on a touch device — effectively invisible on mobile). */
.impact-story.sos-request::before,
.impact-story.crisis-report::before {
  opacity: 1 !important;
}
.impact-story.sos-request::before {
  background: linear-gradient(90deg, var(--danger-color), var(--danger-light), var(--danger-color)) !important;
}
.impact-story.crisis-report::before {
  background: linear-gradient(90deg, var(--warning-color), #FBBF24, var(--warning-color)) !important;
}

/* Faint tinted wash near the top of the card only — keeps the rest of
   the card the same clean white used by every other post so the feed
   doesn't turn into a wall of colour, while still visually setting SOS/
   crisis cards apart from ordinary posts at a glance. */
.impact-story.sos-request    { background: linear-gradient(180deg, rgba(239,68,68,0.045) 0%, var(--color-white) 110px) !important; border-left: none !important; }
.impact-story.crisis-report  { background: linear-gradient(180deg, rgba(245,158,11,0.045) 0%, var(--color-white) 110px) !important; border-left: none !important; }
.impact-story.success-story  { border-left: 3px solid var(--success-color) !important; }

/* Eyebrow label above the headline ("SOS Appeal" / "Crisis Report"),
   separating the category from the applicant's own title text instead
   of jamming both into one prefixed string ("SOS: tuition"). */
.sos-eyebrow, .crisis-eyebrow {
  display: block; font-size: 0.68rem; font-weight: var(--weight-bold);
  letter-spacing: 0.06em; text-transform: uppercase; margin-bottom: 2px;
}
.sos-eyebrow   { color: var(--danger-color); }
.crisis-eyebrow{ color: var(--warning-color); }

/* Circular avatar with a soft urgency-coloured ring, replacing the flat
   slightly-rounded square (which is what made the ui-avatars.com
   initials fallback look like a plain flat colour tile). */
.impact-story.sos-request .avatar-placeholder.square,
.impact-story.crisis-report .avatar-placeholder.square {
  width: 50px !important; height: 50px !important; border-radius: var(--radius-full) !important;
  position: relative; overflow: visible !important; background: transparent !important;
}
.impact-story.sos-request .avatar-placeholder.square img,
.impact-story.crisis-report .avatar-placeholder.square img {
  width: 100%; height: 100%; border-radius: var(--radius-full); object-fit: cover; display: block;
}
.impact-story.sos-request .avatar-placeholder.square {
  box-shadow: 0 0 0 2.5px var(--color-white), 0 0 0 4.5px rgba(239,68,68,0.5), 0 4px 10px rgba(239,68,68,0.18);
}
.impact-story.crisis-report .avatar-placeholder.square {
  box-shadow: 0 0 0 2.5px var(--color-white), 0 0 0 4.5px rgba(245,158,11,0.5), 0 4px 10px rgba(245,158,11,0.18);
}

/* Small urgency-icon badge pinned to the avatar, echoing the verified-
   checkmark pattern already used elsewhere in the app. */
.avatar-urgency-badge {
  position: absolute; bottom: -2px; right: -2px; width: 18px; height: 18px; border-radius: var(--radius-full);
  display: flex; align-items: center; justify-content: center; border: 2px solid var(--color-white);
  box-shadow: 0 2px 5px rgba(0,0,0,0.25);
}
.sos-request .avatar-urgency-badge   { background: var(--danger-color); }
.crisis-report .avatar-urgency-badge { background: var(--warning-color); }

/* Badges: icon + label, with a slow, gentle breathing glow on the true
   emergency badge only (SOS) — subtle enough not to feel gaudy. */
.sos-badge, .crisis-badge { display: inline-flex !important; align-items: center; gap: 5px; }
.sos-badge svg, .crisis-badge svg { flex-shrink: 0; }
.sos-badge {
  background: linear-gradient(135deg, var(--danger-color), var(--danger-light)) !important; color: var(--color-white);
  padding: 5px 12px; border-radius: var(--radius-pill) !important; font-size: var(--text-md);
  font-weight: var(--weight-bold); margin-left: 15px; box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3) !important;
  animation: sosBadgePulse 2.6s ease-in-out infinite;
}
.crisis-badge {
  background: linear-gradient(135deg, var(--warning-color), #FBBF24) !important; color: var(--color-white) !important;
  padding: 5px 12px; border-radius: var(--radius-pill) !important; font-size: var(--text-md);
  font-weight: var(--weight-bold); margin-left: 15px; box-shadow: 0 4px 12px rgba(245,158,11,0.3) !important;
}
@keyframes sosBadgePulse {
  0%, 100% { box-shadow: 0 4px 12px rgba(239,68,68,0.3); }
  50%      { box-shadow: 0 4px 18px rgba(239,68,68,0.55); }
}

/* NOTE: the "amount needed" panel (formerly .sos-amount-chip here) has moved
   to a self-contained component — see window.buildSosAmountBadgeHTML() in
   app-feed.js, which injects its own <style id="sos-amount-badge-styles">
   for the .sos-goal-badge markup. That's now the ONLY definition of this
   badge (both the feed card and app-sos.js's card + repair sweep call it),
   so it no longer needs an entry here. */

/* Badges */
.sponsored-badge { background: var(--accent-color); color: var(--text-primary); padding: 3px 10px; border-radius: 12px; font-size: var(--text-sm); font-weight: var(--weight-bold); margin-left: 10px; }

/* Gift button */
.gift-button { background: var(--accent-color); color: var(--text-primary); padding: 6px 15px; border-radius: 20px; font-weight: var(--weight-bold); border: none; margin-left: auto; cursor: pointer; }

/* Follow button (inline, not on suggested-users card) */
.follow-btn { background: var(--accent-color); color: var(--text-primary); border: none; padding: 6px 15px; border-radius: 20px; font-weight: var(--weight-bold); cursor: pointer; transition: var(--transition-color); }
.follow-btn.followed { background: var(--secondary); color: var(--color-white); }

/* FIX (bug — live host-preview panel "Message" button had zero CSS anywhere,
   rendering as a tiny unstyled native button with no visible label, easy to
   miss against the dark .live-sub-modal background): give .lhp-actions a
   proper row layout and style .lhp-message-btn to match .lhp-follow-btn's
   pill shape as a clearly visible secondary action, icon + "Message" label. */
.lhp-actions { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
.lhp-actions .lhp-follow-btn { flex: 1; }
.lhp-message-btn {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    background: transparent;
    color: var(--color-white);
    border: 1.5px solid rgba(255,255,255,0.45);
    padding: 6px 15px;
    border-radius: 20px;
    font-weight: var(--weight-bold);
    font-size: var(--text-sm, 0.85rem);
    cursor: pointer;
    transition: var(--transition-color);
}
.lhp-message-btn:hover, .lhp-message-btn:active { background: rgba(255,255,255,0.15); }
.lhp-message-btn i { font-size: 1rem; }

/* Feed empty state */
#feed-empty-state { background: var(--color-white) !important; border-radius: var(--radius-3xl) !important; border: 2px dashed var(--border) !important; padding: 60px 30px !important; text-align: center !important; }

/* Post moderation */
.post-content-warning { filter: blur(6px); pointer-events: none; }
.post-moderation-banner { background: rgba(239,68,68,0.10); border: 1.5px solid rgba(239,68,68,0.25); border-radius: var(--radius-lg); padding: 12px 16px; margin: 8px 0; color: #DC2626; font-size: var(--text-sm); font-weight: var(--weight-semibold); display: flex; align-items: center; gap: 8px; }

/* Avatar */
.avatar-placeholder { position: relative; overflow: hidden; background-color: var(--color-neutral-100); cursor: pointer; flex-shrink: 0; }
.avatar-placeholder.square { width: 45px; height: 45px; border-radius: var(--radius-md); margin-right: 15px; }
.avatar-placeholder .upload-overlay { position: absolute; inset: 0; background: rgba(0,0,0,0.5); color: var(--color-white); display: flex; align-items: center; justify-content: center; opacity: 0; transition: var(--transition-opacity); }
.avatar-placeholder:hover .upload-overlay { opacity: 1; }
.avatar-placeholder img, .avatar-placeholder video { width: 100%; height: 100%; object-fit: cover; }

/* Comment section */
.comment-section { display: none; margin-top: 20px; padding-top: 15px; border-top: 1px solid var(--light-gray); }
.comment-list { max-height: 300px; overflow-y: auto; margin-bottom: 15px; }
.comment { display: flex; gap: 10px; margin-bottom: 15px; }
.comment .avatar-placeholder { width: 35px; height: 35px; border-radius: var(--radius-md); }
.comment-content { background: #f7f7f7; padding: 10px 15px; border-radius: var(--radius-lg); flex-grow: 1; }
.comment-content strong { font-size: var(--text-md); color: var(--primary); }
.comment-content p { font-size: var(--text-lg); margin: 5px 0 0 0; line-height: var(--leading-snug); white-space: pre-wrap; word-wrap: break-word; }
.comment-form { display: flex; gap: 10px; }
.comment-form input { flex-grow: 1; border-radius: var(--radius-pill) !important; padding-left: 15px; border: 1.5px solid rgba(10,14,39,0.10) !important; background: var(--color-surface-blue) !important; font-size: 0.87rem !important; }
.comment-form button { background: var(--g-navy) !important; color: var(--color-white) !important; border: none; border-radius: var(--radius-full) !important; width: 36px !important; height: 36px !important; display: flex; align-items: center; justify-content: center; cursor: pointer; flex-shrink: 0; }

/* Post options menu */
.post-options { position: relative; margin-left: auto; }
.options-btn { background: none; border: none; font-size: var(--text-lg); color: var(--color-neutral-350); cursor: pointer; padding: 5px; }
.options-menu { display: none; position: absolute; right: 0; top: 100%; background: var(--color-white); border-radius: var(--radius-md); box-shadow: var(--shadow-md); overflow: hidden; list-style: none; padding: 5px 0; z-index: var(--z-dropdown); width: 120px; }
.options-menu.show { display: block; }
.options-menu a { display: flex; align-items: center; gap: 10px; padding: 10px 15px; text-decoration: none; color: var(--text-primary); font-size: var(--text-md); }
.options-menu a:hover { background: var(--color-neutral-75); }
.options-menu a i { width: 20px; }

/* Post creation */
#create-post-form { position: relative; }
#create-post-form textarea { min-height: 80px; margin-bottom: 15px; }
.post-actions-container { display: flex; justify-content: space-between; align-items: center; }
#post-media-preview, #sos-media-preview, #crisis-media-preview, #business-post-media-preview { margin-top: 15px; display: grid; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: 10px; }
#post-media-preview img, #post-media-preview video,
#sos-media-preview img, #sos-media-preview video,
#crisis-media-preview img, #crisis-media-preview video,
#business-post-media-preview img, #business-post-media-preview video { width: 100%; height: 100px; object-fit: cover; border-radius: var(--radius-md); }
.btn-media-upload { background-color: var(--color-neutral-100); border: 1px solid var(--color-neutral-200); color: var(--primary); padding: 8px 15px; font-weight: var(--weight-medium); }
.btn-media-upload:hover { background-color: var(--color-neutral-150); }

/* Guest login banner */
#guest-login-banner { animation: slideUp 0.35s ease; }


/* ═══════════════════════════════════════════════════════════════════════════
   §8  MARKETPLACE / PROPERTY CARDS
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Marketplace: category picker (posting form) ── */
.mkt-category-picker { display: flex; flex-wrap: wrap; gap: 10px; margin: 8px 0 4px; }
.mkt-cat-tab { display: flex; align-items: center; gap: 8px; padding: 10px 16px; border-radius: 12px; border: 1.5px solid rgba(var(--color-navy-rgb),0.15); background: #fff; font-size: var(--text-sm); font-weight: 600; color: var(--color-neutral-600); cursor: pointer; transition: all 0.18s; }
.mkt-cat-tab i { color: var(--secondary); }
.mkt-cat-tab:hover { border-color: var(--secondary); }
.mkt-cat-tab.active { background: var(--g-navy, linear-gradient(135deg,var(--color-navy),var(--color-royal))); border-color: transparent; color: #fff; }
.mkt-cat-tab.active i { color: var(--color-gold); }
.mkt-category-fields { margin-top: 14px; padding-top: 14px; border-top: 1px dashed rgba(var(--color-navy-rgb),0.15); animation: mktCatFieldsIn 0.2s ease; }
@keyframes mktCatFieldsIn { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: translateY(0); } }
.mkt-category-fields .form-group { margin-bottom: 14px; }

/* ── Marketplace: filter/sort bar (listings grid) ── */
.mkt-search-bar { padding: 7px 14px; margin-bottom: 16px; }
.mkt-search-bar input { font-size: var(--text-base) !important; }

.mkt-filter-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; margin: 16px 0; }
.mkt-filter-tabs { display: flex; flex-wrap: wrap; gap: 8px; }
.mkt-filter-tab { padding: 8px 14px; border-radius: 20px; border: 1.5px solid rgba(var(--color-navy-rgb),0.15); background: #fff; font-size: var(--text-sm); font-weight: 600; color: var(--color-neutral-600); cursor: pointer; transition: all 0.18s; }
.mkt-filter-tab i { margin-right: 4px; }
.mkt-filter-tab.active { background: var(--secondary); border-color: var(--secondary); color: #fff; }
.mkt-filter-controls { display: flex; align-items: center; gap: 8px; }
#mkt-sort-select { padding: 8px 12px; border-radius: 10px; border: 1.5px solid rgba(var(--color-navy-rgb),0.15); font-size: var(--text-sm); background: #fff; font-family: inherit; color: inherit; }
#mkt-save-search-btn { padding: 8px 12px; border-radius: 10px; border: 1.5px solid rgba(var(--color-navy-rgb),0.15); background: #fff; cursor: pointer; color: var(--secondary); }
#mkt-save-search-btn.active-saved { background: var(--color-gold); border-color: var(--color-gold); color: #fff; }
.mkt-saved-searches { display: flex; flex-wrap: wrap; gap: 6px; width: 100%; }
.mkt-saved-search-chip { display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px; border-radius: 14px; background: rgba(var(--color-navy-rgb),0.06); font-size: var(--text-xs); color: var(--color-neutral-600); cursor: pointer; }
.mkt-saved-search-chip .remove-chip { color: var(--danger); cursor: pointer; }

/* ── Marketplace: card additions (category badge + quick specs) ── */
.property-card .mkt-cat-badge { display: inline-flex; align-items: center; gap: 4px; font-size: var(--text-xs); font-weight: 700; padding: 3px 9px; border-radius: 10px; background: rgba(27,43,139,0.08); color: var(--secondary); margin-bottom: 4px; }

/* ── Marketplace Adjustments #3 follow-up (2026-08-09): the chip strip
   (Condition/Brand/Model/Year/etc.) is now wrapped in its own clamped
   container that shows only its first line by default — this is the "car
   features column is still too crowded" fix: a spec-heavy category like
   Vehicles was wrapping this strip across two or three rows on its own,
   on top of the separate Features-text row below. max-height is sized to
   one .mkt-quick-spec chip's row-box (padding 3px top+bottom + ~11.2px
   text-xs line-box ≈ 20px; 24px leaves a little headroom across
   browsers/zoom levels) with overflow hidden, so any second/third row of
   chips is simply clipped until Expand is tapped. */
.property-card .mkt-quick-specs-row { padding: 0 12px 8px; }
.property-card .mkt-quick-specs { display: flex; flex-wrap: wrap; gap: 6px; max-height: 24px; overflow: hidden; }
.property-card .mkt-quick-specs-row.mkt-specs-expanded .mkt-quick-specs { max-height: none; overflow: visible; }
.property-card .mkt-specs-expand-btn {
  display: inline-block; margin-top: 4px; background: none; border: none; padding: 0;
  font-size: var(--text-xs); font-weight: 700; color: var(--secondary, #1B2B8B);
  cursor: pointer; white-space: nowrap;
}
.property-card .mkt-specs-expand-btn:active { opacity: 0.7; }
.property-card .mkt-quick-spec { font-size: var(--text-xs); color: var(--color-neutral-600); background: rgba(var(--color-navy-rgb),0.05); padding: 3px 8px; border-radius: 8px; }

/* ── Marketplace Adjustments #3 (2026-08-09): Features shows one line by
   default; "Expand" reveals the rest. Kept separate from .mkt-quick-specs
   above so it can span the card's full width instead of wrapping mid-row.
   Independent toggle/state from the chip-strip clamp above — a listing
   can expand one without the other. */
.property-card .mkt-features-row { padding: 0 12px 8px; display: flex; align-items: baseline; gap: 8px; }
.property-card .mkt-features-text {
  flex: 1; min-width: 0; font-size: var(--text-xs); color: var(--color-neutral-600);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.property-card .mkt-features-row.mkt-features-expanded .mkt-features-text {
  white-space: normal; overflow: visible; text-overflow: clip;
}
.property-card .mkt-features-expand-btn {
  flex-shrink: 0; background: none; border: none; padding: 0;
  font-size: var(--text-xs); font-weight: 700; color: var(--secondary, #1B2B8B);
  cursor: pointer; white-space: nowrap;
}
.property-card .mkt-features-expand-btn:active { opacity: 0.7; }

/* FIX (request — "reduce the width of the card thumbnail a little"):
   this grid had no horizontal padding at all, so on a single-column
   phone screen (auto-fit collapses to 1 column below ~660px) each
   card — and the full-bleed photo inside it — ran edge-to-edge with
   the device screen (see the "Rx350L" listing screenshot). A small
   side inset here narrows every card (and its thumbnail, which is
   width:100% of the card) a little without touching the desktop
   multi-column breakpoints, which just get slightly narrower columns
   from the same change. */
.property-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(330px, 1fr)); gap: 28px; padding: 0 10px; }

/* ── FIX (request — Marketplace Home Page: card avatar thumbnail size +
   grid view toggle, 2026-08-09) ──────────────────────────────────────────
   Card thumbnail enlarged (236px → 300px desktop, 192px → 240px mobile —
   see the height overrides further down) to match the larger, more
   prominent card-photo proportions requested. #mkt-view-toggle-btn (in
   the search bar, index.html) toggles `.mkt-grid-view` on
   #property-grid-container: default is the normal auto-fit single-card
   layout above; `.mkt-grid-view` forces a fixed 2-column layout with a
   shorter thumbnail so more listings are visible per screen, mirroring a
   standard marketplace grid/list toggle. State is remembered via
   localStorage (see _mktInitViewToggle() in app-marketplace.js). */
.mkt-view-toggle-btn {
  flex-shrink: 0; width: 38px; height: 38px; border-radius: 10px;
  border: 1.5px solid rgba(var(--color-navy-rgb),0.15); background: #fff;
  color: var(--secondary); display: flex; align-items: center; justify-content: center;
  cursor: pointer; margin-left: 6px; font-size: 0.9rem;
}
.mkt-view-toggle-btn.active-view { background: var(--color-gold); border-color: var(--color-gold); color: #fff; }
.property-grid.mkt-grid-view {
  grid-template-columns: repeat(2, 1fr) !important;
  gap: 12px !important;
}
.property-grid.mkt-grid-view .property-card img,
.property-grid.mkt-grid-view .property-card video,
.property-grid.mkt-grid-view .mkt-media-carousel,
.property-grid.mkt-grid-view .mkt-media-carousel .mkt-carousel-track > * {
  height: 140px !important;
}
.property-grid.mkt-grid-view .property-info h4 { font-size: var(--text-sm); }
/* FIX (Marketplace Layout Upgrade): the old .mkt-quick-specs-row/
   .mkt-features-row are retired — condition/specs+features now live in
   .mkt-row2 (Row 2 of the new 3-row layout). Row 1 (.mkt-row1, brand +
   price) stays visible here, same as the price div always did before —
   matches the existing "grid view shows only price/model/contact" rule
   just below. */
.property-grid.mkt-grid-view .mkt-row2 { display: none; }

/* ── Marketplace Adjustments #9 (2026-08-09): "After toggling the grid
   view, redesign the card to be more compact — show only the price,
   model name, and contact information." Everything else on the card
   (category badge, location line, features row, seller-info bar,
   documents chips, and the owner-only Promote/Edit/Delete/Auto-Reply
   buttons) is hidden in this mode; Contact Seller/Call/WhatsApp — the
   "contact information" the request asks to keep — stay visible. */
.property-grid.mkt-grid-view .property-info .mkt-cat-badge,
.property-grid.mkt-grid-view .property-info p,
.property-grid.mkt-grid-view .mkt-features-row,
.property-grid.mkt-grid-view .mkt-row2,
.property-grid.mkt-grid-view .property-seller-info,
.property-grid.mkt-grid-view .mkt-doc-chips,
.property-grid.mkt-grid-view .direct-trade-warning,
.property-grid.mkt-grid-view .promote-post-btn,
.property-grid.mkt-grid-view .promote-item-btn,
.property-grid.mkt-grid-view .edit-post-btn,
.property-grid.mkt-grid-view .delete-post-btn,
.property-grid.mkt-grid-view .mkt-autoreply-btn {
  display: none !important;
}
.property-grid.mkt-grid-view .property-actions {
  padding: 6px 10px 10px !important; gap: 6px !important;
}

/* ── Multi-media horizontal swipe carousel inside the card thumbnail
   (request — "Enable multiple media uploads": horizontal swipe carousel,
   optimized for mobile touch). Replaces the previous static photo grid
   for listings with more than one media item — see app-fixes.js's card
   builder, which now emits this markup for _mktAllUrls.length > 1
   instead of a CSS grid of thumbnails. Native scroll-snap gives free,
   momentum-based touch swiping with no extra JS gesture handling needed;
   a small dot/count badge (top-right, matching the reference design)
   shows how many photos the listing has. */
.mkt-media-carousel { position: relative; width: 100%; height: 250px; overflow: hidden; background: #000; }
.mkt-carousel-track {
  display: flex; width: 100%; height: 100%; overflow-x: auto; scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.mkt-carousel-track::-webkit-scrollbar { display: none; }
.mkt-carousel-track > img, .mkt-carousel-track > video {
  flex: 0 0 100%; width: 100%; height: 100%; object-fit: cover; scroll-snap-align: start;
}
.mkt-carousel-count-badge {
  position: absolute; top: 10px; right: 10px; z-index: 2;
  background: rgba(0,0,0,0.6); color: #fff; font-size: var(--text-xs); font-weight: 700;
  padding: 4px 9px; border-radius: 12px; display: flex; align-items: center; gap: 5px;
  pointer-events: none;
}
.property-card {
  background: var(--color-white) !important;
  border-radius: var(--radius-2xl) !important;
  border: 1px solid var(--border) !important;
  box-shadow: var(--shadow-sm) !important;
  overflow: hidden !important;
  transition: all var(--duration-slow) var(--ease-in-out) !important;
  display: flex !important; flex-direction: column !important; position: relative !important;
  cursor: pointer;
}
.property-card::after { content: ''; position: absolute; inset: 0; border-radius: var(--radius-2xl); background: linear-gradient(135deg, rgba(255, 213, 0,0.08), transparent); opacity: 0; transition: var(--transition-opacity); pointer-events: none; }
.property-card:hover { box-shadow: var(--shadow-xl) !important; transform: translateY(-6px) !important; }
.property-card:hover::after { opacity: 1; }
/* FIX (request — "reduce the video and pictures size a little, the
   media is too large"): 300px ran taller than the card really needed
   (see the Rx350L listing screenshot — the photo alone filled most of
   the screen). Brought down a little to 250px; .mkt-media-carousel
   just below stays matched to the same value so a single-photo and
   multi-photo listing still read as the same size as each other. */
.property-card img, .property-card video { width: 100% !important; height: 250px !important; object-fit: cover !important; }
.mkt-no-media-placeholder {
  width: 100%; height: 200px; position: relative; overflow: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  background: radial-gradient(circle at 30% 18%, rgba(255,213,0,0.28), transparent 60%),
              linear-gradient(135deg, var(--color-navy, #0A0C1F) 0%, var(--color-royal, #1A2A7F) 48%, #2844B8 100%);
}
/* Fine diagonal pinstripe texture — a classic tailoring cue rather than a
   flat block of color. */
.mkt-no-media-placeholder::before {
  content: ''; position: absolute; inset: 0; opacity: 0.55; pointer-events: none; z-index: 0;
  background-image: repeating-linear-gradient(115deg, rgba(255,213,0,0.08) 0 2px, transparent 2px 26px);
}
/* Soft vignette — draws the eye to the medallion the way a lit plaque or
   museum placard would, kept light so the jewel-tone gradient still reads
   vivid rather than muddy. */
.mkt-no-media-placeholder::after {
  content: ''; position: absolute; inset: 0; pointer-events: none; z-index: 0;
  background: radial-gradient(circle at 50% 45%, transparent 55%, rgba(0,0,0,0.20) 100%);
}
/* Inset double-line frame — a picture-frame cue that reads as intentional
   design rather than an empty box waiting for a photo. */
.mkt-no-media-placeholder .mkt-no-media-frame {
  position: absolute; inset: 14px; z-index: 1; pointer-events: none; border-radius: 8px;
  border: 1px solid rgba(255,213,0,0.42);
  box-shadow: 0 0 0 4px rgba(255,213,0,0.07), inset 0 0 0 1px rgba(255,213,0,0.12);
}
.mkt-no-media-placeholder .mkt-no-media-medallion {
  position: relative; z-index: 2; width: 56px; height: 56px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(circle at 35% 28%, rgba(255,255,255,0.18), rgba(255,255,255,0.05) 60%);
  border: 1.5px solid rgba(255,213,0,0.88);
  box-shadow: 0 0 0 3px rgba(255,213,0,0.16), 0 0 0 8px rgba(255,213,0,0.09),
              inset 0 1px 2px rgba(255,255,255,0.22), inset 0 -4px 8px rgba(0,0,0,0.24);
}
.mkt-no-media-medallion i { color: var(--color-gold, #FFD500); font-size: 1.55rem; filter: drop-shadow(0 0 6px rgba(255,213,0,0.45)) drop-shadow(0 1px 1px rgba(0,0,0,0.35)); }
/* Short divider rule between the medallion and label — a small formal
   flourish, like the rule under a letterhead. */
.mkt-no-media-placeholder .mkt-no-media-rule {
  position: relative; z-index: 2; width: 34px; height: 1.5px; margin: 14px 0 10px;
  background: linear-gradient(90deg, transparent, rgba(255,213,0,0.85), transparent);
}
.mkt-no-media-placeholder .mkt-no-media-label {
  position: relative; z-index: 2; text-align: center;
  font-family: var(--font-ui); font-size: 0.7rem; font-weight: 700; letter-spacing: 0.16em;
  text-transform: uppercase; color: #FFE28A;
}
/* ── Job & Service listing variant — premium classic emerald + antique
   gold, so a Job/Job Seeking/Professional Services/Repair listing (which
   was never going to have a "product photo") reads as its own kind of
   listing rather than a photo the seller forgot to upload. Built by
   app-marketplace.js's _mktNoMediaPlaceholderHTML(). ── */
.mkt-no-media-placeholder.mkt-no-media-service {
  background: radial-gradient(circle at 30% 18%, rgba(212,175,55,0.32), transparent 60%),
              linear-gradient(135deg, #0B251A 0%, #1B5438 48%, #2A8555 100%);
}
.mkt-no-media-placeholder.mkt-no-media-service .mkt-no-media-frame {
  border-color: rgba(212,175,55,0.45);
  box-shadow: 0 0 0 4px rgba(212,175,55,0.08), inset 0 0 0 1px rgba(212,175,55,0.13);
}
.mkt-no-media-placeholder.mkt-no-media-service .mkt-no-media-medallion {
  background: radial-gradient(circle at 35% 28%, rgba(255,255,255,0.16), rgba(255,255,255,0.04) 60%);
  border-color: rgba(212,175,55,0.92);
  box-shadow: 0 0 0 3px rgba(212,175,55,0.14), 0 0 0 8px rgba(212,175,55,0.09),
              inset 0 1px 2px rgba(255,255,255,0.18), inset 0 -4px 8px rgba(0,0,0,0.28);
}
.mkt-no-media-placeholder.mkt-no-media-service .mkt-no-media-medallion i { color: #E8C458; filter: drop-shadow(0 0 6px rgba(212,175,55,0.5)) drop-shadow(0 1px 1px rgba(0,0,0,0.4)); }
.mkt-no-media-placeholder.mkt-no-media-service .mkt-no-media-rule { background: linear-gradient(90deg, transparent, rgba(212,175,55,0.9), transparent); }
.mkt-no-media-placeholder.mkt-no-media-service .mkt-no-media-label { color: #F0D584; }
/* ── Premium "Avatar" card — Job Seeking & Professional Services ──────────
   Full-width shelf card (see app-marketplace.js's _mktIsAvatarCategory /
   _mktAvatarScrollHTML / _mktAvatarInfoHTML, wired in via app-fixes.js).
   Horizontal-scrolling avatar/portfolio strip on the left, qualifications
   panel on the right — the emerald + antique-gold "premium classic"
   colorway already used for the Job/Service no-media placeholder, carried
   through here so the two read as one consistent design language. Reuses
   .property-seller-info / .property-actions / .direct-trade-warning
   unchanged, so ownership, contact, promote/edit/delete, and sort/search
   all keep working exactly as they do for every other listing. */
/* ── People/Services Card — Vibrant premium card for Job Seeker, Professional Service, Job Vacancy ── */
.property-card.mkt-avatar-card {
  grid-column: 1 / -1;
  /* Vibrant emerald-teal with premium gold accents — professional, sophisticated, distinct from product cards */
  background: linear-gradient(135deg, #118B6B 0%, #1AA588 35%, #27C9A0 65%, #1BA888 100%) !important;
  box-shadow: 0 6px 26px rgba(26, 155, 124, 0.22), 0 2px 6px rgba(0,0,0,0.18) !important;
  border: 1.2px solid rgba(255, 255, 255, 0.2) !important;
  border-radius: 14px !important;
}
.property-card.mkt-avatar-card::after { display: none; }
.mkt-avatar-top { display: flex; flex-direction: row; }
.mkt-avatar-top .mkt-avatar-info { flex: 1; }
.mkt-avatar-top .mkt-card-media-wrap { flex: 0 0 112px; }
@media (max-width: 720px) {
  .mkt-avatar-top { flex-direction: column !important; }
  .mkt-avatar-top .mkt-card-media-wrap { flex: 0 0 auto; width: 100%; }
}

/* ── Marketplace Adjustments #2 (2026-08-09): "slightly increase the
   length of the avatar frame card in the marketplace" — the seller's
   photo frame on the Job Seeking / Professional Service / Job Vacancy
   avatar card, main grid ONLY. Scoped to #property-grid-container so the
   homepage dashboard strip/carousel version (#dashboard-market-slider /
   .mkt-avatar-carousel-inner, styled separately further down this file)
   is untouched, per the explicit "do not modify the dashboard homepage
   card" instruction. */
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-top .mkt-card-media-wrap {
  flex-basis: 132px;
}
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-top .mkt-card-media-wrap img,
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-top .mkt-card-media-wrap video {
  min-height: 132px;
}

/* ── Marketplace Adjustments #4 (2026-08-09): reduce/compact the Job
   Service + Professional Service (avatar) cards in the main marketplace
   grid only — tighter padding/type scale so the card reads denser,
   without touching the dashboard homepage strip/carousel version (same
   scoping rationale as #2 directly above). */
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-info {
  padding: 6px 10px 5px !important;
}
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-info h4 {
  font-size: 0.92rem !important; margin: 2px 0 !important;
}
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-info p {
  font-size: 0.72rem !important; margin: 1px 0 !important;
}
#property-grid-container .property-card.mkt-avatar-card .property-actions {
  padding: 6px 10px 9px !important; gap: 5px !important;
}

/* Horizontally scrollable avatar strip — compact, refined with elegant spacing */
.mkt-avatar-scroll {
  display: flex; gap: 8px; overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch;
  padding: 8px 10px; flex: 0 0 112px; align-content: flex-start;
  scrollbar-width: none; -ms-overflow-style: none;
}
@media (max-width: 720px) { .mkt-avatar-scroll { flex: 0 0 auto; width: 100%; } }
.mkt-avatar-scroll::-webkit-scrollbar { display: none; }

/* Compact, elegant circular thumbnail frames — smaller avatar display */
.mkt-avatar-scroll-item {
  flex: 0 0 44px; height: 44px; border-radius: 10px; overflow: hidden;
  scroll-snap-align: start; position: relative;
  border: 2px solid rgba(255, 215, 0, 0.55);
  box-shadow: 0 0 0 2px rgba(255, 215, 0, 0.12), 0 2px 6px rgba(26, 155, 124, 0.28);
  transition: transform 0.2s, box-shadow 0.2s, border-color 0.2s;
}
.mkt-avatar-scroll-item:active { transform: scale(0.94); }
.mkt-avatar-scroll-item:hover { border-color: #FFD700; box-shadow: 0 0 0 3px rgba(255, 215, 0, 0.25), 0 3px 10px rgba(26, 155, 124, 0.32); }
/* Primary avatar frame — slightly larger, vibrant gold accent ring */
.mkt-avatar-scroll-item.mkt-avatar-main {
  flex-basis: 54px;
  height: 54px;
  border-color: #FFD700;
  box-shadow: 0 0 0 3px rgba(255, 215, 0, 0.3), 0 3px 12px rgba(26, 155, 124, 0.36);
}
.mkt-avatar-scroll-item img, .mkt-avatar-scroll-item video {
  width: 100% !important; height: 100% !important; object-fit: cover !important; display: block !important;
}
/* No-avatar lettered medallion — elegant emerald theme */
.mkt-avatar-scroll-item.mkt-avatar-initials {
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(circle at 38% 30%, rgba(212, 175, 55, 0.18), rgba(20, 125, 99, 0.1) 60%);
}
.mkt-avatar-scroll-item.mkt-avatar-initials span {
  font-family: var(--font-ui); font-size: 1.1rem; font-weight: 800; color: #D4AF37;
  filter: drop-shadow(0 0 5px rgba(212, 175, 55, 0.5));
}

/* Info panel — centered, elegant, tightened vertical rhythm for a more
   compact card while keeping every element legible. */
/* FIX (request — "the position element has not been adjusted or moved to
   the center"): all info panel elements — badge, title, chips, desc, price
   — are centered. The h4 (job title / position / service offering) is now
   wrapped in a horizontally scrollable strip (.mkt-avatar-title-scroll) so
   that even a long title never clips or wraps awkwardly; the user can swipe
   it left/right. */
.mkt-avatar-info { padding: 8px 12px 6px !important; display: flex; flex-direction: column; align-items: center !important; text-align: center !important; min-width: 0; gap: 0; }
.mkt-avatar-info .mkt-avatar-role-badge {
  align-self: center !important;
  background: rgba(255, 215, 0, 0.25) !important;
  color: #FFEB3B !important;
  border: 1.5px solid rgba(255, 215, 0, 0.45) !important;
  font-size: 0.72rem !important;
  padding: 4px 11px !important;
  border-radius: 9px !important;
  font-weight: 700 !important;
}

/* Horizontally scrollable position/title strip */
.mkt-avatar-title-scroll {
  width: 100%;
  overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch;
  scrollbar-width: none; -ms-overflow-style: none;
  display: flex; justify-content: center;
  margin: 6px 0 4px;
}
.mkt-avatar-title-scroll::-webkit-scrollbar { display: none; }
.mkt-avatar-title-scroll h4 {
  white-space: nowrap;
  flex-shrink: 0;
}
.mkt-avatar-info h4 {
  font-family: var(--font-ui) !important;
  font-size: 0.98rem !important;
  font-weight: 800 !important;
  color: #fff !important;
  margin: 0 !important;
  line-height: 1.25 !important;
  white-space: nowrap;
}
.mkt-avatar-quals { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 6px; justify-content: center; }
.mkt-avatar-quals .mkt-qual-chip {
  font-size: 0.68rem; font-weight: 700; color: #0B3D2C;
  background: linear-gradient(135deg, #FFD700, #FFF44F);
  padding: 3px 10px; border-radius: 9px;
  display: inline-flex; align-items: center; gap: 3px;
  box-shadow: 0 2px 6px rgba(255, 215, 0, 0.18);
}
.mkt-avatar-desc {
  font-size: 0.78rem !important; color: rgba(255,255,255,0.90) !important; margin-bottom: 6px !important; line-height: 1.3;
  /* Clamp to 2 lines so a long description can't push the card's height up —
     keeps the compact silhouette regardless of listing content length. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.mkt-avatar-info p { color: rgba(255,255,255,0.85) !important; font-size: 0.78rem !important; margin: 2px 0 !important; font-weight: 500; }
.mkt-avatar-price { font-size: 1.1rem !important; font-weight: 900 !important; color: #FFEB3B !important; margin-top: 6px !important; font-family: var(--font-ui) !important; text-shadow: 0 2px 6px rgba(0,0,0,0.3); }
.property-card.mkt-avatar-card .property-seller-info { background: rgba(0,0,0,0.25) !important; border-top-color: rgba(255, 215, 0, 0.2) !important; color: rgba(255,255,255,0.88) !important; padding: 6px 14px !important; font-size: 0.74rem !important; }
.property-card.mkt-avatar-card .property-seller-info strong { color: #FFEB3B; font-weight: 700; }
/* Compact action-button row for the marketplace-grid avatar card only —
   the dashboard/home strip version renders its own inline padding in JS
   and is untouched by this rule. */
.property-card.mkt-avatar-card .property-actions { padding: 8px 14px 12px !important; gap: 6px !important; }

/* ── Marketplace Adjustments #7 (2026-08-09 — "should be premium white, I
   didn't ask for colour redesign, it was card redesign I asked for, please
   reduce the size of the card"): Adjustments #6 above had swapped this
   card's background to a deep-navy/gold "midnight boutique" colourway when
   only a SIZE reduction was actually asked for. Replaced here with a
   premium white/ivory ground instead — same restrained gold-hairline,
   gold-ribbon, gold-accent language (still reads as boutique/premium,
   still matches the brand's navy+gold identity via navy text-on-white
   instead of gold text-on-navy), plus a further round of size trimming on
   top of Adjustments #2/#4 (smaller avatar frame, smaller avatar-strip
   thumbnails, tighter type scale and padding throughout).
   SCOPING: every rule below is scoped to #property-grid-container, the
   same convention Adjustments #2/#4/#6 all use, so the homepage dashboard
   slider/strip (#dashboard-market-slider / #dashboard-market-container,
   styled separately above with its own vibrant teal gradient) is
   completely unaffected — per the explicit "don't touch the marketplace
   card in the home page" instruction. This block supersedes (not just
   overrides) Adjustments #6's colours; nothing from that block is still
   in effect once this one loads after it in the cascade. */
#property-grid-container .property-card.mkt-avatar-card {
  background:
    radial-gradient(circle at 18% 10%, rgba(212, 175, 55, 0.08), transparent 55%),
    linear-gradient(135deg, #FFFFFF 0%, #FDFCF8 55%, #F6F2E7 100%) !important;
  border: 1px solid rgba(212, 175, 55, 0.38) !important;
  box-shadow: 0 1px 2px rgba(10, 14, 39, 0.05), 0 10px 22px rgba(10, 14, 39, 0.10) !important;
  position: relative;
  transition: box-shadow 0.22s ease, transform 0.22s ease;
  border-radius: 12px !important;
}
#property-grid-container .property-card.mkt-avatar-card::before {
  content: '';
  position: absolute; top: 0; left: 0; right: 0; height: 2.5px;
  background: linear-gradient(90deg, transparent, #D4AF37 18%, #E8C766 50%, #D4AF37 82%, transparent);
  opacity: 0.9; pointer-events: none; z-index: 1; border-radius: 12px 12px 0 0;
}
#property-grid-container .property-card.mkt-avatar-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 2px 4px rgba(10, 14, 39, 0.06), 0 14px 28px rgba(10, 14, 39, 0.14) !important;
}
/* Further size reduction — media frame, avatar strip thumbnails, type
   scale and padding, all trimmed a step past Adjustments #2/#4. */
/* FIX (request — "increase the avatar thumbnail card a little"): nudged
   back up a step from Adjustments #7's trim above — 100px/36px/44px ->
   116px/42px/50px. Still scoped to #property-grid-container only, so the
   homepage dashboard slider is untouched, same as every adjustment round
   before this one. */
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-top .mkt-card-media-wrap {
  flex-basis: 116px;
}
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-top .mkt-card-media-wrap img,
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-top .mkt-card-media-wrap video {
  min-height: 116px;
}
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-scroll {
  flex-basis: 116px !important;
  padding: 6px 8px !important;
  gap: 6px !important;
}
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-scroll-item {
  flex-basis: 42px !important; height: 42px !important; border-radius: 8px !important;
}
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-scroll-item.mkt-avatar-main {
  flex-basis: 50px !important; height: 50px !important;
}
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-info {
  padding: 5px 9px 4px !important;
}
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-info h4 {
  font-size: 0.86rem !important; margin: 1px 0 !important;
}
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-desc,
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-info p {
  font-size: 0.7rem !important; margin: 1px 0 !important;
}
#property-grid-container .property-card.mkt-avatar-card .property-actions {
  padding: 5px 9px 8px !important; gap: 5px !important;
}
/* Colour language — navy-on-white instead of Adjustments #6's gold-on-navy */
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-scroll-item {
  border-color: rgba(212, 175, 55, 0.55) !important;
  box-shadow: 0 0 0 2px rgba(212, 175, 55, 0.10), 0 2px 6px rgba(10, 14, 39, 0.12) !important;
}
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-scroll-item.mkt-avatar-main {
  border-color: #D4AF37 !important;
  box-shadow: 0 0 0 3px rgba(212, 175, 55, 0.20), 0 3px 10px rgba(10, 14, 39, 0.16) !important;
}
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-scroll-item.mkt-avatar-initials {
  background: radial-gradient(circle at 38% 30%, rgba(212, 175, 55, 0.20), rgba(246, 242, 231, 0.9) 60%) !important;
}
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-scroll-item.mkt-avatar-initials span {
  color: #A8841F !important;
  filter: none;
}
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-info .mkt-avatar-role-badge {
  background: linear-gradient(135deg, #D4AF37, #F0D584) !important;
  color: #0A0E27 !important;
  border: none !important;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5), 0 2px 6px rgba(212, 175, 55, 0.22) !important;
  letter-spacing: 0.05em !important;
}
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-info h4 {
  color: #0F1B4C !important;
  font-family: Georgia, 'Times New Roman', serif !important;
  font-weight: 700 !important;
  letter-spacing: 0.01em !important;
}
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-quals .mkt-qual-chip {
  background: rgba(212, 175, 55, 0.12) !important;
  color: #8A6D1F !important;
  border: 1px solid rgba(212, 175, 55, 0.4) !important;
  box-shadow: none !important;
}
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-desc,
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-info p {
  color: rgba(30, 35, 60, 0.72) !important;
}
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-price {
  color: #A8841F !important;
  text-shadow: none !important;
  border-top: 1px dashed rgba(212, 175, 55, 0.4);
  padding-top: 5px !important;
}
#property-grid-container .property-card.mkt-avatar-card .property-seller-info {
  background: rgba(10, 14, 39, 0.03) !important;
  border-top-color: rgba(212, 175, 55, 0.28) !important;
  color: rgba(30, 35, 60, 0.72) !important;
}
#property-grid-container .property-card.mkt-avatar-card .property-seller-info strong {
  color: #8A6D1F !important;
}
#property-grid-container .property-card.mkt-avatar-card .mkt-doc-chip-pdf {
  background: rgba(220, 38, 38, 0.09) !important; color: #B91C1C !important; border: 1px solid rgba(220, 38, 38, 0.28) !important;
}
#property-grid-container .property-card.mkt-avatar-card .mkt-doc-chip-doc {
  background: rgba(37, 99, 235, 0.09) !important; color: #1D4ED8 !important; border: 1px solid rgba(37, 99, 235, 0.28) !important;
}


/* ── Compact "ID Card" header (request — "redesign the card thumbnail...
   use the mockup to improve the card") ───────────────────────────────────
   Shared by the Job Seeker / Professional Service / Job Vacancy grid
   thumbnail (window._mktAvatarIdCardHTML, app-marketplace.js) and the
   Listing Details page (app-marketplace-sellers.js) — a single premium
   navy/gold ID-card row: a circular photo medallion beside the category
   kicker, name, role/position and price. Replaces the old
   .mkt-avatar-top strip+panel on the grid card, and the old full-width
   photo hero (which rendered as an empty navy block when a listing had
   no photos) on the Listing Details page. Not scoped to
   #property-grid-container since the Listing Details page needs it too. */
.mkt-idcard { margin: 10px; border-radius: 16px; padding: 2px; background: linear-gradient(155deg, #BFA000, #FFE666 40%, #BFA000); }
.mkt-idcard-inner { position: relative; border-radius: 14px; padding: 14px 16px 12px; background: radial-gradient(140% 90% at 50% -10%, rgba(255,213,0,0.10) 0%, rgba(255,213,0,0) 45%), linear-gradient(165deg, #1B2B8B 0%, #0A0E27 80%); display: flex; align-items: center; gap: 12px; overflow: hidden; }
.mkt-idcard-inner::before { content: ""; position: absolute; inset: 0; background-image: repeating-linear-gradient(135deg, rgba(255,255,255,0.025) 0px, rgba(255,255,255,0.025) 1px, transparent 1px, transparent 10px); pointer-events: none; }
.mkt-idcard-verified { position: absolute; top: 9px; right: 11px; color: #FFE666; font-size: 11px; }
.mkt-idcard-medallion { width: 56px; height: 56px; border-radius: 50%; flex-shrink: 0; padding: 2.5px; background: linear-gradient(155deg, #FFE666, #BFA000); }
.mkt-idcard-medallion-inner { width: 100%; height: 100%; border-radius: 50%; background: #0D1540 center/cover no-repeat; display: flex; align-items: center; justify-content: center; overflow: hidden; border: 2px solid #0D1540; }
.mkt-idcard-medallion-inner img { width: 100%; height: 100%; object-fit: cover; display: block; }
.mkt-idcard-medallion-inner span { font-family: Georgia, 'Times New Roman', serif; font-weight: 700; font-size: 18px; color: #FFE666; }
.mkt-idcard-text { flex: 1; min-width: 0; }
.mkt-idcard-kicker { font-size: 9px; letter-spacing: 0.10em; text-transform: uppercase; color: rgba(255,230,102,0.7); font-weight: 700; margin: 0 0 3px; }
.mkt-idcard-name { font-weight: 700; font-size: 15px; color: #fff; margin: 0 0 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mkt-idcard-role { font-size: 11px; color: #FFE666; font-weight: 700; margin: 0 0 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mkt-idcard-price { font-size: 13px; font-weight: 800; color: #fff; margin: 0; }

/* Grid-card body — qualifications chips, description, location, attached
   documents — sits below the ID card on the marketplace grid thumbnail.
   Name/role/price no longer repeat here (they're in the ID card above),
   so this is a plain light panel rather than the old dark centered block. */
.mkt-avatar-body { padding: 2px 12px 4px; }
.mkt-avatar-body .mkt-avatar-quals { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 6px; }
.mkt-avatar-body .mkt-qual-chip { font-size: 0.7rem; font-weight: 700; color: #8A6D1F; background: rgba(212,175,55,0.12); border: 1px solid rgba(212,175,55,0.35); padding: 3px 9px; border-radius: 9px; display: inline-flex; align-items: center; gap: 3px; }
.mkt-avatar-body .mkt-avatar-desc { font-size: 0.78rem; color: rgba(30,35,60,0.75); margin: 0 0 6px; line-height: 1.35; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.mkt-avatar-body p { font-size: 0.76rem; color: rgba(30,35,60,0.6); margin: 2px 0; }
.mkt-avatar-body p i { color: var(--secondary); }

/* ── Uploaded-document chips (PDF / DOC / Image) ─────────────────────────
   FIX (request — "uploaded files should display according to their
   type"): used by window._mktDocumentsHTML (app-marketplace.js) for
   posted listings, and by app-fixes.js's own selection-time preview
   (#mkt-doc-preview) on the Sell form — same visual language in both
   places so what a seller sees while attaching files matches what a
   buyer later sees on the card. */
.mkt-doc-list { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0; justify-content: center; }
.mkt-doc-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: 10px;
  font-size: 0.76rem; font-weight: 700;
  text-decoration: none; white-space: nowrap;
  transition: background 0.2s, color 0.2s;
}
.mkt-doc-chip-pdf { background: rgba(239,68,68,0.16); color: #FF6B6B; }
.mkt-doc-chip-doc { background: rgba(37,99,235,0.16); color: #3B9FFF; }
.mkt-avatar-card .mkt-doc-chip-pdf { background: rgba(255,107,107,0.28); color: #FFD4D4; border: 1.2px solid rgba(255,107,107,0.45); }
.mkt-avatar-card .mkt-doc-chip-doc { background: rgba(100,180,255,0.28); color: #D4E8FF; border: 1.2px solid rgba(100,180,255,0.45); }
.mkt-doc-chip-img { padding: 0; width: 44px; height: 44px; border-radius: 8px; overflow: hidden; border: 1.5px solid rgba(212,175,55,0.55); box-shadow: 0 2px 6px rgba(0,0,0,0.2); transition: transform 0.2s, box-shadow 0.2s; }
.mkt-doc-chip-img:hover { transform: scale(1.05); box-shadow: 0 3px 10px rgba(0,0,0,0.3); }
.mkt-doc-chip-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Selection-time preview chips on the Sell form (plain File objects, not
   yet uploaded) — same shapes, on the form's light background. */
#mkt-doc-preview { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
#mkt-doc-preview .mkt-doc-chip-pdf { background: rgba(239,68,68,0.10); color: #DC2626; }
#mkt-doc-preview .mkt-doc-chip-doc { background: rgba(37,99,235,0.10); color: #1D4ED8; }

/* Listing Detail page's own "Attached Files" section (request — full
   details opened from a card should also give access to download the
   attached files). Reuses .mkt-doc-list/.mkt-doc-chip* above for the
   chips themselves — this just wraps/labels them on this page. */
.mkt-listing-detail-docs { margin: 14px 0; text-align: center; }
.mkt-listing-detail-docs-h {
  font-size: 0.8rem; font-weight: 700; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: 0.03em; margin: 0 0 8px;
}

/* FIX (request — "implement exactly the screenshot featuring the 4
   downloadable folder indicating PDF for PDF upload"): "Credentials &
   Files" section on the Listing Detail page for Job Seeker /
   Professional Service / Job Vacancy listings. Reuses .mkt-dash-av-tiles
   (the always-4 folder-tile grid already built for the dashboard-strip
   card, app-marketplace.js) as-is — this block just gives it its own
   labeled section + a little breathing room so a 4-column tile grid
   sized for a ~480px dashboard card also reads cleanly on a full-width
   detail page. */
.mkt-listing-detail-credentials { margin: 18px 0; }
.mkt-listing-detail-tiles { margin-top: 0; max-width: 420px; margin-left: auto; margin-right: auto; }
.mkt-listing-detail-tiles .mkt-dash-av-tile { font-size: 0.78rem; }
.mkt-listing-detail-tiles .mkt-dash-av-tile i { width: 38px; height: 38px; font-size: 1.15rem; }


.property-info { padding: 18px 18px 10px !important; flex: 1; display: flex; flex-direction: column; }
.property-info h4 { font-family: var(--font-ui) !important; font-size: var(--text-2xl) !important; font-weight: var(--weight-bold) !important; color: var(--primary) !important; margin-bottom: 6px !important; line-height: var(--leading-snug) !important; flex-grow: 1; }
.property-info p { font-size: var(--text-sm) !important; color: var(--text-muted) !important; margin-bottom: 15px; }
.property-info > div:last-child { font-size: var(--text-xl) !important; font-weight: var(--weight-extrabold) !important; color: var(--secondary) !important; margin-top: auto !important; font-family: var(--font-ui) !important; }

/* ── Marketplace Layout Upgrade (request): only two lines of text
   (title + location, via .property-info above) now render directly
   under each listing's media. Everything else — brand+price,
   condition/specs+features+date, contact — is spread across three
   horizontally-scrollable rows below that. Nothing is removed, only
   rearranged: a row simply scrolls sideways instead of wrapping/
   clipping vertically, so no Expand/Collapse toggle is needed anymore.
   Scoped to .property-card only — avatar (Job Seeking/Services/Jobs)
   cards use their own separate .mkt-avatar-info layout, untouched. */
.property-card .mkt-scroll-row {
  display: flex; flex-wrap: nowrap; align-items: center; gap: 8px;
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  padding: 0 12px 10px; scrollbar-width: none; -ms-overflow-style: none;
}
.property-card .mkt-scroll-row::-webkit-scrollbar { display: none; }
.property-card .mkt-row-chip {
  flex-shrink: 0; white-space: nowrap; font-size: var(--text-xs);
  color: var(--color-neutral-600); background: rgba(var(--color-navy-rgb),0.05);
  padding: 4px 10px; border-radius: 8px;
}
.property-card .mkt-row-chip-brand { font-weight: 700; color: var(--secondary); }
.property-card .mkt-row-chip-features strong { color: var(--secondary); }
.property-card .mkt-row-chip-date { background: none; padding: 4px 2px; color: var(--text-muted); }
/* Row 1's price — replaces the old .property-info > div:last-child
   styling above (that rule is now dead for standard cards since price
   moved out of .property-info; left in place since avatar-card markup
   is untouched and unaffected either way). .mkt-price-display is a
   STABLE class, not a positional selector, so the currency-conversion
   and edit-listing JS (app-fixes.js/app-marketplace.js) can find this
   element wherever it lives. */
.property-card .mkt-price-display {
  flex-shrink: 0; font-size: var(--text-xl) !important; font-weight: var(--weight-extrabold) !important;
  color: var(--danger-color) !important; font-family: var(--font-ui) !important; white-space: nowrap;
}
/* ── FIX (request — "texts after the product listing display is still
   much... hide them under a Chevron expansion/collapse, only the
   contact information should be visible for now"): Row 1 + Row 2 now
   render inside .mkt-details-collapse, collapsed to 0 height by
   default. Tapping .mkt-details-toggle-btn (JS in app-marketplace.js)
   toggles .mkt-details-open on both. Row 3 (.property-actions) is
   outside this container, so Contact Seller/WhatsApp/owner actions
   stay visible regardless of collapsed state. */
.property-card .mkt-details-toggle-btn {
  display: flex; align-items: center; gap: 6px; width: 100%; text-align: left;
  background: none; border: none; padding: 8px 12px; margin: 0;
  font-size: var(--text-xs); font-weight: 700; color: var(--secondary, #1B2B8B);
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.property-card .mkt-details-toggle-btn i { font-size: 0.7em; transition: transform 0.2s ease; }
.property-card .mkt-details-toggle-btn.mkt-details-open i { transform: rotate(180deg); }
.property-card .mkt-details-collapse { max-height: 0; overflow: hidden; transition: max-height 0.25s ease; }
.property-card .mkt-details-collapse.mkt-details-open { max-height: 600px; }
/* Row 3 — the existing .property-actions row (Contact Seller +
   WhatsApp, added by app-fixes.js/app-patch-v2.js) now scrolls
   horizontally too, matching Rows 1 and 2, instead of wrapping. Owner-
   only Promote/Edit/Delete buttons share this same row when present. */
.property-actions {
  overflow-x: auto !important; flex-wrap: nowrap !important;
  -webkit-overflow-scrolling: touch; scrollbar-width: none; -ms-overflow-style: none;
}
.property-actions::-webkit-scrollbar { display: none; }
.property-actions > * { flex-shrink: 0; }

.property-seller-info { padding: 10px 18px !important; background: rgba(10,14,39,0.02) !important; border-top: 1px solid var(--border) !important; font-size: 0.78rem !important; color: var(--text-muted) !important; display: flex; align-items: center; justify-content: space-between; }
/* ── Marketplace Adjustments #5 (2026-08-09): hide the poster's @name on
   listing cards in the main marketplace grid — buyers now have to open the
   seller's profile to see who's selling. Scoped to the grid only, so the
   seller's OWN profile page (where their name is meant to be visible to
   them per #7) and the homepage dashboard strip (which never showed a
   seller name to begin with) are both untouched. */
#property-grid-container .property-card .property-seller-info strong { display: none !important; }
.property-actions { padding: 12px 16px 16px !important; display: flex !important; gap: 8px !important; }
.property-description { margin-bottom: 15px; font-size: var(--text-lg); line-height: var(--leading-relaxed); color: var(--color-neutral-600); }
.verified-badge-small { font-size: var(--text-sm); color: var(--success-color); margin-left: 5px; }
.unverified-badge-small { font-size: var(--text-sm); color: var(--danger-color); margin-left: 5px; }
.star-rating { color: var(--accent-color); }
.direct-trade-warning { display: none; padding: 0 20px 15px 20px; }
.direct-contact-info { display: block !important; padding: 0; max-height: 0; overflow: hidden; transition: max-height 0.35s ease, padding 0.3s ease; }
.direct-contact-info.open { display: block !important; max-height: 500px !important; padding: 14px 16px !important; }
.direct-trade-warning { background: var(--color-surface-warm); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); padding-top: 15px; font-size: var(--text-md); }
.direct-trade-warning strong { color: var(--color-warning-dark); }
.direct-contact-info p { margin-bottom: 5px; font-size: var(--text-md); }
.contact-seller-btn { width: 100%; }
.promote-item-btn { margin-top: 10px; width: 100%; background-color: var(--accent-color); color: var(--text-primary); }
.dispute-section { border: 1px solid var(--danger-color); padding: 15px; border-radius: var(--radius-sm); margin-top: 20px; background: var(--color-surface-red2); }
.inspection-report { margin-top: 15px; }
.inspection-report label { font-weight: var(--weight-bold); }
/* FIX: this block used to stay display:none until a photo was uploaded,
   which — combined with the category picker added above it — made the
   posting form feel like three disconnected steps (category, then upload,
   then a surprise reveal of the rest). Now shown from the start as one
   continuous form; see app-fixes.js's #item-media change handler and the
   remove-media-btn handler, which no longer force this back to none. */
#marketplace-media-preview { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 15px; }
.media-thumbnail { position: relative; width: 100px; height: 100px; }
.media-thumbnail img, .media-thumbnail video { width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius-md); }
.remove-media-btn { position: absolute; top: -5px; right: -5px; background: var(--danger-color); color: var(--color-white); border-radius: var(--radius-full); width: 22px; height: 22px; border: none; font-size: var(--text-sm); cursor: pointer; display: flex; align-items: center; justify-content: center; z-index: 1; }

/* ── Marketplace upload preview — premium grid (mkt-preview-*) ──
   Used by handleMarketplacePreview() in app-fixes.js. Scoped to its
   own classes so it doesn't touch the legacy .media-thumbnail rules
   above, which other code paths may still rely on. */
.mkt-preview-grid { background: rgba(0,0,0,0.02); padding: 4px; }
.mkt-preview-cell {
    position: relative;
    overflow: hidden;
    border-radius: 10px;
    background: #eef0f3;
    cursor: pointer;
    box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 0 0 1px rgba(0,0,0,0.04);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.mkt-preview-cell:active { transform: scale(0.97); }
.mkt-preview-media { width: 100%; height: 100%; object-fit: cover; display: block; }
.mkt-preview-playicon {
    position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
    width: 40px; height: 40px; border-radius: 50%;
    background: rgba(0,0,0,0.45); color: #fff;
    display: flex; align-items: center; justify-content: center;
    font-size: 0.85rem; pointer-events: none;
}
.mkt-preview-zoomhint {
    position: absolute; bottom: 6px; right: 6px;
    width: 26px; height: 26px; border-radius: 50%;
    background: rgba(0,0,0,0.45); color: #fff;
    display: flex; align-items: center; justify-content: center;
    font-size: 0.7rem; opacity: 0; transition: opacity 0.15s ease;
    pointer-events: none;
}
.mkt-preview-cell:hover .mkt-preview-zoomhint { opacity: 1; }
.mkt-preview-overflow {
    position: absolute; inset: 0;
    background: rgba(0,0,0,0.55); color: #fff;
    font-size: 1.4rem; font-weight: 800;
    display: flex; align-items: center; justify-content: center;
    pointer-events: none;
}
.mkt-preview-cell .remove-media-btn {
    top: 6px; right: 6px;
    box-shadow: 0 2px 6px rgba(0,0,0,0.3);
    z-index: 2;
}
@media (hover: none) {
    /* Touch devices: always show the zoom hint since :hover never fires */
    .mkt-preview-zoomhint { opacity: 0.85; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   §9  NEWS LIST CARDS
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Dashboard Market Slider: Horizontal Scrollable Avatar Cards ── */
#dashboard-market-container {
  position: relative;
  overflow: hidden;
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  padding: 0 !important;
}

#dashboard-market-slider.horizontal-slider-wrapper {
  display: flex !important;
  gap: 16px !important;
  overflow-x: auto !important;
  overflow-y: hidden !important;
  padding: 20px 40px !important;
  scroll-snap-type: x proximity !important;
  -webkit-overflow-scrolling: touch !important;
  scrollbar-width: none !important;
  -ms-overflow-style: none !important;
  justify-content: flex-start !important;
  user-select: auto !important;
  /* Both card variants now carry their own explicit, shared height (see
     ".dashboard-market-card.mkt-dash-avatar-card, .dashboard-market-card
     :not(.mkt-dash-avatar-card) { height: 500px }" below) so every card
     in this strip is the same size regardless of content — flex-start
     (rather than the default stretch) keeps this row from fighting that
     explicit height by trying to stretch a card to match a sibling's. */
  align-items: flex-start !important;
}
#dashboard-market-slider::-webkit-scrollbar { display: none !important; }
#dashboard-market-slider > * {
  scroll-snap-align: center !important;
  /* FIX (request — "reduce card width to be 300px"): 330 -> 240 -> 300px. */
  flex: 0 0 300px !important;
  min-width: 300px !important;
}

/* Dashboard market card: compact, vibrant, centered */
#dashboard-market-slider .property-card.mkt-avatar-card {
  grid-column: auto !important;
  max-width: 330px;
  height: 520px;
  background: linear-gradient(135deg, #1A9B7C 0%, #2DB399 35%, #35C7B0 65%, #2BA897 100%) !important;
  box-shadow: 0 16px 48px rgba(26, 155, 124, 0.35), 0 2px 8px rgba(0,0,0,0.2) !important;
  border: 1.8px solid rgba(255, 255, 255, 0.3) !important;
  border-radius: 22px !important;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}

#dashboard-market-slider .property-card.mkt-avatar-card:hover {
  transform: translateY(-8px) !important;
  box-shadow: 0 20px 60px rgba(26, 155, 124, 0.45), 0 4px 12px rgba(0,0,0,0.25) !important;
}

/* Brighter, more vibrant avatar cards */
#dashboard-market-container .property-card.mkt-avatar-card {
  background: linear-gradient(135deg, #1A9B7C 0%, #2DB399 35%, #35C7B0 65%, #2BA897 100%) !important;
  box-shadow: 0 16px 48px rgba(26, 155, 124, 0.35), 0 2px 8px rgba(0,0,0,0.2) !important;
  border-color: rgba(255, 255, 255, 0.3) !important;
}

/* Dashboard market card info styling */
#dashboard-market-slider .mkt-avatar-top {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

#dashboard-market-slider .mkt-avatar-scroll {
  flex: 0 0 140px;
  padding: 12px;
}

#dashboard-market-slider .mkt-avatar-info {
  flex: 1;
  overflow-y: auto;
  padding: 14px !important;
}

#news .card { padding: 0; }
.news-list { display: flex; flex-direction: column; }
.news-list-item {
  background: var(--color-white) !important;
  border-radius: var(--radius-2xl) !important;
  border: 1px solid var(--border) !important;
  box-shadow: var(--shadow-xs) !important;
  margin-bottom: 14px !important; overflow: hidden !important;
  transition: var(--transition-slow) !important;
  display: flex; flex-direction: column;
  padding: 20px; border-bottom: 1px solid var(--light-gray);
}
.news-list-item:hover { box-shadow: var(--shadow-lg) !important; transform: translateY(-3px) !important; background: var(--color-surface-purple) !important; }
.news-item-content-wrapper { flex-grow: 1; min-width: 0; }
.news-item-image { width: 100%; height: 200px; flex-shrink: 0; border-radius: var(--radius-md); overflow: hidden; margin-bottom: 20px; cursor: pointer; }
.news-item-image img, .news-item-image video { width: 100%; height: 100%; object-fit: cover; }
.news-item-content h4 { font-family: var(--font-ui) !important; color: var(--primary) !important; font-weight: var(--weight-bold) !important; font-size: var(--text-2xl) !important; margin-bottom: 8px; cursor: pointer; }
.news-item-content h4::after { content: '\f078'; font-family: 'Font Awesome 6 Free'; font-weight: 900; color: var(--secondary); margin-left: 10px; font-size: var(--text-md); display: inline-block; transition: transform var(--duration-slow) var(--ease-in-out); }
.news-list-item.expanded h4::after { transform: rotate(180deg); }
.news-meta { color: var(--text-muted) !important; font-size: var(--text-sm) !important; margin-bottom: 12px; display: flex; align-items: center; gap: 8px; }
.news-item-content p { max-height: 0; overflow: hidden; margin: 0; line-height: var(--leading-relaxed); color: var(--color-neutral-700); transition: max-height 0.5s ease-out, margin-top 0.5s ease-out; }
.news-list-item.expanded .news-item-content p { max-height: 500px; margin-top: 15px; transition: max-height 0.5s ease-in, margin-top 0.5s ease-in; }
#news-media-preview { margin-top: 15px; display: grid; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: 10px; }
#news-media-preview img, #news-media-preview video { max-width: 100%; max-height: 100px; object-fit: cover; border-radius: var(--radius-md); }


/* ═══════════════════════════════════════════════════════════════════════════
   §10  DASHBOARD SLIDER CARDS
   ═══════════════════════════════════════════════════════════════════════════ */

.horizontal-slider-container { overflow: hidden; padding-bottom: 15px; }
.horizontal-slider-wrapper {
  display: flex; overflow-x: auto; gap: 12px !important;
  padding: 8px 16px 18px !important;
  scroll-snap-type: x mandatory !important;
  -webkit-overflow-scrolling: touch;
  -ms-overflow-style: none !important; scrollbar-width: none !important;
  cursor: grab !important;
}
.horizontal-slider-wrapper:active, .horizontal-slider-wrapper.is-dragging { cursor: grabbing !important; }
.horizontal-slider-wrapper::-webkit-scrollbar { display: none !important; }
.horizontal-slider-wrapper > * { scroll-snap-align: start !important; }
.horizontal-slider-wrapper.is-dragging, .horizontal-slider-wrapper.is-dragging * { user-select: none !important; -webkit-user-select: none !important; pointer-events: none !important; }
.horizontal-slider-wrapper.is-dragging { pointer-events: auto !important; }

/* News & market slider cards — premium elevated thumbnail style
   FIX (request — "reduce the width and make it look compact elegant
   premium and beautiful"): rounder 20px corners, a soft hairline
   border and a gentler two-layer shadow read as a more refined,
   boutique "premium" tile than the older flatter 16px/no-border card,
   without changing the underlying card mechanics. */
.dashboard-news-card, .dashboard-market-card {
  flex: 0 0 200px !important; width: 200px !important;
  border-radius: 20px !important; overflow: hidden !important;
  box-shadow: 0 4px 14px rgba(10,14,39,0.09), 0 1px 3px rgba(10,14,39,0.07) !important;
  background: var(--color-white) !important;
  border: 1px solid rgba(10,14,39,0.06) !important; cursor: pointer !important;
  transition: box-shadow 0.25s ease, transform 0.25s ease, border-color 0.25s ease !important;
  flex-shrink: 0; position: relative; display: inline-block;
}
.dashboard-news-card:hover, .dashboard-market-card:hover {
  box-shadow: 0 12px 32px rgba(10,14,39,0.16), 0 3px 8px rgba(10,14,39,0.09) !important;
  transform: translateY(-5px) !important;
  border-color: rgba(10,14,39,0.10) !important;
}
.dashboard-news-card img, .dashboard-market-card img,
.dashboard-news-card video, .dashboard-market-card video {
  width: 100% !important; height: 160px !important; object-fit: cover !important;
  display: block !important;
}
.dashboard-news-card-info, .dashboard-market-card-info { padding: 12px 14px 14px !important; }
.dashboard-news-card-info h5, .dashboard-market-card-info h5 {
  font-size: 0.82rem !important; font-weight: 700 !important;
  color: var(--primary) !important; white-space: normal !important;
  line-height: 1.35 !important; display: -webkit-box !important;
  -webkit-line-clamp: 2 !important; -webkit-box-orient: vertical !important;
  overflow: hidden !important; margin-bottom: 5px;
  letter-spacing: 0.1px !important;
}
.dashboard-market-card-info p {
  font-size: 0.8rem !important; font-weight: 800 !important;
  color: var(--secondary) !important; margin-top: 4px !important;
  font-family: var(--font-ui) !important;
  letter-spacing: 0.2px !important;
}

/* FIX (request — "the entire horizontal scrollable marketplace card in
   the general public dashboard should be of the same size" as the Job
   Seeker/Professional Service avatar card, then "reduce further to
   ~500px"): both card variants share one explicit height so every card
   in the "New in Marketplace" strip is the same-size box regardless of
   content. overflow-y:auto is the safety net for the rare avatar-card
   listing whose content (owner Edit/Delete footer, or a long unfolded
   Experience Summary) runs past this height — it scrolls inside the
   card instead of being clipped or forcing every other card taller.
   FIX (dev request — "reduce the card thumbnail to 480px in total...
   photo area for other products should be 360px [but] the job seeker
   card should [total] 480px too, to make the entire card uniform"):
   500 -> 544 -> 480px. The product/vehicle card variant below keeps
   its 360px photo and now splits the remaining 120px between a
   tightened text area (64px) and its Edit/Delete or WhatsApp/Call
   footer row (56px) — see both further down. This shared rule is what
   keeps the Job Seeking/Professional Service avatar-card variant at
   that exact same overall 480px box height (its own content still
   flexes/scrolls internally via overflow-y:auto above if it ever runs
   long) rather than the two drifting out of sync, so every card in
   the strip stays uniform regardless of which template it uses. */
/* FIX (request — "reduce the height to be 400px"): 480 -> 464 -> 400px
   total (276px media frame + 68px text area + 56px action-row footer).
   Kept as one shared rule so both the product/vehicle card and the Job
   Seeking/Service avatar card stay the same uniform box height. */
.dashboard-market-card.mkt-dash-avatar-card,
.dashboard-market-card:not(.mkt-dash-avatar-card) {
  height: 400px !important;
  overflow-y: auto !important;
}
.dashboard-market-card:not(.mkt-dash-avatar-card) {
  display: flex !important;
  flex-direction: column !important;
  /* FIX (dev request — "marketplace horizontal scrollable card on the
     general public dashboard": bottom text region + action row were
     unusable): this card variant's Edit/Delete owner toolbar
     (.vf-owner-toolbar, appended by app-fix-final.js's _ensureToolbar,
     which runs against EVERY .property-card including this one) and
     its buyer-facing WhatsApp/Call quick-contact icons
     (.mkt-dash-quickcontact, appended by app-marketplace.js's
     _mktDecorateDashboardCard) were both simply appended as extra
     children past the shared height/overflow-y:auto box above —
     nothing ever reserved room for them, so whichever one rendered
     was clipped down to a barely-visible sliver at the card's bottom
     edge instead of a real, tappable row. overflow:visible (this
     variant only — the Job Seeking/Professional Service avatar-card
     variant above keeps its own overflow-y:auto exactly as before,
     untouched) lets that footer row sit as a normal in-flow child
     instead of being scroll-hidden at the box's edge; the shared
     height rule above (now 544px, covering both variants uniformly)
     is what actually gives it the room — see the dedicated
     .vf-owner-toolbar/.mkt-dash-quickcontact rule further down this
     file. */
  overflow: visible !important;
}
/* FIX (follow-up — the flex:1/height:auto version of this rule did not
   actually cap the photo in the browser: a flex item that is a replaced
   element (<img>) computes its OWN "automatic minimum size" from its
   intrinsic/natural dimensions for shrink purposes, which can win out
   over flex-shrink even with an explicit min-height set, so a very tall
   source photo could still blow past the card's fixed height. Switched
   to a fixed, non-flex pixel height instead — deterministic regardless
   of the source photo's own dimensions, no flex auto-sizing involved at
   all. object-fit:cover (base rule, untouched) still crops it to fill
   this exact box.
   FIX (request — "reduce the text card region from 160 to 140, the
   space at the bottom is too large"): the info block is now an explicit
   140px (was auto-filling whatever was left after the photo, ~160px,
   with real text content well under that — hence the leftover blank
   space at the bottom). The 20px freed up goes to the photo (340px ->
   360px) rather than being dropped, so the shared 500px card total
   (see above) is unchanged. */
.dashboard-market-card:not(.mkt-dash-avatar-card) img,
.dashboard-market-card:not(.mkt-dash-avatar-card) video {
  /* FIX (request — "reduce the height to be 400px"): 360 -> 320 -> 276px.
     Paired with the 68px text area and 56px footer just below, this
     totals the requested 400px card height. */
  height: 276px !important;
  flex: 0 0 276px !important;
}
/* FIX (bug report — "optimize bottom text area 140px region... reduce
   the excessive spacing... adjust text and thumbnails so the card
   layout is fully occupied and visually balanced"): the box's total
   footprint (140px) is unchanged — what changed is that its content
   (title + price) was plain block flow, so a short one-line title left
   a large dead gap between the price and the bottom edge of the box.
   Flex + space-between spreads the title block toward the top and the
   price toward the bottom of the SAME 140px, so the region reads as
   deliberately laid out instead of half-empty.
   FIX (dev request — "still too much space... reduce the card
   thumbnail to 480px in total, photo area for other products should
   be 360px"): 140 -> 120 -> 64px (the freed space goes toward the
   new, smaller total — see the shared card-height rule above, now
   480px). Title is now clamped to a single line instead of two (see
   the h5 override below) since 64px no longer has room for a
   two-line title without either overlapping the price or forcing the
   box taller again — a long name still shows in full on the listing's
   own page, this compact card was never the place reading the whole
   thing depended on. space-between was exactly what was pushing the
   title up against the top edge and the price down against the
   bottom edge of this box, leaving a big visible gap between them
   even though the box itself is short — switched to `center` + an
   explicit small `gap` so the title and price sit right next to each
   other as one compact block, vertically centered in the box, instead
   of stretched apart. */
.dashboard-market-card:not(.mkt-dash-avatar-card) .dashboard-market-card-info {
  /* FIX (request — "reduce the height to be 400px"): 64 -> 80 -> 68px.
     Paired with the 276px photo above and the 56px footer below, that's
     the requested 400px total card height. */
  height: 68px !important;
  flex: 0 0 68px !important;
  overflow: hidden !important;
  display: flex !important;
  flex-direction: column !important;
  justify-content: center !important;
  gap: 4px !important;
  /* FIX (dev request — "bottom text area... apply padding for
     consistent spacing... verify alignment so text does not overlap
     or truncate"): box-sizing was missing, so the 12px/14px padding
     from the shared .dashboard-market-card-info rule above was being
     ADDED on top of this box's own fixed height instead of being
     counted inside it, silently shrinking the actual content area
     available to the title/price text. Also, this info box used to
     sit directly under app-marketplace.js's WhatsApp/Call
     quick-contact icons, which were absolutely positioned right on
     top of its bottom-right corner (see .mkt-dash-quickcontact below,
     now moved into its own dedicated row) — that overlay is what was
     actually covering/truncating the price line for buyers. With the
     quick-contact icons relocated to their own row beneath this box,
     that overlap can't happen anymore; padding is trimmed down (was
     14px/12px) to fit this smaller 64px box without re-cramping the
     text. */
  padding: 8px 16px !important;
  box-sizing: border-box !important;
}
/* FIX (dev request — 64px text area): the shared
   .dashboard-market-card-info h5 rule further up this file clamps to
   2 lines, sized for the old 120px/140px box — at 64px that would
   either overlap the price line or force this box taller again.
   Single line + ellipsis for a long name instead. */
.dashboard-market-card:not(.mkt-dash-avatar-card) .dashboard-market-card-info h5 {
  -webkit-line-clamp: 1 !important;
  white-space: nowrap !important;
  text-overflow: ellipsis !important;
}
/* The gap above already sets the spacing between the title and price —
   their own individual margins (from the shared
   .dashboard-market-card-info h5/p rule further up this file) would
   otherwise stack on top of that and re-open the gap this fix is
   meant to close. */
.dashboard-market-card:not(.mkt-dash-avatar-card) .dashboard-market-card-info h5 {
  margin-bottom: 0 !important;
}
.dashboard-market-card:not(.mkt-dash-avatar-card) .dashboard-market-card-info p {
  margin-top: 0 !important;
}

/* FIX (dev request — marketplace dashboard-strip card "action row
   visibility"): whichever one of these two mutually-exclusive rows
   actually renders on a given card — the owner/admin Edit+Delete
   toolbar (a listing's own seller/admin only) or the buyer-facing
   WhatsApp+Call quick-contact icons (everyone else) — now gets a
   dedicated, always-visible 64px footer row (see the matching
   height/overflow override on the card itself, above) instead of
   being appended past the card's old fixed-height boundary and
   clipped down to a near-invisible sliver. position:static overrides
   .mkt-dash-quickcontact's own absolute/corner-overlay positioning
   (app-marketplace.js's injected CSS) so it lays out as a normal flex
   child here instead of floating on top of the info box's text. The
   Job Seeking/Professional Service avatar-card variant's own footer
   (.mkt-dash-av-owner-foot) is untouched — out of scope, already
   correct. */
.dashboard-market-card:not(.mkt-dash-avatar-card) .vf-owner-toolbar,
.dashboard-market-card:not(.mkt-dash-avatar-card) .mkt-dash-quickcontact {
  /* FIX (request — "reduce the height to be 400px"): 64 -> 56px, with
     padding trimmed 10px -> 8px top/bottom to still fit the 40px
     min-height buttons below without clipping. */
  position: static !important;
  right: auto !important;
  bottom: auto !important;
  z-index: auto !important;
  flex: 0 0 56px !important;
  width: 100% !important;
  height: 56px !important;
  box-sizing: border-box !important;
  display: flex !important;
  flex-wrap: nowrap !important;
  align-items: center !important;
  justify-content: space-evenly !important;
  gap: 10px !important;
  padding: 8px 14px !important;
  border-top: 1px solid rgba(10,14,39,0.07) !important;
  background: var(--color-white) !important;
  overflow-x: auto !important;
  scrollbar-width: none !important;
}
.dashboard-market-card:not(.mkt-dash-avatar-card) .vf-owner-toolbar::-webkit-scrollbar,
.dashboard-market-card:not(.mkt-dash-avatar-card) .mkt-dash-quickcontact::-webkit-scrollbar {
  display: none !important;
}
/* Even spacing + touch-target sizing (Google/Apple guidance is ~40-44px
   minimum) for whichever buttons land in that row. */
.dashboard-market-card:not(.mkt-dash-avatar-card) .vf-tb-btn {
  flex: 1 1 0 !important;
  min-height: 40px !important;
  justify-content: center !important;
}
.dashboard-market-card:not(.mkt-dash-avatar-card) .mkt-dash-icon-btn {
  width: 40px !important;
  height: 40px !important;
  font-size: 1rem !important;
  flex-shrink: 0 !important;
}

/* ── "New in Marketplace" dashboard card — Job Seeking / Professional
   Services / Job Vacancy variant ─────────────────────────────────────
   FIX (request — "the job card / employer card on the general
   dashboard should show more features instead of just the generic
   profile page"): same .dashboard-market-card box/shape/shadow as
   every other card on this strip (base rule above) — this only
   restyles what's INSIDE for the three "person, not product"
   categories (see _mktDashboardAvatarCardHTML in app-marketplace.js,
   which builds this markup). Every other category's dashboard card
   keeps its original thumbnail+name+price layout, completely
   untouched. Reserves space bottom-right (.mkt-dash-av-foot's
   padding-right) for the WhatsApp/Call quick-contact icon overlay
   app-marketplace.js's _mktDecorateDashboardCard() already injects on
   top of every dashboard card, avatar or not, so the two don't visually
   collide. */
/* FIX (request — Job Seeker / Professional Service card redesign,
   "study the screenshot"): this variant now carries a full labeled
   details section + Experience Summary + (for the owner) an Edit/Delete
   footer, on top of everything it already rendered — the compact 200px
   width every other dashboard-strip card keeps is too narrow to hold
   that without cramming, so this one card variant only is widened.
   Overriding the base `.dashboard-market-card` width/flex-basis needs
   equal specificity plus !important since that base rule already uses
   !important — the two-class selector already used everywhere else in
   this block provides that. min-height is dropped in favor of a natural
   height (the amount of content varies per listing — an owner's own
   card is taller than a buyer's, a listing with no documents is shorter
   than one with all four) so nothing is ever clipped or oversized. */
.dashboard-market-card.mkt-dash-avatar-card {
  display: flex !important;
  flex-direction: column !important;
  /* NOTE: width/flex-basis is intentionally NOT set here — cards inside
     #dashboard-market-slider already render at 330px (see that ID's own
     `> *` rule further up this file), which is plenty of room for the
     content this variant adds below; setting a competing width here
     would either lose to that higher-specificity ID rule silently or,
     if it ever won, fight it for no benefit. */
  /* FIX (request — WhatsApp/Call icons now overlay in the bottom-right
     corner with no dedicated footer row reserving space for them (see
     app-marketplace.js's _mktDashboardAvatarCardHTML, which no longer
     renders its own Contact footer for a buyer view): extra bottom
     padding keeps that circular overlay (.mkt-dash-quickcontact, ~6px
     from each edge) from sitting on top of this card's own last line of
     text (Experience Summary / details) instead of clear space below
     it. Owner view (Edit/Delete footer) still renders its own footer row
     as before — this is just a touch of breathing room under it too. */
  padding: 18px 16px 44px !important;
  /* height is now set (500px, shared with the plain product card) by the
     "same size as..." rule above — this block used to set height:auto
     here itself, which, being later in the cascade at equal specificity,
     would silently win and undo that shared sizing. Not repeated here. */
}
/* FIX (bug report — "optimize bottom text area 140px region"): this is
   the card's sole direct child inside the fixed-height, flex-column
   .dashboard-market-card.mkt-dash-avatar-card (see that rule further up
   this file) — without flex-grow it only shrink-wraps its own content,
   so a short listing left a blank gap between it and the card's bottom
   edge. flex:1 makes it stretch to fill the card's full available
   height instead, giving .mkt-dash-av-exp below (flex:1 itself) real
   room to absorb any leftover space rather than leaving it blank. */
.mkt-dash-av-card-inner { display: flex; flex-direction: column; flex: 1 1 auto; }
.mkt-dash-av-head { display: flex; align-items: center; gap: 11px; }
/* FIX (request — "increase the avatar a little... make it premium and
   elegant"): was 52px, then reduced to 36px to match this strip's other
   avatars (.dashboard-reel-avatar 34px, .donor-wall-avatar 36px) — bumped
   back up a little (44px) since a same-size seller photo is the card's
   main visual identity and read too small at 36px for a "beautiful and
   elegant" listing. Still smaller than the original 52px, and still in
   the same size family as its neighbors, just with a bit more presence. */
.mkt-dash-av-avatar {
  flex: 0 0 44px; width: 44px; height: 44px; border-radius: 50%;
  overflow: hidden; background: linear-gradient(135deg,#1B2B8B,#0A0E27);
  display: flex; align-items: center; justify-content: center;
  border: 2px solid rgba(201,166,107,0.55);
  box-shadow: 0 2px 6px rgba(10,14,39,0.18);
}
.mkt-dash-av-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* FIX (bug report — avatar fallback): the initials <span> is now always
   present in the markup alongside the <img> (see _mktDashboardAvatarCardHTML,
   app-marketplace.js) so it can be revealed instantly on image failure
   instead of being built by JS after the fact. Hidden here by default so
   it never double-renders behind a working photo. */
.mkt-dash-av-avatar span { display: none; }
.mkt-dash-av-avatar.mkt-dash-av-initials span {
  display: block;
  color: #E8C874; font-weight: 800; font-size: 1.05rem; font-family: var(--font-ui);
}
.mkt-dash-av-names { min-width: 0; flex: 1; padding-top: 2px; }
/* FIX (request — "I don't like the font that was used for the
   profile [on the dashboard home page card]... reduce the size and
   use a premium font"): Syne is a bold geometric display face — at
   1.05rem/800-weight on this card it ran heavy and wide enough to
   crowd the role badge beside it (see the "New in Marketplace"
   screenshot). Switched to var(--font-display) — Fraunces, the same
   token every other "premium/editorial" heading across the app now
   uses (the live-broadcast host name, etc. — see the 2026-07-25
   rollout note near .live-host-info), at a smaller size/weight, so
   this card reads elegant rather than shouting and stays consistent
   with the app's one established premium-heading font instead of
   introducing a second, different one just for this card. Already
   loaded (style.css's own @import), so nothing new to fetch. */
.mkt-dash-av-names h5 {
  font-size: 0.92rem !important; font-weight: 700 !important;
  font-family: var(--font-display) !important; letter-spacing: 0.005em;
  color: var(--primary) !important; margin: 0 0 2px !important;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* FIX (request — navy/gold redesign, "well structured"): the small
   identity pill (Job Seeker / Service Provider / Job Vacancy) under the
   name — gold-on-cream, matching the approved mockup's badge treatment. */
.mkt-dash-av-role-badge {
  display: inline-block; margin-top: 2px;
  font-size: 0.66rem; font-weight: 700; color: #8A6D2A;
  background: #F3E4C2; padding: 2px 8px; border-radius: 6px;
  letter-spacing: 0.01em;
}
.mkt-dash-av-names p {
  font-size: 0.76rem !important; font-weight: 600 !important;
  color: var(--text-muted) !important; margin: 0 !important;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Thumbnails section — "enlarged and expanded to fill empty space,
   aligned in a neat grid or row, with professional framing" (request).
   A fixed 4-column grid (rather than the previous flex-wrap row) keeps
   all four tiles the same size regardless of label length, and the
   taller aspect ratio + bigger glyph gives each one real presence
   instead of a cramped chip. */
.mkt-dash-av-tiles { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-top: 14px; }
.mkt-dash-av-tile {
  position: relative;
  min-width: 0; aspect-ratio: 1 / 1; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 6px;
  padding: 8px 4px; border-radius: 14px; text-decoration: none;
  /* FIX (request — navy/gold redesign): warm ivory chip instead of the
     previous cool-gray gradient, matching the approved mockup's palette. */
  background: linear-gradient(160deg,#F8F6F0,#EEE9DC);
  border: 1px solid rgba(10,14,39,0.08);
  box-shadow: 0 1px 3px rgba(10,14,39,0.06);
  color: var(--primary); font-size: 0.72rem; font-weight: 700;
  transition: transform 0.15s, box-shadow 0.15s;
}
.mkt-dash-av-tile:active { transform: scale(0.94); }
/* FIX (request — "use dark blue background colour for the PDF, record,
   and photo card thumbnail... make it beautiful and elegant"): every
   tile's glyph now gets the same dark-blue badge treatment that was
   previously only applied to the Portfolio/folder icon (Resume, Photo,
   Record included) — one consistent premium look across all four tiles
   instead of one standing out from the other three.
   FIX (follow-up — navy/gold redesign, approved mockup): icon glyph
   recolored from white to gold — more distinctive, and ties to the same
   gold already used for the avatar's border. */
.mkt-dash-av-tile i {
  width: 34px; height: 34px; border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.05rem; color: #E8C874;
  background: linear-gradient(135deg, #1B2B8B, #0A0E27);
  box-shadow: 0 2px 6px rgba(10,14,39,0.28);
}
/* FIX (bug report — "repair record icon"): the Record tile's icon is now
   an inline SVG (font-independent, see MKT_ICONS.clipboard in
   app-marketplace.js) instead of a Font Awesome glyph — this box already
   centers/colors/backgrounds its content by tag name (.mkt-dash-av-tile i
   above) so nothing else about the tile changes; this just sizes the SVG
   itself and lets it pick up the same gold color via currentColor. */
.mkt-dash-av-tile i.mkt-dash-av-tile-svgicon svg {
  width: 17px; height: 17px; display: block; stroke: currentColor;
}
.mkt-dash-av-tile span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.mkt-dash-av-tile-empty { opacity: 0.55; }
/* FIX (request — "PDF folder indication"): small corner badge naming the
   actual file type behind a filled tile, so it's clear at a glance
   whether a credential is a PDF/DOC/image without tapping through. */
.mkt-dash-av-tile-type {
  position: absolute; top: 4px; right: 5px;
  font-size: 0.56rem; font-weight: 800; letter-spacing: 0.02em;
  color: #fff; background: rgba(27,43,139,0.82);
  border-radius: 5px; padding: 1px 4px; line-height: 1.3;
}

/* Details section — Full Name / Desired Position / Proposed Salary /
   Email / Phone, matching the reference screenshot's two-column layout
   for the paired fields.
   FIX (dev request — "still too much space... reduce the marketplace
   card thumbnail to 480px in total"): the card is already fixed at
   480px total (job seeker) / 360px photo (other products) — see the
   shared height rules above, both already at those values. The visible
   leftover blank gap under this card's content came from one level
   down: .mkt-dash-av-exp's flex:1 (further below) only distributes
   space *inside* this block (.mkt-dash-av-details), and this block
   itself was never told to grow to fill ITS parent
   (.mkt-dash-av-card-inner)'s leftover height — so the "fill the gap"
   flex chain stopped here, one level too shallow, leaving the blank gap
   between this block and the card's real bottom edge untouched. flex:1
   here (this block is card-inner's flex-column child) lets it reach the
   card's actual bottom edge, at which point .mkt-dash-av-exp's own
   flex:1 can do its job properly. */
.mkt-dash-av-details { margin-top: 14px; display: flex; flex-direction: column; gap: 10px; flex: 1 1 auto; }
.mkt-dash-av-detail-row.mkt-dash-av-detail-full {
  /* FIX (request — "make the Full Name align well with the rest"): this
     row used to be plain inline text (label + colon + value on one
     line, both the same size) while every other field
     (.mkt-dash-av-detail-col below) stacks a small-caps label above a
     bold value. Same flex-column treatment here so Full Name reads as
     one more field in the same set instead of a differently-formatted
     line above them. */
  display: flex; flex-direction: column; gap: 2px;
}
.mkt-dash-av-detail-row.mkt-dash-av-detail-cols {
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
}
.mkt-dash-av-detail-row.mkt-dash-av-detail-cols:empty { display: none; }
.mkt-dash-av-detail-col { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.mkt-dash-av-detail-label {
  /* FIX (request — navy/gold redesign, approved mockup): warm gold-brown
     instead of the previous cool blue-gray, so labels contrast against
     their navy values in hue, not just weight. */
  font-size: 0.66rem; font-weight: 700; color: #8A6D2A;
  text-transform: uppercase; letter-spacing: 0.02em;
}
.mkt-dash-av-detail-value {
  font-size: 0.82rem; font-weight: 700; color: var(--primary);
  overflow-wrap: anywhere;
}
.mkt-dash-av-detail-value.mkt-dash-av-detail-ellipsis {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Experience Summary — collapsed to two lines by default, expands with
   a gentle max-height transition on tap (see the onclick toggle in
   _mktDashboardAvatarDetailsHTML, app-marketplace.js). */
.mkt-dash-av-exp {
  margin-top: 2px; padding: 10px 12px; border-radius: 12px;
  /* FIX (request — navy/gold redesign, approved mockup): warm ivory
     panel instead of the previous cool gray tint, matching the rest of
     the card's new palette. */
  background: #F1EFE7; border: 1px solid rgba(10,14,39,0.06);
  /* FIX (bug report — "optimize bottom text area 140px region... reduce
     the excessive spacing... fully occupied and visually balanced"):
     the card's fixed 500px height (shared with the plain product card,
     see the height rule above) is taller than this card's content on a
     short listing — the gap used to be blank white space below
     everything. flex:1 lets this, the last real content block, absorb
     that leftover height itself: the ivory panel grows to fill it
     (instead of a blank gap sitting under it), and the still-clamped
     text is centered inside the taller panel rather than stuck at its
     top. Owner Edit/Delete footer (below) still renders after this and
     pins to the very bottom via its own margin-top:auto. */
  flex: 1 1 auto;
  display: flex; flex-direction: column; justify-content: center;
}
.mkt-dash-av-exp .mkt-dash-av-detail-label { display: block; margin-bottom: 4px; }
.mkt-dash-av-exp-text {
  margin: 0; font-size: 0.8rem; line-height: 1.45; color: var(--text-muted);
  cursor: pointer;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; max-height: 2.9em; transition: max-height 0.35s ease;
}
.mkt-dash-av-exp-text.mkt-dash-av-exp-open {
  -webkit-line-clamp: unset; max-height: 400px; overflow: visible;
}

.mkt-dash-av-foot {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 6px; margin-top: 14px; padding-top: 10px; padding-right: 64px;
  border-top: 1px solid rgba(10,14,39,0.06);
}

.mkt-dash-av-foot span {
  font-size: 0.68rem; font-weight: 700; color: var(--primary);
  text-transform: uppercase; letter-spacing: 0.02em;
}
.mkt-dash-av-foot b {
  font-size: 0.78rem; font-weight: 800; color: var(--secondary);
  font-family: var(--font-ui); white-space: nowrap;
}

/* Owner-only Edit/Delete footer — replaces .mkt-dash-av-foot above when
   the card belongs to the person viewing it (or they're an admin). Same
   green/red pill treatment as the reference screenshot.
   FIX (bug report — "optimize bottom text area 140px region... fully
   occupied and visually balanced"): margin-top changed from a fixed
   14px to auto — with .mkt-dash-av-card-inner now stretched to the
   card's full height (see that rule near the top of this section), auto
   pins this footer to the card's actual bottom edge whenever it
   renders, instead of floating directly under whatever content happens
   to precede it and leaving blank space beneath. */
.mkt-dash-av-owner-foot {
  display: flex; gap: 10px; margin-top: auto; padding-top: 12px;
  border-top: 1px solid rgba(10,14,39,0.06);
}
.mkt-dash-av-owner-btn {
  flex: 1; display: flex; align-items: center; justify-content: center;
  gap: 6px; padding: 10px 0; border-radius: 50px; border: none;
  font-size: 0.82rem; font-weight: 700; cursor: pointer;
  font-family: var(--font-ui); transition: transform 0.15s, opacity 0.15s;
}
.mkt-dash-av-owner-btn:active { transform: scale(0.96); }
.mkt-dash-av-owner-edit {
  background: rgba(0,144,105,0.14); color: #007a56;
}
.mkt-dash-av-owner-delete {
  background: rgba(178,34,34,0.12); color: #b22222;
}

/* Reel cards */
.reels-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; }
.reel-card {
  position: relative; height: 450px; border-radius: var(--radius-2xl) !important;
  overflow: hidden; color: var(--color-white);
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: 15px; box-shadow: var(--shadow-md) !important;
  cursor: pointer; border: 2px solid transparent !important;
  transition: var(--transition-slow) !important;
}
.reel-card::before { content: ''; position: absolute; inset: 0; background: linear-gradient(to top, rgba(0,0,0,0.8), transparent 60%); z-index: 2; }
.reel-card > img, .reel-card > video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 1; transition: transform var(--duration-slow) var(--ease-out); }
.reel-card:hover > img, .reel-card:hover > video { transform: scale(1.05); }
.reel-content, .reel-actions { z-index: 3; position: relative; }
.reel-user-info { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.reel-user-info .avatar-placeholder { width: 35px; height: 35px; border-radius: var(--radius-md); border: 2px solid var(--color-white); flex-shrink: 0; }
#reels .header h1 { color: var(--danger-color) !important; }
#reels .reel-card:hover { border-color: var(--accent) !important; box-shadow: 0 12px 40px rgba(255, 213, 0,0.25) !important; }

/* Dashboard reel card — premium tall thumbnail */
.dashboard-reel-card {
  width: 160px; height: 260px; flex-shrink: 0; position: relative;
  border-radius: 16px; overflow: hidden; display: inline-block;
  box-shadow: 0 4px 16px rgba(10,14,39,0.18), 0 1px 3px rgba(10,14,39,0.10);
  cursor: pointer; transition: transform 0.22s ease, box-shadow 0.22s ease;
}
.dashboard-reel-card:hover { transform: translateY(-5px); box-shadow: 0 12px 36px rgba(10,14,39,0.24); }
.dashboard-reel-card::before { content: ''; position: absolute; inset: 0; background: linear-gradient(to top, rgba(0,0,0,0.75) 0%, transparent 60%); z-index: 2; }
.dashboard-reel-card > * { z-index: 3; position: relative; }
.dashboard-reel-card video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 1; }
.dashboard-reel-card .reel-content { position: absolute; bottom: 12px; left: 12px; right: 12px; color: var(--color-white); text-align: left; }
.dashboard-reel-avatar { width: 34px; height: 34px; border-radius: 50%; overflow: hidden; border: 2px solid var(--color-white); box-shadow: 0 2px 8px rgba(10,14,39,0.35); background-color: var(--color-neutral-100); flex-shrink: 0; }
.dashboard-reel-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Recorded livestream card */
.livestream-card { flex: 0 0 280px; width: 280px; height: 220px; display: flex; flex-direction: column; background: var(--color-neutral-25); border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-xs); cursor: pointer; transition: var(--transition-slow); }
.livestream-card:hover { transform: translateY(-5px); box-shadow: var(--shadow-md); }
.livestream-video-container { position: relative; width: 100%; height: 150px; background-color: var(--color-neutral-100); }
.livestream-video-container video { width: 100%; height: 100%; object-fit: cover; }
.livestream-info { padding: 15px; flex-grow: 1; display: flex; flex-direction: column; justify-content: center; }
.livestream-info strong { display: block; color: var(--primary); margin-bottom: 5px; white-space: normal; line-height: var(--leading-snug); }
.livestream-info span { font-size: var(--text-md); color: var(--color-neutral-400); white-space: normal; }

/* Live stream preview card in slider */
.live-stream-preview-card {
  flex: 0 0 180px !important; min-width: 180px !important;
  height: 220px !important; scroll-snap-align: start;
  border-radius: var(--radius-xl) !important; cursor: pointer; position: relative; overflow: hidden;
  box-shadow: var(--shadow-lg) !important;
  border: 2px solid rgba(255, 213, 0, 0.2) !important;
  background-size: cover; background-position: center;
  display: flex; flex-direction: column; justify-content: space-between;
  padding: 10px; color: var(--color-white);
}
.live-stream-preview-card::before { content:''; position:absolute; inset:0; z-index:1; background: linear-gradient(to top, rgba(0,0,0,0.8), transparent); pointer-events:none; }
.live-preview-header, .live-preview-footer { position: relative; z-index: 2; }
.live-preview-footer .host-name { font-weight: var(--weight-bold); }
.live-preview-footer .stream-title { font-size: var(--text-md); line-height: var(--leading-snug); }
/* FIX (2026-07-21 — Midnight & Champagne Gold recolor): was
   var(--danger-color)/#F87171 directly — the exact same red used for
   errors, delete buttons, and SOS/crisis reports. Now uses the dedicated
   --live-badge-bg/--live-badge-bg-light crimson pair (token.css) instead,
   so the LIVE badge can be refined on its own without touching any
   error/danger state elsewhere in the app. */
.live-tag { background: linear-gradient(135deg, var(--live-badge-bg), var(--live-badge-bg-light)) !important; border-radius: var(--radius-pill) !important; padding: 4px 12px !important; font-size: 0.72rem !important; font-weight: var(--weight-bold) !important; letter-spacing: 1px !important; box-shadow: 0 4px 14px rgba(180,55,58,0.4) !important; }
.join-live-btn { flex: 0 0 180px !important; min-width: 180px !important; height: 220px !important; }


/* ═══════════════════════════════════════════════════════════════════════════
   §11  STAT CARDS
   ═══════════════════════════════════════════════════════════════════════════ */

.analytics-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; }
.stat-card {
  background: var(--color-white) !important;
  border-radius: var(--radius-2xl) !important; padding: 24px !important;
  box-shadow: var(--shadow-sm) !important; border: 1px solid var(--border) !important;
  position: relative !important; overflow: hidden !important;
  transition: var(--transition-slow) !important; text-align: center;
}
.stat-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px; background: var(--g-navy) !important; }
.stat-card:nth-child(2)::before { background: var(--g-gold) !important; }
.stat-card:nth-child(3)::before { background: var(--g-teal) !important; }
.stat-card:nth-child(4)::before { background: linear-gradient(135deg, var(--danger-color), var(--danger-light)) !important; }
.stat-card::after { content: ''; position: absolute; bottom: -20px; right: -20px; width: 80px; height: 80px; border-radius: var(--radius-full); background: rgba(10,14,39,0.03); }
.stat-card:hover { transform: translateY(-4px) !important; box-shadow: var(--shadow-lg) !important; }
.stat-card h4 { font-size: var(--text-sm) !important; font-weight: var(--weight-semibold) !important; color: var(--text-muted) !important; text-transform: uppercase !important; letter-spacing: var(--tracking-wider) !important; margin-bottom: 10px !important; }
.stat-value { font-family: var(--font-ui) !important; font-size: var(--text-6xl) !important; font-weight: var(--weight-extrabold) !important; color: var(--primary) !important; line-height: 1 !important; margin: 10px 0; }
.stat-card p { font-size: var(--text-sm) !important; color: var(--text-muted) !important; margin-top: 4px !important; }

/* Wallet card */
.wallet-card { text-align: center; padding: 30px; border: 1px solid var(--light-gray); border-radius: var(--radius-md); }
.empy-balance { color: var(--accent-color) !important; }


/* ═══════════════════════════════════════════════════════════════════════════
   §12  BUTTONS
   ═══════════════════════════════════════════════════════════════════════════ */

.btn {
  border-radius: var(--radius-xl) !important; font-weight: var(--weight-semibold) !important;
  font-size: var(--text-base) !important; cursor: pointer !important;
  transition: var(--transition-base) !important; letter-spacing: 0.1px !important;
  border: none !important; padding: 12px 25px;
  background: var(--secondary); color: var(--color-white);
  display: inline-flex; align-items: center; justify-content: center;
}
.btn:hover, .btn:active { transform: translateY(-2px); box-shadow: var(--shadow-sm); }
.btn-accent, button.btn-accent { background: var(--g-gold) !important; color: var(--primary) !important; box-shadow: var(--shadow-gold) !important; }
.btn-accent:hover { transform: translateY(-2px) !important; box-shadow: 0 12px 40px rgba(255, 213, 0,0.45) !important; }
.btn-success { background: var(--g-teal) !important; color: var(--color-white) !important; box-shadow: var(--shadow-teal) !important; }
.btn-danger { background: linear-gradient(135deg, var(--danger-color) 0%, var(--danger-light) 100%) !important; color: var(--color-white) !important; box-shadow: 0 6px 20px rgba(239,68,68,0.30) !important; }
.btn-small { padding: 5px 14px !important; font-size: var(--text-sm) !important; border-radius: var(--radius-md) !important; }
.sos-button { background: var(--danger-color); color: var(--color-white); }

/* 3D icon treatment */
.icon-3d { width: 52px; height: 52px; border-radius: var(--radius-lg); display: flex; align-items: center; justify-content: center; font-size: var(--text-3xl); position: relative; flex-shrink: 0; box-shadow: 0 8px 24px rgba(0,0,0,0.12), inset 0 1px 0 rgba(255,255,255,0.4); }
.icon-3d.navy { background: var(--g-navy); color: var(--color-white); }
.icon-3d.gold { background: var(--g-gold); color: var(--primary); }
.icon-3d.teal { background: var(--g-teal); color: var(--color-white); }
.icon-3d.red { background: linear-gradient(135deg, var(--danger-color), var(--danger-light)); color: var(--color-white); }

/* Business register button */
.biz-register-btn { display: inline-flex; align-items: center; gap: 8px; background: linear-gradient(135deg, var(--live-color), var(--secondary)); color: var(--color-white); border: none; border-radius: var(--radius-pill); padding: 12px 24px; font-size: var(--text-md); font-weight: var(--weight-bold); cursor: pointer; transition: var(--transition-base); text-decoration: none; }
.biz-register-btn:hover { transform: translateY(-2px); box-shadow: var(--shadow-live); }


/* ═══════════════════════════════════════════════════════════════════════════
   §13  FORM INPUTS & LABELS
   ═══════════════════════════════════════════════════════════════════════════ */

.form-group { margin-bottom: 15px; text-align: left; }
.form-group label { display: block; font-weight: var(--weight-semibold); margin-bottom: 8px; color: var(--primary) !important; font-size: var(--text-sm) !important; letter-spacing: var(--tracking-wide) !important; text-transform: uppercase !important; }
.form-group input, .form-group select, .form-group textarea { width: 100%; padding: 12px; font-size: var(--text-lg); background: var(--color-surface-blue) !important; border: 1.5px solid rgba(10,14,39,0.10) !important; border-radius: var(--radius-xl) !important; color: var(--primary) !important; transition: var(--transition-base) !important; }
.form-group input:focus, .form-group select:focus, .form-group textarea:focus { border-color: var(--secondary) !important; box-shadow: 0 0 0 4px rgba(27,43,139,0.08) !important; outline: none !important; background: var(--color-white) !important; }
.form-group input::placeholder { color: var(--text-light) !important; }

.form-feedback { padding: 10px; margin-bottom: 15px; border-radius: var(--radius-sm); font-size: var(--text-md); text-align: center; display: none; border-left-width: 5px; border-left-style: solid; animation: fadeIn 0.3s; }
.form-feedback.info { background: #e3f2fd; border-color: #2196f3; color: #1e88e5; }
.form-feedback.success { background: var(--color-surface-green); border-color: var(--success-color); color: #1e88e5; }
.form-feedback.warning { background: var(--color-surface-warm); border-color: #ffb300; color: var(--color-warning-dark); }
.form-feedback.error { background: var(--color-surface-red); border-color: var(--danger-color); color: #c62828; }

.user-type-selection { display: flex; justify-content: center; gap: 15px; margin-bottom: 25px; flex-wrap: wrap; }
.wallet-selection { display: flex; justify-content: flex-start; gap: 15px; margin-bottom: 25px; flex-wrap: wrap; }
.user-type-selection input[type="radio"], .wallet-selection input[type="radio"] { display: none; }
.user-type-selection label, .wallet-selection label { cursor: pointer; padding: 10px 20px; border: 2px solid var(--light-gray); border-radius: var(--radius-pill); transition: var(--transition-slow); }
.user-type-selection input[type="radio"]:checked + label, .wallet-selection input[type="radio"]:checked + label { background: var(--secondary); color: var(--color-white); border-color: var(--primary); }
.user-type-selection label i, .wallet-selection label i { margin-right: 8px; }

.date-select-group { display: flex; gap: 10px; }
.security-note { font-size: var(--text-md); color: var(--color-neutral-500); margin-top: 15px; text-align: center; }
.security-note i { color: var(--success-color); margin-right: 5px; }

/* Rich text toolbar */
.rich-text-toolbar { display: flex; flex-wrap: wrap; gap: 4px; padding: 8px 10px; background: var(--color-neutral-100); border: 1px solid var(--color-neutral-150); border-bottom: none; border-radius: var(--radius-sm) var(--radius-sm) 0 0; }
.rich-text-toolbar button { background: var(--color-white); border: 1px solid var(--color-neutral-150); border-radius: var(--radius-xs); padding: 4px 8px; cursor: pointer; font-size: var(--text-sm); color: var(--color-neutral-600); transition: var(--transition-base); min-width: 28px; }
.rich-text-toolbar button:hover { background: var(--primary); color: var(--color-white); border-color: var(--primary); }
.rich-text-toolbar select { padding: 3px 6px; border: 1px solid var(--color-neutral-150); border-radius: var(--radius-xs); font-size: 0.82rem; color: var(--color-neutral-600); cursor: pointer; }
.rich-text-toolbar .separator { width: 1px; background: var(--color-neutral-150); margin: 2px 4px; align-self: stretch; }
textarea.has-toolbar { border-radius: 0 0 var(--radius-sm) var(--radius-sm) !important; }

/* Flutterwave badge */
.flw-badge { display: inline-flex; align-items: center; gap: 6px; background: #f0f4ff; border: 1px solid #c0cefe; border-radius: var(--radius-md); padding: 5px 12px; font-size: 0.82rem; color: var(--color-neutral-700); }
.flw-badge i { color: #F5A623; }

/* Captcha */
.captcha-group { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 20px; }
#captcha-code { user-select: none; font-family: var(--font-mono); letter-spacing: 4px; font-weight: var(--weight-bold); font-size: var(--text-4xl); background: var(--color-neutral-75); padding: 10px 15px; border-radius: var(--radius-sm); border: 1px solid var(--color-neutral-200); text-decoration: line-through; color: var(--color-neutral-500); }
#refresh-captcha { background: none; border: none; font-size: var(--text-2xl); cursor: pointer; color: var(--primary); }

/* Toggle switch */
input[type="checkbox"][switch] { -webkit-appearance: none; -moz-appearance: none; appearance: none; width: 44px; height: 24px; background: var(--color-neutral-200); border-radius: 12px; position: relative; cursor: pointer; outline: none; transition: background-color var(--duration-slow); }
input[type="checkbox"][switch]:checked { background: var(--success-color); }
input[type="checkbox"][switch]::before { content: ''; position: absolute; top: 2px; left: 2px; width: 20px; height: 20px; background: var(--color-white); border-radius: var(--radius-full); transition: transform var(--duration-slow); }
input[type="checkbox"][switch]:checked::before { transform: translateX(20px); }


/* ═══════════════════════════════════════════════════════════════════════════
   §14  AUTH MODAL & CARD
   ═══════════════════════════════════════════════════════════════════════════ */

#auth-modal-overlay, .modal-overlay-container {
  display: none; position: fixed; inset: 0;
  background: rgba(10, 14, 39, 0.85) !important;
  backdrop-filter: blur(16px) !important;
  z-index: var(--z-modal); align-items: flex-start; justify-content: center;
  padding: 4vh 0; overflow-y: auto; animation: fadeInModal 0.3s;
}
#auth-modal-overlay.show, .modal-overlay-container.show { display: flex; }
#buy-empy-modal.modal-overlay-container, #promotion-modal-overlay.modal-overlay-container { z-index: var(--z-live); }
.modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.6); z-index: var(--z-overlay); display: none; }
.modal-overlay.show { display: block; }

.auth-card, .modal-card {
  background: var(--color-white); padding: 40px; border-radius: var(--radius-modal) !important;
  box-shadow: var(--shadow-xl) !important; border: 1px solid rgba(10,14,39,0.08) !important;
  width: 100%; max-width: 450px; text-align: center; position: relative;
  max-height: 92vh; overflow-y: auto;
}
.modal-card { max-width: 500px; }
.auth-card h2 { font-family: var(--font-ui) !important; font-weight: var(--weight-extrabold) !important; color: var(--primary) !important; }
.close-modal { position: absolute; top: 15px; right: 15px; font-size: var(--text-4xl); color: var(--color-neutral-300); cursor: pointer; border: none; background: none; }
#signup-view, #forgot-password-view { display: none; }
.auth-switch { margin-top: 15px; font-size: var(--text-md); }
.forgot-password-link { margin-left: 10px; }
#org-fields { display: none; }

/* Avatar uploader */
.avatar-uploader { text-align: center; margin-bottom: 20px; }
.avatar-uploader label { display: inline-block; width: 120px; height: 120px; border-radius: var(--radius-full); border: 3px solid var(--light-gray); cursor: pointer; position: relative; overflow: hidden; background-color: var(--color-neutral-75); }
.avatar-uploader img, .avatar-uploader video { width: 100%; height: 100%; object-fit: cover; }
.avatar-uploader img { display: none; }
.avatar-uploader img.active + .upload-icon { opacity: 0; }
.avatar-uploader .upload-icon { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; color: var(--primary); transition: var(--transition-opacity); }

/* Google sign-in */
.auth-card .separator { display: flex; align-items: center; text-align: center; color: var(--color-neutral-350); margin: 20px 0; }
.auth-card .separator::before, .auth-card .separator::after { content: ''; flex: 1; border-bottom: 1px solid var(--color-neutral-200); }
.auth-card .separator:not(:empty)::before { margin-right: .25em; }
.auth-card .separator:not(:empty)::after { margin-left: .25em; }
.btn-google { background: var(--color-white); color: var(--color-neutral-600); border: 1px solid var(--color-neutral-200) !important; width: 100%; margin-top: 10px; }
.btn-google:hover { background: var(--color-neutral-75) !important; }
.btn-google i { color: #DB4437; margin-right: 10px; }
.btn-google:disabled, .btn-google.btn-google-loading { opacity: 0.75; cursor: default; display: flex; align-items: center; justify-content: center; gap: 8px; }
.btn-google-spinner { width: 15px; height: 15px; border-radius: 50%; border: 2px solid rgba(27,43,139,0.25); border-top-color: var(--primary, #1B2B8B); display: inline-block; animation: btn-google-spin 0.7s linear infinite; }
@keyframes btn-google-spin { to { transform: rotate(360deg); } }

/* Modal card for payments */
#sos-donation-modal .modal-card, #buy-empy-modal .modal-card { max-width: 550px; text-align: left; }
.payment-tabs { display: flex; border-bottom: 1px solid var(--light-gray); margin-bottom: 20px; }
.payment-tab { padding: 10px 20px; cursor: pointer; color: var(--color-neutral-350); font-weight: var(--weight-bold); border-bottom: 3px solid transparent; }
.payment-tab.active { background: var(--g-navy) !important; color: var(--color-white) !important; border-radius: var(--radius-md) !important; }
.payment-method-content { display: none; }
.payment-method-content.active { display: block; }
.crypto-address-box { background: var(--color-neutral-75); padding: 15px; border-radius: var(--radius-sm); font-family: var(--font-mono); word-wrap: break-word; }
#withdrawal-method-fields > div { display: none; }
#withdrawal-preview, #transfer-preview, #cross-chain-transfer-preview { background: #E8EAF6; padding: 15px; border-radius: var(--radius-sm); margin-top: 20px; border: 1px solid #C5CAE9; }
#withdrawal-preview p, #transfer-preview p, #cross-chain-transfer-preview p { margin: 5px 0; font-weight: var(--weight-medium); }
#withdrawal-preview strong, #transfer-preview strong, #cross-chain-transfer-preview strong { color: var(--primary); }
#checkout-view { display: none; }
.cart-modal {
  position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
  background: var(--color-white); padding: 30px; border-radius: var(--radius-3xl) !important;
  z-index: var(--z-modal); width: 90%; max-width: 600px;
  box-shadow: var(--shadow-xl) !important; border: 1px solid var(--border) !important;
  max-height: 90vh; overflow-y: auto;
}
.cart-modal h2 { margin-bottom: 20px; color: var(--primary); font-family: var(--font-ui) !important; }
.cart-item { display: flex; align-items: center; gap: 15px; margin-bottom: 15px; padding-bottom: 15px; border-bottom: 1px solid var(--light-gray); }
.cart-item img { width: 80px; height: 80px; object-fit: cover; border-radius: var(--radius-sm); }
.cart-item-info { flex-grow: 1; }
#cart-total { margin-top: 20px; text-align: right; font-size: var(--text-2xl); font-weight: var(--weight-bold); }
#promotion-payment-details { display: none; }

/* Cart modal premium */
.cart-modal { border-radius: var(--radius-3xl) !important; border: 1px solid var(--border) !important; box-shadow: var(--shadow-xl) !important; }


/* ═══════════════════════════════════════════════════════════════════════════
   §15  NOTIFICATION TOAST
   ═══════════════════════════════════════════════════════════════════════════ */

#reward-notification {
  position: fixed; top: 20px; right: 20px; color: var(--color-white);
  padding: 15px 25px; border-radius: var(--radius-xl) !important;
  box-shadow: var(--shadow-lg) !important; z-index: var(--z-toast);
  font-size: var(--text-xl); font-weight: var(--weight-bold);
  opacity: 0; transform: translateY(-20px);
  transition: opacity var(--duration-slow) var(--ease-out),
              transform var(--duration-slow) var(--ease-out);
  border: 1px solid rgba(255,255,255,0.15) !important;
  backdrop-filter: blur(12px); letter-spacing: 0.1px;
  /* FIX (root cause of "chevron / trophy / viewer-count / End Live / add-guest
     all completely unresponsive to taps"): this toast sits at top:20px;
     right:20px — the exact same corner as the live header's icon row.
     opacity:0 hides it visually but does NOT remove it from hit-testing,
     so even fully invisible and not showing any message, it was still a
     full-size fixed element silently absorbing every tap in that corner,
     both in and out of a live stream. Confirmed via a raw click-target
     probe: every tap on that corner reported e.target as #reward-notification,
     never the button underneath. pointer-events:none here means taps pass
     straight through when no toast is showing; .show below re-enables them
     only while a real, visible toast (including tappable "live" toasts) is
     on screen. */
  pointer-events: none;
}
#reward-notification.show { opacity: 1; transform: translateY(0); pointer-events: auto; }

/* Live / SOS notification indicator */
#notif-list > div[title*="join"]:hover { background: rgba(239, 68, 68, 0.05) !important; }


/* ═══════════════════════════════════════════════════════════════════════════
   §16  LIVE STREAM — CONTAINER, CHAT, GIFTS, OVERLAYS
   ═══════════════════════════════════════════════════════════════════════════ */

#go-live-modal-overlay { display: none; position: fixed; inset: 0; width: 100%; height: 100%; background: #000; z-index: var(--z-live); justify-content: center; align-items: center; }

.live-stream-container {
  /* TikTok-style: the live view IS the full screen, edge-to-edge,
     no card chrome, no rounding, no margins — not a centered modal.
     Uses --live-vh (set in JS from window.innerHeight, see
     app-live-tiktok-patch.js) instead of 100vh/100dvh: mobile
     WebViews handle dynamic address-bar show/hide inconsistently,
     so vh/dvh units can leave the header rendering partly behind
     the browser chrome and the container falling short of the real
     bottom of the screen (letting the site's own nav bleed through
     underneath). A JS-measured pixel value is the only thing that's
     reliably correct everywhere. 100% is the fallback before JS runs. */
  width: 100%; height: 100%; height: calc(var(--live-vh, 1vh) * 100);
  max-width: none; max-height: none;
  background: #000; border-radius: 0; overflow: hidden;
  box-shadow: none;
  position: relative; color: var(--color-white);
  display: flex; flex-direction: column;
  background-size: cover; background-position: center;
  justify-content: space-between; z-index: 4;
}
.live-stream-container::before { content: ''; position: absolute; inset: 0; background: linear-gradient(to top, rgba(0,0,0,0.8) 0%, rgba(0,0,0,0.3) 50%, transparent 100%); z-index: 1; pointer-events: none; }
.live-header, .live-footer, .live-body { position: relative; z-index: 3; padding: 15px; }

/* FIX: .live-header never actually had flex layout defined anywhere in
   the codebase — .live-host-info and .live-stats were just stacking as
   plain block rows (host info on its own line, stats below it) instead
   of sitting side by side at the top like the TikTok reference. Host
   avatar + name stays on the LEFT (its natural DOM order), stats/viewer
   count/close button on the right — matching the reference and how
   every major live-streaming app places it. */
.live-header {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
}

/* FIX ("scattered header", end-live text overlapping the guest-request
   icon, host name disappearing): the header used to try to cram the host
   name AND every icon (viewer count, rank trophy, guest-request bell, End
   Live) into ONE row, splitting the row's width by percentage between
   .live-host-info and .live-stats. Any time either side needed a little
   more room the other side had to give it up — usually the host name,
   since it was the only thing allowed to shrink. .live-header is now a
   column flex container, so .live-host-info (avatar + name) and .live-stats
   (viewer count / rank / requests / End Live) are simply two separate
   rows, each sized to its own content — not two columns splitting one
   row's width. */
.live-host-info { display: flex; align-items: center; gap: 10px; background: rgba(0,0,0,0.4); padding: 5px 10px; border-radius: var(--radius-pill); cursor: pointer; min-width: 0; max-width: calc(100vw - 70px); }
/* FEATURE ("the dynamic like/love tap count should be beneath the name,
   very small — like TikTok's live tap counter"): #live-like-count-container
   now sits on its own small third line inside .live-host-name-block (see
   index.html), directly under the username, instead of as a pill next to
   the avatar. Being inside the name block means it takes zero width away
   from either .live-host-info or .live-stats — it just wraps onto its own
   line under the text, sized down (no background, tiny font) to read as a
   subtle counter rather than another button. */
.live-host-name-block #live-like-count-container {
    display: block; background: none; padding: 0; margin-top: 1px;
    font-size: 0.66rem; font-weight: 600; color: #ff6b81; opacity: 0.9;
}
.live-host-name-block #live-like-count-container i { margin-right: 3px; font-size: 0.62rem; }
/* FEATURE ("host should carry a circle avatar frame at the top-left, same
   row as the name"): a two-tone gradient ring around the host avatar,
   matching the reference screenshot's framed-avatar look, instead of the
   plain flat border it had before. */
#live-host-avatar {
    width: 40px; height: 40px; border-radius: var(--radius-full);
    border: 2.5px solid transparent;
    background: linear-gradient(#1a1a1a,#1a1a1a) padding-box,
                linear-gradient(135deg, var(--accent), #ff6b6b) border-box;
    object-fit: cover;
    box-shadow: 0 0 0 1px rgba(255,255,255,0.15);
    flex-shrink: 0;
}
.live-host-info img { width: 40px; height: 40px; border-radius: var(--radius-full); border: 2px solid var(--accent); flex-shrink: 0; }
/* FIX (bug: "header icons scattered, not arranged professionally" / "reduce
   host name font so all buttons align in the same column"): the name block
   had no width cap, so a long display name grew .live-host-info until it
   crowded .live-stats off the row and forced it to wrap onto a second line
   (see the .live-stats flex-wrap note below). Capping the block's width and
   truncating with an ellipsis keeps the host block a predictable size so
   the stats row has room to stay on one line at normal phone widths. */
.live-host-name-block { min-width: 34px; overflow: hidden; }
.live-host-info strong {
    font-size: 0.92rem;
    display: block;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    /* FEATURE (host/guest display names: "water-white" color + a more
       captivating, distinct font): uses var(--font-display) (Fraunces,
       2026-07-25 rollout — was Playfair Display), so this rides whatever
       the token points to instead of hardcoding a typeface here. */
    color: #F2FAFF;
    font-family: var(--font-display);
    font-style: italic;
    font-weight: 700;
    letter-spacing: 0.2px;
    text-shadow: 0 0 8px rgba(142, 197, 255, 0.35);
}
/* FIX ("remove the username completely, let it show only the host
   name"): #live-host-username used to render a second "@handle" line
   under the bold host name. Hidden outright now so only the host's
   display name shows in the live header. */
.live-host-info #live-host-username {
    display: none !important;
}
@media (max-width: 420px) {
    .live-host-info { padding: 4px 8px; }
    .live-host-info strong { font-size: 0.82rem; }
}
/* Real, functional red heart — the decorative duplicate that used to sit
   here (a second, unstyled <i class="fa-heart">) has been removed from
   index.html entirely; this rule now only targets the one live inside
   .live-stat-item (#live-like-count-container). */
.live-stat-item .fa-heart { color: var(--engagement); }
/* FIX ("header icons should be packed in one row, like TikTok"):
   flex-wrap:wrap let the stats row (trophy / requests bell / viewer
   count / End Live / close) drop onto a second line whenever it ran a
   little wide, which read as scattered/unprofessional. Icons are kept
   compact (see .live-stats .live-stat-item and the small circular
   buttons below) specifically so the whole cluster now fits in one
   single row instead of needing to wrap. */
.live-stats { display: flex; align-items: center; gap: 5px; flex-wrap: nowrap; justify-content: flex-start; max-width: calc(100vw - 30px); }
.live-stats .live-stat-item { padding: 5px 8px; font-size: 0.72rem; }
.live-stats .live-stat-item i, .live-stats .live-stat-item svg { margin-right: 3px; }

/* FEATURE ("notification when new members join live, first circle avatar
   indicates the newest joiner with a premium clapping icon"): overlapping
   avatar stack sourced from the real viewer presence subcollection —
   see attachJoinAvatarListener() in app-live-tiktok-patch.js. */
.tk-join-avatar-stack { display: flex; align-items: center; margin-right: auto; }
.tk-join-avatar { position: relative; width: 26px; height: 26px; border-radius: 50%; border: 2px solid #1a1a1a; margin-right: -10px; background: #333; flex-shrink: 0; }
.tk-join-avatar img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
.tk-join-avatar-new { animation: tkJoinPop 0.5s ease; z-index: 2; }
.tk-clap-badge { position: absolute; top: -10px; right: -8px; font-size: 0.85rem; animation: tkClapFlash 2.2s ease forwards; }
.tk-join-count-pill { background: rgba(0,0,0,0.55); border: 1px solid rgba(255,255,255,0.25); color: #fff; font-size: 0.72rem; border-radius: var(--radius-pill); padding: 2px 8px; margin-left: 12px; }
@keyframes tkJoinPop { 0% { transform: scale(0.4); opacity: 0; } 60% { transform: scale(1.15); opacity: 1; } 100% { transform: scale(1); } }
@keyframes tkClapFlash { 0% { opacity: 0; transform: scale(0.5) rotate(-15deg); } 15% { opacity: 1; transform: scale(1.2) rotate(10deg); } 30% { transform: scale(1) rotate(0deg); } 85% { opacity: 1; } 100% { opacity: 0; } }
/* FIX (bug: End Live button + trailing icons clipped off-screen on phone widths):
   .live-stream-container has overflow:hidden (needed to keep the video edge-to-edge),
   and .live-stats used to be a single non-wrapping row. On a phone-width screen the
   row (heart count, viewer count, requests bell, trophy, End Live, x) is wider than
   the available space, so it silently overflowed past the right edge and got clipped
   by the ancestor's overflow:hidden -- nothing was visibly broken, the controls were
   just off-screen. flex-wrap:wrap lets it drop onto a second line instead of being
   cut off, and the items shrink individually via .live-stat-item below. */
.live-stat-item, .tk-host-req-btn, .tk-end-live-btn, #live-close-btn { flex-shrink: 0; }
@media (max-width: 420px) {
  .live-stats { gap: 5px; }
  .live-stat-item { padding: 6px 8px; font-size: var(--text-sm, 0.8rem); }
  .tk-end-live-btn { width: 30px !important; height: 30px !important; }
}
.live-stat-item { background: rgba(0,0,0,0.4); padding: 8px 12px; border-radius: var(--radius-2xl); font-weight: var(--weight-bold); font-size: var(--text-md); cursor: pointer; }
.live-stat-item i { margin-right: 5px; }
.live-stat-item.recording { color: var(--danger-color); animation: pulse 1.5s infinite; }

/* FEATURE ("implement tap-counting on the heart icon, bubble animation with
   an indicator when tapping stops, TikTok-style"): #live-like-count-container
   gets a brief scale pulse per tap (feels responsive to rapid taps), and a
   floating "+N" combo badge appears above it, growing with the tap streak,
   then fades out ~700ms after the last tap — mirroring TikTok's like-burst
   behavior. See the click handler in app-live-tiktok-patch.js. */
#live-like-count-container { position: relative; transition: transform 0.12s ease; }
#live-like-count-container.tk-like-pulse { transform: scale(1.18); }
.tk-like-burst {
    position: absolute; top: -22px; left: 50%; transform: translateX(-50%);
    background: rgba(var(--color-pink-rgb), 0.92); color: #fff; font-size: 0.72rem; font-weight: 800;
    padding: 2px 8px; border-radius: var(--radius-pill, 50px);
    pointer-events: none; white-space: nowrap;
    animation: tkLikeBurstPop 0.75s ease forwards;
}
@keyframes tkLikeBurstPop {
    0%   { opacity: 0; transform: translateX(-50%) translateY(4px) scale(0.7); }
    20%  { opacity: 1; transform: translateX(-50%) translateY(0) scale(1.08); }
    70%  { opacity: 1; }
    100% { opacity: 0; transform: translateX(-50%) translateY(-10px) scale(1); }
}

.live-body { flex-grow: 1; display: flex; flex-direction: column-reverse; overflow: hidden; position: relative; }
.live-body .main-host-video { height: 100%; width: 100%; position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; pointer-events: none; z-index: 2; background: transparent; }
.live-body .main-host-video video { width: 100%; height: 100%; object-fit: cover; pointer-events: auto; background: transparent; }
.live-body .main-host-video img { width: 100%; height: 100%; object-fit: cover; background: #222; display: none; pointer-events: auto; }

.live-comments-container { max-height: 50vh; overflow-y: auto; display: flex; flex-direction: column-reverse; -ms-overflow-style: none; scrollbar-width: none; padding: 0 15px; z-index: 3; pointer-events: auto; -webkit-overflow-scrolling: touch; }
.live-comments-container::-webkit-scrollbar { display: none; }
.live-comment { background: rgba(0,0,0,0.3); padding: 8px 12px; border-radius: var(--radius-md); margin-bottom: 8px; animation: slideInUp 0.3s; align-self: flex-start; max-width: 90%; display: flex; align-items: flex-start; gap: 8px; transition: opacity 0.4s ease; }
.live-comment.pinned-comment { border: 2px solid var(--accent); background: rgba(10,14,39,0.7); }
.live-comment strong {
    /* FEATURE (host/guest display names: water-white + distinct font) --
       was var(--accent) (gold), which visually competed with the gold gift
       captions/icons on the same row; water-white reads as its own,
       distinct "name" treatment instead. */
    color: #F2FAFF;
    font-size: var(--text-md);
    font-family: var(--font-display);
    font-style: italic;
    font-weight: 700;
    text-shadow: 0 0 6px rgba(142, 197, 255, 0.3);
}
.live-comment p { font-size: var(--text-lg); margin: 2px 0 0; word-wrap: break-word; white-space: pre-wrap; }

/* FIX (missing entirely — referenced in app-fixes.js's createLiveComment
   but never defined anywhere in the codebase): the small circular avatar
   next to each chat line, and the body column holding name + text. */
.live-comment-avatar { width: 26px; height: 26px; border-radius: 50%; object-fit: cover; flex-shrink: 0; margin-top: 1px; border: 1px solid rgba(255,255,255,0.25); }
.live-comment-body { display: flex; flex-direction: column; min-width: 0; }

/* FEATURE (fade-after-4): the newest 4 comments stay fully readable;
   anything older fades toward transparent ("into the cloud") but the
   list stays scrollable (overflow-y:auto is already set on
   .live-comments-container) so older messages can still be read by
   scrolling up. */
.live-comment.tk-comment-faded { opacity: 0.28; }
.live-comment.tk-comment-faded:hover, .live-comment.tk-comment-faded:active { opacity: 0.9; }

/* FIX (missing entirely — referenced in app-fixes.js's createLiveGiftComment
   but never defined anywhere): the TikTok-style "sent {gift}" row with a
   name, caption, and a right-aligned icon + ×N multiplier that pulses
   when the same person sends the same gift again in a row. */
.live-comment.tk-gift-comment { background: linear-gradient(90deg, rgba(255, 213, 0,0.18), rgba(0,0,0,0.3)); border: 1px solid rgba(255, 213, 0,0.35); align-items: center; }
.tk-gift-caption { font-size: var(--text-md); color: var(--accent); margin-top: 1px; }
.tk-gift-icon-count { margin-left: auto; display: flex; align-items: center; gap: 4px; flex-shrink: 0; padding-left: 10px; }
.tk-gift-emoji { font-size: 1.4rem; line-height: 1; }
.tk-gift-multiplier { font-weight: 700; color: var(--accent); font-size: var(--text-lg); }
.tk-gift-comment.tk-gift-pulse { animation: tkGiftPulse 0.4s ease; }
@keyframes tkGiftPulse { 0% { transform: scale(1); } 40% { transform: scale(1.06); } 100% { transform: scale(1); } }

.live-footer { display: flex; flex-wrap: nowrap; gap: 10px; align-items: center; z-index: 3; }
.live-footer form { flex-grow: 1; min-width: 0; display: flex; gap: 10px; }
.live-footer input { flex-grow: 1; min-width: 0; background: rgba(0,0,0,0.4); border: 1px solid #555; border-radius: var(--radius-pill); padding: 12px 20px; color: var(--color-white); }
.live-footer .live-action-btn { background: rgba(0,0,0,0.4); width: 45px; height: 45px; border-radius: var(--radius-full); display: flex; align-items: center; justify-content: center; font-size: var(--text-2xl); color: var(--color-white); cursor: pointer; border: 1px solid #555; flex-shrink: 0; }

/* Inline SVG send/share icons — render identically with or without the
   Font Awesome CDN (screenshots showed plain Unicode fallback glyphs
   instead of real icons, suggesting FA wasn't loading reliably; SVG has
   no such dependency). stroke uses currentColor so it automatically
   follows the button's existing color/gold-highlight treatment. */
.tk-icon-svg { width: 18px; height: 18px; display: block; }

.live-footer form button[type="submit"] { flex-shrink: 0; }
#live-gift-btn { color: var(--accent); }

/* Live fullscreen button */
.live-fullscreen-btn { position: absolute; bottom: 80px; right: 12px; background: rgba(255,255,255,0.18); backdrop-filter: blur(8px); border: 1.5px solid rgba(255,255,255,0.3); border-radius: var(--radius-md); color: var(--color-white); padding: 8px 12px; cursor: pointer; font-size: var(--text-lg); z-index: 20; transition: var(--transition-base); }
.live-fullscreen-btn:hover { background: rgba(255,255,255,0.28); }

/* Gift animation layer */
#gift-animation-layer { position: absolute; inset: 0; z-index: 3; pointer-events: none; overflow: hidden; }

/* ═══════════════════════════════════════════════════════════════════════
   FLOATING GIFT ANIMATION — SINGLE SOURCE OF TRUTH (session 2026-07-19,
   fifth follow-up)

   This entire block used to be injected at runtime by app-gifts.js via a
   dynamically-created <style> tag. Moved here, into the statically linked
   stylesheet, because a runtime-injected <style> tag has failure modes a
   linked stylesheet doesn't: it can be silently dropped by a strict
   Content-Security-Policy style-src directive (this app's Helmet config
   has already silently blocked things before — see the Agora SDK CSP fix
   in an earlier session), it depends on winning a DOM-insertion-order
   race against this file for any selector both declare, and it never
   runs at all if anything earlier in that IIFE throws. None of those
   apply to a <link>-ed stylesheet. showGiftAnimation() / triggerGiftAnimation()
   (app-gifts.js, app-fixes.js) still add the 'gift-animation-small' /
   'gift-animation-token' classes at send-time using EMPY_GIFT_CATALOG's
   own stamped .tier — only where the CSS that responds to those classes
   lives has changed. Do not re-add any of this to app-gifts.js's
   injected <style> block; this is now the ONLY copy.
   ═══════════════════════════════════════════════════════════════════════ */
@keyframes giftFloat {
    from { opacity:1; transform:translateY(0) scale(1); }
    to   { opacity:0; transform:translateY(-130px) scale(1.6); }
}
@keyframes heartMill {
    0%   { opacity:0; transform:translateY(0)      scale(0.6) rotate(0deg); }
    15%  { opacity:1; }
    100% { opacity:0; transform:translateY(-200px) scale(1.2) rotate(30deg); }
}
/* TikTok-style horizontal drift for small-tier gifts — single unbroken
   direction, no zigzag, no vertical climb (see history below).
   FIX (session 2026-07-19, seventh follow-up — "too small, increase to
   normal size 45px"): the 0.42→0.5 scale here was shrinking the gift on
   TOP of the already-reduced 22px box further still. Now that the box
   itself is back to the normal 45px (see .gift-animation-small below),
   the scale only needs a small, purely decorative zoom (1→1.08) so the
   gift stays at its actual 45px size throughout the drift instead of
   being scaled back down to a sliver of it. */
@keyframes giftFloatSmall {
    0%   { opacity: 1; transform: translate(0,0)    scale(1);    }
    100% { opacity: 0; transform: translate(60px,0) scale(1.08); }
}
@keyframes giftFloatSmallLeft {
    0%   { opacity: 1; transform: translate(0,0)     scale(1);    }
    100% { opacity: 0; transform: translate(-60px,0) scale(1.08); }
}
.gift-animation {
    position: absolute;
    bottom: 80px;
    font-size: 2.5rem;
    z-index: 10;
    pointer-events: none;
    animation: giftFloat 2.2s ease-out forwards;
    filter: drop-shadow(0 4px 10px rgba(0,0,0,0.35));
}
.heart-mill-animation {
    position: absolute;
    bottom: 60px;
    font-size: 1.6rem;
    z-index: 10;
    pointer-events: none;
    animation: heartMill 2.8s ease-out forwards;
}
/* Image-based gifts (Rose, Empy Token) have no intrinsic em-based sizing
   like the emoji/SVG glyphs do, so they need an explicit box here. */
.gift-animation .tk-rose-img,
.gift-animation .tk-empy-token-img {
    width: 45px !important; height: 45px !important; display: block; object-fit: contain;
}
/* Small-tier gifts ('basic'/'rare', i.e. under the 'epic' 120-EMPY
   threshold _tierForPrice() in app-gifts.js uses) float with far less
   magnification and a horizontal drift instead of the big vertical rise
   + zoom every gift used to get regardless of value. */
.gift-animation.gift-animation-small {
    /* Normal size (session 2026-07-19, seventh follow-up) — was 1.3rem,
       which read as too small to be "conspicuous." Matches the base
       .gift-animation glyph size below. */
    font-size: 2.5rem !important;
    animation: giftFloatSmall 2.4s ease-out forwards !important;
}
.gift-animation.gift-animation-small:nth-child(even) {
    animation-name: giftFloatSmallLeft !important;
}
.gift-animation.gift-animation-small .tk-rose-img,
.gift-animation.gift-animation-small .tk-empy-token-img {
    /* Normal size (was 22px) — matches the 45px used for image-based
       gifts (Rose, Empy Token) everywhere else in .gift-animation. */
    width: 45px !important; height: 45px !important;
}
/* Forced leftward drift when the gift is anchored at the guest-box
   avatar tile (#tk-guestbox-stack sits near the right edge of the
   screen — see showGiftAnimation() in app-fixes.js) — drifting right
   from that position would carry the gift off-screen almost
   immediately, so this always overrides the even/odd left/right
   alternation above for avatar-anchored gifts specifically. */
.gift-animation.gift-animation-small.gift-animation-avatar-anchor {
    animation-name: giftFloatSmallLeft !important;
}
/* FIX (session 2026-07-19, eighth follow-up) — mirror-image case: when
   there are no accepted guests yet, showGiftAnimation() (app-fixes.js)
   now falls back to anchoring at #live-host-avatar (top-LEFT header
   badge) instead of a random bottom-of-screen spot. That anchor sits
   at the opposite edge from the guest-box case above, so the SAME
   forced-left override would carry it straight off the left edge of
   the screen. Forces the opposite (rightward) drift for this specific
   anchor instead — same override mechanism, mirrored direction. */
.gift-animation.gift-animation-small.gift-animation-host-anchor {
    animation-name: giftFloatSmall !important;
}
/* FIX (session 2026-07-19, eighth follow-up) — the circular-crop
   workaround below is no longer needed. It existed because Empy
   Token's source image used to be a flat JPEG (no transparency
   channel) with a square background baked into the pixels; cropping to
   a circle here hid that square. The source asset (app-gifts.js's
   EMPY_TOKEN_IMG_DATA_URI) has since been re-exported as a real
   transparent PNG — see that file's own comment — so there is no
   background left to hide, and forcing a circular mask on top of an
   already-transparent, already-round coin image only risks clipping
   its outer edge/rim for no reason. Neutralized rather than deleted,
   so this class remains harmless if ever re-added: it no longer forces
   any crop, matching how Rose (also transparent) has always been left
   alone in this same .gift-animation context.
.gift-animation.gift-animation-token .tk-empy-token-img {
    border-radius: 50%; object-fit: cover; background: transparent; box-shadow: none;
}
*/
.heart-mill-animation { position: absolute; bottom: 0; font-size: 1.5rem; color: var(--danger-color); opacity: 0; animation: floatUpHearts 4s ease-out forwards; pointer-events: none; text-shadow: 0 0 5px rgba(255,255,255,0.5); will-change: transform, opacity; }
.like-bubble { position: absolute; bottom: 80px; right: 20px; font-size: 2rem; color: var(--danger-color); animation: bubbleUp 1.5s ease-out forwards; opacity: 0.8; pointer-events: none; }

/* FIX: the host-screen love-bubble tap (app-fixes.js isClickOnBackground
   handler) references an animation called likeBubblePop that was only ever
   defined in app-patch-v7.js, a file not present in this codebase copy.
   Without a matching @keyframes rule the browser silently no-ops the
   animation — the heart span still gets created and removed by its own
   JS timeout, but it never floats or fades, so tapping looked broken.
   Defining it here (once, in the base stylesheet) makes the tap-to-like
   heart actually rise and fade regardless of whether app-patch-v7.js
   is present. UPDATE: app-patch-v7.js has since been provided and also
   defines this keyframe (its version loads later, so it's the one that
   actually applies in practice) — this stays as a fallback in case that
   file is ever missing again, same defense-in-depth pattern already used
   for the offline Font Awesome fallback in index.html. */
@keyframes likeBubblePop {
    0%   { transform: translateY(0) scale(0.6); opacity: 0; }
    15%  { transform: translateY(-10px) scale(1.15); opacity: 1; }
    30%  { transform: translateY(-30px) scale(1); opacity: 1; }
    100% { transform: translateY(-160px) scale(0.85); opacity: 0; }
}


/* Gift catalog & viewers modals */
#live-gift-catalog-modal, #live-viewers-modal, #live-pin-message-modal { display: none; position: absolute; bottom: 0; left: 0; width: 100%; height: 50%; background: #2a2a2e; border-top-left-radius: 20px; border-top-right-radius: 20px; z-index: 4; padding: 20px; flex-direction: column; animation: slideUpModal 0.3s; }
#live-gift-catalog-modal.show, #live-viewers-modal.show, #live-pin-message-modal.show, #live-guest-requests-modal.show { display: flex; }
#live-gift-catalog-modal h3, #live-viewers-modal h3, #live-pin-message-modal h3, #live-guest-requests-modal h3 { text-align: center; margin-bottom: 15px; }
.gift-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(80px, 1fr)); gap: 15px; overflow-y: auto; }
.gift-item { display: flex; flex-direction: column; align-items: center; justify-content: center; background: #3c3c42; padding: 10px; border-radius: var(--radius-md); cursor: pointer; transition: var(--transition-base); }
.gift-item:hover, .gift-item.selected { background: var(--secondary); }
.gift-item .symbol { font-size: 2rem; }
.gift-item .price { font-size: var(--text-sm); font-weight: var(--weight-bold); color: var(--accent); margin-top: 5px; }
.gift-quick-item { display: flex; flex-direction: column; align-items: center; justify-content: center; background: rgba(255,255,255,0.08); border-radius: var(--radius-md); padding: 6px 5px; cursor: pointer; transition: var(--transition-base); border: 1px solid rgba(255,255,255,0.1); }
.gift-quick-item:hover { background: var(--secondary); }
.gift-quick-item .g-sym { font-size: var(--text-3xl); }
.gift-quick-item .g-price { font-size: 0.62rem; color: var(--accent); font-weight: var(--weight-bold); }

/* Viewer list */
.viewer-list { overflow-y: auto; }
.viewer-item { display: flex; align-items: center; gap: 15px; padding: 10px; border-bottom: 1px solid #444; }
.viewer-item:last-child { border-bottom: none; }
.viewer-item img { width: 40px; height: 40px; border-radius: var(--radius-full); }
.viewer-item-info { flex-grow: 1; }
.viewer-actions button { background: var(--secondary); border: none; color: var(--color-white); padding: 5px 10px; border-radius: 15px; font-size: var(--text-sm); cursor: pointer; }

/* Host avatar */
#host-avatar-container { position: absolute; top: 10px; left: 15px; z-index: 5; width: 60px; height: 60px; border-radius: var(--radius-full); overflow: hidden; display: none; justify-content: center; align-items: center; background: rgba(0,0,0,0.5); border: 2px solid var(--accent); }
#host-avatar-container img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius-full); }
#host-avatar-toggle-btn-inner { display: none; }

/* Multi-guest container */
/* FIX (root cause of guest boxes overlapping the End Live button):
   this container used to sit at top:10px, the exact same corner as
   .live-stats (viewer count, trophy, group icon, add-friend, and the
   red End Live button) -- identical disease to the one already fixed
   for #tk-guestbox-stack by moving it to top:112px. Applying the same,
   already-proven offset here so the persistent guest/pending/self
   boxes never sit on top of the header controls. */
/* FIX 2026-07-16: moved from right:10px to left:10px — app-live-final.js's
   injected override (the authoritative position, see its own [9] STYLES
   section) now docks this to the left edge so it can never overlap
   app-live-tiktok-patch.js's #tk-guestbox-stack vertical box, which owns
   the right edge. Matched here too so there's no flash of the old
   right-edge position before that script runs. */
#multi-guest-container { position: absolute; top: 98px; left: 10px; right: auto; z-index: 3; width: 150px; height: auto; max-height: 62%; background: rgba(0,0,0,0.4); border-radius: var(--radius-md); padding: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.5); display: flex; flex-direction: column; gap: 8px; overflow-y: auto; pointer-events: auto; }
#multi-guest-container:empty { display: none; }
#multi-guest-slots { display: flex; flex-direction: column; gap: 8px; }
.guest-slot { width: 100%; height: 100px; background: rgba(255,255,255,0.1); border: 1px solid rgba(255,255,255,0.3); border-radius: var(--radius-md); position: relative; overflow: hidden; display: flex; align-items: center; justify-content: center; color: var(--color-white); font-size: var(--text-md); flex-shrink: 0; pointer-events: auto; }
.guest-slot.active-video { border-color: var(--accent); }
.guest-slot video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.guest-slot .guest-avatar-placeholder { object-fit: cover; width: 100%; height: 100%; position: absolute; inset: 0; background: rgba(0,0,0,0.7); }
.guest-slot .guest-controls { position: absolute; bottom: 5px; right: 5px; display: flex; gap: 5px; background: rgba(0,0,0,0.6); border-radius: var(--radius-sm); padding: 3px; }
.guest-slot .guest-controls button { background: none; border: none; color: var(--color-white); font-size: var(--text-md); cursor: pointer; padding: 2px 4px; }
.guest-slot .guest-controls button:hover { color: var(--accent); }
.guest-slot .guest-username { position: absolute; top: 5px; left: 5px; background: rgba(0,0,0,0.6); padding: 2px 8px; border-radius: var(--radius-sm); font-size: var(--text-sm); font-weight: var(--weight-bold); color: var(--color-white); }
.guest-slot.empty { opacity: 0.7; border-style: dashed; }

/* Live overlay boxes */
.live-overlay-box { position: absolute; z-index: 5; background: rgba(0,0,0,0.6); color: var(--color-white); padding: 10px 15px; border-radius: var(--radius-md); box-shadow: 0 2px 10px rgba(0,0,0,0.5); display: flex; align-items: center; gap: 10px; font-weight: var(--weight-bold); font-size: var(--text-md); transition: var(--transition-slow); }
#live-goals-display { top: 60px; left: 15px; flex-direction: column; align-items: flex-start; padding: 10px 15px 5px 15px; width: auto; max-width: calc(100% - 30px); }
#live-goals-display .progress-bar { width: 150px; }
#live-fan-club-display { top: 130px; left: 15px; }
#live-games-display { top: 200px; left: 15px; }
#live-pinned-message-display { bottom: 80px; left: 15px; width: calc(100% - 30px); justify-content: space-between; align-items: flex-start; padding: 8px 12px; font-size: var(--text-md); z-index: 6; }
#live-pinned-message-display .pinned-content { flex-grow: 1; }
#live-pinned-message-display .close-pinned-msg { background: none; border: none; color: var(--color-white); font-size: var(--text-lg); cursor: pointer; padding: 0; margin-left: 10px; }

/* Host control panel */
/* FIX: previously the transform:translateX(-100%) collapse state lived on
   #host-control-panel itself, and #host-control-toggle-btn was a CHILD of
   that same element. .live-stream-container has overflow:hidden, so the
   collapsed panel carried its own toggle button off the left edge of the
   screen with it -- there was nothing left on-screen to tap to expand it.
   Now the panel wrapper stays put at left:0 (untransformed) and only the
   inner button stack (#host-control-panel-inner) slides; the toggle button
   is a sibling, not a child of the sliding part, so it's always visible. */
/* FIX (root cause of "Chevron host control panel not clickable at all"):
   app-live-tiktok-patch.js raises `.live-stream-container > .live-header` to
   z-index:9 (to fix the guestbox-stack covering the header). #host-control-panel
   is a SIBLING of .live-header, not a child of it, and both occupy the same
   top-left corner of the container. It was left at z-index:6 — below the
   header's 9 — so the header (a full-width block) has silently sat on top of
   the toggle button ever since, swallowing every tap before it could reach
   the button underneath, even though the chevron icon still renders visually.
   Raising the panel above the header (and above the guestbox-stack at
   z-index:6) restores it to being actually clickable. */
#host-control-panel { position: absolute; top: 10px; left: 0; z-index: 11; display: flex; align-items: flex-start; }
#host-control-toggle-btn { background: rgba(0,0,0,0.5); color: var(--color-white); border: none; border-radius: 0 var(--radius-md) var(--radius-md) 0; padding: 8px 12px; font-size: var(--text-xl); cursor: pointer; flex-shrink: 0; }
/* Reveals via max-width/opacity instead of translateX so nothing ever moves
   off-canvas into the clipped region of .live-stream-container (overflow:hidden) */
#host-control-panel-inner { background: rgba(0,0,0,0.5); border-radius: 0 var(--radius-md) var(--radius-md) 0; padding: 0 5px; display: flex; flex-direction: column; gap: 5px; max-width: 0; opacity: 0; overflow-x: hidden; overflow-y: auto; transition: max-width var(--duration-slow) var(--ease-in-out), opacity var(--duration-slow) var(--ease-in-out), padding var(--duration-slow) var(--ease-in-out);
  /* FIX (2026-08-02 — "button list too long to reach"): the button column
     has grown across v42/v50-v59 (mic/video/desktop/goal/star/gamepad/pin
     plus clap/chat-mode/poll/PK-battle/sound/beauty/product-pin/snapshot/
     watermark) well past a single screen's height on most phones. This
     was never height-capped, so once the panel's own content ran taller
     than the space between the header and the bottom of the live screen,
     it just kept extending off the bottom of .live-stream-container
     (overflow:hidden on that ancestor silently clipped the rest — nothing
     to scroll to, buttons simply unreachable). Capping the height and
     switching to overflow-y:auto keeps every button on screen and
     reachable by scrolling this one column, without disturbing the
     existing max-width/opacity slide-open animation (overflow-x stays
     hidden so that horizontal transition is untouched). Uses the same
     --live-vh JS-measured value .live-stream-container itself relies on
     (see that rule's own comment) rather than 100vh, for the same mobile
     address-bar-chrome reason. */
  max-height: calc((var(--live-vh, 1vh) * 100) - 130px);
  scrollbar-width: thin; scrollbar-color: rgba(255,255,255,0.35) transparent;
}
#host-control-panel-inner::-webkit-scrollbar { width: 4px; }
#host-control-panel-inner::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.35); border-radius: var(--radius-full); }
#host-control-panel.expanded #host-control-panel-inner { max-width: 55px; opacity: 1; padding: 5px; }
#host-control-panel .live-action-btn { background: rgba(0,0,0,0.6); width: 45px; height: 45px; border-radius: var(--radius-full); display: flex; align-items: center; justify-content: center; font-size: var(--text-2xl); color: var(--color-white); cursor: pointer; border: 1px solid #555; flex-shrink: 0; transition: var(--transition-base); }
#host-control-panel .live-action-btn:hover { background: var(--secondary); transform: scale(1.05); }

/* FIX (2026-08-02 — help-center "?" FAB floating over the live screen):
   self-help-assistance-center.js's #emp-help-fab is position:fixed and
   appended straight to <body>, so it renders on top of every screen in
   the app, live-stream included, where it has nothing to do with the
   live UI it's floating over. body.emp-live-active is toggled by the
   new app-patch-v60 module (see app-patch-v42.js's end) in sync with
   #go-live-modal-overlay's own .show class. */
body.emp-live-active #emp-help-fab { display: none !important; }

/* Live sub-modals */
.live-sub-modal { display: none; position: absolute; bottom: 0; left: 0; width: 100%; height: 50%; background: #2a2a2e; border-top-left-radius: 20px; border-top-right-radius: 20px; z-index: 7; padding: 20px; flex-direction: column; animation: slideUpModal 0.3s; color: var(--color-white); box-shadow: 0 -5px 20px rgba(0,0,0,0.5); }
.live-sub-modal.show { display: flex; }
.live-sub-modal h3 { text-align: center; margin-bottom: 15px; color: var(--color-white); }
.live-sub-modal label { color: #eee; }
.live-sub-modal input[type="text"], .live-sub-modal input[type="number"], .live-sub-modal textarea { background: #3c3c42; border: 1px solid #555; color: var(--color-white); padding: 8px 12px; border-radius: var(--radius-sm); width: 100%; margin-bottom: 10px; }
.live-sub-modal .btn { width: 100%; margin-top: 10px; }
.live-game-btn { background: var(--secondary); color: var(--color-white); padding: 12px; border-radius: var(--radius-md); }
.live-game-btn:hover { background: var(--primary); }

/* Pin message choices */
.pin-message-choice { background: #3c3c32; padding: 10px; border-radius: var(--radius-md); margin-bottom: 8px; cursor: pointer; transition: var(--transition-base); display: flex; flex-direction: column; gap: 5px; }
.pin-message-choice:hover, .pin-message-choice.selected { background: var(--secondary); }
.pin-message-choice strong { color: var(--accent); font-size: var(--text-md); }
.pin-message-choice p { font-size: var(--text-base); margin: 0; color: #ccc; }

/* Background selector */
#go-live-form #live-bg-selector { display: flex; gap: 10px; overflow-x: auto; padding-bottom: 10px; margin-top: 10px; }
#go-live-form .bg-thumb { width: 80px; height: 120px; border-radius: var(--radius-md); flex-shrink: 0; cursor: pointer; border: 3px solid transparent; background-size: cover; background-position: center; }
#go-live-form .bg-thumb img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius-sm); }
#go-live-form .bg-thumb.active { border-color: var(--primary); }
#dashboard-live-container { display: block; }


/* ═══════════════════════════════════════════════════════════════════════════
   §17  FULL-SCREEN REEL VIEWER
   ═══════════════════════════════════════════════════════════════════════════ */

#reel-viewer-modal-overlay { display: none; position: fixed; inset: 0; background: #000; z-index: var(--z-live); }
.reel-viewer-container { width: 100%; height: 100%; overflow-y: auto; scroll-snap-type: y mandatory; }
.reel-viewer-item { width: 100%; height: 100%; position: relative; scroll-snap-align: start; display: flex; align-items: center; justify-content: center; }
.reel-viewer-item video { width: 100%; height: 100%; object-fit: contain; }
.reel-viewer-close { position: absolute; top: 20px; left: 20px; font-size: var(--text-5xl); color: var(--color-white); background: rgba(0,0,0,0.5); border: none; border-radius: var(--radius-full); width: 40px; height: 40px; cursor: pointer; z-index: 10; }
.reel-viewer-info { position: absolute; bottom: 20px; left: 20px; right: 20px; color: var(--color-white); z-index: 5; text-shadow: 1px 1px 3px rgba(0,0,0,0.7); display: flex; justify-content: space-between; align-items: flex-end; }
.reel-viewer-actions .action-btn { font-size: var(--text-4xl); color: var(--color-white); background: rgba(0,0,0,0.4) !important; border: none !important; border-radius: var(--radius-full); width: 50px; height: 50px; display: flex; flex-direction: column; align-items: center; justify-content: center; text-decoration: none; }
.reel-viewer-actions .action-btn span { font-size: var(--text-sm); margin-top: 4px; }


/* ═══════════════════════════════════════════════════════════════════════════
   §18  PROFILE — HEADER, PICTURE, TABS, GALLERY, BIO
   ═══════════════════════════════════════════════════════════════════════════ */

.profile-header-container { position: relative; }
.cover-photo-container { height: 250px; background: var(--light-gray); position: relative; border-radius: var(--radius-md) var(--radius-md) 0 0; overflow: hidden; background-size: cover; background-position: center; }
.cover-photo-container img { width: 100%; height: 100%; object-fit: cover; }
.cover-photo-container .upload-overlay { position: absolute; top: 10px; right: 10px; z-index: 2; background: rgba(0,0,0,0.5); color: var(--color-white); padding: 5px 10px; border-radius: var(--radius-sm); font-size: var(--text-md); cursor: pointer; }
.profile-header { display: flex; align-items: flex-end; gap: 20px; flex-wrap: wrap; padding: 0 25px 25px; transform: translateY(-50px); }
.profile-header-info { flex-grow: 1; padding-top: 50px; }
.profile-header-actions { display: flex; gap: 10px; margin-top: 10px; }
.profile-pic-container { position: relative; flex-shrink: 0; align-self: flex-start; }
.profile-pic { width: var(--avatar-4xl); height: var(--avatar-4xl); border-radius: var(--radius-full); object-fit: cover; border: 4px solid var(--color-white) !important; box-shadow: 0 8px 32px rgba(10,14,39,0.2) !important; }
.badge { background: var(--g-teal) !important; color: var(--color-white); padding: 4px 10px; border-radius: 15px; font-size: var(--text-md); font-weight: var(--weight-bold); display: inline-flex; align-items: center; gap: 5px; box-shadow: var(--shadow-teal) !important; }

/* Profile tabs */
.profile-tabs { display: flex; border-bottom: 1px solid var(--light-gray); margin-top: -30px; }
.profile-tab { padding: 15px 25px; cursor: pointer; font-weight: var(--weight-semibold); color: var(--color-neutral-500); border-bottom: 3px solid transparent; }
.profile-tab.active { color: var(--primary); border-bottom-color: var(--primary); }
.profile-tab-content { display: none; padding: 25px 0 0 0; }
.profile-tab-content.active { display: block; animation: fadeIn 0.4s; }

/* Profile gallery */
#profile-gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 15px; }
.gallery-item { position: relative; height: 200px; border-radius: var(--radius-md); overflow: hidden; cursor: pointer; background: var(--color-neutral-100); }
.gallery-item img, .gallery-item video { width: 100%; height: 100%; object-fit: cover; }

/* Profile bio */
#profile-extended-info { display: none; margin-top: 20px; }
#profile-bio { min-height: auto; max-height: 60px; transition: max-height var(--duration-slow) var(--ease-out); overflow: hidden; }
#profile-bio.expanded { max-height: 200px; }
.bio-container { position: relative; }
#toggle-bio-btn, #toggle-profile-info-btn { font-size: var(--text-md); color: var(--primary); text-decoration: underline; cursor: pointer; margin-top: 5px; display: inline-block; background: none; border: none; padding: 0; }
#toggle-profile-info-btn { margin-top: 15px; font-weight: var(--weight-bold); }

/* Marketplace gallery modal */
#marketplace-gallery-modal { z-index: 7000; }
.gallery-modal-content { max-width: 90vw; max-height: 90vh; background: #111; padding: 15px; text-align: center; }
.gallery-main-image-container { width: 100%; height: 70vh; display: flex; align-items: center; justify-content: center; margin-bottom: 15px; position: relative; }
.gallery-main-image-container img, .gallery-main-image-container video { max-width: 100%; max-height: 100%; object-fit: contain; }
/* Gallery prev/next arrow buttons removed per request — full-view media
   navigation is swipe/touch only (see app-fixes.js touchstart/touchend
   handlers on .gallery-main-image-container) plus arrow keys on desktop.
   #gallery-prev-btn/#gallery-next-btn no longer exist in index.html. */
.gallery-thumbnails { display: flex; gap: 10px; justify-content: center; overflow-x: auto; padding-bottom: 5px; }
.gallery-thumbnail { width: 80px; height: 80px; cursor: pointer; border: 2px solid transparent; border-radius: var(--radius-md); overflow: hidden; }
.gallery-thumbnail img, .gallery-thumbnail video { width: 100%; height: 100%; object-fit: cover; }
.gallery-thumbnail.active { border-color: var(--accent); }

/* Media lightbox */
#media-lightbox { animation: lbFadeIn 0.18s ease; }
#lb-img { transition: opacity var(--duration-base) var(--ease-out); }


/* ═══════════════════════════════════════════════════════════════════════════
   §19  SUGGESTED USERS WIDGET
   ═══════════════════════════════════════════════════════════════════════════ */

#suggested-users-container { margin-top: 20px; overflow: hidden; padding: 0 !important; }
#suggested-users-container .horizontal-slider-container { position: relative; }
#suggested-users-slider { display: flex; flex-direction: row; overflow-x: auto; overflow-y: hidden; scroll-behavior: smooth; -webkit-overflow-scrolling: touch; scroll-snap-type: x mandatory; gap: 0; padding: 0 0 14px 0; scrollbar-width: none; -ms-overflow-style: none; cursor: grab; }
#suggested-users-slider:active { cursor: grabbing; }
#suggested-users-slider::-webkit-scrollbar { display: none; }
#suggested-users-slider > * { scroll-snap-align: start; flex-shrink: 0; }

.suggested-user-card { flex: 0 0 100%; min-width: 100%; max-width: 100%; width: 100%; text-align: left; background: var(--color-white); border-radius: var(--radius-2xl); box-shadow: 0 2px 14px rgba(10,14,39,0.10); border: 1px solid var(--border); overflow: visible; position: relative; cursor: pointer; transition: var(--shadow-md); white-space: normal; -webkit-tap-highlight-color: transparent; display: flex; flex-direction: column; }
.suggested-user-card:hover, .suggested-user-card:active { box-shadow: 0 6px 28px rgba(10,14,39,0.15); }
.suggested-user-cover { position: relative; width: 100%; height: 155px; min-height: 155px; background: var(--g-navy); background-size: cover; background-position: center; display: block; flex-shrink: 0; overflow: hidden; border-radius: var(--radius-2xl) var(--radius-2xl) 0 0; }
.suggested-user-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* FIX (2026-08-24 — Follow button clipped/cut off on the dashboard
   Suggested For You card): this rule's "top: 168px" was tuned for an
   older card layout (155px cover + a -45px avatar overlap — see the
   .suggested-user-cover/.avatar-placeholder rules just above/below,
   which assume that same older layout). The card markup app-feed.js
   actually builds today uses a 110px cover and a -36px avatar overlap
   — a real design that's ~50-60px shorter than what 168px was tuned
   for — so the button was being forced below the card's real bottom
   edge and clipped by .suggested-user-card's overflow:hidden (see
   app-fixes.js's own injected .suggested-user-card CSS). Removed the
   stale top override so the button falls back to the correct inline
   position (top:10px;right:16px, right beside the avatar) that
   app-feed.js's card HTML already sets and that actually matches the
   card's real height. */
.suggested-user-card .follow-btn { position: absolute !important; right: 18px !important; padding: 9px 24px !important; font-size: var(--text-base) !important; font-weight: var(--weight-bold) !important; border-radius: var(--radius-pill) !important; background: var(--primary) !important; color: var(--color-white) !important; border: none !important; cursor: pointer !important; transition: var(--transition-base) !important; box-shadow: 0 4px 14px rgba(10,14,39,0.22) !important; z-index: 3; white-space: nowrap; line-height: 1.2; width: auto !important; margin: 0 !important; display: inline-flex !important; align-items: center; gap: 5px; }
.suggested-user-card .follow-btn:hover, .suggested-user-card .follow-btn:active { background: var(--secondary) !important; box-shadow: 0 6px 20px rgba(27,43,139,0.35) !important; transform: translateY(-1px) !important; }
.suggested-user-card .follow-btn.followed { background: transparent !important; color: var(--primary) !important; border: 2px solid rgba(10,14,39,0.25) !important; box-shadow: none !important; }

.suggested-user-card .avatar-placeholder { width: 90px !important; height: 90px !important; border-radius: var(--radius-full) !important; margin: -45px 0 0 18px !important; position: relative; border: 4px solid var(--color-white) !important; box-shadow: 0 3px 12px rgba(0,0,0,0.18) !important; background: var(--secondary); overflow: hidden; flex-shrink: 0; z-index: 2; display: block; }
.suggested-user-card .avatar-placeholder img { width: 100%; height: 100%; object-fit: cover; display: block; }

.suggested-user-card-info { padding: 6px 18px 18px; flex: 1; display: flex; flex-direction: column; background: var(--color-white); border-radius: 0 0 var(--radius-2xl) var(--radius-2xl); }
.suggested-user-card-info strong { font-size: var(--text-4xl); font-weight: var(--weight-extrabold); color: var(--primary); display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-bottom: 2px; margin-top: 10px; line-height: var(--leading-snug); }
.suggested-user-card-info p { font-size: var(--text-base); color: var(--color-neutral-350); margin-bottom: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: var(--leading-normal); }
.suggested-user-bio { font-size: var(--text-md) !important; color: var(--color-neutral-600) !important; white-space: nowrap !important; overflow: hidden !important; text-overflow: ellipsis !important; display: block !important; margin: 2px 0 14px !important; line-height: var(--leading-relaxed) !important; }
.suggested-user-divider { height: 1px; background: var(--border); margin: 0 0 12px; display: block; }
.suggested-user-stats { display: flex; justify-content: flex-start; align-items: center; gap: 26px; margin: 0 0 10px; font-size: var(--text-base); color: var(--color-neutral-400); line-height: var(--leading-snug); }
.suggested-user-stats span { display: flex; align-items: baseline; gap: 5px; }
.suggested-user-stats strong { color: var(--primary); font-size: var(--text-xl); font-weight: var(--weight-extrabold); display: inline; }
.suggested-user-stats em { font-style: normal; font-size: var(--text-sm); color: var(--color-neutral-400); }
.suggested-user-empy { font-size: var(--text-base); color: var(--color-neutral-350); margin-top: 2px; display: flex; align-items: center; justify-content: flex-start; gap: 6px; }
.suggested-user-empy strong { color: var(--primary); font-size: var(--text-md); font-weight: var(--weight-extrabold); }
.suggested-user-empy em { font-style: normal; font-size: var(--text-sm); color: var(--color-neutral-350); }


/* ═══════════════════════════════════════════════════════════════════════════
   §19b  BUSINESS POSTS — PRODUCT / LISTING CARDS (#dashboard-bizposts-slider)
   Makes what sellers are offering clearly visible. Reinforces the 220 px
   width set by JS and ensures a tall hero image + prominent CTA.
   ═══════════════════════════════════════════════════════════════════════════ */

#dashboard-bizposts-slider {
    padding: 4px 16px 18px !important;
    gap: 14px !important;
}

/* Each product card */
#dashboard-bizposts-slider > [data-post-id] {
    flex: 0 0 220px !important;
    width: 220px !important;
    min-width: 220px !important;
    border-radius: 20px !important;
    box-shadow: 0 6px 24px rgba(10,14,39,0.14) !important;
    transition: transform 0.22s, box-shadow 0.22s !important;
}
#dashboard-bizposts-slider > [data-post-id]:hover {
    transform: translateY(-5px) !important;
    box-shadow: 0 14px 34px rgba(10,14,39,0.22) !important;
}

/* Hero media area */
#dashboard-bizposts-slider > [data-post-id] > div:first-child {
    height: 200px !important;
    min-height: 200px !important;
    flex-shrink: 0 !important;
}
#dashboard-bizposts-slider > [data-post-id] > div:first-child img,
#dashboard-bizposts-slider > [data-post-id] > div:first-child video {
    width: 100% !important;
    height: 100% !important;
    object-fit: cover !important;
    display: block !important;
}

/* Empty-state placeholder — matches the 220 px card */
#bizposts-empty {
    flex: 0 0 220px !important;
    width: 220px !important;
    height: 320px !important;
    border-radius: 20px !important;
    font-size: 0.78rem !important;
}
#bizposts-empty i { font-size: 2rem !important; margin-bottom: 8px !important; }


/* ═══════════════════════════════════════════════════════════════════════════
   §19c  BUSINESS PAGES DASHBOARD CARDS (.dashboard-business-card)
   The "Business Posts" section header strip — §6 in app-business.js.
   ═══════════════════════════════════════════════════════════════════════════ */

.dashboard-business-card {
    flex: 0 0 200px !important;
    width: 200px !important;
    min-width: 200px !important;
    border-radius: 18px !important;
    box-shadow: 0 4px 18px rgba(10,14,39,0.12) !important;
    transition: transform 0.2s, box-shadow 0.2s !important;
}
.dashboard-business-card:hover {
    transform: translateY(-4px) !important;
    box-shadow: 0 12px 30px rgba(10,14,39,0.18) !important;
}
/* Cover strip */
.dashboard-business-card > div:first-child {
    height: 88px !important;
    min-height: 88px !important;
    flex-shrink: 0 !important;
}
/* Action button */
.dashboard-business-card .biz-card-action-btn {
    width: 100% !important;
    padding: 8px !important;
    border-radius: 10px !important;
    font-size: 0.75rem !important;
    font-weight: 700 !important;
    cursor: pointer !important;
}


/* ═══════════════════════════════════════════════════════════════════════════
   §19d  SUGGESTED FOR YOU — BUSINESS PAGES (#vf-biz-suggest-slider)
   Rendered dynamically by app-fix-final.js. Structural selectors catch
   the cards regardless of class names the renderer uses.
   ═══════════════════════════════════════════════════════════════════════════ */

#vf-biz-suggest-container { margin-top: 6px; }

#vf-biz-suggest-slider {
    gap: 14px !important;
    padding: 6px 16px 20px !important;
}

/* Every card */
#vf-biz-suggest-slider > * {
    flex: 0 0 200px !important;
    width: 200px !important;
    min-width: 200px !important;
    border-radius: 18px !important;
    overflow: hidden !important;
    background: white !important;
    box-shadow: 0 4px 18px rgba(10,14,39,0.12) !important;
    border: 1px solid rgba(10,14,39,0.07) !important;
    display: flex !important;
    flex-direction: column !important;
    flex-shrink: 0 !important;
    cursor: pointer !important;
    transition: transform 0.2s, box-shadow 0.2s !important;
    scroll-snap-align: start !important;
}
#vf-biz-suggest-slider > *:hover {
    transform: translateY(-4px) !important;
    box-shadow: 0 12px 30px rgba(10,14,39,0.18) !important;
}

/* Cover strip */
#vf-biz-suggest-slider > * > div:first-child {
    height: 88px !important;
    min-height: 88px !important;
    flex-shrink: 0 !important;
    background-size: cover !important;
    background-position: center !important;
}

/* Avatar */
#vf-biz-suggest-slider .avatar-placeholder,
#vf-biz-suggest-slider [class*="avatar"] {
    width: 46px !important;
    height: 46px !important;
    border: 3px solid white !important;
    box-shadow: 0 3px 10px rgba(0,0,0,0.2) !important;
}

/* Business name */
#vf-biz-suggest-slider strong {
    font-size: 0.86rem !important;
    font-weight: 800 !important;
    color: #0A0E27 !important;
}

/* Industry tag */
#vf-biz-suggest-slider [class*="industry"],
#vf-biz-suggest-slider [class*="category"],
#vf-biz-suggest-slider span[style*="color:#1B2B8B"],
#vf-biz-suggest-slider span[style*="color: #1B2B8B"] {
    font-size: 0.65rem !important;
    font-weight: 700 !important;
    color: var(--live-color) !important;
    background: var(--surface-live) !important;
    padding: 2px 8px !important;
    border-radius: 20px !important;
    display: inline-block !important;
}

/* Follower count */
#vf-biz-suggest-slider [class*="follower"],
#vf-biz-suggest-slider span[style*="color:#6B7280"],
#vf-biz-suggest-slider span[style*="color: #6B7280"] {
    font-size: 0.68rem !important;
    color: #6B7280 !important;
    display: block !important;
    margin-top: 4px !important;
}

/* Follow / View button — full-width, reset absolute positioning */
#vf-biz-suggest-slider .follow-btn,
#vf-biz-suggest-slider button {
    width: 100% !important;
    padding: 8px 12px !important;
    border-radius: 10px !important;
    font-size: 0.76rem !important;
    font-weight: 700 !important;
    cursor: pointer !important;
    transition: background 0.18s !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    gap: 5px !important;
    position: static !important;
    top: auto !important;
    right: auto !important;
    box-shadow: none !important;
}
#vf-biz-suggest-slider .follow-btn:hover,
#vf-biz-suggest-slider button:hover {
    background: rgba(27,43,139,0.13) !important;
}


/* ═══════════════════════════════════════════════════════════════════════════
   §20  MESSAGES / CHAT
   ═══════════════════════════════════════════════════════════════════════════ */

#messages-view { display: flex; height: calc((var(--app-vh, 1vh) * 100) - 120px); background: var(--color-white); border-radius: var(--radius-md); overflow: hidden; box-shadow: var(--shadow-sm); }
.contact-list { width: 300px; border-right: 1px solid var(--light-gray); overflow-y: auto; }
.contact-item { display: flex; align-items: center; gap: 15px; padding: 15px; cursor: pointer; border-bottom: 1px solid var(--light-gray); }
.contact-item:hover, .contact-item.active { background: var(--color-surface-purple); }
.contact-item .avatar-placeholder { width: 50px; height: 50px; border-radius: var(--radius-full); }
.chat-view { flex-grow: 1; display: flex; flex-direction: column; }
.chat-header { padding: 15px; border-bottom: 1px solid var(--light-gray); display: flex; align-items: center; gap: 15px; cursor: pointer; }
.chat-header .avatar-placeholder { width: 40px; height: 40px; border-radius: var(--radius-full); }
.chat-messages { flex-grow: 1; padding: 20px; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; }
.message { max-width: 70%; padding: 10px 15px; border-radius: var(--radius-2xl); line-height: var(--leading-snug); }
.message.sent { background: var(--primary); color: var(--color-white); align-self: flex-end; border-bottom-right-radius: 4px; }
.message.received { background: var(--light-gray); color: var(--text-primary); align-self: flex-start; border-bottom-left-radius: 4px; }
.message-media { max-width: 100%; border-radius: 15px; margin-top: 5px; }
.message-input-area { padding: 15px; border-top: 1px solid var(--light-gray); display: flex; gap: 10px; align-items: center; }
.message-input-area input[type="text"] { flex-grow: 1; padding: 12px 20px; border: 1px solid var(--color-neutral-200); border-radius: var(--radius-pill); }
.message-input-area .btn { border-radius: var(--radius-full); width: 48px; height: 48px; padding: 0; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.message-actions-left button { margin-right: 5px; }


/* ═══════════════════════════════════════════════════════════════════════════
   §21  CART MODAL (covered in §14 — no duplication needed)
   ═══════════════════════════════════════════════════════════════════════════ */
/* cart-modal styles live in §14 Auth Modal section */


/* ═══════════════════════════════════════════════════════════════════════════
   §22  KYC — FORM, UPLOAD AREAS, CAMERA MODAL
   ═══════════════════════════════════════════════════════════════════════════ */

#kyc-entity-selector { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; margin-top: 16px; }
.kyc-entity-btn { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; padding: 20px 12px; border: 2px solid rgba(91,14,166,0.2); border-radius: var(--radius-xl); cursor: pointer; background: var(--color-white); transition: var(--transition-base); text-align: center; font-size: var(--text-base); font-weight: var(--weight-semibold); color: var(--primary); user-select: none; -webkit-tap-highlight-color: transparent; }
.kyc-entity-btn:hover { border-color: var(--live-color); background: rgba(91,14,166,0.05); transform: translateY(-2px); box-shadow: 0 4px 14px rgba(91,14,166,0.12); }
.kyc-entity-btn.active { border-color: var(--live-color); background: rgba(91,14,166,0.09); color: var(--live-color); }
.kyc-entity-btn i { font-size: var(--text-5xl); color: var(--live-color); display: block; }
.kyc-entity-btn span { font-weight: var(--weight-bold); }
.kyc-form { display: none !important; }
.kyc-form.active { display: block !important; animation: fadeIn 0.3s ease; }
#profile-kyc-tab { padding: 8px 0; }

.upload-area { border: 2px dashed var(--light-gray); border-radius: var(--radius-md); padding: 20px; text-align: center; cursor: pointer; }
.upload-area:hover { border-color: var(--primary); }
.upload-area i { font-size: var(--text-4xl); margin-bottom: 10px; }
.upload-area span { font-weight: var(--weight-medium); }

.upload-area.kyc-file-upload { border: 2px dashed rgba(10,14,39,0.15) !important; border-radius: var(--radius-xl) !important; background: rgba(10,14,39,0.02) !important; transition: var(--transition-base) !important; display: flex; align-items: center; justify-content: center; gap: 10px; min-height: 60px; position: relative; }
.upload-area.kyc-file-upload:hover { border-color: var(--secondary) !important; background: rgba(27,43,139,0.04) !important; }
.upload-area.kyc-file-upload.has-file { border-color: var(--success-color) !important; border-style: solid !important; background: rgba(16,185,129,0.04) !important; }
.upload-area.kyc-file-upload .file-name-display { font-size: var(--text-sm); color: var(--success-color); font-weight: var(--weight-semibold); }

.live-capture-btn { margin-top: 10px; }
.file-upload-preview { margin-top: 10px; display: block; font-size: 0.9em; color: var(--color-neutral-400); }
.file-upload-preview img { width: 80px; height: 80px; object-fit: cover; border-radius: var(--radius-md); margin-right: 10px; vertical-align: middle; }
.kyc-capture-btn { display: flex; align-items: center; gap: 8px; }

#kyc-camera-modal { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.9); z-index: var(--z-live); align-items: center; justify-content: center; flex-direction: column; }
#kyc-camera-modal.show { display: flex; }
#kyc-camera-video { width: min(400px, 90vw); border-radius: var(--radius-lg); background: #000; }
#kyc-camera-canvas { display: none; }
.kyc-camera-controls { display: flex; gap: 15px; margin-top: 15px; }


/* ═══════════════════════════════════════════════════════════════════════════
   §23  ADMIN PANEL
   ═══════════════════════════════════════════════════════════════════════════ */

.admin-queue-item { display: flex; justify-content: space-between; align-items: center; padding: 16px !important; border-bottom: 1px solid var(--light-gray); background: var(--color-white) !important; border-radius: var(--radius-lg) !important; border: 1px solid var(--border) !important; box-shadow: var(--shadow-xs) !important; margin-bottom: 12px !important; transition: var(--transition-slow); }
.admin-queue-item:last-child { border-bottom: none; }
.admin-queue-info { flex-grow: 1; }
.admin-queue-info p { margin: 0; }
.admin-queue-actions { display: flex; gap: 10px; }

/* KYC admin docs */
#admin-kyc-docs-container .kyc-doc-card { display: flex; align-items: center; justify-content: space-between; padding: 14px 20px; border-bottom: 1px solid var(--light-gray); flex-wrap: wrap; gap: 10px; }
#admin-kyc-docs-container .kyc-doc-card:last-child { border-bottom: none; }
.kyc-doc-preview { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 10px; }
.kyc-doc-preview img { width: 80px; height: 60px; object-fit: cover; border-radius: var(--radius-sm); border: 1px solid var(--color-neutral-150); cursor: pointer; }
.kyc-status-badge { padding: 3px 12px; border-radius: var(--radius-lg); font-size: var(--text-sm); font-weight: var(--weight-bold); }
.kyc-status-badge.pending { background: var(--color-surface-warm); color: var(--color-warning-dark); }
.kyc-status-badge.approved { background: var(--color-surface-green); color: #2e7d32; }
.kyc-status-badge.rejected { background: var(--color-surface-red); color: #c62828; }

/* Admin swipe rows */
.sos-action-row::-webkit-scrollbar, #admin-sos-queue::-webkit-scrollbar, #admin-kyc-docs-container::-webkit-scrollbar { display: none; }
.sos-action-row { -ms-overflow-style: none; scrollbar-width: none; }

/* Vault badge / disbursement */
#vault-status-badge[style*="CONNECTED"] { animation: vaultPulse 2.5s ease-in-out infinite; }
#disb-ngo-list::-webkit-scrollbar { width: 5px; }
#disb-ngo-list::-webkit-scrollbar-track { background: transparent; }
#disb-ngo-list::-webkit-scrollbar-thumb { background: rgba(10,14,39,0.15); border-radius: 99px; }
#disb-history-body tr:hover { background: rgba(27,43,139,0.03); }
#master-delete-bar { transition: width 0.4s ease, background 0.4s ease; }
.admin-nav-tab[data-tab="admin-disburse-tab"] i { color: var(--accent-color); }
.admin-nav-tab[data-tab="admin-disburse-tab"].active i { color: inherit; }

/* Submit complaint FAB */
#submit-complaint-fab { position: fixed; bottom: 120px; right: 16px; z-index: var(--z-modal); background: var(--danger-color); color: var(--color-white); border: none; border-radius: var(--radius-full); width: 40px; height: 40px; font-size: var(--text-sm); font-weight: var(--weight-bold); cursor: grab; box-shadow: 0 3px 10px rgba(244,67,54,0.4); display: none; align-items: center; justify-content: center; transition: var(--transition-base); touch-action: none; user-select: none; }
#submit-complaint-fab:active { cursor: grabbing; }
#submit-complaint-fab:hover { box-shadow: 0 5px 16px rgba(244,67,54,0.55); transform: scale(1.1); }
#submit-complaint-fab .fab-label { display: none; position: absolute; right: 46px; top: 50%; transform: translateY(-50%); background: rgba(0,0,0,0.75); color: var(--color-white); font-size: 0.72rem; padding: 3px 8px; border-radius: var(--radius-md); white-space: nowrap; pointer-events: none; }
#submit-complaint-fab:hover .fab-label { display: block; }


/* ═══════════════════════════════════════════════════════════════════════════
   §24  DISPUTE & COMPLAINT SYSTEM
   ═══════════════════════════════════════════════════════════════════════════ */

.dispute-card { background: var(--color-white); border-radius: var(--radius-md); padding: 18px 20px; margin-bottom: 12px; border-left: 4px solid var(--danger-color); box-shadow: var(--shadow-xs); transition: var(--shadow-md); }
.dispute-card:hover { box-shadow: var(--shadow-md); }
.dispute-card.status-resolved { border-left-color: var(--success-color); opacity: 0.75; }
.dispute-card.status-pending { border-left-color: var(--accent-color); }
.dispute-meta { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0; font-size: var(--text-sm); color: var(--color-neutral-400); }
.dispute-meta span { background: var(--color-neutral-75); padding: 3px 10px; border-radius: var(--radius-lg); }
.dispute-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
.dispute-status-badge { display: inline-block; padding: 3px 12px; border-radius: var(--radius-2xl); font-size: var(--text-sm); font-weight: var(--weight-bold); }
.dispute-status-badge.open { background: var(--color-surface-red); color: var(--danger-color); }
.dispute-status-badge.resolved { background: var(--color-surface-green); color: var(--success-color); }
.dispute-status-badge.pending { background: var(--color-surface-warm); color: var(--color-warning-dark); }
#dispute-detail-modal .modal-card { max-width: 700px; text-align: left; }
.dispute-evidence-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(100px,1fr)); gap: 10px; margin: 10px 0; }
.dispute-evidence-grid img, .dispute-evidence-grid video { width: 100%; height: 90px; object-fit: cover; border-radius: var(--radius-md); cursor: pointer; }
.dispute-chat-bubble { padding: 10px 15px; border-radius: var(--radius-lg); margin-bottom: 10px; max-width: 85%; }
.dispute-chat-bubble.admin { background: var(--primary); color: var(--color-white); align-self: flex-end; border-bottom-right-radius: 3px; }
.dispute-chat-bubble.member { background: var(--color-neutral-100); color: var(--color-neutral-700); align-self: flex-start; border-bottom-left-radius: 3px; }
.dispute-chat-bubble .sender { font-size: 0.78rem; font-weight: var(--weight-bold); margin-bottom: 4px; opacity: 0.8; }
.dispute-chat-bubble .ts { font-size: 0.72rem; opacity: 0.65; margin-top: 4px; }
#dispute-chat-thread { display: flex; flex-direction: column; }

.complaint-card { background: var(--color-white); border-radius: var(--radius-md); padding: 16px 20px; margin-bottom: 10px; border-left: 4px solid var(--secondary); box-shadow: var(--shadow-xs); }
.complaint-card.unread { border-left-color: var(--danger-color); font-weight: var(--weight-medium); }
.complaint-card .complaint-subject { font-weight: var(--weight-bold); color: var(--primary); margin-bottom: 4px; }
.complaint-card .complaint-meta { font-size: 0.82rem; color: var(--color-neutral-350); margin-bottom: 8px; }
.complaint-card .complaint-preview { font-size: var(--text-md); color: var(--color-neutral-500); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }


/* ═══════════════════════════════════════════════════════════════════════════
   §25  STAKING INDICATORS & REWARDS HISTORY
   ═══════════════════════════════════════════════════════════════════════════ */

.staking-status { font-size: 0.8em; margin-top: 5px; font-weight: var(--weight-bold); }
.staking-status.active { color: var(--success-color); }
.staking-status.locked { color: var(--accent-color); }
.staking-status.unlocked { color: var(--danger-color); }

.claimed-history-list { list-style: none; padding: 0; margin-top: 15px; }
.claimed-history-item { background: var(--color-neutral-100); padding: 10px; border-radius: var(--radius-sm); margin-bottom: 8px; display: flex; justify-content: space-between; align-items: center; font-size: 0.9em; }
.claimed-history-item .date { font-style: italic; color: var(--color-neutral-350); }
.claimed-history-item .amount { font-weight: var(--weight-bold); color: var(--primary); }


/* ═══════════════════════════════════════════════════════════════════════════
   §26  SETTINGS & MONETISATION
   ═══════════════════════════════════════════════════════════════════════════ */

/* REDESIGNED (2026-07-25 — settings tab bar): was a bare `display:flex` row
   with no wrap/scroll handling, so on narrow screens the tabs fought for
   space, wrapped awkwardly, and got clipped at the viewport edge (5 tabs:
   Profile, Security, Privacy Policy, Terms, E-Commerce Policy). Rebuilt as
   a compact horizontally-scrollable pill bar — every tab keeps its full
   width and label; overflow scrolls instead of wrapping or clipping. Each
   tab's icon now sits in its own small rounded badge (same visual language
   as the sidebar's .nav-icon-box) instead of a bare inline glyph, which
   reads as more deliberate/premium than plain icon-plus-text. */
.settings-tabs {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  gap: 8px;
  padding: 12px var(--space-4) 14px;
  margin-bottom: var(--space-2);
  border-bottom: 1px solid var(--border);
}
.settings-tabs::-webkit-scrollbar { display: none; }

.settings-tab {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  white-space: nowrap;
  padding: 6px 16px 6px 6px;
  border-radius: var(--radius-pill);
  cursor: pointer;
  color: var(--text-muted);
  font-weight: var(--weight-semibold);
  font-size: 0.85rem;
  letter-spacing: 0.01em;
  background: var(--color-neutral-25);
  border: 1px solid var(--border);
  transition: var(--transition-base);
}
.settings-tab:hover { background: var(--color-neutral-75); color: var(--primary); border-color: var(--border-strong); }

.settings-tab-icon {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  background: var(--color-white);
  color: var(--text-muted);
  font-size: 0.68rem;
  box-shadow: var(--shadow-xs);
  transition: var(--transition-base);
}
.settings-tab-label { line-height: 1; }
.settings-tab:hover .settings-tab-icon { color: var(--primary); }
.settings-tab.active {
  background: var(--g-navy);
  color: var(--color-white);
  border-color: transparent;
  box-shadow: var(--shadow-sm);
  transform: translateY(-1px);
}
.settings-tab.active .settings-tab-icon {
  background: rgba(255,255,255,0.16);
  color: var(--color-gold-light);
  box-shadow: none;
}
.settings-tab.active:hover { color: var(--color-white); }
.settings-content { display: none; }
.settings-content.active { display: block; animation: fadeIn 0.4s; }

/* Shared intro block at the top of every settings tab — gives Profile,
   Security and the three policy tabs one consistent heading treatment
   instead of each tab styling its own <h3> ad hoc. */
.settings-section-head { margin-bottom: var(--space-4); }
.settings-section-head h3 { margin-bottom: 4px !important; }
.settings-section-sub { font-size: var(--text-sm); color: var(--text-muted); margin: 0; }

/* Grouped field sections inside Profile / Security — small tracked-out
   label + divider, same visual language as the settings tab bar, so the
   form reads as organised sections rather than one long field list. */
.settings-subsection { padding-bottom: 20px; margin-bottom: 20px; border-bottom: 1px solid var(--border); }
.settings-subsection-last { border-bottom: none; margin-bottom: 8px; padding-bottom: 0; }
.settings-subsection-label {
  display: flex; align-items: center; gap: 8px;
  font-size: var(--text-xs); font-weight: var(--weight-bold);
  color: var(--secondary); text-transform: uppercase; letter-spacing: var(--tracking-wide);
  margin-bottom: 14px;
}
.settings-subsection-label i { font-size: 0.85em; color: var(--secondary); }
.settings-subsection .form-group:last-child { margin-bottom: 0; }

.settings-danger-zone { background: rgba(var(--color-danger-rgb),0.05); border: 1.5px solid rgba(var(--color-danger-rgb),0.2); border-radius: var(--radius-xl); padding: 20px; }
.settings-danger-zone h4 { color: var(--color-danger-dark) !important; margin-bottom: 8px !important; display: flex; align-items: center; gap: 8px; }
.settings-danger-zone p { color: var(--text-muted); font-size: var(--text-sm); margin-bottom: 16px; }
.settings-danger-zone .btn-danger { background: var(--color-danger-dark); border: none; }

.card-content h4, .static-content h4 {
  font-family: var(--font-ui); font-weight: var(--weight-bold);
  color: var(--primary); font-size: var(--text-md);
  letter-spacing: var(--tracking-tight); margin-top: 1.2em;
}
.static-content p, .static-content li { font-size: var(--text-md); color: var(--text-color); }
.static-content p, .static-content h3, .static-content h4, .static-content li { margin-bottom: 1em; }
.static-content ul, .static-content ol { padding-left: 20px; }
.static-content blockquote { border-left: 4px solid var(--light-gray); padding-left: 15px; margin: 1em 0; font-style: italic; }
.session-item { display: flex; justify-content: space-between; align-items: center; padding: 12px 14px; border: 1px solid var(--color-neutral-100); border-radius: var(--radius-md); margin-bottom: 10px; font-size: var(--text-sm); background: var(--color-neutral-25); }
.session-item i { color: var(--text-muted); margin-right: 8px; }
.session-item:last-child { margin-bottom: 0; }

/* Progressive-disclosure layers (Settings > Profile): a locked layer is
   present in the DOM (so its inputs still submit) but visually collapsed
   and non-interactive until the layer before it is complete. Revealing
   animates open rather than popping in, so it reads as an intentional
   "next chapter unlocked" moment rather than a layout jump. */
.emp-form-card.emp-layer-locked {
  max-height: 0;
  padding-top: 0; padding-bottom: 0;
  margin: 0;
  border-width: 0;
  opacity: 0;
  overflow: hidden;
  pointer-events: none;
  transition: max-height 0.45s ease, opacity 0.3s ease, padding 0.45s ease;
}
.emp-form-card.emp-layer-revealed {
  animation: empLayerReveal 0.5s ease both;
}
@keyframes empLayerReveal {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}


/* ═══════════════════════════════════════════════════════════════════════════
   §27  NGO / GRANT PORTAL & COMMUNITY TASKS
   ═══════════════════════════════════════════════════════════════════════════ */

.table-container { overflow-x: auto; }
.styled-table { width: 100%; border-collapse: collapse; margin: 25px 0; font-size: var(--text-md); box-shadow: 0 0 20px rgba(0,0,0,0.15); }
.styled-table thead tr { background: var(--primary); color: var(--color-white); text-align: left; }
.styled-table th, .styled-table td { padding: 12px 15px; }
.styled-table tbody tr { border-bottom: 1px solid var(--color-neutral-150); }
.styled-table tbody tr:nth-of-type(even) { background: var(--color-neutral-75); }
.styled-table tbody tr:last-of-type { border-bottom: 2px solid var(--primary); }
.tx-hash { font-family: var(--font-mono); font-size: 0.85em; color: var(--secondary); text-decoration: none; }
.tx-hash:hover { text-decoration: underline; }
.status-completed { color: var(--success-color); font-weight: var(--weight-bold); }

.task-list { list-style: none; }
.task-item { background: var(--color-white); padding: 15px; border-radius: var(--radius-sm); margin-bottom: 10px; display: flex; justify-content: space-between; align-items: center; }
.task-item i { color: var(--primary); margin-right: 10px; font-size: var(--text-2xl); }

/* ============================================================================
   COMMUNITY TASKS — premium redesign (2026-07-24)
   Replaces the plain list rows above with a card-based layout that matches
   the navy/gold "editorial" language used elsewhere (emp-form-card, icon-3d):
   circular navy/gold icon badge, serif section heading, gold reward pill and
   CTA. Brand icons are inline SVG (not a webfont) for the same reason the
   SOS/Crisis forms were switched — no external font request, no risk of a
   broken "tofu" glyph on a slow connection.
   ============================================================================= */
.comm-tasks-intro h3 {
    font-family: var(--font-display);
    color: var(--color-navy);
    font-size: var(--text-2xl);
    letter-spacing: var(--tracking-tight);
    margin-bottom: 4px;
}
.comm-tasks-intro p {
    color: var(--text-muted);
    font-size: var(--text-sm);
    margin: 0;
}

.comm-task-list {
    list-style: none;
    margin: 22px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.comm-task-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 14px 16px;
    background: var(--color-white);
    border: 1px solid var(--border);
    border-radius: var(--radius-xl);
    padding: 16px 18px;
    box-shadow: var(--shadow-sm);
    transition: box-shadow 0.25s ease, transform 0.25s ease;
}
.comm-task-item:hover {
    box-shadow: var(--shadow-md), var(--shadow-gold-sm, 0 4px 14px rgba(255,213,0,0.22));
    transform: translateY(-2px);
}

.comm-task-info {
    display: flex;
    align-items: center;
    gap: 14px;
    min-width: 0;
}
.comm-task-icon {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    flex-shrink: 0;
    background: var(--g-navy);
    color: var(--color-gold);
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: var(--shadow-navy);
}
.comm-task-icon svg { width: 20px; height: 20px; }

.comm-task-text { min-width: 0; }
.comm-task-text strong {
    display: block;
    color: var(--color-navy);
    font-size: 0.96rem;
    font-weight: var(--weight-semibold);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.comm-task-reward-amt {
    display: inline-block;
    margin-top: 4px;
    background: rgba(255, 213, 0, 0.14);
    color: var(--color-navy);
    padding: 2px 10px;
    border-radius: var(--radius-pill);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.02em;
}

.comm-task-cta {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    flex-shrink: 0;
    background: var(--g-gold) !important;
    color: var(--primary) !important;
    border: none;
    cursor: pointer;
    font-family: inherit;
    padding: 9px 18px;
    border-radius: var(--radius-pill);
    font-size: 0.82rem;
    font-weight: 700;
    text-decoration: none;
    white-space: nowrap;
    box-shadow: var(--shadow-gold-sm, 0 4px 14px rgba(255,213,0,0.32));
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.comm-task-cta:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-gold, 0 8px 22px rgba(255,213,0,0.4));
}
.comm-task-cta svg { width: 14px; height: 14px; }

.comm-task-done {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    background: rgba(16, 185, 129, 0.12);
    color: var(--color-success);
    padding: 8px 16px;
    border-radius: var(--radius-pill);
    font-size: 0.8rem;
    font-weight: 700;
    white-space: nowrap;
}
.comm-task-done svg { width: 14px; height: 14px; }

@media (max-width: 480px) {
    .comm-task-item { padding: 14px 16px; }
    .comm-task-cta, .comm-task-done { width: 100%; justify-content: center; }
}

#ngo-grid-view .ngo-card { flex: 0 0 280px; }
.ngo-profile-header { display: flex; gap: 20px; align-items: center; padding: 25px; background: var(--color-surface-purple); border-radius: var(--radius-md); }
.ngo-profile-header .avatar-placeholder { width: 100px; height: 100px; border-radius: var(--radius-full); flex-shrink: 0; }
.ngo-impact-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px; margin: 25px 0; text-align: center; }
.ngo-impact-stats .stat-value { font-size: var(--text-4xl); font-weight: var(--weight-bold); color: var(--primary); }

.map-placeholder { height: 150px; background: var(--color-neutral-100); border-radius: var(--radius-md); display: flex; align-items: center; justify-content: center; color: var(--color-neutral-350); text-align: center; border: 1px solid var(--color-neutral-200); margin-bottom: 10px; }
#crisis-location-coords { font-size: 0.9em; font-style: italic; color: var(--success-color); }

/* ── Grant Transparency Portal (2026-07-25) — classic emerald/gold premium
   finish. Was navy/gold; moved to the giving-context green primary (see
   tokens.css §2 co-primary rule + the #donor-hub, .gtp-section scope
   rule above §6b) so this reads as giving-context, not social-context. ── */

.gtp-hero {
    display: flex; justify-content: space-between; align-items: center; gap: 24px; flex-wrap: wrap;
    background: var(--g-giving);
    color: var(--color-white, #fff);
    border-radius: var(--radius-2xl, 22px);
    padding: 28px 32px;
    position: relative; overflow: hidden;
    box-shadow: 0 14px 34px rgba(10,14,39,0.28);
    border: 1px solid rgba(255,213,0,0.28);
    margin-bottom: 22px;
}
.gtp-hero::before {
    content: ""; position: absolute; inset: 0; pointer-events: none;
    background: radial-gradient(circle at 88% -15%, rgba(255,213,0,0.28), transparent 55%);
}
.gtp-hero-text { position: relative; z-index: 1; max-width: 540px; }
.gtp-hero-text h3 {
    font-family: 'Syne', sans-serif; font-size: 1.3rem; font-weight: 800;
    margin: 0 0 8px; letter-spacing: 0.2px; display: flex; align-items: center; gap: 12px;
}
.gtp-hero-text h3::before { content: ""; display: inline-block; width: 22px; height: 2px; background: var(--accent); flex-shrink: 0; }
.gtp-hero-text p { margin: 0; font-size: 0.86rem; line-height: 1.65; color: rgba(255,255,255,0.78); }
.gtp-hero-stats { position: relative; z-index: 1; display: flex; gap: 16px; flex-wrap: wrap; }
.gtp-stat {
    text-align: center; min-width: 108px; padding: 14px 20px;
    border-radius: 16px; background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,213,0,0.32);
}
.gtp-stat-value { display: block; font-family: 'Syne', sans-serif; font-size: 1.9rem; font-weight: 800; color: var(--accent); line-height: 1.1; }
.gtp-stat-label { display: block; margin-top: 5px; font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.6px; color: rgba(255,255,255,0.68); }

.gtp-grid { display: grid; grid-template-columns: minmax(280px, 340px) 1fr; gap: 22px; align-items: start; }
@media (max-width: 900px) { .gtp-grid { grid-template-columns: 1fr; } }

.gtp-pie-card, .gtp-table-card {
    background: var(--color-white, #fff);
    border-radius: 20px;
    border: 1px solid rgba(10,14,39,0.06);
    box-shadow: var(--shadow-sm);
    padding: 22px;
}
.gtp-pie-card h4, .gtp-table-header h4 {
    display: flex; align-items: center; gap: 9px;
    font-family: 'Syne', sans-serif; font-size: 1rem; font-weight: 700;
    color: var(--primary); margin: 0 0 18px;
}
.gtp-pie-card h4 i, .gtp-table-header h4 i { color: var(--accent); }

.gtp-pie-row { display: flex; align-items: center; gap: 28px; flex-wrap: wrap; justify-content: center; }
.gtp-pie-svg-wrap { position: relative; width: 176px; height: 176px; flex-shrink: 0; margin: 0 auto; }
.gtp-pie {
    width: 176px; height: 176px; border-radius: 50%;
    box-shadow: 0 6px 20px rgba(10,14,39,0.18), inset 0 0 0 6px rgba(255,255,255,0.9);
    transition: background 0.5s ease;
    display: flex; align-items: center; justify-content: center;
}
.gtp-pie-empty { font-size: 0.78rem; color: var(--text-muted); text-align: center; line-height: 1.4; padding: 0 20px; }
.gtp-pie-center {
    position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
    width: 108px; height: 108px; border-radius: 50%;
    background: var(--color-white, #fff);
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    box-shadow: 0 2px 10px rgba(10,14,39,0.1);
}
.gtp-pie-center span { font-family: 'Syne', sans-serif; font-size: 1.55rem; font-weight: 800; color: var(--primary); line-height: 1; }
.gtp-pie-center small { margin-top: 3px; font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-muted); }

.gtp-pie-legend { display: flex; flex-direction: column; gap: 12px; min-width: 190px; }
.gtp-legend-item { display: flex; align-items: center; gap: 10px; font-size: 0.85rem; color: var(--primary); }
.gtp-legend-item span:nth-child(2) { flex: 1; }
.gtp-legend-item strong { font-family: 'Syne', sans-serif; font-size: 1rem; }
.gtp-legend-dot { width: 12px; height: 12px; border-radius: 3px; flex-shrink: 0; box-shadow: var(--shadow-sm); }

.gtp-table-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.gtp-table-header h4 { margin: 0; }
.gtp-export-btn { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; }

.gtp-table { box-shadow: none; margin: 0; border-radius: 14px; overflow: hidden; border: 1px solid rgba(10,14,39,0.06); }
.gtp-table thead tr { background: var(--g-giving); }
.gtp-table th {
    font-family: var(--font-sans); font-size: 0.7rem; font-weight: 700;
    letter-spacing: 0.6px; text-transform: uppercase; padding: 13px 14px;
    white-space: nowrap;
}
.gtp-table td { font-size: 0.85rem; color: var(--primary); vertical-align: middle; }
.gtp-table tbody tr:nth-of-type(even) { background: rgba(10,14,39,0.015); }
.gtp-table tbody tr:last-of-type { border-bottom: none; }

@media (max-width: 640px) {
    .gtp-hero { padding: 22px; }
    .gtp-hero-stats { width: 100%; justify-content: space-between; }
    .gtp-stat { flex: 1; min-width: 0; padding: 12px 10px; }
    .gtp-pie-row { gap: 18px; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   §28  BUSINESS PAGE
   ═══════════════════════════════════════════════════════════════════════════ */

.business-page-header { position: relative; }
.business-page-header .profile-header { transform: translateY(-60px); }
.business-page-header .profile-pic { width: 150px; height: 150px; object-fit: cover; border-radius: var(--radius-md) !important; }
.business-page-header .avatar-placeholder { width: 150px; height: 150px; border-radius: var(--radius-md) !important; }
.business-page-header .profile-header-info { padding-top: 60px; }
.business-page-content h4 { color: var(--primary); border-bottom: 2px solid var(--light-gray); padding-bottom: 10px; margin-bottom: 15px; display: flex; justify-content: space-between; align-items: center; }
.business-page-content .edit-icon { font-size: var(--text-md); color: var(--secondary); cursor: pointer; }
.business-page-content p { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.business-page-content p .edit-icon { margin-left: auto; }
#create-page-prompt { text-align: center; padding: 40px; }
#business-page-feed-tab { padding-top: 0 !important; }
#business-page-feed-container { margin-top: 30px; }
#business-page-tabs { margin-top: -30px; }
#create-business-page-modal .modal-card { max-width: 600px; text-align: left; }
.page-image-uploader { display: flex; flex-direction: column; align-items: center; margin-bottom: 20px; }
.page-cover-photo-preview { width: 100%; height: 150px; background: var(--color-neutral-100); border-radius: var(--radius-md); margin-bottom: -50px; background-size: cover; background-position: center; cursor: pointer; display: flex; align-items: center; justify-content: center; color: var(--color-neutral-350); border: 2px dashed var(--light-gray); }
.page-profile-photo-preview { width: 100px; height: 100px; border-radius: var(--radius-full); background: var(--color-neutral-150); border: 3px solid var(--color-white); box-shadow: var(--shadow-xs); cursor: pointer; background-size: cover; background-position: center; }


/* ═══════════════════════════════════════════════════════════════════════════
   §29  UTILITIES
   ═══════════════════════════════════════════════════════════════════════════ */

/* Upload progress bar */
.upload-progress-container { width: 100%; background: rgba(10,14,39,0.06); border-radius: var(--radius-md); overflow: hidden; margin-top: 10px; }
.upload-progress-bar { height: 5px; background: var(--g-teal); border-radius: var(--radius-md); transition: width var(--duration-slow) var(--ease-out); box-shadow: 0 0 10px rgba(0,212,170,0.5); }

/* Promotion modal fix */
#promotion-payment-details { display: none; }

/* Post format toolbar (legacy) */
#post-format-toolbar { position: absolute; top: 0; right: 0; display: flex; gap: 5px; background: var(--color-neutral-100); padding: 5px; border-radius: var(--radius-sm); transform: translateY(-120%); }
#post-format-toolbar button { background: none; border: 1px solid var(--color-neutral-200); border-radius: var(--radius-xs); width: 30px; height: 30px; font-weight: var(--weight-bold); cursor: pointer; }

/* Withdrawal fields */
#withdrawal-method-fields > div { display: none; }

/* Dashboard feed grid */
.dashboard-grid { display: grid; grid-template-columns: 1fr; gap: 30px; }


/* ═══════════════════════════════════════════════════════════════════════════
   §30  ANIMATIONS & KEYFRAMES
   ═══════════════════════════════════════════════════════════════════════════ */

@keyframes fadeIn        { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
@keyframes fadeInModal   { from { opacity: 0; } to { opacity: 1; } }
@keyframes orbit         { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
@keyframes avatarPulse   { 0%, 100% { transform: scale(1); box-shadow: 0 0 40px rgba(255,87,34,0.5), 0 0 80px rgba(142,36,170,0.3); } 50% { transform: scale(1.05); box-shadow: 0 0 60px rgba(255,87,34,0.8), 0 0 120px rgba(142,36,170,0.5); } }
@keyframes loadProgress  { 0% { width: 0%; } 70% { width: 85%; } 100% { width: 100%; } }
@keyframes premiumBgShift{ 0%, 100% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } }
@keyframes nebulaDrift   { 0% { transform: scale(1) rotate(0deg); } 100% { transform: scale(1.08) rotate(4deg); } }
@keyframes bgBreath      { to { transform: scale(1.05); } }
@keyframes particleTwinkle { 0% { opacity: 0.6; } 100% { opacity: 1; } }
@keyframes heartBeat     { 0% { transform: scale(1); } 50% { transform: scale(1.3); } 100% { transform: scale(1); } }
@keyframes pulse         { 0% { box-shadow: 0 0 0 0 var(--danger-color); } 70% { box-shadow: 0 0 0 10px rgba(244,67,54,0); } 100% { box-shadow: 0 0 0 0 rgba(244,67,54,0); } }
@keyframes floatUpAndFade{ 0% { opacity: 1; transform: translateY(0) scale(0.5) rotate(0deg); filter: hue-rotate(0deg); } 25% { transform: translateY(-50px) scale(0.7) rotate(45deg); filter: hue-rotate(90deg); } 50% { opacity: 0.8; transform: translateY(-150px) scale(1) rotate(180deg); filter: hue-rotate(180deg); } 75% { transform: translateY(-250px) scale(1.2) rotate(270deg); filter: hue-rotate(270deg); } 100% { opacity: 0; transform: translateY(-350px) scale(1.5) rotate(360deg); filter: hue-rotate(360deg); } }
/* @keyframes giftFloatSmall removed from here (session 2026-07-19,
   second follow-up) — it duplicated app-gifts.js's own keyframe of the
   same name under the same global CSS keyframe namespace, which is
   fragile (whichever one the browser resolves last wins, silently).
   app-gifts.js is now the only place this keyframe is defined. */
@keyframes floatUpHearts { 0% { opacity: 0; transform: translateY(0) scale(0.5); } 10% { opacity: 1; transform: translateY(-50px) scale(1); } 100% { opacity: 0; transform: translateY(-800px) scale(2); } }
@keyframes bubbleUp      { 0% { transform: translateY(0) scale(1); opacity: 0.8; } 100% { transform: translateY(-200px) scale(1.5); opacity: 0; } }
@keyframes slideUpModal  { from { transform: translateY(100%); } }
@keyframes slideInUp     { from { opacity: 0; transform: translateY(20px); } }
@keyframes goldTextShimmer { 0% { background-position: 200% center; } 100% { background-position: -200% center; } }
@keyframes goldBarShimmer  { 0% { background-position: 200% center; } 100% { background-position: -200% center; } }
@keyframes vaultPulse    { 0%, 100% { opacity: 1; } 50% { opacity: 0.65; } }
@keyframes lbFadeIn      { from { opacity: 0; } to { opacity: 1; } }
@keyframes slideUp       { from { transform: translateX(-50%) translateY(20px); opacity: 0; } to { transform: translateX(-50%) translateY(0); opacity: 1; } }


/* ═══════════════════════════════════════════════════════════════════════════
   §31  RESPONSIVE OVERRIDES
   ═══════════════════════════════════════════════════════════════════════════ */

@media (max-width: 992px) {
  .sidebar { transform: translateX(-100%); }
  .sidebar.open { transform: translateX(0); box-shadow: 5px 0 15px rgba(0,0,0,0.2); }
  .main-content { margin-left: 0 !important; }
  .mobile-menu-toggle { display: block; }
}

@media (max-width: 768px) {
  /* ── Edge-to-edge layout ── */
  .main-content { padding: 0 !important; padding-bottom: calc(80px + env(safe-area-inset-bottom, 0px)) !important; }
  .dashboard-grid { gap: 0 !important; }

  /* Cards expand to full viewport width with no border-radius on sides */
  .card {
    border-radius: 0 !important;
    border-left: none !important;
    border-right: none !important;
    margin-bottom: 8px !important;
    box-shadow: none !important;
    border-bottom: 1px solid rgba(10,14,39,0.07) !important;
  }

  /* Section headers stay padded */
  .card > h3,
  .card-content > h3 { padding: 20px 16px 0 !important; }
  .card-content { padding: 16px !important; }

  /* Feed posts stretch full width */
  #feed-container { border-radius: 0 !important; box-shadow: none !important; }
  .impact-story .story-header { padding: 14px 16px 8px !important; }

  /* Slider starts flush with screen edge */
  .horizontal-slider-wrapper { padding: 8px 16px 16px !important; }
  .horizontal-slider-container { padding-bottom: 0; }
  
  /* Dashboard market cards responsive
     FIX (request — "reduce card width to 300px, height to 400px"):
     scaled down in step with the new 300px desktop width / 400px card
     height above. */
  #dashboard-market-slider .property-card.mkt-avatar-card {
    max-width: 260px;
    height: 380px;
  }
  #dashboard-market-slider > * {
    flex: 0 0 260px;
    min-width: 260px;
  }
  #dashboard-market-slider {
    padding: 16px 20px !important;
  }
}

  /* News & market cards — slightly smaller on phone */
  .dashboard-news-card, .dashboard-market-card { flex: 0 0 170px !important; width: 170px !important; }
  .dashboard-news-card img, .dashboard-market-card img,
  .dashboard-news-card video, .dashboard-market-card video { height: 130px !important; }

  /* Reel cards */
  .dashboard-reel-card { width: 140px !important; height: 230px !important; }

  .news-list-item { flex-direction: column; gap: 0; }
  .news-item-image { order: 0; width: 100%; height: 180px; margin-bottom: 15px; }
  .header { padding: 20px 16px 12px !important; margin-bottom: 16px; }
  .header h1 { font-size: var(--text-3xl) !important; }
  .stat-value { font-size: var(--text-5xl) !important; }
  /* FIX (request — enlarge card thumbnail, 2026-08-09): 192px → 240px on mobile. */
  .property-card img, .property-card video { height: 240px !important; }
  .mkt-media-carousel { height: 240px !important; }

@media (min-width: 768px) {
  .news-list-item { flex-direction: row; gap: 30px; align-items: flex-start; padding: 25px; }
  .news-item-image { order: 2; width: 160px; height: 160px; margin-bottom: 0; }
  .news-item-content-wrapper { order: 1; }
}

@media (max-width: 480px) {
  #auth-modal-overlay, .modal-overlay-container { align-items: flex-start; padding-top: 5vh; overflow-y: auto; }
  .auth-card, .modal-card { padding: 25px 20px; max-height: none; overflow-y: visible; }
  .auth-card h2, .modal-card h2 { font-size: var(--text-3xl); }
  .avatar-uploader label { width: 100px; height: 100px; }
  .form-group { margin-bottom: 12px; }
  .user-type-selection { gap: 10px; margin-bottom: 20px; }
  .user-type-selection label { padding: 8px 15px; }
  .status-viewer-content { width: 100vw; height: 100dvh; }
}
/* ── Announcement header (redesigned — simple column, no inline-style
   concatenation) ─────────────────────────────────────────────────────
   Previous version built the whole badge/heading/body style attribute by
   concatenating strings on every render. Any leftover/leaked fragment of
   that concatenation (or corrupted data still holding a piece of it) was
   rendered as literal text instead of being parsed as an attribute. Using
   real CSS classes removes that failure mode entirely: nothing is built
   or concatenated per render, so there is no string to leak. */
.ann-block {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 2px 0;
}
.ann-eyebrow {
  display: flex;
  align-items: center;
  gap: 6px;
  font-weight: 800;
  font-size: 0.72rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.ann-eyebrow i { font-size: 0.85em; }
.ann-eyebrow--announcement,
.ann-eyebrow--update   { color: var(--secondary); }
.ann-eyebrow--appreciation { color: #E0A800; }
.ann-eyebrow--sos-thanks   { color: var(--danger-color); }
.ann-title {
  margin: 0;
  font-size: 1.08rem;
  font-weight: 800;
  color: var(--primary);
  line-height: 1.35;
}
.ann-body {
  margin: 0;
  font-size: 0.9rem;
  color: #374151;
  line-height: 1.6;
}
/* =============================================================================
   FIX (2026-07-21) — "+" quick-post button flashing at the TOP of the
   screen during load, instead of only ever appearing at the bottom.
   ROOT CAUSE (confirmed): index.html's static markup gives #quick-post-fab
   an inline `top:14px;right:68px` position. app-fixes.js later repositions
   it to the bottom (bottom:90px;right:20px) once its own init code runs —
   but several other scripts (app-patch-v2.js's _updateFab, app-fix-
   final.js's _showComposerDOM) can flip its `display` from none to flex
   in response to early app-boot events (e.g. the first
   "empyrean-section-change"/navigateTo call), and there is no guarantee
   those fire AFTER app-fixes.js's own repositioning code has already run.
   Whichever happens first wins the race: if display is shown before the
   reposition applies, the button flashes at its ORIGINAL top-right
   position from the static HTML until the reposition catches up a moment
   later.
   FIX: pin the CORRECT final position (bottom-right, matching what
   app-fixes.js already intends as the permanent home for this button)
   directly in the stylesheet with !important. A stylesheet !important
   rule always wins over a plain (non-!important) inline style value for
   the same property — and nothing in this codebase ever sets top/right/
   bottom on this element with !important — so this makes it impossible
   for the button to ever render at the top again, regardless of which
   script's display toggle fires first. Only `display` itself is left
   alone (still controlled by the existing show/hide logic elsewhere),
   so all existing visibility rules (guest hides it, dashboard-only,
   hidden during live streams, etc.) keep working exactly as before.
   ============================================================================= */
/* FIX (2026-08-06 — Help & Assistance Center "?" button and the Report/
   Complaint button both float on top of the Reel viewer's right-side
   engagement column (like/comment/share/download), blocking taps on
   those icons): hidden for the duration of the reel viewer, the same
   way they're already hidden during a live stream (body.emp-live-active,
   above) — see app-patch-v42.js's matching body.emp-reel-active toggle.
   Outside the reel viewer (general public, home page, everywhere else)
   #submit-complaint-fab is untouched — still at its original position
   (bottom:120px;right:16px, set in this stylesheet's earlier rule) and
   still visible to everyone exactly as before. The home-page overlap
   with the quick-post FAB is fixed separately by moving the OTHER
   button involved — the "Minimize video" live-stream PiP button — see
   app-patch-v44-v45.js's own position fix instead. */
body.emp-reel-active #emp-help-fab,
body.emp-reel-active #submit-complaint-fab {
    display: none !important;
}

/* FIX (2026-08-10) — request: "Hide all FAB buttons from the reel
   section." The rule above only covers the fullscreen reel VIEWER
   (body.emp-reel-active, set while a single reel is open full-screen).
   It didn't reach the reel GRID section itself (#reels, browsing the
   "Reels (Shorts)" list) — the Report/Complaint and Help & Assistance
   FABs were still floating over that screen too. body.emp-section-reels
   is set by app-nav.js's navigateTo() whenever the active section is
   'reels' (mirroring the emp-live-active/emp-reel-active pattern already
   used above), and cleared the moment the person navigates anywhere else.
   quick-post-fab needs no rule here — app-nav.js already hides it outside
   the dashboard section unconditionally. */
body.emp-section-reels #emp-help-fab,
body.emp-section-reels #submit-complaint-fab {
    display: none !important;
}

#quick-post-fab {
    position: fixed !important;
    top: auto !important;
    left: auto !important;
    bottom: 90px !important;
    right: 20px !important;
}
@media (max-width: 480px) {
    #quick-post-fab {
        bottom: 80px !important;
        right: 14px !important;
    }
}

/* FIX (2026-07-21, follow-up) — the position pin above stopped the button
   from flashing at the TOP, but it can still appear (correctly positioned,
   at the bottom) WHILE THE APP IS STILL LOADING, which is also unwanted —
   the button should not be visible at all until the app has actually
   finished initializing. The position pin only ever addressed WHERE it
   renders, not WHETHER it's allowed to render yet.
   FIX: hide it unconditionally with !important as long as <body> lacks
   the `emp-app-ready` class. app-patch-v39.js adds that class at the
   exact moment app-fixes.js's own `empyrean-init-done` event fires (the
   one signal in this codebase that means "initial render is actually
   complete" — dashboard built, role resolved, section navigated), with a
   network-aware polling fallback (2026-08-24 follow-up — waits longer on
   a connection the browser itself reports as slow, instead of a single
   fixed timer, so a poor connection can't reveal the nav/FAB while the
   app is still genuinely loading; see app-patch-v39.js's own §2 comment)
   in case that event is ever missed outright. Once the class is
   present, this selector no longer matches anything, so it hands full
   control right back to the existing show/hide logic elsewhere
   (dashboard-only, guest-hidden, hidden during live streams, etc.) —
   nothing about that logic changes, this only gates the EARLY window
   before it's had a chance to run at all. */
/* FIX (2026-07-21, follow-up #2) — the OLD/first-draft bottom navigation
   bar (#mobile-bottom-nav, built by app-fix-final.js's §1 fixBottomNav())
   was also visible during loading. ROOT CAUSE (confirmed): that section's
   own `_build()` runs immediately via `ready(_build)` — i.e. at script-
   parse time, before real auth/role state has resolved — using whatever
   `_isGuest()` returns AT THAT EARLY MOMENT to decide which nav items to
   show. It's rebuilt correctly later on `empyrean-init-done` and
   `empyrean-user-ready`, but that first, possibly-wrong-state draft is
   what was flashing on screen. Same fix as the quick-post FAB above: hide
   it unconditionally until `body.emp-app-ready` is present, which
   app-patch-v39.js adds at the same real "init actually finished" moment
   already used for the FAB. The later rebuild(s) are untouched — once
   `emp-app-ready` is set, this selector stops matching and the nav bar's
   own rendering (correct items, correct active tab) takes over exactly
   as before. */
body:not(.emp-app-ready) #quick-post-fab {
    display: none !important;
}

body:not(.emp-app-ready) #mobile-bottom-nav {
    display: none !important;
}

/* FIX (2026-08-01) — the Messages screen's contact/group list
   (#contacts-inner, built by app-chat.js / app-patch-v14.js /
   app-patch-v20.js, none of which are edited here) briefly rendered its
   own default "No contacts yet." / "No groups yet." empty states during
   the same early startup window as the nav bar/FAB above — visible
   whenever the last-visited section a page load restores into happens to
   be Messages, before the real-time Firestore listeners that populate it
   have returned actual data. Same cause, same fix as the two rules
   above: hide #contacts-inner's contents unconditionally until
   `body.emp-app-ready` lands (app-patch-v39.js, at the one signal that
   means initial render/listener startup is actually done), then hand
   full control straight back — nothing about app-chat.js's, v14's, or
   v20's own rendering changes, this only gates the early window before
   they've had a chance to receive real data yet. */
body:not(.emp-app-ready) #contacts-inner {
    visibility: hidden !important;
}

/* =============================================================================
   NEW FEATURE (2026-07-21) — premium section-navigation transition.
   Implemented entirely with NEW, isolated class/keyframe names
   (.emp-section-transition / @keyframes empSectionEnter, #emp-nav-progress)
   so nothing here touches the shared `fadeIn` keyframe already relied on
   by .content-section.active, .profile-tab-content.active, .kyc-form.active,
   .settings-content.active, and .form-feedback — all of those keep working
   exactly as they already do. app-patch-v40.js applies these classes at
   runtime; see that file for the logic.
   ============================================================================= */

/* Slim top progress bar — plays a brief fill/fade on every section change,
   the same visual cue used by YouTube/Medium/Notion-style "premium" apps.
   Isolated from the splash screen's own `loadProgress` keyframe (different
   element, different animation, cannot collide). */
#emp-nav-progress {
    position: fixed;
    top: 0;
    left: 0;
    height: 3px;
    width: 0%;
    background: linear-gradient(90deg, var(--color-royal), var(--live-color), var(--color-teal));
    z-index: 999999;
    opacity: 0;
    box-shadow: 0 0 8px rgba(91, 14, 166, 0.55);
    border-radius: 0 2px 2px 0;
    pointer-events: none;
    transition: width 0.32s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.25s ease;
}
#emp-nav-progress.emp-nav-progress--active { opacity: 1; }
#emp-nav-progress.emp-nav-progress--done {
    transition: width 0.2s ease, opacity 0.4s ease 0.05s;
    opacity: 0;
}

/* Section entrance — a clean fade on a premium "ease-out-expo"-style
   curve. Higher specificity than the base `.content-section.active {
   animation: fadeIn ... }` rule (3 classes vs 2), so it cleanly overrides
   ONLY the `animation` property for sections that app-patch-v40.js has
   tagged — the base rule, and every other consumer of `fadeIn`, is left
   completely untouched.
   FIX (2026-08-01 — Issue #1: persistent post-load "shaking"): this used
   to also animate `transform: translateY(...) scale(...)`. That was the
   actual cause of the shake, not the settle-window timing app-patch-v40.js
   originally suspected: `.content-section` is the same element other
   listeners read/adjust scroll-position and layout on right around a
   section switch, and a transform animation running on it at that exact
   moment is what read as jitter. Dropped the transform entirely rather
   than disabling the feature — opacity-only has nothing left for a
   concurrent layout/scroll change to visibly collide with, and still
   reads as a deliberate, premium entrance rather than an abrupt cut. The
   previous blanket `animation: none !important` override (and the same
   for #emp-nav-progress, which was never actually implicated — it only
   ever animates its own fixed-position width/opacity, never page
   content) has been removed now that the real cause is fixed here at
   the animation's own definition instead of papered over by disabling
   both effects wholesale. */
@keyframes empSectionEnter {
    from { opacity: 0; }
    to   { opacity: 1; }
}
.content-section.active.emp-section-transition {
    animation: empSectionEnter 0.42s ease-out;
}
@media (prefers-reduced-motion: reduce) {
    .content-section.active.emp-section-transition,
    #emp-nav-progress {
        animation: none !important;
        transition: none !important;
    }
}

/* =============================================================================
   PREMIUM CARD-FORM SYSTEM — SOS "Request Help" + "Report Crisis"  (2026-07-24)
   Scope: #sos-create-panel and #crisis-create-panel only (both use the same
   .emp-form-* classes below so the two sections stay visually IDENTICAL —
   same navy/gold/ivory palette, same serif headings, same card treatment —
   rather than drifting into two different "premium" looks). Reuses the
   existing design tokens (--color-navy, --color-gold, --g-navy, --g-gold,
   --shadow-*, --font-display, --radius-*) already established across the
   app (token.css, Grant Transparency Portal redesign above) — no new
   one-off colours introduced. Additive only — does not touch the base
   .form-group / .card rules other sections still rely on.
   ============================================================================= */

.emp-form-intro h3 {
    font-family: var(--font-display);
    color: var(--color-navy);
    font-size: var(--text-3xl);
    letter-spacing: var(--tracking-tight);
    margin-bottom: 4px;
}
.emp-form-intro p {
    color: var(--text-muted);
    font-size: var(--text-sm);
    margin-bottom: 22px;
}

.emp-form-cards { display: flex; flex-direction: column; gap: 18px; }

.emp-form-card {
    position: relative;
    /* FIX (2026-07-24 — "doesn't blend with other sections"): this used to
       wash the card in var(--color-surface-warm), the same warm-ivory tint
       the rest of the app reserves for warning/pending states (form-feedback
       .warning, KYC/dispute "pending" badges — see style.css search for
       --color-surface-warm). Reusing it here as a plain background made
       these cards read as "caution" against a codebase where every other
       .card is flat white, and looked visually off next to them. Matching
       the base .card surface (plain white) instead keeps the premium feel
       through the gold top-border + navy/gold icon badge alone, and now
       sits flush with every other white card in the app. */
    background: var(--color-white);
    border: 1px solid var(--border);
    border-radius: var(--radius-2xl);
    padding: 22px 24px;
    box-shadow: var(--shadow-md);
    transition: box-shadow 0.25s ease, transform 0.25s ease;
    overflow: hidden;
}
.emp-form-card::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 3px;
    /* FIX (2026-07-24 — step wizard): edge accent moved from gold to blue
       (--color-royal) to match the new wizard progress/nav accent colour. */
    background: var(--g-royal, var(--color-royal));
}
.emp-form-card:hover {
    box-shadow: var(--shadow-lg), var(--shadow-royal-sm, 0 4px 14px rgba(37, 99, 235, 0.18));
    transform: translateY(-2px);
}
.emp-form-card .form-group:last-child { margin-bottom: 0; }

.emp-form-card-head {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 16px;
}
.emp-form-card-head h4 {
    font-family: var(--font-display);
    color: var(--color-navy);
    font-size: var(--text-xl);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-tight);
    margin: 0;
    flex: 1 1 auto;
}
.emp-form-card-icon {
    width: 38px;
    height: 38px;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-full);
    background: var(--g-navy);
    color: var(--color-gold);
    font-size: var(--text-md);
    box-shadow: var(--shadow-navy);
}

/* — Inline SVG icons (Request Help / Report Crisis) —
   FIX (2026-07-24 — broken icons): these forms previously relied on
   Font Awesome <i> glyphs loaded from the cdnjs webfont. On a slow or
   flaky connection the font arrives late or not at all, so the glyph
   renders as an empty "tofu" box — exactly what was reported. Inline
   SVG has no external request and no font-load race, so it renders
   immediately and identically regardless of network conditions. */
.emp-icon {
    width: 1em;
    height: 1em;
    display: inline-block;
    vertical-align: -0.15em;
    flex-shrink: 0;
}
.emp-form-card-icon .emp-icon { width: 1.05em; height: 1.05em; }
.emp-icon-lg { width: 2em; height: 2em; }
.btn .emp-icon { margin-right: 4px; }

.emp-form-card .form-group input,
.emp-form-card .form-group select,
.emp-form-card .form-group textarea {
    background: var(--color-white) !important;
    border: 1.5px solid var(--border-strong) !important;
}
.emp-form-card .form-group input:focus,
.emp-form-card .form-group select:focus,
.emp-form-card .form-group textarea:focus {
    border-color: var(--color-gold) !important;
    box-shadow: 0 0 0 4px rgba(255, 213, 0, 0.16) !important;
}

/* Geological map placeholder — restyled to match card language */
.emp-form-card .map-placeholder {
    background: var(--color-surface-blue);
    border: 1.5px dashed var(--border-strong);
    border-radius: var(--radius-xl);
    color: var(--text-light);
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 140px;
    margin-bottom: 12px;
}
.emp-form-card #crisis-location-coords {
    font-size: var(--text-sm);
    color: var(--text-muted);
    margin: 8px 0 0;
}

/* — Auto-detect location toggle switch (Request Help) — */
.emp-toggle-switch {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    user-select: none;
    flex: 0 0 auto;
}
.emp-toggle-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.emp-toggle-slider {
    position: relative;
    width: 38px;
    height: 20px;
    border-radius: var(--radius-pill);
    background: var(--color-neutral-200);
    transition: background 0.25s ease;
    flex: 0 0 auto;
}
.emp-toggle-slider::before {
    content: '';
    position: absolute;
    top: 2px; left: 2px;
    width: 16px; height: 16px;
    border-radius: var(--radius-full);
    background: var(--color-white);
    box-shadow: var(--shadow-xs);
    transition: transform 0.25s ease;
}
.emp-toggle-switch input:checked + .emp-toggle-slider {
    background: var(--g-gold);
}
.emp-toggle-switch input:checked + .emp-toggle-slider::before {
    transform: translateX(18px);
}
.emp-toggle-switch input:focus-visible + .emp-toggle-slider {
    box-shadow: 0 0 0 3px rgba(255, 213, 0, 0.35);
}
.emp-toggle-label {
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wide);
    white-space: nowrap;
}

.emp-location-status {
    font-size: var(--text-sm);
    color: var(--text-muted);
    margin: 6px 0 0;
    min-height: 1.1em;
}
.emp-location-status.is-detecting { color: var(--color-royal); }
.emp-location-status.is-success   { color: var(--color-success); }
.emp-location-status.is-error     { color: var(--color-danger); }

.emp-form-submit-btn {
    width: 100%;
    margin-top: 4px;
    letter-spacing: var(--tracking-wide);
}

/* — Guided step wizard (Request Help / Report Crisis) — */
.emp-wizard-progress {
    margin-bottom: 22px;
}
.emp-wizard-progress-track {
    height: 6px;
    width: 100%;
    background: var(--color-neutral-200);
    border-radius: var(--radius-pill);
    overflow: hidden;
}
.emp-wizard-progress-fill {
    height: 100%;
    width: 0%;
    background: var(--g-royal, var(--color-royal));
    border-radius: var(--radius-pill);
    transition: width 0.35s ease;
}
.emp-wizard-meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 10px;
}
.emp-wizard-step-count {
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    color: var(--color-royal);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wide);
    white-space: nowrap;
}
.emp-wizard-step-title {
    font-family: var(--font-display);
    font-size: var(--text-md);
    font-weight: var(--weight-semibold);
    color: var(--color-navy);
    text-align: right;
}

.emp-wizard-nav {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 4px;
}
.emp-wizard-back-btn {
    flex: 0 0 auto;
    background: var(--color-white) !important;
    color: var(--color-navy) !important;
    border: 1.5px solid var(--border-strong) !important;
}
.emp-wizard-back-btn:hover {
    background: var(--color-neutral-100) !important;
}
.emp-wizard-next-btn,
.emp-wizard-nav .emp-form-submit-btn {
    flex: 1 1 auto;
    width: auto;
    margin-top: 0;
    background: var(--g-royal, var(--color-royal)) !important;
    color: var(--color-white) !important;
    box-shadow: var(--shadow-royal, 0 4px 14px rgba(37, 99, 235, 0.28)) !important;
}

@media (max-width: 768px) {
    .emp-form-card { padding: 18px 16px; border-radius: var(--radius-xl); }
    .emp-form-card-head h4 { font-size: var(--text-lg); }
    .emp-form-card-icon { width: 34px; height: 34px; }
    .emp-wizard-meta { flex-direction: column; align-items: flex-start; gap: 4px; }
    .emp-wizard-step-title { text-align: left; }
}
/* =============================================================================
   MARKETPLACE DASHBOARD — screenshot-matched UI overhaul.
   Paired with the "§DASHBOARD" section appended to the end of
   app-marketplace.js (category grid, card decoration, filter/sort/
   saved-search toolbar, Home/Saved/Search/Sell/Profile bottom bar).
   Purely additive — no existing marketplace rule above is edited.
   Uses this app's own tokens (--danger-color for the coral price/
   contact/rating accent, --secondary for the navy already used
   elsewhere in the marketplace, --color-gold for the existing badge
   accent) so it stays visually consistent with the rest of the app.
   ============================================================================= */

/* room for the fixed bottom dashboard bar */
#marketplace.content-section { padding-bottom: 78px !important; position: relative; }

/* browse-by-category icon grid */
/* PREMIUM REDESIGN (request): the category browser used to wrap into a
   4-column grid (several rows, small 52px icon tiles). Now a single row
   that scrolls/swipes horizontally, with larger, more premium tiles —
   soft gradient background, deeper icon, subtle shadow/lift on tap —
   scroll-snapped so a swipe settles cleanly on a tile instead of
   stopping mid-item. Scrollbar hidden since the partially-visible next
   tile at the edge is what signals "there's more to the right" here,
   not a visible scrollbar track. */
.mkt-dash-categories {
  display: flex; flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden;
  gap: 14px; padding: 10px 4px 20px;
  scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch;
  scrollbar-width: none; -ms-overflow-style: none;
}
.mkt-dash-categories::-webkit-scrollbar { display: none; height: 0; }
.mkt-dash-cat-item {
  flex: 0 0 auto; width: 84px; scroll-snap-align: start;
  display: flex; flex-direction: column; align-items: center; gap: 9px;
  background: none; border: none; cursor: pointer; font-family: var(--font-ui);
}
.mkt-dash-cat-icon {
  width: 66px; height: 66px; border-radius: 20px;
  background: linear-gradient(160deg, rgba(27,43,139,0.09), rgba(27,43,139,0.04));
  border: 1px solid rgba(var(--color-navy-rgb), 0.07);
  display: flex; align-items: center; justify-content: center;
  font-size: 26px; color: var(--secondary);
  box-shadow: 0 3px 10px rgba(10,14,39,0.06);
  transition: transform .15s, box-shadow .15s, background .15s;
}
.mkt-dash-cat-item:active .mkt-dash-cat-icon {
  transform: scale(0.93);
  box-shadow: 0 1px 4px rgba(10,14,39,0.08);
  background: linear-gradient(160deg, rgba(27,43,139,0.14), rgba(27,43,139,0.07));
}
.mkt-dash-cat-label { font-size: 12px; line-height: 1.25; text-align: center; color: var(--primary); font-weight: 600; }

/* "Featured Listings" section title */
.mkt-dash-section-title { font-size: var(--text-xl); font-weight: 800; color: var(--primary); margin: 6px 4px 14px; font-family: var(--font-ui); }

/* card decoration overlay pieces */
.property-card { position: relative; }
.mkt-card-media-wrap { position: relative; }
.mkt-ribbons { position: absolute; top: 10px; left: 10px; display: flex; flex-direction: column; gap: 6px; z-index: 2; }
.mkt-ribbon { font-size: 10.5px; font-weight: 800; letter-spacing: .2px; padding: 4px 10px; border-radius: 6px; color: #fff; text-transform: capitalize; box-shadow: 0 2px 6px rgba(0,0,0,.18); }
.mkt-ribbon-featured { background: var(--danger-color); }
.mkt-ribbon-verified { background: #fff; color: var(--primary); }
.mkt-icon-actions { position: absolute; top: 10px; right: 10px; display: flex; gap: 8px; z-index: 2; }
.mkt-icon-btn { width: 32px; height: 32px; border-radius: 50%; background: rgba(20,20,30,0.45); backdrop-filter: blur(2px); border: none; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 14px; cursor: pointer; transition: background .15s, transform .15s; }
.mkt-icon-btn:active { transform: scale(0.9); }
.mkt-icon-btn.mkt-saved { color: var(--danger-color); background: rgba(255,255,255,0.85); }
.mkt-play-overlay { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 56px; height: 56px; border-radius: 50%; background: rgba(20,20,30,0.45); display: flex; align-items: center; justify-content: center; color: #fff; font-size: 20px; z-index: 2; pointer-events: none; }

/* price / rating / contact row, screenshot-matched */
.property-info > div:last-child { color: var(--danger-color) !important; }
.mkt-price-row { display: flex; align-items: baseline; gap: 8px; }
.mkt-price-old { font-size: var(--text-sm); color: var(--text-muted); text-decoration: line-through; font-weight: 600; }
.mkt-rating-contact-row { display: flex; align-items: center; justify-content: space-between; padding: 0 12px 12px; gap: 10px; }
.mkt-rating-line { font-size: 11.5px; color: var(--text-muted); display: flex; align-items: center; gap: 4px; }
.mkt-rating-line i { color: var(--color-gold); font-size: 11px; }
.property-actions .btn-accent.add-to-cart-btn,
.property-actions .btn-danger.contact-seller-btn { border-radius: var(--radius-pill) !important; background: var(--danger-color) !important; border: none !important; padding: 9px 20px !important; font-size: var(--text-sm) !important; }

/* saved-tab empty state */
.mkt-saved-empty { grid-column: 1/-1; text-align: center; padding: 40px 20px; color: var(--text-muted); }
.mkt-saved-empty i { font-size: 2rem; display: block; margin-bottom: 10px; }

/* Search tab: draw attention to the existing search bar */
.mkt-search-spotlight { box-shadow: 0 0 0 3px rgba(var(--color-navy-rgb), 0.18) !important; border-radius: 14px; }

/* filter/sort/saved-search toolbar */
#mkt-search-toolbar { display: none; padding: 4px 4px 16px; }
#mkt-search-toolbar.mkt-toolbar-visible { display: block; }
.mkt-filter-tabs-row { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 10px; -webkit-overflow-scrolling: touch; }
.mkt-filter-tabs-row::-webkit-scrollbar { display: none; }
.mkt-filter-tab { flex: 0 0 auto; padding: 8px 15px; border-radius: var(--radius-pill); border: 1.5px solid rgba(var(--color-navy-rgb), 0.15); background: #fff; font-size: var(--text-sm); font-weight: 700; color: var(--color-neutral-600); cursor: pointer; white-space: nowrap; }
.mkt-filter-tab.active { background: var(--secondary); border-color: var(--secondary); color: #fff; }
.mkt-sort-save-row { display: flex; gap: 10px; align-items: center; margin-bottom: 10px; }
#mkt-sort-select { flex: 1; padding: 9px 12px; border-radius: 10px; border: 1.5px solid rgba(var(--color-navy-rgb), 0.15); background: #fff; font-size: var(--text-sm); color: var(--primary); }
#mkt-save-search-btn { padding: 9px 14px; border-radius: 10px; border: 1.5px solid rgba(var(--color-navy-rgb), 0.15); background: #fff; font-size: var(--text-sm); font-weight: 700; color: var(--secondary); cursor: pointer; white-space: nowrap; }
#mkt-saved-searches { display: flex; gap: 8px; flex-wrap: wrap; }
.mkt-saved-search-chip { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-xs); background: rgba(var(--color-navy-rgb), 0.06); color: var(--primary); padding: 5px 10px; border-radius: var(--radius-pill); cursor: pointer; }
.mkt-saved-search-chip .remove-chip { color: var(--danger-color); font-weight: 800; padding-left: 2px; }

/* Top dashboard bar — sticky directly under the "Marketplace" header (this
   is where app-marketplace.js's _mktBuildSubnav() actually inserts it in the
   DOM). Previously this rule pinned the bar to `bottom:0` of the whole
   scrollable section, which is what made it appear to float near the end
   of the content instead of at the top — fixed here to match. */
#mkt-subnav { position: sticky; top: 0; left: 0; right: 0; display: flex; background: #fff; border-bottom: 1px solid rgba(var(--color-navy-rgb), 0.08); box-shadow: 0 2px 10px rgba(0,0,0,0.05); z-index: 20; }
#mkt-subnav .mkt-subnav-tab { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 9px 2px 8px; background: none; border: none; cursor: pointer; color: var(--text-muted); font-family: var(--font-ui); }
#mkt-subnav .mkt-subnav-tab i, #mkt-subnav .mkt-subnav-tab svg { font-size: 18px; width: 18px; height: 18px; }
#mkt-subnav .mkt-subnav-tab span { font-size: 10px; font-weight: 700; }
#mkt-subnav .mkt-subnav-tab.active { color: var(--danger-color); }
#mkt-subnav .mkt-subnav-tab .mkt-inbox-tab-badge {
  position: absolute; margin-left: 10px; margin-top: -14px; background: #EF4444; color: #fff;
  font-size: 9px; font-weight: 800; min-width: 15px; height: 15px; border-radius: 8px;
  display: flex; align-items: center; justify-content: center; padding: 0 3px;
}

/* The global mobile sidebar toggle (the small dark rounded-square hamburger
   button, fixed top-left) has no place overlapping the Marketplace's own
   Home/Saved/Search/Profile views — it's confined to the Sell tab only,
   where it doesn't sit on top of listing content. Toggled by
   app-marketplace.js's _mktSetActiveTab() via body.mkt-hide-menu-toggle. */
body.mkt-hide-menu-toggle .mobile-menu-toggle { display: none !important; }

/* ── Sell flow, step 1: accordion category chooser (modeled on the
   "Select a category from the list below" reference) ───────────────── */
.mkt-sell-step-title { font-size: var(--text-md); font-weight: 700; color: var(--primary); margin: 4px 0 14px; }
.mkt-sell-category-list { border: 1px solid rgba(var(--color-navy-rgb),0.10); border-radius: 14px; overflow: hidden; }
.mkt-sell-cat-row { border-bottom: 1px solid rgba(var(--color-navy-rgb),0.08); }
.mkt-sell-cat-row:last-child { border-bottom: none; }
.mkt-sell-cat-head { display: flex; align-items: center; gap: 12px; width: 100%; padding: 14px 16px; background: #fff; border: none; cursor: pointer; text-align: left; font-family: var(--font-ui); }
.mkt-sell-cat-head svg { flex-shrink: 0; color: var(--secondary); }
.mkt-sell-cat-head span.mkt-sell-cat-label { flex: 1; font-size: var(--text-sm); font-weight: 600; color: var(--primary); }
.mkt-sell-cat-head .mkt-sell-cat-chevron { transition: transform 0.18s; color: var(--text-muted); flex-shrink: 0; }
.mkt-sell-cat-row.open .mkt-sell-cat-head .mkt-sell-cat-chevron { transform: rotate(180deg); }
/* FIX (bug — categories used to expand their subcategories inline in an
   accordion here; now each category navigates to its own dedicated
   #mkt-sell-subcategory-step page instead, so nothing in this list ever
   gets an .open class or a nested .mkt-sell-cat-subs div anymore). The
   two rules below are dead code from that old design — left in place
   rather than deleted per this codebase's no-deletion convention. */
.mkt-sell-cat-subs { max-height: 0; overflow: hidden; transition: max-height 0.22s ease; background: rgba(var(--color-navy-rgb),0.02); }
.mkt-sell-cat-row.open .mkt-sell-cat-subs { max-height: 480px; }
/* Subcategory-page buttons — flat top-level rows now (own dedicated page),
   not indented accordion children, so they get the same row treatment as
   .mkt-sell-cat-head rather than the old indented/bordered flat-text style. */
.mkt-sell-cat-sub-btn { display: flex; align-items: center; gap: 12px; width: 100%; text-align: left; padding: 14px 16px; background: #fff; border: none; border-bottom: 1px solid rgba(var(--color-navy-rgb),0.08); cursor: pointer; font-family: var(--font-ui); font-size: var(--text-sm); font-weight: 600; color: var(--primary); }
.mkt-sell-cat-sub-btn:last-child { border-bottom: none; }
.mkt-sell-cat-sub-btn .mkt-sell-cat-chevron { margin-left: auto; color: var(--text-muted); flex-shrink: 0; }
.mkt-sell-cat-sub-btn:active { background: rgba(var(--color-navy-rgb),0.06); }

/* ── Seller-profile swipe banner: removed from the Marketplace UI per
   request. This selector is a belt-and-braces safety net in case any
   cached/older script on the live site still creates the element — it
   guarantees the banner never renders even then. ─────────────────── */
#mkt-seller-swipe-banner, .mkt-seller-swipe-banner { display: none !important; }

/* ── Per-category dynamic "Ad Details" fields ───────────────────────
   Built fresh per category by _mktRenderDynamicFields() in
   app-marketplace.js; reuses the existing .form-group look so each
   field matches the rest of the sell form. */
.mkt-dynamic-fields { margin-bottom: 4px; }
.mkt-dynamic-fields .form-group { margin-bottom: 15px; }
.mkt-dynamic-fields .grid-2 { margin-bottom: 0; }
.mkt-dyn-section-label { font-size: var(--text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--color-neutral-500); margin: 4px 0 10px; }

/* ── Cascading Location (State → LGA) selects ───────────────────── */
.mkt-location-cascade select:disabled { opacity: 0.55; cursor: not-allowed; }

/* ── Multi-select dropdown (Features / Amenities) ───────────────────
   A button that toggles a checklist panel, grouped into sections, plus
   a row of chips underneath showing the current selection. */
.mkt-multiselect { position: relative; }
.mkt-multiselect-btn { display: flex; align-items: center; justify-content: space-between; width: 100%; padding: 12px; font-size: var(--text-lg); background: var(--color-surface-blue); border: 1.5px solid rgba(10,14,39,0.10); border-radius: var(--radius-xl); color: var(--primary); cursor: pointer; text-align: left; font-family: var(--font-ui); }
.mkt-multiselect-btn .mkt-multiselect-count { font-size: var(--text-xs); font-weight: 700; background: var(--secondary); color: #fff; border-radius: 999px; padding: 2px 9px; margin-left: 8px; }
.mkt-multiselect-btn i { transition: transform 0.18s; color: var(--text-muted); flex-shrink: 0; }
.mkt-multiselect.open .mkt-multiselect-btn i { transform: rotate(180deg); }
.mkt-multiselect-panel { display: none; position: relative; margin-top: 8px; border: 1.5px solid rgba(10,14,39,0.10); border-radius: var(--radius-xl); background: #fff; max-height: 340px; overflow-y: auto; padding: 6px 4px; box-shadow: 0 8px 24px rgba(10,14,39,0.10); }
.mkt-multiselect.open .mkt-multiselect-panel { display: block; }
.mkt-multiselect-group-title { padding: 10px 12px 6px; font-size: var(--text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--secondary); }
.mkt-multiselect-option { display: flex; align-items: center; gap: 10px; padding: 9px 12px; cursor: pointer; border-radius: 10px; font-size: var(--text-sm); color: var(--color-neutral-700); }
.mkt-multiselect-option:hover { background: rgba(var(--color-navy-rgb),0.05); }
.mkt-multiselect-option input[type="checkbox"] { width: 17px; height: 17px; flex-shrink: 0; accent-color: var(--secondary); }
.mkt-multiselect-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.mkt-multiselect-chip { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-xs); font-weight: 600; background: rgba(27,43,139,0.08); color: var(--secondary); padding: 5px 10px; border-radius: 999px; }
.mkt-multiselect-chip .remove-chip { cursor: pointer; font-weight: 800; }

/* Sell flow, step 2: "Ad Details" — chosen-category readout + back button */
.mkt-sell-back-btn { display: inline-flex; align-items: center; gap: 8px; background: none; border: none; padding: 8px 4px; margin-left: -4px; border-radius: 999px; font-family: var(--font-ui); font-size: var(--text-sm); font-weight: 700; color: var(--secondary); cursor: pointer; transition: var(--transition-base); }
.mkt-sell-back-btn:hover { background: rgba(var(--color-navy-rgb),0.05); transform: translateX(-2px); }
.mkt-sell-back-btn:active { transform: translateX(-2px) scale(0.97); }
.mkt-sell-chosen-cat { font-size: var(--text-sm); font-weight: 700; color: var(--primary); background: rgba(var(--color-navy-rgb),0.05); border-radius: 10px; padding: 10px 14px; margin-bottom: 16px; }
.mkt-sell-chosen-cat span { color: var(--secondary); }

/* ── PREMIUM REDESIGN — "List Your Item" form ────────────────────────
   Elevates the Ad Details step (previously plain, unstyled sections —
   .mkt-form-heading/.mkt-form-section/.mkt-form-section-title existed
   in index.html's markup but had no rules here, so the form rendered
   as bare stacked inputs with no grouping or hierarchy) to a classic,
   elegant, card-grouped layout consistent with the app's existing
   token set (colors, radii, shadows, type scale — nothing new
   introduced). Purely additive CSS; no markup or JS behavior changes. */
.mkt-form-heading {
  font-family: var(--font-display, var(--font-ui));
  font-size: var(--text-xl, 1.4rem);
  font-weight: 800;
  color: var(--primary);
  letter-spacing: -0.01em;
  margin: 2px 0 14px;
}

.mkt-form-section {
  background: var(--color-white, #fff);
  border: 1px solid rgba(var(--color-navy-rgb), 0.08);
  border-radius: var(--radius-xl, 18px);
  padding: 20px 18px;
  margin-bottom: 18px;
  box-shadow: 0 2px 10px rgba(10, 14, 39, 0.04);
  transition: box-shadow 0.2s ease, border-color 0.2s ease;
}
.mkt-form-section:focus-within {
  border-color: rgba(27, 43, 139, 0.18);
  box-shadow: 0 4px 18px rgba(10, 14, 39, 0.07);
}
.mkt-form-section:last-of-type { margin-bottom: 22px; }

.mkt-form-section-title {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: var(--text-xs, 0.78rem);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide, 0.06em);
  color: var(--secondary);
  margin: 0 0 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid rgba(var(--color-navy-rgb), 0.07);
}
.mkt-form-section-title::before {
  content: '';
  display: inline-block;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--g-gold, var(--accent-color));
  flex-shrink: 0;
}
.mkt-form-section .form-group:last-child { margin-bottom: 0; }

/* Slightly more refined field chrome specifically within the sell
   form's own sections — a touch more breathing room and a softer,
   classic focus treatment than the compact default .form-group. */
.mkt-form-section .form-group label { font-size: 0.72rem; color: var(--color-neutral-600) !important; }
.mkt-form-section .form-group input,
.mkt-form-section .form-group select,
.mkt-form-section .form-group textarea {
  background: var(--color-white) !important;
  border: 1.5px solid rgba(10, 14, 39, 0.09) !important;
}
.mkt-form-section .form-group input:hover,
.mkt-form-section .form-group select:hover,
.mkt-form-section .form-group textarea:hover {
  border-color: rgba(10, 14, 39, 0.18) !important;
}
.mkt-form-section textarea { resize: vertical; min-height: 96px; line-height: 1.5; }

.mkt-form-section .grid-2 { gap: 14px; }

.mkt-form-section .btn-media-upload {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--color-surface-blue, rgba(27,43,139,0.04)) !important;
  border: 1.5px dashed rgba(27, 43, 139, 0.25) !important;
  color: var(--secondary) !important;
  border-radius: var(--radius-xl, 14px);
  padding: 12px 18px;
  font-weight: 700;
  transition: var(--transition-base);
}
.mkt-form-section .btn-media-upload:hover {
  background: rgba(27, 43, 139, 0.08) !important;
  border-color: var(--secondary) !important;
}

.mkt-form-submit-btn {
  width: 100%;
  padding: 15px;
  font-size: var(--text-md, 1rem);
  font-weight: 800;
  letter-spacing: 0.01em;
  border-radius: var(--radius-xl, 16px) !important;
  margin-top: 4px;
}

/* ── AVATAR CARDS CAROUSEL (Jobs, Job Seeking, Professional Services) ──
   Dedicated horizontally scrollable container for avatar-based listings.
   These represent people and services, not products, so they get their
   own premium teal-gradient styled shelf instead of being scattered in
   the main product grid. */
#mkt-avatar-carousel {
  width: 100%;
  background: var(--color-white, #fff);
  border-radius: var(--radius-xl, 16px);
  overflow: hidden;
  margin: 24px 0;
  border: 1px solid rgba(10, 14, 39, 0.06);
  box-shadow: 0 2px 12px rgba(10, 14, 39, 0.04);
  /* FIX (request — relocate this shelf from the top of the marketplace
     listing to the middle): once app-marketplace.js's
     _mktRepositionAvatarCards() moves this element into
     #property-grid-container, this makes it span the full grid row
     (like the section header it replaces) instead of collapsing into a
     single grid cell. No effect while it sits outside the grid. */
  grid-column: 1 / -1;
}
#mkt-avatar-carousel h3 {
  font-size: 1.1rem;
  font-weight: 600;
  margin: 16px 0 8px 12px;
  color: var(--primary, #1B2B8B);
  letter-spacing: -0.01em;
}

/* Horizontally scrollable inner track */
.mkt-avatar-carousel-inner {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  gap: 0; /* edge-to-edge cards, per request */
  padding: 0;
  scroll-behavior: smooth;
  scrollbar-width: none; /* Firefox */
  -webkit-overflow-scrolling: touch; /* iOS momentum scroll */
}
.mkt-avatar-carousel-inner::-webkit-scrollbar { display: none; } /* Chrome/Safari */

/* ── "Jobs & Services" marketplace shelf — redesigned to match the
   dashboard's "Latest News" card exactly ─────────────────────────────
   FIX (request — "redesigned exactly like the news card in screenshot
   2. Stretch the card to get to edge to edge, reduce the length of
   height and increase the width"): the previous version was a tall
   272px-wide portrait card (min-height 410px) — the opposite of the
   news card's proportions. This now mirrors .dashboard-news-card's own
   structure and measurements 1:1 — same rounded corners, same flat
   white background, same lightweight shadow, same 160px media-strip
   height, same compact info-panel padding and clamped 2-line title —
   with the one deliberate difference being width: instead of the news
   card's fixed 200px slide, this card stretches to fill the full width
   of the carousel edge-to-edge (flex/width: 100%), which is also what
   drives the height down (a wide, short card instead of a narrow, tall
   one) exactly as requested. Scoped entirely to
   .mkt-avatar-carousel-inner (the shelf as it renders inside the
   Marketplace tab) so the home-page dashboard slider
   (#dashboard-market-slider) and the base .property-card.mkt-avatar-card
   fallback are both left exactly as they were. */
.mkt-avatar-carousel-inner {
  gap: 16px;
  padding: 4px 0 18px;
}
.mkt-avatar-carousel-inner .property-card.mkt-avatar-card {
  flex: 0 0 100%;
  min-width: 100%;
  max-width: 100%;
  width: 100%;
  height: auto;
  min-height: 0;
  grid-column: auto !important; /* Override grid-column: 1/-1 */
  display: flex;
  flex-direction: column;
  background: var(--color-white, #fff) !important;
  box-shadow: 0 2px 8px rgba(10,14,39,0.10), 0 1px 2px rgba(10,14,39,0.06) !important;
  border: none !important;
  border-radius: 16px !important;
  padding: 0 !important;
  overflow: hidden;
  transition: box-shadow 0.22s ease, transform 0.22s ease;
  cursor: pointer;
}
.mkt-avatar-carousel-inner .property-card.mkt-avatar-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 8px 28px rgba(10,14,39,0.16), 0 2px 6px rgba(10,14,39,0.08) !important;
}

/* Media strip — same 160px height as .dashboard-news-card img/video, so
   the "photo area" of this card is proportioned exactly like the news
   card's, with the avatar/portfolio strip centered inside it. */
.mkt-avatar-carousel-inner .mkt-avatar-top {
  display: flex;
  flex-direction: column;
  height: auto;
}
.mkt-avatar-carousel-inner .mkt-card-media-wrap {
  width: 100%;
  height: 160px;
  flex: 0 0 160px;
  background: linear-gradient(160deg, #0B3D2C 0%, #118B6B 50%, #1AA588 100%);
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.mkt-avatar-carousel-inner .mkt-avatar-scroll {
  flex: 0 0 auto;
  width: 100%;
  height: 100%;
  padding: 0 16px;
  justify-content: center;
  align-items: center;
  gap: 12px;
}
.mkt-avatar-carousel-inner .mkt-avatar-scroll-item {
  flex-basis: 60px;
  height: 60px;
}
.mkt-avatar-carousel-inner .mkt-avatar-scroll-item.mkt-avatar-main {
  flex-basis: 76px;
  height: 76px;
}

/* Content panel — same padding/scale as .dashboard-news-card-info, a
   compact bar instead of a roomy portrait panel. */
.mkt-avatar-carousel-inner .mkt-avatar-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 12px 14px 14px !important;
}
.mkt-avatar-carousel-inner .mkt-avatar-info,
.mkt-avatar-carousel-inner .mkt-avatar-info p,
.mkt-avatar-carousel-inner .mkt-avatar-desc {
  color: var(--primary, #1B2B8B) !important;
}
.mkt-avatar-carousel-inner .mkt-avatar-info .mkt-avatar-role-badge {
  background: linear-gradient(135deg, #D4AF37, #F0D584) !important;
  color: #0B3D2C !important;
  border: none !important;
  font-size: 0.7rem !important;
  padding: 4px 12px !important;
  font-weight: 800 !important;
  letter-spacing: 0.02em;
  box-shadow: 0 3px 10px rgba(212,175,55,0.3);
}
.mkt-avatar-carousel-inner .mkt-avatar-title-scroll {
  overflow: visible;
  width: 100%;
  margin: 8px 0 4px;
}
.mkt-avatar-carousel-inner .mkt-avatar-title-scroll h4 {
  white-space: normal;
  flex-shrink: 1;
}
/* Title clamped to 2 lines at the same 0.84rem scale as
   .dashboard-news-card-info h5, matching the news card exactly. */
.mkt-avatar-carousel-inner .mkt-avatar-info h4 {
  font-size: 0.84rem !important;
  line-height: 1.35 !important;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.mkt-avatar-carousel-inner .mkt-avatar-quals {
  margin-bottom: 6px;
}
.mkt-avatar-carousel-inner .mkt-avatar-quals .mkt-qual-chip {
  background: rgba(212, 175, 55, 0.14);
  color: #8A6D14;
  box-shadow: none;
  border: 1px solid rgba(212, 175, 55, 0.4);
}
.mkt-avatar-carousel-inner .mkt-avatar-desc {
  font-size: 0.8rem !important;
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.mkt-avatar-carousel-inner .mkt-avatar-price {
  color: #0B7A5A !important;
  text-shadow: none !important;
  font-size: 0.95rem !important;
  margin-top: auto !important;
  padding-top: 8px;
  border-top: 1px dashed rgba(212,175,55,0.45);
}
.mkt-avatar-carousel-inner .property-card.mkt-avatar-card .property-seller-info {
  background: rgba(11, 61, 44, 0.05) !important;
  color: var(--primary, #1B2B8B) !important;
  border-top: 1px solid rgba(212,175,55,0.28) !important;
}

/* ── AVATAR CARDS CAROUSEL — premium shelf refinements ──────────────────
   FIX (request — "make the horizontal scrollable job and professional
   service rendering categories card... more professional premium classic
   elegant sleek and beautiful"): purely additive polish layered on top of
   the existing shelf above — no existing rule is removed, every selector
   here is either new (the header) or more specific than what's already
   defined for the same property, so it wins on the cascade without
   deleting anything. Borrows the app's OWN established "premium/classic"
   visual language — deep navy, antique gold (#D4AF37/#F0D584, already
   used on this exact shelf's role badge), and a Georgia-serif kicker with
   wide letter-spacing — from #app-concept-screen's .kicker/.hero
   treatment, so this reads as one deliberate identity already present in
   the app rather than a new, unrelated style bolted on. */

/* Container: soften into a genuine "premium shelf" — a fine gold hairline
   frame, a deeper resting shadow, and a slim gold-gradient ribbon along
   the top edge (the same kind of accent line a printed programme or menu
   uses to mark a featured section). */
#mkt-avatar-carousel {
  position: relative;
  border: 1px solid rgba(212, 175, 55, 0.22) !important;
  border-radius: 18px !important;
  box-shadow: 0 1px 2px rgba(10,14,39,0.04), 0 10px 30px rgba(10,14,39,0.07) !important;
  overflow: hidden;
}
#mkt-avatar-carousel::before {
  content: '';
  position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: linear-gradient(90deg, transparent, #D4AF37 18%, #F0D584 50%, #D4AF37 82%, transparent);
  opacity: 0.85;
}

/* Header: kicker + serif title + a slim gold divider, replacing the plain
   default h3 that used to sit here. */
.mkt-avatar-shelf-header {
  padding: 20px 16px 10px;
  text-align: center;
}
.mkt-avatar-shelf-kicker {
  display: inline-block;
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 0.68rem;
  font-weight: 400;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: #B8912E;
  margin-bottom: 6px;
}
.mkt-avatar-shelf-header h3 {
  margin: 0 auto 10px;
  font-family: Georgia, 'Times New Roman', serif;
  font-weight: 400;
  font-size: 1.2rem;
  letter-spacing: 0.02em;
  color: var(--primary, #1B2B8B);
}
.mkt-avatar-shelf-header::after {
  content: '';
  display: block;
  width: 46px;
  height: 2px;
  margin: 0 auto;
  background: linear-gradient(90deg, #D4AF37, #F0D584);
  border-radius: 2px;
}

/* Scroll behavior: crisp, deliberate paging between cards instead of a
   loose free-scroll — each swipe settles cleanly on the next card,
   the way a well-made physical carousel clicks into place. */
.mkt-avatar-carousel-inner {
  scroll-snap-type: x mandatory;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 14px, #000 calc(100% - 14px), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 14px, #000 calc(100% - 14px), transparent 100%);
}
.mkt-avatar-carousel-inner .property-card.mkt-avatar-card {
  scroll-snap-align: center;
  scroll-snap-stop: always;
  border: 1px solid rgba(212, 175, 55, 0.16) !important;
}
.mkt-avatar-carousel-inner .property-card.mkt-avatar-card:hover {
  border-color: rgba(212, 175, 55, 0.4) !important;
}

/* Media strip: a soft vignette for depth, and an elegant gold ring around
   the seller's own portrait (the "main" avatar item) so it reads as a
   framed photograph rather than a plain thumbnail. */
.mkt-avatar-carousel-inner .mkt-card-media-wrap {
  position: relative;
  background: linear-gradient(160deg, #082A20 0%, #0F7A5E 55%, #189D80 100%);
}
.mkt-avatar-carousel-inner .mkt-card-media-wrap::after {
  content: '';
  position: absolute; inset: 0;
  background: radial-gradient(ellipse at center, transparent 45%, rgba(5,10,8,0.28) 100%);
  pointer-events: none;
}
.mkt-avatar-carousel-inner .mkt-avatar-scroll-item.mkt-avatar-main {
  box-shadow: 0 0 0 2px rgba(212,175,55,0.55), 0 4px 14px rgba(0,0,0,0.35);
}

/* Role badge: a touch more "medal" than "sticker" — a fine inner highlight
   along the top edge, tighter tracking. */
.mkt-avatar-carousel-inner .mkt-avatar-info .mkt-avatar-role-badge {
  letter-spacing: 0.06em !important;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.5), 0 3px 10px rgba(212,175,55,0.3) !important;
}

/* ── Marketplace Adjustments #8 (2026-08-09 — "should be premium white...
   reduce the size of the card more or redesign to something more
   beautiful and elegant"): this "Jobs & Services" CURATED shelf — the
   #mkt-avatar-carousel-inner card every avatar listing (Job Seeking /
   Professional Services / Job Vacancy) actually ends up inside, since
   _mktRepositionAvatarCards() relocates every one of them out of the
   plain grid and into this shelf — is a SEPARATE, more specific set of
   rules from the #property-grid-container ones Adjustments #7 already
   turned white. Adjustments #7 alone couldn't have been visible here:
   this card's own .mkt-card-media-wrap background (a dark forest-green
   gradient) is set by class-only selectors below that #property-grid-
   container's ID-scoped rules never targeted, so the photo strip stayed
   green regardless. Retired that dark green ground here too — same
   ivory/gold "premium white" language as #7 — and trimmed every
   dimension down another step (shorter media strip, smaller avatar
   thumbnails, tighter padding/type) on top of the size cuts #7 already
   made to the grid version.
   SCOPING: every rule below is scoped to #mkt-avatar-carousel-inner
   (an actual element id, not just a class — see index.html), so nothing
   else on the page — including the homepage dashboard slider/strip this
   request explicitly said not to touch — is affected. */
#mkt-avatar-carousel-inner .property-card.mkt-avatar-card {
  border-radius: 12px !important;
  box-shadow: 0 1px 2px rgba(10,14,39,0.05), 0 8px 20px rgba(10,14,39,0.08) !important;
}
#mkt-avatar-carousel-inner .mkt-card-media-wrap {
  height: 116px !important;
  flex: 0 0 116px !important;
  background:
    radial-gradient(circle at 22% 20%, rgba(212, 175, 55, 0.10), transparent 55%),
    linear-gradient(135deg, #FFFFFF 0%, #FDFCF8 55%, #F6F2E7 100%) !important;
  border-bottom: 1px solid rgba(212, 175, 55, 0.26);
}
#mkt-avatar-carousel-inner .mkt-card-media-wrap::after {
  background: none !important;
}
#mkt-avatar-carousel-inner .mkt-avatar-scroll {
  gap: 8px !important;
  padding: 0 12px !important;
}
#mkt-avatar-carousel-inner .mkt-avatar-scroll-item {
  flex-basis: 44px !important;
  height: 44px !important;
  border-radius: 9px !important;
  border-color: rgba(212, 175, 55, 0.55) !important;
  box-shadow: 0 0 0 2px rgba(212, 175, 55, 0.10), 0 2px 6px rgba(10, 14, 39, 0.10) !important;
}
#mkt-avatar-carousel-inner .mkt-avatar-scroll-item.mkt-avatar-main {
  flex-basis: 56px !important;
  height: 56px !important;
  border-color: #D4AF37 !important;
  box-shadow: 0 0 0 3px rgba(212, 175, 55, 0.20), 0 3px 10px rgba(10, 14, 39, 0.14) !important;
}
#mkt-avatar-carousel-inner .mkt-avatar-scroll-item.mkt-avatar-initials {
  background: radial-gradient(circle at 38% 30%, rgba(212, 175, 55, 0.20), rgba(246, 242, 231, 0.9) 60%) !important;
}
#mkt-avatar-carousel-inner .mkt-avatar-scroll-item.mkt-avatar-initials span {
  color: #A8841F !important;
}
#mkt-avatar-carousel-inner .mkt-avatar-info {
  padding: 8px 11px 10px !important;
}
#mkt-avatar-carousel-inner .mkt-avatar-info h4 {
  font-size: 0.78rem !important;
  font-family: Georgia, 'Times New Roman', serif !important;
  color: #0F1B4C !important;
}
#mkt-avatar-carousel-inner .mkt-avatar-info,
#mkt-avatar-carousel-inner .mkt-avatar-info p,
#mkt-avatar-carousel-inner .mkt-avatar-desc {
  color: rgba(30, 35, 60, 0.72) !important;
  font-size: 0.68rem !important;
}
#mkt-avatar-carousel-inner .mkt-avatar-quals {
  margin-bottom: 4px !important;
}
#mkt-avatar-carousel-inner .mkt-avatar-quals .mkt-qual-chip {
  color: #8A6D1F !important;
  font-size: 0.64rem !important;
  padding: 2px 8px !important;
}
#mkt-avatar-carousel-inner .mkt-avatar-price {
  color: #A8841F !important;
  font-size: 0.86rem !important;
  padding-top: 5px !important;
}
#mkt-avatar-carousel-inner .property-card.mkt-avatar-card .property-seller-info {
  background: rgba(10, 14, 39, 0.03) !important;
  color: rgba(30, 35, 60, 0.72) !important;
}

/* ── "Badge" ID Card — grid thumbnail / "Jobs & Services" horizontal
   carousel (request — "fix the scrollable horizontal card inside the
   marketplace section... integrate the code into the existing
   codebase") ──────────────────────────────────────────────────────────
   Every avatar-category card is relocated into #mkt-avatar-carousel-inner
   by _mktRepositionAvatarCards (app-marketplace.js), so that ID-scoped
   selector is what actually renders on screen — these rules target it
   directly (ID beats the earlier class-only "premium white" rules above
   without needing !important gymnastics) plus a matching
   #property-grid-container fallback for the brief moment before a card
   is relocated. window._mktAvatarBadgeCardHTML (app-marketplace.js)
   builds the .mkt-badgecard markup these style. */
#mkt-avatar-carousel-inner .property-card.mkt-avatar-card,
#property-grid-container .property-card.mkt-avatar-card {
  background: linear-gradient(145deg, #0e1e38, #162a4a) !important;
  border: 1px solid #d4af37 !important;
}
#mkt-avatar-carousel-inner .property-card.mkt-avatar-card .property-seller-info,
#property-grid-container .property-card.mkt-avatar-card .property-seller-info {
  background: rgba(0, 0, 0, 0.18) !important;
  color: #a0aec0 !important;
  border-top: 1px solid rgba(212, 175, 55, 0.25) !important;
}
#mkt-avatar-carousel-inner .property-card.mkt-avatar-card .property-seller-info strong,
#property-grid-container .property-card.mkt-avatar-card .property-seller-info strong {
  color: #f4e8c1 !important;
}
/* Star-rating row _mktDecorateCard() inserts before the Contact/Call
   buttons on every card — needs light text on this card's dark
   background (it's dark-navy-on-dark-navy by default elsewhere). */
#mkt-avatar-carousel-inner .property-card.mkt-avatar-card .mkt-rating-line,
#property-grid-container .property-card.mkt-avatar-card .mkt-rating-line {
  color: #a0aec0 !important;
}

.mkt-badgecard { padding: 20px 18px 4px; display: flex; flex-direction: column; align-items: center; text-align: center; }
.mkt-badgecard-header { display: flex; flex-direction: column; align-items: center; margin-bottom: 14px; }
.mkt-badgecard-logo { width: 38px; height: 38px; background: #1e3a8a; border: 2px solid #d4af37; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 15px; box-shadow: 0 0 10px rgba(212, 175, 55, 0.2); }
.mkt-badgecard-kicker { font-size: 9px; letter-spacing: 1.5px; color: #d4af37; margin-top: 6px; text-transform: uppercase; font-weight: 700; }
.mkt-badgecard-avatar { width: 76px; height: 76px; border-radius: 50%; border: 2px solid #d4af37; padding: 3px; background: #0e1e38; margin-bottom: 10px; }
.mkt-badgecard-avatar img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; display: block; }
.mkt-badgecard-avatar.mkt-badgecard-initials { display: flex; align-items: center; justify-content: center; }
.mkt-badgecard-avatar.mkt-badgecard-initials span { font-family: Georgia, 'Times New Roman', serif; font-weight: 700; font-size: 22px; color: #f4e8c1; }
.mkt-badgecard-info { margin-bottom: 14px; }
.mkt-badgecard-name { margin: 0; font-size: 13px; letter-spacing: 1px; color: #f4e8c1; text-transform: uppercase; }
.mkt-badgecard-title { margin: 4px 0 8px; font-size: 16px; font-weight: 700; letter-spacing: 0.3px; color: #fff; }
.mkt-badgecard-status { display: inline-block; background: rgba(212, 175, 55, 0.15); border: 1px solid #d4af37; color: #d4af37; font-size: 9px; padding: 4px 10px; border-radius: 20px; font-weight: 700; letter-spacing: 0.4px; text-transform: uppercase; }
.mkt-badgecard-details { width: 100%; background: rgba(0, 0, 0, 0.2); border-radius: 8px; padding: 10px 12px; margin-bottom: 4px; box-sizing: border-box; }
.mkt-badgecard-detail-row { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 4px 0; font-size: 12px; border-bottom: 1px solid rgba(255, 255, 255, 0.06); }
.mkt-badgecard-detail-row:last-child { border-bottom: none; }
.mkt-badgecard-label { color: #a0aec0; flex-shrink: 0; }
.mkt-badgecard-value { color: #fff; font-weight: 500; text-align: right; }
.mkt-badgecard-value.mkt-badgecard-highlight { color: #d4af37; font-weight: 700; font-size: 14px; }

/* .mkt-avatar-body (description + attached documents, right below the
   badge card, still inside the same navy .property-card) — light text
   to match the new dark card instead of the "premium white card" ink
   colours those rules were written for. */
#mkt-avatar-carousel-inner .property-card.mkt-avatar-card .mkt-avatar-body,
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-body {
  padding: 4px 18px 14px;
}
#mkt-avatar-carousel-inner .property-card.mkt-avatar-card .mkt-avatar-desc,
#property-grid-container .property-card.mkt-avatar-card .mkt-avatar-desc {
  color: #a0aec0 !important;
  text-align: center;
}
