/* Booklist — the Kohlrabi design language, in a bookish register.
   Warm-paper light theme, ink-blue accent, soft radii. No build step.
   Themes switch via [data-theme] on <html>; every color goes through variables. */

/* Mobile app feel: no pinch/double-tap zoom, no visible page scrollbar.
   (iOS 10+ ignores user-scalable=no in the viewport meta, so the meta
   alone never blocked pinch zoom. touch-action: pan-x pan-y allows
   scrolling on both axes but kills the pinch-zoom gesture; the
   gesturestart handler in js/app.js is the fallback for older iOS.) */
html { touch-action: pan-x pan-y; }
@media (pointer: coarse) {
  html { scrollbar-width: none; -ms-overflow-style: none; }
  html::-webkit-scrollbar { display: none; }
}
:root, [data-theme="paper"] {
  color-scheme: light;
  --bg: #faf4ed;
  --surface: #fffaf3;
  --surface-2: #f2e9e1;
  --surface-raised: #fffdf8;
  --ink: #1c1c1e;
  --ink-strong: #000000;
  --muted: #6c6c70;
  --subtle: #8e8e93;
  --line: #dfdad9;
  --line-strong: #cecacd;
  --accent: #1e5a8a;
  --accent-hover: #174a72;
  --accent-soft: #dce9f5;
  --gold: #a86a12; /* v0.2.10: darkened for 3.0 contrast on paper */
  --gold-soft: #fae9cc;
  --warn: #8a5a10;
  --iris: #7c6cf0;
  --iris-soft: #e6e2fd;
  --danger: #cf2a1e; /* v0.2.10: darkened for 4.5 contrast on paper */
  --danger-soft: #fbe3e1;
  --on-accent: #ffffff;
  --focus-ring: rgba(30,90,138,.22);
  --shadow-color: rgba(28,28,30,.10);
  --shadow-soft-color: rgba(28,28,30,.07);
  --backdrop: rgba(0,0,0,.32);
  --nav-bg: rgba(255,253,248,.82);
  --shadow: 0 14px 34px var(--shadow-color);
  --shadow-soft: 0 6px 18px var(--shadow-soft-color);
  --radius-sm: 14px;
  --radius-md: 20px;
  --radius-lg: 22px;
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-serif: Georgia, "Times New Roman", serif;
}
[data-theme="ember"] {
  color-scheme: dark;
  --bg: #221a13;
  --surface: #2c231a;
  --surface-2: #3a2e21;
  --surface-raised: #342a1f;
  --ink: #f2e9da;
  --ink-strong: #fffdf8;
  --muted: #bfae95;
  --subtle: #937f60;
  --line: #4a3b2b;
  --line-strong: #5c4b37;
  --accent: #e2a557;
  --accent-hover: #c98f42;
  --accent-soft: rgba(226,165,87,.16);
  --gold: #e2a557;
  --gold-soft: rgba(226,165,87,.16);
  --warn: #e8b96a;
  --iris: #9d8ff5;
  --iris-soft: rgba(157,143,245,.18);
  --danger: #ef7d68;
  --danger-soft: rgba(239,125,104,.16);
  --on-accent: #241a10;
  --focus-ring: rgba(226,165,87,.28);
  --shadow-color: rgba(0,0,0,.40);
  --shadow-soft-color: rgba(0,0,0,.30);
  --backdrop: rgba(0,0,0,.60);
  --nav-bg: rgba(44,35,26,.85);
}
[data-theme="sage"] {
  color-scheme: light;
  --bg: #f4f2e9;
  --surface: #faf8ef;
  --surface-2: #e9e5d3;
  --surface-raised: #fffdf6;
  --ink: #20241f;
  --ink-strong: #0c0e0b;
  --muted: #66685e;
  --subtle: #8a8c7e;
  --line: #dbd7c4;
  --line-strong: #c8c3ac;
  --accent: #2e6b4e;
  --accent-hover: #245741;
  --accent-soft: #d9e9dd;
  --gold: #b57a1c; /* v0.2.10: darkened for 3.0 contrast on sage */
  --gold-soft: #f4e5c4;
  --warn: #8a5a10;
  --iris: #6c5ce7;
  --iris-soft: #e4e0fb;
  --danger: #c23829; /* v0.2.10: darkened for 4.5 contrast on sage */
  --danger-soft: #f9dfda;
  --on-accent: #ffffff;
  --focus-ring: rgba(46,107,78,.22);
  --shadow-color: rgba(32,36,31,.10);
  --shadow-soft-color: rgba(32,36,31,.07);
  --backdrop: rgba(20,24,18,.36);
  --nav-bg: rgba(250,248,239,.85);
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--ink);
  -webkit-text-size-adjust: 100%;
}
.app { max-width: 520px; margin: 0 auto; min-height: 100dvh; }

/* ===== Icons (inline Tabler sprite) ===== */
.icon { width: 1.25em; height: 1.25em; flex: none; vertical-align: -.22em; }
.icon.sm { width: 16px; height: 16px; }
.icon.tab-ico { width: 22px; height: 22px; }
.icon.logo { width: 26px; height: 26px; color: var(--accent); }
.e-ico { width: 42px; height: 42px; color: var(--subtle); margin-bottom: 10px; }

