/* ==========================================================================
   TAPHOU5E v2 — additions on top of ember.css
   Only things the design handoff did not cover: campaign screens, empty and
   loading states, the version switch, toasts and focus rings.
   Everything here uses tokens.css variables; no new colours are introduced.
   ========================================================================== */

/* ---------- The hidden attribute must actually hide.
   The UA rule is `[hidden] { display: none }`, which any author rule setting
   a display wins against on specificity. `.login-card` sets `display: flex`,
   so the create form rendered under the join form with the segmented switch
   toggling nothing. Asserting it once here means no future `display` can
   quietly break the attribute again. ---------- */
[hidden] { display: none !important; }

/* ---------- Focus. The handoff notes the current build has no focus ring
   at all, so every interactive element gets one. ---------- */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent-primary);
  outline-offset: 2px;
}

/* ---------- Shared chrome bits ---------- */
.world-row { display: flex; align-items: center; gap: var(--space-6); margin-top: var(--space-6); }
.world-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--hp-high); flex: none; }
.world-name {
  font-size: var(--fs-12); color: var(--text-secondary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.role-pill {
  margin-left: auto; flex: none;
  font-size: var(--fs-10); color: var(--accent-primary);
  border: 1px solid var(--border-strong); border-radius: 4px; padding: 1px 5px;
}
.nav-count { margin-left: auto; font-size: var(--fs-11); color: var(--text-tertiary); }
.nav-count.is-live {
  color: var(--accent-on); background: var(--accent-primary);
  border-radius: 4px; padding: 1px 5px; font-size: var(--fs-10);
}

.side-menu-item { text-decoration: none; }
.side-menu-item:hover { text-decoration: none; }

/* ---------- States ---------- */
.empty-state {
  display: flex; flex-direction: column; align-items: center; gap: var(--space-10);
  padding: var(--space-2xl) var(--space-lg); text-align: center;
  background: var(--bg-secondary); border: 1px dashed var(--border-default);
  border-radius: var(--radius-lg);
}
.empty-state h3 { font-family: var(--font-display); font-size: var(--fs-17); font-weight: 700; color: var(--text-primary); }
.empty-state p { font-size: var(--fs-13); color: var(--text-tertiary); max-width: 42ch; line-height: 1.55; }

.skeleton {
  background: var(--bg-secondary); border: 1px solid var(--border-default);
  border-radius: var(--radius-lg); height: 104px;
  animation: pulse 1.4s ease-in-out infinite;
}
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }

.error-banner {
  padding: var(--space-12) var(--space-14);
  background: var(--harm-bg); border: 1px solid var(--harm-border); color: var(--harm-ink);
  border-radius: var(--radius-lg); font-size: var(--fs-13); line-height: 1.5;
}

/* ---------- Toasts ---------- */
.toast-host {
  position: fixed; left: 50%; bottom: calc(var(--tab-bar-height) + var(--space-md));
  transform: translateX(-50%); z-index: 300;
  display: flex; flex-direction: column; gap: var(--space-sm); pointer-events: none;
}
.toast {
  padding: var(--space-10) var(--space-md);
  background: var(--bg-elevated); border: 1px solid var(--border-strong);
  border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
  font-size: var(--fs-13); color: var(--text-primary); max-width: 90vw;
}
.toast-error { border-color: var(--harm-border); color: var(--harm-ink); }
.toast-success { border-color: var(--heal-border); color: var(--heal-ink); }
@media (min-width: 900px) { .toast-host { bottom: var(--space-lg); } }

/* ---------- Summary rows (hub) ---------- */
.summary-card {
  display: flex; align-items: center; gap: var(--space-md);
  padding: var(--space-12) var(--space-14);
  background: var(--bg-secondary); border: 1px solid var(--border-default);
  border-radius: var(--radius-lg); text-decoration: none; color: inherit;
}
.summary-card:hover { border-color: var(--border-strong); background: var(--bg-elevated); text-decoration: none; }
.summary-card .body { flex: 1; min-width: 0; }
.summary-card .title { font-size: var(--fs-14); font-weight: 600; color: var(--text-primary); }
.summary-card .meta { font-size: var(--fs-12); color: var(--text-tertiary); margin-top: 2px; }
.summary-card .go { color: var(--text-tertiary); flex: none; }

.hub-tile { text-decoration: none; }
.hub-tile:hover { border-color: var(--border-strong); background: var(--bg-elevated); text-decoration: none; }
.character-card { text-decoration: none; color: inherit; display: flex; }

/* ---------- Campaigns ---------- */
.campaign-grid { display: grid; grid-template-columns: 1fr; gap: var(--space-12); }
@media (min-width: 900px) { .campaign-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1200px) { .campaign-grid { grid-template-columns: repeat(3, 1fr); } }

.campaign-card {
  display: flex; flex-direction: column; gap: var(--space-10);
  padding: var(--space-14);
  background: var(--bg-secondary); border: 1px solid var(--border-default);
  border-radius: var(--radius-lg); text-decoration: none; color: inherit;
}
.campaign-card:hover { border-color: var(--border-strong); background: var(--bg-elevated); text-decoration: none; }
.campaign-card .head { display: flex; align-items: flex-start; gap: var(--space-sm); }
.campaign-card h3 {
  flex: 1; min-width: 0;
  font-family: var(--font-display); font-size: var(--fs-17); font-weight: 700; color: var(--text-primary);
}
.campaign-card .summary {
  font-size: var(--fs-12); color: var(--text-tertiary); line-height: 1.55;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.campaign-card .stats { display: flex; gap: var(--space-md); margin-top: auto; padding-top: var(--space-6); }
.campaign-card .stats > div { display: flex; align-items: baseline; gap: 4px; }
.campaign-card .stats b { font-family: var(--font-mono); font-size: var(--fs-13); color: var(--text-primary); font-weight: 600; }
.campaign-card .stats span { font-size: var(--fs-10); color: var(--text-tertiary); letter-spacing: .08em; }

.status-pill {
  flex: none; font-family: var(--font-mono); font-size: var(--fs-9);
  letter-spacing: .1em; text-transform: uppercase;
  border: 1px solid var(--border-strong); border-radius: var(--radius-full);
  padding: 2px 8px; color: var(--text-tertiary);
}
.status-pill.is-active { color: var(--hp-high); border-color: var(--hp-high); }
.status-pill.is-planning { color: var(--accent-secondary); border-color: var(--accent-secondary); }
.status-pill.is-completed { color: var(--text-muted); }

/* A row players cannot see yet. Marks DM-only content so a DM always knows
   what is hidden, rather than guessing from the absence of a marker. */
.hidden-pill {
  flex: none; display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-10); color: var(--text-tertiary);
  border: 1px dashed var(--border-strong); border-radius: var(--radius-full);
  padding: 1px 7px;
}

/* ---------- Login additions ---------- */
.login-main {
  flex: 1; width: 100%; max-width: 440px; margin: 0 auto;
  padding: var(--space-lg);
  display: flex; flex-direction: column; gap: var(--space-18);
}
.login-footer { padding: var(--space-18) var(--space-lg); text-align: center; border-top: 1px solid var(--border-default); }
.login-footer p { font-size: var(--fs-11); color: var(--text-muted); }
.remember-row { display: flex; align-items: center; gap: var(--space-10); font-size: var(--fs-13); color: var(--text-secondary); cursor: pointer; }
.remember-row input { width: 18px; height: 18px; accent-color: var(--accent-primary); }
.btn-submit { padding: 14px 0; font-size: var(--fs-15); }
.switch-line { text-align: center; font-size: var(--fs-12); color: var(--text-tertiary); }
.switch-line a { color: var(--accent-primary); cursor: pointer; }
.hint { font-size: var(--fs-11); color: var(--text-tertiary); line-height: 1.5; }
.btn[aria-busy="true"] { opacity: .6; pointer-events: none; }

/* ---------- Not-yet-built destinations ----------
   Rendered as inert rows instead of links, so the shell shows the shape of the
   finished app without pointing anywhere that 404s. */
.is-pending { opacity: .55; cursor: default; pointer-events: none; }
.nav-soon {
  margin-left: auto; flex: none;
  font-family: var(--font-mono); font-size: var(--fs-9);
  letter-spacing: .1em; text-transform: uppercase; color: var(--text-muted);
  border: 1px solid var(--border-default); border-radius: var(--radius-full);
  padding: 1px 6px;
}
.hub-tile .nav-soon { margin-left: auto; }

/* ---------- Grid blowout fix ----------
   `1fr` is `minmax(auto, 1fr)`, so a grid item's min-content width sets a floor
   on its track. The four stat chips inside a roster card made that floor wider
   than half the viewport, pushing the page into horizontal scroll at 390px.
   Letting the items shrink below min-content is the fix; the tracks themselves
   are untouched, so the 4-up desktop grid still works. */
.party-roster > *,
.hub-tiles > *,
.campaign-grid > * { min-width: 0; }
.chip { min-width: 0; }
.card-name, .card-meta { min-width: 0; }

/* The handoff allows dropping SP below the breakpoint to keep the remaining
   chips legible at 2-up. */
@media (max-width: 899px) {
  .chip-sp { display: none; }
}

/* ==========================================================================
   Character sheet
   ember.css supplies .sheet-header/.sheet-id/.sheet-combat/.tab-bar, and the
   .sheet-nav rail + .pane only above 900px. These fill in the page scaffold
   and the mobile behaviour of both.
   ========================================================================== */
.sheet-page { display: flex; flex-direction: column; min-height: 100vh; min-height: 100dvh; min-width: 0; }
.sheet-nav { display: none; }                      /* tab rail is desktop-only */
.sheet-content { flex: 1; min-height: 0; min-width: 0; display: flex; }
.sheet-scroll {
  flex: 1; min-width: 0; overflow: auto;
  padding: var(--space-md) var(--space-12) calc(var(--tab-bar-height) + var(--space-lg));
  display: flex; flex-direction: column; gap: var(--space-sm);
}

/* Large HP readout in the sticky header */
.hp-big { display: flex; align-items: baseline; gap: 2px; }
.hp-big .current { font-size: var(--fs-24); font-weight: 600; color: var(--text-primary); }
.hp-big .max { font-size: var(--fs-14); color: var(--text-tertiary); }
.hp-big .temp { font-size: var(--fs-14); color: var(--hp-temp-text); margin-left: 4px; }

/* The amount field flexes, but is capped: unbounded it stretched the width of
   a 1280px viewport. */
.hp-ctl { max-width: 420px; }
.hp-ctl input {
  flex: 1; min-width: 0; max-width: 140px; height: 36px; text-align: center;
  background: var(--bg-primary); border: 1px solid var(--border-strong);
  border-radius: var(--radius-md); color: var(--text-primary);
  font-family: var(--font-mono); font-size: var(--fs-15);
}
.hp-ctl .btn { height: 36px; padding: 0 var(--space-md); }
.sheet-combat .chipline { max-width: 560px; }

/* Stats tab */
.ability-box .save { cursor: pointer; }
.ability-box .save:hover { color: var(--accent-primary); }
.temp-row { display: flex; align-items: center; gap: var(--space-10); }
.temp-input {
  width: 84px; padding: 8px 10px; text-align: center;
  background: var(--bg-tertiary); border: 1px solid var(--border-default);
  border-radius: var(--radius-md); color: var(--text-primary); font-size: var(--fs-14);
}
.temp-input:focus { outline: none; border-color: var(--accent-primary); }
.rest-row { display: flex; align-items: center; gap: var(--space-sm); flex-wrap: wrap; }
.rest-row .chip { flex: none; padding: 6px 12px; }
.condition-tag { cursor: pointer; font-family: inherit; }

.death-saves { display: flex; flex-direction: column; gap: var(--space-sm); }
.death-row { display: flex; align-items: center; gap: var(--space-sm); }
.death-row .label { font-size: var(--fs-12); color: var(--text-tertiary); width: 82px; }
.death-dot {
  width: 20px; height: 20px; border-radius: 50%; cursor: pointer;
  background: transparent; border: 2px solid var(--border-strong);
}
.death-dot.success.filled { background: var(--hp-high); border-color: var(--hp-high); }
.death-dot.failure.filled { background: var(--hp-low); border-color: var(--hp-low); }

/* Generic rows used by Actions / Spells / Inventory */
.stack { display: flex; flex-direction: column; gap: var(--space-6); }
.list-row {
  display: flex; align-items: center; gap: var(--space-md); cursor: pointer;
  padding: var(--space-10) var(--space-12);
  background: var(--bg-secondary); border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
}
.list-row:hover { border-color: var(--border-strong); background: var(--bg-elevated); }
.list-row .who { flex: 1; min-width: 0; }
.list-row .name { font-size: var(--fs-14); font-weight: 600; color: var(--text-primary); }
.list-row .meta { font-size: var(--fs-12); color: var(--text-tertiary); margin-top: 2px; }
.list-row .lvl { font-size: var(--fs-13); color: var(--text-secondary); flex: none; }
.chipline.wrap { flex-wrap: wrap; }
.chipline.wrap .chip, .slot-line .chip { flex: none; padding: 6px 12px; }
.prose { font-family: var(--font-body); font-size: var(--fs-13); color: var(--text-secondary); line-height: 1.6; white-space: pre-wrap; }

/* Detail: a bottom sheet on mobile, the right-hand pane on desktop */
.pane { position: relative; }
.pane-close { position: absolute; top: var(--space-sm); right: var(--space-sm); }
@media (max-width: 899px) {
  .pane.detail-open {
    position: fixed; inset: auto 0 0 0; z-index: 210; max-height: 76vh; overflow: auto;
    padding: var(--space-18) var(--space-md) calc(var(--tab-bar-height) + var(--space-md));
    background: var(--bg-secondary); border-top: 1px solid var(--border-strong);
    border-radius: var(--radius-xl) var(--radius-xl) 0 0; box-shadow: var(--shadow-lg);
  }
}
@media (min-width: 900px) {
  .sheet-nav { display: flex; }
  .sheet-scroll { padding: var(--space-18) var(--space-lg); }
  /* The rail carries the rest buttons on desktop, so the body row would duplicate them. */
  .rest-head, .rest-row { display: none; }
  .sheet-combat { padding: 0 var(--space-lg) var(--space-14); }
  .sheet-id { padding: 0 var(--space-lg); }
  .pane.detail-open {
    width: var(--pane-width); flex: none; overflow: auto;
    padding: var(--space-18) var(--space-20);
    background: var(--bg-sunken); border-left: 1px solid var(--border-subtle);
  }
}

/* Icon rail + tab rail (desktop only; ember.css sizes .rail and .sheet-nav) */
.rail-brand { font-family: var(--font-display); font-size: var(--fs-15); font-weight: 700; color: var(--accent-primary); }
.rail .icon-btn.is-current { background: var(--bg-hover); color: var(--accent-primary); }
.rail .icon-btn.is-pending { opacity: .4; cursor: default; pointer-events: none; }
.sheet-nav .nav-name { font-family: var(--font-display); font-size: var(--fs-17); font-weight: 700; line-height: 1.2; }
.sheet-nav .nav-meta { font-size: var(--fs-11); color: var(--text-tertiary); margin-top: 3px; }
.sheet-nav .nav-rests { margin-top: auto; display: flex; flex-direction: column; gap: var(--space-6); }

/* ---------- Modal ---------- */
.modal-host {
  position: fixed; inset: 0; z-index: 300; display: flex; align-items: flex-end;
  justify-content: center; background: rgba(10, 7, 5, .6);
}
.modal {
  width: 100%; max-width: 520px; max-height: 88vh; overflow: auto;
  background: var(--bg-secondary); border: 1px solid var(--border-default);
  border-radius: var(--radius-xl) var(--radius-xl) 0 0; box-shadow: var(--shadow-lg);
}
.modal-head {
  display: flex; align-items: center; gap: var(--space-sm);
  padding: var(--space-md) var(--space-md) var(--space-sm);
  border-bottom: 1px solid var(--border-subtle);
}
.modal-head h2 { flex: 1; font-family: var(--font-display); font-size: var(--fs-19); font-weight: 700; }
.modal-body { padding: var(--space-md); display: flex; flex-direction: column; gap: var(--space-14); }
.modal-actions { display: flex; gap: var(--space-sm); justify-content: flex-end; margin-top: var(--space-6); }
.modal-actions .btn { padding: 10px 18px; }
@media (min-width: 640px) {
  .modal-host { align-items: center; }
  .modal { border-radius: var(--radius-xl); }
}

/* ---------- Legacy engine modal ----------
   level-up-engine.js is shared with v1 and builds its own overlay: a .modal
   wrapping .modal-backdrop + .modal-content, where v2's .modal IS the card.
   Restyling that shape here is what lets the shared file stay untouched.
   Every custom property it uses is already an Ember token. */
.modal:has(> .modal-backdrop) {
  position: fixed; inset: 0; z-index: 320; display: flex;
  align-items: center; justify-content: center; padding: var(--space-md);
  width: auto; max-width: none; max-height: none; overflow: visible;
  background: none; border: 0; border-radius: 0; box-shadow: none;
}
.modal > .modal-backdrop { position: absolute; inset: 0; background: rgba(10, 7, 5, .6); }
.modal > .modal-content {
  position: relative; width: 100%; max-height: 88vh; overflow: auto;
  padding: var(--space-md);
  background: var(--bg-secondary); border: 1px solid var(--border-default);
  border-radius: var(--radius-xl); box-shadow: var(--shadow-lg);
}
.modal > .modal-content h2 {
  font-family: var(--font-display); font-size: var(--fs-19); font-weight: 700;
}
.modal > .modal-content label { min-width: 0; }
.modal > .modal-content .btn-primary {
  padding: 10px 18px; border-radius: var(--radius-md); border: 0; cursor: pointer;
  font: inherit; font-weight: 600;
  background: var(--accent-primary); color: var(--bg-primary);
}
.modal > .modal-content .btn-primary:disabled { opacity: .5; cursor: not-allowed; }

/* ---------- Campaign detail ---------- */
.campaign-head { display: flex; flex-direction: column; gap: var(--space-6); }
.campaign-head .title-row { display: flex; align-items: center; gap: var(--space-sm); }
.campaign-head h1 { font-family: var(--font-display); font-size: var(--fs-24); font-weight: 700; }
.campaign-tabs {
  display: flex; gap: 2px; overflow-x: auto; padding-bottom: 2px;
  border-bottom: 1px solid var(--border-subtle);
}
.campaign-tabs button {
  flex: none; padding: var(--space-sm) var(--space-12); border: none; background: transparent;
  color: var(--text-tertiary); font: inherit; font-size: var(--fs-13); cursor: pointer;
  border-bottom: 2px solid transparent; white-space: nowrap;
}
.campaign-tabs button:hover { color: var(--text-primary); }
.campaign-tabs button.is-active { color: var(--text-primary); font-weight: 600; border-bottom-color: var(--accent-primary); }
.campaign-tabs .count { font-family: var(--font-mono); font-size: var(--fs-10); color: var(--text-muted); margin-left: 5px; }

.row-actions { display: flex; align-items: center; gap: var(--space-6); flex: none; }
.tree-child { margin-left: var(--space-md); border-left: 1px solid var(--border-subtle); padding-left: var(--space-12); }
.beat-list { display: flex; flex-direction: column; gap: var(--space-6); margin-top: var(--space-sm); }
.check-row {
  display: flex; align-items: center; gap: var(--space-sm);
  padding: var(--space-6) var(--space-10); background: var(--bg-tertiary);
  border-radius: var(--radius-sm); font-size: var(--fs-12); color: var(--text-secondary);
}
.check-row .dc { font-family: var(--font-mono); color: var(--accent-secondary); font-weight: 600; }
.dm-note {
  padding: var(--space-10) var(--space-12); background: var(--accent-soft);
  border: 1px dashed var(--accent-soft-border); border-radius: var(--radius-md);
  font-family: var(--font-body); font-size: var(--fs-12); color: var(--text-secondary);
  line-height: 1.55; white-space: pre-wrap;
}
.dm-note-head { display: flex; align-items: center; gap: var(--space-6); margin-bottom: 4px; }
.dm-note-head .eyebrow { color: var(--accent-primary); }
.btn-tiny { padding: 4px 10px; font-size: var(--fs-11); }
.section-head .btn-tiny { flex: none; }
.dm-note-block { display: flex; flex-direction: column; gap: 2px; }
.campaign-tab-body { display: flex; flex-direction: column; gap: var(--space-sm); }

/* ---------- Compendium ---------- */
.compendium-controls { display: flex; align-items: center; gap: var(--space-sm); flex-wrap: wrap; }
.srd-search {
  flex: 1; min-width: 180px; padding: 9px 12px;
  background: var(--bg-tertiary); border: 1px solid var(--border-default);
  border-radius: var(--radius-md); color: var(--text-primary);
  font-family: var(--font-sans); font-size: var(--fs-14);
}
.srd-search:focus { outline: none; border-color: var(--accent-primary); }
.compendium-split { display: flex; flex-direction: column; gap: var(--space-md); min-height: 0; }
.srd-list { min-width: 0; }
.srd-list .list-row.is-selected { border-color: var(--accent-primary); background: var(--accent-soft); }
.srd-detail { min-width: 0; }
.srd-detail .statblock { padding: var(--space-md); background: var(--bg-secondary);
  border: 1px solid var(--border-default); border-radius: var(--radius-lg); }
.pane-actions { margin-top: var(--space-sm); }
@media (min-width: 900px) {
  .compendium-split { flex-direction: row; align-items: flex-start; }
  .srd-list { flex: 1; max-height: calc(100vh - 220px); overflow: auto; }
  .srd-detail { width: var(--pane-width); flex: none; max-height: calc(100vh - 220px); overflow: auto; }
}

/* ---------- Encounter tracker ----------
   ember.css supplies .init-row and its columns; these add the controls, the
   wrapping behaviour on a phone, and the inline condition editor. */
.tracker-controls { display: flex; flex-wrap: wrap; gap: var(--space-sm); }
.round-pill {
  font-size: var(--fs-11); letter-spacing: .1em; color: var(--accent-primary);
  border: 1px solid var(--accent-soft-border); border-radius: var(--radius-full); padding: 2px 10px;
}
.read-aloud {
  padding: var(--space-12) var(--space-14); background: var(--bg-elevated);
  border-left: 3px solid var(--accent-secondary); border-radius: var(--radius-md);
  font-style: italic;
}
.init-row { flex-wrap: wrap; }
.init-input {
  width: 46px; height: 30px; text-align: center; background: var(--bg-primary);
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  color: var(--text-primary); font-family: var(--font-mono); font-size: var(--fs-15); font-weight: 600;
}
.init-row.is-active .init-input { border-color: var(--accent-primary); color: var(--accent-primary); }
.init-name { cursor: pointer; }
.init-conditions, .init-detail { flex-basis: 100%; }
.init-detail { padding-top: var(--space-sm); border-top: 1px solid var(--border-subtle); }
.init-conditions { display: flex; flex-wrap: wrap; gap: 4px; }
.init-row.is-dead .init-actions, .init-row.is-dead .hp { opacity: .6; }
.btn:disabled { opacity: .45; pointer-events: none; }

@media (max-width: 899px) {
  /* The identity column is fixed at 180px in ember.css, which does not fit
     beside the HP rail and the controls on a phone. Let it share a line. */
  .init-id { width: auto; flex: 1 1 140px; }
  .init-hp { flex-basis: 100%; }
  .init-actions { margin-left: auto; }
}

/* ==========================================================================
   Review fixes
   ========================================================================== */

/* 1. Block-level anchors must not inherit the inline-link hover underline from
   ember.css. It propagates to every descendant, and on touch the hover state
   sticks after a tap, so a card stays underlined. */
.character-card, .character-card:hover,
.campaign-card, .campaign-card:hover,
.summary-card, .summary-card:hover,
.hub-tile, .hub-tile:hover,
a.list-row, a.list-row:hover,
.side-menu-item, .side-menu-item:hover,
.fab-item, .fab-item:hover { text-decoration: none; }

/* 4. An <input> carries an intrinsic width from its default size="20", and a
   flex item's min-width is auto, so the PIN boxes refused to shrink below about
   20 characters at 22px and pushed the login page into horizontal scroll. */
.pin-input { min-width: 0; }
.pin-inputs { max-width: 100%; }

/* 2 + 5. Floating action button: the topbar is desktop-only, so this carries
   the same actions below the breakpoint. */
.fab-wrap {
  position: fixed; right: var(--space-md); bottom: var(--space-md); z-index: 250;
  display: flex; flex-direction: column; align-items: flex-end; gap: var(--space-sm);
}
.fab {
  width: 56px; height: 56px; border-radius: var(--radius-full);
  background: var(--accent-primary); border: none; color: var(--accent-on);
  box-shadow: var(--shadow-lg); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: transform var(--transition-fast), background var(--transition-fast);
}
.fab:hover { background: var(--accent-primary-hover); }
.fab-wrap.open .fab { transform: rotate(45deg); }

/* One panel, not a stack of pills. Each pill sized itself to its own label,
   so ten actions read as ten unrelated bubbles of ten different widths. */
.fab-menu {
  display: flex; flex-direction: column; align-items: stretch;
  width: 232px; max-width: calc(100vw - var(--space-md) * 2);
  max-height: min(60vh, 460px); overflow-y: auto;
  padding: var(--space-6); border-radius: var(--radius-lg);
  background: var(--bg-secondary); border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-lg);
  /* visibility, not opacity alone: a transparent menu still sits in the tab
     order and the accessibility tree. Delaying it keeps the fade on close. */
  opacity: 0; visibility: hidden; pointer-events: none; transform: translateY(8px);
  transition: opacity var(--transition-fast), transform var(--transition-fast),
              visibility 0s linear var(--transition-fast);
}
.fab-wrap.open .fab-menu {
  opacity: 1; visibility: visible; pointer-events: auto; transform: translateY(0);
  transition: opacity var(--transition-fast), transform var(--transition-fast),
              visibility 0s linear 0s;
}
.fab-item {
  display: block; width: 100%; text-align: left;
  padding: 11px 12px; border-radius: var(--radius-sm);
  background: transparent; border: 0; box-shadow: none;
  color: var(--text-primary); font: inherit; font-size: var(--fs-13); font-weight: 500;
  cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* A hairline between rows, but not above the first: a panel with a line
   across its top edge looks like a rendering fault. */
.fab-item + .fab-item { box-shadow: inset 0 1px 0 var(--border-subtle); border-radius: 0; }
.fab-item + .fab-item:last-child { border-radius: 0 0 var(--radius-sm) var(--radius-sm); }
.fab-item.is-primary { color: var(--accent-primary); font-weight: 700; }
.fab-item:hover { background: var(--bg-hover); }
.fab-item.is-primary:hover { background: var(--bg-hover); }

/* The sheet and tracker have their own bottom furniture to clear. */
.sheet-page ~ .fab-wrap, .fab-wrap.above-tabs { bottom: calc(var(--tab-bar-height) + var(--space-md)); }

.topbar-actions { display: contents; }

@media (min-width: 900px) {
  /* Above the breakpoint the topbar already shows these -- unless there are
     too many to sit in a row, in which case the + button carries them here
     too and the topbar shows none. */
  .fab-wrap { display: none; }
  .fab-wrap.is-compact { display: flex; }
  .topbar-actions.is-collapsed { display: none; }
}

/* 3. Compendium on a phone: the detail sat under a list of a hundred-plus rows,
   so picking something looked like it did nothing. Show it as a bottom sheet. */
@media (max-width: 899px) {
  .srd-detail.has-detail {
    position: fixed; inset: auto 0 0 0; z-index: 240;
    max-height: 78vh; overflow: auto;
    padding: var(--space-md) var(--space-md) var(--space-xl);
    background: var(--bg-secondary); border-top: 1px solid var(--border-strong);
    border-radius: var(--radius-xl) var(--radius-xl) 0 0; box-shadow: var(--shadow-lg);
  }
  .srd-detail.has-detail .statblock { background: transparent; border: none; padding: 0; }
  .srd-detail:not(.has-detail) { display: none; }
  .srd-close { position: absolute; top: var(--space-sm); right: var(--space-sm); }
}
@media (min-width: 900px) { .srd-close { display: none; } }

/* ---------- Tracker parity with the classic version ---------- */

/* A combatant's assigned colour, as a left stripe. is-party uses the same
   channel, so an explicit colour wins. */
.init-row.has-color { border-left: 3px solid var(--row-color); }
.init-note {
  flex-basis: 100%; margin-top: 4px;
  font-family: var(--font-body); font-size: var(--fs-12); color: var(--text-tertiary);
  white-space: pre-wrap;
}
.ac-edit { cursor: pointer; border-bottom: 1px dotted var(--border-strong); }
.ac-edit:hover { color: var(--accent-primary); }

.enc-group > h2 {
  display: flex; align-items: center; gap: var(--space-sm); cursor: pointer;
  padding: var(--space-6) 0;
}
.enc-group .group-caret { color: var(--text-tertiary); font-size: var(--fs-12); }
.enc-group .group-count { margin-left: auto; font-size: var(--fs-11); color: var(--text-tertiary); }

/* Colour swatches, used both when adding and per row */
.swatches { display: flex; flex-wrap: wrap; gap: var(--space-sm); }
.swatch {
  width: 28px; height: 28px; border-radius: var(--radius-full); cursor: pointer;
  border: 2px solid transparent; box-shadow: inset 0 0 0 1px var(--border-strong);
}
.swatch.is-none { background: var(--bg-tertiary); position: relative; }
.swatch.is-none::after {
  content: ''; position: absolute; inset: 40% 12% auto; height: 2px;
  background: var(--text-muted); transform: rotate(-45deg);
}
.swatch.is-active { border-color: var(--text-primary); }

/* Add-monsters panel */
.modal-wide { max-width: 620px; }
.add-suggestions { display: flex; flex-direction: column; gap: 4px; max-height: 260px; overflow: auto; }
.add-suggestions .eyebrow { margin-top: var(--space-6); }
.add-suggestion {
  display: flex; align-items: center; gap: var(--space-sm); text-align: left;
  padding: var(--space-10) var(--space-12);
  background: var(--bg-tertiary); border: 1px solid var(--border-default);
  border-radius: var(--radius-md); color: var(--text-primary);
  font: inherit; font-size: var(--fs-14); cursor: pointer;
}
.add-suggestion:hover { background: var(--bg-hover); border-color: var(--border-strong); }
.add-suggestion .hidden-pill { margin-left: auto; }
.add-row { display: flex; gap: var(--space-sm); align-items: flex-start; }
.add-hp-rows { display: flex; flex-direction: column; gap: 6px; max-height: 240px; overflow: auto; }
.add-hp-row { display: flex; align-items: center; gap: var(--space-sm); }
.add-hp-row label { flex: 1; min-width: 0; font-size: var(--fs-13); color: var(--text-secondary); }
.add-hp-row input {
  width: 86px; flex: none; padding: 7px 10px; text-align: center;
  background: var(--bg-tertiary); border: 1px solid var(--border-default);
  border-radius: var(--radius-md); color: var(--text-primary); font-family: var(--font-mono);
}
#add-config.hidden { display: none; }
#add-search { width: 100%; }

/* ---------- DM panel ---------- */
.dm-row-exp { align-items: flex-start; }
.dm-row .exp-text { font-size: var(--fs-11); color: var(--text-tertiary); margin-top: 3px; }
.exp-grant { display: flex; gap: var(--space-sm); align-items: center; flex: none; }
.exp-grant input {
  width: 110px; min-width: 0; padding: 8px 10px; text-align: center;
  background: var(--bg-tertiary); border: 1px solid var(--border-default);
  border-radius: var(--radius-md); color: var(--text-primary); font-family: var(--font-mono);
}
.exp-grant input:focus { outline: none; border-color: var(--accent-primary); }
@media (max-width: 899px) {
  .dm-row { flex-wrap: wrap; }
  .dm-row .who { flex-basis: 100%; }
  .exp-grant { margin-left: auto; }
}

/* The party amount field carries a longer placeholder than the per-row ones. */
#party-exp { width: 170px; }

/* A colour marks a set of combatants, so it boxes the whole set. Rows inside
   the box drop their own stripe -- one border, not five. */
.colour-block {
  display: flex; flex-direction: column; gap: var(--space-6);
  padding: var(--space-6);
  border: 2px solid var(--block-color);
  border-radius: var(--radius-lg);
}
.colour-block .init-row.has-color { border-left: 1px solid var(--border-default); }

/* ---------- Row text must not wrap a character at a time ----------
   .list-row carries fixed-width columns either side of .who, so a long name
   had almost no room left and broke across four lines. Truncate instead, and
   below the breakpoint let the row wrap into two tidy lines. */
.list-row .name, .list-row .meta {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.party-hp { width: 120px; flex: none; }

@media (max-width: 899px) {
  .party-row { flex-wrap: wrap; row-gap: var(--space-sm); }
  /* Avatar and identity share the first line; HP and the buttons take the second. */
  .party-row .who { flex: 1 1 auto; }
  .party-row .party-hp { flex: 1 1 100%; width: auto; order: 3; }
  .party-row .row-actions { order: 4; margin-left: auto; }
}
.story-link {
  font-size: var(--fs-11); color: var(--text-tertiary);
  border: 1px solid var(--border-default); border-radius: var(--radius-full); padding: 2px 10px;
}
a.check-row { text-decoration: none; }
a.check-row:hover { text-decoration: none; background: var(--bg-hover); }

/* ---------- Share code ---------- */
.share-code {
  font-family: var(--font-mono); font-size: var(--fs-24); font-weight: 600;
  letter-spacing: .18em; text-align: center; color: var(--accent-primary);
  padding: var(--space-md); user-select: all;
  background: var(--bg-tertiary); border: 1px dashed var(--border-strong);
  border-radius: var(--radius-lg);
}

/* ---------- Creation / level-up wizard ----------
   Both wizards share this. Every step is sized to fit a 390px screen without
   the controls themselves scrolling, which is the whole reason v2 steps the
   form rather than repeating v1's single long page. */
.wizard { display: flex; flex-direction: column; gap: var(--space-md); }
.wizard-body { display: flex; flex-direction: column; gap: var(--space-14); min-width: 0; }

.wizard-steps {
  display: flex; align-items: center; gap: var(--space-6);
  list-style: none; margin: 0; padding: 0; min-width: 0;
}
.wizard-steps li {
  display: flex; align-items: center; gap: 6px; min-width: 0; flex: 1;
  font-size: var(--fs-11); color: var(--text-tertiary);
}
.wizard-steps li .dot {
  flex: none; width: 22px; height: 22px; border-radius: 50%;
  display: grid; place-items: center;
  font-family: var(--font-mono); font-size: var(--fs-11); font-weight: 600;
  background: var(--bg-tertiary); border: 1px solid var(--border-subtle);
}
.wizard-steps li .label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wizard-steps li.is-current { color: var(--text-primary); font-weight: 600; }
.wizard-steps li.is-current .dot { background: var(--accent-primary); color: var(--bg-primary); border-color: transparent; }
.wizard-steps li.is-done .dot { background: var(--bg-tertiary); color: var(--accent-primary); border-color: var(--accent-primary); }
/* Below the breakpoint only the current step is named; the dots carry the
   rest, which keeps four steps on one line at 390px. */
@media (max-width: 560px) {
  .wizard-steps li:not(.is-current) { flex: none; }
  .wizard-steps li:not(.is-current) .label { display: none; }
}

.wizard-nav { display: flex; gap: var(--space-sm); justify-content: flex-end; }
.wizard-nav .btn { min-width: 96px; justify-content: center; }
.wizard-blocker {
  font-size: var(--fs-12); color: var(--text-secondary);
  padding: 10px 12px; border-radius: var(--radius-md);
  background: var(--bg-tertiary); border: 1px solid var(--border-subtle);
}

.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-12); min-width: 0; }
.form-row > * { min-width: 0; }
@media (max-width: 560px) { .form-row { grid-template-columns: 1fr; } }

