/* Shelf (working title) — functional-first. Mobile + desktop. No build step. */

:root{
  --bg:#faf7f2; --surf:#fff; --surf2:#f2ede4; --line:#e0d8ca; --line2:#cfc3ae;
  --text:#1c1917; --text2:#6b6257; --text3:#9a9084;
  --accent:#8c2f21; --accent-t:#fff; --ok:#2f6b46; --warn:#8a6d1f;
  --radius:10px; --tap:44px;
  --font:ui-serif,Georgia,'Iowan Old Style','Times New Roman',serif;
  --sans:system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;
}
@media (prefers-color-scheme:dark){
  :root{
    --bg:#12100e; --surf:#1b1815; --surf2:#232019; --line:#332e27; --line2:#4a4238;
    --text:#ece7df; --text2:#a49a8c; --text3:#736a5f;
    --accent:#c9564a; --accent-t:#fff;
  }
}
:root[data-theme="light"]{
  --bg:#faf7f2; --surf:#fff; --surf2:#f2ede4; --line:#e0d8ca; --line2:#cfc3ae;
  --text:#1c1917; --text2:#6b6257; --text3:#9a9084; --accent:#8c2f21;
}
:root[data-theme="dark"]{
  --bg:#12100e; --surf:#1b1815; --surf2:#232019; --line:#332e27; --line2:#4a4238;
  --text:#ece7df; --text2:#a49a8c; --text3:#736a5f; --accent:#c9564a;
}

*{box-sizing:border-box}
[hidden]{display:none !important}
html,body{margin:0;padding:0}
/* Kill the translucent blue box mobile browsers flash over any tapped button/link. Our own
   :active and :focus-visible styles already give press + keyboard feedback, so nothing is lost. */
html{-webkit-tap-highlight-color:transparent}
body{
  background:var(--bg); color:var(--text); font-family:var(--sans);
  font-size:16px; line-height:1.5; overflow-x:clip;
  -webkit-font-smoothing:antialiased;
  padding-bottom:calc(64px + env(safe-area-inset-bottom));
}
@media(min-width:900px){ body{padding-bottom:0} }

a{color:inherit}
button,input,select,textarea{font:inherit;color:inherit}
a,button,[role="button"],input,select,textarea,label{-webkit-tap-highlight-color:transparent}

/* ── topbar ─────────────────────────────────────────── */
.topbar{
  position:sticky; top:0; z-index:30;
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:calc(10px + env(safe-area-inset-top)) 14px 10px;
  background:color-mix(in srgb,var(--bg) 88%,transparent);
  backdrop-filter:blur(8px); border-bottom:1px solid var(--line);
}
/* The wordmark must never shrink or clip — it's the brand. flex:none holds it at full width;
   space is made instead by dropping the redundant top "+ Add" on mobile (below). */
.brand{display:flex;align-items:center;gap:8px;text-decoration:none;flex:none;min-width:0}
.brand-mark{width:27px;height:27px;flex:none;overflow:visible}
.brand-mark rect{fill:var(--surf2);stroke:var(--line2);stroke-width:.85}
.brand-mark .wm-accent{fill:var(--accent);stroke:var(--accent)}
.brand-mark .wm-shelf{fill:var(--text3);stroke:none}
.brand-mark .wm-books{transform-origin:14px 23px}
.brand:hover .wm-books{animation:wm-wobble .7s ease-in-out}
@keyframes wm-wobble{0%,100%{transform:rotate(0)}20%{transform:rotate(-4deg)}60%{transform:rotate(3deg)}}
@media(prefers-reduced-motion:reduce){.brand:hover .wm-books{animation:none}}
.brand-name{font-family:var(--font);font-weight:700;font-size:1.12rem;letter-spacing:-.01em;display:flex;align-items:baseline;flex:none;white-space:nowrap}
/* "Wobbly" in the text colour, "Shelves" in the accent — one wordmark, the accent leaning
   into the wobble. */
.brand-shelves{color:var(--accent)}
.topbar-actions{display:flex;gap:8px;align-items:center;min-width:0}
/* The top "+ Add" duplicates the bottom tab-bar's Add on mobile, and crowding it there is what
   clipped the wordmark and wrapped the button. Show it only where the tab-bar is hidden. */
@media(max-width:899px){ .topbar-actions > .btn-accent{display:none} }

/* ── buttons ────────────────────────────────────────── */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
  min-height:var(--tap); padding:0 14px; border-radius:var(--radius);
  border:1px solid var(--line2); background:var(--surf); color:var(--text);
  font-weight:600; font-size:.9rem; text-decoration:none; cursor:pointer;
  white-space:nowrap; transition:border-color .12s,background .12s;
}
.btn:hover{border-color:var(--accent)}
.btn:active{transform:translateY(1px)}
.btn-accent{background:var(--accent);border-color:var(--accent);color:var(--accent-t)}
.btn-accent:hover{filter:brightness(1.08)}
.btn-ghost{background:transparent;border-color:transparent;padding:0 10px}
/* Theme toggle: a real, legibly-sized contrast icon instead of a tiny ◐ glyph. */
.theme-toggle{padding:0 8px}
.theme-toggle svg{width:22px;height:22px;display:block}
.btn-sm{min-height:34px;padding:0 10px;font-size:.82rem;border-radius:8px}
.btn-danger{color:var(--accent);border-color:var(--line2)}
.btn:focus-visible,a:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{
  outline:2px solid var(--accent); outline-offset:2px;
}
/* <main> is focused programmatically on every route change so screen readers announce the
   new view. It is not an interactive control, so it must never draw a focus ring — Chrome
   otherwise paints one after a keyboard refresh (Ctrl+R), which reads as a stray black box. */
#view:focus,#view:focus-visible{outline:none}

