/* Sketchbook flipbook engine styles — adapted from sketchbook-template/widget.html.
   Paired with js/sketchbook.js. Chrome (arrows/zoom/hint) is hidden site-wide
   in styles.css; this file is only the turn/curl/tilt machinery + fallback look. */

.sketchbook-mount {
  --ink: #2b2721;
  --ink-soft: rgba(43, 39, 33, 0.58);
  --ink-faint: rgba(43, 39, 33, 0.36);
  --hairline: rgba(43, 39, 33, 0.14);
  --earth: #9a6a3e;
  --pg: 1%;
  --paper: #ece7dc;
}

.sb-wrap,
.sb-wrap * {
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
}
.sb-wrap img {
  -webkit-user-drag: none;
  user-drag: none;
}

.sb-wrap { display: grid; justify-items: center; gap: 20px; width: 100%; position: relative; z-index: 2; }
.sb-stage { display: flex; align-items: center; justify-content: center; width: 100%; position: relative; touch-action: pan-y; }
.sb-arrow {
  flex: none; display: inline-flex; align-items: center; justify-content: center; padding: 6px 2px;
  border: 0; background: transparent; color: var(--ink-faint); cursor: pointer; transition: color 0.2s;
  -webkit-tap-highlight-color: transparent; z-index: 8;
}
.sb-arrow:hover { color: var(--ink); }
.sb-arrow:disabled { opacity: 0.22; cursor: default; }

.sb-3d { position: relative; flex: 1 1; min-width: 0; perspective: 1750px; perspective-origin: 50% 46%; }
.sb-tilt {
  position: relative;
  transform-style: preserve-3d;
  transform: translateX(var(--shift, 0%)) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) scale(var(--zoom, 1));
  will-change: transform;
}
.sb-book { position: relative; width: 100%; aspect-ratio: 1760/1240; transform-style: preserve-3d; z-index: 1; }
/* About's own cover/page photos have a noticeably different natural
   ratio than 1760x1240 (see sketchbook-template/scripts/prepare_assets.py's
   `canvas` param) — its assets are generated at 1536x1240 to match them
   instead of cropping or padding those photos to fit the shared ratio.
   Keep this in sync with whatever `canvas=` was passed for that book. */
#about-book .sb-book { aspect-ratio: 1536/1240; }

.sb-cast { position: absolute; pointer-events: none; z-index: 0; }
.sb-cast.ambient {
  left: calc(5% + var(--fpL, 0) * 45%); right: calc(5% + var(--fpR, 0) * 45%); top: 27%; bottom: 2%;
  background: radial-gradient(50% 50% at 50% 58%, rgba(58, 44, 26, 0.34) 0%, rgba(58, 44, 26, 0.19) 40%, rgba(58, 44, 26, 0) 74%);
  filter: blur(26px);
  opacity: calc(1 - var(--shade, 0) * 0.42);
}
.sb-cast.contact {
  left: calc(9% + var(--fpL, 0) * 41%); right: calc(9% + var(--fpR, 0) * 41%); top: 62%; bottom: 10%;
  background: radial-gradient(50% 44% at 50% 42%, rgba(44, 32, 14, 0.4) 0%, rgba(44, 32, 14, 0.17) 48%, rgba(44, 32, 14, 0) 78%);
  filter: blur(11px);
  opacity: calc(1 - var(--shade, 0) * 0.5);
}
.sb-cast.hair {
  left: calc(12% + var(--fpL, 0) * 38%); right: calc(12% + var(--fpR, 0) * 38%); top: 70%; bottom: 17%;
  background: radial-gradient(50% 52% at 50% 40%, rgba(40, 28, 10, 0.34) 0%, rgba(40, 28, 10, 0) 76%);
  filter: blur(4px);
  opacity: calc(1 - var(--shade, 0) * 0.62);
}
.sb-book {
  /* Safari/WebKit can rasterize transparent PNGs as opaque black inside a
     preserve-3d + perspective ancestor unless forced onto their own
     compositing layer. */
  -webkit-transform: translateZ(0);
  transform: translateZ(0);
}
/* Corner rounding used to live here (border-radius + overflow:hidden),
   but that clipping didn't reliably hold up on the sketchbook's 3D
   page-turn transforms — a square image corner could show through as a
   "white border" right at the edge during/after a flip. It's baked
   into the actual image pixels now instead (see round_corners() in
   sketchbook-template/scripts/prepare_assets.py), which renders
   correctly regardless of what 3D context it's composited into, so
   there's nothing left to clip here. */
.sb-full { position: absolute; inset: 0; background: transparent; }
.sb-full img {
  width: 100%; height: auto; display: block;
  -webkit-transform: translateZ(0);
  transform: translateZ(0);
}
.sb-half { position: absolute; top: 0; bottom: 0; width: 50%; overflow-x: clip; overflow-y: visible; }
.sb-half.left { left: 0; }
.sb-half.right { left: 50%; }
/* same fix as .sb-full img above — this is the other place a page
   image actually renders (the two static halves shown for the whole
   duration of a turn, not just the settled single-page view), and it
   was missing the fix, which is exactly why a rasterization glitch
   would show up specifically during/around a flip and not otherwise */
.sb-half-img {
  width: 200%; max-width: none; height: auto; display: block;
  -webkit-transform: translateZ(0);
  transform: translateZ(0);
}
.sb-half-img.right { margin-left: -100%; }
.gutter-shade {
  position: absolute; top: var(--pg, 21.8%); bottom: var(--pg, 21.8%); width: 46%;
  pointer-events: none; opacity: calc(var(--shade, 0) * 0.62);
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 5.2%, #000 94.8%, transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0, #000 5.2%, #000 94.8%, transparent 100%);
}
.gutter-shade.left { right: 0; background: linear-gradient(270deg, rgba(52, 38, 20, 0.3), rgba(52, 38, 20, 0) 82%); }
.gutter-shade.right { left: 0; background: linear-gradient(90deg, rgba(52, 38, 20, 0.24), rgba(52, 38, 20, 0) 82%); }

