/* ═══════════════════════════════════════════════════════════════════
   GALLERY — a chapter of the album (portfolio.html)

   WHY THIS IS NOT THE BOOK
   index.html is a physical album: a fixed number of leaves, two pages to
   a sheet, turning around a spine. A category page cannot be that. It
   holds however many photographs the admin has uploaded — one today,
   forty next year — and a fixed spread count is the wrong shape for a
   variable list. So a chapter uses the older, simpler mechanism: pages
   stacked with `position: sticky`, the next one rising over the last.

   What the two DO share is material — paper, the table they lie on, the
   ink for small type. Those tokens live in design-system.css so neither
   layer owns them, and so a chapter plate looks like it came out of the
   same album as the book.

   The one rule that matters here: a chapter plate is CONTAINED. In a
   gallery the visitor came to see the whole frame, so nothing is ever
   cropped to fill a screen.

   (This file was css/album.css until the book rebuild. It kept ~24KB of
   plate types — bleed, spread, tall, quote, cover — that only the old
   homepage ever used, and a `.album` class that now means something else
   entirely in css/book.css. Both are gone.)
   ═══════════════════════════════════════════════════════════════════ */

.chapter { position: relative; }

/* The plate wrapper exists so portfolio.js has one node to write into.
   display:contents removes its box so the leaves inside stay direct
   children of .chapter for the sticky stack. */
.chapter__plates { display: contents; }

.sr-only {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ── A leaf, mobile-first: an ordinary block ─────────────────────── */

.leaf {
  position: relative;
  z-index: 1;
  /* Opaque on purpose: a stacked leaf has to hide the one beneath it,
     and an opaque box is also what lets the browser cull the covered
     ones. */
  background: var(--table);
}

.leaf--paper-2 { background: var(--color-bg-secondary); }

.leaf__stage {
  position: relative;
  block-size: 100%;
  display: flex;
  flex-direction: column;
}

/* The recede wash. Animating opacity on a flat colour composites on the
   GPU; `filter: brightness()` would repaint the photograph. */
.leaf__shade {
  position: absolute;
  inset: 0;
  z-index: 5;
  background: #0B0806;
  opacity: 0;
  pointer-events: none;
}

/* ── Type ────────────────────────────────────────────────────────── */

.leaf__num {
  font-family: var(--font-family-hebrew);
  font-size: var(--font-size-xs);
  letter-spacing: var(--tracking-widest);
  font-variant-numeric: tabular-nums;
  color: var(--ink-quiet);
}

.leaf__plate-hint {
  font-size: var(--font-size-xs);
  letter-spacing: var(--tracking-label);
  color: var(--ink-quiet);
}

.leaf__link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--font-size-sm);
  letter-spacing: var(--tracking-wide);
  color: inherit;
  border-block-end: 1px solid currentColor;
  padding-block-end: 2px;
  opacity: 0.85;
  transition: opacity var(--transition-fast), gap var(--transition-fast);
}

.leaf__link::after { content: "←"; font-size: 0.9em; }
.leaf__link:hover { opacity: 1; gap: var(--space-3); }
.leaf__frame .leaf__link { align-self: center; }

/* ── The chapter's opening and closing pages ─────────────────────── */

.leaf--text .leaf__stage {
  justify-content: safe center;
  align-items: center;
  text-align: center;
  padding-inline: var(--container-padding);
  /* The header is fixed and owns the top of the screen. Padding on BOTH
     edges keeps the page optically centred while guaranteeing nothing
     renders under the logo. */
  padding-block: max(5.5rem, var(--space-16));
}

.leaf__frame {
  inline-size: 100%;
  max-inline-size: 52rem;
  margin-inline: auto;
}

.leaf__statement {
  font-family: var(--font-family-editorial);
  font-weight: 400;
  font-size: clamp(1.5rem, 1rem + 2.4vw, 2.9rem);
  line-height: 1.45;
  letter-spacing: var(--tracking-tight);
  color: var(--color-text-primary);
  margin: 0 auto;
  max-inline-size: 34ch;
  text-wrap: balance;
}

.leaf--chapter .back-link { margin-bottom: var(--space-8); }

.leaf__chapter-title {
  font-family: var(--font-family-editorial);
  font-weight: 400;
  font-size: clamp(2rem, 1.3rem + 3.2vw, 4rem);
  line-height: 1.1;
  letter-spacing: var(--tracking-tight);
  color: var(--color-text-primary);
  margin: 0 0 var(--space-4);
}

.leaf__chapter-desc {
  font-size: var(--font-size-md);
  color: var(--color-text-secondary);
  max-inline-size: 42ch;
  margin: 0 auto var(--space-8);
}

.leaf__end {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  font-size: var(--font-size-xs);
  letter-spacing: var(--tracking-widest);
  color: var(--ink-quiet);
}

.leaf__end::before {
  content: "";
  inline-size: 2.5rem;
  block-size: 1px;
  background: var(--color-line-strong);
}

