/* book.css — scroll-linked look book (#work) and its fallback gallery.
   Moved from prototype-book/style.css. Script: js/book.js */

.book-section {
  /* Page size: fit height (leaving room for caption and skip link while pinned),
     but keep the open spread within ~90% of the width */
  --page-h: min(70vh, calc(45vw * 1.491));
  --page-h: min(70svh, calc(45vw * 1.491));
  --page-w: calc(var(--page-h) / 1.491);
}

/* ---------- Layout ---------- */
.book-section {
  /* svh (screen with the address bar shown) keeps the pinned book still while the
     iPhone address bar shows or hides; the cost is a little room under the caption */
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-6);
  padding: var(--space-5) var(--space-4);
  /* A turning leaf leans toward the viewer: never let it cause sideways scroll */
  overflow-x: clip;
}

/* Gallery (no book) on wider screens: more room between the gallery and the caption */
@media (min-width: 768px) {
  .book-section {
    gap: var(--space-8);
  }
}

.book-stage {
  width: calc(var(--page-w) * 2);
  height: var(--page-h);
}

/* ---------- Phones: the same spread as desktop, as wide as the screen allows ---------- */

@media (max-width: 767px) {
  .book-section {
    /* Minimal side margin; height still capped so caption and skip link fit */
    --page-h: min(70vh, calc((100vw - 2 * var(--space-2)) / 2 * 1.491));
    --page-h: min(70svh, calc((100vw - 2 * var(--space-2)) / 2 * 1.491));
    padding-inline: var(--space-2);
  }
}

/* Upright phone: book just above the middle of the screen with the page count +
   Previous / Next just under it, caption and skip link on the bottom edge (bottom row
   shared with desktop below; small phones on their side use the landscape layout) */
@media (max-width: 767px) and (orientation: portrait) {
  .book-section.has-book {
    display: grid;
    grid-template-columns: 100%;
    /* 2 : 3 split of the free space puts the book a little above the middle */
    grid-template-rows: 2fr auto 3fr;
    justify-items: center;
    gap: 0;
  }

  .book-section.has-book .book-stage {
    grid-column: 1;
    grid-row: 2;
    position: relative;
    z-index: 1; /* a turning leaf passes over the pager, not under it */
  }

  .book-section.has-book .book-pager {
    display: flex;
    grid-column: 1;
    grid-row: 3;
    align-self: start;
    margin-top: var(--space-3);
  }

  /* "View full size" sits at the top of the bottom-right group, just above the
     AI notice (js/book.js moves it there); text flush with the spread edge */
  .book-section.has-book .book-meta__end .book-view {
    display: flex;
  }

  .book-section.has-book .book-meta__end .book-view__btn {
    margin-right: calc(-1 * var(--space-3));
  }
}

/* Desktop: book above the middle of the screen with the page count + Previous / Next
   just under it; at the bottom, credits left and AI notice + skip link right */
@media (min-width: 768px) and (min-height: 501px) {
  .book-section.has-book {
    /* How far the book (and its pager) sits above the middle of the screen */
    --book-raise: 75px;
    display: grid;
    grid-template-columns: 100%;
    grid-template-rows: 1fr auto 1fr;
    justify-items: center;
    gap: 0;
  }

  .book-section.has-book .book-stage {
    grid-column: 1;
    grid-row: 2;
    position: relative;
    z-index: 1; /* a turning leaf passes over the pager, not under it */
    transform: translateY(calc(-1 * var(--book-raise)));
  }

  .book-section.has-book .book-pager {
    display: flex;
    grid-column: 1;
    grid-row: 3;
    align-self: start;
    margin-top: var(--space-4);
    transform: translateY(calc(-1 * var(--book-raise)));
  }

  /* "View full size": same row as the pager, flush with the spread's right edge */
  .book-section.has-book .book-view {
    display: flex;
    justify-content: flex-end;
    grid-column: 1;
    grid-row: 3;
    align-self: start;
    width: calc(var(--page-w) * 2);
    margin-top: var(--space-4);
    transform: translateY(calc(-1 * var(--book-raise)));
    pointer-events: none; /* only the button itself takes clicks, not the row over the pager */
  }

  .book-section.has-book .book-view__btn {
    pointer-events: auto;
    margin-right: calc(-1 * var(--space-3)); /* text, not padding, lines up with the page edge */
  }
}