/* ===== Top bar (fixed, translucent, iOS-26-safe) ===== */
header.topbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 30;
  max-width: 520px; margin: 0 auto;
  height: calc(54px + env(safe-area-inset-top));
  padding: env(safe-area-inset-top) 4px 0;
  display: grid; grid-template-columns: auto minmax(0,1fr) auto; align-items: center;
  border-bottom: 1px solid var(--line);
  background-color: var(--bg);
  background-image: linear-gradient(var(--nav-bg), var(--nav-bg));
  -webkit-backdrop-filter: blur(20px) saturate(1.6);
  backdrop-filter: blur(20px) saturate(1.6);
}
header.topbar .gearbtn {
  grid-column: 3; justify-self: end; margin-right: 6px;
  border: 0; background: none; color: var(--ink);
  padding: 10px; min-width: 44px; min-height: 44px; cursor: pointer; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
}
header.topbar .gearbtn .icon { width: 22px; height: 22px; }
header.topbar .gearbtn:active { color: var(--accent); }
/* Book-page back arrow: lives in the fixed top bar at top left (no floating
   circle). Hidden on every other tab. */
header.topbar .backbtn {
  grid-column: 1; justify-self: start; margin-left: 6px;
  border: 0; background: none; color: var(--ink);
  padding: 10px; min-width: 44px; min-height: 44px; cursor: pointer; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
}
header.topbar .backbtn .icon { width: 22px; height: 22px; }
header.topbar .backbtn:active { color: var(--accent); }
header.topbar .backbtn[hidden] { display: none; }
header.topbar .title {
  position: absolute; left: 0; right: 0; top: env(safe-area-inset-top); bottom: 0;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  margin: 0; padding: 0 56px;
  font-family: var(--font-serif);
  font-size: 21px; font-weight: 700; letter-spacing: -.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; pointer-events: none;
}

/* ===== Bottom nav (fixed, translucent) ===== */
nav.tabs {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  max-width: 520px; margin: 0 auto;
  display: grid; grid-template-columns: repeat(3, minmax(0, 104px)); justify-content: center;
  padding: 8px 14px calc(8px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
  background-color: var(--bg);
  background-image: linear-gradient(var(--nav-bg), var(--nav-bg));
  -webkit-backdrop-filter: blur(20px) saturate(1.6);
  backdrop-filter: blur(20px) saturate(1.6);
}
nav.tabs button {
  border: 0; background: none; padding: 6px 0; cursor: pointer;
  color: var(--muted); font-size: 10px; font-weight: 400;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  font-family: var(--font-sans);
}
nav.tabs button.active { color: var(--accent); font-weight: 700; }

/* The `hidden` attribute must always win: component display rules
 * (e.g. .btn's inline-flex) otherwise override it and show elements
 * that JS explicitly hid (the sign-in sheet's second button). */
[hidden] { display: none !important; }

main { padding: calc(54px + env(safe-area-inset-top) + 12px) 12px calc(96px + env(safe-area-inset-bottom)); }
.tab { display: none; }
.tab.active { display: block; }

/* ===== Cards ===== */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-soft);
  padding: 16px;
  margin-bottom: 12px;
}
.card h3 { margin: 0 0 10px; font-size: 17px; font-weight: 700; letter-spacing: -.02em; }
.muted { color: var(--muted); font-size: 13px; }

/* ===== Buttons ===== */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%;
  min-height: 52px; padding: 0 22px;
  border: 0; border-radius: 999px;
  background: var(--accent); color: var(--on-accent);
  font-family: var(--font-sans); font-size: 16px; font-weight: 700;
  cursor: pointer;
}
.btn:active { background: var(--accent-hover); }
a.btn { text-decoration: none; }
.btn.secondary {
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line-strong);
}
.btn.secondary:active { background: var(--surface-2); }
.btn.small { width: auto; min-height: 44px; padding: 0 18px; font-size: 14px; white-space: nowrap; }
.btn.danger { background: var(--danger-soft); color: var(--danger); }

/* ===== Forms ===== */
label.field { display: block; color: var(--muted); font-size: 12px; font-weight: 700; margin: 10px 0 4px; }
input[type=text], input[type=email], input[type=password], input[type=number], input[type=tel], input[type=date], select, textarea {
  width: 100%; min-height: 44px; padding: 8px 12px;
  font-size: 16px; font-family: var(--font-sans); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface-raised); outline: none;
}
input:focus, select:focus, textarea:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--focus-ring); }
/* Kohlrabi-style short-link field: bare URL in a readonly monospace box. */
.mono-field {
  flex: 1; min-width: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 13px; color: var(--ink);
  background: var(--surface-raised); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 10px 12px;
  white-space: nowrap; overflow-x: auto;
}
.row { display: flex; gap: 8px; align-items: center; }
.row.between { justify-content: space-between; }

/* ===== Embed section picker (Settings → Now page) ===== */
.check-list { display: flex; flex-direction: column; gap: 2px; margin: 6px 0 4px; }
.check-row {
  display: flex; align-items: center; gap: 12px;
  min-height: 44px; padding: 6px 2px; margin: 0;
  font-size: 15px; color: var(--ink); cursor: pointer;
}
.check-row input[type=checkbox] {
  width: 22px; height: 22px; flex: none; margin: 0;
  accent-color: var(--accent); cursor: pointer;
}
textarea.mono-area {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px; line-height: 1.55;
  white-space: pre; overflow: auto;
  min-height: 0; resize: vertical;
}