.method-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-6); min-width: 0; }
@media (max-width: 460px) { .method-grid { grid-template-columns: 1fr; } }
.method-tile {
  display: flex; flex-direction: column; gap: 2px; align-items: flex-start;
  min-width: 0; text-align: left; cursor: pointer;
  padding: 10px 12px; border-radius: var(--radius-md);
  background: var(--bg-tertiary); border: 1px solid var(--border-subtle); color: inherit; font: inherit;
}
.method-tile .title { font-weight: 600; font-size: var(--fs-13); }
.method-tile .blurb { font-size: var(--fs-11); color: var(--text-tertiary); }
.method-tile.is-on { border-color: var(--accent-primary); background: var(--bg-secondary); }

.ability-assign { display: flex; flex-direction: column; gap: var(--space-6); }
.ability-assign-row {
  display: grid; grid-template-columns: 42px minmax(0, 1fr) auto;
  align-items: center; gap: var(--space-sm); min-width: 0;
  padding: 8px 10px; border-radius: var(--radius-md);
  background: var(--bg-tertiary); border: 1px solid var(--border-subtle);
}
.ability-assign-row .ab { font-size: var(--fs-11); color: var(--text-tertiary); font-weight: 600; }
.ability-assign-row select, .ability-assign-row input {
  width: 100%; min-width: 0; padding: 7px 9px; border-radius: var(--radius-sm);
  background: var(--bg-secondary); border: 1px solid var(--border-subtle);
  color: var(--text-primary); font: inherit;
}
.score-readout { display: flex; align-items: baseline; gap: 6px; white-space: nowrap; }
.score-readout .racial { font-size: var(--fs-11); color: var(--accent-primary); }
.score-readout .total { font-size: var(--fs-16); font-weight: 700; }
.score-readout .mod { font-size: var(--fs-11); color: var(--text-tertiary); }