.curl { position: absolute; top: 0; height: 100%; width: calc(var(--bw, 0px) * var(--span)); transform-style: preserve-3d; z-index: 6; }
/* translateZ(0) chained onto every transform in this curl hierarchy —
   same rasterization risk as .sb-full img / .sb-half-img (nested
   preserve-3d + perspective can rasterize a transparent PNG incorrectly
   for the length of a transform animation and briefly after), just
   caught later here because it only actually shows up as a visible
   seam on a half-width cover image sitting next to a full-bleed page —
   chained rather than a separate rule since each of these already
   carries its own real rotateY, and a second `transform` declaration
   would just overwrite it instead of combining. */
.curl.next { left: 50%; transform-origin: left center; transform: rotateY(calc(-1 * var(--tt, 0deg))) translateZ(0); }
.curl.prev { right: 50%; transform-origin: right center; transform: rotateY(var(--tt, 0deg)) translateZ(0); }
.strip { position: absolute; top: 0; height: 100%; width: calc(var(--bw, 0px) * var(--span) / var(--n)); transform-style: preserve-3d; transform: translateZ(0); }
.curl.next .strip { transform-origin: left center; }
.curl.prev .strip { transform-origin: right center; }
.curl.next > .strip { left: 0; }
.curl.prev > .strip { right: 0; left: auto; }
.curl.next .strip .strip { left: 100%; transform: rotateY(var(--td, 0deg)) translateZ(0); }
.curl.prev .strip .strip { right: 100%; transform: rotateY(calc(-1 * var(--td, 0deg))) translateZ(0); }
.face {
  position: absolute; top: 0; bottom: 0; left: 0; right: -1.1px;
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
  background-repeat: no-repeat; background-size: var(--bw, 0px) auto;
  transform: translateZ(0);
}
.face.back { transform: rotateY(180deg) translateZ(0); }
.face .sh,
.face .gl {
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 5.2%, #000 94.8%, transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0, #000 5.2%, #000 94.8%, transparent 100%);
}
.strip.edge .face .sh,
.strip.edge .face .gl {
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 9%, #000 91%, transparent 100%), var(--hf);
  mask-image: linear-gradient(180deg, transparent 0, #000 9%, #000 91%, transparent 100%), var(--hf);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}
.curl.next .strip.edge .face.front,
.curl.prev .strip.edge .face.back {
  --hf: linear-gradient(90deg, #000 0 22%, transparent 96%);
}
.curl.next .strip.edge .face.back,
.curl.prev .strip.edge .face.front {
  --hf: linear-gradient(270deg, #000 0 22%, transparent 96%);
}
.face .sh { position: absolute; left: 0; right: 0; top: var(--pg, 21.8%); bottom: var(--pg, 21.8%); pointer-events: none; }
.curl.next .face.front .sh,
.curl.prev .face.back .sh {
  background: linear-gradient(90deg, rgba(58, 43, 20, var(--a1, 0)), rgba(58, 43, 20, var(--a2, 0)));
}
.curl.next .face.back .sh,
.curl.prev .face.front .sh {
  background: linear-gradient(90deg, rgba(58, 43, 20, var(--a2, 0)), rgba(58, 43, 20, var(--a1, 0)));
}
.face .gl {
  position: absolute; left: 0; right: 0; top: var(--pg, 21.8%); bottom: var(--pg, 21.8%);
  pointer-events: none; background: #fffaf0;
  opacity: calc(var(--shade, 0) * var(--lit, 1) * var(--lit, 1) * 0.2);
}

.sb-tools {
  display: flex; align-items: center; gap: 6px;
  border: 1px solid var(--hairline); border-radius: 999px;
  padding: 5px 7px; background: rgba(250, 246, 238, 0.62);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.tool {
  width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 50%; background: transparent; color: var(--ink-soft);
  cursor: pointer; transition: background-color 0.18s ease, color 0.18s ease;
}
.tool:hover { background: rgba(255, 252, 244, 0.9); color: var(--ink); }
.tool:disabled { opacity: 0.32; cursor: default; background: transparent; }
.tool svg { width: 15px; height: 15px; display: block; }
.zoom-read { font-size: 11px; letter-spacing: 0.1em; color: var(--ink-faint); min-width: 40px; text-align: center; font-variant-numeric: tabular-nums; }

.sb-zone { position: absolute; top: 0; bottom: 0; border: 0; background: transparent; cursor: grab; z-index: 60; -webkit-tap-highlight-color: transparent; }
.sb-zone:active { cursor: grabbing; }
.sb-prev { left: 0; width: 50%; }
.sb-next { right: 0; width: 50%; }

.sb-captions { display: grid; justify-items: center; }
.sb-captions > * { grid-area: 1/1; margin: 0; }
.sb-caption { font-size: 13px; letter-spacing: 0.24em; text-transform: uppercase; color: var(--ink-soft); animation: sb-cap-in 0.5s ease both; }
.sb-caption.live { animation: none; }
@keyframes sb-cap-in { 0% { opacity: 0; } }
.sb-hint { margin: 0; font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-faint); transition: opacity 0.4s ease; }
.sb-hint.gone { opacity: 0; }
.sb-wrap.closed .sb-tools { opacity: 0.35; pointer-events: none; }
