  :root { 
    --accent: #E5C158; /*Live Color: #E5C158, PTS Color: #497ab4 */
    --accent-dim: #D1B366; /* Live Color: #D1B366, PTS Color: #223b5a*/
    --bg: #232323;
    --card-bg: #181818;
    --text: #e0e0e0;
    --text-muted: #aaa;
    --border-subtle: rgba(229, 193, 88, 0.18);
    --content-width: 800px;
    --card-width: 720px;
  }

  html {
    background-color: var(--bg);
  }

  body {
    font-family: Arial, sans-serif;
    margin: 0;
    background-color: var(--bg);
    color: var(--text);
    overflow-x: hidden;
  }

  .container {
    max-width: var(--content-width);
    margin: 0 auto;
    padding: 0 16px;
  }

  h1 {
    color: var(--accent);
    margin-bottom: 5px;
    text-align: center;
  }

 .meta {
    text-align: center;
    margin-top: 0.5em;
  }

  .author {
    color: var(--text-muted);
    font-size: 13px;
  }

  .badge-link {
    background: #333;
    color: var(--accent);
    border-radius: 4px;
    padding: 2px 6px;
    text-decoration: none;
    font-size: 13px;
    transition: background 0.2s;
  }

  @media (hover: hover) {
    .badge-link:hover {
      background: #555;
    }
  }

  .placement-note {
    margin: 0px;
    font-size: 0.85rem;
    color: var(--text-muted);
    width: 100%;
  }


  #pagination button {
    padding: 6px 0;
    width: 50px;
    margin-left: 2px;
    background: var(--card-bg);
    color: var(--text);
    border: 1px solid var(--border-subtle);
    border-radius: 4px;
    cursor: pointer;
    text-align: center;
    transition: 0.2s;
  }
  @media (hover: hover) {
    #pagination button:hover:not(:disabled) {
      background: var(--accent);
      color: black;
    }
  }
  #pagination button:disabled {
    opacity: 0.4;
    cursor: default;
  }
  #pagination button.active-page {
    background: var(--accent);
    color: black;
    font-weight: bold;
  }

  #paginationTop {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 2px;
    margin: 10px 0 0;
    padding: 0;
  }
  #paginationTop button {
    padding: 2px 0;
    width: 34px;
    height: 40px;
    margin: 0;
    background: var(--card-bg);
    color: var(--text-muted);
    border: 1px solid var(--border-subtle);
    border-radius: 4px;
    cursor: pointer;
    font-size: 18px;
    font-weight: 700;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    transition: 0.2s;
    box-sizing: border-box;
  }
  @media (hover: hover) {
    #paginationTop button:hover:not(:disabled) {
      background: var(--accent);
      color: black;
      border-color: var(--accent);
    }
  }
  #paginationTop button:disabled {
    opacity: 0.3;
    cursor: default;
  }
  #paginationTop button.active-page {
    background: transparent;
    color: var(--accent);
    border-color: var(--accent);
    font-weight: bold;
  }
  #paginationTop span {
    color: var(--text-muted);
    font-size: 12px;
  }
  
  .controls {
    position: flex;
    top: 0;
    z-index: 100;
    background: var(--bg);
    padding: 12px 16px;
    border-bottom: 1px solid var(--card-bg);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
  }

  .controls input[type="text"] {
    padding: 10px;
    font-size: 16px;
    width: 100%;
    max-width: 350px;
    border: 1px solid var(--border-subtle);
    border-radius: 6px;
    background-color: var(--card-bg);
    color: var(--text);
  }
  .search-line input[type="text"] {
    border: none;
    border-radius: 0;
    background-color: transparent;
    max-width: none;
  }

  .controls .search-line {
    display: flex;
    gap: 0;
    width: 100%;
    max-width: 450px;
    height: 40px;
    background-color: var(--card-bg);
    border: 1px solid var(--border-subtle);
    border-radius: 6px;
    align-items: stretch;
    box-sizing: border-box;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
  }

  .controls .search-line:focus-within {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(229, 193, 88, 0.15);
  }

  .search-line input:focus,
  .search-line select:focus,
  .search-line textarea:focus {
    outline: none;
    box-shadow: none;
  }

  .search-line input {
    -webkit-appearance: none;
  }

  .controls label {
    font-size: 14px;
    color: var(--text-muted);
    margin-left: 4px;
  }

  .controls .inline-group {
    display: flex;
    align-items: center;
    gap: -10px;
    justify-content: center;
  }

  .inline-group {
    display: flex;
    align-items: center;
    gap: 0px;
    justify-content: center;
    width: 100%;
  }

  #clearFiltersExternal {
    background-color: var(--card-bg);
    border: 1px solid var(--border-subtle);
    border-left: none;
    position: relative;
    top: -8px;
    border-radius: 0 6px 6px 0;
    height: 36px;
    padding: 0 12px;
    cursor: pointer;
    transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
    color: #888;
  }

  @media (hover: hover) {
    #clearFiltersExternal:hover {
      background-color: rgba(255, 77, 79, 0.15);
      color: #ff6b6b;
      border-color: rgba(255, 77, 79, 0.4);
    }
  }

  .inline-group label {
    font-size: 14px;
    color: var(--text-muted);
  }

  .group-filters {
    display: flex;
    margin-right: 10px;
    flex-shrink: 0;
  }

  .group-sort {
    display: flex;
    align-items: center;
    gap: 8px; 
  }

  #results {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 20px;
    padding: 16px;
    margin: 0 auto;
    max-width: 1200px;
  }

  /* ── Filter Modal ── */
  .filter-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.7);
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    animation: filterFadeIn 0.15s ease forwards;
  }
  .filter-modal-overlay.closing {
    animation: filterFadeOut 0.15s ease forwards;
  }
  @keyframes filterFadeIn { from { opacity: 0; } to { opacity: 1; } }
  @keyframes filterFadeOut { from { opacity: 1; } to { opacity: 0; } }
  .filter-modal {
    background: var(--card-bg);
    border: 1px solid var(--border-subtle);
    border-radius: 8px;
    width: min(700px, 95vw);
    height: 92vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    animation: filterSlideIn 0.15s ease forwards;
  }
  .filter-modal.closing {
    animation: filterSlideOut 0.15s ease forwards;
  }
  @keyframes filterSlideIn { from { transform: scale(0.97); opacity: 0; } to { transform: scale(1); opacity: 1; } }
  @keyframes filterSlideOut { from { transform: scale(1); opacity: 1; } to { transform: scale(0.97); opacity: 0; } }
  .filter-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border-subtle);
    flex-shrink: 0;
  }
  .filter-modal-title {
    font-weight: 700;
    font-size: 14px;
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: 0.05em;
  }
  .filter-modal-close {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 18px;
    cursor: pointer;
    padding: 2px 6px;
    border-radius: 4px;
    transition: color 0.15s;
  }
  @media (hover: hover) {
    .filter-modal-close:hover { color: var(--text); }
  }
  .filter-modal-close:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    color: var(--text);
  }
  .filter-modal-body {
    display: flex;
    flex-direction: row;
    overflow: hidden;
    flex: 1;
  }
  .filter-modal-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 16px;
    border-top: 1px solid var(--border-subtle);
    flex-shrink: 0;
  }
  .filter-modal-footer .clear-filters {
    background: var(--bg);
    border: 2px solid #ff4d4f;
    border-radius: 4px;
    color: #ff4d4f;
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
    padding: 6px 20px;
    margin: 0;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    align-self: center;
    box-sizing: border-box;
    transition: background-color 0.15s, color 0.15s;
  }
  @media (hover: hover) {
    .filter-modal-footer .clear-filters:hover {
      background: #ff4d4f;
      color: black;
    }
  }
  .filter-modal-done {
    background: var(--accent);
    color: black;
    border: 2px solid var(--accent);
    border-radius: 4px;
    padding: 6px 20px;
    font-weight: 700;
    font-size: 13px;
    margin: 0;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    align-self: center;
    box-sizing: border-box;
    cursor: pointer;
    transition: background-color 0.15s;
  }
  @media (hover: hover) {
    .filter-modal-done:hover { background: var(--accent-dim); }
  }

  .filter-col-placement,
  .filter-col-categories {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 10px 8px;
    border-right: 1px solid var(--border-subtle);
    overflow-y: auto;
    flex-shrink: 0;
  }
  .filter-col-placement  { min-width: 130px; }
  .filter-col-categories { min-width: 150px; }
  .filter-col-sub {
    flex: 1;
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;
    gap: 6px;
    padding: 10px;
    overflow-y: auto;
    overflow-x: hidden;
    transition: opacity 0.15s ease;
    min-height: 200px;
  }
  .filter-col-sub button { flex: 0 0 auto; }
  .filter-col-sub-empty {
    color: #555;
    font-size: 12px;
    font-style: italic;
    padding: 4px 2px;
    width: 100%;
  }
  #filtersOptions button.cat-active {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
  }
  .filter-header {
    font-weight: 700;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--accent);
    padding: 4px 0 6px;
    margin: 0;
    text-align: center;
  }

  /* Mobile Support: Tablets and smaller. Keep 3 columns, just tighten */
  @media (max-width: 800px) {
    .filter-modal {
      width: min(700px, 95vw);
    }
    .filter-col-placement  { min-width: 90px; }
    .filter-col-categories { min-width: 110px; }
    .filter-col-placement button,
    .filter-col-categories button,
    .filter-col-sub button {
      font-size: 12px;
      padding: 4px 6px;
    }
  }

  /* Mobile Support: Phones (max 599px). Keep 3 columns, shrink further */
  @media (max-width: 599px) {
    .filter-modal {
      width: 95vw;
      height: 85vh;
      border-radius: 6px;
    }
    .filter-modal-header {
      padding: 8px 10px;
    }
    .filter-modal-title {
      font-size: 12px;
    }
    .filter-col-placement  { min-width: 72px; padding: 6px 4px; }
    .filter-col-categories { min-width: 100px; padding: 6px 4px; }
    .filter-col-sub { padding: 6px 4px; gap: 3px; }
    .filter-header {
      font-size: 9px;
      padding: 2px 0 3px;
    }
    .filter-col-placement button,
    .filter-col-categories button,
    .filter-col-sub button {
      font-size: 11px;
      padding: 4px 5px;
    }
    .filter-modal-footer {
      padding: 8px 10px;
    }
    .filter-modal-footer .clear-filters,
    .filter-modal-footer .filter-modal-done {
      font-size: 12px;
      padding: 5px 10px;
    }
  }

  /* Mobile Support: Very small phones (max 374px) */
  @media (max-width: 374px) {
    .filter-modal {
      width: 92vw;
      height: 80vh;
    }
    .filter-col-placement button,
    .filter-col-categories button,
    .filter-col-sub button {
      font-size: 10px;
      padding: 4px 6px;
      min-height: 26px;
    }
    .filter-header {
      font-size: 8px;
      padding: 1px 0 2px;
    }
  }



  /* While #results has no cards in it yet (first paint, before the DB
     fetch resolves), hold open roughly the amount of space the grid will
     occupy. This stops the page from being short-then-suddenly-tall, which
     is what causes the header's elevated background to visually "flash"
     before the darker page background takes over. Once JS inserts cards,
     :empty stops matching and this rule drops out automatically. */
  #results:empty {
    display: block;
    min-height: 60vh;
  }

  .cover-image-wrap {
    width: 100%;
    aspect-ratio: 1042 / 340;
    overflow: hidden;
  }
  .cover-image {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
  }



  .inline-wrap {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    flex-wrap: wrap;
  }

  /* Used specifically for Placement Conditions. By default this is a plain
     left-aligned row. If everything fits on one line, it stays that way,
     unchanged from before. Only when content actually wraps does JS add
     .is-wrapped, which switches to a single max-content grid column: the
     first (topmost) condition sets the column's width and stays
     left-aligned, while the connector and whatever follows it centers
     underneath in that same width. minmax(0, ...) lets the column shrink on
     narrow cards instead of overflowing. */
  .inline-wrap--conditions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-start;
    gap: 6px;
    max-width: 100%;
  }
  .inline-wrap--conditions.is-wrapped {
    display: inline-grid;
    grid-template-columns: 1fr;
    row-gap: 6px;
    justify-items: center;
  }
  .inline-wrap--conditions.is-wrapped > *:first-child {
    justify-self: start;
  }
  .inline-wrap--conditions.is-wrapped .connector {
    text-align: center;
  }

  .connector {
    color: var(--accent);
    font-weight: 600;
    font-size: 13px;
    margin: 0 6px;
    line-height: 1;
    text-transform: uppercase;
  }
  .connector--chain {
    flex-basis: 100%;
    margin: 0 0 0 2px;
    font-size: 12px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    text-align: left;
    color: var(--text-muted);
  }

  .arrow {
    display: inline-block;
    width: 0;
    height: 0;
    border-top: 6px solid transparent;
    border-bottom: 6px solid transparent;
    border-left: 10px solid var(--accent);
    margin: 0 8px;
    vertical-align: middle;
  }

  .inline-wrap .arrow + .arrow {
    display: none;
  }

  .pill {
    background: var(--bg);
    border: 2px solid var(--accent);
    border-radius: 20px;
    padding: 4px 12px;
    font-size: 14px;
    color: var(--accent);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    line-height: 1.2;
    max-width: 240px;
    min-height: 32px;
    word-break: break-word;
  }

  /* Merged group for pills that satisfy an OR requirement (any one fulfills it) */
  .pill-group {
    display: flex;
    flex-direction: column;
    border: 2px solid var(--accent);
    border-radius: 14px;
    overflow: hidden;
    max-width: 240px;
    width: 100%;
    background: var(--bg);
  }

  .pill-group .pill {
    border: none;
    border-radius: 0;
    max-width: none;
    width: 100%;
    padding: 6px 12px;
  }

  .pill-group-divider {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 10px;
    font-size: 10px;
    line-height: 1.4;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
  }

  .pill-group-divider::before,
  .pill-group-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--accent-dim);
    opacity: 0.4;
  }

  .changelog-older-toggle {
    display: block;
    width: 100%;
    margin: 10px 0 4px;
    padding: 8px 12px;
    background: rgba(229, 193, 88, 0.08);
    border: 1px solid var(--border-subtle);
    border-radius: 4px;
    color: var(--accent);
    font-size: 13px;
    font-weight: bold;
    cursor: pointer;
    transition: background-color 0.2s ease;
  }
  @media (hover: hover) {
    .changelog-older-toggle:hover {
      background: rgba(229, 193, 88, 0.16);
    }
  }

  .changelog-entry h4 {
      margin: 0 0 4px 0;
      font-size: 14px;
      font-weight: bold;
      color: var(--accent);
    }

    .changelog-entry { /*Live Color: rgba(229, 193, 88, 0.05), PTS Color: rgba(15, 147, 255, 0.05); */
      background: rgba(229, 193, 88, 0.05);
      border-left: 3px solid var(--accent);
      border-radius: 4px;
      padding: 6px 12px;
      margin: 6px 0;
      text-align: left;
      min-width: 0;
      overflow-wrap: anywhere;
      word-wrap: break-word;
    }

    .changelog-entry ul {
      padding: 0;
      margin: 4px 0;
      background: transparent;
      list-style-type: disc;
      list-style-position: outside;
      min-width: 0;
    }

    .changelog-entry li {
      display: list-item;
      background-color: transparent;
      border: none;
      box-shadow: none;
      margin-bottom: 6px;
      margin-left: 16px;
      padding: 2px 0;
      border-radius: 0;
      align-items: baseline;
      width: auto;
      text-align: left;
      min-width: 0;
      overflow-wrap: anywhere;
      word-wrap: break-word;
    }

    .changelog-entry li ul {
      margin: 2px 0 0 0;
      list-style-type: circle;
    }

    .changelog-entry li li {
      margin-bottom: 2px;
      margin-left: 16px;
      font-size: 13px;
      color: var(--text-muted);
    }

  #searchBox {
    flex: 1;
    min-width: 0;
    font-size: 16px;
    padding: 0 12px;
    border: none;
    border-radius: 0;
    background-color: transparent;
    color: var(--text);
    box-sizing: border-box;
    outline: none;
  }

  .search-line .custom-dropdown::before {
    content: '';
    width: 1px;
    align-self: stretch;
    background-color: rgba(255, 255, 255, 0.15);
    flex-shrink: 0;
  }

  /* #dropdownOptions/#sortOptions listbox-panel rules removed - Search By
     and Sort By are now native <select> elements (see the block near the
     end of this file), so the OS/browser renders the open option list
     and it can't be themed the way the old custom listbox was. */

  #dropdownSelected {
    display: flex;
    align-items: center;
    padding: 0 12px;
    font-size: 14px;
    border: none;
    border-radius: 0 5px 5px 0;
    background-color: transparent;
    color: var(--text);
    cursor: pointer;
    box-sizing: border-box;
    transition: background-color 0.15s, color 0.15s;
    white-space: nowrap;
  }

  @media (hover: hover) {
    #dropdownSelected:hover {
      background-color: var(--accent);
      color: black;
    }
  }

  .custom-dropdown {
    position: relative;
    width: max-content;
    height: 40px;
    display: flex;
    flex-shrink: 0;
  }

  #sortDropdown, #sortSelected,
  .custom-dropdown, #dropdownSelected {
    box-sizing: border-box;
  }

  /* Modal background */
  .modal {
    display: none;
    position: fixed;
    z-index: 1000;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    overflow: auto;
    background-color: rgba(26,26,26, 0.5); 
  }

  .modal.is-open {
    display: block;
    opacity: 1;
  }

  .modal-content {
    position: relative;
    background-color: var(--card-bg);
    color: var(--text);
    width: min(90%, 640px);
    display: flex;
    flex-direction: column;
    /* dvh keeps this honest on mobile browsers whose chrome (address
       bar, etc.) eats into vh - falls back to vh where dvh isn't
       supported. Matches the height item-view's "view more" modals use. */
    max-height: 85vh;
    max-height: min(85vh, 85dvh);
    margin: 50px auto;
    border-radius: 8px;
    box-shadow: 0 0 15px rgba(0,0,0,0.5);
    overflow: hidden; 
    transform: translateY(-6px);
    transition: transform 120ms ease-out, opacity 120ms ease-out;
    opacity: 0;
  }

  .modal-header {
    padding: 10px 15px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-shrink: 0;
  }

  .modal-body {
    /* Fills whatever space remains under the fixed-height header,
       instead of a separate fixed max-height competing with the
       parent's own cap - same pattern as .assignable-modal. */
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;      
    padding: 10px 15px;
    scrollbar-width: thin;
    scrollbar-color: var(--accent) var(--card-bg);
  }

    /* Modal scrollbar */
  .modal-body::-webkit-scrollbar {
    width: 8px;
  }
  
  .modal-body::-webkit-scrollbar-track {
    background: var(--card-bg); /* same as modal bg */
    border-radius: 4px;
  }
  
  .modal-body::-webkit-scrollbar-thumb {
    background-color: var(--accent); /* accent color */
    border-radius: 4px;
    border: 2px solid var(--card-bg); /* optional padding around thumb */
  } 

  .modal.is-open .modal-content {
    transform: translateY(0);
    opacity: 1;
  }

  /* Close button */
  .close {
    font-size: 24px;
    font-weight: bold;
    cursor: pointer;
    color: var(--accent);
  }

  @media (hover: hover) {
    .close:hover {
      color: var(--accent-dim);
    }
  }
  .close:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 2px;
  }

  /* Modal headings are focused programmatically on open (tabindex="-1":
     reachable by script, never a Tab stop) so screen readers announce the
     dialog without lighting up the close button. No ring: there is nothing
     to activate here, and the first Tab lands on a real control with its
     own indicator. Scoped to exactly these headings - interactive
     controls keep their focus styles. */
  #infoModalTitle:focus,
  #versionModalTitle:focus,
  .filter-modal-title:focus {
    outline: none;
  }

  /* Shared close-button glyph (see makeCloseIcon in camp-shared.js): exact
     fixed geometry instead of a font-dependent ×/✕ character, so every
     modal close matches. Lives here rather than item-view.css because both
     pages load this sheet. */
  .icon-svg {
    display: block;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
    flex-shrink: 0;
  }
  .icon-svg--close {
    transform: translateY(0px);
  }

  /* Accent button style */
    .accent-btn {
    background-color: var(--card-bg);      /* dark background */
    color: var(--accent);                   /* yellow text */
    border: 1px solid var(--border-subtle);       /* subtle border */
    padding: 6px 20px;
    border-radius: 6px;
    font-weight: bold;
    cursor: pointer;
    display: block;                         /* allow centering */
    margin: 6px auto;                      /* center horizontally */
    font-size: 14px;
    text-align: center;
    transition: background-color 0.2s, color 0.2s;
  }

  @media (hover: hover) {
    .accent-btn:hover {
      background-color: var(--accent);
      color: black;
    }
  }

  .modal-content h2 {
    color: var(--accent);
    font-size: 1.5em;
    margin-bottom: 10px;
  }

  #infoBody {
    color: var(--text);
    font-size: 1em;
    line-height: 1.5em;
  }

  #infoBody p.question {
    color: var(--accent);
    font-weight: bold;
    margin-top: 15px;
    margin-bottom: 5px;
  }

  #infoBody p.answer {
    color: var(--text);
    margin-left: 10px;
    margin-bottom: 10px;
    line-height: 1.5em;
  }


  #filtersButton,
  #sortSelected {
    height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    padding: 0 6px;
    font-size: 13px;
    line-height: 1;
    border: 1px solid var(--border-subtle);
    border-radius: 6px;
    background-color: var(--card-bg);
    color: var(--text);
    cursor: pointer;
    box-sizing: border-box;
    vertical-align: middle;
  }

  #filtersDropdown,
  #sortDropdown {
    display: inline-flex;
    position: relative;
    align-items: center;
    margin: 0;
    padding: 0;
  }


  #sortDropdown {
    position: relative;
    width: auto;
    white-space: nowrap;
    height: 36px;
    display: flex;
    flex-shrink: 0;
    overflow: visible;
  }

  #filtersButton {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    padding: 0 20px;
    font-size: 13px;
    border: 1px solid var(--border-subtle);
    border-radius: 6px 0 0 6px;
    background-color: var(--card-bg);
    color: var(--text);
    cursor: pointer;
    box-sizing: border-box;
    height: 36px;
    width: auto !important;
    flex-shrink: 0;
    transition: background-color 0.15s, color 0.15s;
    white-space: nowrap;
  }
  @media (hover: hover) {
    #filtersButton:hover {
      background-color: var(--accent);
      color: black;
    }
  }
  #filtersButton:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }
  #filtersButton.active {
    background-color: var(--accent);
    color: black;
  }
  #filtersButton .filter-icon {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
  }

  /* filtersOptions is now the modal body, no dropdown positioning */
  #filtersOptions {
    display: flex;
    flex-direction: row;
    flex: 1;
    overflow: hidden;
  }

  #filtersOptions button {
    padding: 5px 10px;
    border: 1px solid var(--border-subtle);
    border-radius: 4px;
    background: var(--card-bg);
    color: var(--text);
    font-size: 13px;
    cursor: pointer;
  }
  #filtersOptions button[data-filter] {
    display: block;
    width: 100%;
    text-align: left;
    padding: 4px 8px;
    background: var(--card-bg);
    border: none;
    color: var(--text);
    font-size: 13px;
    line-height: 1.4;
    cursor: pointer;
    border-radius: 3px;
  }
  @media (hover: hover) and (pointer: fine) {
    #filtersOptions button[data-filter]:hover {
      background-color: var(--accent);
      color: black;
    }
  }
  #filtersOptions button[data-filter].selected {
    background-color: var(--accent);
    color: black;
  }
  .filter-header {
    font-weight: 700;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--accent);
    padding: 4px 0 6px;
    margin: 0;
  }
  .clear-filters {
    margin-top: 8px;
    background-color: #ffeded;
    border: 1px solid #ff4d4f;
    color: #ff4d4f;
    border-radius: 4px;
    padding: 4px 8px;
    cursor: pointer;
    transition: background-color 0.15s, color 0.15s;
  }

  @media (hover: hover) {
    .clear-filters:hover {
      background-color: #ff4d4f;
      color: black;
    }
  }

  #sortSelected,
  #filtersButton,
  #sortDropdown {
    position: relative;
    width: 240px;
    white-space: nowrap; 
    height: 36px;
    display: flex;
    flex-shrink: 0;
  }

  #sortSelected {
    display: inline-flex;;
    align-items: center;
    gap: 4px;
    padding: 0 12px;
    font-size: 14px;
    max-width: none;
    width: 100%;
    border: 1px solid var(--border-subtle);
    border-radius: 6px;
    background-color: var(--card-bg);
    white-space: nowrap;
    color: var(--text);
    cursor: pointer;
    box-sizing: border-box;
    transition: background-color 0.15s, color 0.15s;
  }

  @media (hover: hover) {
    #sortSelected:hover {
      background-color: var(--accent);
      color: black;
    }
  }

  /* .open / #sortOptions .option rules removed here too - see the native
     <select> note near the end of this file. */

  .tooltip {
    position: fixed;
    background: var(--card-bg);
    color: #fff;
    padding: 6px 10px;
    border-radius: 4px;
    font-size: 13px;
    border: 1px solid var(--border-subtle);
    opacity: 0;
    pointer-events: none;
    transform: translateY(-4px);
    transition: opacity 0.15s ease, transform 0.15s ease;
    z-index: 9999;
    white-space: pre-line;
    line-height: 1.4;
    max-width: 340px;
  }

  .tooltip.show {
    opacity: 1;
    transform: translateY(0);
  }

  #mobile-tooltip-box {
    position: fixed;
    bottom: 20px;
    left: 50%;
    transform: translateX(-50%);
    max-width: 90%;
    background: var(--card-bg);
    color: white;
    padding: 12px 16px;
    border-radius: 6px;
    font-size: 14px;
    line-height: 1.4;
    z-index: 9999;
    text-align: center;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.25s ease;
    border: 1px solid var(--border-subtle);
    /* Multi-source tooltips (e.g. +N chips) join flavors with newlines.
       Without this they collapse into one continuous line - the desktop
       .tooltip already sets pre-line, this was just missing here. */
    white-space: pre-line;
  }

  #mobile-tooltip-box.show {
    bottom: 20px;
    opacity: 1;
  }

  /* Icons that carry a tooltip become tab stops when TOOLTIP_ICONS_FOCUSABLE is
     true in script.js; give them the same focus ring as the other controls. */
  [data-tip]:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 3px;
  }

  @media (prefers-reduced-motion: reduce) {
    .tooltip,
    #mobile-tooltip-box {
      transition: none;
    }
    .tooltip {
      transform: none;
    }
  }

  .grid-card {
    background: var(--card-bg);
    border: 1px solid var(--border-subtle);
    border-radius: 10px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 0.3s ease, transform 0.3s ease;
  }
  .grid-card.visible {
    opacity: 1;
    transform: translateY(0);
  }
  .grid-card-name {
    background: var(--card-bg);
    padding: 12px 14px;
    font-size: 15px;
    font-weight: 700;
    color: var(--accent);
    text-align: center;
    cursor: pointer;
    border-bottom: 1px solid var(--border-subtle);
    transition: color 0.15s;
    text-decoration: none;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
    word-break: break-word;
  }
  @media (hover: hover) {
    .grid-card-name:hover {
      color: #fff;
      background: #252525;
    }
  }
  .grid-card-image-wrap {
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    background: var(--card-bg);
    width: 100%;
    aspect-ratio: 1 / 1;
    overflow: hidden;
  }
  .grid-card-image-wrap img {
    width: 100%;
    height: 100%;
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    transition: opacity 0.3s ease;
  }
  .grid-card-info {
    padding: 12px 14px;
    flex: 1;
    display: flex;
    flex-direction: column;
  }
  .grid-card-section {
    margin-bottom: 10px;
  }
  .grid-card-section:last-child {
    margin-bottom: 0;
  }
  .grid-card-section .section-title {
    font-size: 14px;
    font-weight: 600;
    color: #888;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 5px;
  }
  .grid-card-section .section-value {
    font-size: 14px;
    color: #ccc;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px;
  }

  .return-to-top {
    position: fixed;
    bottom: 32px;
    right: 24px;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    border: 1px solid var(--border-subtle);
    background-color: var(--card-bg);
    color: var(--accent);
    cursor: pointer;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 0;
    transition: all 0.3s ease;
    z-index: 999;
  }

  @media (hover: hover) {
    .return-to-top:hover {
      background-color: var(--accent);
      color: black;
      transform: translateY(-4px);
    }
  }

  .return-to-top.show {
    display: flex;
  }

  .return-to-top svg {
    width: 24px;
    height: 24px;
  }

  @media (max-width: 600px) {
    .controls {
      flex-direction: column;
    }
  }

  @media (max-width: 600px) {
    #results {
      grid-template-columns: 1fr;
    }
  }

  @media (min-width: 601px) and (max-width: 800px) {
    #results {
      grid-template-columns: repeat(2, 1fr);
    }
  }

