/* ═══════════════════════════════════════════════════════════════
   xKAF XTE Converter — iOS-style light theme.
   ═══════════════════════════════════════════════════════════════ */

:root {
  --bg: #F2F2F7;
  --card: #FFFFFF;
  --accent: #007AFF;
  --accent-press: #0062CC;
  --green: #34C759;
  --orange: #FF9500;
  --red: #FF3B30;
  --text: #1C1C1E;
  --text-2: #8A8A8E;
  --text-3: #AEAEB2;
  --hairline: rgba(60, 60, 67, 0.12);
  --hairline-strong: rgba(60, 60, 67, 0.18);
  --fill-quart: rgba(118, 118, 128, 0.08);
  --fill-tert: rgba(118, 118, 128, 0.12);
  --fill-sec: rgba(120, 120, 128, 0.16);
  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.04);
  --shadow-float: 0 8px 32px rgba(0, 0, 0, 0.12);
  --radius: 12px;
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text",
          "Segoe UI Variable Text", "Segoe UI", system-ui, sans-serif;
  --bar-bg: rgba(255, 255, 255, 0.82);
  --track: #E4E4E9;
  --seg-on: #FFFFFF;
  --scroll: rgba(0, 0, 0, 0.16);
  --scroll-hover: rgba(0, 0, 0, 0.28);
  color-scheme: light;
}

/* Dark interface theme (iOS system dark palette) — toggled by the round
   sun/moon button (see wireThemeToggle() in ui-polish.js). The page
   preview itself stays white: it shows what the e-ink screen will. */
:root[data-theme="dark"] {
  --bg: #000000;
  --card: #1C1C1E;
  --accent: #0A84FF;
  --accent-press: #0071E3;
  --green: #30D158;
  --orange: #FF9F0A;
  --red: #FF453A;
  --text: #FFFFFF;
  --text-2: #98989F;
  --text-3: #636366;
  --hairline: rgba(84, 84, 88, 0.45);
  --hairline-strong: rgba(84, 84, 88, 0.65);
  --fill-quart: rgba(118, 118, 128, 0.18);
  --fill-tert: rgba(118, 118, 128, 0.24);
  --fill-sec: rgba(118, 118, 128, 0.32);
  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow-float: 0 8px 32px rgba(0, 0, 0, 0.5);
  --bar-bg: rgba(28, 28, 30, 0.82);
  --track: #3A3A3C;
  --seg-on: #636366;
  --scroll: rgba(255, 255, 255, 0.18);
  --scroll-hover: rgba(255, 255, 255, 0.3);
  color-scheme: dark;
}
/* Colour changes animate when the theme flips (not on first paint). */
body, #toolbar, #pagerbar, .side, .card, .modal, .modal-list, #export-card {
  transition: background-color 0.25s ease, color 0.25s ease;
}

/* Excludes the offscreen book (engine.js's #xalibre-book-N): it's measured
   in this document but rasterized in an isolated SVG clone this stylesheet
   never reaches, so any app rule matching book content makes the two lay out
   differently (zeroed margins here, UA defaults there). :where() keeps this
   reset at zero specificity, as before. */
:where(*:not([id^="xalibre-book-"], [id^="xalibre-book-"] *)) { margin: 0; padding: 0; box-sizing: border-box; }

html, body { height: 100%; overflow: hidden; }

body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  font-size: 13px;
  -webkit-font-smoothing: antialiased;
  user-select: none;
  display: flex;
  flex-direction: column;
}

.hidden:not([id^="xalibre-book-"] *) { display: none !important; }

/* ═══════════ TOOLBAR ═══════════ */
#toolbar {
  min-height: 66px;
  flex-shrink: 0;
  display: flex;
  /* A window too narrow for one row wraps the right-hand group onto a
     second row rather than pushing it off screen. */
  flex-wrap: wrap;
  row-gap: 8px;
  align-items: center;
  gap: 20px;
  padding: 8px 22px;
  background: var(--bar-bg);
  backdrop-filter: blur(24px) saturate(1.6);
  -webkit-backdrop-filter: blur(24px) saturate(1.6);
  border-bottom: 1px solid var(--hairline);
  position: relative;
  z-index: 10;
}

.tb-identity { min-width: 150px; }
.tb-title { font-size: 17px; font-weight: 700; letter-spacing: -0.2px; white-space: nowrap; }
.tb-version { font-size: 9px; font-weight: 500; color: var(--text-3); letter-spacing: 0; margin-left: 3px; }

