/* ── Content Library — uses the global theme variables (dark root + [data-theme="light"]) ── */
.library-shell { max-width: 1100px; margin: 0 auto; padding: 24px 20px 64px; }
.lib-loading { text-align: center; padding: 48px 0; color: var(--text-muted, #9aa4b2); }

.lib-view { display: flex; flex-direction: column; gap: 18px; }

/* View header: title left, back button top-right */
.lib-view-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.lib-view-title { font-family: "Cormorant Garamond", serif; font-size: 28px; font-weight: 700; margin: 0; }
.lib-back {
  margin-left: auto; padding: 7px 14px; border-radius: 8px;
  background: var(--surface); border: 1px solid var(--border, #3a4150);
  color: var(--text, #d8dee9); cursor: pointer; font-size: 14px; font-weight: 600;
  font-family: inherit;
}
.lib-back:hover { background: rgba(255,255,255,0.06); }

/* Landing cards */
.lib-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 16px; }
.lib-card {
  display: flex; flex-direction: column; gap: 8px; text-align: left;
  padding: 18px; border-radius: 12px; cursor: pointer;
  background: var(--surface); border: 1px solid var(--border, #3a4150);
  color: var(--text, #d8dee9); font: inherit;
}
.lib-card:hover { border-color: var(--accent); }
.lib-card-icon { font-size: 26px; }
.lib-card-name { font-family: "Cormorant Garamond", serif; font-size: 19px; font-weight: 700; }
.lib-card-desc { font-size: 13px; color: var(--text-muted, #9aa4b2); line-height: 1.45; }
.lib-card-count { margin-top: auto; font-size: 12px; font-weight: 700; color: var(--accent); }
.lib-card.disabled { opacity: 0.55; cursor: not-allowed; }

/* Toolbar: search + filters */
.lib-toolbar { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.lib-search {
  /* flex:none + explicit width, not a flex-basis shorthand: this element is a direct
     child of `.lib-controls` (flex-direction: column) in every list view except Spells,
     so a `flex: 1 1 220px` here would set its flex-basis on the column's main axis
     (height), not width — producing a 220px-tall input instead of a 220px-wide one. */
  flex: none; width: 100%; max-width: 420px;
  padding: 9px 12px; border-radius: 8px;
  background: var(--surface); border: 1px solid var(--border, #3a4150);
  color: var(--text, #d8dee9); font-size: 14px; line-height: 1.4;
  appearance: none; -webkit-appearance: none;
}
.lib-toolbar .lib-search { flex: 1 1 220px; max-width: none; }
.lib-search::-webkit-search-decoration,
.lib-search::-webkit-search-cancel-button,
.lib-search::-webkit-search-results-button,
.lib-search::-webkit-search-results-decoration { -webkit-appearance: none; }
.lib-filters, .lib-filter-pills { display: flex; flex-wrap: wrap; gap: 6px; }
.lib-pill {
  padding: 6px 12px; border-radius: 999px; font-size: 13px; font-weight: 600;
  background: var(--surface); border: 1px solid var(--border, #3a4150);
  color: var(--text, #d8dee9); cursor: pointer; font-family: inherit;
}
.lib-pill.on { background: var(--accent-glow); border-color: var(--accent); color: var(--accent); }
.lib-count { font-size: 13px; color: var(--text-muted, #9aa4b2); margin-left: auto; }

/* Expandable rows */
.lib-list { display: flex; flex-direction: column; gap: 8px; }
/* `hidden` must beat the display:flex above (author styles override the UA rule) */
.lib-list[hidden], .lib-class-grid[hidden] { display: none; }
.lib-row { background: var(--surface); border: 1px solid var(--border, #3a4150); border-radius: 10px; }
.lib-row > summary {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 12px 14px; cursor: pointer; list-style: none; font-size: 14px;
}
.lib-row > summary::-webkit-details-marker { display: none; }
.lib-row-name { font-weight: 700; }
.lib-row-meta { display: flex; align-items: center; gap: 6px; margin-left: auto; flex-wrap: wrap; }
.lib-chip {
  font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 999px;
  background: rgba(120,140,200,0.12); color: var(--text-muted, #9aa4b2);
}
.lib-row-chevron { margin-left: 4px; color: var(--text-muted, #9aa4b2); transition: transform 0.15s; }
.lib-row[open] .lib-row-chevron { transform: rotate(90deg); }
.lib-row-body { padding: 0 14px 14px; font-size: 14px; line-height: 1.55; display: grid; gap: 8px; color: var(--text, #d8dee9); }
.lib-empty, .lib-error { text-align: center; padding: 40px 0; color: var(--text-muted, #9aa4b2); }
.lib-retry { margin-top: 10px; padding: 7px 14px; border-radius: 8px; border: 1px solid var(--border, #3a4150); background: var(--surface); color: var(--text, #d8dee9); cursor: pointer; font-family: inherit; }

/* Class picker tiles */
.lib-class-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 12px; }
.lib-card-meta { margin-top: auto; display: flex; gap: 4px; flex-wrap: wrap; }

/* Spells toolbar bits */
.lib-chip-row { display: flex; flex-wrap: wrap; gap: 6px; }
button.lib-chip { border: 1px solid var(--border, #3a4150); cursor: pointer; font: inherit; }
button.lib-chip.active { background: var(--accent-glow); border-color: var(--accent); color: var(--accent); }
.lib-badge {
  font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 999px;
  /* --accent-soft, not --accent-glow: the latter is a 50%-alpha focus-ring value,
     and accent text on it measures about 2.3:1. */
  background: var(--accent-soft); color: var(--accent);
}
.lib-field { display: flex; align-items: center; gap: 6px; }
.lib-label {
  font-size: 12px; font-weight: 700; color: var(--text-muted, #9aa4b2);
  text-transform: uppercase; letter-spacing: 0.04em;
}

/* Detail views: class hero, tables, features, subclass slot */
.lib-class-hero { padding: 18px; border-radius: 12px; background: var(--surface); border: 1px solid var(--border, #3a4150); }
.lib-class-hero h2 { margin: 0 0 8px; font-family: "Cormorant Garamond", serif; font-size: 24px; }
.lib-class-hero p { margin: 10px 0 0; line-height: 1.6; }
.lib-table-wrap { overflow-x: auto; }
.lib-table {
  width: 100%; border-collapse: collapse; font-size: 14px;
  background: var(--surface); border: 1px solid var(--border, #3a4150); border-radius: 10px;
}
.lib-table th, .lib-table td { text-align: left; padding: 8px 12px; border-bottom: 1px solid var(--border, #3a4150); vertical-align: top; }
.lib-table th { font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted, #9aa4b2); }
.lib-feature { margin-bottom: 10px; }
.lib-feature p { margin: 4px 0 0; color: var(--text, #d8dee9); line-height: 1.55; }
.lib-subclass-slot { display: grid; gap: 10px; }
.lib-subclass-row { width: 100%; text-align: left; font: inherit; color: var(--text, #d8dee9); cursor: pointer; }

/* Mobile */
@media (max-width: 720px) {
  .library-shell { padding: 16px 12px 56px; }
  .lib-cards { grid-template-columns: 1fr; gap: 10px; }
  .lib-row > summary { align-items: flex-start; }
  .lib-row-meta { margin-left: 0; }
  .lib-view-title { font-size: 22px; }
}

/* Controls block: count + filters + search + empty state are inside one column */
.lib-controls { display: flex; flex-direction: column; gap: 10px; }

/* Category pill rows (items / magic items) */
.lib-cat-row { display: flex; flex-wrap: wrap; gap: 6px; }
.lib-cat-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: 999px; font-size: 13px; font-weight: 600;
  background: var(--surface); border: 1px solid var(--border, #3a4150);
  color: var(--text, #d8dee9); cursor: pointer; font-family: inherit;
}
.lib-cat-btn:hover { border-color: var(--accent); }
.lib-cat-btn.on { background: var(--accent-glow); border-color: var(--accent); color: var(--accent); }
.lib-cat-ic { font-size: 15px; line-height: 1; }
.lib-cat-label { white-space: nowrap; }

/* Book filter: toggle button + selected chips + dropdown menu */

/* Class detail section headings + per-level blocks */
.lib-section-title {
  margin: 22px 0 10px; padding-bottom: 6px;
  font-family: "Cormorant Garamond", serif; font-size: 22px; font-weight: 700;
  color: var(--accent); border-bottom: 1px solid var(--border, #3a4150);
}
.lib-level { margin-top: 16px; }
.lib-level h3 { margin: 0 0 6px; font-family: "Cormorant Garamond", serif; font-size: 17px; font-weight: 700; color: var(--text, #d8dee9); }

/* ── Monsters (Bestiary) ──────────────────────────────────────────────────
   Column template is declared once and consumed by both the header row and
   every monster row, so the two cannot drift out of alignment. */
.library-shell { --lib-mon-cols: 2fr 0.7fr 1.1fr 1fr 0.8fr 1.2fr; }

/* Creature-type circles: the same active treatment as .lib-cat-btn (accent
   border + accent label + soft accent wash), drawn as circles with icons.
   All 15 types plus All are always visible — no "show more". */
/* auto-fit grid rather than a wrapping flex row: all 16 circles share the row
   evenly at desktop width and reflow to even rows below it, instead of leaving a
   ragged tail. */
.lib-mon-types { display: grid; grid-template-columns: repeat(auto-fit, minmax(58px, 1fr)); gap: 8px 6px; }
.lib-mon-type {
  padding: 0; display: flex; flex-direction: column; align-items: center; gap: 4px;
  background: none; border: none; color: inherit; font: inherit; cursor: pointer;
}
.lib-mon-type-ic {
  width: 42px; height: 42px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-emoji); font-size: 18px; line-height: 1;
  background: var(--surface); border: 2px solid var(--border);
  transition: border-color 140ms cubic-bezier(0.23, 1, 0.32, 1), box-shadow 140ms cubic-bezier(0.23, 1, 0.32, 1);
}
.lib-mon-type-label {
  font-size: 10px; font-weight: 700; letter-spacing: 0.02em; text-transform: uppercase;
  color: var(--text-faint); text-align: center;
}
.lib-mon-type:hover .lib-mon-type-ic { border-color: var(--accent); }
.lib-mon-type.on .lib-mon-type-ic {
  border-color: var(--accent); background: var(--accent-soft);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.lib-mon-type.on .lib-mon-type-label { color: var(--accent); }
.lib-mon-type:focus-visible { outline: none; }
.lib-mon-type:focus-visible .lib-mon-type-ic { outline: 2px solid var(--accent); outline-offset: 3px; }

/* Filter panels: primary (always visible) and advanced (behind the toggle) */
.lib-mon-filters {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px;
  padding: 16px; border-radius: var(--radius-lg);
  background: var(--surface); border: 1px solid var(--border);
}
.lib-mon-field { min-width: 0; }
.lib-mon-flabel {
  display: block; margin-bottom: 5px;
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--text-faint);
}
/* Background, border, radius, padding, font and width all come from the global
   input[type=text] / input[type=number] / select rule in style-wizard-shell.css;
   re-declaring them here only duplicated that rule and lost the cascade. */
.lib-mon-input { box-sizing: border-box; }
.lib-mon-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.lib-mon-pair { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 6px; }
.lib-mon-dash { font-size: 11px; color: var(--text-faint); }

/* The gateway to nineteen more filters, so it reads as a control rather than a
   footnote under the primary panel: full width, bordered, on its own surface. */
.lib-mon-advtoggle {
  width: 100%; padding: 12px; cursor: pointer;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  font-family: inherit; font-size: 15px; font-weight: 700; letter-spacing: 0.03em;
  color: var(--accent);
  transition: border-color 120ms cubic-bezier(0.23, 1, 0.32, 1);
}
.lib-mon-advtoggle:hover { border-color: var(--accent); }
.lib-mon-advtoggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lib-mon-adv {
  display: grid; gap: 18px; padding: 16px; border-radius: var(--radius-lg);
  background: var(--surface); border: 1px solid var(--border);
}
.lib-mon-adv .lib-mon-filters { padding: 0; background: none; border: none; }
/* Nineteen filters in one flat stack is a wall. Named groups — tight inside,
   airy between — give the eye somewhere to land. */
.lib-mon-group { display: grid; gap: 8px; }
.lib-mon-group-title {
  margin: 0; font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--accent);
}
/* .lib-label is 12px/--text-muted elsewhere; inside this panel it has to read as
   the same tier as .lib-mon-flabel, or the two label styles fight each other. */
.lib-mon-adv .lib-label { font-size: 11px; letter-spacing: 0.03em; color: var(--text-faint); }
/* Pill rows share a fixed label column so every row's first pill starts at the same
   x. Left inline, "Senses" and "Save Proficiency" pushed their pills to different
   offsets and the group read as ragged. */
.lib-mon-adv .lib-filter-pills {
  display: grid; grid-template-columns: 128px 1fr; align-items: start; gap: 6px 10px;
}
/* Top-aligned, not centred. Planar Detail's fourteen values wrap to two rows, and centring
   floated its heading down between them while every single-row heading above sat level with
   its pills. The padding is the pill's own, so the two texts share a line. */
.lib-mon-adv .lib-filter-pills > .lib-label { align-self: start; padding-top: 8px; }
.lib-mon-pillset { display: flex; flex-wrap: wrap; gap: 6px; }

/* Monster Tags, Sub-types, Languages and Source run to dozens - or hundreds - of values
   each. As pill rows or a plain checkbox column they were paragraphs of controls to read
   past; as a searchable menu each is one control you type into. The selected values still
   show as chips, so a panel says what is filtering without being opened. */
.lib-multi { position: relative; display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.lib-multi-toggle { display: inline-flex; align-items: center; gap: 4px; }
.lib-multi-count { font-size: 12px; color: var(--text-muted); }
.lib-multi-chips { display: inline-flex; flex-wrap: wrap; gap: 4px; align-items: center; }
/* The menu floats clear of whatever is under it, so it states its own foreground colour
   rather than inheriting one from the panel it happens to open over. */
.lib-multi-menu {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 20;
  width: min(320px, 90vw); max-height: 300px; display: grid; gap: 4px;
  padding: 8px; border-radius: var(--radius-lg);
  background: var(--surface); border: 1px solid var(--border-strong); color: var(--text);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
}
.lib-multi-menu[hidden] { display: none; }
/* The shell's input rule covers text, number, select and textarea - not `type=search`, which
   is what this box has to be for the browser's own clear button. Left to the shell it came
   out as a white box with a grey system border in both themes. */
.lib-multi-search {
  box-sizing: border-box; width: 100%;
  appearance: none; -webkit-appearance: none;
  padding: 7px 10px; border-radius: var(--radius);
  background: var(--input-bg); border: 1px solid var(--border);
  color: var(--text); font-family: var(--font); font-size: 13px; line-height: 1.4;
}
.lib-multi-search::-webkit-search-decoration,
.lib-multi-search::-webkit-search-cancel-button,
.lib-multi-search::-webkit-search-results-button,
.lib-multi-search::-webkit-search-results-decoration { -webkit-appearance: none; }
.lib-multi-search:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.lib-multi-list { overflow-y: auto; max-height: 220px; display: grid; gap: 2px; }
.lib-multi-opt {
  display: flex; align-items: center; gap: 8px; padding: 5px 6px;
  border-radius: 6px; cursor: pointer; font-size: 13px;
}
.lib-multi-opt:hover { background: rgba(255, 255, 255, 0.06); }
.lib-multi-opt input { accent-color: var(--accent); cursor: pointer; }
.lib-multi-opt[hidden] { display: none; }
.lib-multi-none { padding: 6px; font-size: 12px; color: var(--text-faint); }
[data-theme="light"] .lib-multi-opt:hover { background: rgba(0, 0, 0, 0.05); }
[data-theme="light"] .lib-multi-menu { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); }

.lib-mon-actionbar { display: flex; align-items: center; gap: 10px; }
.lib-mon-actionbar .lib-count { margin-left: 0; margin-right: auto; }
.lib-mon-clear {
  padding: 7px 14px; border-radius: 999px; cursor: pointer;
  font-family: inherit; font-size: 13px; font-weight: 600;
  background: var(--surface); border: 1px solid var(--border); color: var(--text-muted);
  transition: transform 120ms cubic-bezier(0.23, 1, 0.32, 1), border-color 120ms cubic-bezier(0.23, 1, 0.32, 1);
}
.lib-mon-clear:hover { border-color: var(--accent); color: var(--accent); }
.lib-mon-clear:active { transform: scale(0.97); }
.lib-mon-clear:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Column headers, labelled once above the list instead of per row */
/* Zone rhythm: the type band, the filter panels and the list are three different
   zones, so they get more air between them than the controls column's default. */
.lib-mon-types { margin-bottom: 8px; }
.lib-mon-actionbar { margin-top: 6px; }
/* 15px, not 14px: a row is a bordered .lib-row, so its 14px padding starts 1px
   further in than an unbordered header's would and every column drifts. Matching
   the border here puts both content boxes at listWidth - 30. */
.lib-mon-headrow {
  display: grid; grid-template-columns: var(--lib-mon-cols); gap: 10px;
  margin-top: 4px; padding: 0 15px 2px;
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--text-faint);
}
/* Each header is a sort control. It keeps the header row's type so the list still
   reads as columns and not as a toolbar. */
.lib-mon-sort {
  display: flex; align-items: center; gap: 4px; min-width: 0; padding: 2px 0;
  background: none; border: none; cursor: pointer; text-align: left;
  font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit;
  transition: color 120ms cubic-bezier(0.23, 1, 0.32, 1);
}
.lib-mon-sort:hover { color: var(--accent); }
.lib-mon-sort[aria-sort="ascending"], .lib-mon-sort[aria-sort="descending"] { color: var(--accent); }
.lib-mon-sort:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.lib-mon-sort-arrow { font-size: 9px; }
.lib-mon-list { gap: 6px; }

/* Full-width skinny rows; the grid matches .lib-mon-headrow exactly */
.lib-mon-row > summary {
  display: grid; grid-template-columns: var(--lib-mon-cols); gap: 10px;
  align-items: center; padding: 10px 14px;
  transition: background-color 120ms cubic-bezier(0.23, 1, 0.32, 1);
}
.lib-mon-row > summary:hover { background: rgba(255, 255, 255, 0.04); }
.lib-mon-row > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: 9px; }
[data-theme="light"] .lib-mon-row > summary:hover { background: rgba(0, 0, 0, 0.04); }
.lib-mon-name { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; font-size: 14px; font-weight: 700; }
/* The name is the row's focal element; legendary/mythic/lair are facts about the
   stat block, so they sit a tier below it rather than as three loud gold pills. */
.lib-mon-name .lib-badge {
  font-size: 9px; letter-spacing: 0.06em; text-transform: uppercase; padding: 1px 6px;
  background: none; border: 1px solid var(--border-strong); color: var(--text-faint);
}
.lib-mon-cr { font-size: 13px; font-weight: 800; color: var(--accent); font-variant-numeric: tabular-nums; }
.lib-mon-cell { font-size: 12.5px; color: var(--text); min-width: 0; }
.lib-mon-cell.muted { color: var(--text-faint); }
.lib-mon-cell:last-of-type { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
/* A page that mounts the browser (Lib.mountMonsterBrowser) can add one control to each
   row's header; the header row and the rows gain the same extra column. */
.lib-mon-hasaction { --lib-mon-cols-action: var(--lib-mon-cols) var(--lib-mon-action-w, 150px); }
.lib-mon-hasaction .lib-mon-headrow,
.lib-mon-hasaction .lib-mon-row > summary { grid-template-columns: var(--lib-mon-cols-action); }
.lib-mon-action { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }

/* Expanded stat block: inset panel, one step down from the row surface */
.lib-statblock { padding: 14px; border-top: 1px solid var(--border); background: rgba(0, 0, 0, 0.15); }
.lib-sb-line { margin-bottom: 6px; font-size: 13px; line-height: 1.5; }
.lib-sb-line b { color: var(--accent); font-weight: 700; }
.lib-sb-vitals, .lib-sb-cr { display: flex; flex-wrap: wrap; gap: 18px; }
.lib-ability-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px; margin: 10px 0; }
.lib-ability {
  text-align: center; padding: 6px 2px; border-radius: 6px;
  background: var(--bg); border: 1px solid var(--border);
}
.lib-ability-name {
  font-size: 10px; font-weight: 700; letter-spacing: 0.04em; color: var(--text-faint);
}
.lib-ability-score { font-size: 14px; font-weight: 800; font-variant-numeric: tabular-nums; }
.lib-sb-section { margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--border); }
.lib-sb-section h4 {
  margin: 0 0 6px; font-size: 13px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.03em; color: var(--accent);
}
.lib-sb-intro { margin: 0 0 8px; font-size: 12.5px; line-height: 1.5; color: var(--text-faint); }
.lib-sb-entry { margin: 0 0 6px; font-size: 13px; line-height: 1.5; text-wrap: pretty; }
/* Lair actions, regional effects and flavour text print outside the stat block
   in the source books, so they sit on the row surface rather than the inset. */
.lib-mon-extra { padding: 12px 14px 14px; border-top: 1px solid var(--border); }
.lib-sb-provenance { margin-top: 10px; font-size: 12px; color: var(--text-faint); font-style: italic; }
.lib-mon-extra .lib-sb-section:first-child { margin-top: 0; padding-top: 0; border-top: none; }

[data-theme="light"] .lib-statblock { background: rgba(0, 0, 0, 0.05); }

@media (max-width: 720px) {
  /* Two columns: Name / CR, then Type / Size, then Environment / Source. The header
     row can't label a wrapped grid — but its headers are the sort controls now, so
     it becomes a wrapping sort bar rather than stepping aside entirely. */
  /* No row gap: the sort buttons already carry the 40px touch height every control
     on mobile gets, so a gap on top of it opens a hole when the bar wraps. */
  .lib-mon-headrow { display: flex; flex-wrap: wrap; gap: 0 12px; align-items: center; }
  .lib-mon-headrow::before { content: 'Sort'; color: var(--text-faint); }
  .lib-mon-row > summary { grid-template-columns: 1fr 1fr; }
  .lib-mon-hasaction .lib-mon-row > summary { grid-template-columns: 1fr 1fr; }
  .lib-mon-hasaction .lib-mon-action { grid-column: 1 / -1; }
  .lib-mon-cr { text-align: right; }
  .lib-mon-filters { grid-template-columns: 1fr; }
  .lib-ability-grid { grid-template-columns: repeat(3, 1fr); }
  .lib-mon-types { grid-template-columns: repeat(auto-fit, minmax(52px, 1fr)); }
  .lib-mon-adv .lib-filter-pills { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  .lib-mon-type-ic, .lib-mon-clear, .lib-mon-row > summary { transition: none; }
  .lib-mon-clear:active { transform: none; }
}

/* Checkbox toggles (spells filters, the encounter builder's homebrew toggle) */
.lib-check {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; font-weight: 600; color: var(--text-muted); cursor: pointer;
}
.lib-check input { accent-color: var(--accent); cursor: pointer; margin: 0; }
.lib-mon-actionbar { flex-wrap: wrap; }

/* Pager: above and below every list that runs past one page */
.lib-pager {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px;
  scroll-margin-top: 72px;
}
.lib-pager[hidden] { display: none; }
.lib-pager-range { font-size: 13px; color: var(--text-muted); margin-right: auto; }
.lib-pager-nav, .lib-pager-strip { display: inline-flex; align-items: center; gap: 4px; }
.lib-pager-btn {
  min-width: 34px; padding: 6px 10px; border-radius: 999px; font-size: 13px; font-weight: 600;
  font-family: inherit; line-height: 1.2; cursor: pointer;
  background: var(--surface); border: 1px solid var(--border); color: var(--text);
}
.lib-pager-btn:hover:not(:disabled):not(.on) { border-color: var(--accent); }
.lib-pager-btn.on { background: var(--accent-glow); border-color: var(--accent); color: var(--accent); cursor: default; }
.lib-pager-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.lib-pager-btn:focus-visible, .lib-pager-select:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lib-pager-gap { padding: 0 4px; color: var(--text-faint); }
.lib-pager-status { display: none; font-size: 13px; font-weight: 600; padding: 0 6px; color: var(--text-muted); }
.lib-pager-size { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; font-size: 13px; color: var(--text-muted); }
.lib-pager-select { cursor: pointer; }
@media (max-width: 480px) {
  /* prev / Page X of Y / next: the number strip and the jump-to-end buttons would overflow */
  .lib-pager-strip, .lib-pager-edge { display: none; }
  .lib-pager-status { display: inline; }
  .lib-pager-nav { width: 100%; justify-content: space-between; }
  .lib-pager-range { width: 100%; }
}

/* Light-theme hover overrides */
[data-theme="light"] .lib-back:hover { background: rgba(0,0,0,0.05); }
[data-theme="light"] .lib-card.disabled { opacity: 0.45; }
[data-theme="light"] .lib-chip { background: rgba(60,90,160,0.10); }
[data-theme="light"] .lib-cat-btn:hover { background: rgba(0,0,0,0.05); }

/* Tablet widths (721-900px) are touch screens, but the mobile sheet only enlarges controls up to 720px, which left the
   category tiles, filter pills, chips, pager and filter fields at 25-35px tall. Desktop is untouched. */
@media (min-width: 721px) and (max-width: 900px) {
  .lib-cat-btn, .lib-pill, button.lib-chip, .lib-pager-btn, .lib-pager-select, .lib-mon-sort, .lib-mon-clear,
  .library-shell input:not([type="checkbox"]):not([type="radio"]), .library-shell select, .lib-mon-field input, .lib-mon-field select { min-height: 36px; box-sizing: border-box; }
  .lib-pill, button.lib-chip, .lib-cat-btn { display: inline-flex; align-items: center; }
  .lib-check { min-height: 36px; }
}

/* Dark theme: the selected pill/chip/tile/page used --accent-glow (a 50%-alpha focus-ring gold), so its gold text measured
   2.9-3.1:1. --accent-soft (the token the badge rule above already uses) keeps the wash and brings the text to about 9:1.
   Light keeps the glow: its text passes there. */
:root:not([data-theme="light"]) .lib-pill.on, :root:not([data-theme="light"]) button.lib-chip.active,
:root:not([data-theme="light"]) .lib-cat-btn.on, :root:not([data-theme="light"]) .lib-pager-btn.on { background: var(--accent-soft); }

/* A grid column defaults to min-width:auto, so one long unbroken token (a Backgrounds proficiency list such as
   "animal_handling,_athletics,...") widened an opened row 31px past the phone viewport. */
.lib-row-body { grid-template-columns: minmax(0, 1fr); overflow-wrap: anywhere; }

/* Phone (UX pass round 3): filter chip walls become one scrolling row so results start higher; small text and
   pager buttons reach touch size. */
@media (max-width: 720px) {
  .lib-chip-row, .lib-filter-pills { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 6px; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
  .lib-chip-row::-webkit-scrollbar, .lib-filter-pills::-webkit-scrollbar { display: none; }
  .lib-chip-row > *, .lib-filter-pills > * { flex: none; }
  .lib-mon-types { display: flex; overflow-x: auto; gap: 10px; padding-bottom: 6px; scrollbar-width: none; }
  .lib-mon-types::-webkit-scrollbar { display: none; }
  .lib-mon-type { flex: none; min-width: 58px; }
  .lib-pager-btn { min-width: 40px; min-height: 40px; }
  .lib-mon-sort { min-height: 40px; padding: 2px 4px; }
  body .lib-mon-type-label, body .lib-mon-sort, body .lib-mon-sort-arrow, body .lib-ability-name, body .lib-badge { font-size: 11px; }
}

@media (max-width: 720px) { body .lib-mon-name .lib-badge { font-size: 11px; } }

/* Phone: a monster row is name + CR, type + size, then source + Add, instead of seven stacked cells. The habitat
   cell is in the stat block when the row opens. */
@media (max-width: 720px) {
  .lib-mon-summary { grid-template-columns: minmax(0, 1fr) auto; gap: 4px 12px; }
  .lib-mon-summary > .lib-mon-cell.muted:nth-child(5) { display: none; }
  .lib-mon-summary > .lib-mon-cell.muted:nth-child(6) { grid-column: 1; grid-row: 3; align-self: center; }
  .lib-mon-summary > .lib-mon-action { grid-column: 2; grid-row: 3; justify-self: end; }
}

/* Phone: the sort labels are chips with real width, not 22px text. */
@media (max-width: 720px) {
  .lib-mon-headrow { flex-wrap: wrap; gap: 8px; align-items: center; }
  .lib-mon-headrow .lib-mon-sort { min-width: 44px; min-height: 40px; padding: 0 14px; justify-content: center; border: 1px solid var(--border); border-radius: 999px; background: var(--surface); }
  .lib-mon-headrow .lib-mon-sort[aria-sort="ascending"], .lib-mon-headrow .lib-mon-sort[aria-sort="descending"] { border-color: var(--accent); }
}

/* A scrolling filter row fades at its right edge so it reads as "more this way". */
@media (max-width: 720px) {
  .lib-chip-row, .lib-filter-pills { padding-right: 28px; -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent); }
}

/* Phone: the class gallery card was ~420px (30 classes = 13,000px). The long blurb folds away; the name, the
   one-line tagline, the three stats and the View Class button stay. */
@media (max-width: 720px) {
  .library-shell .class-gallery-card { min-height: 0; }
  .library-shell .class-gallery-desc { display: none; }
  .library-shell .class-gallery-icon { width: 40px; height: 40px; }
  .library-shell .class-gallery-name { font-size: 26px; margin-top: 6px; }
  .library-shell .class-gallery-action { margin: 0 18px 16px; }
}

/* Tablets (721-900px). The monster filter panel has four columns, which leaves the challenge-range inputs
   64px wide ("Max 3"), so it takes two. In the encounter builder the Environment column was 50px wide and its
   header ran into Source: the column is dropped here, as it is on phones; the stat block still shows it. */
@media (min-width: 721px) and (max-width: 900px) {
  .lib-mon-filters { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .lib-mon-hasaction .lib-mon-headrow,
  .lib-mon-hasaction .lib-mon-row > summary { grid-template-columns: 2fr 0.7fr 1.1fr 1fr 1.2fr var(--lib-mon-action-w, 150px); }
  .lib-mon-hasaction .lib-mon-row > summary > .lib-mon-cell.muted:nth-child(5),
  .lib-mon-hasaction .lib-mon-headrow > :nth-child(5) { display: none; }
}

/* ── Rules view ── */
.rules-bar { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.rules-bar .rules-search { flex: 1 1 220px; max-width: none; width: auto; }
.rules-layout { display: grid; grid-template-columns: 17rem minmax(0, 1fr); gap: 24px; align-items: start; }
.rules-nav-wrap { position: sticky; top: 8px; max-height: calc(100vh - 24px); overflow-y: auto; }
.rules-nav-toggle { display: none; }
.rules-chapter { border-bottom: 1px solid var(--border, #3a4150); padding: 4px 0; }
.rules-chapter > summary { cursor: pointer; font-weight: 700; padding: 6px 0; }
.rules-chapter a { display: block; padding: 3px 0 3px 14px; color: var(--text-muted); text-decoration: none; font-size: 14px; }
.rules-chapter a:hover { color: var(--accent); }
.rules-chapter a.on { color: var(--accent); font-weight: 700; }
.rules-main { min-width: 0; line-height: 1.6; overflow-wrap: anywhere; }
.rules-main h2 { font-family: "Cormorant Garamond", serif; font-size: 24px; margin: 0 0 4px; }
.rules-main ul, .rules-main ol { padding-left: 22px; }
.rules-main h3.rules-sub { font-size: 18px; margin: 22px 0 6px; }
.rules-main h4.rules-sub { font-size: 15px; margin: 16px 0 4px; color: var(--text-muted); }
.rules-main p { margin: 8px 0; }
.rules-table caption { caption-side: top; text-align: left; font-weight: 700; padding: 0 0 4px; }
.rules-meta { color: var(--text-muted); font-size: 13px; }
.rules-main mark { background: var(--accent-soft); color: var(--accent); border-radius: 3px; padding: 0 2px; }
.rules-result { padding: 10px 0; border-bottom: 1px solid var(--border, #3a4150); }
.rules-result-title { font-weight: 700; color: var(--accent); }
.rules-result p { margin: 4px 0 0; }
.rules-table-wrap { overflow-x: auto; margin: 10px 0; }
.rules-table { border-collapse: collapse; font-size: 14px; min-width: 100%; }
.rules-table th, .rules-table td { border: 1px solid var(--border, #3a4150); padding: 5px 9px; text-align: left; vertical-align: top; }
.rules-table th { background: var(--surface); white-space: nowrap; }
.rules-table th, .rules-table td { overflow-wrap: normal; word-break: normal; }
.rules-attribution { margin-top: 32px; padding-top: 12px; border-top: 1px solid var(--border, #3a4150); font-size: 12px; color: var(--text-muted); }
@media (max-width: 700px) {
  .rules-layout { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .rules-nav-wrap { position: static; max-height: none; border: 1px solid var(--border, #3a4150); border-radius: 8px; padding: 0 12px; background: var(--surface); }
  .rules-nav-toggle { display: block; cursor: pointer; font-weight: 700; padding: 10px 0; }
  .rules-nav-wrap[open] > .rules-nav { max-height: 55vh; overflow-y: auto; padding-bottom: 8px; }
}