/* ===== Segmented control ===== */
.seg {
  display: flex; background: var(--surface-2); border-radius: 999px; padding: 3px 14px 3px 3px; gap: 2px;
  overflow-x: auto; scrollbar-width: none;
}
.seg::-webkit-scrollbar { display: none; }
.seg button {
  flex: 1 0 auto; border: 0; background: none; border-radius: 999px;
  min-height: 44px; font-family: var(--font-sans);
  font-size: 13px; font-weight: 750; color: var(--muted); cursor: pointer;
  white-space: nowrap; padding: 0 10px;
}
.seg button[aria-pressed="true"] { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-soft); }

/* ===== Book rows ===== */
.book-row {
  display: flex; gap: 12px; align-items: center;
  padding: 10px 2px; border-bottom: 1px solid var(--line);
  cursor: pointer; width: 100%; border-left: 0; border-right: 0; border-top: 0;
  background: none; text-align: left; font-family: var(--font-sans); color: var(--ink);
}
.book-row:last-child { border-bottom: 0; }
/* Cover frame: the frame is a plain element with the fixed 2:3 box — plain
   elements hold aspect-ratio everywhere (WebKit ignores it on replaced
   <img> flex items), so every cover card is exactly the same size no
   matter the source image's dimensions. The image (or placeholder) inside
   just fills the frame. Width overrides per context (.lane-item, .hero,
   .sheet-cover, .book-hero) keep working: they size the frame. */
.cover {
  display: block; width: 52px; aspect-ratio: 2/3; flex: none;
  border-radius: 6px; background: var(--surface-2);
  border: 1px solid var(--line); overflow: hidden;
}
.cover > img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.cover > .cover-ph {
  width: 100%; height: 100%; display: grid; place-items: center;
  font-family: var(--font-serif); font-size: 20px; color: var(--subtle);
}

/* Barcode scan viewfinder */
.scan-wrap {
  position: relative;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: #111;
  aspect-ratio: 4 / 3;
}
.scan-wrap video { width: 100%; height: 100%; object-fit: cover; display: block; }
.scan-frame {
  position: absolute;
  inset: 22% 12%;
  border: 2px solid var(--accent);
  border-radius: 12px;
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.45);
  pointer-events: none;
}

/* Shelf picker (add-to-shelf flow) */
.shelf-pick { display: flex; flex-direction: column; gap: 8px; }
.shelf-opt {
  display: flex; gap: 12px; align-items: center; text-align: left;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface-raised); color: var(--ink);
  padding: 12px 14px; cursor: pointer; font-family: var(--font-sans); width: 100%;
}
.shelf-opt:active { border-color: var(--accent); }
.shelf-opt .icon { color: var(--accent); width: 22px; height: 22px; flex: none; }
.shelf-opt strong { display: block; font-size: 15px; }
.shelf-opt small { display: block; color: var(--muted); font-size: 12px; margin-top: 2px; }
.book-row .t { font-weight: 700; font-size: 14px; letter-spacing: -.01em; line-height: 1.3; }
.book-row .a { font-size: 12px; color: var(--muted); margin-top: 2px; }
.book-row .meta { font-size: 12px; color: var(--muted); margin-top: 4px; }
.mini-bar { height: 6px; background: var(--surface-2); border-radius: 4px; overflow: hidden; margin-top: 6px; }
.mini-bar .fill { height: 100%; background: var(--accent); border-radius: 4px; }
.stars-line { display: flex; gap: 2px; margin-top: 5px; }
.stars-line svg { width: 14px; height: 14px; }
.stars-line .on { color: var(--gold); }
.stars-line .on svg { fill: currentColor; }
.stars-line .off { color: var(--line-strong); }
.stars-inline { display: inline-flex; gap: 1px; vertical-align: -.15em; }
.stars-inline svg { width: 13px; height: 13px; }
.stars-inline .on { color: var(--gold); }
.stars-inline .on svg { fill: currentColor; }
.stars-inline .off { color: var(--line-strong); }
.quick-add {
  flex: none; display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--line-strong); background: var(--surface);
  border-radius: 999px; min-height: 44px; padding: 0 14px;
  font-size: 13px; font-weight: 750; color: var(--accent); cursor: pointer;
  font-family: var(--font-sans);
}
.quick-add.added { color: var(--muted); }

/* ===== Library: segmented shelf control + sort ===== */
.seg { display: flex; background: var(--surface-2); border-radius: 12px; padding: 3px; gap: 2px; margin: 12px 0 0; }
.segbtn {
  flex: 1; border: none; background: transparent; border-radius: 9px; padding: 9px 2px;
  font-size: 12.5px; font-weight: 600; color: var(--muted); cursor: pointer;
  font-family: var(--font-sans); white-space: nowrap;
}
.segbtn[aria-pressed="true"] { background: var(--surface-raised); color: var(--ink); box-shadow: 0 1px 4px var(--shadow-soft-color); }
/* The generic .seg button rule above sets border-radius:999px with higher
   specificity than .segbtn — force the rounded rectangle on both segmented
   controls (Library filter, book-page shelf picker) with an id-qualified
   selector that wins. */