/* xKAF Org Telegram link */
.btn.telegram-btn {
  background: #24A1DE; color: #fff;
  gap: 6px; padding: 0 11px 0 8px;
  text-decoration: none;
}
.btn.telegram-btn:hover { background: #1E8CB8; }
.telegram-logo { display: block; flex-shrink: 0; }

/* Round light/dark theme button — sun and moon glyphs cross-fade with a
   quarter turn, iOS-style. */
.theme-toggle {
  position: relative;
  width: 36px; height: 36px;
  flex-shrink: 0;
  border: none; border-radius: 50%;
  background: var(--fill-sec);
  color: var(--text);
  cursor: pointer;
  transition: background 0.2s ease, transform 0.08s ease;
}
.theme-toggle:hover { background: var(--fill-tert); }
.theme-toggle:active { transform: scale(0.94); }
.theme-toggle svg {
  position: absolute; top: 9px; left: 9px;
  transition: opacity 0.3s ease, transform 0.45s cubic-bezier(0.3, 1.2, 0.5, 1);
}
.theme-sun { color: #FF9F0A; opacity: 1; transform: rotate(0) scale(1); }
.theme-moon { color: #FFD60A; opacity: 0; transform: rotate(-90deg) scale(0.5); }
:root[data-theme="dark"] .theme-sun { opacity: 0; transform: rotate(90deg) scale(0.5); }
:root[data-theme="dark"] .theme-moon { opacity: 1; transform: rotate(0) scale(1); }
.tb-file  { font-size: 11px; color: var(--text-2); margin-top: 1px;
            max-width: 210px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.tb-actions { display: flex; gap: 8px; flex: 1; }
.tb-right { display: flex; align-items: center; gap: 12px; flex-shrink: 0; margin-left: auto; }
.tb-divider { width: 1px; height: 22px; background: var(--hairline-strong); flex-shrink: 0; }

.tb-progress { display: flex; flex-direction: column; align-items: flex-end; gap: 5px; min-width: 190px; }

.tb-coffee { display: flex; align-items: center; flex-shrink: 0; opacity: 0.92; transition: opacity 0.12s; }
.tb-coffee:hover { opacity: 1; }
.tb-coffee img { height: 36px; width: auto; display: block; border-radius: 8px; }

/* Language toggle (top right) */
.lang-toggle {
  display: flex;
  padding: 2px;
  background: var(--fill-sec);
  border-radius: 8px;
  margin-left: 4px;
  flex-shrink: 0;
}
.lang-toggle button {
  border: none;
  background: transparent;
  font-family: var(--font);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.3px;
  color: var(--text-2);
  padding: 5px 10px;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.15s ease;
}
.lang-toggle button.on {
  background: var(--seg-on);
  color: var(--text);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
}
.tb-status { font-size: 11px; color: var(--text-2); font-variant-numeric: tabular-nums; }
.progress-track { width: 190px; height: 4px; border-radius: 2px; background: var(--fill-sec); overflow: hidden; }
.progress-fill  { width: 0%; height: 100%; border-radius: 2px; background: var(--accent);
                  transition: width 0.25s ease; }

/* ═══════════ BUTTONS ═══════════ */
.btn {
  font-family: var(--font);
  font-size: 13px;
  font-weight: 600;
  border: none;
  border-radius: 10px;
  padding: 0 16px;
  height: 36px;
  cursor: pointer;
  transition: transform 0.08s ease, background 0.12s ease, opacity 0.12s;
  white-space: nowrap;
  /* Real <button>s center their label by default; the plain <div>-based
     buttons v4 uses for a few actions (Import Font, Edit Chapters, cover
     Choose…) don't, so make it explicit for both. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.btn:active:not(:disabled) { transform: scale(0.965); }
.btn:disabled { opacity: 0.38; cursor: default; }

.btn.filled { background: var(--accent); color: #fff; }
.btn.filled:hover:not(:disabled) { background: var(--accent-press); }
.btn.green  { background: var(--green); color: #fff; }
.btn.green:hover:not(:disabled) { background: #2CB350; }
.btn.orange { background: var(--orange); color: #fff; }
.btn.orange:hover:not(:disabled) { background: #E88600; }
.btn.tinted { background: rgba(0, 122, 255, 0.13); color: var(--accent); }
.btn.tinted:hover:not(:disabled) { background: rgba(0, 122, 255, 0.20); }
/* Muted gray — for the two page-level export buttons (PNG, XTC page):
   deliberately unobtrusive next to the primary green "Export XTC" (book)
   action, both sharing the same neutral tone so neither draws the eye. */
.btn.muted { background: var(--fill-sec); color: var(--text-2); }
.btn.muted:hover:not(:disabled) { background: var(--fill-tert); }
.btn.plain  { background: transparent; color: var(--text-2); }
.btn.plain:hover:not(:disabled) { background: var(--fill-tert); color: var(--text); }
.btn.sm { height: 32px; padding: 0 13px; font-size: 12px; border-radius: 8px; }
.btn.block { display: block; width: calc(100% - 32px); margin: 14px 16px 4px; height: 42px; border-radius: 12px; }

.link-btn {
  display: block; width: 100%;
  background: none; border: none;
  color: var(--accent); font-family: var(--font); font-size: 12px; font-weight: 500;
  padding: 9px 0 11px; cursor: pointer; border-radius: 8px;
}
.link-btn:hover { background: var(--fill-quart); }

/* ═══════════ LAYOUT ═══════════ */
#main { display: flex; flex: 1; min-height: 0; position: relative; }

.side {
  width: 356px;
  flex-shrink: 0;
  overflow-y: auto;
  background: var(--bg);
}
#side-left  { border-right: 1px solid var(--hairline); }
#side-right { border-left: 1px solid var(--hairline); }

.side-caption {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.3px;
  padding: 16px 20px 0;
}
.side-pad { height: 28px; }

.row-value { font-size: 13px; color: var(--text-2); font-variant-numeric: tabular-nums; }
.card.top-gap { margin-top: 8px; }

/* Header & Footer Elements — drag-and-drop zones */
.hf-elements { padding: 12px 14px; display: flex; flex-direction: column; gap: 12px; }
.hf-zone-label {
  font-size: 11px; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.03em; color: var(--text-2); margin-bottom: 5px;
}
.hf-zone-list {
  display: flex; flex-direction: column; gap: 5px;
  min-height: 34px;
  border: 1px dashed var(--hairline-strong);
  border-radius: 8px;
  padding: 5px;
}
.hf-item {
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
  padding: 7px 8px 7px 10px;
  background: var(--fill-quart);
  border-radius: 7px;
  font-size: 13px; color: var(--text);
  user-select: none;
}
/* Desktop (>860px): draggable, arrows hidden — dragging reorders/moves
   between zones (see setupHfDragDrop() in app.js). Mobile keeps the
   arrows instead (native HTML5 drag doesn't work well with touch), so
   the toggle here is purely visual/CSS — the JS side gates the actual
   drag behavior on the same 860px breakpoint via isMobileLayout(). */
@media (min-width: 861px) {
  .hf-item { cursor: grab; }
  .hf-item-arrows { display: none; }
}
.hf-item.dragging { opacity: 0.4; }

/* Smooth collapse/expand (grid-template-rows fr trick — animates to/from
   auto content height without needing a hardcoded max-height guess).
   Used for: a bar's Marker Radius slider (tied to its own Show Marker
   toggle) and a bar's whole settings section (tied to whether its
   hf-item sits in the Hidden zone) — see syncMarkerRadiusCollapse()/
   syncProgressBarSectionsVisibility() in app.js. */
.collapsible {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transition: grid-template-rows 0.28s ease, opacity 0.22s ease;
}
.collapsible.expanded {
  grid-template-rows: 1fr;
  opacity: 1;
}
.collapsible > .collapsible-inner {
  overflow: hidden;
  min-height: 0;
}
.hf-item-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* iOS-style vertical stepper: one narrow capsule (like .seg/.pager-pill
   elsewhere in this app) with the two arrows stacked and a hairline
   divider between them, in neutral gray rather than the accent blue
   (which read as a link/primary-action color here, not a utility
   control). */
.hf-item-arrows {
  display: flex;
  flex-direction: column;
  background: var(--fill-sec);
  border-radius: 7px;
  overflow: hidden;
  flex-shrink: 0;
}
.hf-arrow-btn {
  width: 26px; height: 17px;
  border: none;
  background: transparent;
  color: var(--text-2);
  font-size: 9px;
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
  display: flex; align-items: center; justify-content: center;
}
.hf-arrow-btn:first-child { border-bottom: 1px solid var(--hairline-strong); }
.hf-arrow-btn:hover:not(:disabled) { background: var(--fill-tert); color: var(--text); }
.hf-arrow-btn:active:not(:disabled) { background: var(--fill-tert); transform: scale(0.92); }
.hf-arrow-btn:disabled { color: var(--text-3); opacity: 0.35; cursor: default; }

.hyph-detected {
  font-size: 12px;
  color: var(--accent);
  padding: 2px 14px 10px;
}

.group-hint {
  font-size: 11px;
  color: var(--text-3);
  line-height: 1.5;
  padding: 7px 30px 0;
}

/* Help texts (.group-hint, .modal-sub) collapse when the "?" switch is off
   — same grid-rows collapse as .collapsible (see wireHintToggle() in
   ui-polish.js, which wraps each one's text in .help-text-inner). */
.help-text {
  display: grid;
  grid-template-rows: 1fr;
  opacity: 1;
  transition: grid-template-rows 0.28s ease, opacity 0.22s ease,
              padding-top 0.28s ease, margin-top 0.28s ease;
}
.help-text > .help-text-inner { overflow: hidden; min-height: 0; }
.hints-off .help-text {
  grid-template-rows: 0fr;
  opacity: 0;
  padding-top: 0;
  margin-top: 0;
}

/* "?" help switch — a compact iOS switch whose knob carries the "?". */
.hint-switch {
  position: relative;
  display: inline-block;
  width: 42px; height: 26px;
  flex-shrink: 0;
  cursor: pointer;
}
.hint-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.hint-switch::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: 13px;
  background: var(--fill-sec);
  transition: background 0.2s ease;
}
.hint-switch:has(input:checked)::before { background: var(--green); }
.hint-knob {
  position: absolute;
  top: 2px; left: 2px;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: #fff;
  color: var(--text-2);
  font-size: 13px; font-weight: 800; line-height: 22px;
  text-align: center;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18), 0 1px 1px rgba(0, 0, 0, 0.14);
  transition: transform 0.2s cubic-bezier(0.3, 1.2, 0.5, 1), color 0.2s ease;
}
.hint-switch input:checked ~ .hint-knob { transform: translateX(16px); color: var(--green); }
.hint-switch input:focus-visible ~ .hint-knob { outline: 2px solid var(--accent); outline-offset: 2px; }

.inline-warning {
  font-size: 11px;
  color: var(--orange);
  line-height: 1.5;
  padding: 7px 14px 0;
}

@keyframes fadein { from { opacity: 0; transform: translateY(3px); } to { opacity: 1; transform: none; } }

/* Presets */
.preset-card {
  margin: 12px 16px 4px;
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: 12px 14px 4px;
}
.preset-row { display: flex; gap: 8px; margin-bottom: 6px; }
.grow { flex: 1; }

/* Grouped inset lists */
.group-title {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--text-2);
  padding: 18px 30px 7px;
}
.card {
  margin: 0 16px;
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}

.row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 46px;
  padding: 0 14px;
}
.row.tall { min-height: 64px; }
.row + .row, .row + .slider-row, .slider-row + .row,
.slider-row + .slider-row, .field + .field {
  border-top: 1px solid var(--hairline);
}
.row-label { font-size: 13px; color: var(--text); min-width: 0; }
.row-controls { display: flex; align-items: center; gap: 7px; }
.notice { color: var(--red); font-size: 12px; line-height: 1.6; }
.notice code { background: var(--fill-tert); padding: 1px 6px; border-radius: 5px; font-size: 11px; }

/* ═══════════ CONTROLS ═══════════ */

/* Select */
.select {
  font-family: var(--font);
  font-size: 13px;
  color: var(--text);
  background: var(--fill-quart);
  border: none;
  border-radius: 8px;
  padding: 7px 28px 7px 11px;
  cursor: pointer;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='7' viewBox='0 0 11 7'%3E%3Cpath d='M1 1l4.5 4.5L10 1' fill='none' stroke='%238A8A8E' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  max-width: 220px;
}
.select:hover { background-color: var(--fill-tert); }
.select.sm { padding: 5px 26px 5px 10px; font-size: 12px; }
.select.block { width: 100%; max-width: none; }

/* Number / text inputs */
.num {
  font-family: var(--font);
  font-size: 13px;
  width: 58px;
  padding: 6px 8px;
  text-align: center;
  border: 1px solid var(--hairline-strong);
  border-radius: 8px;
  background: var(--card);
  color: var(--text);
}
.num.xs { width: 42px; }
.num:focus, .text:focus { outline: 2px solid rgba(0, 122, 255, 0.45); outline-offset: -1px; }

.text {
  font-family: var(--font);
  font-size: 13px;
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--hairline-strong);
  border-radius: 8px;
  background: var(--card);
  color: var(--text);
}
.text.block { width: 100%; }

