/* Filters UI: sheet modal, accordion fields, distance slider with puck thumb,
   filter buttons, in-sheet save panel, chips, searchable checkbox lists,
   desktop modal positioning, and saved-filters trigger + panel + actions.
   Extracted from arenas/templates/arenas/base.html on 2026-05-03. */

/* --- Filter sheet (modal) --- */
.filters-sheet-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.5);
  z-index: 100;
  opacity: 0;
  transition: opacity 0.2s ease-out;
  pointer-events: none;
  visibility: hidden;
}
.filters-sheet-backdrop.open {
  opacity: 1;
  pointer-events: auto;
  visibility: visible;
}
.filters-sheet {
  position: fixed;
  z-index: 101;
  background: var(--color-bg-secondary);
  display: flex;
  flex-direction: column;
  visibility: hidden;
  /* Mobile default: full-screen slide-up */
  inset: 0;
  transform: translateY(100%);
  transition: transform 0.25s ease-out, opacity 0.2s ease-out;
}
.filters-sheet.open {
  visibility: visible;
  transform: translateY(0);
}
.filters-sheet-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--spacing-lg);
  border-bottom: 1px solid var(--color-border);
  flex-shrink: 0;
}
.filters-sheet-header h2 {
  font-size: var(--font-size-lg);
  font-weight: 700;
  color: var(--color-text);
}
.filters-sheet-close {
  width: 32px;
  height: 32px;
  border: none;
  background: transparent;
  color: var(--color-text-secondary);
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
  border-radius: var(--radius-sm);
}
.filters-sheet-close:hover {
  background: var(--color-bg);
}
.filters-sheet-body {
  flex: 1;
  overflow-y: auto;
  padding: var(--spacing-lg);
  display: flex;
  flex-direction: column;
  gap: var(--spacing-lg);
}
.filter-field {
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--color-border-light);
  padding-top: var(--spacing-md);
}
.filter-field:first-child {
  border-top: none;
  padding-top: 0;
}
.filter-field-toggle {
  display: flex;
  align-items: center;
  gap: var(--spacing-sm);
  width: 100%;
  padding: 0;
  background: transparent;
  border: none;
  cursor: pointer;
  color: inherit;
  text-align: left;
}
.filter-field-label {
  flex: 1;
  font-size: var(--font-size-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--color-text-muted);
}
.filter-field-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9999px;
  background: var(--color-accent);
  color: #fff;
  font-size: var(--font-size-xs);
  font-weight: 700;
  line-height: 1;
}
.filter-field-count:empty {
  display: none;
}
.filter-field-chevron {
  color: var(--color-text-muted);
  transition: transform 0.15s ease-out;
  flex-shrink: 0;
}
.filter-field.expanded .filter-field-chevron {
  transform: rotate(180deg);
}
.filter-field-body {
  display: none;
  flex-direction: column;
  gap: 6px;
  padding-top: var(--spacing-sm);
}
.filter-field.expanded .filter-field-body {
  display: flex;
}

/* --- Distance slider (puck thumb) --- */
/* Visual contract documented in DESIGN.md > Component conventions >
   Distance slider. The track is two-tone driven by a `--pct` CSS
   custom property the template inlines on the input element so cold
   paint is correct before any JS runs; the oninput handler then
   keeps it in sync as the user drags. Thumb is a 22px "puck" with a
   radial-gradient face, ground shadow, and ice-blue focus halo. */
.distance-slider {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.distance-slider-label {
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  color: var(--color-boards-light);
}
.distance-slider-label > output {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 14px;
  color: var(--color-boards);
  font-variant-numeric: tabular-nums;
  margin: 0 2px;
}
.distance-slider input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 22px;
  background: transparent;
  outline: none;
  margin: 0;
  cursor: grab;
}
.distance-slider input[type="range"]:active { cursor: grabbing; }

