/* ===============================================
   GAMES-FILTERS.CSS
   games.md-specific: the sort dropdown, active-
   filter chips, and the whole filter panel (sidebar
   on desktop / slide-out drawer on mobile), plus the
   filters toolbar row above the results grid.
   =============================================== */

/* ===== NEW FILTER SYSTEM ===== */

/* Results bar: one line whenever there's room - Epic-style "Show: ... /
   chip" on the left, and the two things Epic doesn't have (result counter
   + grid/list toggle) grouped on the right. .filters-left can shrink and
   wrap its own contents (the chip drops under "Show:" first) before the
   outer row ever breaks, so .filters-right - counter and view toggle -
   stays put as one intact unit instead of the icons getting stranded on
   their own line below everything (the original bug this all works
   around). Deliberately unboxed (no border/background/shadow) so it reads
   as a light toolbar line rather than a second card competing with the
   grid below it. */
.filters-container {
  /* Positioning root for .sort-dropdown (see below) - anchoring the
     dropdown to the whole toolbar rather than just the sort button means
     it always clears every row of the toolbar, even when .filters-right
     has wrapped onto its own line underneath .filters-left. Anchoring to
     the button alone left the dropdown covering that wrapped line, since
     its own height only ever accounted for clearing the first line. */
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  width: 100%;
  margin: 0 auto 0.6rem;
  padding: 0;
  background: none;
  border: none;
  box-shadow: none;
  box-sizing: border-box;
}

.filters-left {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  flex: 1 1 auto;
  min-width: 0;
}

/* Counter + view toggle - the two extras Epic's layout doesn't have -
   wrap onto a new line as one intact unit rather than splitting apart. */
.filters-right {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-shrink: 0;
}

/* --card-border is too light (#e0e0e0) against the light-mode page
   background to read as a real edge, so these controls get an explicit,
   slightly darker neutral border in light mode instead. (.filter-toggle-btn
   and .view-toggle-wrapper used to be listed here too - they're filled
   pills with no border now, so the override no longer applies to them.) */
[data-md-color-scheme="light"] .sort-toggle-btn,
[data-md-color-scheme="light"] .sort-dropdown {
  border-color: #c4c4c4;
}

/* Hide old filter rows */
.filters-row.fixed-row {
  display: none;
}

/* Search Bar Wrapper - the sort/view-toggle/filter-toggle button group,
   sitting on the right of .filters-container next to #portsCounter. */
.search-wrapper {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
}

/* Search Input */
.search-bar {
  flex: 1;
  min-width: 0; /* Allow input to shrink */
  padding: 0.875rem 1.25rem;
  border-radius: 12px;
  border: 1px solid transparent;
  font-size: 1rem;
  transition: all 0.2s ease;
  outline: none;
}

[data-md-color-scheme="light"] .search-bar {
  background-color: #ffffff;
  color: #111111;
  border-color: #c4c4c4;
}

[data-md-color-scheme="dark"] .search-bar {
  background-color: #2b2b2b;
  color: #eeeeee;
  border-color: #3a3a3a;
}

.search-bar:focus {
  border-color: #F49519;
  box-shadow: 0 0 0 3px rgba(244, 149, 25, 0.12);
}

.search-bar::placeholder {
  color: #888888;
}

/* Filter Toggle Button
   Filled pill, matching .view-toggle-wrapper right beside it (and the
   .active-filter-chip / .carousel-btn treatment used elsewhere). It was an
   outlined 7px-radius square next to a filled 999px pill, at a different
   height - two visual languages sitting adjacent in the same toolbar.
   The 9px padding is load-bearing: it sets the 14px inner box the
   hamburger-to-X transforms below are tuned against, so size changes are
   made via width/height + padding together, never padding alone. */
.filter-toggle-btn {
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  width: 32px;
  height: 32px;
  background-color: rgba(128, 128, 128, 0.18);
  border: none;
  border-radius: 999px;
  cursor: pointer;
  padding: 9px;
  transition: all 0.2s ease;
  flex-shrink: 0;
}

.filter-toggle-btn:hover {
  background-color: rgba(244, 149, 25, 0.18);
}

.filter-toggle-btn span {
  display: block;
  width: 100%;
  height: 2px;
  background-color: var(--card-text, #555555);
  border-radius: 2px;
  transition: all 0.3s ease;
}

.filter-toggle-btn.active {
  background-color: rgba(244, 149, 25, 0.18);
}

.filter-toggle-btn.active span {
  background-color: #F49519;
}

.filter-toggle-btn.active span:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}