.stepper { display: flex; align-items: center; gap: var(--space-6); }
.stepper button {
  flex: none; width: 34px; height: 34px; border-radius: var(--radius-sm);
  background: var(--bg-secondary); border: 1px solid var(--border-subtle);
  color: var(--text-primary); font: inherit; font-size: var(--fs-16); cursor: pointer;
}
.stepper button:disabled { opacity: .35; cursor: not-allowed; }
.stepper .val { min-width: 2ch; text-align: center; font-size: var(--fs-16); font-weight: 700; }

.budget {
  font-size: var(--fs-12); color: var(--text-secondary);
  padding: 8px 12px; border-radius: var(--radius-md);
  background: var(--bg-tertiary); border: 1px solid var(--border-subtle);
}
.budget .mono { font-size: var(--fs-16); font-weight: 700; color: var(--text-primary); }
.budget.is-over { border-color: var(--danger); }
.budget.is-over .mono { color: var(--danger); }

.chip-row { display: flex; flex-wrap: wrap; gap: var(--space-6); }
.chip-row .chip {
  cursor: pointer; padding: 7px 12px; border-radius: 999px;
  background: var(--bg-tertiary); border: 1px solid var(--border-subtle);
  color: var(--text-secondary); font: inherit; font-size: var(--fs-12);
}
.chip-row .chip.is-on { border-color: var(--accent-primary); color: var(--text-primary); }

