/* ---------- The album book ---------- */
/* The book is the album's only container; this pill (in the nav row) switches
   how its pages read — flippable spreads, or one scrollable gallery page. */
.album-views {
  display: flex;
  gap: 3px;
  padding: 2px;
  border: 1px solid var(--line);
  border-radius: 999px;
  width: max-content;
}
.album-view {
  border: 0;
  background: transparent;
  cursor: pointer;
  padding: 5px 14px;
  border-radius: 999px;
  display: grid;
  place-items: center;
  color: var(--ink-faint);
  transition: color 0.2s ease, background 0.2s ease;
}
.album-view svg { width: 17px; height: 17px; fill: currentColor; display: block; }
.album-view:hover { color: var(--ink-dim); }
.album-view.active { color: #1a1b20; background: var(--flame-2); }
.album-view:focus-visible { outline: 2px solid var(--flame-2); outline-offset: 2px; }

/* A two-page spread. Leaves are hinged at the centre spine: unturned ones rest
   on the right, turned ones lie on the left and STAY there, stacking. */
.book-stage {
  position: relative;
  margin: 0 auto;
  display: flex;
  justify-content: center;
}

/* ---- The page-turner (a faithful copy of the jasonhibbs pen) ----
   Pages alternate: recto (odd → right, rotateY 0) and verso (even → left,
   rotateY 180, hidden). A turned recto swings to the left (rotateY -180) and
   stays; its paired verso is revealed there. The tilt + shading sell the 3D. */
.pt-book.bound { perspective: 250vw; }
.pt-book.bound .pt-pages {
  position: relative;
  width: min(92vw, 620px);
  aspect-ratio: 3 / 2;                  /* two 3:4 portrait pages side by side */
  margin: 0 auto;
  transform: rotateX(10deg);
  transform-style: preserve-3d;
  backface-visibility: hidden;
  border-radius: 4px;
}
.pt-book.bound .pt-page {
  position: absolute;
  top: 0;
  width: 50%;
  height: 100%;
  transform-origin: 0 0;
  transition: transform 1s cubic-bezier(0.3, 0.1, 0.2, 1);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  transform-style: preserve-3d;
  cursor: pointer;
  user-select: none;
  background: #ece7dc;
  overflow: hidden;
  padding: 5%;
  outline: 1px solid transparent;   /* anti-crack: pads the rasterised region of the
                                       transformed layer so tile edges can't hairline */
  /* no drop shadow by default — a page stacked behind another (e.g. behind a
     closed cover) would halo out around it. The shell's boards carry the
     book's shadows instead. */
}
.pt-page::before {                       /* shading that reads as a page in / out of the light —
                                            driven by OPACITY, which animates on the compositor;
                                            background transitions repainted every stacked page
                                            per frame and made the cover's opening turn stutter */
  content: '';
  position: absolute; inset: 0;
  background: #000;
  opacity: 0;
  transition: opacity 0.5s;
  z-index: 2;
  pointer-events: none;
}
.pt-book.bound .pt-page:nth-child(odd) {     /* recto — right page, facing up */
  pointer-events: all;
  transform: rotateY(0deg) translateZ(var(--zi, 0px));   /* sub-pixel Z: stacked leaves must
                                                            never be coplanar (z-fighting) */
  right: 0;
  border-radius: 0 6px 6px 0;
}
.pt-book.bound .pt-page:nth-child(even) {    /* verso — left page, initially facing away */
  pointer-events: none;
  transform: rotateY(180deg) translateZ(var(--zi, 0px));
  transform-origin: 100% 0;
  left: 0;
  border-radius: 6px 0 0 6px;
}
.pt-book.bound .pt-page:nth-child(even)::before { opacity: 0.2; }
.pt-book.bound .pt-page.flipped:nth-child(odd) {   /* turned to the left, staying */
  pointer-events: none;
  transform: rotateY(-180deg) translateZ(var(--zi, 0px));   /* the rotation mirrors Z, so the same
                                                               value lands it correctly on the left */
}
.pt-book.bound .pt-page.flipped:nth-child(odd)::before { opacity: 0.2; }
.pt-book.bound .pt-page.flipped:nth-child(even) {  /* revealed on the left */
  pointer-events: all;
  transform: rotateY(0deg) translateZ(var(--zi, 0px));
}
.pt-book.bound .pt-page.flipped:nth-child(even)::before { opacity: 0; }
@media (prefers-reduced-motion: reduce) { .pt-book.bound .pt-page { transition: none; } }

/* covers: front (title) and back (a quiet mark), both dark boards */
.pt-cover { display: grid; place-items: center; padding: 0 !important; }
.pt-cover-front, .pt-cover-back {
  background: radial-gradient(130% 100% at 50% 0%, #2c2823 0%, #17140f 78%) !important;
  box-shadow: inset 0 0 55px rgba(0, 0, 0, 0.5) !important;                                       /* inset always */
}
.pt-backmark { font-size: 2.4rem; color: rgba(214, 189, 126, 0.6); }

/* photos scattered on the page like snapshots — each one's spot, size, tilt
   and orientation come as seeded custom props (JS), so the casual mess is
   stable: a photo keeps its place every time the book opens */
.pt-scatter { position: relative; width: 100%; height: 100%; }
.pt-photo {
  position: absolute;
  left: var(--x, 50%); top: var(--y, 50%);
  width: var(--w, 48%);
  transform: translate(-50%, -50%) rotate(var(--tilt, 0deg));
  border: 0; margin: 0;
  padding: 5px 5px 9px;      /* the snapshot's white mount, a little heavier at the foot */
  cursor: pointer;
  border-radius: 2px;
  background: #fff;
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3), 0 1px 2px rgba(0, 0, 0, 0.3);
}
.pt-photo img, .pt-photo video {
  width: 100%;
  aspect-ratio: var(--ar, 3 / 4);
  height: auto;
  object-fit: cover;
  object-position: 50% 30%;
  display: block;
  border-radius: 1px;
}
.pt-photo .play-badge {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.5rem; color: rgba(240, 242, 245, 0.92);
  background: rgba(0, 0, 0, 0.26);
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.8);
  pointer-events: none;
}

