/* saygex app layout (app-specific; tokens and components live in theme.css).
   Load after theme.css. */

[x-cloak] { display: none !important; }

html, body { height: 100%; }
body { overscroll-behavior-y: none; }

/* One screen = a full-height column: header, scrolling main, optional tab bar */
.sx-screen {
  height: 100dvh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  overflow: clip;   /* hidden can still be scrolled by scrollIntoView(), which would push the header away */
}
.sx-screen > main { flex: 1 1 auto; overflow-y: auto; min-height: 0; }
.sx-header { padding-top: env(safe-area-inset-top); flex-shrink: 0; }

/* Signed-out screens (A1 to A7): centred column */
.sx-auth {
  width: 100%;
  max-width: 26rem;
  margin: 0 auto;
  min-height: 100%;
  display: flex;
  flex-direction: column;
  padding: calc(3rem + env(safe-area-inset-top)) 1.5rem calc(1.5rem + env(safe-area-inset-bottom));
}

/* Settings section headings (same as the settings.html mockup) */
.sx-section-label {
  padding: 1.25rem 1rem .5rem;
  font-size: .75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--bs-secondary-color);
}

/* "Verify your email" banner on signed-in screens */
.sx-banner {
  flex-shrink: 0;
  font-size: .875rem;
  background: var(--bs-primary-bg-subtle);
  color: var(--bs-body-color);
  border-bottom: 1px solid var(--bs-primary-border-subtle);
}