/* Bottom row on desktop and upright phones: two groups side by side across the spread,
   credits on the left and AI notice + skip link on the right, bottoms lined up */
@media (min-width: 768px) and (min-height: 501px), (max-width: 767px) and (orientation: portrait) {
  .book-section.has-book .book-meta {
    grid-column: 1;
    grid-row: 3;
    align-self: end;
    width: calc(var(--page-w) * 2);
    flex-direction: row;
    justify-content: space-between;
    align-items: flex-end;
    gap: var(--space-4);
  }

  .book-section.has-book .book-caption {
    align-items: flex-start;
    text-align: left;
  }

  .book-section.has-book .book-meta__end {
    flex-shrink: 0; /* on narrow phones the credits wrap instead */
    align-items: flex-end;
    text-align: right;
  }

  /* Line the link text up with the spread edge and the credits' last line */
  .book-section.has-book .book-meta__end .skip-link {
    margin-right: calc(-1 * var(--space-3));
    margin-bottom: calc(-1 * var(--space-3));
  }
}

/* Upright phones: the two groups read as three shared lines, each lined up on its
   baseline — title | View full size, credits | AI notice, byline | Skip the book.
   The groups dissolve into one grid; the link and button keep their 44px tap area
   but take no extra room (negative margins) */
@media (max-width: 767px) and (orientation: portrait) {
  .book-section.has-book .book-meta {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: baseline;
    gap: var(--space-1) var(--space-4);
  }

  .book-section.has-book .book-caption,
  .book-section.has-book .book-meta__end {
    display: contents;
  }

  .book-section.has-book .book-caption > :nth-child(1) { grid-area: 1 / 1; }
  .book-section.has-book .book-caption > :nth-child(2) { grid-area: 2 / 1; }
  .book-section.has-book .book-caption > :nth-child(3) { grid-area: 3 / 1; }

  .book-section.has-book .book-meta__end .book-view,
  .book-section.has-book .book-caption__ai,
  .book-section.has-book .book-meta__end .skip-link {
    grid-column: 2;
    justify-self: end;
  }

  .book-section.has-book .book-meta__end .book-view { grid-row: 1; }
  .book-section.has-book .book-caption__ai { grid-row: 2; }
  .book-section.has-book .book-meta__end .skip-link { grid-row: 3; }

  .book-section.has-book .book-meta__end .book-view__btn,
  .book-section.has-book .book-meta__end .skip-link {
    margin-block: calc(-1 * var(--space-3));
  }
}

/* Desktop has room for a wider gap between the two groups */
@media (min-width: 768px) and (min-height: 501px) {
  .book-section.has-book .book-meta {
    gap: var(--space-5);
  }
}

/* Phone on its side: the book takes the height; caption, page count + Previous / Next
   and skip link move beside it */
@media (orientation: landscape) and (max-height: 500px) {
  .book-section.has-book {
    --page-h: min(88vh, calc((100vw - 240px) / 2 * 1.491));
    --page-h: min(88svh, calc((100vw - 240px) / 2 * 1.491));
    display: grid;
    grid-template-columns: auto auto;
    grid-template-rows: 1fr auto 1fr;
    align-items: center;
    justify-content: center;
    column-gap: var(--space-6);
    row-gap: var(--space-2);
    padding-block: var(--space-2);
  }

  .book-section.has-book .book-stage {
    grid-column: 1;
    grid-row: 1 / -1;
  }

  /* Right column: credits and AI notice, then the pager in the middle, then the skip link */
  .book-section.has-book .book-meta,
  .book-section.has-book .book-meta__end {
    display: contents;
  }

  .book-section.has-book .book-caption,
  .book-section.has-book .book-caption__ai {
    grid-column: 2;
    grid-row: 1;
    align-self: end;
    justify-self: start;
    align-items: flex-start;
    text-align: left;
  }

  /* Credits end one line (the AI notice) above the pager */
  .book-section.has-book .book-caption {
    margin-bottom: calc(var(--text-2xs) * var(--leading-snug) + var(--space-1));
  }

  .book-section.has-book .book-pager {
    display: flex;
    grid-column: 2;
    grid-row: 2;
    justify-self: start;
    margin-left: calc(-1 * var(--space-3));
  }

  /* "View full size" under the pager; the skip link moves down one button */
  .book-section.has-book .book-view {
    display: flex;
    grid-column: 2;
    grid-row: 3;
    align-self: start;
    justify-self: start;
    margin-left: calc(-1 * var(--space-3));
  }

  .book-section.has-book .skip-link {
    grid-column: 2;
    grid-row: 3;
    align-self: start;
    justify-self: start;
    margin-top: calc(44px + var(--space-2));
    margin-left: calc(-1 * var(--space-3));
  }
}