#lib-seg.seg button, #bk-seg.seg button { border-radius: 9px; }
/* Search field with an inline clear (×) button. */
.searchwrap { position: relative; }
.searchwrap input[type=text] { width: 100%; padding-right: 34px; }
.search-clear {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  width: 26px; height: 26px; border: 0; border-radius: 999px;
  background: transparent; color: var(--muted); font-size: 18px; line-height: 1;
  cursor: pointer; font-family: var(--font-sans);
}
.search-clear:hover { background: var(--line); color: var(--ink); }
/* Small "Today" shortcut under a date input. */
.datelink {
  border: 0; background: none; padding: 4px 0 0; margin: 0;
  color: var(--accent, #1e5a8a); font-size: 13px; font-weight: 600;
  cursor: pointer; font-family: var(--font-sans);
}
.sortrow { display: flex; align-items: center; justify-content: space-between; margin-top: 10px; }
.sortcount { font-size: 13px; color: var(--muted); }
/* Offline sync note: a quiet line under the topbar, only while signed in
 * with no connection. */
.sync-note {
  font-size: 12px; color: var(--muted); text-align: center;
  padding: 7px 16px; line-height: 1.45;
}
.sortbtn {
  border: 1px solid var(--line); background: var(--surface); border-radius: 20px;
  padding: 7px 12px; font-size: 13px; font-weight: 600; color: var(--ink);
  cursor: pointer; font-family: var(--font-sans); white-space: nowrap;
}
.sortbtn .muted { color: var(--muted); font-weight: 400; }
.sortopts { display: flex; flex-direction: column; }
.sortopt {
  display: flex; align-items: center; gap: 12px; width: 100%; border: none; background: none;
  padding: 12px 4px; font-size: 15px; color: var(--ink); cursor: pointer;
  font-family: var(--font-sans); text-align: left; border-top: 1px solid var(--line);
}
.sortopt:first-child { border-top: none; }
.radio { width: 20px; height: 20px; border-radius: 50%; border: 2px solid var(--line-strong); flex: none; position: relative; }
.radio.on { border-color: var(--accent); }
.radio.on::after { content: ""; position: absolute; inset: 4px; border-radius: 50%; background: var(--accent); }
.shelf-tag {
  display: inline-block; font-size: 11px; font-weight: 700;
  color: var(--muted); background: var(--surface-2);
  border-radius: 999px; padding: 3px 10px; margin-top: 6px;
}
.goalbar { margin: 10px 0; }
.goalbar .lbl { display: flex; justify-content: space-between; font-size: 13px; font-weight: 700; margin-bottom: 5px; }
.goalbar .track { height: 12px; background: var(--surface-2); border-radius: 7px; overflow: hidden; }
.goalbar .fill { height: 100%; background: var(--accent); border-radius: 7px; transition: width .2s; }

/* ===== Star rating input ===== */
.stars { display: flex; gap: 4px; margin: 6px 0 0; }
.stars button {
  border: 0; background: none; cursor: pointer; padding: 4px;
  color: var(--line-strong); line-height: 1;
}
.stars button svg { width: 32px; height: 32px; }
.stars button.lit { color: var(--gold); }
.stars button.lit svg { fill: currentColor; }
/* A tiny pop when a star is tapped — the feedback the old "Rated N stars"
 * toast used to carry, without interrupting the reader. */
.stars button.pop svg { animation: se-star-pop .3s ease-out; }
@keyframes se-star-pop { 0% { transform: scale(1); } 40% { transform: scale(1.4); } 100% { transform: scale(1); } }
@media (prefers-reduced-motion: reduce) {
  .stars button.pop svg { animation: none; }
  .toast { transition: none; }
}

/* ===== Numeric text inputs (pages read, goal) ===== */
.pages-input { width: 120px; text-align: center; font-size: 20px; font-weight: 800; }

/* ===== Friends / feed ===== */
.avatar {
  width: 44px; height: 44px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent);
  font-weight: 800; font-size: 17px;
}
.avatar.me { background: var(--accent); color: var(--on-accent); }
.feed-item { display: flex; gap: 10px; padding: 10px 2px; border-bottom: 1px solid var(--line); }
.feed-item:last-child { border-bottom: 0; }
.feed-item .avatar { width: 36px; height: 36px; font-size: 14px; }
.feed-item .txt { font-size: 13px; line-height: 1.45; }
.feed-item .txt strong { font-weight: 750; }
.feed-item .txt .em { font-family: var(--font-serif); font-style: italic; }
.feed-item .when { font-size: 11px; color: var(--subtle); margin-top: 2px; }