/* Toast above the tab bar */
.sx-toast {
  position: fixed;
  left: 50%;
  bottom: calc(4.25rem + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  z-index: 1090;
  width: max-content;
  max-width: calc(100% - 2rem);
  padding: .6rem 1rem;
  border-radius: var(--bs-border-radius-lg);
  background: var(--bs-emphasis-color);
  color: var(--bs-body-bg);
  font-size: .875rem;
  box-shadow: 0 .5rem 1.5rem rgba(0, 0, 0, .3);
}

/* Full-screen centred state (boot spinner, link landings) */
.sx-center {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 1.5rem;
}

/* Bootstrap Icons use <i>, which is italic by default and would make the
   browser download Inter Italic for nothing. */
.bi { font-style: normal; }

/* Legal pages (Terms, Privacy Policy): readable text column */
.sx-screen > main.sx-legal {
  width: 100%;
  max-width: 40rem;
  margin: 0 auto;
  padding: 1rem 1rem calc(1.5rem + env(safe-area-inset-bottom));
}
.sx-legal h2 { font-size: 1rem; font-weight: 600; margin: 1.5rem 0 .5rem; }
.sx-legal p { color: var(--bs-secondary-color); }

/* P1 / P2 profile form: one column; sections use `order` so P1 can put the
   display name first and P2 the photos first (same markup). */
.sx-profile-form { display: flex; flex-direction: column; padding-bottom: env(safe-area-inset-bottom); }
.sx-profile-more { display: flex; flex-direction: column; }   /* not .d-flex: its !important beats x-show */

/* P3 photo manager: 4 columns, the main photo spans 2 x 2 (edit.html mockup) */
.sx-photos {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: .5rem;
}
.sx-photo {
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: var(--bs-border-radius-lg);
  overflow: hidden;
  background: var(--bs-tertiary-bg);
  min-width: 0;
}
.sx-photo.dropdown { overflow: visible; }
.sx-photo-main { grid-column: span 2; grid-row: span 2; }
.sx-photo-btn {
  display: block;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  border-radius: inherit;
  overflow: hidden;
  background: var(--bs-tertiary-bg);
  position: relative;
}
/* Not :disabled while busy: Bootstrap won't close a dropdown whose toggle is disabled */
.sx-photo-btn.is-busy { opacity: .7; }
.sx-photo-btn:focus-visible { outline: 2px solid var(--bs-primary); outline-offset: 2px; }
.sx-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sx-photo-badge { position: absolute; top: .25rem; left: .25rem; }

/* Upload tiles: preview (dimmed) + progress or error */
.sx-photo-pending img { opacity: .45; }
.sx-photo-ph {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: 1.5rem;
  color: var(--bs-secondary-color);
}
.sx-photo-status {
  position: absolute; inset: auto 0 0 0;
  padding: .3rem;
  display: flex;
  align-items: flex-end;
}
.sx-photo-pending.is-error { outline: 2px solid var(--bs-danger); outline-offset: -2px; }
.sx-photo-pending.is-error .sx-photo-status { inset: 0; padding: 0; }
.sx-photo-erricon {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: 1.25rem;
  color: var(--bs-danger);
  background: rgba(0, 0, 0, .35);
}

.sx-photo-add {
  display: grid;
  place-items: center;
  cursor: pointer;
  background: transparent;
  border: 2px dashed var(--sx-border-strong);
  font-size: 1.5rem;
  color: var(--bs-secondary-color);
  margin: 0;
}
.sx-photo-add:hover { color: var(--bs-body-color); }
.sx-photo-add:focus-within { outline: 2px solid var(--bs-primary); outline-offset: 2px; }

/* Narrow number fields (ft / in / kg...): no invalid icon, the message below says it */
.sx-num.is-invalid { background-image: none; padding-right: var(--bs-form-control-padding-x, .75rem); }

/* ---------------------------------------------------------------------- */
/* Milestone 3: grid, filters, profile view, favorites, location          */
/* ---------------------------------------------------------------------- */

/* G1: the grid scrolls; pull-to-refresh indicator sits above it */
.sx-grid-main { overscroll-behavior-y: contain; }
.sx-pull {
  height: 0;
  display: grid;
  place-items: center;
  overflow: hidden;
  transition: height .15s ease-out;
}
.sx-spinner-paused { animation-play-state: paused; }
.sx-chips { scrollbar-width: none; }
.sx-chips::-webkit-scrollbar { display: none; }
.sx-chips .badge { font-size: .75rem; padding: .4em .75em; cursor: pointer; flex-shrink: 0; }
.sx-sentinel { height: 1px; }
.sx-tile-silhouette > img { display: none; }

/* G2: two-handle age slider (two range inputs on one track) */
.sx-range2 {
  position: relative;
  height: 1.5rem;
  --lo: 0%;
  --hi: 100%;
}
.sx-range2::before {                     /* track */
  content: "";
  position: absolute;
  left: .5rem; right: .5rem; top: 50%;
  height: .375rem;
  margin-top: -.1875rem;
  border-radius: 1rem;
  background: linear-gradient(to right,
    var(--bs-tertiary-bg) var(--lo), var(--bs-primary) var(--lo),
    var(--bs-primary) var(--hi), var(--bs-tertiary-bg) var(--hi));
  background-clip: content-box;
}
.sx-range2 input[type="range"] {
  position: absolute;
  inset: 0;
  width: 100%;
  margin: 0;
  background: transparent;
  pointer-events: none;
  -webkit-appearance: none;
  appearance: none;
}
.sx-range2 input[type="range"]::-webkit-slider-runnable-track { background: transparent; height: 1.5rem; }
.sx-range2 input[type="range"]::-moz-range-track { background: transparent; }
.sx-range2 input[type="range"]::-webkit-slider-thumb {
  pointer-events: auto;
  -webkit-appearance: none;
  appearance: none;
  width: 1.25rem; height: 1.25rem;
  margin-top: .125rem;
  border-radius: 50%;
  border: 2px solid var(--bs-body-bg);
  background: var(--bs-primary);
  box-shadow: 0 0 0 1px var(--bs-primary);
  cursor: pointer;
}
.sx-range2 input[type="range"]::-moz-range-thumb {
  pointer-events: auto;
  width: 1.25rem; height: 1.25rem;
  border-radius: 50%;
  border: 2px solid var(--bs-body-bg);
  background: var(--bs-primary);
  cursor: pointer;
}
.sx-range2 input[type="range"]:focus { outline: none; }
.sx-range2 input[type="range"]:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 .25rem var(--bs-focus-ring-color); }
.sx-range2 input[type="range"]:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 .25rem var(--bs-focus-ring-color); }
.sx-sheet { max-height: 90dvh; }
.sx-sheet .offcanvas-body { padding-bottom: calc(1rem + env(safe-area-inset-bottom)); }