/* gallery form: the WHOLE book, exactly like the page-turn view (same spread,
   tilt, spine, covers) — but static. All photos sit on ONE scrollable page; the
   facing page is blank. The two pages here are plain flat halves (no flip). */
.pt-gpage {
  position: absolute;
  top: 0;
  width: 50%;
  height: 100%;
  background: #ece7dc;
  overflow: hidden;
  padding: 5%;
}
.pt-gleft {
  left: 0;
  border-radius: 6px 0 0 6px;
  box-shadow: inset -11px 0 22px -8px rgba(0, 0, 0, 0.4), 0 8px 22px rgba(0, 0, 0, 0.4);
}
.pt-gright {
  right: 0;
  border-radius: 0 6px 6px 0;
  box-shadow: inset 11px 0 22px -8px rgba(0, 0, 0, 0.4), 0 8px 22px rgba(0, 0, 0, 0.4);
}
/* ---- Gallery form: the SAME shell as book mode. Between the covers sit two
   board-leaves whose cream pages hold ONE masonry across both halves (four
   columns that scroll together). Cover → open spread → shut on its back. ---- */
.gal-scroll {
  position: absolute;
  background: #ece7dc;
  overflow-y: auto; overflow-x: hidden;
  padding: 6% 5%;
  touch-action: pan-y; overscroll-behavior: contain; scrollbar-width: thin;
}
/* the content box: stretched via min-height (JS) to the taller page, so BOTH
   surfaces scroll the same length and can never drift apart */
.gal-inner { display: flex; gap: 12px; }
.gal-col { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 14px; }

.gal-photo {
  position: relative;
  border: 0;
  padding: 6px 6px 8px;       /* the white mount */
  cursor: pointer;
  background: #fff;
  border-radius: 2px;
  box-shadow: 0 4px 13px rgba(0, 0, 0, 0.28), 0 1px 2px rgba(0, 0, 0, 0.3);
  transform: rotate(var(--tilt, 0deg));
}
.gal-photo img, .gal-photo video {
  display: block;
  width: 100%;
  height: auto;               /* the photo's own shape — never cropped */
  border-radius: 1px;
}
.vstill { display: block; }   /* the captured-frame wrapper behaves like its media */
.gal-photo .vstill img, .gal-photo .vstill video { width: 100%; height: auto; display: block; border-radius: 1px; }
.pt-photo .vstill img, .pt-photo .vstill video {
  width: 100%; aspect-ratio: var(--ar, 3 / 4); height: auto;
  object-fit: cover; object-position: 50% 30%; display: block; border-radius: 1px;
}
.gal-photo .play-badge {
  position: absolute; inset: 6px 6px 8px;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.4rem; color: rgba(240, 242, 245, 0.92);
  background: rgba(0, 0, 0, 0.24);
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.8);
  pointer-events: none;
}

