/* ══════════════════════════════════════════════════════════════════
   CODEX FILTER RAIL (redesign step 4, pass 1)
   See design_handoff_codex_redesign/README.md §Component Vocabulary 3.

   Layout: 280px left rail + flexible content column. The rail wraps the
   legacy .filters block; the right column wraps cardCountInfo, batch
   toolbar, and the cards grid. When other views hide .filters via
   style.display='none', the flex layout collapses to a single column.
   ══════════════════════════════════════════════════════════════════ */

.codex-cards-layout {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  /* Subtract container side padding so the rail can sit edge-aligned. */
  min-width: 0;
}

.codex-cards-main {
  flex: 1 1 auto;
  min-width: 0;
}

/* ── Rail container ───────────────────────────────────────────────── */
/* The legacy .filters class is preserved on the element so any existing
   selector + the view-switch JS (which sets .filters.style.display)
   still works unchanged. Codex chrome layers on top of it.

   The rail itself is the scroll container. Header + footer use position:
   sticky to stay pinned while the middle filter content scrolls. This
   sidesteps the flex-item-can't-shrink problem that was clipping the
   advanced filters with no scrollbar. */
.codex-rail.filters {
  width: 280px;
  flex: 0 0 280px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0;
  margin: 0;
  max-height: calc(100vh - 20px);
  position: sticky;
  top: 12px;
  overflow-y: auto;
  overflow-x: hidden;
  display: block;
  /* Override legacy .filters bg/box-shadow */
  background-image: none;
  box-shadow: none;
}

/* Collapsed state — rail shrinks to a 36px strip. */
.codex-rail--collapsed.filters {
  width: 36px;
  flex: 0 0 36px;
}
/* Hide everything in the header EXCEPT the collapse button. The button
   lives inside .codex-rail-actions (one level deep), so a direct-child
   `:not(.codex-rail-collapse)` would hide the actions container and
   take the button with it. Be explicit about what to hide instead. */
.codex-rail--collapsed .codex-rail-title,
.codex-rail--collapsed .codex-rail-reset,
.codex-rail--collapsed .codex-rail-filtersearch {
  display: none;
}
.codex-rail--collapsed .codex-rail-header {
  padding: 10px 6px;
  justify-content: center;
}
/* When collapsed, the rail's only visible child is the ~35px header, so
   the strip would otherwise shrink to that height — leaving an empty
   column to the left of the cards as you scroll. Anchor the strip to
   the viewport height so it stays grounded next to the grid. */
.codex-rail.codex-rail--collapsed {
  min-height: 100vh;
}
/* Hide everything below the header when the rail is collapsed.
   !important + .codex-rail prefix because .codex-rail .advanced-filters
   itself uses display:block!important to defeat the inline display:none
   on the markup; we need to beat that on collapse. */
.codex-rail.codex-rail--collapsed .codex-rail-sections,
.codex-rail.codex-rail--collapsed .filter-search-row,
.codex-rail.codex-rail--collapsed .quick-filters-row,
.codex-rail.codex-rail--collapsed .advanced-filters,
.codex-rail.codex-rail--collapsed .codex-rail-footer,
.codex-rail.codex-rail--collapsed #breadcrumbs {
  display: none !important;
}
.codex-rail--collapsed .codex-rail-collapse::before {
  /* Flip arrow for the expand action when collapsed */
  content: '▸';
}
/* NB: don't override the button's font-size:0 here. The button's text
   node ("◂") is hidden via font-size:0; the ::before chevron has its
   own explicit font-size below. If we bump font-size on the button in
   collapsed state, we re-enable the text-node and get a double chevron. */
.codex-rail-collapse::before {
  content: '◂';
  font-size: 14px; /* explicit — parent button is font-size:0 so ::before
                      would otherwise inherit 0 and render invisibly. */
  line-height: 1;
}
.codex-rail-collapse {
  font-size: 0; /* hide actual text, show pseudo */
}