.field { padding: 10px 14px 12px; }
.field label { display: block; font-size: 11px; color: var(--text-2); margin-bottom: 5px; }
.field-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }

/* iOS switch */
.switch { position: relative; display: inline-block; width: 51px; height: 31px; flex-shrink: 0; }
.switch input { opacity: 0; width: 0; height: 0; }
.switch .knob {
  position: absolute; inset: 0;
  background: var(--fill-sec);
  border-radius: 16px;
  transition: background 0.2s ease;
  cursor: pointer;
}
.switch .knob::after {
  content: "";
  position: absolute;
  top: 2px; left: 2px;
  width: 27px; height: 27px;
  background: #fff;
  border-radius: 50%;
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.15), 0 1px 1px rgba(0, 0, 0, 0.16);
  transition: transform 0.2s cubic-bezier(0.3, 1.2, 0.5, 1);
}
.switch input:checked + .knob { background: var(--green); }
.switch input:disabled + .knob { opacity: 0.38; cursor: default; }
.switch input:checked + .knob::after { transform: translateX(20px); }

/* iOS segmented control */
.seg {
  display: inline-flex;
  padding: 2px;
  background: var(--fill-sec);
  border-radius: 9px;
  flex-shrink: 0;
}
.seg button {
  border: none;
  background: transparent;
  font-family: var(--font);
  font-size: 12px;
  font-weight: 500;
  color: var(--text);
  padding: 5px 10px;
  border-radius: 7px;
  cursor: pointer;
  transition: all 0.15s ease;
  white-space: nowrap;
}
.seg button.on {
  background: var(--seg-on);
  font-weight: 600;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12), 0 3px 8px rgba(0, 0, 0, 0.04);
}
/* Stacked variant: label on top, seg fills the row below */
.row.stacked-seg {
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  padding-top: 10px;
  padding-bottom: 10px;
}
.seg.seg-full { width: 100%; display: flex; }
.seg.seg-full button { flex: 1; text-align: center; }