.leaf__chapter-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-6);
  flex-wrap: wrap;
  margin-block-start: var(--space-8);
}

.leaf--chapter .eyebrow,
.leaf--closing-chapter .eyebrow { justify-content: center; margin-bottom: var(--space-8); }

/* ── The contained plate ─────────────────────────────────────────── */

.leaf--plate .leaf__stage {
  align-items: center;
  justify-content: safe center;
  padding-block: max(5.5rem, var(--space-16)) var(--space-8);
  padding-inline: var(--container-padding);
}

.leaf__figure--plate {
  margin: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  min-block-size: 0;
  flex: 1 1 auto;
  inline-size: 100%;
}

/* The photograph is mounted on a sheet of paper, the way the album mounts
   its plates — not floated on the page as a bare image. */
.plate-zoom {
  display: block;
  border: 0;
  margin: 0;
  cursor: zoom-in;
  block-size: 100%;
  max-inline-size: 100%;
  line-height: 0;
  background: var(--paper);
  padding: clamp(0.7rem, 1.4vw, 1.4rem);
  box-shadow: 0 2px 6px rgba(52, 36, 26, 0.12),
              0 26px 50px -18px rgba(52, 36, 26, 0.34);
  transition: transform 0.5s var(--ease-out), box-shadow 0.5s var(--ease-out);
}

.plate-zoom picture { display: block; block-size: 100%; }

.plate-zoom img {
  block-size: 100%;
  inline-size: auto;
  max-inline-size: 100%;
  /* contain, not cover: the whole photograph, every time */
  object-fit: contain;
  object-position: center;
}

.plate-zoom:hover,
.plate-zoom:focus-visible {
  transform: translateY(-4px);
  box-shadow: 0 4px 10px rgba(52, 36, 26, 0.14),
              0 40px 70px -20px rgba(52, 36, 26, 0.4);
}

.leaf--plate .leaf__aside {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  inline-size: 100%;
  max-inline-size: 72rem;
  gap: var(--space-4);
  margin-block-start: var(--space-6);
  flex: none;
}

@media (max-width: 879px) {
  .leaf--plate .leaf__stage { padding-block: var(--space-12) var(--space-8); }
  .plate-zoom { block-size: auto; }
  .plate-zoom img { block-size: auto; inline-size: 100%; }
  .leaf__figure--plate { display: block; }
  .leaf--plate .leaf__aside { max-inline-size: none; }
}

/* ══════════════════════════════════════════════════════════════════
   THE STACK
   Each page pins to the top of the screen and the next one rises over
   it. Below 880px wide, or in a window too short to hold a page, none
   of this applies and the chapter is an ordinary scrolling document.
   ══════════════════════════════════════════════════════════════════ */

@media (min-width: 880px) {
  .leaf { min-block-size: 100dvh; }
}

@media (min-width: 880px) and (min-height: 560px) {
  .leaf {
    position: sticky;
    inset-block-start: 0;
    block-size: 100dvh;
  }

  /* Positioned elements with z-index:auto paint in tree order, and
     display:contents on the plate wrapper hoists its children into that
     same tree — so document order already gives the stack. gallery.js
     writes an explicit z-index anyway, which keeps it legible in
     devtools and survives an ancestor gaining a stacking context. */

  /* The sheet shadow: painted above this page's own top edge, so it
     falls on the page below while this one is still rising. */
  .leaf::before {
    content: "";
    position: absolute;
    inset-inline: 0;
    inset-block-start: 0;
    block-size: 4rem;
    transform: translateY(-100%);
    background: linear-gradient(to top, rgba(10, 8, 7, 0.26), rgba(10, 8, 7, 0));
    pointer-events: none;
    z-index: 7;
  }

  .leaf:first-child::before { display: none; }

  /* SAFETY VALVE. gallery.js measures every page and adds this when its
     content is taller than the screen. A sticky box taller than the
     viewport pins at the top and its overflow becomes unreachable —
     trapped scroll, which this must never produce. */
  .chapter .leaf--flow {
    position: relative;
    block-size: auto;
    min-block-size: 100dvh;
  }

  .chapter .leaf--flow::before { display: none; }

  html { scroll-snap-type: y proximity; }
  .chapter .leaf { scroll-snap-align: start; scroll-snap-stop: normal; }
  .chapter .leaf--flow { scroll-snap-align: none; }
}