/* ============================================================
   Merged improvements (previously style-improvements.css)
   Appended in original load order so cascade/output is identical
   to the old two-file setup. These rules intentionally come
   after the base rules above to override/refine them.
   ============================================================ */

/* ============================================================
   style-improvements.css v3
   ============================================================ */

:root {
  --accent-secondary: #5f8fc4;
  --accent-secondary-dim: #3f5f82;
  --divider: rgba(229, 193, 88, 0.12);
}

body {
  overflow-y: visible;
}

#pagination {
  display: none;
}

/* ── Meta row ── */
.meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  margin: 6px 0 0;
  font-size: 13px;
}
.meta .author {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0;
  color: var(--text-muted);
}
.author-text {
  white-space: nowrap;
}
.author-text::after {
  content: '\2022';
  margin: 0 10px;
  color: var(--text-muted);
  opacity: 0.5;
  user-select: none;
}
/* Hidden only when JS detects the author line has actually wrapped
   (see checkAuthorWrap() in script.js) rather than at a fixed breakpoint.
   visibility (not display: none) deliberately keeps the dot's layout
   space reserved - if hiding it shrank .author-text's width, that width
   change could itself flip the wrap measurement back at the threshold
   width, toggling the dot back on, re-growing the width, and flipping
   again: a feedback loop. Reserving the space means toggling this class
   can never change the width checkAuthorWrap() measures. */