/* Font Family pills: tighter padding so Bookerly/Lexend/Crimson Pro/EPUB/+
   fit the sidebar's one row; imported fonts add pills, which wrap onto
   further rows instead of overflowing the card. */
.seg.seg-fonts { flex-wrap: wrap; row-gap: 2px; }
.seg.seg-fonts button { flex: 1 1 auto; padding: 5px 7px; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.seg.seg-fonts button.seg-add {
  flex: 0 0 30px;
  padding: 3px 0;
  font-size: 16px; font-weight: 600; line-height: 1;
  color: var(--accent);
}
.seg.seg-fonts button.seg-add:hover { background: var(--fill-tert); }

/* Icon-glyph segs (data-icons="true" — see buildSegShims() in
   ui-polish.js, currently only FONT/Alignment): center the small inline
   SVG each button gets instead of a text label, with a bit less
   horizontal padding since a 16x16 glyph needs less room than a word. */
.seg[data-icons="true"] button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 6px 8px;
}
.seg[data-icons="true"] button svg { display: block; }

/* Free-entry number input that replaces a seg's "Custom" pill in place
   once selected — see buildSegShims() in ui-polish.js. */
.seg-custom-input {
  width: 46px;
  border: none;
  background: var(--seg-on);
  font-family: var(--font);
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  padding: 5px 6px;
  border-radius: 7px;
  text-align: center;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12), 0 3px 8px rgba(0, 0, 0, 0.04);
}
.seg-custom-input:focus { outline: 2px solid rgba(0, 122, 255, 0.45); outline-offset: -1px; }

/* iOS slider */
.slider-row { padding: 11px 14px 13px; }
.slider-head {
  display: flex; justify-content: space-between;
  font-size: 13px; color: var(--text); margin-bottom: 8px;
}
.slider-head .val { color: var(--text-2); font-variant-numeric: tabular-nums; }

input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 28px;
  background: transparent;
  cursor: pointer;
  --pct: 50%;
}
input[type="range"]::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 2px;
  background: linear-gradient(to right,
    var(--accent) 0%, var(--accent) var(--pct),
    var(--track) var(--pct), var(--track) 100%);
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 24px; height: 24px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.22), 0 0.5px 1px rgba(0, 0, 0, 0.2);
  margin-top: -10px;
  transition: transform 0.1s ease;
}
input[type="range"]:active::-webkit-slider-thumb { transform: scale(1.08); }