.filter-toggle-btn.active span:nth-child(2) {
  opacity: 0;
}

.filter-toggle-btn.active span:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

/* Sort Dropdown */
.sort-dropdown-wrapper {
  flex-shrink: 0;
}

/* "Show:" prefix sitting left of the sort trigger, Epic-style. */
.sort-label {
  font-size: 0.72rem;
  color: var(--card-stat-color, #888888);
  white-space: nowrap;
}

/* Borderless text trigger showing the active sort name + chevron, rather
   than an icon-only bordered square. */
.sort-toggle-btn {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  height: 30px;
  padding: 0 0.3rem;
  background-color: transparent;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  transition: background-color 0.2s ease;
  flex-shrink: 0;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--card-text);
  white-space: nowrap;
}

.sort-toggle-btn i {
  font-size: 0.62rem;
  color: var(--card-stat-color, #888888);
}

.sort-toggle-btn:hover {
  background-color: rgba(128, 128, 128, 0.18);
}

/* Shares the filter panel's own look (same background colors, same dense
   row padding/radius/hover as .filter-checkbox-item) rather than its own
   separate card style, so the two popovers read as one visual language.
   z-index sits above .filter-panel (1100) so it's never clipped or
   interleaved with the sidebar when both happen to be open at once. */
.sort-dropdown {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  min-width: 170px;
  padding: 4px;
  border-radius: 8px;
  border: none;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s;
  z-index: 1200;
  box-shadow: 0 8px 24px rgba(0,0,0,0.3);
}

[data-md-color-scheme="light"] .sort-dropdown {
  background-color: #ececec;
}

[data-md-color-scheme="dark"] .sort-dropdown {
  background-color: #2b2b2b;
}

.sort-dropdown.open {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.sort-option {
  padding: 0.5rem 0.6rem;
  border-radius: 6px;
  cursor: pointer;
  transition: background-color 0.15s ease;
  font-size: 0.72rem;
  font-weight: 500;
}

[data-md-color-scheme="light"] .sort-option {
  color: #111111;
}

[data-md-color-scheme="dark"] .sort-option {
  color: #eeeeee;
}

.sort-option:hover {
  background-color: rgba(128, 128, 128, 0.22);
}

/* Selected state reuses the same orange accent as a checked filter
   checkbox, instead of a separate grey-highlight-row treatment. */
.sort-option.selected {
  color: #F49519;
  font-weight: 700;
}

/* Filter Panel */
.filter-panel {
  position: fixed;
  /* Starts below the site header instead of the viewport's absolute top -
     otherwise this panel's opaque background sits at a higher z-index
     than the header and fully hides it (the header is still there and
     still sticky, just painted over) for as long as the drawer is open.
     --md-header-actual-height is measured live in JS (see
     updateHeaderHeightVar()) rather than assumed as a fixed rem value,
     since the header's real height varies with whether its .md-tabs row
     is showing and with the browser's own font-size settings. Falls back
     to 3rem if the variable isn't set yet (e.g. no-JS). Only applies
     below the 900px breakpoint below, where the panel is still a
     slide-out drawer rather than the static sidebar column it becomes on
     wider screens. */
  top: var(--md-header-actual-height, 3rem);
  right: -400px;
  width: 100%;
  max-width: 400px;
  height: calc(100vh - var(--md-header-actual-height, 3rem));
  /* No z-index here on purpose - it's set only inside the <900px media
     query below, so a raised stacking order can never apply outside the
     narrow range where this is actually an overlay drawer. The desktop
     sidebar rule further down also explicitly sets z-index:auto as a
     second line of defense. */
  transition: right 0.3s ease;
  overflow-y: auto;
  /* No horizontal padding on the panel itself - each row (header /
     accordion) carries its own, so the divider borders span the full
     width edge-to-edge instead of stopping short of it. */
  padding: 0;
  box-shadow: -4px 0 12px rgba(0,0,0,0.2);
}

@media (max-width: 899px) {
  .filter-panel {
    z-index: 1100;
  }
}

[data-md-color-scheme="light"] .filter-panel {
  background-color: #ececec;
  color: #111111;
}

[data-md-color-scheme="dark"] .filter-panel {
  background-color: #2b2b2b;
  color: #eeeeee;
}

.filter-panel.open {
  right: 0;
}

/* Filter Panel Overlay */
.filter-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 1099;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s ease, visibility 0.3s ease;
}

.filter-overlay.active {
  opacity: 1;
  visibility: visible;
}

/* Panel Header */
.filter-panel-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid;
}