.author.wrapped .author-text::after {
  display: none; /* no leftover space, so "Made by MrsBlobby" centers properly.
    Safe against the old flip-flop because checkAuthorWrap() always measures
    with this class removed (see script.js). */
}
.author-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0;
}

.meta-sep {
  color: var(--text-muted);
  margin: 0 10px;
  opacity: 0.5;
  user-select: none;
}

.badge-link,
.meta-link {
  background: none;
  border: 1px solid transparent;
  border-radius: 4px;
  color: var(--accent);
  font-family: inherit;
  font-size: 13px;
  line-height: 16px;
  font-weight: normal;
  vertical-align: middle;
  box-sizing: border-box;
  margin: 0;
  cursor: pointer;
  padding: 2px 6px;
  text-decoration: none;
  transition: color 0.2s, border-color 0.2s, background-color 0.2s;
}
@media (hover: hover) {
  .badge-link:hover,
  .meta-link:hover {
    color: var(--accent);
    border-color: var(--border-subtle);
    background-color: rgba(229, 193, 88, 0.06);
  }
}

/* ── Toolbar height fix ── */
#filtersButton,
#sortSelected,
#sortDropdown {
  height: 40px;
}

#clearFiltersExternal {
  height: 40px;
  top: -4px;
}

.group-filters,
.group-sort {
  display: flex;
  align-items: center;
}