/* ===== Modal dialog (centered, dimmed backdrop) ===== */
.sheet-backdrop {
  position: fixed; inset: 0; z-index: 40;
  background: var(--backdrop);
  display: flex; align-items: center; justify-content: center;
  padding: 20px 16px;
}
.sheet {
  position: relative;
  background: var(--surface); color: var(--ink);
  border-radius: var(--radius-lg);
  width: 100%; max-width: 520px; max-height: 100%; overflow-y: auto;
  padding: 20px 18px;
  box-shadow: 0 24px 70px var(--shadow-color);
}
.sheet h2 { margin: 0 0 4px; padding-right: 96px; font-size: 22px; font-weight: 700; letter-spacing: -.02em; font-family: var(--font-serif); }
.sheet .byline { color: var(--muted); font-size: 13px; margin-bottom: 10px; }
.sheet .desc { font-size: 14px; line-height: 1.6; color: var(--ink); }
.sheet .desc.clamp {
  display: -webkit-box; -webkit-line-clamp: 5; -webkit-box-orient: vertical; overflow: hidden;
}
.sheet-close {
  position: absolute; top: 12px; right: 12px;
  width: 44px; height: 44px; border-radius: 50%; border: 0;
  background: var(--surface-2); color: var(--muted);
  display: grid; place-items: center; cursor: pointer;
}
.sheet-share {
  position: absolute; top: 12px; right: 64px;
  width: 44px; height: 44px; border-radius: 50%; border: 0;
  background: var(--surface-2); color: var(--muted);
  display: grid; place-items: center; cursor: pointer;
}
.sheet-share:active { background: var(--accent-soft); color: var(--accent); }
/* ===== Book page (full page replacing the old centered book sheet) ===== */
/* Shares the shared-review design language: centered cover, serif display
   title, clean Author · Year byline, Started · Finished summary line,
   centered star display, and the review as an italic quote block. */
.book-tools { display: flex; justify-content: flex-end; margin: 2px 2px 4px; }
.book-share {
  width: 44px; height: 44px; border-radius: 50%; border: 0;
  background: var(--surface-2); color: var(--muted);
  display: grid; place-items: center; cursor: pointer;
}
.book-share:active { background: var(--accent-soft); color: var(--accent); }
/* Started/Finished pair: stacked vertically — side-by-side native date
   inputs overlap at phone widths (each pill insists on its own width).
   Labels sit above their inputs; a plain flex column with gap. */
.date-pair { display: flex; flex-direction: column; gap: 2px; }
.date-pair > div { min-width: 0; }
/* The book-page review box: roomy enough to draft in, grows from there. */
.review-box { min-height: 140px; }
/* Book-page progress feedback (mockup-book-progress): one quiet line under
   the pages input. */
.prog-line { font-size: 12px; color: var(--muted); margin-top: 6px; }
/* Goal-complete line (mockup-goal-complete): one quiet bookish line under
   the bar when the goal is met. Persistent card line, not a repeating toast. */
.complete-line { margin: 10px 0 0; font-size: 13px; color: var(--muted); line-height: 1.5; }
.complete-line strong { color: var(--ink); }
.book-hero { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 0; margin: 4px 0 20px; }
.book-hero .book-cover-slot .cover { width: 168px; margin-bottom: 18px; box-shadow: 0 10px 28px rgba(28,28,30,.14); }
/* The cover slot is a button (tap for full size): keep it visually identical. */
button.book-cover-slot { border: 0; background: none; padding: 0; cursor: pointer; font: inherit; text-align: inherit; }
.sheet-cover-lg { padding: 10px 4px 14px; }
.sheet-cover-lg .cover { width: min(72vw, 300px); margin: 0 auto; }
.book-hero .book-cover-slot .cover-ph { font-size: 64px; }
.book-id { min-width: 0; width: 100%; }
.book-title {
  margin: 0 0 6px; font-family: var(--font-serif); font-size: 30px; font-weight: 700;
  line-height: 1.25; overflow-wrap: break-word; hyphens: auto; text-wrap: balance;
}
.book-byline { font-size: 15px; color: var(--muted); overflow-wrap: break-word; margin: 0 0 4px; }
.book-meta { font-size: 13px; margin-top: 4px; }
.book-dates { font-size: 13px; color: var(--subtle); margin: 8px 0 0; }
.book-hero .stars-line { justify-content: center; margin-top: 10px; }
.book-hero .stars-line .icon { width: 20px; height: 20px; }
/* Review quote in the shared-review language: accent left border, italic serif. */
.book-review {
  margin: 18px 0 0; padding: 2px 0 2px 18px; border-left: 2px solid var(--accent);
  color: var(--ink); font-family: var(--font-serif); font-size: 16px; line-height: 1.65;
  font-style: italic; white-space: pre-wrap; text-align: left;
}
/* ===== Form dialogs (Add a person, profile, manual add, scan): header row
   with an inline close instead of the floating circle. ===== */
.sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 0 0 4px; }
.sheet-head h2 { margin: 0; padding-right: 0; }
.sheet-close-inline {
  flex: none; width: 44px; height: 44px; margin: -6px -8px -6px 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 0; border-radius: 10px; color: var(--muted);
  cursor: pointer;
}
.sheet-close-inline:active { color: var(--ink); background: var(--surface-2); }
/* ===== Toast (share fallbacks) ===== */
.toast {
  position: fixed; left: 50%; bottom: calc(110px + env(safe-area-inset-bottom));
  transform: translateX(-50%) translateY(16px);
  background: var(--ink); color: var(--bg);
  font-family: var(--font-sans); font-size: 13px; font-weight: 600; line-height: 1.5;
  padding: 12px 18px; border-radius: 999px; max-width: 88vw; text-align: center;
  opacity: 0; transition: opacity .3s, transform .3s; z-index: 60; pointer-events: none;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.chip-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.chip {
  font-size: 11px; font-weight: 700; color: var(--accent);
  background: var(--accent-soft); border-radius: 999px; padding: 5px 10px;
}
.sheet-cover { display: flex; gap: 14px; margin-bottom: 12px; }
.sheet-cover .cover { width: 110px; align-self: flex-start; } /* flex-start: the tall text column must not stretch the cover (WebKit stretches aspect-ratio imgs in a row) */

/* ===== Two-tap destructive remove (book sheet) ===== */
.remove-zone { margin-top: 26px; padding-top: 16px; border-top: 1px solid var(--line); text-align: center; }
.remove-link {
  border: 0; background: none; cursor: pointer;
  font-family: var(--font-sans); font-size: 13px; font-weight: 600;
  color: var(--subtle); padding: 12px 16px;
}
.remove-link:active { color: var(--muted); }
.remove-link.armed { color: var(--danger); font-weight: 800; }

/* ===== Standalone share view (#s= links) ===== */
.share-page {
  min-height: 100dvh; display: flex; align-items: center; justify-content: center;
  padding: 24px 16px calc(24px + env(safe-area-inset-bottom));
  background: var(--bg);
}
.share-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: var(--shadow);
  max-width: 420px; width: 100%; padding: 28px 24px; text-align: center;
}
.share-brand {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  font-family: var(--font-serif); font-size: 20px; font-weight: 700;
  margin-bottom: 20px; letter-spacing: -.01em;
}
.share-brand .icon { width: 26px; height: 26px; color: var(--accent); }
.share-cover {
  width: 150px; aspect-ratio: 2/3; object-fit: cover; display: block;
  border-radius: 10px; border: 1px solid var(--line); background: var(--surface-2);
  margin: 0 auto 16px;
}
.share-cover.fallback { display: grid; place-items: center; color: var(--subtle); }
.share-cover.fallback .icon { width: 56px; height: 56px; }
.share-title { font-family: var(--font-serif); font-size: 24px; font-weight: 700; letter-spacing: -.02em; margin: 0 0 6px; line-height: 1.25; }
.share-author { color: var(--muted); font-size: 14px; margin-bottom: 12px; }
.share-pill {
  display: inline-block; font-size: 12px; font-weight: 800;
  color: var(--accent); background: var(--accent-soft);
  border-radius: 999px; padding: 6px 14px; margin-bottom: 12px;
}
.share-card .stars-line { justify-content: center; margin-bottom: 14px; }
.share-card .stars-line svg { width: 22px; height: 22px; }
.share-review {
  background: var(--surface-raised); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 16px;
  font-family: var(--font-serif); font-style: italic; font-size: 15px;
  line-height: 1.6; text-align: left; color: var(--ink); margin-bottom: 20px;
}
.linklike { border: 0; background: none; color: var(--accent); font-weight: 700; font-size: 13px; cursor: pointer; padding: 6px 0; min-height: 44px; font-family: var(--font-sans); }

/* ===== Settings ===== */
.theme-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.theme-opt {
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface-raised); color: var(--ink);
  padding: 12px 10px; cursor: pointer;
  display: flex; flex-direction: column; gap: 8px; align-items: flex-start;
  font-family: var(--font-sans);
}
.theme-opt[aria-pressed="true"] { border-color: var(--accent); box-shadow: 0 0 0 2px var(--focus-ring); }
.theme-opt .nm { font-size: 13px; font-weight: 750; }
.theme-opt .swatches { display: flex; gap: 4px; }
.theme-opt .sw { width: 22px; height: 22px; border-radius: 7px; border: 1px solid rgba(0,0,0,.14); }

/* ===== Ratings distribution ===== */
.dist-row { display: flex; align-items: center; gap: 10px; margin: 8px 0; font-size: 13px; }
.dist-row .k { width: 76px; display: flex; gap: 2px; color: var(--gold); flex: none; }
.dist-row .k svg { width: 13px; height: 13px; fill: currentColor; }
.dist-row .track { flex: 1; height: 10px; background: var(--surface-2); border-radius: 6px; overflow: hidden; }
.dist-row .fill { height: 100%; background: var(--gold); border-radius: 6px; }
.dist-row .v { width: 28px; text-align: right; color: var(--muted); font-weight: 700; }

/* ===== Misc ===== */
.empty { padding: 40px 20px; text-align: center; color: var(--muted); font-size: 14px; }
.empty strong { display: block; color: var(--ink); font-size: 20px; font-weight: 700; margin-bottom: 8px; letter-spacing: -.02em; font-family: var(--font-serif); }
.empty-state { padding: 40px 20px; text-align: center; }
.empty-state .icon.xl { width: 44px; height: 44px; color: var(--muted); opacity: .55; }
.empty-title { font-family: var(--font-serif); font-size: 20px; font-weight: 700; letter-spacing: -.02em; color: var(--ink); margin: 10px 0 6px; }
/* ===== Profile ===== */
.avatar img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; display: block; }
.avatar-upload { position: relative; flex: none; cursor: pointer; background: none; border: 0; padding: 0; font: inherit; color: inherit; }
.avatar-upload .avatar { width: 64px; height: 64px; font-size: 24px; }
.avatar-badge {
  position: absolute; right: -4px; bottom: -4px;
  width: 24px; height: 24px; border-radius: 50%;
  background: var(--accent); color: var(--on-accent);
  display: grid; place-items: center;
  border: 2px solid var(--surface);
}
.avatar-badge .icon { width: 13px; height: 13px; }