/* ── Rail header (Refine · count · Reset · collapse) ──────────────── */
/* Sticky at the top of the scrolling rail. */
.codex-rail-header {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 12px;
  margin-bottom: 0;
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 3;
  background: var(--surface);
}
.codex-rail-header-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
}

/* Quick-find for the filters themselves — full-width input under the header. */
.codex-rail-filtersearch {
  width: 100%;
  box-sizing: border-box;
  font-family: var(--font-sans);
  font-size: 12px;
  color: var(--text);
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 10px;
  outline: none;
  transition: border-color 0.12s ease, background 0.12s ease;
}
.codex-rail-filtersearch::placeholder { color: var(--text-dim); }
.codex-rail-filtersearch:focus {
  border-color: var(--accent);
  background: var(--surface);
}

/* Hidden by the filter quick-find when a unit's label doesn't match. */
.codex-rail .filter-search-hide { display: none !important; }

.codex-rail-title {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}

.codex-rail-eyebrow {
  font-family: var(--font-sans);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.codex-rail-count {
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--text-mute);
  letter-spacing: -0.01em;
}

.codex-rail-actions {
  display: flex;
  align-items: center;
  gap: 6px;
}

/* Clear-all is a primary rail action — render it as a tinted accent pill,
   not a plain text link, so it reads as the important button it is. */
.codex-rail-reset {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  color: var(--accent);
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  padding: 4px 11px;
  border-radius: 999px;
  white-space: nowrap;
  /* Avoid wrapping or pushing the header layout. */
  max-width: 140px;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.codex-rail-reset:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.codex-rail-collapse {
  background: transparent;
  border: 0;
  color: var(--text-dim);
  cursor: pointer;
  padding: 0 4px;
  border-radius: 3px;
  font-family: var(--font-sans);
}
.codex-rail-collapse:hover {
  color: var(--text);
  background: var(--surface2);
}

/* ── Rail scrollable area ─────────────────────────────────────────── */
/* The legacy .filter-search-row, .quick-filters-row, and .advanced-filters
   live inside .filters / .codex-rail and become the rail's body. */
.codex-rail.filters > .filter-search-row,
.codex-rail.filters > .quick-filters-row,
.codex-rail.filters > .advanced-filters,
.codex-rail.filters > #breadcrumbs {
  margin: 0;
  flex-shrink: 0;
}

.codex-rail.filters > .filter-search-row,
.codex-rail.filters > .quick-filters-row,
.codex-rail.filters > .advanced-filters {
  overflow-y: auto;
}

/* Sticky search row just below the (also-sticky) header so the search
   stays visible while the user scrolls through filter sections. */
.codex-rail.filters {
  scrollbar-gutter: stable;
}

/* ── Slim Codex scrollbar ─────────────────────────────────────────── */
/* Firefox / standards. */
.codex-rail.filters {
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.12) transparent;
}
:root[data-theme='light'] .codex-rail.filters,
.theme-light .codex-rail.filters {
  scrollbar-color: rgba(15, 23, 42, 0.16) transparent;
}

/* WebKit (Chrome, Safari). */
.codex-rail.filters::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
.codex-rail.filters::-webkit-scrollbar-track {
  background: transparent;
}
.codex-rail.filters::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.08);
  border-radius: 3px;
  transition: background-color 0.15s ease;
}
.codex-rail.filters::-webkit-scrollbar-thumb:hover {
  background: rgba(255, 255, 255, 0.18);
}
:root[data-theme='light'] .codex-rail.filters::-webkit-scrollbar-thumb,
.theme-light .codex-rail.filters::-webkit-scrollbar-thumb {
  background: rgba(15, 23, 42, 0.12);
}
:root[data-theme='light'] .codex-rail.filters::-webkit-scrollbar-thumb:hover,
.theme-light .codex-rail.filters::-webkit-scrollbar-thumb:hover {
  background: rgba(15, 23, 42, 0.24);
}
/* (The search row + clear button used to live in the rail; they moved
   into #cardCountInfo in Codex step 5 — see styles/codex-countbar.css.) */

