/* ============================================================================
   DALFAST Premium 3D eBook Reader — Stylesheet
   Design system: navy nav, gold accents, white space, soft shadows.
   All colours are driven by CSS variables so themes can be swapped in one place.
   ========================================================================== */

:root{
  --bg:#FFFFFF;
  --bg-soft:#F5F7FA;

  --navy:#0B1F3B;
  --navy-2:#143462;

  --gold:#C99B2E;
  --gold-text:#A87F1F;
  --gold-soft:#F3E7C9;

  --orange:#E8913A;

  --ink:#14202E;
  --ink-soft:#5B6B7E;

  --line:#E3E8EF;

  --radius:14px;
  --shadow-card:0 10px 30px -18px rgba(11,31,59,.25);

  /* Reader-specific derived tokens */
  --toolbar-h:60px;
  --panel-w:320px;
  --page-shadow:0 18px 40px -16px rgba(11,31,59,.45);
  --ease:cubic-bezier(.22,.61,.36,1);
  --ease-flip:cubic-bezier(.36,.06,.16,1);   /* weighty page-turn arc */
  --flip-ms:680ms;
}

/* ---------- Reset / base ------------------------------------------------- */
*{box-sizing:border-box;}
html,body{height:100%;}
body{
  margin:0;
  font:15px/1.55 'Segoe UI','Helvetica Neue',Arial,sans-serif;
  color:var(--ink);
  background:var(--bg-soft);
  -webkit-font-smoothing:antialiased;
  overflow:hidden;
}
button{font:inherit;color:inherit;cursor:pointer;}
:focus-visible{outline:3px solid var(--gold);outline-offset:2px;border-radius:6px;}

/* Screen-reader-only text */
.sr-only{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0,0,0,0);white-space:nowrap;border:0;
}

/* ---------- App shell ---------------------------------------------------- */
.reader{
  display:flex;flex-direction:column;
  height:100vh;height:100dvh;width:100%;
  background:var(--bg-soft);
}

