/* ========================================================================== 
   Earthy Shared Components
   Covers imported UI blocks: modals, offcanvas, accordion, forms, alerts, chips
   ========================================================================== */

.offcanvas,
.modal-content {
  background: var(--earthy-surface-1);
  color: var(--earthy-text);
  border: 1px solid var(--earthy-border);
}

.offcanvas-header,
.modal-header {
  border-bottom: 1px solid var(--earthy-border);
}

/* Filter drawers on listings/wanted pages (override legacy materialish gradients). */
.listings-offcanvas {
  border-left: 1px solid var(--earthy-border) !important;
}

.listings-offcanvas .offcanvas-header {
  background: var(--earthy-surface-2) !important;
  color: var(--earthy-text) !important;
}

.listings-offcanvas .offcanvas-header .text-muted {
  color: var(--earthy-text-muted) !important;
}

[data-theme="dark"] .listings-offcanvas .offcanvas-header {
  background: var(--earthy-surface-2) !important;
  color: var(--earthy-text) !important;
}

.offcanvas-footer,
.modal-footer {
  border-top: 1px solid var(--earthy-border);
}

.offcanvas-title,
.modal-title {
  color: var(--earthy-text);
  font-weight: 700;
}

.btn-close {
  opacity: 0.8;
}

[data-theme="dark"] .btn-close {
  filter: invert(1) grayscale(1);
}

.accordion-item {
  background: var(--earthy-surface-1);
  border: 1px solid var(--earthy-border);
}

.accordion-button {
  background: var(--earthy-surface-2);
  color: var(--earthy-text);
  font-weight: 600;
}

.accordion-button:not(.collapsed) {
  background: var(--earthy-primary-soft);
  color: var(--earthy-text);
  box-shadow: none;
}

.accordion-button:focus {
  border-color: var(--earthy-primary);
  box-shadow: 0 0 0 0.2rem rgba(138, 120, 105, 0.2);
}

/* Filter drawer accordion alignment and chevrons (including dark mode visibility). */
.listings-offcanvas .filter-drawer-form .accordion-button {
  background: var(--earthy-surface-2) !important;
  color: var(--earthy-text) !important;
}

.listings-offcanvas .filter-drawer-form .accordion-button:not(.collapsed) {
  background: var(--earthy-primary-soft) !important;
  color: var(--earthy-text) !important;
  box-shadow: none !important;
}

.listings-offcanvas .filter-drawer-form .accordion-button::after {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%238a7869'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") !important;
  opacity: 0.95;
  content: "";
  background-repeat: no-repeat;
  background-position: center;
  background-size: 1rem;
}

[data-theme="dark"] .listings-offcanvas .filter-drawer-form .accordion-button::after {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23efe8df'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") !important;
  opacity: 1;
  filter: none !important;
}

/* Offcanvas quick-preview accordions use bg-light in templates; force earthy surfaces. */
.offcanvas .accordion-button.bg-light {
  background: var(--earthy-surface-2) !important;
  color: var(--earthy-text) !important;
}

.offcanvas .accordion-button.bg-light.collapsed {
  background: var(--earthy-surface-2) !important;
}

.offcanvas .accordion-button:not(.collapsed) {
  background: var(--earthy-primary-soft) !important;
}

.offcanvas .accordion-button .text-primary {
  color: var(--earthy-primary) !important;
}

/* Keep chevrons visible in dark mode so users notice accordion expandability. */
.offcanvas .accordion-button::after {
  opacity: 0.95;
}

[data-theme="dark"] .offcanvas .accordion-button::after {
  filter: invert(1) brightness(1.8);
  opacity: 1;
}

.form-control,
.form-select {
  border-color: var(--earthy-border);
}

.form-control:focus,
.form-select:focus {
  border-color: var(--earthy-primary);
  box-shadow: 0 0 0 0.2rem rgba(138, 120, 105, 0.2);
}

/* Remove blue bootstrap states inside listings/wanted filter drawers. */
.listings-offcanvas .filter-drawer-form .form-check-input:checked {
  background-color: var(--earthy-primary);
  border-color: var(--earthy-primary);
}

.listings-offcanvas .filter-drawer-form .form-check-input:focus {
  border-color: var(--earthy-primary);
  box-shadow: 0 0 0 0.2rem rgba(138, 120, 105, 0.25);
}