/* ── Quick filters row → vertical stack of sections in the rail ───── */
/* Override the legacy .quick-filters-row { align-items: flex-end;
   flex-wrap: wrap } so children stretch full-width left-aligned, not
   collapsed to content-width right-aligned. */
.codex-rail .quick-filters-row {
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap;
  align-items: stretch;
  justify-content: flex-start;
  gap: 0;
  padding: 0;
}

/* Each .filter-section becomes a Codex accordion block. */
.codex-rail .filter-section {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  margin: 0;
  background: transparent;
}

/* Clickable section label (data-action="toggleFilterSection"). Doubles
   as the accordion toggle — chevron rotates when collapsed. */
.codex-rail .filter-section-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  font-family: var(--font-sans);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin: 0;
  padding: 2px 0;
  cursor: pointer;
  user-select: none;
}
.codex-rail .filter-section-label:hover {
  color: var(--text);
}

/* Optional count badge inside the section/group label. */
.codex-rail .filter-section-label .codex-section-count,
.codex-rail .filter-group > label .codex-section-count {
  flex: 0 0 auto;
  margin-left: auto;
  margin-right: 6px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-mute);
  font-weight: 500;
}

/* Active-filter badge — only inserted by JS when count > 0. Sits
   between the section label text and the optional total-count badge.
   Accent-coloured so the user can spot collapsed sections that hold
   active filters at a glance. */
.codex-rail .codex-section-active-count {
  flex: 0 0 auto;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--accent);
  color: var(--surface);
  border-radius: 8px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0;
  text-transform: none;
  font-weight: 600;
  line-height: 1;
}
/* When both badges are present, the active one bumps the total one to
   the right margin (drop the total's auto). */
.codex-rail .filter-section-label:has(.codex-section-active-count) .codex-section-count,
.codex-rail .filter-group > label:has(.codex-section-active-count) .codex-section-count {
  margin-left: 6px;
}

/* Chevron — appended via ::after on every collapsible label. Rotates
   when the parent section is collapsed.
   Note: base.css sets ::before/::after on .filter-section-header to be
   flex:1 horizontal dividers with a gradient background. We override
   here, but must also explicitly reset flex (else the chevron stretches)
   and background (else the gradient rotates into a diagonal bar). */
.codex-rail .filter-section-label::after,
.codex-rail .filter-group > label::after,
.codex-rail .filter-section-header::after {
  content: '';
  display: inline-block;
  flex: 0 0 auto;
  background: none;
  width: 8px;
  height: 8px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
  margin-left: 4px;
  margin-top: -3px;
  opacity: 0.6;
  transition: transform 0.2s ease, opacity 0.15s ease;
}
/* Same trick for the leading ::before that base.css adds on group
   headers — codex layout doesn't want it. */
.codex-rail .filter-section-header::before {
  display: none;
}

/* dark-mode.css scopes a `body.dark-mode .filter-section-header::after`
   rule that re-applies the gradient background. Bump specificity to
   override it inside the codex rail. */
body.dark-mode .codex-rail .filter-section-header::after,
body.dark-mode .codex-rail .filter-section-header::before {
  background: none;
}
.codex-rail .filter-section-label:hover::after,
.codex-rail .filter-group > label:hover::after,
.codex-rail .filter-section-header:hover::after {
  opacity: 1;
}

/* Collapsed: chevron flips to point right (collapsed state). Section
   body hides — everything inside .filter-section that isn't the label,
   and the .filter-row that immediately follows a collapsed group
   header. */
.codex-rail .filter-section.codex-section--collapsed > *:not(.filter-section-label),
.codex-rail .filter-group.codex-section--collapsed > *:not(label),
.codex-rail .filter-section-header.codex-section--collapsed + .filter-row {
  display: none !important;
}
.codex-rail .filter-section.codex-section--collapsed .filter-section-label::after,
.codex-rail .filter-group.codex-section--collapsed > label::after,
.codex-rail .filter-section-header.codex-section--collapsed::after {
  transform: rotate(-45deg);
  margin-top: 0;
}