/* ---------- Top toolbar -------------------------------------------------- */
.toolbar{
  height:var(--toolbar-h);flex:0 0 var(--toolbar-h);
  display:flex;align-items:center;gap:6px;
  padding:0 14px;
  background:var(--navy);color:#fff;
  box-shadow:0 2px 14px -6px rgba(11,31,59,.6);
  z-index:40;position:relative;
  transition:transform .35s var(--ease),opacity .35s var(--ease);
}
.toolbar .brand{
  display:flex;align-items:center;gap:10px;font-weight:700;letter-spacing:.02em;
  margin-right:6px;white-space:nowrap;
  text-decoration:none;color:inherit;cursor:pointer;
}
.toolbar .brand svg{width:30px;height:30px;flex:0 0 30px;}
.toolbar .brand .name{display:flex;flex-direction:column;line-height:1.05;font-size:12px;}
.toolbar .brand .name span{font-weight:750;}
.toolbar .brand .name small{margin-top:3px;color:var(--gold);font-size:10px;font-weight:700;letter-spacing:.06em;}
.toolbar .brand .name small .dph{color:#fff;}
.toolbar .title{
  font-size:13px;color:#cdd7e6;max-width:26ch;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.toolbar .spacer{flex:1 1 auto;}

.tgroup[hidden]{display:none;}   /* display:flex below is an author rule and would otherwise beat the UA [hidden] default — e.g. #installGroup would show on every load, not just when installable */
.tgroup{display:flex;align-items:center;gap:2px;}
.tgroup + .tgroup{margin-left:6px;padding-left:8px;border-left:1px solid rgba(255,255,255,.14);}

.tbtn[hidden]{display:none;}   /* .tbtn's own display:inline-flex below is an author rule and would otherwise beat the UA [hidden] default */
.tbtn{
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
  min-width:38px;height:38px;padding:0 9px;
  background:transparent;border:0;border-radius:10px;color:#eaf0f8;
  transition:background .18s var(--ease),color .18s var(--ease),transform .12s var(--ease);
  text-decoration:none;cursor:pointer;
}
.tbtn svg{width:19px;height:19px;pointer-events:none;}
.tbtn:hover{background:rgba(255,255,255,.12);}
.tbtn:active{transform:translateY(1px);}
.tbtn[aria-pressed="true"],.tbtn.active{background:var(--gold);color:var(--navy);}
.tbtn[disabled]{opacity:.35;cursor:not-allowed;}
.tbtn .lbl{font-size:13px;font-weight:600;}

.pagebox{
  display:flex;align-items:center;gap:6px;font-size:13px;color:#cdd7e6;
  padding:4px 12px;white-space:nowrap;
  background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.15);border-radius:22px;
}
.pagebox input{
  width:52px;height:32px;text-align:center;border-radius:8px;border:1px solid rgba(255,255,255,.2);
  background:rgba(255,255,255,.08);color:#fff;font:inherit;
}
.zoomlabel{min-width:46px;text-align:center;font-variant-numeric:tabular-nums;font-size:13px;color:#cdd7e6;}
.zoom-fit{height:36px;padding:0 8px;border:0;border-radius:8px;background:transparent;}
.zoom-fit:hover,.zoom-fit:focus-visible{background:rgba(255,255,255,.12);color:#fff;}

/* ---------- Main stage --------------------------------------------------- */
.stage-wrap{position:relative;flex:1 1 auto;min-height:0;display:flex;}
.stage{
  position:relative;flex:1 1 auto;min-width:0;max-width:none;
  display:flex;align-items:center;justify-content:center;
  overflow:hidden;
  background:
    radial-gradient(120% 85% at 50% -4%, #1a2b47 0%, #0d1c33 52%, #071120 100%);
  perspective:2600px;
  touch-action:none;
}
/* soft museum spotlight above the book */
.stage::after{
  content:"";position:absolute;left:50%;top:-8%;width:70%;height:60%;transform:translateX(-50%);
  background:radial-gradient(closest-side, rgba(255,251,240,.16), rgba(255,251,240,0));
  pointer-events:none;filter:blur(8px);z-index:0;
}
.stage.grabbing{cursor:grabbing;}

/* Zoom / pan viewport wrapper (transform applied here) */
.viewport{
  position:relative;
  transform-origin:center center;
  transition:transform .28s var(--ease);
  will-change:transform;
}
.viewport.panning{transition:none;}
.viewport.hover-magnify{transition:transform .18s var(--ease);}

/* Pointer magnification is deliberately desktop-only. Touch and pen users
   keep the existing pinch/double-tap path and never receive a fake hover. */

/* ---------- The book ----------------------------------------------------- */
/* .book holds the 3D leaves. It can spin 360° (cover tour) around Y. */
.book{
  position:relative;
  transform-style:preserve-3d;
  transition:transform var(--flip-ms) var(--ease);
  will-change:transform;
}
.book.spin-anim{transition:transform 1400ms var(--ease);}

/* A leaf = one physical page. Bound at its left edge; flips reveal the next. */
.leaf{
  position:absolute;top:0;left:0;
  transform-style:preserve-3d;
  transform-origin:left center;
  will-change:transform;
  transition:transform var(--flip-ms) var(--ease-flip);
  backface-visibility:hidden;
}
.leaf.dragging{transition:none;}

.face{
  position:absolute;top:0;left:0;width:100%;height:100%;
  backface-visibility:hidden;
  background:#fff;
  overflow:hidden;
  box-shadow:var(--page-shadow);
  border-radius:2px 6px 6px 2px;
}
.face.back{transform:rotateY(180deg);border-radius:6px 2px 2px 6px;}

/* Paper texture + inner gutter shading for realism */
.face::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(90deg, rgba(11,31,59,.10) 0, rgba(11,31,59,0) 6%);
  z-index:3;
}
.face.back::before{background:linear-gradient(-90deg, rgba(11,31,59,.10) 0, rgba(11,31,59,0) 6%);}

/* Dynamic curl/turn shadow overlay used while flipping.
   Intensity is driven by --curl (0→1) so it deepens through the turn. */
.face .curl{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:4;
  background:
    linear-gradient(90deg, rgba(11,31,59,.28) 0%, rgba(11,31,59,.05) 14%, rgba(0,0,0,0) 42%),
    linear-gradient(270deg, rgba(11,31,59,.20) 0%, rgba(0,0,0,0) 30%);
  opacity:0;transition:opacity .25s var(--ease);
}
.leaf.dragging .face .curl,.leaf.turning .face .curl{opacity:var(--curl, .85);}

/* The turning leaf lifts off the stack with a soft cast shadow + sheen. */
.leaf.turning,.leaf.dragging{
  box-shadow:0 30px 60px -24px rgba(11,31,59,.55);
}
.leaf.turning .face,.leaf.dragging .face{
  box-shadow:var(--page-shadow), 0 0 40px -10px rgba(11,31,59,.35);
}

/* The rendered page content scroller inside a face */
.page-content{
  position:absolute;inset:0;overflow:hidden;
  padding:0;
}
.page-content .paper{
  width:100%;height:100%;overflow:hidden;position:relative;
  background:#fff;
  container-type:inline-size;
}
/* Inner page margins — must match the Paginator measurer padding exactly so
   the on-screen page holds the same amount of text it was measured for. */
.page-content .paper .pgflow{
  padding:30px 34px;box-sizing:border-box;height:100%;overflow:hidden;
  /* The day theme's ink, stated rather than inherited. Sepia and night set
     their own further down; without a value here the chain runs all the way
     up to <body>, which the book's own stylesheet is free to repaint — and a
     book authored for a dark ground sets it to near-white. */
  color:var(--ink);
}
/* ── Pages rendered straight from the book's own EPUB ────────────────────
   Each section keeps its original stylesheet, so we supply only the page box.
   Source stylesheets are written for a scrolling window, so a cover sized
   "max-height:80vh" would float in the middle of a fixed page — hence the
   full-bleed override for image-only pages below. */
.page-content .paper .pgflow:has(> .epub-leaf){padding:0;}
.epub-leaf{
  height:100%;width:100%;overflow:hidden;box-sizing:border-box;padding:6% 7%;
}
.epub-leaf > *:first-child{margin-top:0;}
.epub-leaf img{max-width:100%;height:auto;}

/* Full-bleed image pages (cover, divider photos) — flagged deterministically
   server-side by EpubBook::sectionIsFullBleedImage(), not guessed here from
   how deeply each book happens to nest its <img>. Every wrapper between the
   leaf and the image is neutralised so the book's own (scrolling-page) CSS
   can't keep the artwork small or centered in a fixed leaf. */
.epub-leaf[data-fullbleed="1"]{padding:0;}
.epub-leaf[data-fullbleed="1"] :not(style):not(script){
  margin:0;padding:0;display:block;
  width:100%;height:100%;max-width:none;max-height:none;
}
.epub-leaf[data-fullbleed="1"] style,
.epub-leaf[data-fullbleed="1"] script{display:none;}
/* CONTAIN, not cover.
   These are pages of a book, not photographs: the running head, the folio and
   the trim margin all sit at the very edge, and `cover` crops exactly those —
   "COLOR TOWN'S MISSING RAINBOW" arrived as "OLOR TOWN'S", with the page number
   sliced in half. A sample that shows a cropped page is showing the customer
   something that is not the book.
   Letterboxing is the honest trade: every PDF and ebook reader does the same,
   and the leaf's own paper colour makes the spare space read as the page
   surround rather than as a gap. */
.epub-leaf[data-fullbleed="1"] img{
  object-fit:contain;object-position:center;
  background:#0f1723;
}

/* WHILE A PAGE IMAGE IS LOADING
   A full-page illustration is around half a megabyte, and until it arrives the
   browser draws the alt text on a blank white leaf — "Front cover" in the
   corner of an empty page. That is indistinguishable from a broken book, and it
   is the first thing a customer sees on opening something they paid for.

   So alt text is suppressed while loading (color:transparent) and the leaf
   carries a slow sheen instead, which reads as "coming" rather than "missing".
   On genuine failure the alt text is deliberately restored — a page that
   really cannot load should say what it was, not sit blank and silent
   pretending forever that it is still on its way. */
.epub-leaf img{
  color:transparent;
  background-color:#f2f5f9;
  background-image:linear-gradient(100deg,
      rgba(255,255,255,0) 30%, rgba(255,255,255,.55) 50%, rgba(255,255,255,0) 70%);
  background-size:220% 100%;
  background-repeat:no-repeat;
  animation:leaf-shimmer 1.4s ease-in-out infinite;
}
@keyframes leaf-shimmer{
  0%{background-position:120% 0;}
  100%{background-position:-40% 0;}
}
/* Loaded: drop the placeholder entirely so it can never tint the artwork. */
.epub-leaf img.is-loaded{
  animation:none;background-image:none;background-color:transparent;
}
.epub-leaf[data-fullbleed="1"] img.is-loaded{background-color:#0f1723;}

/* Failed: say so, in the book's own voice rather than a browser icon. */
.epub-leaf img.is-failed{
  animation:none;background-image:none;
  background-color:#FDF4F2;color:#9A2B1E;
  font:italic 13px/1.5 Georgia,serif;
  display:flex;align-items:center;justify-content:center;text-align:center;padding:8%;
}

@media (prefers-reduced-motion: reduce){
  .epub-leaf img{animation:none;}
}
/* Cover / full-bleed pages fill edge-to-edge with no page margin — that's
   for full-bleed cover IMAGES. Text-only covers (title, subtitle, imprint)
   need their own inset so long titles can't run past the page edge; a book
   with a real trim size narrower than the old generic default made this an
   actual bug (clipped titles), not just a defensive style. */
.page-content .paper .pgflow:has(> .cover){padding:0;}
.page-content .paper .pgflow > .cover{
  height:100%;box-sizing:border-box;padding:0 8%;
  max-width:100%;overflow-wrap:break-word;word-break:break-word;
}
.page-content .paper .pgflow > .cover h1{
  max-width:100%;overflow-wrap:break-word;word-break:break-word;
  font-size:clamp(15pt,7.5cqw,28pt);
}
.page-content .paper .pgflow > .cover .sub{max-width:100%;overflow-wrap:break-word;}
/* Cover pages built as a single full-bleed image (a <img> as the only or
   first child) should still go fully edge-to-edge — undo the text inset. */
.page-content .paper .pgflow > .cover:has(> img:only-child),
.page-content .paper .pgflow > .cover:has(> p:only-child > img:only-child){
  padding:0;
}
/* Full-page artwork (lookbook / gallery previews) — image fills the page. */
.page-content .paper .pgflow:has(> .fullpage){padding:0;}
.page-content .paper .pgflow > .fullpage{
  height:100%;display:flex;align-items:center;justify-content:center;background:#fff;
}
.page-content .paper .pgflow > .fullpage img{max-width:100%;max-height:100%;object-fit:contain;}
/* Two-page spread layout */
.book.spread-mode{display:flex;}
.book.spread-mode .leaf{position:relative;left:auto;top:auto;}
.book.spread-mode .leaf .face{box-shadow:none;}
.book.spread-mode .leaf.right .face{box-shadow:var(--page-shadow);border-radius:2px 6px 6px 2px;}
.book.spread-mode .leaf.left  .face{box-shadow:var(--page-shadow);border-radius:6px 2px 2px 6px;}

/* Page number badge */
.page-num{
  position:absolute;bottom:10px;font-size:11px;color:var(--ink-soft);
  z-index:5;font-variant-numeric:tabular-nums;
}
.face:not(.back) .page-num{right:16px;}
.face.back  .page-num{left:16px;}
.face.outer-cover .page-num{display:none;}

/* DO NOT NUMBER A PAGE THE PUBLISHER ALREADY NUMBERED.
   A full-bleed page is the publisher's own artwork, and these books carry their
   own furniture inside it — running head across the top, a folio in a coloured
   pill at the foot. The reader was stamping its own number on top of that, so
   every page of every illustrated title showed "27" twice, a few centimetres
   apart, in two different designs. It reads as a rendering fault, and on a
   picture book it is the kind of detail that makes a paid edition feel cheaper
   than the PDF the customer could have opened instead.

   Where the book supplies no furniture — reflowable prose, which has no fixed
   pages of its own — the reader's number is the only one there is, and it stays.
   The rule is simply: whoever owns the page owns the page number. */
.face:has(.epub-leaf[data-fullbleed="1"]) .page-num{display:none;}
/* Fixed-layout PDF pages already carry their publisher folio in the artwork.
   Suppress the reader badge there as well so page numbers are never doubled. */
.face:has(.img-page) .page-num{display:none;}
/* Cover styling (first leaf front) */
.face.cover{
  background:linear-gradient(160deg,var(--navy) 0%,var(--navy-2) 100%);
  color:#fff;display:flex;align-items:center;justify-content:center;
}
.face.cover::after{
  content:"";position:absolute;left:0;top:0;bottom:0;width:14px;
  background:linear-gradient(90deg, rgba(255,255,255,.14), rgba(255,255,255,0));
}

/* Spine plate shown during 360° tour */
.spine{
  position:absolute;top:0;left:50%;height:100%;
  transform-origin:left center;
  background:linear-gradient(90deg,#081729,#0e2647);
  display:flex;align-items:center;justify-content:center;
  color:var(--gold-soft);
  writing-mode:vertical-rl;text-orientation:mixed;
  font-weight:700;letter-spacing:.14em;text-transform:uppercase;font-size:12px;
  box-shadow:inset -6px 0 14px -8px rgba(0,0,0,.6);
  backface-visibility:hidden;
}

/* Loading / empty states */
.stage-msg{
  position:absolute;inset:0;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:14px;color:var(--ink-soft);z-index:20;
}
.stage-msg .spinner{
  width:42px;height:42px;border-radius:50%;
  border:3px solid var(--line);border-top-color:var(--gold);
  animation:spin 1s linear infinite;
}
@keyframes spin{to{transform:rotate(360deg);}}

/* Edge hot-zones for click-to-flip */
.edge{
  position:absolute;top:0;bottom:0;width:11%;max-width:120px;z-index:15;
  cursor:pointer;background:transparent;border:0;
}
.edge.left{left:0;}
.edge.right{right:0;}
.edge:hover{background:linear-gradient(90deg,rgba(11,31,59,.06),transparent);}
.edge.right:hover{background:linear-gradient(-90deg,rgba(11,31,59,.06),transparent);}

/* Floating prev/next arrows */
.nav-arrow{
  position:absolute;top:50%;transform:translateY(-50%);z-index:16;
  width:46px;height:46px;border-radius:50%;border:1px solid var(--line);
  background:rgba(255,255,255,.9);color:var(--navy);
  display:flex;align-items:center;justify-content:center;
  box-shadow:var(--shadow-card);backdrop-filter:blur(4px);
  transition:transform .16s var(--ease),background .16s var(--ease),opacity .2s var(--ease);
}
.nav-arrow:hover{background:#fff;transform:translateY(-50%) scale(1.06);}
.nav-arrow svg{width:22px;height:22px;}
.nav-arrow.prev{left:16px;}
.nav-arrow.next{right:16px;}
.nav-arrow[disabled]{opacity:0;pointer-events:none;}
/* The toolbar and bottom navigator already provide complete, labelled page
   controls. The oversized floating circles duplicated them, obscured the book
   at wide sizes and looked like broken decoration on shorter samples. */
.nav-arrow{display:none!important;}
.edge[hidden]{display:none!important;}

/* ---------- Side panels (TOC / thumbs / bookmarks / notes / search) ------ */
.panel{
  position:absolute;top:0;bottom:0;left:0;width:var(--panel-w);max-width:86vw;
  background:var(--bg);border-right:1px solid var(--line);
  box-shadow:8px 0 30px -20px rgba(11,31,59,.5);
  transform:translateX(-102%);transition:transform .32s var(--ease);
  z-index:30;display:flex;flex-direction:column;
}
.panel.open{transform:translateX(0);}
.panel-head{
  display:flex;align-items:center;justify-content:space-between;
  padding:14px 16px;border-bottom:1px solid var(--line);
}
.panel-head h2{margin:0;font-size:15px;color:var(--navy);letter-spacing:.01em;}
.panel-head .close{
  width:34px;height:34px;border-radius:9px;border:0;background:var(--bg-soft);
  display:flex;align-items:center;justify-content:center;color:var(--ink-soft);
}
.panel-head .close:hover{background:var(--line);}
.panel-body{flex:1 1 auto;overflow-y:auto;padding:10px 12px;}
.format-intro{margin:4px 2px 14px;color:var(--ink-soft);font-size:13px;line-height:1.55;}
.format-grid{display:grid;gap:10px;}
.format-card{display:block;width:100%;padding:14px;text-align:left;border:1px solid var(--line);border-radius:12px;background:#fff;color:var(--ink);}
.format-card:not(:disabled):hover{border-color:var(--gold);box-shadow:0 8px 24px -18px rgba(11,31,59,.55);transform:translateY(-1px);}
.format-card.is-current{border-color:var(--gold);box-shadow:inset 3px 0 0 var(--gold);}
.format-card:disabled{cursor:not-allowed;background:var(--bg-soft);opacity:.78;}
.format-card-top{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;}
.format-card-top strong{font-size:15px;color:var(--navy);}
.format-status{flex:0 0 auto;padding:4px 7px;border-radius:999px;background:#edf2f7;color:var(--ink-soft);font-size:10px;font-weight:700;line-height:1.2;}
.format-status.available,.format-status.published{background:#e7f6ed;color:#17603a;}
.format-status.planned,.format-status.in_development,.format-status.in_review{background:var(--gold-soft);color:var(--gold-text);}
.format-status.review_required{background:#fff1df;color:#8a4d08;}
.format-kind,.format-copy,.format-isbn,.format-current,.format-open{display:block;}
.format-kind{margin-top:7px;font-size:12px;font-weight:700;color:var(--gold-text);text-transform:uppercase;letter-spacing:.07em;}
.format-copy{margin-top:5px;font-size:12px;line-height:1.45;color:var(--ink-soft);}
.format-isbn{margin-top:7px;font-size:12px;font-weight:700;letter-spacing:.025em;color:var(--navy);}
.format-current,.format-open{margin-top:9px;font-size:12px;font-weight:700;color:var(--navy);}
.format-details{display:flex;align-items:center;justify-content:center;min-height:42px;margin-top:14px;border:1px solid var(--line);border-radius:10px;color:var(--navy);font-size:13px;font-weight:700;text-decoration:none;}
.format-details:hover{border-color:var(--gold);background:var(--gold-soft);}

/* TOC */
.toc-item{
  display:block;width:100%;text-align:left;padding:9px 12px;border-radius:10px;
  border:0;background:transparent;color:var(--ink);font-size:14px;margin-bottom:2px;
}
.toc-item:hover{background:var(--bg-soft);}
.toc-item.active{background:var(--gold-soft);color:var(--gold-text);font-weight:600;}
.toc-item.lvl2{padding-left:26px;font-size:13px;color:var(--ink-soft);}

/* Thumbnails */
.thumbs{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;}
.thumb{
  position:relative;border:1px solid var(--line);border-radius:8px;overflow:hidden;
  background:#fff;aspect-ratio:1/1.414;cursor:pointer;padding:0;
  transition:border-color .16s var(--ease),transform .16s var(--ease),box-shadow .16s var(--ease);
}
.thumb:hover{transform:translateY(-2px);box-shadow:var(--shadow-card);}
.thumb.active{border-color:var(--gold);box-shadow:0 0 0 2px var(--gold-soft);}
.thumb .mini{
  position:absolute;inset:0;overflow:hidden;transform-origin:top left;background:#fff;
}
.thumb .tn{
  position:absolute;bottom:0;left:0;right:0;font-size:10px;text-align:center;
  background:rgba(11,31,59,.72);color:#fff;padding:2px 0;
}

/* Bookmarks & notes lists */
.list-empty{color:var(--ink-soft);font-size:13px;text-align:center;padding:26px 10px;}
.rowcard{
  display:flex;align-items:flex-start;gap:10px;padding:10px 12px;border-radius:10px;
  border:1px solid var(--line);margin-bottom:8px;background:#fff;
}
.rowcard .go{flex:1 1 auto;text-align:left;border:0;background:transparent;padding:0;}
.rowcard .go .p{font-size:12px;color:var(--gold-text);font-weight:600;}
.rowcard .go .t{font-size:13px;color:var(--ink);margin-top:2px;}
.rowcard .swatch{width:12px;height:12px;border-radius:3px;flex:0 0 12px;margin-top:4px;}
.rowcard .del{border:0;background:transparent;color:var(--ink-soft);width:26px;height:26px;border-radius:7px;}
.rowcard .del:hover{background:var(--bg-soft);color:#c0392b;}

/* Search box */
.searchbar{display:flex;gap:8px;padding:12px;border-bottom:1px solid var(--line);}
.searchbar input{
  flex:1 1 auto;height:38px;border:1px solid var(--line);border-radius:10px;padding:0 12px;font:inherit;
}
.searchbar button{
  height:38px;padding:0 14px;border-radius:10px;border:0;background:var(--navy);color:#fff;font-weight:600;
}
.search-count{padding:8px 14px;font-size:12px;color:var(--ink-soft);border-bottom:1px solid var(--line);}
.search-hit{
  display:block;width:100%;text-align:left;border:0;background:transparent;
  padding:10px 12px;border-radius:10px;font-size:13px;color:var(--ink);margin-bottom:2px;
}
.search-hit:hover{background:var(--bg-soft);}
.search-hit .p{font-size:11px;color:var(--gold-text);font-weight:600;}
.search-hit mark{background:var(--gold-soft);color:var(--gold-text);padding:0 2px;border-radius:3px;}

/* In-page search highlight + selection highlights */
mark.reader-hl{background:#ffe9a8;color:inherit;border-radius:2px;}
mark.reader-hl.current{background:var(--orange);color:#fff;}
.user-hl{border-radius:2px;padding:0 1px;cursor:pointer;}

/* ---------- Selection popover (highlight / note) ------------------------- */
.sel-pop{
  position:absolute;z-index:60;display:none;
  background:var(--navy);color:#fff;border-radius:12px;padding:8px;gap:6px;
  box-shadow:var(--shadow-card);align-items:center;
}
.sel-pop.show{display:flex;}
.sel-pop .color{width:24px;height:24px;border-radius:6px;border:2px solid rgba(255,255,255,.4);cursor:pointer;}
.sel-pop .color.sel{border-color:#fff;transform:scale(1.08);}
.sel-pop .act{border:0;background:rgba(255,255,255,.14);color:#fff;height:28px;padding:0 10px;border-radius:8px;font-size:12px;}
.sel-pop .act:hover{background:rgba(255,255,255,.26);}

/* Note editor dialog */
.note-dialog{
  position:absolute;z-index:70;width:280px;background:#fff;border-radius:var(--radius);
  box-shadow:var(--shadow-card);border:1px solid var(--line);padding:14px;display:none;
}
.note-dialog.show{display:block;}
.note-dialog textarea{
  width:100%;min-height:88px;resize:vertical;border:1px solid var(--line);border-radius:10px;
  padding:10px;font:inherit;
}
.note-dialog .row{display:flex;justify-content:flex-end;gap:8px;margin-top:10px;}
.note-dialog .row button{height:34px;padding:0 14px;border-radius:9px;border:0;font-weight:600;}
.note-dialog .save{background:var(--navy);color:#fff;}
.note-dialog .cancel{background:var(--bg-soft);color:var(--ink);}

/* ---------- Bottom bar: dark floating control pill ------------------------ */
.bottombar{
  position:relative;z-index:35;flex:0 0 auto;
  display:flex;align-items:center;gap:10px;
  width:max-content;max-width:calc(100% - 24px);margin:0 auto 14px;padding:8px 14px;
  background:rgba(9,20,37,.94);border:1px solid rgba(255,255,255,.12);border-radius:32px;
  box-shadow:0 14px 34px -16px rgba(0,0,0,.7);backdrop-filter:blur(8px);
  transition:transform .35s var(--ease),opacity .35s var(--ease);
}
.bottombar .bbtn{
  width:38px;height:38px;border-radius:50%;border:0;background:transparent;color:#eaf0f8;
  display:flex;align-items:center;justify-content:center;transition:background .16s var(--ease);
}
.bottombar .bbtn:hover{background:rgba(255,255,255,.12);}
.bottombar .bbtn[disabled]{opacity:.32;cursor:not-allowed;}
.bottombar .bbtn svg{width:19px;height:19px;}
.slider{width:clamp(120px,30vw,260px);flex:0 0 auto;-webkit-appearance:none;appearance:none;height:5px;border-radius:6px;background:rgba(255,255,255,.18);}
.slider::-webkit-slider-thumb{
  -webkit-appearance:none;width:16px;height:16px;border-radius:50%;background:var(--gold);
  box-shadow:0 2px 6px -1px rgba(0,0,0,.5);cursor:pointer;border:2px solid #fff;
}
.slider::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background:var(--gold);border:2px solid #fff;cursor:pointer;}
.bottombar .count{font-size:12px;color:#cdd7e6;white-space:nowrap;font-variant-numeric:tabular-nums;padding:0 4px;}

/* ---------- Fullscreen / immersive --------------------------------------- */
.reader.immersive .toolbar{transform:translateY(-100%);opacity:0;pointer-events:none;}
.reader.immersive .bottombar{transform:translateY(100%);opacity:0;pointer-events:none;}
.reader.immersive .stage{background:radial-gradient(120% 85% at 50% 0%, #16273f, #060f1d);}
.immersive-exit{
  position:absolute;top:14px;right:14px;z-index:50;display:none;
  width:42px;height:42px;border-radius:50%;border:0;background:rgba(11,31,59,.86);color:#fff;
  align-items:center;justify-content:center;box-shadow:var(--shadow-card);
}
.reader.immersive .immersive-exit{display:flex;}

/* Scrim for panels on mobile */
.scrim{
  position:absolute;inset:0;background:rgba(11,31,59,.32);z-index:25;opacity:0;
  pointer-events:none;transition:opacity .3s var(--ease);
}
.scrim.show{opacity:1;pointer-events:auto;}

/* ---------- Responsive --------------------------------------------------- */
@media (max-width:900px){
  .toolbar .brand .name,.toolbar .title{display:none;}
  .tbtn .lbl{display:none;}
  :root{--panel-w:300px;}
}
@media (max-width:620px){
  :root{--toolbar-h:54px;}
  .tgroup.optional{display:none;}         /* hide secondary groups on small screens */
  .nav-arrow{width:40px;height:40px;}
  .bottombar{padding:8px 12px;gap:10px;}

  /* PHONE TOOLBAR
     Measured on the live reader: the toolbar needs 686px. A 390px phone was
     therefore 300px short, and because the page does not scroll sideways
     those controls were not merely off-screen, they were unreachable. The
     two .optional groups were already hidden and did not come close to
     closing the gap.

     Two changes. First, everything the bottom bar already provides comes
     out of the top bar: first/prev/next/last are the same four actions as
     the bottom bar arrows, and on a phone the bottom bar is the one within
     thumb reach, so the duplicates are pure cost. The page box stays, since
     jump-to-page exists nowhere else. Thumbnails go too, because a grid of
     page images at this width cannot be read and Contents does the same job
     better. Fullscreen goes because immersive mode covers it and iOS Safari
     does not honour requestFullscreen anyway.

     Second, whatever survives is allowed to scroll. Install appears only on
     installable devices, so the row can still exceed the viewport by a
     button or two on some phones; a swipe reaches it rather than it being
     lost. The scrollbar is hidden because a visible one inside a 54px chrome
     bar reads as damage. */
  #thumbsBtn,#firstBtn,#prevBtn,#nextBtn,#lastBtn,#fullBtn{display:none;}
  /* The remaining 80px comes out of spacing, not out of the buttons. A 38px
     target is already under the 44px anyone recommends for a thumb, so
     shrinking the controls to make the row fit would trade a visible bug for
     an invisible one. Padding, gaps and group dividers give it up instead. */
  .toolbar{padding:0 8px;gap:4px;}
  .tgroup + .tgroup{margin-left:4px;padding-left:5px;}
  .pagebox{padding:4px 8px;gap:4px;}
  .pagebox input{width:44px;}
  .toolbar{
    overflow-x:auto;overflow-y:hidden;
    -webkit-overflow-scrolling:touch;
    scrollbar-width:none;
  }
  .toolbar::-webkit-scrollbar{display:none;}
  /* Nothing may shrink below its own size, or the icons squash instead of
     the row scrolling. */
  .toolbar > *{flex:0 0 auto;}
  .toolbar .spacer{display:none;}
}

/* ---------- Reduced motion ----------------------------------------------- */
@media (prefers-reduced-motion:reduce){
  .book,.leaf,.face,.viewport,.panel,.toolbar,.bottombar,.nav-arrow{transition-duration:.01ms !important;}
  .book.spin-anim{transition-duration:.01ms !important;}
  .spinner{animation-duration:1.4s;}
}

/* ---------------------------------------------------------------------- *
 *  Reading settings
 *
 *  Segmented buttons rather than sliders or a dropdown: a reader adjusting
 *  text size on a phone is doing it because reading is uncomfortable right
 *  now, and a four-option row is one tap with a visible current state. A
 *  slider needs a drag and shows no label; a <select> hides every option
 *  until it is opened.
 * ---------------------------------------------------------------------- */
.set-group{margin:0 0 4px;}
.set-label{
  margin:14px 0 6px;font-size:11px;font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-soft);
}
.set-label:first-child{margin-top:2px;}
.set-row{display:flex;gap:6px;flex-wrap:wrap;}
.set-opt{
  flex:1 1 auto;min-width:64px;min-height:40px;padding:0 10px;
  border:1px solid var(--line);border-radius:9px;background:transparent;
  color:var(--ink);font:600 13px/1 inherit;cursor:pointer;
}
.set-opt:hover{background:var(--gold-soft);}
.set-opt[aria-pressed="true"]{
  background:var(--navy);border-color:var(--navy);color:#fff;
}
.set-opt:focus-visible{outline:2px solid var(--gold);outline-offset:2px;}

.set-reset{
  margin-top:18px;width:100%;min-height:40px;border:1px solid var(--line);
  border-radius:9px;background:transparent;color:var(--ink-soft);
  font:600 13px/1 inherit;cursor:pointer;
}
.set-reset:hover{color:var(--ink);background:var(--gold-soft);}
.set-note{margin:10px 0 0;font-size:12px;line-height:1.5;color:var(--ink-soft);}

/* The settings themselves. Applied to the page content only — never to the
   chrome, so a "Bold" choice does not embolden the toolbar as well.

   BOTH containers, because the reader has two rendering paths: .pgflow for
   HTML books and .epub-leaf for EPUB. Styling only .pgflow silently did
   nothing to every EPUB in the catalogue, which is currently all of them. */
.pgflow, .epub-leaf{
  font-size:calc(1em * var(--read-size, 1));
  font-weight:var(--read-weight, 400);
  line-height:var(--read-lead, 1.6);
}
/* THE PUBLISHER WINS UNTIL THE READER ASKS.
   A book carries its own stylesheet, injected after this one, and it usually
   sets an absolute size on its paragraphs — The Focused Founder sets 13pt. So
   inheritance alone changed nothing: choosing Bold or Largest moved a variable
   that every paragraph then ignored, and the control looked broken.

   Overriding by default would be worse: it would throw away the typography of
   every book in the catalogue to make a setting work that most readers never
   touch. So the override switches on only once somebody has actually chosen
   something — [data-readcustom] — and only for body text. Headings keep their
   own scale, or a chapter title ends up the same size as the prose under it. */
.pgflow :is(p, li, blockquote, td, th, dd, dt),
.epub-leaf:not([data-fullbleed="1"]) :is(p, li, blockquote, td, th, dd, dt){font-weight:inherit;}

/* ONE PROPERTY PER CONTROL.
   These were a single rule behind one flag, so choosing Bold also replaced the
   publisher's font size — the text went bold and, on a 13pt book, visibly
   smaller at the same time. Nobody asking for bold text is asking for smaller
   text. Each control now overrides only what it is named after, and a property
   nobody has touched stays exactly as the book set it. */
.reader[data-set-size="1"] .pgflow :is(p, li, blockquote, td, th, dd, dt), .reader[data-set-size="1"] .epub-leaf:not([data-fullbleed="1"]) :is(p, li, blockquote, td, th, dd, dt){
  font-size:calc(1rem * var(--read-size, 1)) !important;
}
.reader[data-set-weight="1"] .pgflow :is(p, li, blockquote, td, th, dd, dt), .reader[data-set-weight="1"] .epub-leaf:not([data-fullbleed="1"]) :is(p, li, blockquote, td, th, dd, dt){
  font-weight:var(--read-weight, 400) !important;
}
.reader[data-set-lead="1"] .pgflow :is(p, li, blockquote, td, th, dd, dt), .reader[data-set-lead="1"] .epub-leaf:not([data-fullbleed="1"]) :is(p, li, blockquote, td, th, dd, dt){
  line-height:var(--read-lead, 1.6) !important;
}
/* A full-bleed page is a single image. Nothing here applies to it, and the
   settings panel says so rather than offering controls that do nothing. */
.epub-leaf[data-fullbleed="1"]{font-size:inherit;font-weight:inherit;}

/* Page colour. Only the paper and its text — the surround follows, so the
   book never sits as a bright card on a dark stage or the reverse. */
.reader[data-readtheme="sepia"] .paper{background:#FBF3E4;color:#3A3226;}
.reader[data-readtheme="sepia"] .page-content .paper .pgflow{color:#3A3226;background-color:transparent !important;}
.reader[data-readtheme="sepia"] .stage{background:#E8DCC6;}

.reader[data-readtheme="night"] .paper{background:#15171C;color:#E7EBF0;}
.reader[data-readtheme="night"] .page-content .paper .pgflow{color:#E7EBF0;background-color:transparent !important;}
.reader[data-readtheme="night"] .stage{background:#0A0B0E;}
.reader[data-readtheme="night"] .page-num{color:#7C8794;}
/* Artwork is not re-coloured — dimming a children's illustration to match a
   dark theme changes the book, which is not ours to do. */

/* ── THE READER SUPPLIES THE PAPER, SO IT MUST SUPPLY THE INK ────────────
   A book's stylesheet travels with its pages, and the theme rules above set
   the colour on .pgflow — which a book's own `h1 { color: … }` out-specifies
   without trying. That is invisible until a book is authored for a dark
   background: "Work With AI, Stay Essential" ships its title at #D7E7EF,
   which on the reader's white sheet is a contrast ratio of 1.2:1 against a
   floor of 4.5:1. The page looked blank. Nothing had failed — the book was
   correct on its own dark ground, and the reader was correct to paint white
   paper; only the combination was unreadable, and nothing in either half
   could detect it alone.

   `inherit` rather than a fixed colour deliberately: the value then comes
   from .pgflow, so day, sepia and night each keep their own ink and this
   stays one rule instead of three that can drift apart. At twenty thousand
   books nobody can audit each stylesheet, so legibility has to be structural
   rather than a property of the book that happens to be open.

   Everything else the book asked for is untouched — typeface, size, weight,
   spacing, alignment, artwork. Only colour is claimed, and only where the
   reader is what painted the surface underneath. */
.pgflow,
.pgflow *:not(img):not(svg):not(picture):not(video):not(canvas),
.epub-leaf:not([data-fullbleed="1"]),
.epub-leaf:not([data-fullbleed="1"]) *:not(img):not(svg):not(picture):not(video):not(canvas){
  color:inherit !important;
  background-color:transparent !important;
}
/* Links lose their colour with everything else, so they carry the underline
   instead — identifiable in any theme, and readable in all of them. */
.pgflow a,
.epub-leaf:not([data-fullbleed="1"]) a{text-decoration:underline;}

/* ---------------------------------------------------------------------- *
 *  PROTECT THE APPLICATION SHELL FROM THE BOOK'S OWN STYLESHEET
 *
 *  A book carries its own CSS, and a <style> tag applies to the WHOLE
 *  document no matter how deeply it is nested — so putting book CSS inside
 *  the page does not contain it. Before the Leap ships
 *
 *      body { margin: 5%; }
 *
 *  which is a perfectly ordinary thing for an EPUB to say, and it was
 *  styling the READER's body: the entire application was inset by 18.76px a
 *  side, the toolbar ran off the right edge with the page counter cut in
 *  half, and the book — already sized against the wider stage — ended up 361px
 *  across inside a 338px frame, clipped ~12px on each side.
 *
 *  This is deliberately the smallest possible answer. An earlier attempt
 *  rewrote every book's stylesheet at render time to scope it; that touched
 *  every page of every book and caused more problems than it solved. Here
 *  nothing about the book is altered — only the two elements that belong to
 *  the application are made non-negotiable. Book content lives in .pgflow and
 *  .epub-leaf and is completely unaffected, including that same `body` rule,
 *  which never applied to it either way.
 * ---------------------------------------------------------------------- */
html, body {
  margin: 0 !important;
  padding: 0 !important;
}

/* Comfortable online reading, shared by authorised full editions and samples. */
.continuous-reader .stage{display:block;overflow-y:auto;overflow-x:hidden;padding:18px 12px;scrollbar-gutter:stable;}
.continuous-reader .viewport{display:block;width:100%;height:auto;transform:none!important;perspective:none;}
.continuous-reader .book{position:relative;margin:0 auto;width:min(100%,680px)!important;height:auto!important;transform:none!important;box-shadow:none;}
.continuous-reader .reading-sheet{position:relative;background:#fff;color:var(--ink);margin:0 auto 22px;box-shadow:0 4px 18px #0002;border-radius:3px;overflow:hidden;overflow-wrap:anywhere;}
.continuous-reader .reading-sheet .pgflow,.continuous-reader .reading-sheet .epub-leaf{height:auto!important;min-height:0;overflow:visible!important;padding:32px 28px;transform:none!important;width:100%!important;}
.continuous-reader .reading-sheet.reading-cover{max-width:min(420px,calc((100dvh - 140px)/1.5));background:transparent;box-shadow:none;}
.continuous-reader .reading-cover .pgflow,.continuous-reader .reading-cover .epub-leaf,.continuous-reader .reading-cover :is(p,div,section){padding:0!important;margin:0!important;height:auto!important;min-height:0!important;max-height:none!important;}
.continuous-reader .reading-cover img{display:block;width:100%!important;height:auto!important;max-height:none!important;object-fit:contain;}
.reader.continuous-reader .reading-sheet :is(p,li,blockquote,td,th,dd,dt){font-size:calc(18px * var(--read-size,1))!important;line-height:var(--read-lead,1.6)!important;}
.continuous-reader .reading-sheet :is(p,li,blockquote,td,th,dd,dt) span{font-size:inherit!important;line-height:inherit!important;}
.continuous-reader .reading-sheet table{width:100%;max-width:100%;table-layout:fixed;}
.continuous-reader .reading-sheet img{max-width:100%;}
.continuous-reader .edge,.continuous-reader .nav-arrow{display:none!important;}
.continuous-reader .tgroup:has(#zoomInBtn),.continuous-reader .tgroup:has(#firstBtn),.continuous-reader #spreadBtn,.continuous-reader #spinBtn{display:none;}
.toolbar{overflow-x:auto;min-width:0;}.toolbar .tgroup{flex-shrink:0;}
.reader[data-device="phone"] .book{max-width:360px;}.reader[data-device="tablet"] .book{max-width:640px;}
.reader-device{display:flex;align-items:center;gap:6px;font-size:13px;white-space:nowrap;}.reader-device select{font:inherit;background:#143462;color:#fff;border:1px solid #71819a;border-radius:8px;padding:8px;min-height:38px;}
.reader-download-panel[hidden]{display:none;}.reader-download-panel{position:fixed;z-index:70;top:74px;right:16px;width:min(360px,calc(100vw - 32px));background:#fff;color:#14202E;border:1px solid #dce3ec;border-radius:14px;box-shadow:0 12px 40px #0005;padding:22px;line-height:1.55;}.reader-download-panel a{display:block;padding:12px;margin:12px 0;border:1px solid #c99b2e;border-radius:8px;color:#0B1F3B;text-decoration:none;font-weight:600;}.reader-download-panel a[hidden]{display:none;}.reader-download-panel button{float:right;border:0;background:#eef2f7;border-radius:8px;min-width:44px;min-height:44px;}.reader-download-panel h2{margin-top:0;font-size:20px;}
.continuous-reader[data-readtheme="sepia"] .reading-sheet:not(.reading-cover){background:#FBF3E4;color:#3A3226;}
.continuous-reader[data-readtheme="night"] .reading-sheet:not(.reading-cover){background:#15171C;color:#E7EBF0;}
@media(max-width:760px){.continuous-reader .stage{padding:12px 6px;}.continuous-reader .reading-sheet .pgflow,.continuous-reader .reading-sheet .epub-leaf{padding:24px 20px;}.toolbar{overflow-x:auto;}.toolbar .tgroup{flex-shrink:0;}#libraryReaderLink{white-space:nowrap;}}
.reader-download-panel{box-sizing:border-box;max-height:calc(100dvh - 94px);overflow-y:auto;overscroll-behavior:contain;}.reader-download-panel button:not([aria-label]){float:none;display:inline-block;margin:6px 4px 6px 0;padding:8px 12px;font:inherit;} .reader-download-panel label{display:block;margin-top:14px;}

.reader-sample-end{box-sizing:border-box;padding:22px 26px;text-align:left;font-family:system-ui,sans-serif;}
.reader-sample-end h2{font-size:20px!important;line-height:1.3;margin:0 0 10px;}
.reader-sample-end p{margin:0 0 16px;line-height:1.5!important;text-indent:0;}
.sample-end-actions{display:flex;flex-wrap:wrap;gap:10px;}
.sample-end-actions a{display:inline-flex;align-items:center;min-height:44px;padding:8px 16px;box-sizing:border-box;border:1px solid #9ba8b8;border-radius:8px;color:inherit;text-decoration:none;font-weight:600;}
.sample-end-actions a:first-child{background:#0b1f3b;color:#fff;border-color:#0b1f3b;}
.sample-end-actions a:focus-visible{outline:3px solid #c99b2e;outline-offset:3px;}
.continuous-reader .reading-sheet:has(>.reader-sample-end){min-height:0;height:auto;box-shadow:none;border:1px solid #dce3eb;border-radius:10px;}
.reader.continuous-reader{--reading-max-width:420px;--reading-width:min(var(--reading-max-width),calc((100dvh - 140px)/1.5),calc(100vw - 24px));}.reader.continuous-reader[data-device="phone"]{--reading-max-width:360px;}.reader.continuous-reader .book{width:var(--reading-width)!important;max-width:var(--reading-width)!important;}.reader.continuous-reader .reading-sheet{width:100%;min-height:calc(var(--reading-width) * 1.5);}.reader.continuous-reader .reading-sheet.reading-cover{max-width:100%;min-height:0;}.reader.continuous-reader .reading-sheet:has(>.reader-sample-end){min-height:0;}
.reader.continuous-reader .reading-sheet:not(.reading-cover) :is(.pgflow,.epub-leaf){font-family:Georgia,"Times New Roman",serif;}.reader.continuous-reader .reading-sheet:not(.reading-cover) p{margin-block:.35em!important;}.reader.continuous-reader .reading-sheet:not(.reading-cover) p.TOC{margin-block:.12em!important;}.reader.continuous-reader:not([data-set-lead="1"]) .reading-sheet:not(.reading-cover) :is(p,li,blockquote,td,th,dd,dt){line-height:1.4!important;}.reader.continuous-reader .reading-sheet:not(.reading-cover) :is(h1,h2,h3){line-height:1.25;}.reader.continuous-reader .reader-sample-end p{margin:0 0 16px!important;}

.book.sample-ending-card{background:#fff;color:#0b1f3b;border-radius:12px;box-shadow:0 4px 20px #0002;overflow:hidden;}