/* Track — WebKit/Blink */
.distance-slider input[type="range"]::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 3px;
  background: linear-gradient(
    to right,
    var(--color-ice-blue) 0%,
    var(--color-ice-blue) var(--pct, 0%),
    var(--color-blue-line) var(--pct, 0%),
    var(--color-blue-line) 100%
  );
}
/* Track — Firefox: separate ::-moz-range-track + ::-moz-range-progress.
   Firefox renders the filled portion automatically from input value,
   ignoring the --pct gradient — that's fine, the visual matches. */
.distance-slider input[type="range"]::-moz-range-track {
  height: 6px;
  border-radius: 3px;
  background: var(--color-blue-line);
}
.distance-slider input[type="range"]::-moz-range-progress {
  height: 6px;
  border-radius: 3px;
  background: var(--color-ice-blue);
}

/* Puck thumb — both engines need the rule, can't be merged because
   a single selector with both prefixes is rejected by the parser. */
.distance-slider input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 35%, #475569 0%, #1e293b 40%, #0c1830 75%);
  border: 1px solid #000;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    0 1px 2px rgba(0, 0, 0, 0.35);
  margin-top: -8px; /* (track-height - thumb-height) / 2 */
}
.distance-slider input[type="range"]::-moz-range-thumb {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 35%, #475569 0%, #1e293b 40%, #0c1830 75%);
  border: 1px solid #000;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    0 1px 2px rgba(0, 0, 0, 0.35);
}

/* Focus halo — only on keyboard focus, not on click. */
.distance-slider input[type="range"]:focus-visible::-webkit-slider-thumb {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    0 1px 2px rgba(0, 0, 0, 0.35),
    0 0 0 4px rgba(14, 165, 233, 0.25);
}
.distance-slider input[type="range"]:focus-visible::-moz-range-thumb {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    0 1px 2px rgba(0, 0, 0, 0.35),
    0 0 0 4px rgba(14, 165, 233, 0.25);
}

.filters-sheet-footer {
  display: flex;
  gap: var(--spacing-sm);
  padding: var(--spacing-md) var(--spacing-lg);
  border-top: 1px solid var(--color-border);
  background: var(--color-bg-secondary);
  flex-shrink: 0;
}
.btn-clear,
.btn-save,
.btn-apply,
.btn-cancel-save,
.btn-confirm-save {
  flex: 1;
  padding: 12px 16px;
  border-radius: var(--radius-md);
  font-size: var(--font-size-base);
  font-weight: 600;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}
.btn-clear {
  background: transparent;
  color: var(--color-accent-hover);
  border: 1px solid var(--color-accent);
}
.btn-clear:hover {
  text-decoration: none;
}
.btn-apply {
  background: var(--color-accent);
  color: #fff;
  border: 1px solid var(--color-accent);
}
.btn-apply:hover {
  background: var(--color-accent-hover);
  border-color: var(--color-accent-hover);
}
.btn-save {
  background: var(--color-success);
  color: #fff;
  border: 1px solid var(--color-success);
}
.btn-save:hover {
  filter: brightness(0.94);
}
.btn-save .btn-save-icon { flex-shrink: 0; }
.btn-cancel-save {
  background: transparent;
  color: var(--color-text-secondary);
  border: 1px solid var(--color-border);
}
.btn-confirm-save {
  background: var(--color-success);
  color: #fff;
  border: 1px solid var(--color-success);
}
.btn-confirm-save:hover {
  filter: brightness(0.94);
}
/* The native [hidden] attribute must beat the inline-flex display
   declared above; without !important the buttons stay visible when
   the JS toggles save mode. */
.filters-sheet-footer button[hidden] { display: none !important; }

/* --- Inline save panel inside the Filters sheet --- */
.filters-sheet-save-panel {
  padding: var(--spacing-md) var(--spacing-lg);
  border-top: 1px solid var(--color-border);
  background: var(--color-bg);
  flex-shrink: 0;
}
.filters-sheet-save-panel[hidden] { display: none; }
.filters-sheet-save-panel .filter-field-label {
  margin-bottom: 6px;
}
.filters-sheet-save-name {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-md);
  font-size: var(--font-size-base);
  background: var(--color-bg-secondary);
  color: var(--color-text);
}
.filters-sheet-save-default-label {
  display: flex;
  align-items: center;
  gap: var(--spacing-sm);
  margin-top: var(--spacing-sm);
  font-size: var(--font-size-sm);
  color: var(--color-text-secondary);
  cursor: pointer;
}
.filters-sheet-save-feedback {
  margin-top: var(--spacing-sm);
  padding: var(--spacing-xs) var(--spacing-sm);
  background: rgba(220, 38, 38, 0.08);
  color: #b91c1c;
  border-radius: var(--radius-sm);
  font-size: var(--font-size-sm);
}
.filters-sheet-save-feedback[hidden] { display: none; }