/* Hide vertical dividers between sections in the rail (we use borders). */
.codex-rail .divider-vertical {
  display: none;
}

/* Hide the "more filters" toggle inside the rail (advanced filters are
   always open below for pass 1). */
.codex-rail .btn-toggle-advanced {
  display: none;
}

/* ── Status: ownership-btn stack ──────────────────────────────────── */
/* The legacy six ownership buttons rendered horizontally; rebuild as a
   vertical stack of Codex tri-state-styled rows. The underlying button
   state (active/exclude) is still driven by JS via the same classes. */
.codex-rail .ownership-filters {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.codex-rail .ownership-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  height: 28px;
  /* No horizontal padding — let the icon column line up with the section
     label "STATUT", and reach the rail's left edge for full-width hover. */
  padding: 0;
  background: transparent;
  border: 0;
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 12.5px;
  font-weight: 500;
  border-radius: 5px;
  cursor: pointer;
  text-align: left;
  /* Wipe out legacy gradients/borders */
  background-image: none;
  box-shadow: none;
}
.codex-rail .ownership-btn:hover {
  background: var(--surface2);
}
.codex-rail .ownership-btn.active {
  background: var(--accent-dim);
  color: var(--accent);
}
.codex-rail .ownership-btn .ownership-icon {
  width: 14px;
  text-align: center;
  font-size: 11px;
  color: var(--text-dim);
  flex-shrink: 0;
}
.codex-rail .ownership-btn.active .ownership-icon {
  color: var(--accent);
}
.codex-rail .ownership-btn .ownership-label {
  flex: 1;
  margin: 0;
}

/* ── Extras: 3-state segmented (Hide / Show / Only) ───────────────── */
.codex-rail .extras-toggle {
  display: flex;
  gap: 1px;
  padding: 2px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.codex-rail .extras-toggle-btn {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 26px;
  padding: 0 6px;
  background: transparent;
  border: 0;
  color: var(--text-dim);
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: background-color 0.15s ease, color 0.15s ease;
  background-image: none;
}
.codex-rail .extras-toggle-btn:hover {
  background: var(--surface3);
  color: var(--text);
}
.codex-rail .extras-toggle-btn.active {
  background: var(--surface3);
  color: var(--accent);
}
.codex-rail .extras-toggle-btn .extras-icon {
  width: 16px;
  height: 16px;
}

/* ── Language flags grid ──────────────────────────────────────────── */
.codex-rail .language-filters {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 4px;
}
.codex-rail .lang-filter-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 26px;
  padding: 0;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 5px;
  cursor: pointer;
  opacity: 0.6;
  transition: opacity 0.15s ease, border-color 0.15s ease, background-color 0.15s ease;
}
.codex-rail .lang-filter-btn:hover {
  opacity: 0.9;
  background: var(--surface3);
}
.codex-rail .lang-filter-btn[data-state='include'] {
  opacity: 1;
  background: var(--accent-dim);
  border-color: var(--accent);
}
.codex-rail .lang-filter-btn[data-state='exclude'] {
  opacity: 1;
  background: var(--neg-dim);
  border-color: var(--neg);
}
.codex-rail .lang-filter-btn .flag-icon {
  width: 18px;
  height: 13px;
  border-radius: 2px;
}
.codex-rail .lang-filter-btn .lang-filter-label {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Exclusive switch — last item in the language-filters grid, spans full row. */
.codex-rail .lang-exclusive-btn {
  grid-column: 1 / -1;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 26px;
  padding: 0 10px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 5px;
  cursor: pointer;
  color: var(--text-dim);
  font-family: var(--font-sans);
  font-size: 11.5px;
  font-weight: 500;
  margin-top: 2px;
}
.codex-rail .lang-exclusive-btn:hover {
  color: var(--text);
  background: var(--surface3);
}
.codex-rail .lang-exclusive-btn[data-state='on'] {
  background: var(--accent-dim);
  border-color: var(--accent);
  color: var(--accent);
}
.codex-rail .lang-exclusive-btn .exclusive-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--text-dim);
}
.codex-rail .lang-exclusive-btn[data-state='on'] .exclusive-dot {
  background: var(--accent);
}