.review-head h3 { font-family: var(--font-display); font-size: var(--fs-21); font-weight: 700; }
.review-head .meta { font-size: var(--fs-12); color: var(--text-tertiary); margin-top: 2px; }
.review-scores { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-6); }
@media (max-width: 460px) { .review-scores { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.review-score {
  display: flex; flex-direction: column; gap: 1px; min-width: 0;
  padding: 10px; border-radius: var(--radius-md);
  background: var(--bg-tertiary); border: 1px solid var(--border-subtle);
}
.review-score .ab { font-size: var(--fs-9); color: var(--text-tertiary); font-weight: 600; }
.review-score .total { font-size: var(--fs-21); font-weight: 700; line-height: 1.1; }
.review-score .mod { font-size: var(--fs-11); color: var(--text-secondary); }
.review-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-6); }
@media (max-width: 460px) { .review-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.review-grid > div {
  display: flex; flex-direction: column; gap: 1px; min-width: 0;
  padding: 10px; border-radius: var(--radius-md); background: var(--bg-tertiary);
}
.review-grid .k { font-size: var(--fs-9); color: var(--text-tertiary); text-transform: uppercase; letter-spacing: .04em; }
.review-grid .v { font-size: var(--fs-16); font-weight: 700; }

.pick-list { display: flex; flex-direction: column; gap: var(--space-6); }
.pick-row {
  display: flex; flex-direction: column; gap: 1px; align-items: flex-start;
  min-width: 0; text-align: left; cursor: pointer; width: 100%;
  padding: 12px 14px; border-radius: var(--radius-md);
  background: var(--bg-tertiary); border: 1px solid var(--border-subtle); color: inherit; font: inherit;
}
.pick-row .name { font-weight: 600; font-size: var(--fs-14); }
.pick-row .meta { font-size: var(--fs-11); color: var(--text-tertiary); text-transform: capitalize; }
.pick-row.is-on { border-color: var(--accent-primary); background: var(--bg-secondary); }

/* ---------- Level-up ---------- */
.levelup-banner {
  display: flex; align-items: center; gap: var(--space-sm); width: 100%;
  text-align: left; cursor: pointer; font: inherit; color: inherit;
  padding: 12px 14px; margin-bottom: var(--space-12);
  border-radius: var(--radius-md);
  background: var(--bg-tertiary); border: 1px solid var(--accent-primary);
}
.levelup-banner .body { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.levelup-banner .title { font-weight: 700; font-size: var(--fs-14); }
.levelup-banner .meta {
  font-size: var(--fs-11); color: var(--text-tertiary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.levelup-banner .go { margin-left: auto; color: var(--accent-primary); font-size: var(--fs-17); }

.hp-choice-row {
  display: flex; align-items: center; gap: var(--space-sm); min-width: 0; flex-wrap: wrap;
  padding: 10px; border-radius: var(--radius-md);
  background: var(--bg-tertiary); border: 1px solid var(--border-subtle);
}
.hp-choice-row .ab { font-size: var(--fs-11); color: var(--text-tertiary); font-weight: 600; flex: none; }
.hp-choice-actions { display: flex; gap: var(--space-6); margin-left: auto; min-width: 0; }
.hp-choice-actions .btn { padding: 7px 12px; font-size: var(--fs-12); white-space: nowrap; }

.asi-block { display: flex; flex-direction: column; gap: var(--space-sm); }
.asi-block + .asi-block { margin-top: var(--space-md); }

.seg { display: flex; gap: 2px; padding: 3px; border-radius: var(--radius-md); background: var(--bg-tertiary); }
.seg button {
  flex: 1; min-width: 0; padding: 8px 10px; cursor: pointer; font: inherit;
  font-size: var(--fs-12); font-weight: 600; border: 0; border-radius: var(--radius-sm);
  background: transparent; color: var(--text-tertiary);
}
.seg button.is-on { background: var(--bg-secondary); color: var(--text-primary); }

/* ---------- Press-and-hold card menus ----------
   The card is the control, so it must not offer iOS's own selection callout
   or leave text highlighted behind the menu that opens. */
.holdable, .holdable * {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  /* Without this, a long press on a row still shows the blue tap flash and,
     on some Android builds, starts a selection before user-select applies. */
  -webkit-tap-highlight-color: transparent;
}
/* Inputs inside a holdable list still need selection and a caret -- but only
   the field itself. Letting the whole row select is what let a long press
   highlight the text, raise the keyboard, and leave a stray selection that
   the next tap dismissed instead of doing what it was aimed at. */
.holdable input, .holdable textarea {
  -webkit-user-select: auto; user-select: auto;
  -webkit-touch-callout: default;
}

.card-menu { display: flex; flex-direction: column; gap: 2px; }
.card-menu-item {
  display: flex; flex-direction: column; gap: 1px; align-items: flex-start;
  width: 100%; text-align: left; min-width: 0; cursor: pointer;
  padding: 13px 14px; border-radius: var(--radius-md);
  background: transparent; border: 0; color: var(--text-primary);
  font: inherit; font-size: var(--fs-14);
}
.card-menu-item:hover { background: var(--bg-hover); }
.card-menu-item .label { font-weight: 600; }
.card-menu-item .hint { font-size: var(--fs-11); color: var(--text-tertiary); }
.card-menu-item.is-danger .label { color: var(--danger); }

/* The support menu's coffee row is a real anchor -- a button calling
   window.open would be blocked, since the menu closes before the action runs
   and the popup then falls outside the click's gesture. Being an anchor, the
   global `a` rules would repaint and underline it on hover, so they are
   answered here rather than by making the row a button again. */
a.card-menu-item, a.card-menu-item:hover { color: var(--text-primary); text-decoration: none; }

/* A hint that the gesture exists, for the pointer that can hover. */
@media (hover: hover) {
  .holdable [data-holdable]:hover { cursor: context-menu; }
}

/* ---------- Sheet editing ----------
   The sheet was read-only everywhere but hit points; these are the controls
   that close that. All of them sit inside a row that is itself a button, so
   each stops its own click from opening the detail pane behind it. */
.slot-chip, .charge, .prep-toggle, .qty button {
  font: inherit; cursor: pointer; border: 1px solid var(--border-subtle);
  background: var(--bg-tertiary); color: var(--text-primary);
}
.slot-chip.is-spent, .charge.is-spent { opacity: .45; }
.slot-chip { min-width: 58px; }

.charge {
  flex: none; padding: 5px 9px; border-radius: var(--radius-sm);
  font-size: var(--fs-11); font-weight: 600;
}

.prep-toggle {
  flex: none; padding: 5px 9px; border-radius: var(--radius-sm);
  font-size: var(--fs-9); font-weight: 700; letter-spacing: .06em;
  color: var(--text-tertiary);
}
.prep-toggle.is-on {
  background: var(--accent-primary); border-color: var(--accent-primary);
  color: var(--accent-on);
}

.qty { display: flex; align-items: center; gap: var(--space-6); flex: none; }
.qty button {
  width: 30px; height: 30px; border-radius: var(--radius-sm);
  font-size: var(--fs-14); line-height: 1;
}
.qty .mono { min-width: 2ch; text-align: center; font-weight: 700; }

/* A paragraph that opens an editor needs to look like it does something,
   without becoming a button-shaped block of prose. */
.prose.editable { cursor: pointer; }
.prose.editable:hover { color: var(--text-primary); }

/* The SRD lookup that sits above an add form's own fields. */
.srd-search { position: relative; }
.srd-results { display: flex; flex-direction: column; gap: 2px; }
.srd-hit {
  text-align: left; padding: 9px 11px; border-radius: var(--radius-sm);
  background: var(--bg-tertiary); border: 1px solid var(--border-subtle);
  color: var(--text-primary); font: inherit; font-size: var(--fs-13); cursor: pointer;
}
.srd-hit:hover { background: var(--bg-hover); border-color: var(--accent-primary); }

/* ---------- The logo ----------
   Beside the wordmark on the login screen, and again beside it in the sidebar
   and the mobile drawer.

   The source art is black on transparent, so on the dark shell it has to be
   inverted to white and on the light one left alone. The theme selectors
   follow tokens.css: an explicit data-theme, or the system preference when no
   attribute is set. theme.js REMOVES the attribute for "system", so
   `[data-theme="light"]` on its own would never match the common case. */
:root { --logo-filter: brightness(0) invert(1); }
[data-theme="light"] { --logo-filter: none; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) { --logo-filter: none; }
}

.login-header h1 {
  display: flex; align-items: center; justify-content: center; gap: var(--space-sm);
}
.login-logo { height: 36px; width: auto; filter: var(--logo-filter); }
@media (min-width: 640px) { .login-logo { height: 48px; } }

/* The brand lockup in the sidebar and the drawer. flex rather than an inline
   image so the mark sits on the wordmark's optical centre rather than its
   baseline. */
.sidebar-brand .brand,
.side-menu-header .brand {
  display: flex; align-items: center; gap: 9px;
}
.brand-logo { height: 22px; width: auto; flex: none; filter: var(--logo-filter); }

/* The sidebar foot carries the same items as the drawer, so they need the
   drawer's row styling at a size that suits a narrower column. */
.sidebar-foot { display: flex; flex-direction: column; gap: var(--space-6); }
.sidebar-foot .side-menu-item {
  display: flex; align-items: center; gap: var(--space-sm);
  padding: 9px 10px; border-radius: var(--radius-md);
  font-size: var(--fs-12); color: var(--text-secondary); cursor: pointer;
}
.sidebar-foot .side-menu-item:hover { background: var(--bg-hover); color: var(--text-primary); }
.sidebar-foot .side-menu-item-danger { color: var(--danger); }

/* ---------- Check outcomes ----------
   What happens on a pass or a fail was collected by the form and stored, and
   then never shown -- which is the only reason you write one down. */
.check-block { display: flex; flex-direction: column; gap: 3px; }
.check-block + .check-block { margin-top: var(--space-6); }
.outcome {
  display: flex; gap: var(--space-sm); align-items: baseline; min-width: 0;
  padding: 7px 10px 7px 12px; border-radius: var(--radius-sm);
  background: var(--bg-tertiary); font-size: var(--fs-12); line-height: 1.5;
  border-left: 2px solid var(--border-strong);
}
.outcome .eyebrow { flex: none; }
.outcome.is-pass { border-left-color: var(--success); }
.outcome.is-fail { border-left-color: var(--danger); }
@media (max-width: 560px) {
  .outcome { flex-direction: column; gap: 1px; }
}

/* ---------- Subclass rows ----------
   One box per subclass: its name, and a line saying what it plays like. */
.subclass-list { display: flex; flex-direction: column; gap: var(--space-6); }

.subclass-row {
  display: flex; flex-direction: column; gap: 2px; align-items: flex-start;
  width: 100%; min-width: 0; text-align: left; cursor: pointer; font: inherit;
  padding: 12px 14px; border-radius: var(--radius-md);
  background: var(--bg-tertiary);
  border: 1px solid var(--border-subtle);
  border-left: 2px solid transparent;
  color: var(--text-primary);
  transition: border-color var(--transition-fast), background var(--transition-fast);
}
.subclass-row:hover { border-color: var(--border-strong); }
.subclass-row.is-on {
  background: var(--bg-secondary);
  border-color: var(--accent-primary);
  border-left-color: var(--accent-primary);
}
.subclass-row .name { font-weight: 600; font-size: var(--fs-14); }
.subclass-row .summary { font-size: var(--fs-12); color: var(--text-tertiary); line-height: 1.5; }