/* V1: photo carousel (scroll-snap, swipe) */
.sx-carousel { position: relative; }
.sx-track {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
}
.sx-track::-webkit-scrollbar { display: none; }
.sx-slide {
  position: relative;
  flex: 0 0 100%;
  aspect-ratio: 1 / 1;
  scroll-snap-align: start;
  padding: 0;
  border: 0;
  background: var(--bs-tertiary-bg);
  display: block;
  overflow: hidden;
}
.sx-carousel > .sx-slide { width: 100%; }
.sx-slide > img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sx-slide:focus-visible { outline: 2px solid var(--bs-primary); outline-offset: -4px; }
.sx-dots {
  position: absolute;
  left: 0; right: 0; bottom: .5rem;
  display: flex;
  justify-content: center;
  gap: .125rem;
}
.sx-dots button {
  width: 1.5rem; height: 1.5rem;          /* touch target; the dot is drawn by ::before */
  padding: 0; border: 0; background: none;
  display: grid; place-items: center;
}
.sx-dots button::before {
  content: "";
  width: .5rem; height: .5rem;
  border-radius: 50%;
  background: rgba(255, 255, 255, .5);
  box-shadow: 0 0 2px rgba(0, 0, 0, .6);
}
.sx-dots button.active::before { background: #fff; }
.sx-dots button:focus-visible { outline: 2px solid #fff; border-radius: 50%; }
.sx-prewrap { white-space: pre-wrap; }
.d-contents { display: contents; }
.sx-actions { flex-shrink: 0; padding-bottom: calc(.5rem + env(safe-area-inset-bottom)) !important; }

/* V2: full-screen photo viewer */
.sx-viewer {
  position: fixed;
  inset: 0;
  z-index: 1080;
  background: #000;
  color: #fff;
  display: flex;
  flex-direction: column;
}
.sx-viewer-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: calc(.25rem + env(safe-area-inset-top)) .75rem .25rem 1rem;
}
.sx-vtrack {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.sx-vtrack::-webkit-scrollbar { display: none; }
.sx-vslide { flex: 0 0 100%; scroll-snap-align: start; display: grid; place-items: center; min-width: 0; }
.sx-vslide > img { max-width: 100%; max-height: 100%; object-fit: contain; }
.sx-vnav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 2.75rem; height: 2.75rem;
  border: 0; border-radius: 50%;
  background: rgba(0, 0, 0, .45);
  color: #fff;
  font-size: 1.25rem;
}
.sx-vnav:focus-visible { outline: 2px solid #fff; }
.sx-vprev { left: .5rem; }
.sx-vnext { right: .5rem; }
@media (hover: none) { .sx-vnav { display: none; } }

/* S2 blocked users: small rounded avatar */
.sx-avatar {
  position: relative;
  width: 40px; height: 40px;
  flex-shrink: 0;
  border-radius: .6rem;
  overflow: hidden;
  background: var(--bs-tertiary-bg);
}
.sx-avatar > img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* L3 dev location: map + capital presets */
.sx-map-wrap { position: relative; }
.sx-map { height: 45dvh; min-height: 240px; background: var(--bs-tertiary-bg); }
.sx-map-msg { position: absolute; inset: 0; display: grid; place-items: center; padding: 1rem; text-align: center; }
.sx-capitals { display: flex; flex-wrap: wrap; gap: .5rem; }
.leaflet-container { font: inherit; }
.leaflet-container a { color: var(--bs-link-color); }
[data-bs-theme="dark"] .leaflet-control-attribution { background: rgba(15, 15, 18, .8) !important; color: var(--bs-secondary-color); }
[data-bs-theme="dark"] .leaflet-bar a { background: var(--bs-secondary-bg); color: var(--bs-body-color); border-color: var(--bs-border-color); }
/* display:flex without !important, so x-show can still hide it (Bootstrap's .d-flex can't be hidden by x-show) */
.sx-flex { display: flex; }
/* Always-visible field error without !important (same reason): x-show hides it, so an empty one adds no gap */
.invalid-feedback.sx-feedback { display: block; }
/* Active-filter count on the G1 filter button (kept inside the header so it isn't clipped at the top) */
.btn .sx-filter-badge {
  position: absolute;
  top: -.3rem;
  right: -.5rem;
  font-size: .625rem;
  padding: .25em .45em;
  box-shadow: 0 0 0 2px var(--bs-body-bg);
}
/* V1 stats: label / value columns (5:7 like the mockup's .row) */
.sx-stats { display: grid; grid-template-columns: 5fr 7fr; column-gap: 1.5rem; }
.sx-stats dd { margin-bottom: .5rem; overflow-wrap: anywhere; }
/* Empty-state ring on raised surfaces (S2 modal): punch out with the surface color */
.modal .sx-empty-icon::before { background: var(--bs-modal-bg); }

/* Dev switch user (#/dev-users): full-width row buttons */
.sx-dev-user {
  display: flex;
  align-items: center;
  gap: .75rem;
  width: 100%;
  padding: .625rem 1rem;
  border: 0;
  background: transparent;
  color: inherit;
  text-align: left;
}
.sx-dev-user:not(:disabled):hover { background: var(--bs-tertiary-bg); }
.sx-dev-user:focus-visible { outline: 2px solid var(--bs-primary); outline-offset: -2px; }
.sx-dev-user:disabled { color: inherit; opacity: 1; }
.list-group-item.sx-dev-you { background: var(--bs-tertiary-bg); }
.sx-dev-you .sx-avatar { opacity: .6; }
/* Grid header dev badges. The "viewing as {name}" chip (.sx-dev-as) is icon-only (person-gear), with the
   full name in title/aria-label; while it shows, DEV LOC is icon-only too (geo pin), so "Nearby" stays
   readable at 375px whatever the name (M5 QA). */
.sx-dev-badge {
  flex-shrink: 0;
  line-height: 1;
}

/* ---- Chat (milestone 5) ------------------------------------------------ */
/* C1 row avatar (52px like chats.html) with the online dot on its corner */
.sx-chat-avatar {
  position: relative;
  display: block;
  width: 52px; height: 52px;
  flex-shrink: 0;
  border-radius: .75rem;
  background-color: var(--bs-tertiary-bg);
}
.sx-chat-avatar > img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; display: block; }
.sx-chat-avatar.sx-tile-silhouette::before { border-radius: inherit; }
.sx-chat-avatar .sx-online-dot { position: absolute; right: -2px; bottom: -2px; width: .75rem; height: .75rem; box-shadow: 0 0 0 2px var(--bs-body-bg); }
.sx-chat-avatar-sm { width: 36px; height: 36px; border-radius: .6rem; }
.list-group-item-action:hover .sx-chat-avatar .sx-online-dot { box-shadow: 0 0 0 2px var(--bs-tertiary-bg); }

/* C2 thread */
.sx-screen > main.sx-thread { overscroll-behavior: contain; }
.sx-bubble-failed { opacity: .65; }
.sx-send { width: 2.375rem; height: 2.375rem; display: inline-grid; place-items: center; padding: 0; flex-shrink: 0; }
.sx-chat-photo {
  position: relative;
  display: block;
  width: 200px;
  max-width: 70%;
  max-height: 320px;
  border: 0;
  overflow: hidden;
  aspect-ratio: 4 / 5;
}
.sx-chat-photo > img { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: calc(var(--sx-bubble-radius) - .25rem); }
.sx-chat-photo-ph { display: grid; place-items: center; gap: .25rem; width: 100%; height: 100%; min-height: 8rem; font-size: 1.5rem; opacity: .7; }
.sx-chat-photo-progress { position: absolute; left: 0; bottom: 0; height: 3px; background: currentColor; transition: width .2s; }
.sx-share-card { width: 240px; max-width: 80%; border-radius: var(--sx-bubble-radius); }
.sx-share-map { height: 140px; background: #f2efe9; }   /* map tiles are light in both themes */
.sx-share-wait { display: flex; align-items: center; justify-content: center; background: var(--bs-secondary-bg); }
.sx-typing { display: inline-flex; gap: .3rem; align-items: center; padding: .7rem .9rem; }
.sx-typing > span { width: .45rem; height: .45rem; border-radius: 50%; background: var(--bs-secondary-color); animation: sx-typing 1.2s infinite ease-in-out; }
.sx-typing > span:nth-child(2) { animation-delay: .15s; }
.sx-typing > span:nth-child(3) { animation-delay: .3s; }
@keyframes sx-typing { 0%, 60%, 100% { opacity: .3; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-2px); } }
@media (prefers-reduced-motion: reduce) { .sx-typing > span { animation: none; opacity: .7; } }