/* ── Advanced-filters block in the rail ───────────────────────────── */
/* The legacy "Plus de filtres" toggle is hidden in the rail; show
   advanced filters always-expanded. Restyle each .filter-section-header
   and .filter-row as Codex sections. */
.codex-rail .advanced-filters {
  display: block !important;
  background: transparent;
  border: 0;
  padding: 0;
  margin: 0;
}

/* Codex group divider: a quiet top-level section header sitting on a
   stronger rule, with a small accent square marker that doubles as a
   "collapsible group" cue without overwhelming the sub-section labels
   inside it. */
.codex-rail .filter-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-family: var(--font-sans);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-mute);
  padding: 12px 14px 6px;
  background: transparent;
  border-top: 1px solid var(--border-hi);
  margin: 0;
  cursor: pointer;
  user-select: none;
}
.codex-rail .filter-section-header:hover {
  color: var(--text);
}
.codex-rail .filter-section-header > span:not(.codex-group-marker):not(.codex-section-active-count):not(.codex-section-help) {
  /* The legacy markup has the label text inside a <span> child. */
  flex: 1;
  position: relative;
  padding-left: 12px;
}
.codex-rail .filter-section-header > span:not(.codex-group-marker):not(.codex-section-active-count):not(.codex-section-help)::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  width: 6px;
  height: 6px;
  margin-top: -3px;
  background: var(--accent);
  border-radius: 1px;
}
.codex-rail .filter-section-header:hover > span:not(.codex-group-marker):not(.codex-section-active-count):not(.codex-section-help)::before {
  background: var(--accent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 25%, transparent);
}

.codex-rail .filter-row {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 6px 14px 12px;
}
/* The .filter-row rule above unintentionally overrides base.css's
   `.dev-filters { display: none }` (higher specificity). Re-hide the
   dev filter row + its accordion header inside the rail unless
   `body.show-dev-data` is set (toggled by initDevToggle /
   toggleDevMode in src/app.js). */
.codex-rail .filter-row.dev-filters,
.codex-rail .filter-section-header.dev-filters-header {
  display: none;
}
body.show-dev-data .codex-rail .filter-row.dev-filters {
  display: flex;
}
body.show-dev-data .codex-rail .filter-section-header.dev-filters-header {
  display: block;
}
/* When dev mode is on AND the section is collapsed, the accordion rule
   `.filter-section-header.codex-section--collapsed + .filter-row` already
   hides the row with !important — keep that priority. */
body.show-dev-data .codex-rail .filter-section-header.dev-filters-header.codex-section--collapsed + .filter-row.dev-filters {
  display: none !important;
}

.codex-rail .filter-group {
  display: flex;
  flex-direction: column;
  gap: 4px;
  position: relative;
}
.codex-rail .filter-group > label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  font-family: var(--font-sans);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin: 0;
  padding: 2px 0;
  cursor: pointer;
  user-select: none;
}
.codex-rail .filter-group > label:hover {
  color: var(--text);
}
.codex-rail .filter-group select {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 5px;
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 12px;
  padding: 6px 28px 6px 8px;
  height: 30px;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a929e' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
  background-repeat: no-repeat;
  background-position: right 8px center;
  background-size: 14px 14px;
}
.codex-rail .filter-group select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--focus-ring);
}
.codex-rail .filter-group .filter-exclude-toggle {
  position: absolute;
  right: 4px;
  top: auto;
  /* Bottom-anchor instead of fixed top:22 so the toggle stays
     vertically centred on the 30px select regardless of label
     height. (30 - 22) / 2 = 4px from the bottom = vertically
     centred on the select row. */
  bottom: 4px;
  width: 22px;
  height: 22px;
  background: transparent;
  border: 0;
  color: var(--text-mute);
  font-size: 12px;
  cursor: pointer;
  border-radius: var(--radius-sm);
}
/* Pokémon / illustrator: the exclude toggle now lives inside the
   wrapper (next to the input), so positioning is relative to the
   input row only — easy vertical centering. */