/* ---------- Book ---------- */

.book {
  position: relative;
  width: 100%;
  height: 100%;
  /* Not preserve-3d: leaves stack by z-index, each leaf renders its own 3D turn */
  perspective: 2400px;
  transform: translateX(0);
  transition: transform var(--duration-turn) var(--ease-turn);
  -webkit-tap-highlight-color: transparent;
  outline: none;
}

/* Closed covers: one page sits in the middle of the stage */
.book[data-state="0"] {
  transform: translateX(-25%);
}

.book[data-state="7"] {
  transform: translateX(25%);
}

/* Scroll mode: script.js draws every frame from the scroll position */
.book.is-scrubbed,
.book.is-scrubbed .leaf {
  transition: none;
}

.leaf {
  position: absolute;
  top: 0;
  left: 50%;
  width: 50%;
  height: 100%;
  transform-origin: left center;
  transform-style: preserve-3d;
  -webkit-transform-style: preserve-3d;
  transform: rotateY(0deg);
  transition: transform var(--duration-turn) var(--ease-turn);
  /* Clicking a page opens it full size (js/viewer.js); the empty half beside a
     closed cover keeps the normal cursor */
  cursor: zoom-in;
}

.leaf.is-flipped {
  transform: rotateY(-180deg);
}

.face {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: var(--color-surface);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  /* Tiny Z offset keeps Safari from z-fighting the two faces */
  transform: translateZ(0.1px);
}

.face--back {
  transform: rotateY(180deg) translateZ(0.1px);
}

/* Pages on show take keyboard focus: Enter opens them full size */
.face:focus-visible {
  outline: 2px solid var(--color-action);
  outline-offset: -2px;
}

.face img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none;
}

/* Spine shading on inner pages (covers stay clean) */
.face::before,
.face::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.face--front:not(.is-cover)::before {
  background: linear-gradient(to right, var(--shade-spine-strong), var(--shade-spine-soft) 6%, transparent 14%);
}

.face--back:not(.is-cover)::before {
  background: linear-gradient(to left, var(--shade-spine-strong), var(--shade-spine-soft) 6%, transparent 14%);
}

/* Turning shade: darkens the moving leaf, peaking mid-turn.
   Scroll mode sets --shade from the leaf angle; click mode animates it. */
.face::after {
  opacity: var(--shade, 0);
}

.face--front::after {
  background: linear-gradient(to left, var(--shade-turn-strong), var(--shade-turn-soft));
}

.face--back::after {
  background: linear-gradient(to right, var(--shade-turn-strong), var(--shade-turn-soft));
}

.leaf.is-turning .face::after {
  animation: turn-shade var(--duration-turn) var(--ease-turn);
}

@keyframes turn-shade {
  0%   { opacity: 0; }
  50%  { opacity: 1; }
  100% { opacity: 0; }
}

/* ---------- Film button (opens the player in js/film.js) ---------- */

.film-btn {
  min-width: 44px;
  min-height: 44px;
  padding: var(--space-3) var(--space-5);
  border: 1px solid var(--color-action);
  border-radius: var(--radius-sm);
  background: var(--color-action);
  color: var(--color-action-contrast);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  white-space: nowrap;
  cursor: pointer;
  transition:
    background-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out);
}

.film-btn:hover {
  background: var(--color-action-contrast);
  color: var(--color-action);
}

.film-btn:active {
  transform: translateY(1px);
}

.film-btn:focus-visible {
  outline: 2px solid var(--color-action-contrast);
  outline-offset: 3px;
  box-shadow: 0 0 0 5px var(--color-action);
}

.film-btn:disabled {
  cursor: not-allowed;
  background: var(--color-surface);
  border-color: var(--color-line);
  color: var(--color-text-muted);
}