/* --- Chips (short-list filters) --- */
.filter-chip-group {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-xs);
}
.filter-chip {
  display: inline-flex;
  align-items: center;
  padding: 6px 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  background: var(--color-bg-secondary);
  color: var(--color-text);
  cursor: pointer;
  font-size: var(--font-size-sm);
  user-select: none;
  transition: background 0.1s, border-color 0.1s, color 0.1s;
}
.filter-chip input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  width: 0;
  height: 0;
}
.filter-chip:hover {
  border-color: var(--color-accent);
}
.filter-chip:has(input:checked) {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #fff;
}

/* --- Searchable checkbox lists (long-list filters) --- */
.filter-search {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--font-size-base);
  background: var(--color-bg-secondary);
  color: var(--color-text);
}
.filter-checkbox-list {
  max-height: 240px;
  overflow-y: auto;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}
.filter-checkbox-item {
  display: flex;
  gap: var(--spacing-sm);
  align-items: center;
  padding: 8px 12px;
  cursor: pointer;
  font-size: var(--font-size-sm);
}
.filter-checkbox-item:hover {
  background: var(--color-bg);
}
.filter-checkbox-item input {
  margin: 0;
  flex-shrink: 0;
}

/* --- Desktop: centered modal instead of full-screen --- */
@media (min-width: 768px) {
  .filters-sheet {
    inset: 5vh auto auto 50%;
    width: 92%;
    max-width: 480px;
    max-height: 90vh;
    border-radius: var(--radius-lg);
    box-shadow: 0 8px 32px rgba(15, 23, 42, 0.24);
    transform: translate(-50%, 16px);
    opacity: 0;
  }
  .filters-sheet.open {
    transform: translate(-50%, 0);
    opacity: 1;
  }
}

/* === Saved Filters === */

/* Trigger pill inherits .filters-trigger styling. The wrapper exists
   to provide a positioning context for the desktop dropdown panel. */
.saved-filters-wrapper {
  position: relative;
  display: inline-flex;
}

/* Panel mount point. Empty until the trigger is tapped, at which
   point htmx GETs /saved-filters/ and innerHTML-swaps the panel
   fragment in. The fragment includes its own #saved-filters-panel
   root that subsequent writes (create/rename/delete/set-default)
   outerHTML-swap. */
.saved-filters-panel-container {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 100;
  /* Empty initially — sized by the panel fragment when present. */
}
.saved-filters-panel-container:empty {
  display: none;
}

.saved-filters-panel {
  background: var(--color-bg-secondary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--spacing-sm);
  min-width: 280px;
  max-width: 360px;
  box-shadow: 0 4px 12px rgba(15, 23, 42, 0.08);
}

/* Sheet-style affordances on the panel fragment. The drag handle and
   header render at every viewport width — desktop sees them as a small
   visual hint that this is a poppable sheet; mobile relies on them. */
.saved-filters-sheet-handle {
  width: 36px;
  height: 4px;
  border-radius: 2px;
  background: var(--color-border);
  margin: 0 auto var(--spacing-sm);
  flex-shrink: 0;
}
.saved-filters-sheet-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-bottom: var(--spacing-sm);
  margin-bottom: var(--spacing-sm);
  border-bottom: 1px solid var(--color-border);
}
.saved-filters-sheet-title {
  font-size: var(--font-size-base);
  font-weight: 700;
  color: var(--color-text);
  margin: 0;
}
.saved-filters-sheet-close {
  width: 32px;
  height: 32px;
  border: none;
  background: transparent;
  color: var(--color-text-secondary);
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
  border-radius: var(--radius-sm);
}
.saved-filters-sheet-close:hover {
  background: var(--color-bg);
}