.codex-rail .pokemon-filter-wrapper,
.codex-rail .illustrator-filter-wrapper {
  position: relative;
}
.codex-rail .pokemon-filter-search,
.codex-rail .illustrator-filter-search {
  padding-right: 30px;
}
.codex-rail .filter-group .filter-exclude-toggle--pokemon,
.codex-rail .filter-group .filter-exclude-toggle--illustrator {
  position: absolute;
  right: 4px;
  top: 4px;
  bottom: auto;
  width: 22px;
  height: 22px;
}
.codex-rail .filter-group .filter-exclude-toggle.active {
  color: var(--neg);
  background: var(--neg-dim);
}
.codex-rail .filter-group .filter-exclude-toggle:hover {
  color: var(--text);
  background: var(--surface2);
}

/* Pokémon / illustrator search wrappers — stack input over select. */
.codex-rail .pokemon-filter-wrapper,
.codex-rail .illustrator-filter-wrapper {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.codex-rail .pokemon-filter-search,
.codex-rail .illustrator-filter-search {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 5px;
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 11.5px;
  padding: 5px 8px;
}
.codex-rail .pokemon-filter-search:focus,
.codex-rail .illustrator-filter-search:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--focus-ring);
}

/* Typeahead result panel — replaces the closed <select> with an
   inline list that updates as the user types. See
   wireTypeaheadFilter() in src/filters.js. */
.codex-rail .codex-typeahead-results {
  display: flex;
  flex-direction: column;
  max-height: 200px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 5px;
  margin-top: 2px;
}
.codex-rail .codex-typeahead-results[hidden] {
  display: none;
}
.codex-rail .codex-typeahead-item {
  display: block;
  text-align: left;
  padding: 5px 8px;
  background: transparent;
  border: 0;
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 11.5px;
  cursor: pointer;
  transition: background-color 0.1s ease;
}
.codex-rail .codex-typeahead-item:hover,
.codex-rail .codex-typeahead-item:focus-visible {
  background: var(--surface2);
  outline: none;
}
.codex-rail .codex-typeahead-empty {
  padding: 6px 8px;
  font-family: var(--font-sans);
  font-size: 11.5px;
  color: var(--text-mute);
  font-style: italic;
}
.codex-rail .codex-typeahead-count {
  color: var(--text-mute);
  font-family: var(--font-mono);
  font-size: 0.9em;
  margin-left: 4px;
}

/* ══════════════════════════════════════════════════════════════════
   CODEX TRI-STATE CHECKLIST (step 4 pass 2b)
   Replaces the legacy <select> + ✕ exclude toggle for filters that
   support per-value include/exclude. The button's data-state attribute
   (off / include / exclude) drives the visual.
   ══════════════════════════════════════════════════════════════════ */

.codex-rail .filter-group.filter-group--checklist {
  gap: 6px;
}

.codex-rail .codex-checklist {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin: 0;
}

.codex-rail .codex-check {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 4px 4px;
  background: transparent;
  border: 0;
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 12px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-align: left;
  background-image: none;
  box-shadow: none;
  transition: background-color 0.15s ease;
}
.codex-rail .codex-check:hover {
  background: var(--surface2);
}