/* On the book: centred on the back cover, shown once the book is closed */
.book .film-btn {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 1;
  transform: translate(-50%, -50%);
  visibility: hidden;
  opacity: 0;
  transition:
    opacity var(--duration-base) var(--ease-out),
    background-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out),
    visibility 0s linear var(--duration-base);
}

.book[data-state="7"] .film-btn {
  visibility: visible;
  opacity: 1;
  transition:
    opacity var(--duration-base) var(--ease-out) var(--duration-turn),
    background-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out),
    visibility 0s;
}

.book .film-btn:active {
  transform: translate(-50%, calc(-50% + 1px));
}

/* Scroll mode: show the button only once the book has fully closed */
.book.is-scrubbed .film-btn {
  visibility: hidden;
  opacity: 0;
  transition:
    opacity var(--duration-base) var(--ease-out),
    background-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out),
    visibility 0s linear var(--duration-base);
}

.book.is-scrubbed.is-at-end .film-btn {
  visibility: visible;
  opacity: 1;
  transition:
    opacity var(--duration-base) var(--ease-out),
    background-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out),
    visibility 0s;
}

/* ---------- Fallback gallery (no JS, or the book could not be built) ---------- */

.book-fallback {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-6);
}

/* Hidden while js/book.js may still replace it, so its lazy images are not
   fetched alongside the first screen. Shown again on load if the book failed
   (the class is set and cleared by the inline script in index.html). */
.book-pending .book-fallback {
  display: none;
}

.book-gallery {
  width: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--space-5);
}

.book-gallery img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1000 / 1491;
  background: var(--color-surface);
}

/* Desktop: covers alone, inner pages side by side as spreads */
@media (min-width: 768px) {
  .book-gallery {
    width: min(100%, var(--page-w) * 2);
    grid-template-columns: 1fr 1fr;
    column-gap: 0;
    row-gap: var(--space-7);
  }

  .book-gallery__page--cover {
    grid-column: 1 / -1;
    justify-self: center;
    width: 50%;
  }
}

/* ---------- Caption: project + credits, then AI notice + skip link ---------- */

/* Page count with Previous / Next (built by js/book.js). Placed per layout above. */
.book-pager {
  display: none;
  align-items: center;
  gap: var(--space-2);
}

.book-pager__count {
  /* Fixed to the longest label ("12–13 / 14") so the buttons never shift */
  width: 10ch;
  font-size: var(--text-2xs);
  color: var(--color-text-muted);
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* "View full size" is placed by each layout above (desktop, upright phone, phone on its side) */
.book-view {
  display: none;
}

.book-pager__btn,
.book-view__btn {
  /* Quick repeated taps turn pages, never trigger the iPhone's double-tap zoom */
  touch-action: manipulation;
  min-width: 44px;
  min-height: 44px;
  padding: 0 var(--space-3);
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--color-text);
  font: inherit;
  font-size: var(--text-xs);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
  transition: color var(--duration-fast) var(--ease-out);
}

.book-pager__btn:hover,
.book-view__btn:hover {
  color: var(--color-text-muted);
}

.book-pager__btn:focus-visible,
.book-view__btn:focus-visible {
  outline: 2px solid var(--color-action);
  outline-offset: 2px;
}

.book-pager__btn:active,
.book-view__btn:active {
  transform: translateY(1px);
}

.book-pager__btn:disabled {
  color: var(--color-text-muted);
  opacity: 0.4;
  text-decoration: none;
  cursor: default;
  transform: none;
}

.book-meta,
.book-meta__end {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
}

/* Keeps "Post-production" whole when the credits wrap on narrow phones */
.book-caption__keep {
  white-space: nowrap;
}

.book-caption__ai {
  margin: 0;
  font-size: var(--text-2xs);
  line-height: var(--leading-snug);
  color: var(--color-text-muted);
  text-align: center;
}

.book-caption {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  text-align: center;
  font-size: var(--text-2xs);
  line-height: var(--leading-snug);
  color: var(--color-text-muted);
}

.book-caption__title {
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-text);
}

/* ---------- Skip link ---------- */

.skip-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--space-3);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
  border-radius: var(--radius-sm);
  transition: color var(--duration-fast) var(--ease-out);
}

.skip-link:hover {
  color: var(--color-text);
}

.skip-link:focus-visible {
  outline: 2px solid var(--color-action);
  outline-offset: 2px;
  color: var(--color-text);
}