/* ── Pagination ── */
#paginationTop {
  gap: 2px;
  align-items: center;
}
#paginationTop button {
  border-color: var(--border-subtle);
}
#paginationTop span {
  color: var(--text-muted);
  font-size: 13px;
  min-width: 50px;
  text-align: center;
}
@media (hover: hover) {
  #paginationTop button:hover:not(:disabled) {
    border-color: var(--accent);
  }
}

/* Disabled pagination: single page / no results, layout stays stable */
.pagination-single {
  opacity: 0.4;
  pointer-events: none;
  user-select: none;
}
.pagination-single button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* ── Site header ── */
.site-header {
  position: relative;
  padding: 12px 0 0;
  background: var(--bg-elevated);
}
.site-header .cover-image-wrap {
  line-height: 0;
  font-size: 0;
}
.site-header .meta {
  line-height: 1.4;
}
.site-header::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: -20px;
  left: 50%;
  width: 100vw;
  margin-left: -50vw;
  background: var(--bg-elevated);
  z-index: -1;
}

/* ── Grid cards ── */
.grid-card {
  transition: border-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}
@media (hover: hover) {
  .grid-card:hover {
    transform: translateY(-2px);
  }
}
.grid-card-section .section-title {
  color: var(--text-muted);
}
.grid-card-section .section-value {
  color: var(--text);
}
.grid-card-name {
  border-bottom: 1px solid var(--divider);
}