.listings-offcanvas .filter-drawer-form .btn-check:checked + .btn,
.listings-offcanvas .filter-drawer-form .btn-group .btn-check:checked + .btn {
  background: var(--earthy-primary-soft);
  border-color: var(--earthy-primary);
  color: var(--earthy-text);
}

.listings-offcanvas .filter-drawer-form .btn-outline-secondary {
  border-color: var(--earthy-border);
  color: var(--earthy-text-muted);
}

.listings-offcanvas .filter-drawer-form .btn-outline-secondary:hover,
.listings-offcanvas .filter-drawer-form .btn-outline-secondary:focus {
  background: var(--earthy-primary-soft);
  border-color: var(--earthy-primary);
  color: var(--earthy-text);
}

.listings-offcanvas .filter-drawer-form .text-primary,
.listings-offcanvas .filter-drawer-form .spinner-border.text-primary {
  color: var(--earthy-primary) !important;
}

.list-group-item {
  background: transparent;
  border-color: var(--earthy-border);
  color: var(--earthy-text);
}

.alert.alert-info {
  background: color-mix(in srgb, var(--earthy-primary-soft) 45%, white 55%);
  color: var(--earthy-text);
  border: 1px solid var(--earthy-border);
}

.alert-success {
  background: color-mix(in srgb, var(--earthy-success) 22%, white 78%);
  color: var(--earthy-text);
  border: 1px solid var(--earthy-border);
}

.filter-chip,
.results-summary .badge,
.filter-chip-bar .filter-chip {
  border-radius: var(--earthy-radius-pill);
}

.multiselect-scroll {
  max-height: 300px;
  overflow-y: auto;
}

.drawer-hidden-section {
  display: none;
}

[data-theme="dark"] .alert-info,
[data-theme="dark"] .alert-success {
  color: var(--earthy-text);
}

[data-theme="dark"] .alert.alert-info {
  background: #3a332d;
  border-color: #8a7869;
  color: #efe8df;
}

/* alert-success / alert-warning: the base rules above use a near-white
   color-mix background. In dark mode only the text colour was being flipped to
   light, leaving light text on a light background (invisible). Give them proper
   dark surfaces, mirroring alert-info. */