/* Tri-state box: empty (off) / ✓ (include) / ✕ (exclude). */
.codex-rail .codex-check-box {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  background: transparent;
  border: 1px solid var(--border-hi);
  border-radius: 3px;
  font-size: 9px;
  font-weight: 700;
  line-height: 1;
  color: transparent;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.codex-rail .codex-check[data-state='include'] .codex-check-box {
  background: var(--accent-dim);
  border-color: var(--accent);
  color: var(--accent);
}
.codex-rail .codex-check[data-state='include'] .codex-check-box::after {
  content: '✓';
}

.codex-rail .codex-check[data-state='exclude'] .codex-check-box {
  background: var(--neg-dim);
  border-color: var(--neg);
  color: var(--neg);
}
.codex-rail .codex-check[data-state='exclude'] .codex-check-box::after {
  content: '✕';
}

.codex-rail .codex-check[data-state='exclude'] .codex-check-label {
  color: var(--text-dim);
  text-decoration: line-through;
}

.codex-rail .codex-check[data-state='include'] {
  color: var(--text);
}

/* Type / super-type icon prefix inside check labels (Pokemon types,
   POK/TRA/ENE). Keep the icon tight against the label text. */
.codex-rail .codex-check-label {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.codex-rail .codex-check-label .type-icon {
  width: 12px;
  height: 12px;
  object-fit: contain;
  flex-shrink: 0;
}
/* Match-count suffix shown next to each checklist label, e.g. "(18)".
   Dim and lightly mono so the count reads as metadata, not part of the
   label text. */
.codex-rail .codex-check-count {
  color: var(--text-mute);
  font-family: var(--font-mono);
  font-size: 0.9em;
}
.codex-rail .codex-check[data-state='exclude'] .codex-check-count {
  text-decoration: none;
}

/* Per-section help icon injected next to each filter section label
   (see injectSectionHelpIcons in src/filters.js). The standard tooltip
   plumbing (data-i18n-tooltip → tooltip.js) handles the popover; the
   icon itself just needs to look like a passive metadata glyph. */
.codex-rail .codex-section-help {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: 0;
  width: 14px;
  height: 14px;
  font-size: 11px;
  color: var(--text-mute);
  cursor: help;
  opacity: 0.7;
  transition: color 0.15s ease, opacity 0.15s ease;
}
.codex-rail .codex-section-help:hover {
  color: var(--accent);
  opacity: 1;
}

/* ── Year sparkline (tri-state histogram) ──────────────────────────── */
.codex-rail .codex-year-sparkline {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 4px 4px 0;
}

.codex-rail .codex-year-range {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 4px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text);
}
.codex-rail .codex-year-range .codex-year-sep {
  color: var(--text-mute);
  padding: 0 2px;
}
.codex-rail .codex-year-min,
.codex-rail .codex-year-max {
  width: 50px;
  padding: 2px 4px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 11px;
  text-align: center;
  /* Hide the up/down spinner buttons on number inputs. */
  -moz-appearance: textfield;
}
.codex-rail .codex-year-min::-webkit-inner-spin-button,
.codex-rail .codex-year-min::-webkit-outer-spin-button,
.codex-rail .codex-year-max::-webkit-inner-spin-button,
.codex-rail .codex-year-max::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.codex-rail .codex-year-min:focus,
.codex-rail .codex-year-max:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--focus-ring);
}

.codex-rail .codex-year-bars {
  display: flex;
  align-items: end;
  gap: 2px;
  height: 36px;
}

.codex-rail .codex-year-bar {
  flex: 1;
  min-width: 0;
  padding: 0;
  border: 0;
  background: var(--accent);
  opacity: 0.45;
  height: var(--bar-h, 8%);
  min-height: 3px;
  border-radius: 2px 2px 0 0;
  cursor: pointer;
  background-image: none;
  box-shadow: none;
  transition: opacity 0.15s ease, background-color 0.15s ease, transform 0.15s ease;
}

.codex-rail .codex-year-bar:hover {
  opacity: 0.85;
  transform: translateY(-1px);
}

.codex-rail .codex-year-bar[data-state='include'] {
  background: var(--accent);
  opacity: 1;
}

.codex-rail .codex-year-bar[data-state='exclude'] {
  background: var(--neg);
  opacity: 0.85;
}

/* Live hover-range while click-dragging across bars. */
.codex-rail .codex-year-bar.hover-range {
  opacity: 0.9;
  background: var(--accent);
}
.codex-rail .codex-year-bars {
  cursor: ew-resize;
  user-select: none;
}

