/* The page around the screens in a browser: safe areas, the dynamic viewport, no sideways
   scrolling, the first paint before the WebAssembly, dropping files, menus above everything. */

:root {
  --sat: env(safe-area-inset-top, 0px);
  --sab: env(safe-area-inset-bottom, 0px);
  --sal: env(safe-area-inset-left, 0px);
  --sar: env(safe-area-inset-right, 0px);
}
/* A phone must not enlarge the text by itself, pull the page about or flash what is tapped. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
/* Prevent browser overscroll and a sideways document outside the app panes. */
html, body { overflow-x: hidden; overscroll-behavior: none; }
/* Suppress the browser's default highlight on touch controls. */
body { -webkit-tap-highlight-color: transparent; }
#main { min-height: 100%; }

/* Before the WebAssembly arrives */
.boot { height: 100vh; height: 100dvh; display: flex; align-items: center; justify-content: center; text-align: center; padding: 24px; }

/* The window: dvh follows the phone's moving address bar. */
.app { height: 100vh; height: 100dvh; min-width: 0; min-height: 0; } /* the desktop window's minimum size does not apply */
.content { padding-left: max(28px, var(--sal)); padding-right: max(28px, var(--sar)); }
/* The Library's sticky top reaches over this padding. */
.lib-top { margin-left: calc(-1 * max(28px, var(--sal))); margin-right: calc(-1 * max(28px, var(--sar))); padding-left: max(28px, var(--sal)); padding-right: max(28px, var(--sar)); }
/* The first-run and failure screens fill the dynamic viewport too. */
.splash { height: 100vh; height: 100dvh; display: flex; flex-direction: column; align-items: center; justify-content: center; margin: auto; }

/* Dropping files on the page */
.drop-overlay {
  display: none; position: fixed; inset: 0; z-index: 90; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, 0.8); pointer-events: none; padding: 20px;
}
body.dragging .drop-overlay { display: flex; }
.drop-card {
  display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center;
  border: 2px dashed var(--accent); border-radius: 18px; padding: 40px 48px; background: var(--panel);
}

/* Menus */
.import-anchor .menu { right: 0; }
/* Above the tab bar and the settings sheet of a phone. */
.menu-scrim { z-index: 70; }
/* Menus must sit above the browser tab bar and mobile settings sheet too. */
.menu { z-index: 71; }

@media (prefers-reduced-motion: reduce) {
  * { scroll-behavior: auto !important; }
}
.app[data-motion="snappy"] .desk-slide { animation: none; }

/* The reader in a browser: touch, pinch and the dynamic viewport. */

.reader-stage {
  touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-user-select: none; user-select: none;
  -webkit-touch-callout: none; padding-bottom: 0;
}
/* A touch on a page is the reader's (pinch, swipe), not the picture's. */
.reader-tile img { pointer-events: none; }
/* Not zoomed: only vertical drags pan. */
.reader[data-hpan="no"] .reader-stage { touch-action: pan-y; }
/* A touch target, and a menu that follows the phone's address bar. */
.reader-end .btn { min-height: 44px; }
/* Keep the chapter list within the browser's changing viewport height. */
.reader-menu { max-height: 60vh; max-height: 60dvh; }

/* Tablets and phones: 44 px targets and dialogs that fill the screen. The dock and the corner bar are the
   same as on a computer (crates/ui/css/shell.css). */