.book-cover-title {
  font-size: clamp(1rem, 4.4vw, 1.55rem);
  letter-spacing: 0.08em;
  color: #d6bd7e;
  text-align: center;
  padding: 0 0.9rem;
  line-height: 1.35;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.6);
}
.book-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  margin-top: 0.8rem;
}
/* gallery has its own flip nav (cover → spread → back cover); just hide the count */
.album-book.gallery-mode .book-count { display: none; }

.book-nav-btn {
  width: 34px; height: 34px; border-radius: 50%;
  border: 1px solid var(--line-strong);
  background: rgba(255, 255, 255, 0.04);
  color: var(--ink-dim);
  font-size: 1.3rem; line-height: 1; cursor: pointer;
  display: grid; place-items: center;
  transition: background 0.15s ease, opacity 0.15s ease;
}
.book-nav-btn:hover { background: rgba(255, 255, 255, 0.09); }
.book-nav-btn:disabled { opacity: 0.3; cursor: default; }
.book-nav-btn:focus-visible { outline: 2px solid var(--flame-2); outline-offset: 2px; }
.book-count {
  font-size: 0.8rem; color: var(--ink-dim);
  font-variant-numeric: tabular-nums; min-width: 3.5em; text-align: center;
}

/* ---- The album shell: a complete closed book that rises, opens in one
   motion, and turns. The back cover is the board beneath everything, visible
   from the first frame — opening only MOVES parts, nothing appears. ---- */
.book-stage .pt-riser {
  transform: translateY(70px) scale(0.95);
  opacity: 0;
  transition: transform 0.65s cubic-bezier(0.3, 1.16, 0.4, 1), opacity 0.45s ease;
}
.book-stage .pt-riser.up {
  /* NOT none: a microscopic scale keeps the whole book off the compositor's
     exact-1:1 fast path, which composites 3D layers unfiltered and lets
     sub-pixel misalignments crack through as hairlines. Any non-identity
     scale forces bilinear resampling — the same reason the fractures vanish
     the instant the user zooms by any amount. Imperceptible (~1px overall). */
  transform: scale(1.0015);
  opacity: 1;
}

.pt-book.pt-shell {
  width: min(86vw, 110vh, 880px);   /* bigger on desktop; height-capped for short screens */
  margin: 0 auto 22px;            /* room for the back cover's foot overhang, clear of the nav */
  touch-action: pan-y;            /* horizontal is ours (swipe to turn); vertical stays native scroll */
  perspective: 2200px;
  transform: translateX(-25%);                     /* closed: the one-page-wide book reads centred */
  transition: transform 1.05s cubic-bezier(0.32, 0.06, 0.15, 1);
  /* NO preserve-3d here: the perspective root must stay flat. With it, the
     shell's own invisible plane joins the 3D sort, and the scene's 6° tilt
     puts the book's whole top half BEHIND that plane — which then swallowed
     every tap and hover up there. (The reference pen never sets it either.) */
}
.pt-book.pt-shell.open { transform: translateX(0); }   /* it eases right AS the cover turns */
.pt-book.pt-shell.shut { transform: translateX(25%); } /* shut on its back: one page wide, on the left */

/* A faint candle halo behind the book, so its near-black boards part from the
   night. A blurred slab (not a radial gradient — the light must hug the
   book's RECTANGLE, corners included). It rides the shell, which carries the
   stance translate; left/right retarget to wrap only the visible half while
   the book sits closed on either cover. */