/* ── Sticky toolbar ── */
.toolbar {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  row-gap: 10px;
  column-gap: 12px;
  background: var(--bg-elevated);
  border-bottom: 1px solid var(--border-subtle);
  padding: 12px 16px;
  margin: -1px 0 0;
}
.toolbar .search-line {
  flex: 1 1 380px;
  /* No max-width set here specifically - it's still capped at 450px via
     .controls .search-line further up this file (same specificity,
     earlier in the cascade), which is what keeps the search box from
     stretching edge-to-edge. With that cap in place and the toolbar
     centered below, leftover space splits evenly on both sides instead
     of collecting as one lopsided gap - checked this by actually
     rendering the page at 900px/1866px/2400px widths rather than just
     reasoning about the flexbox math. */
}
.toolbar .inline-group {
  flex: 0 0 auto;
  width: auto;
}
.toolbar #paginationTop {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  margin: 0;
}
.controls {
  display: block;
  padding: 8px 0 0;
  margin: 0;
  gap: 0;
  border: none;
  background: var(--bg-elevated);
}

@media (max-width: 600px) {
  .toolbar {
    flex-direction: column;
    margin: 0;
  }
  .toolbar .search-line,
  .toolbar .inline-group,
  .toolbar #paginationTop {
    flex: 0 0 auto;
    width: 100%;
    max-width: 100%;
    margin-left: 0;
    justify-content: center;
  }
}