/* Settings rows stack on narrow screens */
@media (max-width: 700px) {
  .sx-row { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .sx-control { justify-content: flex-start; }
  .sx-control .seg { width: 100%; }
  /* The reader form's buttons: Remove and Reset share a row, Save has the whole row under them. */
  .form-footer { flex-wrap: wrap; gap: 10px; }
  .form-footer > .grow { display: none; }
  .form-footer > .btn { flex: 1 1 0; min-width: 0; justify-content: center; }
  .form-footer > .btn.primary { flex: 1 1 100%; }
}

/* ---- tablets and phones ---- */
@media (max-width: 800px) {
  .content { padding: calc(14px + var(--sat)) max(14px, var(--sar)) calc(170px + var(--sab)) max(14px, var(--sal)); }
  h1 { font-size: 1.35rem; }

  /* 44px targets */
  .btn { min-height: 44px; }
  .btn.small, .btn.ghost.small { min-height: 40px; }
  .seg button { min-height: 44px; }
  .pill { min-height: 40px; display: inline-flex; align-items: center; }
  .menu-item { min-height: 46px; }
  select, input[type="text"], input[type="search"], input[type="number"] { min-height: 44px; font-size: 16px; }
  .poster-more { width: 40px; height: 40px; }
  .toast-x { width: 40px; height: 40px; }

  /* Library */
  .q-head { gap: 8px; }
  .lib-tools { gap: 8px; }
  /* The views get a row to themselves; the filter and the sort share the next one. */
  .lib-tools .pillrow { flex: 1 1 100%; flex-wrap: nowrap; gap: 6px; overflow-x: auto; scrollbar-width: none; }
  .lib-tools .pillrow::-webkit-scrollbar { display: none; }
  .lib-tools .pillrow .pill { flex: none; padding-left: 14px; padding-right: 14px; }
  .lib-filter { flex: 1 1 0; width: auto; min-width: 0; }
  .lib-sort { flex: none; max-width: 48%; }
  /* A book's chapters: the filter has a row to itself, and the range box and Select the next. */
  .toolbar:has(#book-filter) { flex-wrap: wrap; }
  .book-filter-box { flex: 1 1 100%; max-width: none; }
  .book-range-form { flex: 1 1 100%; margin-left: 0; }
  #book-range { flex: 1; width: auto; min-width: 0; }
  .lib-top {
    top: calc(-14px - var(--sat)); margin: calc(-14px - var(--sat)) calc(-1 * max(14px, var(--sar))) 14px calc(-1 * max(14px, var(--sal)));
    padding: calc(14px + var(--sat)) max(14px, var(--sar)) 12px max(14px, var(--sal));
  }
  .poster-grid { grid-template-columns: repeat(auto-fill, minmax(min(150px, 40%), 1fr)); gap: 22px 14px; }

  /* Dialogs fill the screen */
  .overlay { padding: 0; align-items: stretch; }
  .modal { border-radius: 0; max-width: none; padding: calc(16px + var(--sat)) 14px calc(14px + var(--sab)); display: flex; flex-direction: column; overflow-y: auto; }
  .modal.import { width: 100%; max-height: none; height: 100%; }
  .modal:not(.import) { align-self: center; border-radius: 12px; margin: 16px; width: auto; max-width: 460px; }
  .overlay:has(.modal:not(.import)) { align-items: center; padding: 8px; }
  .import-body { flex: 1; }
  .import-bar { flex-wrap: wrap; }
  .import-title { flex: 1 1 100%; order: -1; }
  .import-file { flex: 1 1 auto; text-align: left; }
  .import-book-body { grid-template-columns: minmax(0, 1fr); }
  .import-cover { width: 96px; }
  .import-chapter { grid-template-columns: auto 64px minmax(0, 1fr); }
  .import-chapter .import-pages { grid-column: 3; text-align: left; margin-top: -4px; }
  .import-chapters { max-height: none; }
  .import-chapter input[type="checkbox"] { width: 22px; height: 22px; }
  .modal .actions { flex-wrap: wrap; position: sticky; bottom: 0; background: var(--panel); padding-top: 10px; }
  .modal .actions .btn { flex: 1 1 auto; }

  /* Export and settings */
  
  
  .seg { flex-wrap: nowrap; }
  .seg button { flex: 1; white-space: normal; }

  /* Toasts above the dock */
  .toasts { left: 12px; right: 12px; width: auto; bottom: calc(160px + var(--sab)); }
  .toast { left: 0; right: 0; width: auto; }

}


/* Settings in a browser: its rows, and the App page about the desktop app. */

/* Settings cards */
.page > .card { max-width: 860px; }
.page > .card + .card { margin-top: 14px; }

/* Settings page */
.sx-bar { margin: 2px 0 10px; }
@media (max-width: 700px) { .sx-buttons { justify-content: flex-start; } }

/* Settings, App: the web app (installing this site), then the desktop app */
.web-app { display: flex; flex-direction: column; gap: 16px; }
.web-app .desk-title { margin-bottom: 0; }
.web-app-lead { margin: -6px 0 4px; text-align: center; }
.web-app-points { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.web-app-point { display: flex; align-items: flex-start; gap: 14px; padding: 16px 18px; border-radius: var(--radius-lg); background: var(--panel-2); }
.web-app-icon { flex: none; display: grid; place-items: center; width: 40px; height: 40px; border-radius: 50%; background: var(--panel-3); color: var(--icon); }
.web-app-words { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.web-app-words strong { color: var(--text); }
.web-app-install { width: 100%; justify-content: center; min-height: 48px; font-size: 1rem; }
.web-app-installed { display: flex; align-items: center; justify-content: center; gap: 8px; min-height: 48px; padding: 10px 16px; border-radius: 999px; background: var(--panel-2); text-align: center; }
@media (max-width: 700px) { .web-app-points { grid-template-columns: minmax(0, 1fr); } }

/* the desktop app, what it does and where to get it */
.desk-app { margin-top: 44px; padding-top: 34px; border-top: 1px solid var(--line); }
.desk-title { text-align: center; font-size: 1.6rem; margin: 0 0 18px; }
.desk-slider { display: flex; flex-direction: column; align-items: stretch; gap: 14px; }
.desk-slide {
  position: relative; margin: 0; width: 100%; display: flex; flex-direction: column; align-items: center; text-align: center;
  overflow: hidden; touch-action: pan-y;
  animation: desk-slide-in 0.28s ease;
}
@keyframes desk-slide-in { from { opacity: 0; transform: translateX(14px); } to { opacity: 1; transform: none; } }
.desk-art { width: 100%; display: flex; align-items: center; justify-content: center; padding: 10px 10px 4px; }
.desk-art .desk-scene { width: 100%; max-width: 336px; height: auto; margin: 0; }
.desk-slide figcaption { padding: 6px 22px 4px; }
.desk-slide strong { display: block; font-size: 1.1rem; margin-bottom: 6px; }
.desk-slide p { margin: 0; line-height: 1.5; }
.desk-arrow {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  width: 42px; height: 42px; border-radius: 50%; border: 1px solid var(--line-strong); background: rgba(20, 20, 20, 0.85);
  color: var(--text); display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
}
.desk-arrow.prev { left: 14px; }
.desk-arrow.next { right: 14px; }
.desk-arrow:hover { background: var(--panel-3); }
.desk-dots { display: flex; gap: 8px; justify-content: center; }
.desk-dot { width: 9px; height: 9px; padding: 0; border: 0; border-radius: 50%; background: var(--line-strong); cursor: pointer; transition: width 0.2s, background 0.2s; }
.desk-dot.on { width: 22px; border-radius: 5px; background: var(--text); }
@media (prefers-reduced-motion: reduce) { .desk-slide { animation: none; } }
.pixel-mark { shape-rendering: crispEdges; image-rendering: pixelated; flex: none; }
/* The scenes move in steps, like the mascot. */
.desk-scene .found { opacity: 0; animation: desk-found 3.6s step-end infinite; }
.desk-scene .found.f1 { animation-delay: 0.6s; }
.desk-scene .found.f2 { animation-delay: 1.2s; }
@keyframes desk-found { 0% { opacity: 0; } 10%, 85% { opacity: 1; } 100% { opacity: 0; } }
.desk-scene .drop { animation: desk-drop 1.6s steps(4) infinite; }
@keyframes desk-drop { from { transform: translateY(-2px); } to { transform: translateY(6px); } }
.desk-scene .fill { opacity: 0; animation: desk-fill 3s step-end infinite; }
.desk-scene .fill.p0 { animation-name: desk-fill0; }
.desk-scene .fill.p1 { animation-name: desk-fill1; }
.desk-scene .fill.p2 { animation-name: desk-fill2; }
@keyframes desk-fill0 { 0% { opacity: 0; } 20%, 100% { opacity: 1; } }
@keyframes desk-fill1 { 0%, 45% { opacity: 0; } 46%, 100% { opacity: 1; } }
@keyframes desk-fill2 { 0%, 72% { opacity: 0; } 73%, 92% { opacity: 1; } 93%, 100% { opacity: 0; } }
.desk-scene .crop { animation: desk-blink 2.4s step-end infinite; }
.desk-scene .pick { animation: desk-blink 2.4s step-end infinite; }
@keyframes desk-blink { 0%, 60% { opacity: 1; } 61%, 80% { opacity: 0; } 81%, 100% { opacity: 1; } }
.desk-scene .wave { opacity: 0; animation: desk-wave 1.8s step-end infinite; }
.desk-scene .wave.w1 { animation-delay: 0.3s; }
.desk-scene .wave.w2 { animation-delay: 0.6s; }
@keyframes desk-wave { 0% { opacity: 0; } 15%, 60% { opacity: 1; } 61%, 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .desk-scene .found, .desk-scene .drop, .desk-scene .fill, .desk-scene .crop, .desk-scene .pick, .desk-scene .wave { animation: none; opacity: 1; }
}
.desk-downloads { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-top: 22px; }
.desk-download {
  display: flex; flex-direction: column; align-items: stretch; gap: 12px; padding: 4px 0; color: var(--text);
}
.desk-download-head { display: flex; align-items: center; gap: 12px; }
.desk-os { font-size: 1.35rem; font-weight: 700; }
.desk-kinds { display: flex; }
.desk-kinds button { flex: 1; white-space: nowrap; }
.desk-get { display: inline-flex; align-items: center; justify-content: center; gap: 6px; text-decoration: none; margin-top: auto; }
.desk-github {
  display: flex; align-items: center; gap: 16px; margin-top: 26px; padding: 4px 0; color: var(--text); text-decoration: none;
}
.desk-github:hover strong { text-decoration: underline; }
.desk-github > span { flex: 1; display: flex; flex-direction: column; gap: 2px; }
@media (max-width: 700px) {
  .desk-downloads { grid-template-columns: minmax(0, 1fr); }
  .desk-arrow { width: 36px; height: 36px; top: 34%; }
  .desk-arrow.prev { left: 8px; }
  .desk-arrow.next { right: 8px; }
}

/* The storage text keeps its room: the control takes only what it needs. */
#storage-card .sx-row { grid-template-columns: minmax(0, 1fr) auto; }

/* The Export screen in a browser: the run and its files, the pages of a phone or tablet book, and
   the narrow window (one pane, a settings sheet). */

/* Export */

.export-run { margin-top: 14px; max-width: 1100px; }
.export-file { padding: 10px 2px; }
.export-file-name { overflow-wrap: anywhere; }

/* ---- Export: the desktop app's three columns on a computer; pages, tabs and a settings sheet on a phone ---- */
.export-preview { min-height: 0; }

.px-more { text-align: center; margin: 0; padding: 8px 14px 14px; }
.export-side .export-run { padding: 0 14px; }
.export-side .export-run .card { margin: 10px 0; }
.export-side .export-run .banner { margin: 10px 0; }
.export-side .export-files { max-height: 180px; overflow-y: auto; }
.px-footer.compact { border-top: 0; padding: 10px 12px; }
.px-footer.compact .btn.big { width: 100%; }

@media (max-width: 900px) {
  .export-screen.narrow { height: 100%; }
  
  .export-screen.narrow > .export-center { flex: 1; min-height: 0; }
  
  .xm-bottom { flex: none; max-height: 55vh; overflow-y: auto; background: var(--panel); border-top: 1px solid var(--line); }
  .xm-bottom .export-run { padding: 0 12px; }
  .xm-bottom .export-run .card, .xm-bottom .export-run .banner { margin: 10px 0 0; }
  .xm-settings-tab {
    display: flex; align-items: center; gap: 8px; width: 100%; height: 46px; box-sizing: border-box; padding: 0 14px;
    border: 0; border-top: 1px solid var(--line-strong); background: var(--panel-3); color: #bdbdbd; cursor: pointer;
    font: inherit; font-size: 0.8rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  }
  .xm-settings-tab:hover { color: var(--text); }
  .xm-settings-tab span { flex: 1; text-align: left; }
  /* The open sheet rises from the bottom to cover the page, in a lighter shade, with its title at the top
     (press it to close). Its contents stay above the dock. */
  .xm-sheet {
    position: fixed; inset: 0; z-index: 40; display: flex; flex-direction: column; background: var(--panel-2);
    padding-top: var(--sat); padding-bottom: calc(104px + var(--sab));
    animation: sheet-up 0.34s cubic-bezier(0.2, 0.9, 0.25, 1) backwards;
  }
  .xm-sheet .xm-settings-tab { border-top: 0; border-bottom: 1px solid var(--line-strong); background: var(--panel-3); }
  .xm-sheet .xm-bottom, .xm-sheet .px-footer { background: var(--panel-2); }
  .xm-sheet-body { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; }
  .xm-sheet .px-panel, .xm-sheet .px-panel.open, .xm-sheet .px-panel.open.fixed { flex: none; overflow: visible; min-height: 0; }
  .xm-sheet .px-panel.collapsed .px-panel-body { display: none; }
  .xm-sheet .px-panel-body { overflow: visible; flex: none; padding-bottom: 16px; }
  .xm-sheet .px-chapters { max-height: 46vh; overflow-y: auto; }
  .xm-sheet .banner { margin: 12px; }
  .px-panel-head { height: 46px; }
  .px-chapter { min-height: 44px; }
  .px-chapter input { width: 22px; height: 22px; }
}

@keyframes sheet-up { from { transform: translateY(100%); } to { transform: none; } }

/* The page list on a narrow window: one pane at a time (the Original / Reader switch picks it), so
   the page takes the whole width and Compare, which the switch replaces, is not drawn. */
@media (max-width: 1100px) {
  .editor-group.comparing { grid-template-columns: minmax(0, 1fr); }
  .editor-group.comparing > .editor-row { grid-column: 1; }
  .compare-tab { display: none; }
  .editor-columns.solo { padding-top: 12px; }
  .source-cell { padding-top: 0; }
}

/* A phone or tablet gets the pages as they are: one long page, nothing between them. */
.original-thumb { width: 100%; height: 100%; aspect-ratio: auto; margin: 0; background: transparent; }
.original-thumb img { object-fit: contain; background: #fff; }
.original-preview.continuous { display: block; background: #000; }
.original-preview.continuous .reader-tile { display: block; margin: 0 auto; background: transparent; max-width: none; }
.original-preview.continuous .reader-tile img { pointer-events: none; }
.original-preview.continuous .original-img { display: block; margin: 0 auto; height: auto; }
/* Zoom is the same for every page and book: 100% is 800px, so a wide cover is scaled to match the rest.
   Fit is one page wide (or the column, if that is narrower), Width fills the column. */
.original-preview[data-zoom="fit"] .reader-tile, .original-preview[data-zoom="fit"] .original-img { width: min(100%, 800px); height: auto; max-width: none; }
.original-preview[data-zoom="width"] .reader-tile, .original-preview[data-zoom="width"] .original-img { width: 100%; height: auto; }
.original-preview[data-zoom="custom"] .reader-tile, .original-preview[data-zoom="custom"] .original-img { width: calc(8px * var(--zoom) * 100); height: auto; max-width: none; }

/* The warning about a big export: the words, then the button under them. */
.banner.big-export { position: relative; flex-direction: column; align-items: stretch; gap: 8px; font-size: 0.8rem; line-height: 1.45; padding: 9px 36px 9px 12px; }
.banner.big-export .btn { align-self: stretch; }
.banner.big-export .big-export-close { position: absolute; top: 4px; right: 4px; align-self: auto; min-height: 0; padding: 4px; }

/* The Library in a browser: a book waiting for its file, a book's overview, the import review's table. */

.poster-menu { right: auto; left: 8px; top: auto; }

/* Library */
.empty-actions { justify-content: center; margin-top: 8px; }

.menu-help { margin-left: auto; display: inline-flex; color: var(--muted); }
/* Library: a book waiting for its file is a card like the others, with a faded placeholder. The
   selection is the app's (the tick on each card, the action bar); on a phone the bar sits above the dock. */
.poster.not-installed .poster-art .cover { opacity: 0.55; }
/* In a browser a card's tick and menu are always shown (a touch screen has no hover to bring them up). */
.poster-check, .poster-more { opacity: 1; }
.poster-place { display: block; margin-top: 2px; }

/* A book's overview: back to the library, what it is and what can be done, then its chapters */
.back-link { margin: -6px 0 14px -10px; }
.book-actions { margin-top: 16px; gap: 8px; }
.book-chapters-head { display: flex; align-items: baseline; gap: 12px; margin-top: 28px; }
.book-chapters-head h2 { margin: 0; font-size: 1.15rem; }
.book-filter-box { max-width: 280px; }
.book-range-form { gap: 6px; margin-left: auto; }
#book-range { width: 190px; }
/* A card with its menu open sits above the cards after it, so the menu is never under them. */
.poster:has(.poster-menu) { z-index: 30; }

/* The chapters of a book being imported: the app's chapter table, with a filter, a range and a tick for
   every chapter shown in a bar that stays in view while the list scrolls. */
.import-chapter-box { margin-top: 12px; }
.import-chapter-tools {
  position: sticky; top: -4px; z-index: 4; display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  margin: 0; padding: 8px 0; background: var(--panel-2);
}
.import-chapter-tools .input-icon { flex: 1 1 180px; min-width: 0; }
.import-range { gap: 6px; margin-left: auto; }
.import-range-text { width: 170px; }
.import-range-error { color: var(--bad); margin: 0 0 6px; }
.import-table-scroll { max-height: 340px; min-height: 0; }
.import-table thead th { position: sticky; top: 0; z-index: 2; }
.import-table th, .import-table td { padding: 5px 8px; }
.import-table th.check, .import-table td.check { width: 34px; }
.import-table td.num { width: 84px; }
.import-table .import-number { width: 68px; }
.import-table .import-name { width: 100%; }
.import-table tr.off .import-name, .import-table tr.off .import-number { opacity: 0.5; }
.import-table td.size { width: 64px; text-align: right; }
.import-none { padding: 10px 12px; margin: 0; }
@media (max-width: 800px) { .import-range { margin-left: 0; } .import-range-text { width: auto; flex: 1; } }