.pt-book.pt-shell::before {
  content: '';
  position: absolute;
  top: -8%; bottom: -8%;
  left: 43%; right: -7%;                 /* closed: only the front cover (right half) shows */
  z-index: -1;
  border-radius: 34px;
  background: rgba(226, 178, 102, 0.3);
  filter: blur(42px);
  pointer-events: none;
  transition: left 1.05s cubic-bezier(0.32, 0.06, 0.15, 1),
              right 1.05s cubic-bezier(0.32, 0.06, 0.15, 1);
}
.pt-book.pt-shell.open::before { left: -7%; right: -7%; }
.pt-book.pt-shell.shut::before { left: -7%; right: 43%; }
.pt-book.pt-shell .pt-scene {
  position: relative;
  aspect-ratio: 3 / 2;
  transform: rotateX(6deg);
  transform-style: preserve-3d;
}
.pt-book.pt-shell .pt-scene.lifting { animation: pt-lift 1.15s cubic-bezier(0.3, 0.1, 0.2, 1); }
@keyframes pt-lift {                                /* picking the album up as it opens —
                                                       translateY only: scaling the 3D subtree
                                                       forced a re-raster on every frame */
  0%   { transform: rotateX(6deg); }
  40%  { transform: rotateX(6deg) translateY(-10px); }
  100% { transform: rotateX(6deg); }
}
.pt-book.pt-shell .pt-pages {
  position: absolute; inset: 0;
  width: auto; aspect-ratio: auto; margin: 0;
  transform: none;                                  /* the scene carries the tilt */
}
/* The transparent 3D planes must be transparent to CLICKS too: the anti-
   fracture translateZ puts right-page leaves BEHIND the scene/pages plane,
   and hit-testing stopped at the plane — killing every tap on the right
   half. Leaves carry their own explicit pointer-events, so they still
   receive everything. */
.pt-book.pt-shell .pt-scene,
.pt-book.pt-shell .pt-pages { pointer-events: none; }

/* Your-idea trims, done safely: while the book is open BETWEEN the covers,
   the boards' page-size chunks turn CREAM (an ::after slab over the brown,
   exactly where the pages sit). Any GPU crack that exposes the board then
   shows cream-on-cream — invisible — while the brown rim, the drop shadows
   and the spine shading all keep painting (clip-path would amputate them).
   Only the INNER faces need it; the outer cover faces are backface-hidden
   when buried and never paint at all. Applied once the covering turn lands,
   lifted before a cover is revealed again. */
.pt-book.pt-shell.trim-front .pt-page.pt-cover-inside::after {
  content: ''; position: absolute; inset: 12px 0 15px 17px;
  background: #ece7dc;
}
.pt-book.pt-shell.trim-back .pt-page.pt-cover-backinside::after {
  content: ''; position: absolute; inset: 12px 17px 15px 0;
  background: #ece7dc;
}


/* leaves in the shell: spine shading, slower turn, and the flood of light —
   pages sit buried in shadow until the cover lifts off them */
.pt-book.pt-shell .pt-page { transition: transform 1.05s cubic-bezier(0.32, 0.06, 0.15, 1); }
/* Shading direction rules (transitions take their timing from the DESTINATION
   state):  INTO THE SHADE tracks the turn exactly — a fast fade darkened a
   still-flat page, a shadow "sliding in" (the forward complaint).  INTO THE
   LIGHT is quick — a returning page first emerges past vertical as a spine
   wedge widening rightward, and on the slow curve that wedge swept residual
   darkness across the spread (the backward complaint). */
.pt-book.pt-shell .pt-page::before { transition: opacity 0.45s ease; }
.pt-book.pt-shell .pt-page:nth-child(even)::before,
.pt-book.pt-shell .pt-page.flipped:nth-child(odd)::before,
.pt-book.pt-shell:not(.open) .pt-page:nth-child(odd)::before {
  transition: opacity 1.05s cubic-bezier(0.32, 0.06, 0.15, 1);
}
.pt-book.pt-shell .pt-page:nth-child(odd)  { box-shadow: inset 14px 0 26px -12px rgba(60, 45, 20, 0.45); }
.pt-book.pt-shell .pt-page:nth-child(even) { box-shadow: inset -14px 0 26px -12px rgba(60, 45, 20, 0.45); }
.pt-book.pt-shell:not(.open) .pt-page:nth-child(odd)::before { opacity: 0.45; }

/* The covers carry their own overhang — the front cover, landed, IS the left
   board. Both boards share the SAME dimensions (12/15/17), so the closed
   book's silhouette is one clean rectangle: with the halo backlighting the
   edges, a mismatched sliver read as misalignment, not binding. */