/* ── Depth ── */
:root {
  --bg-elevated: #232323;
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 4px 14px rgba(0, 0, 0, 0.45);
}

.grid-card {
  border-color: var(--border-subtle);
  box-shadow: var(--shadow-sm);
}
@media (hover: hover) {
  .grid-card:hover {
    border-color: var(--accent);
    box-shadow: var(--shadow-md);
  }
}

#sortSelected {
  border-color: var(--border-subtle);
}
@media (hover: hover) {
  #sortSelected:hover {
    border-color: var(--accent);
  }
}

/* ── Changelog fade-in ── */
.changelog-entry {
  animation: changelogFadeIn 0.15s ease;
}
@keyframes changelogFadeIn {
  from { opacity: 0; transform: translateY(-2px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ── Pills ── */
:root {
  --bg-chip: #222222;
}
.pill {
  border: none;
  border-radius: 6px;
  background: var(--bg-chip);
  color: var(--accent);
}

/* Grey "+N" chip shown when a plan has more source types than the 2 icons
   a pill displays. Hovers/taps to list the remaining source flavor text. */
/* Boxed "+N" chip shown when a plan has more source types than the icons a
   pill displays. Stretches to the pill's full height so it reads as part of
   the pill, and stays on one line without squeezing the plan name. */
.pill-more-count {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  background: #333;
  border: 1px solid #444;
  border-radius: 4px;
  padding: 0 6px;
  font-size: 12px;
  font-weight: bold;
  margin-right: 4px;
  vertical-align: middle;
  cursor: default;
  white-space: nowrap;
  flex: 0 0 auto;
  align-self: stretch;
}

/* ── Placement condition pills: left-aligned list ──
   Overrides the old centered/stacked "wrap" treatment from style.css with a
   plain left-aligned list: each pill on its own line, with AND/OR shown as
   small inline text between them rather than big centered block text. */
.inline-wrap--conditions,
.inline-wrap--conditions.is-wrapped {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-start;
  width: auto;
  max-width: 100%;
}

.inline-wrap--conditions.is-wrapped > *:first-child {
  justify-self: unset;
}

.inline-wrap--conditions .connector,
.inline-wrap--conditions.is-wrapped .connector {
  margin: 0 0 0 2px;
  font-size: 12px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  text-align: left;
  color: var(--text-muted);
}

.inline-wrap--conditions .pill {
  justify-content: flex-start;
  text-align: left;
  align-items: center;
}

/* ── Empty results ── */
.no-results {
  grid-column: 1 / -1;
  list-style: none;
  text-align: center;
  padding: 40px 20px;
  color: var(--text-muted);
  font-size: 16px;
}

#results:has(.no-results) {
  min-height: 678px;
  display: flex;
  align-items: center;
  justify-content: center;
}

* {
  -webkit-tap-highlight-color: transparent;
}

/* ── Touch devices: remove lingering focus/active states on buttons ── */
@media (hover: none) {
  #filtersOptions button[data-filter]:focus,
  #filtersOptions button[data-filter]:active,
  .filter-modal-done:focus,
  .filter-modal-close:focus {
    outline: none;
    background-color: inherit;
    color: inherit;
  }
  #filtersOptions button[data-filter].selected:focus,
  #filtersOptions button[data-filter].selected:active {
    background-color: var(--accent);
    color: black;
  }
}

/* ── Search By / Sort By: native <select> elements.
   These replaced a hand-rolled div-based listbox so the browser/OS
   handles keyboard nav, screen readers, and mobile pickers natively -
   Switch Control, Voice Control, VoiceOver/TalkBack rotor, high-contrast
   ("forced-colors") mode, and so on all work automatically here, which a
   custom listbox can only approximate.

   All box styling (colors, border, sizing, hover background, flex
   alignment) is inherited unchanged from the existing #dropdownSelected /
   #sortSelected rules earlier in this file - those already work
   correctly and are left alone. Only the native browser chrome is
   stripped here, plus a small themed arrow added via the wrapper so it
   never competes with the select's own text layout:
     - appearance: none removes the OS-drawn control chrome (border,
       arrow, background) so our existing box styling shows through
       cleanly instead of fighting the native widget.
     - color-scheme: dark hints to the browser to render the parts it
       still controls natively - most importantly the OPEN option list -
       in a dark palette instead of the default stark white. That native
       list still can't be fully themed (no gold hover rows), but at
       least it won't look like a jarring white popup on a dark site.
     - the arrow itself is a small ::after chevron on the wrapper
       (.custom-dropdown), not inside the select, so its position never
       depends on - or steals space from - the select's own text.

   select#id (tag+ID) has higher specificity than the plain #id rules
   above, so this reliably wins regardless of source order. ── */
select#dropdownSelected,
select#sortSelected {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  color-scheme: dark;
  background-image: none;
  font-family: inherit; /* <select> doesn't reliably inherit the page
    font (Arial) in every browser - without this it can silently render
    with a wider OS default UI font, which was eating into the pixel
    budget below and causing text to run long even when the box math
    looked correct on paper. */
  font-size: 14px;
  line-height: 1.4; /* line-height:1 (inherited from the neighboring
    #filtersButton rule) is fine for a plain button but too tight for how
    some browsers render text inside a native <select>, clipping the
    bottom of descenders. */
  padding-right: 22px; /* room for the wrapper arrow drawn below; both
    dropdowns are now auto-width (see #sortDropdown further down), so
    this just adds to their natural content width instead of eating into
    a fixed budget */
}

