/* ============================================================
   BROWSE SIDEBAR — left-side filter panel, desktop only
   Toggled by Browse button in tool strip (Row 2)
   Pushes grid content right when open
   ============================================================ */

:root {
  --sidebar-w: clamp(200px, 20vw, 260px);

  /* ── The 状 group's four inks, one per LOCKED state (docs/STATUS_TAXONOMY.md).
     Repointed 2026-08-16, the day the group shipped. They stood here since the
     panel was built as --status-new-sidebar / --status-learning-sidebar /
     --status-mastered-sidebar: THREE variables, read by nothing, named for a
     sidebar status filter that never got built — and the third still said
     "mastered", a word the status vocabulary retired on 2026-07-12 (an engine
     term, never a display one). The axis has four states and now has a group
     that draws them, so the names say the states and the dots read them.
     ⛔ The hues are the app's own state inks verbatim — the same ones the grid
     placard's statusline uses — so a filter row and the card it selects read
     as one system. Change a hue HERE and both follow; never hardcode one at a
     dot rule again. ── */
  --sb-state-new: var(--color-faint, #B8B0A4);
  --sb-state-learning: var(--color-amber, #A07850);
  --sb-state-coming: var(--color-moss-bright, #5B8C5A);
  --sb-state-resting: var(--color-moss, #6B7F5C);
}

/* ============================================================
   SIDEBAR CONTAINER
   Edge-flush panel below nav bar, flush to left viewport edge.
   Pushes grid content via margin on .grid-container.
   ============================================================ */
.browse-sidebar {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: var(--sidebar-w);
  /* Stone column (treatment A, owner-approved 2026-06-11): the panel is the
     room's own ground, one ink hairline on the inner edge. */
  background: var(--room-ground);
  border-right: 1px solid rgba(44, 44, 44, 0.10);
  display: flex;
  flex-direction: column;
  z-index: 90;
  transform: translateX(-100%);
  transition: transform 250ms cubic-bezier(0.16, 1, 0.3, 1);
}

.browse-sidebar.open {
  transform: translateX(0);
}

/* ============================================================
   THE HEAD — ONE DRESS FOR BOTH SIDE PANELS (desktop polish round 3,
   finding 7). The filter panel (left) and the settings rail (right) are
   twins: one width, ground, edge and slide, and one 57px title row with
   the same JP + EN lockup and the same close. The filter panel's head
   block carries two more lines under its title row (the tally, the find
   field) and the rule runs under all three, so its scroller starts below
   a rule and no row is ever cut under the tally; the rail's head is the
   title row alone, with the rule under it.
   ============================================================ */
:is(.browse-sidebar, .settings-sidebar) .sidebar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* 16 + the close's 34px seat + 6 + the 1px rule = 57px, the title's
     centre at 33px, exactly where the 22px close of rounds 1-2 sat */
  padding: 16px 10px 6px 16px;
  /* never the legacy 18px gap: css/sidebar-layout.css's unscoped
     .sidebar-header (a dead sidebar's rule) is scoped to its own surface
     now; this zero keeps both heads honest if anything like it returns */
  margin: 0;
  flex-shrink: 0;
  border-bottom: 1px solid rgba(44, 44, 44, 0.08);   /* ink hairline, not gold */
}
/* The panel's title row hands its rule to the head block and keeps its
   57px by a 7px foot (6 + the 1px the rule used to take). */
.browse-sidebar .sidebar-head {
  flex-shrink: 0;
  border-bottom: 1px solid rgba(44, 44, 44, 0.08);
}
.browse-sidebar .sidebar-head .sidebar-header {
  padding-bottom: 7px;
  border-bottom: none;
}

:is(.browse-sidebar, .settings-sidebar) .sidebar-header-title {
  /* Placard-eyebrow voice, one step quieter than the wall's 0.18em so chrome
     never outranks content. */
  display: inline-flex;
  align-items: baseline;
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--text-tertiary, #8C8578);
}

/* ── The bilingual lockup (wp-sechead grammar): a Klee ink mark + the
      small-caps EN carrier, on both panels' titles and every group head.
      The title's mark sits one step above the group marks. ── */
:is(.browse-sidebar, .settings-sidebar) .sec-jp {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-weight: 600;
  font-size: 13.5px;
  color: var(--text-primary, #2C2C2C);
  letter-spacing: 0;
  text-transform: none;
  margin-right: 8px;
}
:is(.browse-sidebar, .settings-sidebar) .sidebar-header-title .sec-jp {
  font-size: 14px;
}

/* Row-level Japanese metalanguage (word-type + politeness rows only): quiet
   Klee beside the EN label. Option flag: .sb-jp { display: none } turns the
   panel back to English rows with kanji marks only. */
.browse-sidebar .sb-jp {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-size: 11px;
  font-weight: 400;
  color: rgba(87, 83, 78, 0.62);
  margin-left: 7px;
  letter-spacing: 0;
  /* If the row must wrap at the 200px clamp, the term wraps WHOLE —
     never 固有名 / 詞 across lines. */
  white-space: nowrap;
}

.browse-sidebar .sidebar-header-actions {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.browse-sidebar .sidebar-clear-btn {
  border: none;
  background: none;
  box-shadow: none;
  font: 500 11px 'Inter', sans-serif;
  letter-spacing: 0.02em;
  color: var(--text-tertiary, #8C8578);
  cursor: pointer;
  padding: 2px 6px;
  border-radius: 4px;
  transition: color 0.15s ease;
}
.browse-sidebar .sidebar-clear-btn:hover {
  color: var(--text-primary, #2C2C2C);
  transform: none;
  box-shadow: none;
}

/* The masthead tally — same predicate as the grid, so it can never lie.
   The head's second line since round 3 (it stood between the head and the
   scroller, where the rows slid up under it and were cut mid-glyph). */
.browse-sidebar .sb-tally {
  padding: 0 16px;
  font: 400 12px/18px 'Inter', sans-serif;
  color: var(--text-secondary, #57534e);
  font-variant-numeric: tabular-nums;
}

/* ── THE FIND (round 3, finding 9): under the tally, the whole row wide, the
      quiet underline field it always was; it finds across every group, so
      '/' lands at the panel's top, never 2,000px down at its foot. ── */
.browse-sidebar .sb-find {
  padding: 6px 16px 12px;
}
.browse-sidebar .sb-find .cat-find {
  display: block;
  width: 100%;
  margin: 0;
  padding: 5px 2px;
  border: none;
  border-bottom: 1px solid rgba(44, 44, 44, 0.10);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  font: 400 12.5px 'Inter', sans-serif;
  color: var(--text-primary, #2C2C2C);
  outline: none;
  transition: border-color 0.15s ease;
}
.browse-sidebar .sb-find .cat-find::placeholder {
  color: var(--text-tertiary, #8C8578);
}
.browse-sidebar .sb-find .cat-find:focus {
  border-bottom-color: rgba(44, 44, 44, 0.30);
}
/* a field shows the ring on any focus, the pointer's too: it is where the
   caret is, and the line alone was too quiet to find it by. The ring is on
   the INPUT, with the palette's own field values (2px, offset 2, radius 4),
   so the two text fields of the gallery ring alike; the underline stays. */
.browse-sidebar .sb-find .cat-find:focus-visible {
  outline: 2px solid var(--color-accent, #3D5A80);
  outline-offset: 2px;
  border-radius: 4px;
  box-shadow: none;
}
.browse-sidebar .sb-find-none {
  margin: 8px 2px 0;
  font: 400 11px/1.4 'Inter', sans-serif;
  color: var(--text-tertiary, #8C8578);
}
.browse-sidebar .sb-find-none:empty {
  display: none;
}

/* ── ONE CLOSE (round 3, finding 8): the round-2 door's dress (.gb-settings,
      .cl-menu): a 34px seat with 8px corners, a 16px svg chevron (2px
      stroke) in quiet warm ink at rest, sumi on a breath of ground under the pointer, no
      lift, no shadow, the one ring for the keyboard. Each says its name
      (Close filters / Close settings). ── */
:is(.browse-sidebar, .settings-sidebar) .sidebar-close-btn {
  appearance: none;
  width: 34px;
  height: 34px;
  padding: 0;
  border: none;
  border-radius: 8px;
  background: transparent;
  box-shadow: none;
  color: var(--color-faint-warm, #6E6860);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  transition: color .2s ease, background-color .2s ease;
}
:is(.browse-sidebar, .settings-sidebar) .sidebar-close-btn:hover {
  color: var(--color-ink, #2C2C2C);
  background: rgba(44, 44, 44, 0.05);
  transform: none;
  box-shadow: none;
}
/* a 16px box over the 16-unit viewBox, so stroke-width 2 renders at exactly
   2px (at 18px it rendered 2.25px, soft at 1x); the palette's ✕ is the same
   16px, 2px. The chevron is drawn 4.5 x 9 units, the size it had at 18px. */
:is(.browse-sidebar, .settings-sidebar) .sidebar-close-btn svg {
  width: 16px;
  min-width: 16px;
  height: 16px;
  flex-shrink: 0;
}

/* ── THE FOOT, on both (round 3, finding 7): the rail's "Press Esc to
      close" line (.settings-footer), now under the filter panel's scroller
      too (.sidebar-foot). ── */
:is(.browse-sidebar, .settings-sidebar) :is(.sidebar-foot, .settings-footer) {
  flex-shrink: 0;
  padding: 10px 16px 14px;
  border-top: 1px solid rgba(44, 44, 44, 0.08);
  text-align: center;
}
:is(.browse-sidebar, .settings-sidebar) :is(.sidebar-foot, .settings-footer) span {
  font-size: 11px;
  color: var(--text-tertiary, #8C8578);
  letter-spacing: 0.2px;
}
:is(.browse-sidebar, .settings-sidebar) :is(.sidebar-foot, .settings-footer) kbd {
  /* the SAME key-chip component as the rail's Shortcuts rows: one chip */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 30px;
  height: 22px;
  border-radius: 5px;
  background: transparent;
  color: var(--text-secondary, #57534e);
  font-family: 'Inter', sans-serif;
  font-size: 11px;
  font-weight: 500;
  padding: 0 6px;
  border: 1px solid rgba(44, 44, 44, 0.14);
  margin: 0 2px;
  vertical-align: middle;
}

/* Scrollable content area — header above handles nav clearance */
.browse-sidebar .sidebar-scroll {
  flex: 1;
  overflow-y: auto;
  padding: 8px 16px 24px;
}


/* Scrollbar — appears only on hover for calm resting state */

.browse-sidebar .sidebar-scroll::-webkit-scrollbar { width: 3px; }
.browse-sidebar .sidebar-scroll::-webkit-scrollbar-track { background: transparent; }
.browse-sidebar .sidebar-scroll::-webkit-scrollbar-thumb {
  background: transparent;
  border-radius: 3px;
  transition: background 0.3s ease;
}
.browse-sidebar .sidebar-scroll:hover::-webkit-scrollbar-thumb {
  background: rgba(44,44,44,0.08);
}

/* ============================================================
   LEARNING STATUS FILTERS (状)
   The four locked states (docs/STATUS_TAXONOMY.md) as one more ledger
   group. Dots carry the app's own state inks verbatim — the same hues the
   grid placard's statusline uses — so a row and the card it selects read as
   one system: Learning amber, Coming back the woken moss, Resting the calm
   moss. NEW is a hollow ring, not a filled dot: silence has always meant
   new (a filled dot on the state that lands on most cards is decoration),
   and the 図録 word panel already draws New as an empty ring.
   ============================================================ */
.browse-sidebar .status-filters {
  margin-bottom: 18px;
}
.browse-sidebar .status-row {
  display: flex;
  align-items: center;
  padding: 7px 10px 7px 5px;
  border-radius: 6px;
  cursor: pointer;
  user-select: none;
  font: 400 13px/1.4 'Inter', sans-serif;
  color: var(--text-secondary, #57534e);
}
.browse-sidebar .status-row:hover {
  background: rgba(44, 44, 44, 0.04);   /* one hover wash, rows and the rail's tiles alike (round 3) */
}
.browse-sidebar .status-row.selected {
  background: rgba(44, 44, 44, 0.045);
  color: var(--text-primary, #2C2C2C);
  font-weight: 500;
}
.browse-sidebar .status-label {
  flex: 1;
}
/* ⛔ The dot is `.status-row-dot`, NOT `.status-dot` (renamed 2026-08-16, the
   day the group shipped). `.status-dot` is an UNSCOPED GLOBAL component
   (css/components.css:873) worn by the card-number statusline and both grade
   verbs, and it carries state this panel never asked for: cursor:help,
   opacity:.9, a 0.3s transition, and a :hover that fires transform:scale(1.2).
   Our rule declared none of those, so the global won every one of them
   unopposed — including a hover that MOVES the hovered element, which the
   panel forbids outright. Named like its neighbour .freq-tier-dot, one class
   per group, so nothing outside this file can dress it by accident. */
.browse-sidebar .status-row-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
  margin-right: 10px;
  background: var(--color-stone, #8C8578);
}
/* NEW is a hollow ring, not a filled dot — see the group's header note. */
.browse-sidebar .status-row-dot[data-status="new"] {
  background: transparent;
  box-shadow: inset 0 0 0 1.5px var(--sb-state-new);
}
.browse-sidebar .status-row-dot[data-status="learning"] { background: var(--sb-state-learning); }
.browse-sidebar .status-row-dot[data-status="coming"]   { background: var(--sb-state-coming); }
.browse-sidebar .status-row-dot[data-status="resting"]  { background: var(--sb-state-resting); }


/* ============================================================
   FREQUENCY TIER FILTERS
   Mirrors window.FreqTier mapping (Top 1K / 5K / 10K / 25K / Rare).
   Dot colors borrow the same hues used by the watermark badge so the
   sidebar rows and grid badges read as one system.
   ============================================================ */
.browse-sidebar .freq-tier-filters {
  margin-bottom: 18px;
}
/* Frequency stopped being the panel's FIRST section on 2026-08-16 (状 STATUS
   opens it now), so it takes the same hairline separator every section below
   the first wears. Scoped to the word path by construction: the kanji wall
   hides both. */
.browse-sidebar .freq-section {
  border-top: 1px solid rgba(44, 44, 44, 0.08);   /* one separator value, both panels (round 3) */
  padding-top: 14px;
}
.browse-sidebar .register-filters {
  margin-bottom: 18px;
}
/* Politeness joins the family rhythm (its old .register-section padding came
   from register-chip.css; scoped here). */
.browse-sidebar .register-section {
  padding: 0;
  border-top: 1px solid rgba(44, 44, 44, 0.08);   /* one separator value, both panels (round 3) */
  padding-top: 14px;
}

.browse-sidebar .freq-tier-row {
  display: flex;
  align-items: center;
  padding: 7px 10px 7px 5px;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.15s ease;
  user-select: none;
}

.browse-sidebar .freq-tier-row:hover {
  background: rgba(44, 44, 44, 0.04);   /* one hover wash, rows and the rail's tiles alike (round 3) */
}

.browse-sidebar .freq-tier-row.selected {
  background: rgba(44, 44, 44, 0.045);
}

.browse-sidebar .freq-tier-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
  margin-right: 10px;
  background: var(--color-stone, #8C8578);
}
/* Indigo Core + warm seasonal cascade — matches freq-tier.css */
.browse-sidebar .freq-tier-dot[data-freq-tier="1"] { background: #3a6438; } /* Core evergreen */
.browse-sidebar .freq-tier-dot[data-freq-tier="2"] { background: #5A7494; } /* Everyday muted indigo */
.browse-sidebar .freq-tier-dot[data-freq-tier="3"] { background: #A88542; } /* Occasional gold */
.browse-sidebar .freq-tier-dot[data-freq-tier="4"] { background: var(--color-faint, #B8B0A4); opacity: 0.85; } /* Rare — faded */

.browse-sidebar .freq-tier-label {
  font-size: 13px;
  color: var(--text-secondary, #57534e);
  flex: 1;
  display: flex;
  align-items: baseline;
  gap: 8px;
}

/* The band's CUT-POINTS (owner ruling 2026-08-01). These rows are the ONE
   permanent home for "what does Everyday actually mean" — they used to live
   only inside a hover card that could not open under (hover:none), so on
   iPad, a primary device running the desktop product, the whole scale was
   unreachable. Numbers come from the bundle's rank_bands via
   populateSidebarFreqTier(); never hardcoded here. */
.browse-sidebar .freq-tier-range {
  font-size: 10.5px;
  letter-spacing: 0.06em;
  color: var(--color-faint-warm, #6E6860);
  font-variant-numeric: tabular-nums lining-nums;
  white-space: nowrap;
}

.browse-sidebar .freq-tier-row.selected .freq-tier-label {
  color: var(--text-primary, #2C2C2C);
  font-weight: 500;
}

/* Politeness rows join the ledger (scoped overrides of register-chip.css —
   that file serves other surfaces and stays untouched). Selected speaks the
   panel's universal ink, not the indigo dialect. */
.browse-sidebar .register-row {
  padding: 7px 10px 7px 5px;
  gap: 10px;
  border-radius: 6px;
  font: 400 13px/1.4 'Inter', sans-serif;
  color: var(--text-secondary, #57534e);
}
.browse-sidebar .register-row .register-dot {
  width: 7px;
  height: 7px;
}
.browse-sidebar .register-row:hover {
  background: rgba(44, 44, 44, 0.04);   /* one hover wash, rows and the rail's tiles alike (round 3) */
}
.browse-sidebar .register-row.selected {
  background: rgba(44, 44, 44, 0.045);
  color: var(--text-primary, #2C2C2C);
  font-weight: 500;
}
.browse-sidebar .register-label {
  flex: 1;
}

/* Rare row reads as least-popular — thinner label weight, lower opacity */
.browse-sidebar .freq-tier-row[data-freq-tier="4"] .freq-tier-label {
  font-weight: 400;
  opacity: 0.75;
}

/* THE COUNT COLUMN — every count in the panel is set once: 11px tabular
   numerals, right-aligned on one x-position from Core to the last category. */
.browse-sidebar :is(.status-count, .freq-tier-count, .register-count, .lesson-count,
                    .pos-item-count, .category-pill-count, .textbook-count) {
  font-size: 11px;
  font-weight: 400;   /* never inherits a row's weight (the 600 eyebrow) */
  letter-spacing: 0;
  color: var(--text-tertiary, #8C8578);
  font-variant-numeric: tabular-nums;
  min-width: 28px;
  text-align: right;
  flex-shrink: 0;
}
.browse-sidebar :is(.pos-item.active .pos-item-count,
                    .category-pill.active .category-pill-count) {
  color: var(--text-secondary, #57534e);
}

/* ============================================================
   SECTION HEADERS
   ============================================================ */
.browse-sidebar .sidebar-section-title {
  display: inline-flex;
  align-items: baseline;
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--text-tertiary, #8C8578);
  margin-bottom: 8px;
  padding: 0 4px;
}

/* ============================================================
   TEXTBOOKS ACCORDION
   ============================================================ */
.browse-sidebar .lessons-section {
  margin-bottom: 18px;
  border-top: 1px solid rgba(44, 44, 44, 0.08);   /* one separator value, both panels (round 3) */
  padding-top: 14px;
}

.browse-sidebar .textbook-group {
  margin-bottom: 2px;
}

.browse-sidebar .textbook-header {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  padding: 8px 10px 8px 5px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 400;
  color: var(--text-secondary, #57534e);
  transition: background 0.12s ease;
  user-select: none;
  border: none;
  background: transparent;
  box-shadow: none;
  width: 100%;
  text-align: left;
  font-family: inherit;
}
.browse-sidebar .textbook-header:hover,
.browse-sidebar .textbook-header:active {
  background: rgba(44, 44, 44, 0.04);   /* one hover wash, rows and the rail's tiles alike (round 3) */
  box-shadow: none;
  transform: none;
}
/* (a :focus wash with outline:none stood here: a series head focused by the
   keyboard showed nothing a learner could find, round 3 finding 10. The one
   ring below dresses it now; a mouse focus shows nothing, as it should.) */
.browse-sidebar .textbook-header:focus:not(:focus-visible) {
  outline: none;
  box-shadow: none;
}

.browse-sidebar .tb-label {
  flex: 1;
  min-width: 0;
}


.browse-sidebar .textbook-chevron {
  width: 14px;
  height: 14px;
  color: var(--text-tertiary, #8C8578);
  transition: transform 200ms ease;
  flex-shrink: 0;
}
/* The fold mark lives in the LEFT gutter on series headers — the right edge
   belongs to the count column alone. */
.browse-sidebar .textbook-header .textbook-chevron {
  width: 10px;
  height: 10px;
  margin-right: 7px;
}
.browse-sidebar .textbook-header.collapsed .textbook-chevron {
  transform: rotate(-90deg);
}

.browse-sidebar .textbook-lessons {
  overflow: hidden;
  transition: max-height 250ms cubic-bezier(0.16, 1, 0.3, 1);
}
.browse-sidebar .textbook-header.collapsed + .textbook-lessons {
  max-height: 0 !important;
}

/* Volume fold inside a multi-volume series (owner round 3): the eyebrow is a
   BUTTON that folds its volume's lessons — collapsed is class-backed state,
   same law as every other fold. The eyebrow voice is unchanged. */
.browse-sidebar .textbook-vol {
  display: flex;
  align-items: center;
  width: 100%;
  border: none;
  background: transparent;
  box-shadow: none;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-tertiary, #8C8578);
  padding: 8px 10px 4px 14px;
  border-radius: 6px;
}
.browse-sidebar .textbook-vol:hover,
.browse-sidebar .textbook-vol:active {
  background: rgba(44, 44, 44, 0.04);   /* one hover wash, rows and the rail's tiles alike (round 3) */
  color: var(--text-secondary, #57534e);
  box-shadow: none;
  transform: none;
}
.browse-sidebar .textbook-vol:focus:not(:focus-visible) {
  outline: none;
  box-shadow: none;
}
.browse-sidebar .textbook-vol .textbook-chevron {
  width: 8px;
  height: 8px;
  margin-right: 7px;
}
.browse-sidebar .textbook-vol.collapsed .textbook-chevron {
  transform: rotate(-90deg);
}
.browse-sidebar .tb-vol-label {
  flex: 1;
  min-width: 0;
}
.browse-sidebar .tb-vol-lessons {
  overflow: hidden;
}
.browse-sidebar .textbook-vol.collapsed + .tb-vol-lessons {
  max-height: 0 !important;
}
.browse-sidebar .textbook-lessons > .textbook-vol:first-child { padding-top: 2px; }

.browse-sidebar .lesson-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 10px 6px 30px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 12.5px;
  color: var(--text-secondary, #57534e);
  transition: background 0.12s ease;
  position: relative;
  user-select: none;
}
.browse-sidebar .lesson-item:hover {
  background: rgba(44, 44, 44, 0.04);   /* one hover wash, rows and the rail's tiles alike (round 3) */
}
.browse-sidebar .lesson-item.active {
  background: rgba(44, 44, 44, 0.045);
  color: var(--text-primary, #2C2C2C);
  font-weight: 500;
}
.browse-sidebar .lesson-item.active::before {
  content: '';
  position: absolute;
  left: 6px;
  top: 4px;
  bottom: 4px;
  width: 3px;
  border-radius: 2px;
  background: rgba(44, 44, 44, 0.55);
}


/* The find's misses (round 3, finding 9): rows, volumes, series and whole
   groups the field does not match leave the panel while it holds a query.
   A fold the find opened (.find-open) shows OPEN over the user's own
   .collapsed, which is never rewritten, so emptying the field puts every
   fold back exactly as it was. */
.browse-sidebar .find-miss {
  display: none !important;
}
/* the first group standing under the head's rule drops its own separator
   while a query holds (no double rule) */
.browse-sidebar .sidebar-scroll.is-finding > .find-first {
  border-top: none;
  padding-top: 0;
}
.browse-sidebar .section-head:has(.sidebar-section-toggle.collapsed.find-open) + * {
  max-height: none !important;
  overflow: visible !important;
}
.browse-sidebar .textbook-header.collapsed.find-open + .textbook-lessons,
.browse-sidebar .textbook-vol.collapsed.find-open + .tb-vol-lessons {
  max-height: none !important;
}
/* an open series carries a px cap from the moment it opened; the find may
   open a volume inside it, so the cap lifts while a query holds */
.browse-sidebar .sidebar-scroll.is-finding .textbook-header:not(.collapsed) + .textbook-lessons {
  max-height: none !important;
}
.browse-sidebar :is(.sidebar-section-toggle, .textbook-header, .textbook-vol).collapsed.find-open .textbook-chevron {
  transform: none;
}

/* ONE RING (desktop polish round 3, finding 10): every control in both
   panels shows the keyboard's focus as the app's one ring, 2px indigo,
   2px off the control, and nothing else. The rows wore it INSET plus the
   global 4px halo (base.css), a double frame; the textbook heads and the
   volumes had none at all; the find field had a hairline. :where() keeps
   this at the specificity of base.css's own [role=button] rule (later in
   the cascade, so it wins) and under every component rule that keeps an
   inset ring of its own (the rail's option tiles). */
:is(.browse-sidebar, .settings-sidebar) :where(button, a[href], input, [role="button"], [tabindex="0"]):focus-visible {
  outline: 2px solid var(--color-accent, #3D5A80);
  outline-offset: 2px;
  box-shadow: none;
}
.browse-sidebar :is(.status-row, .freq-tier-row, .register-row, .lesson-item,
    .pos-item, .category-pill, .textbook-header, .textbook-vol):focus-visible {
  border-radius: 6px;
}

/* The count-tick — the faceted recount made visible: a numeral that just
   changed darkens to ink and settles back. Color-only, diff-guarded in JS,
   dead under reduced motion. */
@keyframes sbCountTick {
  from { color: var(--text-primary, #2C2C2C); font-weight: 500; }
  to   { color: var(--text-tertiary, #8C8578); }
}
.browse-sidebar .count-tick {
  animation: sbCountTick 450ms ease-out;
}
@media (prefers-reduced-motion: reduce) {
  .browse-sidebar .count-tick { animation: none; }
}

/* Faceted counts: an option whose count drops to 0 under the current selection
   is greyed and made inert. A currently-selected option is never marked empty
   (it must stay clickable to deselect), so this only hits dead-end options. */
.browse-sidebar .status-row.is-empty,
.browse-sidebar .freq-tier-row.is-empty,
.browse-sidebar .register-row.is-empty,
.browse-sidebar .pos-item.is-empty,
.browse-sidebar .category-pill.is-empty,
.browse-sidebar .lesson-item.is-empty,
.browse-sidebar .textbook-vol.is-empty,
.browse-sidebar .textbook-header.is-empty {
  opacity: 0.35;
  pointer-events: none;
}
/* Keep the transition gentle so live recounts fade rather than snap. */
.browse-sidebar .status-row,
.browse-sidebar .freq-tier-row,
.browse-sidebar .register-row,
.browse-sidebar .pos-item,
.browse-sidebar .category-pill,
.browse-sidebar .lesson-item,
.browse-sidebar .textbook-vol,
.browse-sidebar .textbook-header {
  transition: opacity 0.18s ease, background 0.12s ease;
}

.browse-sidebar .lesson-item.lesson-all {
  font-weight: 500;
  color: var(--text-primary, #2C2C2C);
  padding-left: 30px;
  margin-bottom: 2px;
}
.browse-sidebar .lesson-item.lesson-all.active {
  background: rgba(44, 44, 44, 0.045);
}

/* ============================================================
   PART OF SPEECH LIST
   ============================================================ */
.browse-sidebar .pos-section {
  margin-bottom: 18px;
  border-top: 1px solid rgba(44, 44, 44, 0.08);   /* one separator value, both panels (round 3) */
  padding-top: 14px;
}

.browse-sidebar .pos-content {
  overflow: hidden;
  transition: max-height 250ms cubic-bezier(0.16, 1, 0.3, 1);
}

.browse-sidebar .pos-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 10px 6px 22px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 12.5px;
  color: var(--text-secondary, #57534e);
  transition: background 0.12s ease;
  user-select: none;
  position: relative;
}
.browse-sidebar .pos-item-label {
  flex: 1;
  min-width: 0;
}
.browse-sidebar .pos-item:hover {
  background: rgba(44, 44, 44, 0.04);   /* one hover wash, rows and the rail's tiles alike (round 3) */
}
.browse-sidebar .pos-item.active {
  background: rgba(44, 44, 44, 0.045);
  color: var(--text-primary, #2C2C2C);
  font-weight: 500;
}
.browse-sidebar .pos-item.active::before {
  content: '';
  position: absolute;
  left: 6px;
  top: 4px;
  bottom: 4px;
  width: 3px;
  border-radius: 2px;
  background: rgba(44, 44, 44, 0.55);
}

/* ============================================================
   COLLAPSIBLE SECTION TOGGLE — shared by POS & Categories
   ============================================================ */
.browse-sidebar .sidebar-section-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 0 4px;
  margin-bottom: 8px;
  border: none;
  background: transparent;
  box-shadow: none;
  cursor: pointer;
  font-family: inherit;
}
.browse-sidebar .sidebar-section-toggle:hover,
.browse-sidebar .sidebar-section-toggle:active {
  transform: none;
  box-shadow: none;
}

.browse-sidebar .sidebar-section-toggle .sidebar-section-title {
  margin-bottom: 0;
  /* The toggle button already carries 4px left padding; drop the title's own 4px
     so its text aligns with the standalone Frequency header (which sits at 4px). */
  padding-left: 0;
}

.browse-sidebar .sidebar-section-toggle .textbook-chevron {
  width: 14px;
  height: 14px;
  color: var(--text-tertiary, #8C8578);
  transition: transform 200ms ease;
  flex-shrink: 0;
}
.browse-sidebar .sidebar-section-toggle.collapsed .textbook-chevron {
  transform: rotate(-90deg);
}
/* Collapsed is a STATE, not an animation endpoint — the class guarantees the
   fold even if the max-height transition never settles (mirrors the textbook
   accordion's own .collapsed + rule). The toggle lives inside .section-head;
   the section content is the head's next sibling. */
.browse-sidebar .section-head:has(.sidebar-section-toggle.collapsed) + * {
  max-height: 0 !important;
  overflow: hidden !important;
}

/* ── Section head row: fold toggle + per-axis clear ✕ (valid HTML — the ✕
      cannot nest inside the toggle button). The ✕ reserves its slot even when
      hidden so the chevron never shifts. ── */
.browse-sidebar .section-head {
  display: flex;
  align-items: center;
  margin-bottom: 8px;
}
.browse-sidebar .section-head .sidebar-section-toggle {
  flex: 1;
  min-width: 0;
  margin-bottom: 0;
}
/* The group's × wears the ONE CLOSE dress at a 24px seat (desktop polish
   round 3, finding 8: it was a 13px text glyph in a bare 20px box): 6px
   corners, quiet warm ink, sumi on a breath of ground under the pointer,
   the one ring for the keyboard, its label kept ("Clear status filters").
   The 2px of seat above and below bleed into the row's air, so the head
   keeps its 20px line and no group moves. */
.browse-sidebar .section-clear {
  visibility: hidden;
  appearance: none;
  width: 24px;
  height: 24px;
  margin: -2px 0;
  padding: 0;
  border: none;
  border-radius: 6px;
  background: transparent;
  box-shadow: none;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-ui, 'Inter', system-ui, sans-serif);
  font-size: 15px;
  line-height: 1;
  color: var(--color-faint-warm, #6E6860);
  cursor: pointer;
  flex: none;
  transition: color .2s ease, background-color .2s ease;
}
.browse-sidebar .section-clear.on {
  visibility: visible;
}
.browse-sidebar .section-clear:hover {
  color: var(--color-ink, #2C2C2C);
  background: rgba(44, 44, 44, 0.05);
  transform: none;
  box-shadow: none;
}

/* ============================================================
   SECTION TALLY — an honest ink numeral ('· 2') on section/series
   headers naming how many selections live inside. Replaces the vague
   gold dot; the element/ids/.visible class survive (the faceted
   refresher reads .section-active-dot.visible as series-is-active).
   ============================================================ */
.browse-sidebar .section-active-dot {
  display: none;
  flex-shrink: 0;
  margin-left: 7px;
  font: 600 10px 'Inter', sans-serif;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  color: var(--text-primary, #2C2C2C);
}
.browse-sidebar .section-active-dot.visible {
  display: inline;
}

/* ============================================================
   CATEGORIES — ledger rows (de-pilled 2026-06-12; .category-pill class
   names survive for the faceted engine, only the shape died)
   ============================================================ */
.browse-sidebar .categories-section {
  margin-bottom: 0;
  border-top: 1px solid rgba(44, 44, 44, 0.08);   /* one separator value, both panels (round 3) */
  padding-top: 14px;
}

.browse-sidebar .category-pills {
  display: block;
  padding: 0;
}

.browse-sidebar .category-pill {
  display: flex;
  width: 100%;
  align-items: center;
  gap: 8px;
  padding: 5px 10px 5px 22px;
  font-size: 12.5px;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--text-secondary, #57534e);
  cursor: pointer;
  user-select: none;
  position: relative;
  font-family: 'Inter', -apple-system, sans-serif;
}
.browse-sidebar .category-pill-label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.browse-sidebar .category-pill:hover {
  background: rgba(44, 44, 44, 0.04);   /* one hover wash, rows and the rail's tiles alike (round 3) */
  color: var(--text-primary, #2C2C2C);
}
.browse-sidebar .category-pill.active {
  background: rgba(44, 44, 44, 0.045);
  color: var(--text-primary, #2C2C2C);
  font-weight: 500;
}
.browse-sidebar .category-pill.active:hover {
  background: rgba(44, 44, 44, 0.06);
}
.browse-sidebar .category-pill.active::before {
  content: '';
  position: absolute;
  left: 6px;
  top: 4px;
  bottom: 4px;
  width: 3px;
  border-radius: 2px;
  background: rgba(44, 44, 44, 0.55);
}

/* (Destination buttons retired 2026-07-04 — the beam's Tutor button left
   with the topnav unification; voice practice enters from the hall door or
   the C key.) */

/* ============================================================
   SETTINGS SIDEBAR — right-side push panel
   Mirror sibling of browse sidebar. Contains display mode,
   keyboard shortcuts, and reset progress.
   ============================================================ */

:root {
  --settings-sidebar-w: clamp(200px, 20vw, 260px);
}

.settings-sidebar {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: var(--settings-sidebar-w);
  /* Stone column — mirror of the browse sidebar. The rail opens over TWO
     rooms (the gallery wall and the 玄関 hall), so it paints the ground
     token, not the wall's recipe: the hall re-points it and the rail
     follows. Background transitions with the swap so a room change under an
     open rail is one gesture, not a snap. */
  background: var(--room-ground);
  border-left: 1px solid rgba(44, 44, 44, 0.10);
  display: flex;
  flex-direction: column;
  z-index: 90;
  transform: translateX(100%);
  transition: transform 250ms cubic-bezier(0.16, 1, 0.3, 1),
              background 200ms ease;
}

.settings-sidebar.open {
  transform: translateX(0);
}

/* ---- Header: the shared head at the top of this file (one title row, one
   lockup, one close for both side panels since round 3, finding 7). ---- */

/* ---- Scroll area ---- */
.settings-sidebar .sidebar-scroll {
  flex: 1;
  overflow-y: auto;
  padding: 8px 16px 24px;
}

.settings-sidebar .sidebar-scroll::-webkit-scrollbar { width: 3px; }
.settings-sidebar .sidebar-scroll::-webkit-scrollbar-track { background: transparent; }
.settings-sidebar .sidebar-scroll::-webkit-scrollbar-thumb {
  background: transparent;
  border-radius: 3px;
  transition: background 0.3s ease;
}
.settings-sidebar .sidebar-scroll:hover::-webkit-scrollbar-thumb {
  background: rgba(44,44,44,0.08);
}

/* ---- Settings groups — shared structure ---- */
.settings-sidebar .settings-group {
  margin-bottom: 18px;
}

/* The rail's group heads wear the filter panel's group head (desktop polish
   round 3, finding 7: 9px caps eyebrows against the panel's Klee mark and
   10.5px caps): the Klee mark (.sec-jp, dressed with the panel's at the top
   of this file) + Inter caps 10.5/600 at .14em in the faint ink. No chevron:
   these groups never fold. The two st-eyebrow groups below wear the same. */
.settings-sidebar .settings-group-label {
  display: flex;
  align-items: baseline;
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--text-tertiary, #8C8578);
  margin: 0 0 10px;
  padding: 0 4px;
}

/* ---- Preference groups (st-* — the ONE settings component, rendered by
   js/journey-settings.js into #settingsPrefsMount; owner ruling 2026-07-17).
   The sheet's vocabulary dressed for the rail's stone column: resting tiles
   recess into the column (inset hairline groove), the chosen tile lifts on
   paper with an ink ring — no dark fills, ink stays meaningful as "chosen".
   Mirrors css/journey.css's .kj st-* block; sizes tightened for the rail. */
.settings-sidebar .st-wrap { padding: 2px 4px 6px; }
.settings-sidebar .st-group { padding: 15px 0; }
.settings-sidebar .st-group + .st-group { border-top: 1px solid rgba(44, 44, 44, 0.08); }
.settings-sidebar .st-eyebrow { display: flex; align-items: baseline; gap: 8px; margin-bottom: 9px; }
/* the panel's group head, verbatim (round 3): the mark is .sec-jp's dress,
   the English is .sidebar-section-title's */
.settings-sidebar .st-eyebrow .ej { font-family: 'Klee One', 'Noto Sans JP', sans-serif; font-size: 13.5px; font-weight: 600; color: var(--text-primary, #2C2C2C); letter-spacing: 0; }
.settings-sidebar .st-eyebrow em { font-style: normal; font-size: 10.5px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-tertiary, #8C8578); font-weight: 600; }
.settings-sidebar .st-seg { display: flex; gap: 6px; }
.settings-sidebar .st-opt {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  padding: 9px 5px; min-height: 46px;
  border: none; cursor: pointer;
  border-radius: 10px;
  background: transparent;
  box-shadow: inset 0 0 0 1px rgba(44, 40, 32, 0.09);
  transition: background .18s ease, box-shadow .18s ease;
}
/* one hover wash with the filter panel's rows (round 3); the tile keeps its
   groove under the pointer (the rail's button:hover reset below used to
   strip it, so a hovered tile lost its shape) */
.settings-sidebar .st-opt:hover:not(.on):not([disabled]) { background: rgba(44, 44, 44, 0.04); box-shadow: inset 0 0 0 1px rgba(44, 40, 32, 0.09); }
.settings-sidebar .st-opt b { font-family: var(--font-ui); font-size: 13px; font-weight: 600; line-height: 1.25; color: var(--color-ink, #2C2C2C); font-variant-numeric: tabular-nums; }
.settings-sidebar .st-opt b .jp { font-family: var(--font-jp); font-size: 14px; }
/* the reading row mixes a ruby sample with plain ones — reserve the ruby's
   headroom in every cell and bottom-align, so all three sit on one line */
.settings-sidebar .st-seg--samples .st-opt b { display: flex; flex-direction: column; align-items: center; justify-content: flex-end; min-height: 2.2em; }
.settings-sidebar .st-opt b ruby { ruby-align: center; }
/* the sample IS the label — preview furigana at the app's own ratio + dim
   (base.css ruby convention: ~0.45em, inherited ink at .55), not an inflated
   settings-only rendition */
.settings-sidebar .st-opt b ruby rt { font-size: 0.45em; font-weight: 500; color: inherit; opacity: 0.55; letter-spacing: .02em; white-space: nowrap; }
.settings-sidebar .st-opt small { font-size: 9px; letter-spacing: .1px; color: var(--color-stone, #57534e); font-weight: 500; }
.settings-sidebar .st-opt small i { font-style: italic; letter-spacing: .15px; }
.settings-sidebar .st-opt.on { background: var(--color-card, #FAFAF7); box-shadow: inset 0 0 0 1.5px var(--color-ink, #2C2C2C); }
.settings-sidebar .st-opt[disabled] { opacity: .45; cursor: default; }
.settings-sidebar .st-hint { margin-top: 9px; font-size: 11px; color: var(--color-stone, #57534e); line-height: 1.45; padding: 0 2px; }

/* Reset global button hover effects — calm, no lifts */
.settings-sidebar button {
  transform: none;
  box-shadow: none;
}
.settings-sidebar button:hover {
  transform: none;
  box-shadow: none;
}
.settings-sidebar button:active {
  transform: none;
}

/* (The old .settings-display-mode / .segment-btn / .settings-session-size
   rail-control styles left with their markup — the preference groups render
   as the st-* component block above since 2026-07-17.) */

/* ---- Shortcuts section — warm tones ---- */
.settings-sidebar .shortcuts-section {
  border-top: 1px solid rgba(44, 44, 44, 0.08);
  padding-top: 14px;
}

.settings-sidebar .shortcuts-column {
  display: flex;
  flex-direction: column;
}

.settings-sidebar .shortcut-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 5px 4px;
  border-radius: 6px;
  transition: background 0.12s ease;
}
.settings-sidebar .shortcut-item:hover {
  background: rgba(44,44,44,0.02);
}

.settings-sidebar .shortcut-item span {
  color: var(--text-secondary, #57534e);
  font-size: 12.5px;
  font-weight: 400;
}

.settings-sidebar .shortcut-item kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 30px;             /* one chip family: a lone C sits as wide as ⌘K */
  height: 22px;
  border-radius: 5px;
  background: transparent;
  color: var(--text-secondary, #57534e);
  font-family: 'Inter', sans-serif;
  font-size: 11px;
  font-weight: 500;
  padding: 0 6px;
  border: 1px solid rgba(44, 44, 44, 0.14);
  white-space: nowrap;
  flex-shrink: 0;
  margin-left: 12px;
}

/* ---- Reset progress — structured section at bottom ---- */
.settings-sidebar .settings-reset-section {
  margin-top: auto;
  margin-bottom: 0;
  border-top: 1px solid rgba(44, 44, 44, 0.08);
  padding-top: 14px;
}

.settings-sidebar .settings-reset-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 6px 4px;
  font-size: 12.5px;
  font-family: 'Inter', -apple-system, sans-serif;
  color: var(--text-secondary, #57534e);
  background: none;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  text-align: left;
  transition: color 0.15s ease, background 0.12s ease;
}
.settings-sidebar .settings-reset-icon {
  /* inline SVG arc (2px stroke — the close chevron's line language) */
  display: inline-flex;
  align-items: center;
  color: var(--text-tertiary, #8C8578);
  transition: color 0.15s ease;
}
.settings-sidebar .settings-reset-btn:hover {
  color: var(--color-amber-deep);
  background: rgba(180, 83, 9, 0.04);
}
.settings-sidebar .settings-reset-btn:hover .settings-reset-icon {
  color: var(--color-amber-deep);
}

/* Two-step inline confirm */
.settings-sidebar .settings-reset-confirm {
  display: none;
  padding: 8px 4px;
}

.settings-sidebar .settings-reset-group.confirming .settings-reset-btn {
  display: none;
}
.settings-sidebar .settings-reset-group.confirming .settings-reset-confirm {
  display: block;
}

.settings-sidebar .settings-reset-label {
  display: block;
  font-size: 12px;
  color: var(--text-secondary, #57534e);
  text-align: center;
  margin-bottom: 8px;
}

.settings-sidebar .settings-reset-buttons {
  display: flex;
  gap: 6px;
}

.settings-sidebar .settings-reset-yes,
.settings-sidebar .settings-reset-no {
  flex: 1;
  padding: 6px 10px;
  border-radius: 6px;
  background: none;
  font-size: 12px;
  font-family: inherit;
  cursor: pointer;
  transition: background 0.15s ease;
}

.settings-sidebar .settings-reset-yes {
  border: 1px solid var(--color-amber-deep);
  color: var(--color-amber-deep);
}
.settings-sidebar .settings-reset-yes:hover {
  background: rgba(180, 83, 9, 0.06);
}

.settings-sidebar .settings-reset-no {
  border: 1px solid rgba(44,44,44,0.08);
  color: var(--text-secondary, #57534e);
}
.settings-sidebar .settings-reset-no:hover {
  border-color: rgba(44,44,44,0.14);
}

/* "Done" state after reset */
.settings-sidebar .settings-reset-group.done .settings-reset-btn,
.settings-sidebar .settings-reset-group.done .settings-reset-confirm {
  display: none;
}
.settings-sidebar .settings-reset-group.done::after {
  content: 'Done';
  display: block;
  text-align: center;
  padding: 8px;
  font-size: 12px;
  color: var(--status-mastered-vivid);
  font-weight: 600;
}

/* ---- Footer hint: the shared .sidebar-foot at the top of this file (the
   filter panel wears it too since round 3, finding 7). ---- */

/* ---- Push grid/nav when open ---- */
body.settings-sidebar-open .grid-container {
  margin-right: var(--settings-sidebar-w, 260px);
  max-width: min(1800px, calc(100% - var(--settings-sidebar-w, 260px)));
}

/* The beam stops at the rail's edge. Its padding is NOT set here any more
   (desktop polish round 3, finding 7): this rule loads after
   css/ink-wash-tabs.css and its 40px pair beat the beam's own side-panel
   rule for the rail alone, so the ⋮ stood 56px off the rail and the brand
   8px off the filter panel. Both gaps live in ink-wash-tabs.css now. */
body.settings-sidebar-open .ink-wash-nav {
  right: var(--settings-sidebar-w, 260px);
}

/* ============================================================
   HIDE ON MOBILE — sidebars are desktop-only
   ============================================================ */
@media (max-width: 768px) {
  .browse-sidebar {
    display: none !important;
  }

  .settings-sidebar {
    display: none !important;
  }

}

/* ============================================================
   REDUCED MOTION — the panel holds still. (The JS that writes
   inline transitions is gated separately: inline styles defeat
   this media query, and the transitionend-dependent expand needs
   a synchronous fallback — see wireSectionToggle.)
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .browse-sidebar,
  .settings-sidebar {
    transition: none;
  }
  .browse-sidebar :is(.textbook-lessons, .pos-content, .textbook-chevron,
      .status-row, .freq-tier-row, .register-row, .pos-item, .category-pill,
      .lesson-item, .textbook-header, .textbook-vol, .tb-vol-lessons,
      .sidebar-clear-btn, .sidebar-close-btn) {
    transition: none;
  }
}