.pt-book.pt-shell .pt-page.pt-cover-front {
  top: -12px; bottom: -15px; left: 50%; right: -17px;
  width: auto; height: auto;
  border-radius: 4px 12px 12px 4px;
  box-shadow: inset 0 0 45px rgba(0, 0, 0, 0.4), inset 7px 0 9px -5px rgba(0, 0, 0, 0.55) !important;
}
.pt-book.pt-shell .pt-page.pt-cover-inside {
  top: -12px; bottom: -15px; left: -17px; right: 50%;
  width: auto; height: auto;
  border-radius: 12px 4px 4px 12px;
  background: radial-gradient(130% 100% at 50% 0%, #2c2823 0%, #17140f 78%);
  box-shadow: inset 0 0 45px rgba(0, 0, 0, 0.4), inset -18px 0 30px -18px rgba(0, 0, 0, 0.55),
    0 18px 45px rgba(0, 0, 0, 0.5);                       /* it carries the left side's shadow when landed */
}

/* the inside of the back cover: BARE board, like the inside of the front —
   no page mounted on it. You've run out of pages; the next turn shuts the book. */
.pt-book.pt-shell .pt-page.pt-cover-backinside {
  top: -12px; bottom: -15px; left: 50%; right: -17px;
  width: auto; height: auto;
  border-radius: 4px 12px 12px 4px;
  background: radial-gradient(130% 100% at 50% 0%, #2c2823 0%, #17140f 78%);
  box-shadow: inset 0 0 45px rgba(0, 0, 0, 0.4), inset 18px 0 30px -18px rgba(0, 0, 0, 0.55),
    0 24px 55px rgba(0, 0, 0, 0.55);
}
/* the back cover's outside: what you see when the book shuts onto its back */
.pt-book.pt-shell .pt-page.pt-cover-back {
  top: -12px; bottom: -15px; left: -17px; right: 50%;
  width: auto; height: auto;
  border-radius: 12px 4px 4px 12px;
  box-shadow: inset 0 0 55px rgba(0, 0, 0, 0.5), 0 24px 55px rgba(0, 0, 0, 0.55) !important;
}

/* gallery board-leaves: the same page-on-board look, holding the masonry */
.pt-book.pt-shell .pt-page.pt-galboard {
  width: auto; height: auto;
  background: radial-gradient(130% 100% at 50% 0%, #2c2823 0%, #17140f 78%);
}
.pt-book.pt-shell .pt-page.pt-galboard-left {
  top: -12px; bottom: -15px; left: -17px; right: 50%;
  border-radius: 12px 4px 4px 12px;
  box-shadow: inset 0 0 45px rgba(0, 0, 0, 0.4), 0 18px 45px rgba(0, 0, 0, 0.5);
}
.pt-book.pt-shell .pt-page.pt-galboard-right {
  top: -12px; bottom: -15px; left: 50%; right: -17px;
  border-radius: 4px 12px 12px 4px;
  box-shadow: inset 0 0 45px rgba(0, 0, 0, 0.4), 0 24px 55px rgba(0, 0, 0, 0.55);
}
.pt-galboard-left .gal-scroll {
  inset: 12px 0 15px 17px; border-radius: 6px 0 0 6px;
  box-shadow: inset -14px 0 26px -12px rgba(60, 45, 20, 0.45);
  padding-right: 8%;
  scrollbar-width: none;          /* its scrollbar would sit ON the spine — the pages scroll
                                     together, so the right page's fore-edge bar is enough */
}
.pt-galboard-left .gal-scroll::-webkit-scrollbar { display: none; }
.pt-galboard-right .gal-scroll {
  inset: 12px 17px 15px 0; border-radius: 0 6px 6px 0;
  box-shadow: inset 14px 0 26px -12px rgba(60, 45, 20, 0.45);
  padding-left: 8%;
}
/* ---- One-page mode (narrow screens): the book is sized so a single page
   nearly fills the phone; the spine and a sliver of the previous page stay in
   view at the left edge. Turning is unchanged — the leaf just swings mostly
   out of view. Shell stances reposition instead of translating halves. ---- */
@media (max-width: 640px) {
  #album-overlay { padding: 0; }
  .modal.album { width: 100vw; }
  .book-stage { display: block; }
  .pt-book.pt-shell {
    --pg: min(calc(100vw - 44px), calc((100vh - 170px) * 0.72));   /* one page, height-capped */
    --slv: 20px;                                                   /* spine + previous-page sliver */
    width: calc(var(--pg) * 2);
    max-width: none;
    margin: 0 0 22px calc(var(--slv) + 8px - var(--pg));           /* right page lands in view */
    transform: none;
  }
  .pt-book.pt-shell.open { transform: none; }
  .pt-book.pt-shell.shut { transform: translateX(calc(var(--pg) - var(--slv) * 2)); }   /* the landed back cover slides into view */
}

@media (prefers-reduced-motion: reduce) {
  .book-stage .pt-riser { transition: none; }
  .pt-book.pt-shell { transition: none; }
  .pt-book.pt-shell::before { transition: none; }
  .pt-book.pt-shell .pt-scene.lifting { animation: none; }
}