select#sortSelected {
  height: 40px; /* Sort By's wrapper (#sortDropdown) was set to 36px
    elsewhere in this file, 4px shorter than Search By's 40px wrapper -
    that's the other reason only Sort By's text looked clipped. Matching
    heights here so both dropdowns render identically. */
}


select#sortSelected:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* Search By lives inside .search-line, which already shows the gold border +
   glow via :focus-within. Its own square, offset outline was drawn on top of
   that glow and (on touch devices, where a tapped <select> keeps
   :focus-visible) looked like a second, misaligned glow. */
select#dropdownSelected:focus-visible {
  outline: none;
}

.custom-dropdown::after {
  content: '';
  position: absolute;
  right: 10px;
  top: 50%;
  width: 6px;
  height: 6px;
  border-right: 2px solid var(--text);
  border-bottom: 2px solid var(--text);
  transform: translateY(-65%) rotate(45deg);
  pointer-events: none; /* clicks pass through to the <select> beneath */
  transition: border-color 0.15s ease;
}

@media (hover: hover) {
  .custom-dropdown:hover::after {
    border-color: black;
  }
}

/* Sort By was a fixed-width box (240/250px), which meant every pixel
   budget for its right-side arrow had to be manually reserved from an
   already-tight text allowance - and it kept coming up short across
   several attempts (font metrics inside <select> aren't perfectly
   predictable across browsers). Simplest permanent fix: stop fixing the
   width at all and let it size to its own content, exactly like Search
   By's wrapper (.custom-dropdown, width: max-content) already does with
   zero width complaints. */
#sortDropdown {
  width: max-content;
  height: 40px;
}
select#sortSelected {
  width: auto;
  max-width: none;
}

/* ── Reduced motion (grid page) ──────────────────────────────────────────
   Script-driven motion (card stagger, smooth scroll) is handled in
   script.js via prefersReducedMotion(). Here, durations are shrunk to ~0
   instead of using `none` so the end state still lands immediately and any
   animationend/transitionend listener still fires. !important is needed to
   beat the `.closing` variants' animation shorthands. The tooltip block
   earlier in this file already covers tooltips. */
@media (prefers-reduced-motion: reduce) {
  .grid-card {
    transform: none; /* drop the 8px rise-in; .visible only fades now */
  }
  .grid-card,
  .modal-content,
  .filter-modal-overlay,
  .filter-modal,
  .changelog-entry {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