/* ═══════════ PREVIEW ═══════════ */
#preview { flex: 1; display: flex; flex-direction: column; min-width: 0; }

#canvas {
  flex: 1;
  overflow: auto;
  display: grid;
  place-items: center;
  padding: 34px;
  background:
    radial-gradient(1200px 500px at 50% -10%, rgba(0, 122, 255, 0.035), transparent),
    var(--bg);
}

#paper {
  background: #fff;
  border-radius: 6px;
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.06),
    0 12px 40px rgba(0, 0, 0, 0.13),
    0 2px 10px rgba(0, 0, 0, 0.06);
  overflow: hidden;
  line-height: 0;
  position: relative;
}
#del-overlay {
  position: absolute;
  inset: 0;
  background: rgba(255, 59, 48, 0.10);
  border: 3px solid #FF3B30;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  font-weight: 800;
  color: #FF3B30;
  letter-spacing: 0.10em;
  pointer-events: none;
}
#btn-del-page { font-size: 17px; padding-bottom: 2px; order: 4; flex-shrink: 0; }
#btn-del-page.del-active {
  background: rgba(255, 59, 48, 0.12);
  color: #FF3B30;
}
/* Desktop: icon-only round button (as before) — the text label only
   shows up on mobile, where it's restyled into a regular labeled
   button to match Export Page (see the mobile media query). */
.del-label { display: none; }
#placeholder {
  position: absolute;
  inset: 0;
  display: grid; place-items: center;
  font-size: 15px; color: var(--text-3);
  line-height: 1.5;
  background: #fff;
  text-align: center;
  padding: 20px;
}

/* No book loaded yet: dim and block every tool except the toolbar itself
   (Import EPUB / Export buttons live there, outside #main). */
body.no-book #side-left,
body.no-book #side-right,
body.no-book #pagerbar {
  opacity: 0.4;
  pointer-events: none;
}
#page-img { display: block; width: 440px; height: auto; }

/* Pager bar — single row (go-to and Refresh were removed, Monitor DPI
   moved to the toolbar, freeing up enough width for everything else to
   fit: chapter select, slider, prev/count/next, delete, export page). */
#pagerbar {
  height: 66px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 18px;
  background: var(--bar-bg);
  backdrop-filter: blur(24px) saturate(1.6);
  -webkit-backdrop-filter: blur(24px) saturate(1.6);
  border-top: 1px solid var(--hairline);
}

.pager-row {
  display: flex;
  flex-wrap: nowrap; /* one row on desktop — the slider absorbs spare width */
  align-items: center;
  justify-content: center;
  gap: 14px;
  /* Wide enough for the page slider to take most of the bar, but capped
     so it never runs edge to edge on a very wide window. */
  width: 100%;
  max-width: 1100px;
}

/* .pager-nav-row/.pager-tools-row exist purely so the mobile layout
   (below) can force page-slider+pager-pill and chapterSelect+export+
   delete into two guaranteed rows via real flex containers, instead of
   relying on flex-wrap to break lines organically (which reflows
   item-by-item as width changes). On desktop they're unwrapped via
   display:contents, so their children act as plain .pager-row flex
   items — the explicit `order` values below restore the original
   left-to-right desktop sequence regardless of where each item now
   physically sits in the markup. */
.pager-nav-row, .pager-tools-row { display: contents; }

#chapterSelect { min-width: 90px; max-width: 130px; order: 1; flex-shrink: 0; }

.pager-pill {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 4px;
  background: var(--fill-quart);
  border-radius: 14px;
  padding: 4px 6px;
  order: 3;
}
.nav-btn {
  width: 38px; height: 38px;
  border: none; border-radius: 10px;
  background: transparent;
  color: var(--accent);
  font-size: 22px; line-height: 1;
  cursor: pointer;
  transition: background 0.12s;
  padding-bottom: 4px;
}
.nav-btn:hover { background: var(--fill-tert); }
.nav-btn:active { transform: scale(0.94); }

.pager-count {
  font-size: 14px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  min-width: 72px; text-align: center;
  padding: 0 6px;
}

/* The longest control in the bar: takes all remaining width in the row. */
#pageSlider { flex: 1 1 auto; min-width: 120px; order: 2; }

.zoom-box {
  flex-shrink: 0;
  display: flex; align-items: center; gap: 10px;
  font-size: 12px; color: var(--text-2);
  white-space: nowrap;
}
.zoom-box input[type="range"] { width: 110px; }

/* ═══════════ EXPORT OVERLAY ═══════════ */
#export-overlay {
  position: fixed; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, 0.35);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  z-index: 200;
  animation: fadein 0.15s ease;
}
#export-card {
  background: var(--card);
  border-radius: 22px;
  padding: 30px 40px 24px;
  text-align: center;
  box-shadow: 0 24px 72px rgba(0, 0, 0, 0.22);
  min-width: 300px;
}
#export-title {
  font-size: 15px; font-weight: 600; color: var(--text);
  margin-bottom: 18px; letter-spacing: -0.01em;
}
/* Shown while any progress overlay is up (export, loading, etc.) so it
   stays in view for as long as the user is waiting. */
.export-card-coffee { justify-content: center; margin-bottom: 16px; }
.export-track {
  height: 8px; background: var(--fill-sec); border-radius: 4px;
  overflow: hidden; margin-bottom: 10px;
}
.export-fill {
  height: 100%; background: var(--green); border-radius: 4px;
  transition: width 0.3s ease; width: 0%;
}
#export-pct { font-size: 13px; color: var(--text-2); font-variant-numeric: tabular-nums; }
#progress-ok-btn { margin-top: 16px; min-width: 100px; }