[data-md-color-scheme="light"] .filter-panel-header {
  border-bottom-color: #e0e0e0;
}

[data-md-color-scheme="dark"] .filter-panel-header {
  border-bottom-color: #333333;
}

.filter-panel-header h2 {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

/* Active-filter count next to "Filters" in the header - plain "(N)" text,
   not a pill/chip. */
.filter-count-badge {
  font-weight: 700;
  color: var(--card-text);
}

.filter-panel-header-actions {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.filter-reset-link {
  background: none;
  border: none;
  padding: 0;
  color: #F49519;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
}

.filter-reset-link:hover {
  text-decoration: underline;
}

.close-panel-btn {
  background: none;
  border: none;
  font-size: 1.75rem;
  cursor: pointer;
  color: var(--card-stat-color, #888888);
  transition: color 0.2s ease, transform 0.2s ease;
  padding: 0;
  line-height: 1;
}

.close-panel-btn:hover {
  color: var(--card-text, #111111);
  transform: scale(1.1);
}

/* Filter Accordion (Device / OS / Genre / Options / Advanced) - plain div
   + JS class toggle (see initFilterAccordions in games.md), not native
   <details>/<summary>: mkdocs-material applies its own "admonition" style
   (colored border, marker icon) to any <details> in the content area,
   which fought this component's own look. */
.filter-accordion {
  border-bottom: 1px solid var(--card-border, rgba(128, 128, 128, 0.15));
  padding: 0;
}

.filter-accordion:last-of-type {
  border-bottom: none;
}

.filter-accordion-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.7rem 1rem;
  cursor: pointer;
  font-weight: 600;
  font-size: 0.78rem;
  user-select: none;
  transition: background-color 0.15s ease;
}

.filter-accordion-summary:hover {
  background-color: rgba(128, 128, 128, 0.14);
}

.accordion-chevron {
  font-size: 0.62rem;
  color: var(--card-stat-color, #888888);
  transition: transform 0.2s ease;
  flex-shrink: 0;
}

.filter-accordion.open .accordion-chevron {
  transform: rotate(180deg);
}

.filter-accordion-body {
  display: none;
  padding: 0 1rem 0.7rem;
  position: relative;
}

.filter-accordion.open .filter-accordion-body {
  display: block;
}

/* Counter - plain inline text sharing the one-line row with the sort/view
   controls now, not its own separate bordered/boxed row. */
#portsCounter {
  margin: 0;
  font-weight: 400;
  font-size: 0.72rem;
  color: var(--card-stat-color, #888888);
  white-space: nowrap;
}

/* Active filter chips - one removable pill per active filter value,
   sitting inline next to the counter (display:none entirely when no
   filters are active - see updateActiveFilterChips()). */
.active-filters-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  min-width: 0;
}

.active-filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.15rem 0.3rem 0.15rem 0.5rem;
  border: none;
  border-radius: 999px;
  background-color: rgba(128, 128, 128, 0.22);
  color: var(--card-text);
  font-size: 0.68rem;
  font-weight: 500;
  cursor: pointer;
  transition: background-color 0.2s ease;
}

.active-filter-chip:hover {
  background-color: rgba(128, 128, 128, 0.38);
}

.active-filter-chip i {
  font-size: 0.7rem;
  opacity: 0.7;
}

/* ===== Steam library section =====
   Lives in the filter panel next to Device/OS - same class of input (a
   detail about the visitor that filters the catalogue). */
.steam-status-badge {
  display: inline-block;
  margin-left: 0.35rem;
  padding: 0.1rem 0.4rem;
  border-radius: 999px;
  background-color: rgba(128, 128, 128, 0.22);
  color: var(--card-stat-color, #888888);
  font-size: 0.62rem;
  font-weight: 600;
  vertical-align: middle;
  white-space: nowrap;
}

.steam-status-badge.is-connected {
  background-color: rgba(244, 149, 25, 0.18);
  color: #F49519;
}

.steam-help {
  margin: 0 0 0.5rem;
  font-size: 0.72rem;
  line-height: 1.45;
  color: var(--md-default-fg-color--light);
}

.steam-input-row {
  display: flex;
  gap: 0.4rem;
}

.steam-input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 0.45rem 0.6rem;
  border-radius: 8px;
  /* Explicit alpha grey, not --card-border (#e0e0e0): that sits ~1:1
     against the light-mode panel and disappears. Same reasoning as the
     outlined controls on the port page. */
  border: 1px solid rgba(128, 128, 128, 0.45);
  background-color: var(--md-default-bg-color);
  color: var(--card-text);
  font-size: 0.78rem;
  outline: none;
}

.steam-input:focus {
  border-color: #F49519;
  box-shadow: 0 0 0 3px rgba(244, 149, 25, 0.12);
}

.steam-connect-btn {
  flex-shrink: 0;
  padding: 0 0.8rem;
  border: none;
  border-radius: 8px;
  background-color: #F49519;
  color: #ffffff;
  font-size: 0.75rem;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 0.2s ease;
}

.steam-connect-btn:hover:not(:disabled) {
  background-color: #ff9d2e;
}

.steam-connect-btn:disabled {
  opacity: 0.6;
  cursor: default;
}

.steam-note {
  margin: 0.5rem 0 0;
  font-size: 0.65rem;
  line-height: 1.45;
  color: var(--card-stat-color, #888888);
}

.steam-status {
  margin: 0.5rem 0 0;
  font-size: 0.68rem;
  line-height: 1.45;
  color: var(--card-stat-color, #888888);
}

.steam-status.is-ok {
  color: #2fb344;
}

.steam-status.is-error {
  color: #dc3545;
}

.steam-status.is-warn {
  color: #F49519;
}

.steam-disconnect-btn {
  margin-top: 0.6rem;
  padding: 0;
  background: none;
  border: none;
  color: var(--card-stat-color, #888888);
  font-size: 0.7rem;
  text-decoration: underline;
  cursor: pointer;
}

.steam-disconnect-btn:hover {
  color: #dc3545;
}

.filter-subgroup {
  margin-bottom: 0.6rem;
}

.filter-subgroup label {
  display: block;
  font-size: 0.72rem;
  font-weight: 500;
  margin-bottom: 0.25rem;
  color: var(--md-default-fg-color--light);
  text-transform: uppercase;
  letter-spacing: 0.3px;
}

/* Filter checkbox/radio list (Device / OS / Genre / Options / Runtime /
   Architecture / Requirements) - matches the Epic Games Store filter
   panel: a plain, dense vertical list of checkbox/radio rows, not pill/
   tag buttons or a dropdown. Device/OS use radio inputs (single-choice),
   everything else uses checkboxes (multi-select) - same row styling
   either way, see the shared input rule below. */
.filter-checkbox-list,
.filter-radio-list {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.filter-checkbox-item {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.15rem 0.25rem;
  border-radius: 4px;
  cursor: pointer;
  user-select: none;
  font-size: 0.72rem;
  color: var(--card-text);
  transition: background-color 0.15s ease;
}

.filter-checkbox-item:hover {
  background-color: rgba(128, 128, 128, 0.22);
}

/* Square tickboxes for everything, checkboxes and radios alike. */
.filter-checkbox-item input[type="checkbox"],
.filter-checkbox-item input[type="radio"] {
  appearance: none;
  -webkit-appearance: none;
  flex-shrink: 0;
  width: 13px;
  height: 13px;
  margin: 0;
  border-radius: 3px;
  border: 1px solid var(--card-border, rgba(128, 128, 128, 0.4));
  background-color: transparent;
  cursor: pointer;
  position: relative;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

.filter-checkbox-item input[type="checkbox"]:checked,
.filter-checkbox-item input[type="radio"]:checked {
  background-color: #F49519;
  border-color: #F49519;
}

.filter-checkbox-item input[type="checkbox"]:checked::after,
.filter-checkbox-item input[type="radio"]:checked::after {
  content: '';
  position: absolute;
  left: 3px;
  top: 0;
  width: 4px;
  height: 7px;
  border: solid #ffffff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* Mobile Responsive */
@media (max-width: 768px) {
  .filter-panel {
    max-width: 100%;
    right: -100%;
  }
  
  /* Mobile toolbar order:
       row 1  Show: [sort]            [grid|list] [filters]
       row 2  active filter chips
       row 3  result counter
     display:contents dissolves the .filters-left / .filters-right grouping
     boxes so their children become flex items of the container directly -
     the only way to interleave them like this (controls come from the
     right group, chips from the left) without duplicating markup. The two
     groups still exist as boxes on desktop, where they're what keeps the
     counter and toggle from being stranded on separate lines. */
  .filters-container {
    padding: 0.75rem;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
  }

  .filters-left,
  .filters-right {
    display: contents;
  }

  .sort-label {
    order: 1;
  }

  /* "Show:" is dropped rather than shrunk. The longest sort value ("Date
     Updated (Newest)") needs 146px and only ~108px was left beside the
     controls, so it ellipsised; no font size fixes that gap without going
     unreadably small (~10px), whereas losing this prefix frees 48px and
     the label fits at full size. The trigger still reads fine on its own -
     it shows the current sort value and carries a chevron. */
  .sort-label {
    display: none;
  }

  /* flex-basis:0 (not auto) is the load-bearing bit. A flex line wraps
     before it shrinks, so with an auto basis the sort trigger claimed its
     full content width - 190px for "Date Updated (Newest)" vs 140px for
     "Most Downloads" - and pushed the controls onto a second row. A zero
     basis means this item can never overflow the line on its own, so no
     wrap happens; it then grows into whatever space the controls leave and
     ellipsises the label if that isn't enough. */
  .sort-dropdown-wrapper {
    order: 2;
    flex: 1 1 0;
    min-width: 0;
  }

  .sort-toggle-btn {
    width: 100%;
    max-width: 100%;
  }

  .sort-toggle-btn > span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .sort-toggle-btn > i {
    flex-shrink: 0;
  }

  /* margin-left:auto rather than margin-right:auto on the sort trigger:
     that only right-aligns these while they share a line with it. This
     keeps them flush right even if they do wrap onto a line of their own. */
  .search-wrapper {
    order: 3;
    flex-shrink: 0;
    margin-left: auto;
  }

  /* flex-basis:100% forces each onto its own row. Still respects the inline
     display:none JS sets on the chip row when no filters are active. */
  .active-filters-row {
    order: 4;
    flex-basis: 100%;
  }

  #portsCounter {
    order: 5;
    flex-basis: 100%;
  }

  .search-bar {
    padding: 0.75rem 1rem;
    font-size: 0.95rem;
  }

  /* Filter button and view toggle are a matched pair in this toolbar, so
     they get the same height on mobile too. Padding grows with the box to
     hold the hamburger's inner square at 14px - the value the X transform
     is tuned against; at the old 44px/9px the bars spread out and the X
     stopped meeting in the middle. */
  .filter-toggle-btn {
    width: 36px;
    height: 36px;
    padding: 11px;
  }

  /* The matching .view-toggle-wrapper/.view-toggle-btn mobile sizes live in
     shared-toggle-pagination.css, next to their base rules - that file
     loads after this one, so an override here loses on source order
     (media queries add no specificity). */

  /* No fixed width here (unlike .filter-toggle-btn above) - this is a
     text+chevron trigger, not an icon square, so squashing it to 36px
     would clip the sort label. Just grow the tap target via height/
     padding/font-size instead. */
  .sort-toggle-btn {
    height: 40px;
    padding: 0 0.5rem;
    font-size: 0.8rem;
  }

  .sort-toggle-btn i {
    font-size: 0.68rem;
  }

  .sort-dropdown {
    min-width: 160px;
  }
}

/* Extra small phones */
@media (max-width: 380px) {
  .filters-container {
    padding: 0.5rem;
  }
  
  .search-wrapper {
    gap: 0.35rem;
  }
  
  .search-bar {
    padding: 0.6rem 0.8rem;
    font-size: 0.9rem;
  }
  
  /* Filter button and view toggle keep the 36px they get at 768px - the
     pair has to stay the same size as each other, and dropping only one of
     them here is what made them mismatch in the first place. */

  /* Text+chevron trigger, not an icon square - no fixed width (see the
     768px block above, same reasoning: forcing one here clips/overflows
     the sort label instead of shrinking it). */
  .sort-toggle-btn {
    height: 34px;
    padding: 0 0.4rem;
    font-size: 0.7rem;
  }

  .sort-toggle-btn i {
    font-size: 1.1rem;
  }
}

