feat(reader): immersive chrome, slide-over drawers, tri-state PDF pointer mode

Phase 1 of the reader redesign:

- Reading surface is edge-to-edge; top/bottom bars overlay
  translucently (backdrop-blur) instead of reserving insets, killing
  the inset-coordination bug class entirely. Chrome auto-hides after
  2.5s of pointer inactivity (chrome_behavior setting finally wired:
  auto-hide / always-visible; legacy values map to auto-hide). Pointer
  activity inside page iframes keeps it awake; Esc toggles.
- TOC / Settings / Bookmarks become slide-over drawers with a scrim
  (z-50, full-height, safe-area aware), replacing the dockable-panel
  system and its window-shade headers. Only one drawer opens at a
  time; Esc or scrim click closes.
- Bottom bar is contextual: reflowable keeps nav/slider/progress/TOC;
  fixed-layout row adds Fit Page/Width select, zoom cluster,
  magnifier (now shows active state), Double Page Spread toggle, and
  a Smart | Pan | Text segmented control replacing the cryptic
  two-state icon. Smart = text-aware drag; Text = selection-only
  (manual smart-detect off); Pan = force pan. Choice persists via
  pdf_interaction_mode (new setting + foliate 29bc958 'text' mode).
- Settings drawer: Behavior (chrome, progress mode), Appearance with
  18 Kindle-style theme swatches (single source of truth from
  THEME_COLORS), Typography, Layout — each scoped by format.
- Keyboard: t/s/b open TOC/settings/bookmark, Esc closes drawers
  before toggling chrome, shortcuts skip form inputs; both slider
  rows tracked correctly (no duplicate-ID lookups).
- Topbar: Back, title, add-bookmark, bookmarks drawer, Aa settings;
  chrome follows user theme.
This commit is contained in:
2026-08-14 14:59:51 -04:00
parent ba95cc3e8b
commit 612f888683
8 changed files with 678 additions and 445 deletions
+59 -20
View File
@@ -725,7 +725,7 @@
border: 1px solid var(--wood-border);
}
/* ---------- Reader ---------- */
/* ---------- Reader chrome & drawers ---------- */
.reader-icon {
display: block;
fill: none;
@@ -735,32 +735,71 @@
stroke-linejoin: round;
}
.dockable-panel {
.drawer-scrim {
position: fixed;
inset: 0;
background-color: rgba(0, 0, 0, 0.45);
z-index: 45;
}
.reader-drawer {
position: fixed;
top: 0;
bottom: 0;
width: 340px;
max-width: calc(100vw - 2rem);
background-color: var(--bg-secondary);
z-index: 50;
display: flex;
flex-direction: column;
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
}
.reader-drawer.left {
left: 0;
border-right: 1px solid var(--border);
}
.reader-drawer.right {
right: 0;
border-left: 1px solid var(--border);
}
.reader-drawer-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.75rem 1rem;
border-bottom: 1px solid var(--border);
transition: max-height 0.2s ease-out;
flex-shrink: 0;
}
.reader-drawer-body {
flex: 1;
overflow-y: auto;
padding: 1rem;
}
.reader-seg {
display: inline-flex;
border: 1px solid var(--border);
border-radius: 0.5rem;
overflow: hidden;
}
.dockable-panel.panel-collapsed .panel-content {
display: none;
.reader-seg button {
padding: 0.25rem 0.6rem;
font-size: 0.75rem;
line-height: 1.25rem;
}
.panel-header {
user-select: none;
.reader-seg button.active {
background-color: #2563eb;
color: #ffffff;
}
.panel-header:hover {
background-color: var(--surface-hover);
.theme-swatch {
height: 2.25rem;
border-radius: 0.5rem;
border: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: center;
}
.panel-container {
background-color: var(--bg-secondary);
border-right: 1px solid var(--border);
width: 320px;
max-width: calc(100vw - 1rem);
max-height: 100%;
overflow-y: auto;
}
#right-sidebar .panel-container {
border-right: none;
border-left: 1px solid var(--border);
.theme-swatch:hover {
border-color: #3b82f6;
}
/* ---------- Series stacked covers ---------- */