/* ── Purchase price range (min/max + visual fill bar) ──────────────── */
.codex-rail .codex-price-range {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 4px 4px 0;
}
.codex-rail .codex-price-range-inputs {
  display: flex;
  gap: 6px;
}
.codex-rail .codex-price-input {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px 6px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 5px;
  font-family: var(--font-mono);
  font-size: 11px;
  overflow: hidden;
}
.codex-rail .codex-price-input:focus-within {
  border-color: var(--accent);
}
.codex-rail .codex-price-input-label {
  color: var(--text-mute);
}
.codex-rail .codex-price-input-unit {
  color: var(--text-mute);
  font-size: 10px;
}
.codex-rail .codex-price-input input {
  flex: 1 1 0;
  min-width: 0;
  width: 100%;
  background: transparent;
  border: 0;
  padding: 0;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text);
  outline: none;
  -moz-appearance: textfield;
}
.codex-rail .codex-price-input input::-webkit-outer-spin-button,
.codex-rail .codex-price-input input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.codex-rail .codex-price-range-bar {
  position: relative;
  height: 6px;
  border-radius: 3px;
  background: var(--surface2);
  overflow: hidden;
}
.codex-rail .codex-price-range-bar-track {
  position: absolute;
  inset: 0;
}
.codex-rail .codex-price-range-bar-active {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background: var(--accent-dim);
  transition: left 0.15s ease, right 0.15s ease, background-color 0.15s ease;
}
.codex-rail .codex-price-range-bar-active[data-active='true'] {
  background: var(--accent);
}

/* Active-filters breadcrumbs were relocated out of the rail and now
   sit above #cardsContainer in the cards column. See .cards-breadcrumbs
   in styles/codex-countbar.css. */
.codex-rail .persist-checkbox {
  font-family: var(--font-sans);
  font-size: 11px;
  color: var(--text-dim);
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.codex-rail .breadcrumb-label {
  font-family: var(--font-sans);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-mute);
}

/* ── Rail footer caption ──────────────────────────────────────────── */
/* Sticky at the bottom of the scrolling rail. */
.codex-rail-footer {
  padding: 8px 12px;
  border-top: 1px solid var(--border);
  font-family: var(--font-sans);
  font-size: 10.5px;
  color: var(--text-mute);
  text-align: center;
  background: var(--surface);
  position: sticky;
  bottom: 0;
  z-index: 3;
}

/* Reset the earlier flex-inner-area rules. The rail itself scrolls now. */
.codex-rail.filters > .filter-search-row,
.codex-rail.filters > .quick-filters-row,
.codex-rail.filters > .advanced-filters,
.codex-rail.filters > #breadcrumbs {
  overflow: visible;
  flex: none;
  min-height: 0;
}

/* ── Light-theme rail tweaks ──────────────────────────────────────── */
:root[data-theme='light'] .codex-rail.filters,
.theme-light .codex-rail.filters {
  background: var(--surface);
  border-color: var(--border);
}

/* Override dark-mode.css .filters hardcoded bg #252540 so the rail
   surfaces the Codex --surface token. */
body.dark-mode .codex-rail.filters {
  background: var(--surface);
}
body.dark-mode .codex-rail .quick-filters-row {
  background: transparent;
}
body.dark-mode .codex-rail .filter-section-label {
  color: var(--text-dim);
}
body.dark-mode .codex-rail .ownership-btn {
  background: transparent;
  border-color: transparent;
  color: var(--text);
}
body.dark-mode .codex-rail .ownership-btn:hover {
  background: var(--surface2);
}
body.dark-mode .codex-rail .ownership-btn.active {
  background: var(--accent-dim);
  color: var(--accent);
}

/* ── Responsive: collapse rail to 36px below tablet ───────────────── */
@media (max-width: 980px) {
  .codex-rail.filters {
    width: 100%;
    flex: 1 1 auto;
    position: static;
    max-height: none;
    margin-bottom: 12px;
  }
  .codex-cards-layout {
    flex-direction: column;
  }
}
