:root {
  --bg: #1b2431;
  --bg-stage: #10151d;
  --accent: #8399d0;
  --paper: #ffffff;
}

* {
  box-sizing: border-box;
}

/* Author rules below set `display` on several of these elements at the same
   specificity as the UA stylesheet's `[hidden] { display: none }`, which
   would otherwise lose to source order. Restate it explicitly. */
[hidden] {
  display: none !important;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  font-family: Inter, "Segoe UI", Roboto, Arial, sans-serif;
  background: var(--bg-stage);
  color: var(--paper);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* --- Top bar ------------------------------------------------------------ */

.topbar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 1.25rem;
  background: var(--bg);
  z-index: 20;
}

.topbar-left {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
}

.topbar-brand {
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: 0.01em;
  color: #eef1f8;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.topbar-actions {
  display: flex;
  gap: 0.5rem;
}

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border: none;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.08);
  color: #eef1f8;
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s ease;
}

.icon-btn:hover {
  background: var(--accent);
}

/* --- Page content (gallery / viewer, one visible at a time) -------------- */

.page-content {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

/* --- Gallery --------------------------------------------------------------- */

.gallery-view {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 2.5rem 1.5rem 3rem;
}

.gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 1.75rem 1.5rem;
  max-width: 1200px;
  margin: 0 auto;
}

.gallery-card {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  text-decoration: none;
  color: inherit;
}

.gallery-thumb {
  height: 250px;
  border-radius: 6px;
  background: var(--paper);
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.4);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.gallery-card:hover .gallery-thumb {
  transform: translateY(-4px);
  box-shadow: 0 16px 34px rgba(0, 0, 0, 0.5);
}

.gallery-thumb img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.gallery-title {
  font-size: 0.85rem;
  font-weight: 600;
  color: #eef1f8;
  text-align: center;
}

/* --- Stage / book -------------------------------------------------------- */

.stage {
  flex: 1 1 auto;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 0;
  min-width: 0;
  padding: 1rem;
}

.loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  color: #c6cede;
}

.spinner {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 3px solid rgba(255, 255, 255, 0.15);
  border-top-color: var(--accent);
  animation: spin 0.9s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.book-wrap {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.book-crop {
  /* Sized in pixels by app.js (a "contain fit" against the available box) —
     page-flip's own auto-sizing has edge cases where the canvas element ends
     up taller than the content it draws, leaving blank bands. Owning the
     size ourselves keeps it exact and avoids that.
     At the front/back cover, this is narrowed to one page's width and
     .book is shifted with a transform, cropping away the blank "phantom"
     half page-flip always paints to fill out the spread — see
     updateCoverCrop() in app.js. */
  overflow: hidden;
  filter: drop-shadow(0 20px 40px rgba(0, 0, 0, 0.45));
  /* Duration is set inline from app.js (FLIP_ANIMATION_MS), so it can be
     kept in sync with page-flip's own flippingTime setting, or suppressed
     entirely for non-animated jumps (thumbnail grid, initial load). */
  transition-property: width;
  transition-timing-function: ease;
}

.book {
  transition-property: transform;
  transition-timing-function: ease;
}

.nav-btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 5;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  border: none;
  background: rgba(255, 255, 255, 0.08);
  color: #eef1f8;
  cursor: pointer;
  transition: background 0.15s ease;
}

.nav-prev {
  left: 0.5rem;
}

.nav-next {
  right: 0.5rem;
}

.nav-btn:hover {
  background: var(--accent);
}

.nav-btn:disabled {
  opacity: 0.3;
  cursor: default;
  background: rgba(255, 255, 255, 0.08);
}

/* --- Bottom toolbar ------------------------------------------------------- */

.toolbar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 0.6rem 1rem;
  background: var(--bg);
}

.page-indicator {
  font-variant-numeric: tabular-nums;
  color: #c6cede;
  font-size: 0.9rem;
  min-width: 5.5rem;
  text-align: center;
}

/* --- Lightbox (zoom) ------------------------------------------------------ */

.lightbox {
  position: fixed;
  inset: 0;
  background: rgba(8, 11, 16, 0.94);
  z-index: 100;
  display: flex;
  flex-direction: column;
}

.lightbox-viewport {
  flex: 1 1 auto;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: grab;
  touch-action: none;
}

.lightbox-viewport.dragging {
  cursor: grabbing;
}

.lightbox-viewport img {
  max-width: 92vw;
  max-height: 86vh;
  user-select: none;
  -webkit-user-drag: none;
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5);
  /* Deliberately no will-change: transform. Chrome/Blink only re-rasters a
     script-driven transform: scale() change (keeping it crisp) when the
     element does NOT have will-change: transform — that property tells the
     compositor to freeze the element as a fixed bitmap and just GPU-stretch
     it on every scale change instead, trading crispness for animation perf.
     This is a click-to-zoom viewer, not a 60fps animation, so there's no
     upside to that trade — see developer.chrome.com/blog/re-rastering-composite.
     (Firefox has no such trade-off, which is why this only ever showed up in
     Chromium-based browsers.) */
}

.lightbox-close {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  z-index: 5;
}

.lightbox-controls {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.75rem;
}

.lightbox-controls .icon-btn {
  font-size: 1.1rem;
  font-weight: 600;
  width: 2.5rem;
  height: 2.5rem;
}

/* --- Page overview grid ---------------------------------------------------- */

.thumb-grid {
  position: fixed;
  inset: 0;
  background: rgba(8, 11, 16, 0.97);
  z-index: 100;
  overflow-y: auto;
  padding: 3.5rem 1.5rem 2rem;
}

.thumb-grid-inner {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 1rem;
  max-width: 1100px;
  margin: 0 auto;
}

.thumb-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  cursor: pointer;
  background: none;
  border: none;
  padding: 0;
  color: #c6cede;
  font-size: 0.75rem;
}

.thumb-item img {
  width: 100%;
  border-radius: 4px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4);
  transition: outline 0.15s ease;
  outline: 2px solid transparent;
}

.thumb-item:hover img {
  outline-color: var(--accent);
}

/* --- Responsive ------------------------------------------------------------ */

@media (max-width: 640px) {
  .topbar-brand {
    font-size: 0.85rem;
  }

  .nav-btn {
    width: 2.25rem;
    height: 2.25rem;
  }

  .nav-prev {
    left: 0.15rem;
  }

  .nav-next {
    right: 0.15rem;
  }
}