/* ===== Auth form ===== */
.code-input { font-size: 28px; font-weight: 800; letter-spacing: .3em; text-align: center; }

/* ===== Now-page theme picker (Profile tab): horizontal scroll-snap row of
   visual preview cards. Native momentum scrolling; scrollbars hidden. ===== */
.theme-pick {
  display: flex; gap: 12px; overflow-x: auto;
  scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch;
  padding: 4px 2px 10px; margin: 0 -2px;
  scrollbar-width: none; -ms-overflow-style: none;
}
.theme-pick::-webkit-scrollbar { display: none; }
.now-theme {
  scroll-snap-align: start; flex: 0 0 auto; width: 152px;
  border: 0; background: none; padding: 0; cursor: pointer;
  font-family: var(--font-sans);
}
.now-theme-mock {
  display: block; border-radius: 14px; padding: 12px 10px;
  border: 2px solid transparent; box-sizing: border-box; min-height: 148px;
}
.now-theme[aria-pressed="true"] .now-theme-mock {
  border-color: var(--accent); box-shadow: 0 0 0 2px var(--focus-ring);
}
.now-theme-name {
  display: block; margin-top: 7px; font-size: 13px; font-weight: 700;
  color: var(--ink); text-align: center;
}
.now-theme[aria-pressed="true"] .now-theme-name { color: var(--accent); }
.now-theme:disabled { opacity: .6; cursor: default; }
.local-note {
  font-size: 12px; color: var(--muted); background: var(--surface-2);
  border-radius: var(--radius-sm); padding: 10px 12px; line-height: 1.5;
}

/* Profile bio: one tappable thing. The rendered bio is the edit target;
   the textarea only appears while editing. */