/* ═══════════ SCRUB CHIPS ═══════════ */
.scrub-chips { display: flex; flex-wrap: wrap; gap: 5px; padding: 10px 14px 2px; min-height: 0; }
.scrub-chips:empty { padding: 0; }
.scrub-chips:not(:empty) + .row { border-top: 1px solid var(--hairline); }
.scrub-chip {
  display: inline-flex; align-items: center; gap: 5px;
  background: rgba(0, 122, 255, 0.10);
  border-radius: 12px;
  padding: 4px 6px 4px 11px;
  font-size: 12px; color: var(--accent);
}
.chip-del {
  display: flex; align-items: center; justify-content: center;
  width: 18px; height: 18px;
  background: var(--fill-tert); border: none; border-radius: 50%;
  color: var(--text-2); cursor: pointer; font-size: 13px; line-height: 1;
  flex-shrink: 0;
}
.chip-del:hover { background: rgba(255, 59, 48, 0.15); color: #FF3B30; }
.scrub-add-row { gap: 8px; }
.scrub-add-row .scrub-text { flex: 1; min-width: 0; }

/* ═══════════ MODALS ═══════════ */
.modal-backdrop {
  position: fixed; inset: 0;
  background: rgba(0, 0, 0, 0.32);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  display: grid; place-items: center;
  z-index: 100;
  animation: fadein 0.15s ease;
}
.modal {
  width: 520px;
  max-height: 82vh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  border-radius: 16px;
  box-shadow: var(--shadow-float);
  overflow: hidden;
  animation: pop 0.2s cubic-bezier(0.2, 1.2, 0.4, 1);
}
@keyframes pop { from { opacity: 0; transform: scale(0.96); } to { opacity: 1; transform: none; } }
.modal.narrow { width: 400px; }

.modal-head { padding: 20px 22px 6px; display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.modal-head-text { min-width: 0; }
.modal-title { font-size: 17px; font-weight: 700; letter-spacing: -0.2px; }
.modal-sub { font-size: 12px; color: var(--text-2); margin-top: 5px; line-height: 1.5; }
.modal-close-btn {
  width: 28px; height: 28px; flex-shrink: 0;
  border: none; border-radius: 50%;
  background: var(--fill-tert);
  color: var(--text-2);
  font-size: 13px;
  cursor: pointer;
  display: grid; place-items: center;
  transition: background 0.12s, color 0.12s;
}
.modal-close-btn:hover { background: var(--fill-sec); color: var(--text); }

.modal-tools { display: flex; gap: 8px; padding: 12px 22px 4px; }

.modal-list {
  flex: 1;
  overflow-y: auto;
  margin: 10px 16px;
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
}
.chap-item {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 14px;
  font-size: 13px;
}
.chap-item + .chap-item { border-top: 1px solid var(--hairline); }
.chap-item:hover { background: var(--fill-quart); }
/* A deleted chapter's title reads as struck-through — reinforces what the
   red .chap-check-delete checkbox already says, even at a glance. */
.chap-item.deleted .chap-title-input { color: var(--text-3); text-decoration: line-through; }
/* Two independent checkboxes per row now (TOC/index vs. Delete — see
   setupCoverAndToc()'s own comment): round accent-blue for TOC/index,
   square red for Delete, so the two are never visually confusable. */
.chap-check {
  width: 22px; height: 22px; flex-shrink: 0;
  border: 1.5px solid var(--text-3);
  border-radius: 50%;
  display: grid; place-items: center;
  cursor: pointer;
  transition: all 0.13s ease;
}
.chap-check.on {
  background: var(--accent);
  border-color: var(--accent);
}
.chap-check.on::after {
  content: "";
  width: 6px; height: 10px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg) translate(-1px, -1px);
}
.chap-check.disabled { opacity: 0.35; cursor: default; pointer-events: none; }
.chap-check-delete { border-radius: 7px; }
.chap-check-delete.on {
  background: var(--red);
  border-color: var(--red);
}
.chap-check-delete.on::after {
  content: "";
  width: 10px; height: 2px;
  background: #fff;
  border: none;
  transform: none;
}
.chap-num { color: var(--text-3); font-variant-numeric: tabular-nums; min-width: 22px; }
.chap-title-input {
  flex: 1; min-width: 0;
  font-family: var(--font); font-size: 13px; color: var(--text);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 4px 6px;
  cursor: text;
}
.chap-title-input:hover { border-color: var(--hairline-strong); }
.chap-title-input:focus { border-color: var(--accent); background: var(--card); outline: none; }
.chap-remove-btn {
  width: 22px; height: 22px; flex-shrink: 0;
  border: none; border-radius: 50%;
  background: transparent;
  color: var(--text-3);
  font-size: 12px;
  cursor: pointer;
  display: grid; place-items: center;
  transition: background 0.12s, color 0.12s;
}
.chap-remove-btn:hover { background: rgba(255, 59, 48, 0.12); color: var(--red); }
.chap-list-header {
  display: flex; align-items: center; gap: 12px;
  padding: 4px 14px;
  font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--text-3);
  border-bottom: 1px solid var(--hairline);
}
.chap-list-header span { width: 22px; flex-shrink: 0; text-align: center; }

.modal-actions { padding: 8px 16px 16px; }
.modal-actions.two { display: flex; gap: 10px; padding: 14px 22px 20px; }