/* Backdrop for the saved-filters bottom sheet on mobile. Always in
   the DOM (when the user has at least one save, which gates the
   whole surface), shown via .open class wired by JS. Mirrors the
   .filters-sheet-backdrop pattern. */
.saved-filters-panel-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.5);
  z-index: 100;
  opacity: 0;
  transition: opacity 0.2s ease-out;
  pointer-events: none;
  visibility: hidden;
}
.saved-filters-panel-backdrop.open {
  opacity: 1;
  pointer-events: auto;
  visibility: visible;
}
/* Backdrop and drag handle are bottom-sheet affordances and only
   make sense on mobile. On desktop the panel is a positioned dropdown
   attached to the trigger pill; a drag handle would visually suggest
   a swipe-to-dismiss gesture that doesn't exist. The sheet header
   (title + close) is kept at every viewport — it doubles as a card
   header on the desktop dropdown. */
@media (min-width: 768px) {
  .saved-filters-panel-backdrop { display: none; }
  .saved-filters-sheet-handle { display: none; }
}

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

.saved-filter-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--spacing-xs) 0;
  border-bottom: 1px solid var(--color-border);
}
.saved-filter-item:last-child {
  border-bottom: none;
}

.saved-filter-name {
  flex: 1;
  color: var(--color-text);
  text-decoration: none;
  font-size: var(--font-size-sm);
  padding: var(--spacing-xs) 0;
}
.saved-filter-name:hover {
  color: var(--color-accent-hover);
}
.saved-filter-default .saved-filter-name {
  font-weight: 600;
}

.saved-filter-actions {
  margin-left: var(--spacing-sm);
}
.saved-filter-actions summary {
  cursor: pointer;
  list-style: none;
  color: var(--color-text-muted);
  padding: 0 var(--spacing-xs);
}
.saved-filter-actions summary::-webkit-details-marker {
  display: none;
}
.saved-filter-actions[open] summary {
  color: var(--color-text);
}
.saved-filter-actions form {
  margin: var(--spacing-xs) 0;
}
.saved-filter-actions button {
  background: none;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 4px 8px;
  color: var(--color-text);
  font-size: var(--font-size-xs);
  cursor: pointer;
}
.saved-filter-actions button:hover {
  background: var(--color-bg);
}

.saved-filters-empty {
  margin: 0;
  padding: var(--spacing-sm) 0;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.saved-filters-error {
  background: rgba(220, 38, 38, 0.08);
  color: #b91c1c;
  padding: var(--spacing-xs) var(--spacing-sm);
  border-radius: var(--radius-sm);
  margin-bottom: var(--spacing-sm);
  font-size: var(--font-size-sm);
}

/* Mobile: panel becomes a full-screen-ish bottom sheet matching the
   .filters-sheet pattern. Tap targets large, slide-up animation,
   rounded top corners, drag handle visible. The container is the
   positioned slider; the inner .saved-filters-panel renders flush. */
@media (max-width: 767px) {
  .saved-filters-panel-container {
    position: fixed;
    inset: auto 0 0 0;
    max-height: 80vh;
    overflow-y: auto;
    z-index: 102;
    background: var(--color-bg-secondary);
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -8px 32px rgba(15, 23, 42, 0.18);
    transform: translateY(100%);
    transition: transform 0.25s ease-out;
  }
  /* When htmx swaps the panel fragment in, the container is no longer
     :empty and slides up into view. Combined with the
     .saved-filters-panel-backdrop scrim (toggled by JS), this matches
     the .filters-sheet's open state. */
  .saved-filters-panel-container:not(:empty) {
    transform: translateY(0);
  }
  .saved-filters-panel {
    border: none;
    border-radius: 0;
    box-shadow: none;
    max-width: none;
    padding: var(--spacing-md) var(--spacing-lg);
  }
}

/* === End Saved Filters === */