/* ── layout ─────────────────────────────────────────── */
main{max-width:1100px;margin:0 auto;padding:16px 14px 28px}
.h1{font-family:var(--font);font-size:1.5rem;font-weight:700;margin:2px 0 4px;letter-spacing:-.01em}
.sub{color:var(--text2);font-size:.9rem;margin:0 0 16px}
.card{background:var(--surf);border:1px solid var(--line);border-radius:var(--radius);padding:14px}
.stack{display:flex;flex-direction:column;gap:12px}
.row{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.spacer{flex:1}
.muted{color:var(--text2)}
.tiny{font-size:.78rem}
.center{text-align:center}

/* ── filters ────────────────────────────────────────── */
.filters{display:flex;gap:7px;overflow-x:auto;padding:2px 0 10px;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.filters::-webkit-scrollbar{display:none}
.chip{
  flex:none; min-height:36px; padding:0 12px; border-radius:99px;
  border:1px solid var(--line2); background:var(--surf); color:var(--text2);
  font-size:.84rem; font-weight:600; cursor:pointer; white-space:nowrap;
  display:inline-flex; align-items:center; gap:6px;
}
.chip[aria-pressed="true"]{background:var(--text);color:var(--bg);border-color:var(--text)}
.chip .n{font-size:.74rem;opacity:.7;font-variant-numeric:tabular-nums}

.search{
  width:100%; min-height:var(--tap); padding:0 12px; border-radius:var(--radius);
  border:1px solid var(--line2); background:var(--surf); margin-bottom:10px;
}

/* ── layout toggle ──────────────────────────────────── */
.head-row{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:14px}
.layout-toggle{display:flex;border:1px solid var(--line2);border-radius:var(--radius);overflow:hidden;flex:none}
.lt{
  width:42px; height:40px; border:0; background:var(--surf); color:var(--text2);
  cursor:pointer; display:flex; align-items:center; justify-content:center;
  border-right:1px solid var(--line);
}
.lt:last-child{border-right:0}
.lt svg{width:19px;height:19px;fill:currentColor}
.lt[aria-pressed="true"]{background:var(--text);color:var(--bg)}

/* ── book list ──────────────────────────────────────── */
.books{display:grid;gap:10px;grid-template-columns:1fr}
@media(min-width:640px){ .books{grid-template-columns:1fr 1fr} }
@media(min-width:980px){ .books{grid-template-columns:1fr 1fr 1fr} }

/* ── grid (cover-forward) — 2 up on a phone, 6 up on a desktop ── */
.books--grid{grid-template-columns:repeat(2,1fr);gap:14px}
@media(min-width:520px){ .books--grid{grid-template-columns:repeat(3,1fr)} }
@media(min-width:760px){ .books--grid{grid-template-columns:repeat(4,1fr)} }
@media(min-width:1000px){ .books--grid{grid-template-columns:repeat(6,1fr)} }

.tilebook{
  display:flex; flex-direction:column; gap:6px; align-items:stretch;
  border:0; background:none; padding:0; cursor:pointer; text-align:left;
  font:inherit; color:inherit; width:100%;
  content-visibility:auto; contain-intrinsic-size:auto 260px;
}
.tile-wrap{position:relative;display:block}
.tile-cov{
  width:100%; aspect-ratio:2/3; object-fit:cover; display:block;
  border-radius:4px; border:1px solid var(--line); background:var(--surf2);
  box-shadow:0 3px 12px rgba(0,0,0,.16);
  transition:transform .14s ease, box-shadow .14s ease;
}
.tilebook:hover .tile-cov{transform:translateY(-3px);box-shadow:0 8px 22px rgba(0,0,0,.24)}
.tile-cov--none{
  display:flex; align-items:center; justify-content:center; text-align:center;
  font-family:var(--font); font-size:.78rem; color:var(--text3);
  padding:10px; border-style:dashed;
}
.tile-badges{
  position:absolute; left:5px; right:5px; bottom:5px;
  display:flex; flex-wrap:wrap; gap:3px; max-height:56px; overflow:hidden;
}
.tile-badges .badge{
  font-size:.6rem; padding:1px 5px; backdrop-filter:blur(4px);
  background:color-mix(in srgb,var(--surf) 84%,transparent);
}
.tile-badges .badge--sale{background:var(--accent)}
.tile-t{
  font-family:var(--font); font-weight:700; font-size:.86rem; line-height:1.25;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
}
.tile-a{font-size:.74rem;color:var(--text2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.book{
  display:grid; grid-template-columns:52px 1fr; gap:12px;
  background:var(--surf); border:1px solid var(--line); border-radius:var(--radius);
  padding:11px; text-align:left; cursor:pointer; width:100%;
  font:inherit; color:inherit;
  /* Offscreen cards cost nothing to lay out or paint. This is what keeps a 2,000-book
     shelf smooth without hand-rolling a virtualiser. */
  content-visibility:auto; contain-intrinsic-size:auto 100px;
}
.book:hover{border-color:var(--line2)}
.cover{
  width:52px; height:76px; border-radius:3px; flex:none; object-fit:cover;
  background:var(--surf2); border:1px solid var(--line);
  display:flex; align-items:center; justify-content:center;
  font-family:var(--font); font-size:.62rem; color:var(--text3); text-align:center; padding:3px; overflow:hidden;
}
/* Broken-image fallback divs (from imgWithFallback) inherit the cover box. */
.cover--none,.tile-cov.tile-cov--none{
  display:flex;align-items:center;justify-content:center;text-align:center;overflow:hidden;
}
.book-main{min-width:0;display:flex;flex-direction:column;gap:3px}
.book-t{font-family:var(--font);font-weight:700;font-size:1rem;line-height:1.25;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.book-a{color:var(--text2);font-size:.83rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.book-meta{display:flex;gap:5px;flex-wrap:wrap;margin-top:3px}

/* ── multi-select (long-press) ──────────────────────── */
/* Kill the long-press text-callout so holding a book feels like a press, not a selection. */
.book,.tilebook{-webkit-touch-callout:none;user-select:none}
.books.selecting .book,.books.selecting .tilebook{position:relative}
/* the pick indicator — an empty ring, filled with a check when selected. Pure CSS, no markup. */
.books.selecting .book::after,
.books.selecting .tilebook::after{
  content:''; position:absolute; top:8px; right:8px; z-index:3;
  width:22px; height:22px; border-radius:50%; box-sizing:border-box;
  border:2px solid var(--line2); background:color-mix(in srgb,var(--bg) 65%,transparent);
}
.books.selecting .book.is-sel::after,
.books.selecting .tilebook.is-sel::after{
  content:'✓'; border-color:var(--accent); background:var(--accent); color:var(--accent-t);
  display:flex; align-items:center; justify-content:center; font-size:.8rem; font-weight:800; line-height:1;
}
.books.selecting .book.is-sel,
.books.selecting .tilebook.is-sel{outline:2px solid var(--accent);outline-offset:-2px;border-radius:12px}

/* the floating action bar */
.sel-bar{
  position:fixed; left:50%; transform:translateX(-50%);
  bottom:calc(72px + env(safe-area-inset-bottom)); z-index:60;
  display:flex; align-items:center; gap:8px;
  max-width:calc(100vw - 20px); overflow-x:auto; scrollbar-width:none;
  padding:8px 10px; border-radius:14px;
  background:var(--surf); border:1px solid var(--line2);
  box-shadow:0 10px 30px rgba(0,0,0,.32);
}
.sel-bar::-webkit-scrollbar{display:none}
.sel-bar[hidden]{display:none}
.sel-bar .btn{flex:none}
.sel-count{font-weight:800;font-size:.82rem;white-space:nowrap;padding:0 4px}
@media(min-width:900px){ .sel-bar{bottom:24px} }
/* the aisle FAB would sit under the bar — hide it while selecting */
body.selecting-mode .fab{display:none}

/* ── batch-location picker ──────────────────────────── */
.locpick{
  position:fixed; inset:0; z-index:90;
  display:flex; align-items:center; justify-content:center; padding:18px;
  background:rgba(8,7,6,.55); backdrop-filter:blur(2px);
}
.locpick[hidden]{display:none}
.locpick-card{
  width:100%; max-width:420px; max-height:80vh; overflow-y:auto;
  background:var(--surf); border:1px solid var(--line2); border-radius:16px;
  padding:18px; box-shadow:0 16px 48px rgba(0,0,0,.45);
}
.locpick-h{font-family:var(--font);font-size:1.2rem;margin:0 0 2px}
.locpick-sub{color:var(--text2);font-size:.85rem;margin:0 0 14px}
.locpick-list{display:flex;flex-direction:column;gap:6px;margin-bottom:14px}
.locpick-opt{
  text-align:left; width:100%; min-height:44px; padding:0 14px;
  border:1px solid var(--line2); border-radius:10px; background:var(--surf2);
  color:var(--text); font:inherit; font-weight:600; font-size:.95rem; cursor:pointer;
}
.locpick-opt:hover{border-color:var(--accent)}
.locpick-new{display:flex;gap:8px;margin-bottom:8px}
.locpick-new input{
  flex:1; min-width:0; min-height:var(--tap); padding:0 12px;
  border:1px solid var(--line2); border-radius:var(--radius); background:var(--bg); color:var(--text);
}
.locpick-cancel{width:100%;margin-top:4px}

.badge{
  font-size:.68rem;font-weight:700;padding:2px 7px;border-radius:99px;
  border:1px solid var(--line2); color:var(--text2); white-space:nowrap;
  text-transform:uppercase; letter-spacing:.04em;
}
.badge--own{background:var(--surf2);color:var(--text);border-color:var(--line2)}
.badge--read{border-color:var(--ok);color:var(--ok)}
.badge--reading{border-color:var(--warn);color:var(--warn)}
.badge--want{border-style:dashed}
.badge--sale{background:var(--accent);color:var(--accent-t);border-color:var(--accent)}
.badge--lent{border-color:var(--warn);color:var(--warn)}
.badge--flag{border-style:dashed;color:var(--text3)}

.empty{
  border:1px dashed var(--line2); border-radius:var(--radius);
  padding:34px 18px; text-align:center; color:var(--text2);
}
.empty .h1{font-size:1.15rem}

/* ── forms ──────────────────────────────────────────── */
.field{display:flex;flex-direction:column;gap:5px;margin-bottom:12px}
.field label{font-size:.78rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text2)}
.field input,.field select,.field textarea{
  min-height:var(--tap); padding:9px 11px; border-radius:var(--radius);
  border:1px solid var(--line2); background:var(--surf); width:100%;
}
.field textarea{min-height:96px;resize:vertical;font-family:var(--font);line-height:1.6}
.grid2{display:grid;gap:0 12px;grid-template-columns:1fr}
@media(min-width:560px){ .grid2{grid-template-columns:1fr 1fr} }
.checks{display:flex;flex-wrap:wrap;gap:7px}
.check{
  display:inline-flex;align-items:center;gap:6px;min-height:38px;padding:0 11px;
  border:1px solid var(--line2);border-radius:99px;background:var(--surf);
  font-size:.83rem;font-weight:600;cursor:pointer;
}
.check input{width:16px;height:16px;min-height:0;margin:0;accent-color:var(--accent)}
.check:has(input:checked){background:var(--text);color:var(--bg);border-color:var(--text)}

/* ── detail page: cover beside the fields ───────────── */
/* The cards keep their full width. Only the FIELD column narrows, because the cover
   takes the space to its left — that's the whole point. Don't cap #editForm: doing so
   shrinks every card on the page, which is not what was asked for. */
.detail-top{display:grid;gap:18px;grid-template-columns:1fr;align-items:start}
@media(min-width:680px){
  .detail-top{grid-template-columns:190px 1fr}
}
/* On a wide monitor, stop the title/author inputs stretching to 900px — but cap the
   inputs, not the card. */
@media(min-width:900px){
  .detail-fields .field > input,
  .detail-fields .field > select{max-width:640px}
  .detail-fields .grid2 .field > input,
  .detail-fields .grid2 .field > select{max-width:none}
}
.detail-cover{display:flex;flex-direction:column;gap:7px;align-items:center}
@media(max-width:679px){
  .detail-cover{flex-direction:row;flex-wrap:wrap;align-items:flex-end;justify-content:flex-start}
}
.cover-lg{
  width:100%; max-width:190px; aspect-ratio:2/3; object-fit:cover;
  border-radius:4px; border:1px solid var(--line2); background:var(--surf2);
  box-shadow:0 4px 16px rgba(0,0,0,.14);
  display:flex; align-items:center; justify-content:center;
}
@media(max-width:679px){ .cover-lg{width:104px} }
.cover-none{
  font-family:var(--font); font-size:.8rem; color:var(--text3);
  border-style:dashed;
}
.detail-cover .btn{width:100%}
@media(max-width:679px){ .detail-cover .btn{width:auto} }
.detail-fields{min-width:0}
/* Own/read status pinned to the top of the fields column, set off from the bibliographic fields. */
.status-top{display:flex;flex-direction:column;gap:10px;margin-bottom:14px;padding-bottom:14px;border-bottom:1px solid var(--line)}
.status-top .seg{max-width:none}

/* Collapsible sections on the book page — keep it short; expand only what you need. */
.sect{background:var(--surf);border:1px solid var(--line);border-radius:var(--radius);margin-bottom:12px;overflow:hidden}
.sect > summary{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:14px; cursor:pointer; list-style:none;
  font-family:var(--font); font-weight:700; font-size:1.02rem;
}
.sect > summary::-webkit-details-marker{display:none}
.sect > summary::after{content:'▾'; color:var(--text3); font-size:.8rem; transition:transform .15s ease}
.sect[open] > summary::after{transform:rotate(180deg)}
.sect-body{padding:2px 14px 14px}
.sect-body > .field:first-child,.sect-body > .grid2:first-child{margin-top:0}

.seg{display:flex;gap:0;border:1px solid var(--line2);border-radius:var(--radius);overflow:hidden}
.seg button{
  flex:1; min-height:var(--tap); border:0; background:var(--surf); color:var(--text2);
  font-weight:600; font-size:.85rem; cursor:pointer; padding:0 6px;
  border-right:1px solid var(--line);
}
.seg button:last-child{border-right:0}
.seg button[aria-pressed="true"]{background:var(--text);color:var(--bg)}

.note{
  background:var(--surf2); border:1px solid var(--line); border-left:3px solid var(--accent);
  border-radius:6px; padding:10px 12px; font-size:.86rem; color:var(--text2);
}

/* ── tabbar (mobile) ────────────────────────────────── */
.tabbar{
  position:fixed; left:0; right:0; bottom:0; z-index:30;
  display:grid; grid-template-columns:repeat(5,1fr);
  background:color-mix(in srgb,var(--bg) 94%,transparent);
  backdrop-filter:blur(8px);
  border-top:1px solid var(--line);
  padding-bottom:env(safe-area-inset-bottom);
}
.tabbar a{
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;
  min-height:58px; text-decoration:none; color:var(--text3);
  font-size:.68rem; font-weight:700; letter-spacing:.03em;
}
.tabbar a[aria-current="page"]{color:var(--accent)}
.tabbar .ti{width:22px;height:22px;fill:currentColor;display:block}
@media(min-width:900px){ .tabbar{display:none} }

/* ── THE SPINE WALL ─────────────────────────────────── */
.plank-wrap{margin:22px 0 6px}
/* Offscreen shelves cost nothing to lay out or paint — this is what keeps 2,000 spines smooth. */
.plank-wrap{content-visibility:auto;contain-intrinsic-size:auto 280px}

.plank-head{display:flex;align-items:baseline;gap:10px;margin-bottom:6px}
.plank-name{
  font-family:var(--font); font-size:1.05rem; font-weight:700; margin:0;
  letter-spacing:-.01em;
}
.plank-n{
  font-size:.72rem; font-weight:700; color:var(--text3);
  font-variant-numeric:tabular-nums;
}
.plank-wrap--unknown .plank-name{color:var(--text2);font-style:italic}
/* Editable shelf title — a button that renames the location on every book on the shelf. */
.plank-name--edit{
  background:none; border:0; padding:0; cursor:pointer; color:inherit; text-align:left;
  display:inline-flex; align-items:center; gap:7px;
}
.plank-edit{font-size:.8rem; color:var(--text3); opacity:.6}
.plank-name--edit:hover .plank-edit{opacity:1; color:var(--accent)}
.plank-note{font-size:.8rem;color:var(--text3);margin:0 0 8px;max-width:56ch}

.plank{position:relative;padding-bottom:12px}
.plank-books{
  display:flex; align-items:flex-end; gap:2px;
  overflow-x:auto; overflow-y:hidden;           /* you scan a shelf left-to-right, same as the real one */
  padding:14px 2px 0;
  scrollbar-width:thin;
  min-height:60px;
}
.plank-board{
  height:9px; border-radius:2px;
  background:linear-gradient(180deg,var(--line2),var(--line));
  box-shadow:0 2px 6px rgba(0,0,0,.18);
}

.spine{
  flex:none; position:relative;
  border:0; padding:0; margin:0; cursor:pointer;
  border-radius:2px 2px 1px 1px;
  background:var(--sc,#444);
  box-shadow:inset -3px 0 6px rgba(0,0,0,.30), inset 2px 0 3px rgba(255,255,255,.10),
             0 1px 3px rgba(0,0,0,.25);
  display:flex; flex-direction:column; align-items:center; justify-content:space-between;
  padding:7px 0 6px;
  transition:transform .16s ease, box-shadow .16s ease;
  transform-origin:bottom center;
  overflow:hidden;
}
.spine:hover{transform:translateY(-5px)}
.spine.is-out{transform:translateY(-16px) rotate(-1.5deg);box-shadow:0 12px 26px rgba(0,0,0,.4)}
.spine:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

.sp-t,.sp-a{
  writing-mode:vertical-rl; text-orientation:mixed;
  color:#fff; text-shadow:0 1px 2px rgba(0,0,0,.5);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  max-height:100%;
}
.sp-t{font-family:var(--font);font-weight:700;font-size:.72rem;letter-spacing:.01em;flex:1}
.sp-a{font-size:.58rem;opacity:.75;font-weight:600;max-height:38%}

/* Unknown page count must LOOK unknown. Thickness from a guess would be a claim about
   how long the book is — that's fabrication, and this app doesn't do it. */
.spine--nopages{
  background-image:repeating-linear-gradient(45deg,
    rgba(255,255,255,.10) 0 3px, transparent 3px 7px);
}

/* Lent out: a gap in the row with a slip standing in it, the way a library left a card.
   The gap is exactly the information you need. */
.spine--lent{
  background:transparent;
  border:1px dashed var(--line2);
  box-shadow:none;
  align-items:center; justify-content:center;
}
.spine--lent:hover{transform:none}
.slip{
  writing-mode:vertical-rl;
  background:var(--surf2); color:var(--text2);
  border:1px solid var(--line2); border-radius:2px;
  font-size:.58rem; font-weight:700; padding:6px 2px;
  max-height:88%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  transform:rotate(-2deg);
}

.peek{
  position:fixed; left:12px; right:12px; z-index:40;
  bottom:calc(74px + env(safe-area-inset-bottom));
  background:var(--surf); border:1px solid var(--line2); border-radius:var(--radius);
  box-shadow:0 12px 40px rgba(0,0,0,.28); padding:12px;
}
@media(min-width:900px){ .peek{bottom:24px;left:auto;right:24px;max-width:460px} }
.peek-in{display:grid;grid-template-columns:52px 1fr;gap:12px;align-items:start}
.peek-act{grid-column:1/-1;display:flex;gap:8px;margin-top:4px}

/* ── aisle check ────────────────────────────────────── */
.fab{
  position:fixed; right:16px; z-index:35;
  bottom:calc(72px + env(safe-area-inset-bottom));
  width:56px; height:56px; border-radius:50%;
  border:1px solid var(--line2); background:var(--accent); color:var(--accent-t);
  cursor:pointer;
  box-shadow:0 6px 20px rgba(0,0,0,.28);
  display:flex; align-items:center; justify-content:center;
}
.fab svg{width:26px;height:26px;fill:currentColor}
@media(min-width:900px){ .fab{bottom:24px} }
body.scanning .fab,body.scanning .tabbar,body.scanning .topbar{display:none}
/* Editing a book: the aisle FAB floated over the Delete button. Not needed on this screen. */
body.on-edit .fab{display:none}

/* ── capture feedback (shutter + processing) ────────── */
/* The white "snap" flash. Sits above the camera overlays (z 80/85) so it reads as the shutter. */
.shutter-fx{position:fixed;inset:0;z-index:120;background:#fff;opacity:0;pointer-events:none}
.shutter-fx.go{animation:shutter-fx .3s ease-out}
@keyframes shutter-fx{0%{opacity:.9}100%{opacity:0}}
@media(prefers-reduced-motion:reduce){.shutter-fx.go{animation-duration:.14s}}

/* The "we're reading it" panel, over the frozen shot. */
.cap-busy{
  position:fixed; inset:0; z-index:118;
  display:flex; align-items:center; justify-content:center;
  background:rgba(8,7,6,.5); backdrop-filter:blur(2px);
}
.cap-busy[hidden]{display:none}
.cap-busy-card{
  display:flex; flex-direction:column; align-items:center; gap:14px;
  padding:22px 30px; border-radius:16px;
  background:var(--surf); border:1px solid var(--line2);
  box-shadow:0 14px 44px rgba(0,0,0,.45);
}
.cap-busy-t{font-family:var(--font);font-weight:700;font-size:1rem;color:var(--text)}
.cap-spin{
  width:34px; height:34px; border-radius:50%;
  border:3px solid var(--line2); border-top-color:var(--accent);
  animation:cap-spin .8s linear infinite;
}
@keyframes cap-spin{to{transform:rotate(360deg)}}
@media(prefers-reduced-motion:reduce){.cap-spin{animation-duration:1.8s}}

.aisle{position:fixed;inset:0;z-index:80;background:#000;overflow:hidden}
.aisle-vid{width:100%;height:100%;object-fit:cover}
.aisle-top{
  position:absolute; left:0; right:0; top:0; z-index:2;
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:calc(12px + env(safe-area-inset-top)) 14px 12px;
  background:linear-gradient(#000c,#0000);
}
.aisle-tally{color:#fff;font-size:.85rem;font-weight:600;font-variant-numeric:tabular-nums}
.aisle-top .btn{background:#fff2;border-color:#fff5;color:#fff}
.aisle-reticle{
  position:absolute; left:50%; top:44%; transform:translate(-50%,-50%);
  width:min(76vw,320px); height:120px; border:2px solid #fff9; border-radius:10px;
  box-shadow:0 0 0 100vmax #0006;
}
/* Reticle is 120px tall centred on 44%, so its bottom edge is 44% + 60px.
   The hint clears it; the button clears the hint. These used to overlap. */
.aisle-hint{
  position:absolute; left:0; right:0; top:calc(44% + 76px);
  text-align:center; color:#fffc; font-size:.85rem; margin:0; padding:0 20px;
  transition:top .2s ease, bottom .2s ease;
}

/* No camera available (iOS Safari, most desktops) — hide the camera furniture, type instead. */
.aisle.no-cam .aisle-vid,
.aisle.no-cam .aisle-reticle,
.aisle.no-cam .aisle-hint{display:none}
.aisle.no-cam{background:var(--bg)}
.aisle-manual{
  position:absolute; left:0; right:0; top:calc(64px + env(safe-area-inset-top));
  padding:0 16px; color:var(--text);
}
.aisle-manual label{
  display:block; font-size:.78rem; font-weight:700; text-transform:uppercase;
  letter-spacing:.06em; color:var(--text2); margin-bottom:6px;
}
.aisle-manual input{
  flex:1; min-height:var(--tap); padding:0 12px; border-radius:var(--radius);
  border:1px solid var(--line2); background:var(--surf); font-size:1.05rem;
}
.aisle-manual .tiny{color:var(--text3);margin-top:8px}
.aisle.no-cam .aisle-top{background:none}
.aisle.no-cam .aisle-tally{color:var(--text2)}
.aisle.no-cam .aisle-top .btn{background:var(--surf);border-color:var(--line2);color:var(--text)}

/* The verdict. Arm's-length type — you're reading this at hip height in bad light. */
.aisle-verdict{
  position:absolute; left:12px; right:12px; z-index:3;
  bottom:calc(16px + env(safe-area-inset-bottom));
  border-radius:14px; padding:16px 18px; color:#fff;
  background:#222; border:1px solid #fff3;
  box-shadow:0 10px 40px rgba(0,0,0,.5);
}
.aisle-verdict.is-own{background:#1c5c3a;border-color:#2f8f5c}
.aisle-verdict.is-other-printing{background:#8a5a12;border-color:#c08a2a}  /* the upgrade decision */
.aisle-verdict.is-want{background:#1d4f7c;border-color:#3b7fb8}
.aisle-verdict.is-read-not-owned{background:#5c3a7a;border-color:#8b5cb0}
.aisle-verdict.is-had{background:#5c3a7a;border-color:#8b5cb0}
.aisle-verdict.is-gap{background:#8a2f21;border-color:#c9564a}
.aisle-verdict.is-new{background:#2a2a2a;border-color:#555}
/* Couldn't identify the scan — a dashed, muted card so it reads as "incomplete, try again"
   and never looks like the confident dark "not on your shelf" answer. */
.aisle-verdict.is-unknown{background:#33302a;border-color:#7a6f52;border-style:dashed}
/* The cover, right there on the verdict. Two jobs: confirms the scanner grabbed the RIGHT
   book, and shows you the cover will actually come with it when you add it. */
.av-in{display:grid;grid-template-columns:56px 1fr;gap:12px;align-items:start}
.av-cov{
  width:56px; aspect-ratio:2/3; object-fit:cover; display:block;
  border-radius:3px; border:1px solid #fff3; background:#0004;
}
.av-cov--none{
  display:flex; align-items:center; justify-content:center; text-align:center;
  font-size:.55rem; font-weight:700; letter-spacing:.04em; text-transform:uppercase;
  color:#fff8; border-style:dashed; padding:3px;
}
.av-text{min-width:0}
.av-head{font-size:.78rem;font-weight:800;letter-spacing:.1em;text-transform:uppercase;opacity:.9}
.av-title{font-family:var(--font);font-size:1.3rem;font-weight:700;line-height:1.2;margin:5px 0 2px}
.av-line{font-size:.92rem;opacity:.95}
.av-sub{font-size:.86rem;opacity:.8;margin-top:4px}
.av-actions{display:flex;gap:8px;margin-top:12px;flex-wrap:wrap}
.av-actions .btn{background:#fff2;border-color:#fff5;color:#fff}
.av-actions .btn-accent{background:#fff;color:#111;border-color:#fff}

/* ── SHELF SWEEP ────────────────────────────────────── */
.sweep{position:fixed;inset:0;z-index:80;background:#000;overflow:hidden}
.sweep-setup{
  position:absolute; inset:0; background:var(--bg); color:var(--text);
  overflow-y:auto; padding:calc(20px + env(safe-area-inset-top)) 18px
    calc(24px + env(safe-area-inset-bottom));
  max-width:560px; margin:0 auto;
}
.sweep-run{position:absolute;inset:0}
.sweep.no-cam .sweep-run{background:var(--bg)}
.sweep.no-cam .aisle-vid,.sweep.no-cam .aisle-reticle{display:none}
.sweep.no-cam .aisle-top{background:none}
.sweep.no-cam .aisle-tally{color:var(--text2)}
.sweep.no-cam .aisle-top .btn{background:var(--surf);border-color:var(--line2);color:var(--text)}
.sweep.no-cam .sw-chip{background:var(--surf);border-color:var(--line2);color:var(--text)}
.sweep.no-cam .sw-chip .k{color:var(--text3)}
/* No camera → the typed-ISBN box has to clear the sticky chips, not sit on top of them. */
.sweep.no-cam .aisle-manual{top:calc(124px + env(safe-area-inset-top));max-width:560px;margin:0 auto;left:0;right:0}
.sweep.no-cam .sw-chips{max-width:560px;margin:0 auto}
@media(min-width:900px){
  /* Centre with margin, NOT transform — the swipe handler owns `transform` and the two
     would fight, making the strip jump sideways the moment you touch it. */
  .sweep .sw-strip{max-width:520px;left:0;right:0;margin:0 auto}
  .sweep .sw-undo{max-width:520px;margin:0 auto}
}

/* The sticky answers, pinned to the FLOOR — the thumb zone. Your other hand holds a book
   and the top corners of a 6.5" phone are unreachable.
   The confirm strip RISES OVER this bar rather than sitting above it: the two are never
   needed at the same moment (you retag between books, never mid-book), so they can share
   the space in time instead of competing for it. Crucially, the floor NEVER MOVES — a row
   that jumped 60px on every scan would destroy thumb muscle memory over 400 books. */
.sw-bar{
  position:absolute; left:0; right:0; bottom:0; z-index:3;
  display:flex; gap:8px; padding:22px 12px calc(10px + env(safe-area-inset-bottom));
  background:linear-gradient(#0000,#000c 45%);
  transition:opacity .15s ease;
}
.sw-chip{
  flex:1 1 0; min-width:0;
  display:flex; flex-direction:column; align-items:flex-start; gap:1px;
  min-height:48px; padding:6px 11px; border-radius:10px; cursor:pointer;
  /* translucent white over a bright bookshelf is unreadable — needs a dark plate */
  background:#0009; border:1px solid #fff3; color:#fff;
  font-size:.86rem; font-weight:700;
  touch-action:manipulation;
  justify-content:center;
}
.sw-chip .v{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:100%}
.sw-chip .k{
  font-size:.56rem; font-weight:700; letter-spacing:.09em; text-transform:uppercase;
  opacity:.7;
}

/* A book is waiting for an answer → the bar is irrelevant AND untouchable.
   This is what makes a full-card swipe safe: you cannot clip a chip mid-gesture. */
.sweep.is-pending .sw-bar{opacity:.35;pointer-events:none}
.sweep.is-pending .sw-undo{opacity:0;pointer-events:none}

/* No camera (iOS typed-ISBN fallback): the keyboard owns the bottom, and an absolutely-
   positioned bar inside a fixed overlay does NOT ride the visual viewport up. The whole
   thumb-zone argument is about holding a camera — no camera, no argument. Back to the top. */
.sweep.no-cam .sw-bar{
  top:calc(124px + env(safe-area-inset-top)); bottom:auto;
  background:none; padding-top:0;
  max-width:560px; margin:0 auto;
}

/* Cover-read fallback button.
   Centred with margin, NOT transform: `.btn:active` sets `transform:translateY(1px)`, which
   would clobber a `translateX(-50%)` and make the button jump sideways on every press. */
/* Cover-read button.
   Centred with margin, NOT transform: `.btn:active` sets `transform:translateY(1px)`, which
   would clobber a `translateX(-50%)` and make the button jump sideways on every press.
   Sits BELOW the hint (44% + 76px + ~24px of text + a gap) — it used to overlap it. */
.cover-btn{
  position:absolute; left:0; right:0; margin:0 auto; z-index:4;
  width:max-content; max-width:calc(100% - 32px);
  top:calc(44% + 118px);
  background:#fff2; border-color:#fff5; color:#fff; backdrop-filter:blur(6px);
  transition:top .2s ease, bottom .2s ease;
}
.sweep.no-cam .cover-btn,.aisle.no-cam .cover-btn{display:none}
.sweep.is-pending .cover-btn{opacity:0;pointer-events:none}

/* ── COVER MODE — full frame, no reticle ─────────────
   A fixed cutout is the wrong idea: books come in every shape, and a frame that doesn't
   match the book you're holding just makes you fight it. So take the WHOLE frame, and let
   the model find the book in it and hand back a bounding box — we crop to that. Aiming
   becomes "get the book roughly in shot", which is what you can actually do one-handed. */
.is-cover .aisle-reticle{display:none}
.is-cover .aisle-hint{
  top:auto; bottom:calc(200px + env(safe-area-inset-bottom));
  font-size:.92rem; color:#fff;
}
.is-cover .cover-btn{
  top:auto; bottom:calc(140px + env(safe-area-inset-bottom));
  min-height:52px; padding:0 30px; font-size:1rem;
}
.is-cover .cover-btn.btn-accent{background:var(--accent);border-color:var(--accent);color:#fff}
.is-cover .sw-undo{opacity:0;pointer-events:none}

/* Corner marks instead of a box — a hint that the whole frame counts, not a cutout to fill. */
.is-cover .sweep-run::after,.aisle.is-cover::after{
  content:''; position:absolute; inset:14px; pointer-events:none;
  border-radius:14px;
  box-shadow:inset 0 0 0 2px #ffffff26;
}

/* A quieter way back out. */
.cover-back{
  position:absolute; left:0; right:0; margin:0 auto; z-index:4;
  width:max-content; bottom:calc(98px + env(safe-area-inset-bottom));
  background:transparent; border-color:transparent; color:#fffb;
  font-size:.82rem;
}
.aisle:not(.is-cover) .cover-back,.sweep:not(.is-cover) .cover-back{display:none}
.sweep.is-pending .cover-back{opacity:0;pointer-events:none}

/* Last five added — a mistake costs one tap, not a hunt through the shelf afterwards. */
.sw-undo{
  position:absolute; left:0; right:0; z-index:2;
  bottom:calc(76px + env(safe-area-inset-bottom));   /* clears the sticky bar on the floor */
  display:flex; gap:6px; padding:0 12px; overflow-x:auto; scrollbar-width:none;
  transition:opacity .15s ease;
}
.sw-undo::-webkit-scrollbar{display:none}
.sw-recent{
  position:relative; flex:none; width:36px; height:52px; padding:0;
  border:1px solid #fff4; border-radius:3px; background:#0006; cursor:pointer;
  overflow:hidden;
}
.sw-recent img{width:100%;height:100%;object-fit:cover;display:block}
.sw-recent-none{
  display:flex;align-items:center;justify-content:center;height:100%;
  font-size:.5rem;color:#fff9;padding:2px;text-align:center;
}
.sw-x{
  position:absolute; top:-1px; right:-1px;
  width:15px; height:15px; border-radius:0 3px 0 5px;
  background:#000a; color:#fff; font-size:.68rem; line-height:15px; text-align:center;
}

/* The confirm strip. Swipe it anywhere, or hit the button. Rises OVER the sticky bar. */
.sw-strip{
  position:absolute; left:12px; right:12px; z-index:5;
  bottom:calc(8px + env(safe-area-inset-bottom));
  background:var(--surf); border:1px solid var(--line2); border-radius:14px;
  box-shadow:0 12px 40px rgba(0,0,0,.5); padding:12px 12px 10px;
  touch-action:pan-y;   /* let our horizontal swipe win, keep vertical scroll native */
  user-select:none;
}
@media(prefers-reduced-motion:no-preference){
  /* Animate transform only — never opacity from 0, or a reduced-motion user gets a card
     that is technically present and visually invisible. */
  .sweep.is-pending .sw-strip{animation:swRise .18s ease}
  @keyframes swRise{from{transform:translateY(110%)}to{transform:translateY(0)}}
}

/* The stickies, restated at the moment of commitment — and TAPPABLE here, because this is
   where you fix the one Fine copy without breaking the rhythm. */
.sw-sticky{display:flex;gap:5px;flex-wrap:wrap;margin-top:5px}
.sw-mini{
  border:1px solid var(--line2); background:var(--surf2); color:var(--text2);
  border-radius:99px; padding:2px 9px; font-size:.72rem; font-weight:700;
  cursor:pointer; min-height:26px;
}
.sw-mini:hover{border-color:var(--accent);color:var(--text)}
.sw-strip.is-dupe{border-color:var(--warn)}
.sw-strip-in{display:grid;grid-template-columns:44px 1fr;gap:11px;align-items:start}
.sw-cov{width:44px;height:64px;object-fit:cover;border-radius:3px;border:1px solid var(--line);display:block}
.sw-cov--none{
  display:flex;align-items:center;justify-content:center;
  background:var(--surf2);color:var(--text3);font-size:1rem;
}
.sw-meta{min-width:0}
.sw-dupe{
  font-size:.62rem;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
  color:var(--warn);margin-bottom:2px;
}
.sw-t{font-family:var(--font);font-weight:700;font-size:1rem;line-height:1.2;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.sw-a{font-size:.8rem;color:var(--text2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sw-sticky{
  font-size:.72rem;color:var(--text3);margin-top:3px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.sw-acts{display:flex;gap:8px;margin-top:10px}
.sw-acts .btn{flex:1;min-height:46px}   /* big targets — you're holding a book in the other hand */
.sw-acts .sw-keep{flex:2}
.sw-hint{
  text-align:center;font-size:.66rem;color:var(--text3);margin-top:7px;
  letter-spacing:.03em;
}

/* ── comps ──────────────────────────────────────────── */
.comps{display:flex;gap:8px;flex-wrap:wrap}

/* ── listing description ────────────────────────────── */
.listing{
  margin-top:12px; padding-top:12px; border-top:1px solid var(--line);
}
.listing-head{
  display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:8px;
  font-size:.78rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--text2);
}
.listing-body{
  margin:0; padding:12px 14px;
  background:var(--surf2); border:1px solid var(--line); border-radius:8px;
  font-family:var(--font); font-size:.9rem; line-height:1.6; color:var(--text);
  white-space:pre-wrap; word-break:break-word;
}

/* ── reading progress ───────────────────────────────── */
/* The page-block seen edge-on: the read part thumbed and darker, the unread part clean,
   with a ribbon where your bookmark is. A physical book has a bookmark, not a percentage. */
.prog-edge{
  position:relative; height:34px; border-radius:3px; overflow:hidden;
  background:repeating-linear-gradient(90deg,
    var(--surf2) 0 2px, var(--line) 2px 3px);
  border:1px solid var(--line2);
}
.prog-read{
  position:absolute; inset:0 auto 0 0; height:100%;
  background:repeating-linear-gradient(90deg,
    color-mix(in srgb,var(--text3) 26%,transparent) 0 2px,
    color-mix(in srgb,var(--text3) 44%,transparent) 2px 3px);
  transition:width .2s ease;
}
.prog-ribbon{
  position:absolute; top:-3px; bottom:-3px; width:4px; margin-left:-2px;
  background:var(--accent); border-radius:2px;
  box-shadow:0 0 0 1px color-mix(in srgb,var(--bg) 60%,transparent);
  transition:left .2s ease;
}
.prog-in{max-width:96px;text-align:center}
.prog-of{color:var(--text3);font-size:.85rem}
.prog-pct{
  margin-left:auto; font-weight:800; font-size:.9rem; color:var(--text2);
  font-variant-numeric:tabular-nums;
}

/* ── batch shelf scan ───────────────────────────────── */
#shelfScan .shelf-hint{
  top:auto; bottom:calc(140px + env(safe-area-inset-bottom));
  font-size:.9rem; color:#fff; line-height:1.6;
}
#shelfScan .cover-btn{
  top:auto; bottom:calc(60px + env(safe-area-inset-bottom));
  min-height:54px; padding:0 34px; font-size:1.02rem;
}
#shelfScan::after{
  content:''; position:absolute; inset:16px; pointer-events:none;
  border-radius:14px; box-shadow:inset 0 0 0 2px #ffffff2e;
}

.bx-list{display:flex;flex-direction:column;gap:8px}
.bx-row{
  display:grid; grid-template-columns:34px 46px 1fr; gap:11px; align-items:center;
  background:var(--surf); border:1px solid var(--line); border-radius:var(--radius);
  padding:9px 11px;
  transition:opacity .12s ease;
}
.bx-row.is-off{opacity:.4}
.bx-check{display:flex;align-items:center;justify-content:center}
.bx-check input{width:20px;height:20px;accent-color:var(--accent);cursor:pointer}
.bx-cov{
  width:46px; height:68px; object-fit:cover; display:block;
  border-radius:3px; border:1px solid var(--line); background:var(--surf2);
}
.bx-cov--none,.bx-cov--wait{
  display:flex;align-items:center;justify-content:center;text-align:center;
  font-size:.52rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  color:var(--text3);border-style:dashed;padding:3px;
}
.bx-cov--wait{
  background:linear-gradient(90deg,var(--surf2),var(--line),var(--surf2));
  background-size:200% 100%; animation:bxShim 1.1s linear infinite; border-style:solid;
}
@keyframes bxShim{from{background-position:200% 0}to{background-position:-200% 0}}
.bx-meta{min-width:0}
.bx-t{font-family:var(--font);font-weight:700;font-size:.96rem;line-height:1.25;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.bx-a{font-size:.79rem;color:var(--text2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bx-tags{display:flex;gap:5px;flex-wrap:wrap;margin-top:3px}
.bx-tag{
  font-size:.62rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  color:var(--text3);border:1px solid var(--line2);border-radius:99px;padding:1px 6px;
}
.bx-tag--warn{color:var(--warn);border-color:var(--warn)}

/* ── family shelves ─────────────────────────────────── */
/* The chip only appears once a second person exists — a solo user should never see family
   plumbing they never asked for. */
.prof-chip{
  display:flex; align-items:center; gap:6px; flex:none;
  min-height:32px; padding:0 11px; margin-left:4px;
  border:1px solid var(--line2); border-radius:99px; background:var(--surf);
  color:var(--text); font:inherit; font-size:.82rem; font-weight:700; cursor:pointer;
  max-width:36vw; overflow:hidden; white-space:nowrap; text-overflow:ellipsis;
}
.prof-chip:hover{border-color:var(--accent)}
.prof-dot{width:9px;height:9px;border-radius:50%;flex:none}

.prof-head{
  font-size:.66rem;font-weight:800;letter-spacing:.09em;text-transform:uppercase;
  color:var(--text3);padding:8px 10px 5px;
}
.prof-list{display:flex;flex-direction:column;gap:2px;margin-bottom:4px}
.prof{
  display:flex;align-items:center;gap:9px;width:100%;text-align:left;
  min-height:40px;padding:0 10px;border:0;border-radius:8px;
  background:none;color:var(--text);font:inherit;font-weight:600;font-size:.9rem;cursor:pointer;
}
.prof:hover{background:var(--surf2)}
.prof.is-on{background:var(--surf2);box-shadow:inset 2px 0 0 var(--accent)}
.prof-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.prof-n{font-size:.75rem;color:var(--text3);font-variant-numeric:tabular-nums}
.acct-item--sm{min-height:36px;font-size:.83rem;font-weight:600;color:var(--text2)}
.acct-item--danger{color:var(--accent)}
.acct-sep{height:1px;background:var(--line);margin:6px 2px}
.acct-legal{
  font-size:.72rem;color:var(--text3);line-height:1.5;padding:8px 10px 4px;margin:0;
}
.acct-legal a{color:var(--text2)}

/* ── description ────────────────────────────────────── */
/* Collapsed by default: it's reference material, not the point of the page. A wall of blurb
   sitting above your own notes gets the priority exactly backwards. */
.blurb{
  background:var(--surf); border:1px solid var(--line); border-radius:var(--radius);
  margin-bottom:12px; overflow:hidden;
}
.blurb summary{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:13px 14px; cursor:pointer; list-style:none;
  font-family:var(--font); font-weight:700; font-size:1.02rem;
}
.blurb summary::-webkit-details-marker{display:none}
.blurb summary::after{
  content:'▾'; color:var(--text3); font-size:.8rem; transition:transform .15s ease;
}
.blurb[open] summary::after{transform:rotate(180deg)}
.blurb-src{
  font-family:var(--sans); font-size:.66rem; font-weight:700; letter-spacing:.06em;
  text-transform:uppercase; color:var(--text3); margin-left:auto; margin-right:6px;
}
.blurb[data-empty] summary{color:var(--text2)}
.blurb-body{padding:0 14px 14px}
.blurb-body p{
  font-family:var(--font); font-size:.95rem; line-height:1.65; color:var(--text);
  margin:0 0 10px;
}
.blurb-body p.tiny{font-family:var(--sans);font-size:.74rem;line-height:1.6;color:var(--text3)}

/* ── account ────────────────────────────────────────── */
.acct-wrap{position:relative}
.acct-btn{display:flex;align-items:center;gap:7px;padding:0 8px}
.acct-label{font-size:.85rem;font-weight:600}
.avatar{
  width:28px;height:28px;border-radius:50%;flex:none;overflow:hidden;
  display:flex;align-items:center;justify-content:center;
  background:var(--surf2);border:1px solid var(--line2);
  font-size:.72rem;font-weight:800;color:var(--text3);letter-spacing:.02em;
}
.avatar.is-in{background:var(--accent);border-color:var(--accent);color:var(--accent-t)}
.avatar img{width:100%;height:100%;object-fit:cover;display:block}

.acct-menu{
  position:absolute; right:0; top:calc(100% + 8px); z-index:50;
  width:min(300px,calc(100vw - 28px));
  background:var(--surf); border:1px solid var(--line2); border-radius:var(--radius);
  box-shadow:0 14px 44px rgba(0,0,0,.24); padding:6px; overflow:hidden;
}
.acct-head{padding:10px 10px 8px}
.acct-name{font-family:var(--font);font-weight:700;font-size:.98rem;line-height:1.25}
.acct-mail{font-size:.8rem;color:var(--text2);margin-top:3px;line-height:1.45}
.acct-note{
  font-size:.76rem;color:var(--text3);padding:8px 10px;margin:2px 0 6px;
  background:var(--surf2);border-radius:7px;line-height:1.5;
}
.acct-item{
  display:block;width:100%;text-align:left;
  min-height:42px;padding:0 10px;border:0;border-radius:8px;
  background:none;color:var(--text);font:inherit;font-weight:600;font-size:.9rem;
  cursor:pointer;
}
.acct-item:hover{background:var(--surf2)}
.acct-item--primary{background:var(--accent);color:var(--accent-t);margin-bottom:4px}
.acct-item--primary:hover{background:var(--accent);filter:brightness(1.08)}

/* Quiet by default — it only speaks when it has something to say. */
.sync-pill{
  position:fixed; left:50%; transform:translateX(-50%); z-index:55;
  top:calc(64px + env(safe-area-inset-top));
  background:var(--surf); border:1px solid var(--line2); color:var(--text2);
  padding:6px 14px; border-radius:99px; font-size:.78rem; font-weight:600;
  box-shadow:0 4px 16px rgba(0,0,0,.16);
}

/* ── toast ──────────────────────────────────────────── */
.toast{
  position:fixed; left:50%; transform:translateX(-50%);
  bottom:calc(76px + env(safe-area-inset-bottom)); z-index:60;
  background:var(--text); color:var(--bg); padding:10px 16px; border-radius:99px;
  font-size:.86rem; font-weight:600; box-shadow:0 6px 20px rgba(0,0,0,.22);
  max-width:calc(100vw - 32px); text-align:center;
}
@media(min-width:900px){ .toast{bottom:24px} }

/* ── import ─────────────────────────────────────────── */
.drop{
  border:2px dashed var(--line2); border-radius:var(--radius);
  padding:30px 18px; text-align:center; background:var(--surf);
}
.drop.over{border-color:var(--accent);background:var(--surf2)}
table.prev{width:100%;border-collapse:collapse;font-size:.82rem}
table.prev th,table.prev td{text-align:left;padding:6px 8px;border-bottom:1px solid var(--line)}
table.prev th{color:var(--text2);font-size:.7rem;text-transform:uppercase;letter-spacing:.06em}
.scrollx{overflow-x:auto;-webkit-overflow-scrolling:touch}

/* ── stats ──────────────────────────────────────────── */
.tiles{display:grid;gap:10px;grid-template-columns:1fr 1fr}
@media(min-width:700px){ .tiles{grid-template-columns:repeat(4,1fr)} }
.tile{background:var(--surf);border:1px solid var(--line);border-radius:var(--radius);padding:14px}
.tile .n{font-family:var(--font);font-size:1.7rem;font-weight:700;line-height:1;font-variant-numeric:tabular-nums}
.tile .l{font-size:.74rem;text-transform:uppercase;letter-spacing:.07em;color:var(--text2);margin-top:5px}

@media(prefers-reduced-motion:reduce){ *{transition:none !important;animation:none !important} }