#preset-name-input { flex: 1; min-width: 0; }
.preset-item {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 14px;
  font-size: 13px;
}
.preset-item + .preset-item { border-top: 1px solid var(--hairline); }
.preset-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.preset-meta { font-size: 11px; color: var(--text-3); flex-shrink: 0; }
.preset-actions { display: flex; gap: 4px; flex-shrink: 0; }
.btn.danger:hover:not(:disabled) { background: rgba(255, 59, 48, 0.13); color: var(--red); }
.preset-empty { padding: 16px 14px; font-size: 13px; color: var(--text-3); text-align: center; }
.modal-actions.two .btn { flex: 1; }
.modal-actions.stack { display: flex; flex-direction: column; gap: 8px; padding: 16px 22px 20px; }
.modal-actions .btn.block { width: 100%; margin: 0; }
.modal-body { padding: 12px 22px 4px; }

#cover-preview {
  display: block;
  max-width: 130px; max-height: 190px;
  margin: 0 auto 14px;
  border-radius: 6px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
}
.cover-fields .pair {
  display: grid;
  grid-template-columns: auto 1fr auto 1fr;
  gap: 8px; align-items: center;
  margin-bottom: 10px;
}
.cover-fields .pair label { font-size: 12px; color: var(--text-2); }
.cover-fields .num { width: 100%; }
.hint { font-size: 11px; color: var(--text-3); margin-top: 10px; line-height: 1.5; }

/* Toast */
#toast {
  position: fixed;
  bottom: 84px; left: 50%;
  transform: translateX(-50%);
  background: rgba(28, 28, 30, 0.92);
  backdrop-filter: blur(10px);
  color: #fff;
  font-size: 13px; font-weight: 500;
  padding: 11px 20px;
  border-radius: 12px;
  box-shadow: var(--shadow-float);
  z-index: 200;
  animation: toastin 0.25s cubic-bezier(0.2, 1.2, 0.4, 1);
  max-width: 70vw;
}
#toast.err { background: rgba(215, 45, 40, 0.94); }
@keyframes toastin { from { opacity: 0; transform: translate(-50%, 10px); } to { opacity: 1; transform: translate(-50%, 0); } }

/* Scrollbars */
::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-thumb { background: var(--scroll); border-radius: 5px; border: 2px solid transparent; background-clip: content-box; }
::-webkit-scrollbar-thumb:hover { background: var(--scroll-hover); border: 2px solid transparent; background-clip: content-box; }
::-webkit-scrollbar-track { background: transparent; }

/* ═══════════════════════════════════════════════════════════════
   Canvas preview, drop-zone, file list, orientation buttons, and the
   conversion/export progress overlay.
   ═══════════════════════════════════════════════════════════════ */

/* Toolbar: two-line book identity + drop-zone-as-button */
.tb-file.tb-author { font-size: 10px; color: var(--text-3); margin-top: 0; }

#dropZone { display: flex; align-items: center; justify-content: center; cursor: pointer; }
#dropZone.drag-over { background: var(--accent-press); }

.file-list:empty { display: none; }
.file-list {
  margin: 10px 16px 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.file-item {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px;
  background: var(--card);
  border-radius: 10px;
  box-shadow: var(--shadow-card);
  padding: 8px 12px;
  font-size: 12px;
}
.file-item.active { background: rgba(0, 122, 255, 0.10); }
.file-item .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; }
.file-item .remove { background: none; border: none; color: var(--text-3); cursor: pointer; padding: 2px 6px; font-size: 14px; }
.file-item .remove:hover { color: var(--red); }

/* Canvas preview, scaled via --preview-scale (set from the Monitor DPI
   control in app.js). `zoom` (not `transform: scale`) so the element's
   layout box shrinks along with its visual size — otherwise #paper
   reserves the canvas's full unscaled 480x800 box and the actual
   (smaller) rendered content ends up floating in a sea of white, easy
   to miss against the light background. */
#previewCanvas {
  display: block;
  background: #fff;
  zoom: var(--preview-scale, 0.44);
}

/* Orientation buttons toggle a literal .active class (rather than the
   .on class used elsewhere) — give it the same look as .seg button.on */
.orientation-buttons button.active {
  background: var(--seg-on);
  font-weight: 600;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12), 0 3px 8px rgba(0, 0, 0, 0.04);
}

/* Conversion / export progress overlay — app.js toggles this container's
   style.display directly. */
/* app.js toggles this with style.display = 'block'/'none' (not flex),
   so #export-card is centered via absolute positioning instead of a
   flex/grid parent — that way it works regardless of which display
   value ends up on the container. */
#progressContainer {
  display: none;
  position: fixed; inset: 0;
  background: rgba(0, 0, 0, 0.35);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  z-index: 200;
}
#progressContainer #export-card {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
}
#progressText {
  font-size: 15px; font-weight: 600; color: var(--text);
  margin-bottom: 18px; letter-spacing: -0.01em;
}

/* ═══════════ MOBILE / RESPONSIVE ═══════════
   Below 860px the two side panels go off-canvas (fixed width, slid out
   via transform) instead of permanently eating into the preview's
   width, and are opened one at a time with the floating toggle buttons
   + backdrop below. Desktop layout is untouched outside the media
   query — the toggles are display:none there, so they never fire. */
.mobile-side-toggle {
  display: none;
  position: absolute;
  top: 12px;
  z-index: 40;
  width: 38px; height: 38px;
  border: none; border-radius: 50%;
  background: var(--card);
  color: var(--text);
  font-size: 16px;
  align-items: center; justify-content: center;
  box-shadow: var(--shadow-float);
  cursor: pointer;
}
.mobile-side-toggle-left { left: 12px; }
.mobile-side-toggle-right { right: 12px; }