.bio-view { line-height: 1.55; cursor: pointer; border-radius: 8px; }
.bio-view .bio-empty { color: var(--muted); }
/* Public Now page link: one short line, never a wrapped raw URL. */
.now-url {
  display: block; margin-top: 6px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Settings account: the identity row is the disclosure toggle; everything
   else hides behind it until tapped. */
.acct-head {
  display: flex; gap: 12px; align-items: center; width: 100%;
  background: none; border: 0; padding: 0; margin: 0 0 4px;
  font: inherit; color: inherit; text-align: left; cursor: pointer;
}
.acct-caret { color: var(--muted); flex: none; transition: transform .15s ease; }
.acct-head[aria-expanded="true"] .acct-caret { transform: rotate(180deg); }
#acct-details { padding-top: 8px; }
.big-count { font-size: 44px; font-weight: 800; letter-spacing: -.03em; }
.big-count small { font-size: 18px; color: var(--muted); font-weight: 700; }


/* ============ v0.2.9 refinement pass: motion, feedback, consistency ============ */
/* Dialog entrance: gentle fade + scale (was a bottom-sheet slide-up). */
.sheet-backdrop { animation: se-fade-in .22s ease-out; }
.sheet { animation: se-modal-in .22s cubic-bezier(.32,.72,.35,1); }
@keyframes se-fade-in { from { opacity: 0; } }
@keyframes se-modal-in { from { transform: scale(.96) translateY(10px); opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .sheet, .sheet-backdrop { animation: none; }
}
/* Tap feedback — these controls previously had no pressed state. */
.book-row:active { background: var(--surface-2); }
.segbtn:active { opacity: .7; }
nav.tabs button:active { color: var(--accent); }
.theme-opt:active { border-color: var(--accent); }
.quick-add:active { background: var(--surface-2); }
.shelf-opt:active { border-color: var(--accent); background: var(--accent-soft); }
/* Visible keyboard focus (pairs with the sheet focus-trap work). */
button:focus-visible, a:focus-visible, [role="button"]:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
/* Skip link: off-screen until focused. */
.skip-link {
  position: absolute; left: 12px; top: -60px; z-index: 200;
  background: var(--accent); color: var(--on-accent);
  padding: 10px 16px; border-radius: 8px;
  font-weight: 700; font-size: 14px; text-decoration: none;
  transition: top .15s ease;
}
.skip-link:focus-visible { top: 12px; }
@media (prefers-reduced-motion: reduce) { .skip-link { transition: none; } }
/* Row main area: a real button filling the row's content area. The quick
   action (quick-add) sits beside it as a sibling, never nested.
   Resets keep the row's visuals identical to the old clickable div. */
.book-row .row-main {
  flex: 1 1 auto; min-width: 0; display: flex; gap: 12px; align-items: center;
  background: none; border: 0; padding: 0; margin: 0;
  font: inherit; color: inherit; text-align: left; cursor: pointer;
}
.sheet h2 { padding-right: 116px; }
/* The fallback letter tile stays tiny on the sheet's large cover — scale it up. */
.sheet-cover .cover-ph { font-size: 44px; }
/* Star-rating touch targets to 44px (were 40px). */
.stars button { padding: 6px; }
/* v0.3.0 — accounts */
/* Auth form error. */
.auth-err {
  color: var(--danger, #b3261e);
  font-size: 13px; line-height: 1.5; font-weight: 600;
  margin-top: 10px;
}
/* Sync status line under the account card (tap to retry). */
.sync-line { margin-top: 12px; }
/* Private-profile toggle row. */
.check-row {
  display: flex; gap: 10px; align-items: flex-start;
  margin-top: 14px; font-size: 14px; line-height: 1.45; cursor: pointer;
}
/* ---------- Home tab ---------- */
.hero-lane { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.hero-lane::-webkit-scrollbar { display: none; }
.hero { flex: 0 0 100%; scroll-snap-align: start; display: flex; gap: 16px; align-items: flex-start; cursor: pointer; }
/* Hero page dots (mockup-hero-dots): iOS-style dots under a multi-book
   swipe lane. The active dot stretches into a pill. Hidden for one book. */
.hero-dots { display: flex; gap: 7px; justify-content: center; margin-top: 14px; }
.hero-dot { width: 7px; height: 7px; border-radius: 999px; background: var(--line-strong); transition: width .2s ease, background-color .2s ease; }
.hero-dot.on { width: 22px; background: var(--ink); }
/* Nightstand pickup (mockup-nightstand-pickup): the Want-book pick card in
   the empty hero — a bordered box, tappable to open the book page. */
.want-pick { border: 1px solid var(--line); border-radius: 12px; padding: 10px; margin: 0 0 12px; background: var(--bg); align-items: center; }
.want-pick .cover { width: 44px; }
.want-pick:last-child { border-bottom: 1px solid var(--line); }
.hero .hero-cover { width: 110px; }
.hero-kicker { font-size: 11px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); margin-bottom: 4px; }
.hero-t { font-weight: 800; font-size: 18px; letter-spacing: -.01em; line-height: 1.3; }
.hero-a { font-size: 13px; color: var(--muted); margin-top: 2px; }
.hero .mini-bar { margin-top: 10px; }
.goal-strip { display: block; width: 100%; background: none; border: 0; padding: 12px 2px 4px; font: inherit; font-size: 13px; color: var(--muted); text-align: left; cursor: pointer; }
.goal-strip strong { color: var(--ink); font-weight: 700; }
.lane { display: flex; gap: 12px; overflow-x: auto; padding: 2px 2px 12px; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.lane::-webkit-scrollbar { display: none; }
.lane-item { flex: 0 0 auto; width: 92px; background: none; border: 0; padding: 0; font: inherit; color: inherit; text-align: left; cursor: pointer; }
.lane-item .cover { width: 92px; }
.lane-t { font-size: 12px; font-weight: 600; line-height: 1.3; margin-top: 6px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.lane-stars { display: flex; gap: 1px; margin-top: 4px; }
.lane-stars svg { width: 11px; height: 11px; }
.lane-stars .on { color: var(--gold); }
.lane-stars .on svg { fill: currentColor; }
.lane-stars .off { color: var(--line-strong); }

/* Customize Home Screen reorder rows (Kohlrabi pattern: chevron buttons, no drag) */
.reorder-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 2px; border-bottom: 1px solid var(--line); }
.reorder-row:last-child { border-bottom: 0; }
.reorder-name { font-weight: 600; font-size: 15px; }
.reorder-arrows { display: flex; gap: 4px; }
.reorder-arrow { width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: center; background: none; border: 0; border-radius: 12px; color: var(--ink); cursor: pointer; }
.reorder-arrow:disabled { opacity: .25; cursor: default; }
.reorder-arrow:not(:disabled):active { background: var(--wash); }

/* Recent-activity swipe-to-delete (Home card, owner only) */
.feed-swipe { position: relative; overflow: hidden; }
.feed-swipe .feed-item { position: relative; z-index: 1; background: var(--surface); transition: transform .18s ease; touch-action: pan-y; }
.feed-del { position: absolute; top: 0; right: 0; bottom: 0; width: 76px; border: 0; background: var(--danger); color: #fff; font: inherit; font-size: 14px; font-weight: 700; cursor: pointer; }

/* ===== Skeleton placeholders (boot + async hydration) ===== */
/* Shimmer blocks in theme tokens — shown instead of blank space while
   Home cards, the Library list, the book page, and search results
   hydrate. Simple and consistent; no spinners replacing card layouts. */
.skel {
  border-radius: 12px;
  background: linear-gradient(100deg, var(--surface-2) 40%, var(--surface-raised) 50%, var(--surface-2) 60%);
  background-size: 200% 100%;
  animation: skel-shimmer 1.2s infinite;
}
@keyframes skel-shimmer { to { background-position: -200% 0; } }
.skel-line { height: 16px; margin: 0 0 10px; }
.skel-line.short { max-width: 55%; }
.skel-cover { width: 92px; aspect-ratio: 2/3; }
.skel-cover.lg { width: 168px; }
.skel-row { display: flex; gap: 12px; margin: 12px 0; align-items: center; }
@media (prefers-reduced-motion: reduce) { .skel { animation: none; } }

/* Compact inline button: the global .btn is width:100%, but a Copy next
   to a short-link field must sit beside it, not stretch full width. */
.btn-inline { width: auto; flex: none; }

/* Now-page link row (Settings account card): label, readonly monospace
   URL field (right-aligned so the link value doesn't read like the other
   rows' labels), compact Copy button. */
.nowrow { margin-top: 12px; }
.nowrow-label { font-size: 12px; font-weight: 700; margin-bottom: 6px; }
.nowrow-link { display: flex; gap: 8px; align-items: center; }
.nowrow-link .mono-field { text-align: right; }