/* ══════════════════════════════════════════════════════════════════
   THE TURN
   The sweep is the scroll itself. Everything here is the SETTLE that
   follows it. Every rule that HIDES something is scoped to .js-gallery,
   a class gallery.js sets the moment it runs, so nothing is ever left
   waiting for a class a blocked script will never deliver.
   ══════════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: no-preference) {
  .js-gallery .leaf__reveal {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity 0.48s var(--ease-out), transform 0.48s var(--ease-out);
  }

  .js-gallery .leaf.is-open .leaf__reveal { opacity: 1; transform: none; }

  .js-gallery .leaf.is-open .leaf__reveal:nth-child(1) { transition-delay: 0.09s; }
  .js-gallery .leaf.is-open .leaf__reveal:nth-child(2) { transition-delay: 0.17s; }
  .js-gallery .leaf.is-open .leaf__reveal:nth-child(3) { transition-delay: 0.24s; }
  .js-gallery .leaf.is-open .leaf__reveal:nth-child(4) { transition-delay: 0.30s; }

  .leaf__shade { transition: opacity 0.75s var(--ease-out); }
  .leaf__stage { transition: transform 0.75s var(--ease-out); }
}

/* The page being covered recedes. It drifts UP, never down: up hides its
   top edge off-screen, where down would open a gap at the bottom before
   the incoming page had covered it. */
@media (min-width: 880px) and (min-height: 560px) and (prefers-reduced-motion: no-preference) {
  .leaf.is-under .leaf__stage { transform: translateY(-3.5%); }
  .leaf.is-under .leaf__shade { opacity: 0.3; }
}

/* ══════════════════════════════════════════════════════════════════
   THE EDGE RAIL
   Where you are in the chapter, and one click to anywhere in it. On the
   page edge — the left, in a right-bound Hebrew album — under 3rem wide,
   and gone entirely below 1180px so it can never crowd a photograph.
   ══════════════════════════════════════════════════════════════════ */

.chapter-rail { display: none; }

@media (min-width: 1180px) and (min-height: 560px) {
  .chapter-rail {
    position: fixed;
    z-index: 90;
    inset-inline-end: clamp(0.75rem, 1.4vw, 1.5rem);
    inset-block-start: 50%;
    transform: translateY(-50%);
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
    padding: 0.5rem;
  }

  .chapter-rail__item {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    justify-content: flex-end;
    color: var(--ink-quiet);
    text-decoration: none;
  }

  .chapter-rail__t {
    font-size: 0.68rem;
    letter-spacing: var(--tracking-label);
    white-space: nowrap;
    opacity: 0;
    transform: translateX(-0.4rem);
    transition: opacity var(--transition-fast), transform var(--transition-fast);
  }

  .chapter-rail__d {
    inline-size: 1.5rem;
    block-size: 1px;
    background: currentColor;
    opacity: 0.4;
    transition: opacity var(--transition-fast), inline-size var(--transition-fast),
                background-color var(--transition-fast);
    flex: none;
  }

  .chapter-rail__item:hover .chapter-rail__t,
  .chapter-rail__item:focus-visible .chapter-rail__t { opacity: 0.9; transform: none; }

  .chapter-rail__item:hover .chapter-rail__d { opacity: 0.8; inline-size: 2rem; }

  .chapter-rail__item.is-here .chapter-rail__d {
    inline-size: 2.25rem;
    opacity: 1;
    background: var(--color-accent);
  }

  .chapter-rail__item.is-here .chapter-rail__t { opacity: 0.95; transform: none; }
}

/* ══════════════════════════════════════════════════════════════════
   REDUCED MOTION
   Snap is motion too. With it turned down the chapter is a plain, fully
   scrollable document: no stacking, no sweep, nothing hidden waiting
   for a class that will never arrive.
   ══════════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  html { scroll-snap-type: none; }

  .chapter .leaf {
    position: relative;
    block-size: auto;
    min-block-size: 100dvh;
    scroll-snap-align: none;
  }

  .chapter .leaf::before { display: none; }

  .js-gallery .leaf__reveal,
  .js-gallery .leaf.is-open .leaf__reveal,
  .leaf__stage,
  .leaf.is-under .leaf__stage {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .leaf__shade,
  .leaf.is-under .leaf__shade { opacity: 0; transition: none; }

  .plate-zoom,
  .plate-zoom:hover { transform: none; transition: none; }

  .chapter-rail__t,
  .chapter-rail__d { transition: none; }
}

/* The footer address, same as the album's — portfolio.html does not load
   css/book.css, so the rule is repeated rather than shared. */

.footer-contact {
  margin: 0 0 var(--space-6);
  font-size: var(--font-size-sm);
  letter-spacing: var(--tracking-wide);
}

.footer-contact a {
  color: rgba(255, 255, 255, 0.88);
  border-block-end: 1px solid rgba(255, 255, 255, 0.35);
  padding-block-end: 2px;
  transition: color var(--transition-fast), border-color var(--transition-fast);
}

.footer-contact a:hover { color: #fff; border-color: rgba(255, 255, 255, 0.8); }

/* The dot between the address and the number. Not a border or a pseudo
   element: the line has two, one or no halves depending on what has been
   filled in, and a separator that is part of the markup disappears with the
   half it belongs to. */
.footer-contact__sep {
  display: inline-block;
  margin-inline: 0.7em;
  color: rgba(255, 255, 255, 0.4);
}