#mobile-backdrop {
  display: none;
  position: absolute; inset: 0;
  background: rgba(0, 0, 0, 0.32);
  z-index: 45;
}

/* Mid-width desktops: compact the toolbar before it has to wrap — Reddit
   shrinks to its logo, tighter gaps, a narrower book title. */
@media (max-width: 1650px) and (min-width: 861px) {
  #toolbar { gap: 14px; padding: 8px 16px; }
  .tb-right { gap: 9px; }
  .btn.telegram-btn { width: 32px; padding: 0; }
  .btn.telegram-btn span { display: none; }
  .tb-file { max-width: 170px; }
  .zoom-label { display: none; } /* still in the zoom box's tooltip */
  .zoom-box input[type="range"] { width: 90px; }
  #toolbar .btn.sm { padding: 0 10px; }
  #toolbar .btn:not(.sm) { padding: 0 13px; }
  .tb-divider { display: none; }
  .tb-coffee img { height: 32px; }
  .tb-identity { min-width: 0; }
}

/* Once the side panels leave the preview too little width, the pager
   splits into two rows: slider on its own full-width row, the rest below. */
@media (max-width: 1200px) and (min-width: 861px) {
  #pagerbar { height: auto; min-height: 66px; padding: 8px 18px; }
  .pager-row { flex-wrap: wrap; row-gap: 8px; }
  #pageSlider { flex-basis: 100%; }
}

@media (max-width: 860px) {
  /* Toolbar becomes 3 rows: (1) lang toggle + title + coffee,
     (2) Import / Presets / Export together, (3) Monitor DPI (full
     width, so the slider isn't squeezed). .tb-actions/.tb-right stay
     real flex containers on desktop but "unwrap" here via
     display:contents so their children can be individually ordered as
     direct #toolbar flex items — a flex-basis:100% item always starts
     a fresh row. */
  #toolbar { flex-wrap: wrap; padding: 10px 14px; gap: 10px; }
  .tb-actions, .tb-right { display: contents; }

  .lang-toggle  { order: 1; }
  .hint-switch  { order: 1; }
  .tb-identity  { order: 2; flex: 1 1 auto; min-width: 0; }
  .tb-coffee    { order: 9; } /* after the export buttons, not ahead of Import */
  .theme-toggle { order: 9; }
  #dropZone        { order: 4; }
  #btn-presets     { order: 5; }
  .telegram-btn      { order: 6; }
  #exportPagePngBtn { order: 6; }
  #exportPageBtn   { order: 7; }
  #exportBtn       { order: 8; }
  .zoom-box        { order: 10; flex-basis: 100%; width: 100%; }
  .zoom-box input[type="range"] { flex: 1; width: auto; }
  .tb-divider      { display: none; } /* group separator only matters in desktop's single row */

  /* Import / Presets / page exports / Export share row 2 (wraps to a 2nd
     line on narrow phones via #toolbar's own flex-wrap — see above) —
     smaller so as many as possible fit per line. */
  #dropZone, #btn-presets, #exportPagePngBtn, #exportPageBtn, #exportBtn, .telegram-btn {
    height: 32px; padding: 0 12px; font-size: 12px; border-radius: 8px;
  }

  .tb-file { max-width: 60vw; }

  .mobile-side-toggle { display: flex; }
  body.no-book .mobile-side-toggle { display: none; }
  #mobile-backdrop.show { display: block; }

  .side {
    position: absolute;
    top: 0; bottom: 0;
    width: min(86vw, 340px);
    z-index: 50;
    box-shadow: var(--shadow-float);
    transition: transform 0.25s ease;
  }
  #side-left  { left: 0; transform: translateX(-100%); border-right: none; }
  #side-right { right: 0; transform: translateX(100%); border-left: none; }
  #side-left.open, #side-right.open { transform: translateX(0); }

  /* Pagerbar becomes 2 guaranteed rows the instant mobile kicks in —
     .pager-nav-row and .pager-tools-row stop being display:contents
     and become real flex rows in their own right, stacked via
     .pager-row switching to flex-direction:column. This is structural
     (DOM grouping), not organic flex-wrap reflow, so the split doesn't
     depend on how narrow the viewport gets. */
  .pager-row { flex-direction: column; align-items: center; gap: 10px; }
  .pager-nav-row, .pager-tools-row {
    display: flex; flex-wrap: nowrap; align-items: center;
    justify-content: center; gap: 10px; width: 100%;
  }

  #pageSlider { order: 1; flex: 1 1 0%; min-width: 60px; max-width: none; }
  .pager-pill { order: 2; flex-shrink: 0; }

  #chapterSelect { order: 1; flex-shrink: 1; min-width: 60px; max-width: 130px; }
  #btn-del-page  { order: 3; flex-shrink: 0; }

  #pagerbar { height: auto; min-height: 66px; padding: 10px 16px; }

  /* Delete becomes a regular labeled button here (icon + "Delete"),
     matching Export Page, instead of desktop's icon-only circle. */
  #btn-del-page {
    width: auto; height: 32px;
    padding: 0 12px; border-radius: 8px;
    display: inline-flex; align-items: center; gap: 6px;
    background: rgba(255, 59, 48, 0.13); color: var(--red);
    font-size: 12px; font-weight: 600;
  }
  #btn-del-page .del-emoji { font-size: 13px; }
  .del-label { display: inline; }
}