[data-theme="dark"] .alert.alert-success {
  background: color-mix(in srgb, var(--earthy-success) 28%, #1f1e23 72%);
  border-color: var(--earthy-success);
  color: #efe8df;
}

[data-theme="dark"] .alert.alert-warning {
  background: color-mix(in srgb, var(--earthy-matches-mutual) 26%, #1f1e23 74%);
  border-color: var(--earthy-matches-mutual);
  color: #efe8df;
}

[data-theme="dark"] .alert.alert-success .btn-close,
[data-theme="dark"] .alert.alert-warning .btn-close {
  filter: invert(1) grayscale(100%) brightness(200%);
}

[data-theme="dark"] .alert.alert-info .text-muted {
  color: #d0c5ba !important;
}

[data-theme="dark"] .alert.alert-info a {
  color: #f2e8dc;
}

/* ---------------------------------------------------------------------------
   Filter offcanvas / sidebar shared styling (used on /listings/ and
   /listings/wanted/). Base look applies at all breakpoints; the @media block
   below upgrades to a sticky inline sidebar at ≥lg.
   --------------------------------------------------------------------------- */
.listings-offcanvas .offcanvas-header {
  background: var(--earthy-surface-2);
}

.listings-offcanvas .offcanvas-body {
  background: var(--earthy-surface-1);
}

/* ---------------------------------------------------------------------------
   Sticky filter sidebar (Bootstrap responsive offcanvas-lg)
   Used on /listings/ and /listings/wanted/. At <lg the drawer is a slide-out
   offcanvas; at ≥lg it becomes an always-visible inline sidebar.

   Root-cause fix for the "range slider pushes drawer past col-lg-3 edge" bug:
   `.row > .col-*` flex children default to `min-width: auto` which forces the
   column to grow to its content's intrinsic min-content. Range sliders have
   wide intrinsic content (text inputs with 6-digit placeholders). Cascading
   `min-width: 0` through the column → sidebar → offcanvas-body → accordion-*
   lets the slider shrink to fit its container.
   --------------------------------------------------------------------------- */
@media (min-width: 992px) {
  .row > .col-lg-3,
  .row > .col-xl-3 {
    min-width: 0;
  }

  .listings-offcanvas.offcanvas-lg {
    position: sticky;
    /* LOW 21: use shared --sticky-top-offset var (kept in sync with navbar) */
    top: var(--sticky-top-offset, 80px);
    max-height: calc(100vh - var(--sticky-top-offset, 80px) - 20px);
    overflow-y: auto;
    overflow-x: hidden;
    min-width: 0;
    background: var(--earthy-surface-1);
    border: 1px solid var(--earthy-border);
    border-radius: var(--earthy-radius-md);
    box-shadow: var(--earthy-shadow-sm, 0 2px 4px rgba(0, 0, 0, 0.04));
    /* Neutralise Bootstrap's mobile offcanvas transform/visibility in static mode. */
    transform: none !important;
    visibility: visible !important;
  }

  .listings-offcanvas.offcanvas-lg .offcanvas-header {
    padding: 0.75rem 1rem 0.5rem;
    border-bottom: 1px solid var(--earthy-border);
    background: var(--earthy-surface-2);
    border-radius: var(--earthy-radius-md) var(--earthy-radius-md) 0 0;
  }

  .listings-offcanvas.offcanvas-lg .offcanvas-body,
  .listings-offcanvas.offcanvas-lg .accordion-item,
  .listings-offcanvas.offcanvas-lg .accordion-body {
    min-width: 0;
  }

  .listings-offcanvas.offcanvas-lg .offcanvas-body {
    padding: 0.75rem 0.75rem 1rem;
  }
}

/* ==========================================================================
   Equipment selection grid (create/update listing + wanted forms)
   CSS columns instead of a fixed row/col split, so a category with few
   items doesn't leave a tall empty gap next to a longer one.
   ========================================================================== */
.equipment-categories-grid {
  column-count: 2;
  column-gap: 2rem;
}

.equipment-categories-grid .equipment-category {
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
}

@media (max-width: 991.98px) {
  .equipment-categories-grid {
    column-count: 1;
  }
}

/* ==========================================================================
   Sticky form action bar (mobile/tablet)
   Keeps the primary submit button reachable without scrolling to the very
   bottom of long create/update listing & wanted forms.
   ========================================================================== */
@media (max-width: 991.98px) {
  body:has(.sticky-form-actions) {
    padding-bottom: calc(4.5rem + env(safe-area-inset-bottom));
  }

  .sticky-form-actions {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1030;
    display: flex;
    gap: 0.5rem;
    padding: 0.6rem 1rem calc(0.6rem + env(safe-area-inset-bottom));
    background: var(--earthy-surface-1, #fff);
    border-top: 1px solid var(--earthy-border, #ddd);
    box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.08);
  }

  .sticky-form-actions .btn {
    flex: 1;
    margin: 0 !important;
  }
}

/* ==========================================================================
   Sticky detail action bar (mobile/tablet)
   Listing / wanted detail pages: keeps the primary actions (contact / propose
   swap, report, share) pinned to the bottom of the screen on phones so they
   are reachable without scrolling past the whole sidebar. On desktop the same
   markup renders as normal stacked full-width buttons inside the sidebar card.
   Mirrors .sticky-form-actions (create/update forms) for a consistent feel.
   ========================================================================== */
@media (max-width: 991.98px) {
  body:has(.detail-action-bar) {
    padding-bottom: calc(4.5rem + env(safe-area-inset-bottom));
  }

  .detail-action-bar {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1030;
    display: flex;
    gap: 0.5rem;
    align-items: stretch;
    padding: 0.6rem 1rem calc(0.6rem + env(safe-area-inset-bottom));
    margin: 0;
    background: var(--earthy-surface-1, #fff);
    border-top: 1px solid var(--earthy-border, #ddd);
    box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.08);
  }

  /* Neutralise the desktop layout helpers on the bar's items: w-100 (width:100%)
     fights flex sizing — without this the fixed-width siblings keep 100% and the
     primary action collapses to a single vertical column of letters. Also drop
     the stacking bottom margins and centre icon-only buttons. */
  .detail-action-bar > .btn,
  .detail-action-bar > .js-share,
  .detail-action-bar > .js-share > .btn {
    width: auto !important;
    margin-bottom: 0 !important;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* Primary action (contact / propose swap, create wanted / edit) grows to fill
     the remaining width. flex-basis 0 (not auto) so intrinsic width is ignored. */
  .detail-action-bar .detail-action-primary {
    flex: 1 1 0;
    min-width: 0;
  }

  /* Secondary actions (report, edit, delete, share) keep their content width. */
  .detail-action-bar .detail-action-secondary,
  .detail-action-bar > .js-share {
    flex: 0 0 auto;
  }

  /* ...and render as uniform square icon buttons (label hidden below). */
  .detail-action-bar .detail-action-secondary,
  .detail-action-bar > .js-share > .btn {
    min-width: 2.75rem;
    padding-left: 0.5rem;
    padding-right: 0.5rem;
  }

  /* The share button lives inside a .js-share wrapper; stretch it to the full bar
     height so it matches the other (direct flex-child) buttons exactly. */
  .detail-action-bar > .js-share {
    align-items: stretch;
  }
  .detail-action-bar > .js-share > .btn {
    height: 100%;
  }

  /* Hide the text labels of compact actions on mobile to save horizontal room. */
  .detail-action-bar .detail-action-label,
  .detail-action-bar .share-btn-label {
    display: none;
  }
}

/* ==========================================================================
   Touch devices: neutralise hover-lift transforms on the sticky bars' card
   ancestors.

   A transformed element becomes the containing block for ANY descendant with
   position:fixed. .card:hover / .mi-hover-lift:hover apply translateY(...), so
   on a phone — where a tap fires a "sticky" :hover on the card — the fixed
   action bar (.sticky-form-actions on create/update, .detail-action-bar on the
   detail pages) is yanked out of the viewport and re-anchored inside the card.
   The bar visibly jumps and its buttons stop responding to the tap. Hover lifts
   are pointless without a pointer, so disable the transform where hover is
   unavailable. Loaded after materialish.css, so this wins.
   ========================================================================== */
@media (hover: none) {
  .card:hover,
  .mi-hover-lift:hover {
    transform: none;
  }
}

/* ---------------------------------------------------------------------------
   Reusable horizontal listing / wanted cards (photo left, info right).
   Used by the dashboard matches, the inquiry list, and the inquiry detail —
   loaded globally so the component looks identical everywhere it is embedded.
   --------------------------------------------------------------------------- */
.listing-card-horizontal,
.wanted-card-horizontal {
  border-radius: var(--earthy-radius-md, 0.5rem);
}

/* Truncate long titles to 2 lines so wide titles don't push the price badge
   off the row or break the embedded card height. */
.listing-card-horizontal .card-title,
.wanted-card-horizontal .card-title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-width: 0;
}

/* Clamp long descriptions inside horizontal cards to 3 lines. */
.listing-card-horizontal .card-text,
.wanted-card-horizontal .card-text {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-width: 0;
}

/* Footer meta — long owner emails / usernames must ellipsis, not wrap. */
.listing-card-horizontal .footer-meta span,
.wanted-card-horizontal .footer-meta span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Allow flex children to shrink below their content width — required for
   the truncation above to actually engage. */
.listing-card-horizontal .card-body,
.wanted-card-horizontal .card-body {
  min-width: 0;
}

/* Fixed media height — portrait photos preserved at upload (PhotoService /
   WantedPhotoService cap MAX 1920×1080 via `Image.thumbnail`, which keeps
   aspect ratio). Fixed-height + object-fit:cover crops uniformly across
   landscape and portrait uploads so every card looks visually consistent. */
.listing-card-horizontal-media,
.wanted-card-horizontal-media {
  overflow: hidden;
  background-color: var(--earthy-surface-1, #f3efe9);
}

.card-horizontal-image,
.card-horizontal-placeholder {
  width: 100%;
  height: 200px;
  object-fit: cover;
  display: block;
}

.wanted-card-horizontal-placeholder-stack {
  line-height: 1.1;
}

.wanted-placeholder-icon,
.wanted-placeholder-icon-top {
  color: var(--md-primary, var(--earthy-primary));
}

.wanted-placeholder-icon-top {
  opacity: 0.7;
}

.wanted-placeholder-icon {
  opacity: 0.5;
}

@media (max-width: 575.98px) {
  .card-horizontal-image,
  .card-horizontal-placeholder {
    height: 140px;
  }
}
