/* ============================================================================
   Viviane Dias — V5 · portfolio
   ---------------------------------------------------------------------------
   What Viviane asked for, in her words: "posso transitar entre um álbum e
   outro facilmente", "dá mais vida à página", and "não gosto da transição dos
   álbuns do V4, me deixa um pouco zonza". Three requirements, and this file
   answers each one with a decision that can be pointed at:

   · EASY  — the chapter rail is sticky. However deep the river runs, the next
             chapter is one click away, and clicking it never opens, closes or
             leaves anything. There is one interaction on this page and this is
             it (portfolio-craft P10).
   · ALIVE — no covers, no thumbnails, no index. The photographs are the page,
             two across on a desktop, each one large enough to be looked at.
   · CALM  — nothing zooms, pans, tilts, rotates or rides the scroll. A chapter
             arrives with a 500ms fade and a 6px rise, 45ms apart; with
             prefers-reduced-motion it is simply there. Her dizziness is a
             health constraint, so it is not worked around with a gentler
             version of the same gesture — the gesture is gone.

   Two more decisions, both from shared-context/portfolio-craft.md:
   · Every photograph in a chapter renders in the SAME box, the shape that
     chapter was actually shot in (P2: 100% per collection, not 85%). The box
     is declared on the panel with data-ratio, so no photograph is ever
     stretched and almost none is cropped.
   · No caption sits on, under or beside a photograph. Five of the five best
     photography sites in the world write nothing about a single picture, and
     on V1 the caption over the frame measured 3.04:1 and failed contrast.
     There is no text over an image anywhere on this page.

   Everything is scoped to .pf-*; site.css is not touched by this file.
   ========================================================================== */

/* ---------- 1. the chapter rail ------------------------------------------ */
/* --pf-top is written by portfolio.js from the real height of the masthead,
   because the masthead is itself sticky and its height changes at 860px. */
.pf-rail{
  position:sticky; top:var(--pf-top, 0px); z-index:40;
  background:var(--paper); border-bottom:1px solid var(--line);
}
.pf-rail__inner{
  display:flex; flex-wrap:wrap; align-items:center; row-gap:.55rem;
  column-gap:clamp(.85rem,1.6vw,1.4rem);
  padding:.85rem 0;
}
.pf-rail__inner::-webkit-scrollbar{ display:none }

.pf-chapter{
  position:relative; flex:none; background:none; border:0; padding:.3rem 0; cursor:pointer;
  font-family:var(--sans); font-size:var(--t-micro); font-weight:400;
  letter-spacing:.12em; text-transform:uppercase; color:var(--ink-3);
  display:inline-flex; align-items:baseline; gap:.5rem; white-space:nowrap;
  transition:color .3s var(--ease);
}
.pf-chapter:hover{ color:var(--ink) }
.pf-chapter[aria-selected="true"]{ color:var(--ink) }
/* the number is written by portfolio.js from the photographs actually in the
   panel — never typed by hand, so it can never be wrong */
.pf-chapter__n{
  font-size:.6875rem; letter-spacing:.1em; color:var(--ink-3);
  font-variant-numeric:tabular-nums; min-width:1.6em; text-align:left;
}
.pf-chapter::after{
  content:""; position:absolute; left:0; right:100%; bottom:-.28rem; height:1px;
  background:var(--ink); transition:right .45s var(--ease);
}
.pf-chapter[aria-selected="true"]::after{ right:0 }

/* ---------- 2. the spread ------------------------------------------------ */
/* An album spread: two photographs across, the way a photographer lays a page.
   A single column on a wide screen put one upright frame in 43% of a 1440 and
   32% of a 1920 — six frames became six screens of scrolling, which is the
   opposite of the thing this page exists for.

   The track is 30–38rem, so the browser fits two frames on a desktop and one
   on a phone without a breakpoint, and the frame itself never changes size to
   suit the screen: at 1440 each photograph renders 574px wide from a 1200px
   original (2.09x, no upscale anywhere — portfolio-craft P3).

   The right-hand frame hangs lower by a fixed offset. Same size, same ratio —
   the proportion inside a chapter stays 100% identical (P2); only the mounting
   height changes, which is what stops two columns from reading as a CMS grid.
   Nothing here moves, scales or follows the scroll. */
.pf-panel[hidden]{ display:none }
.pf-panel{ --pf-ar:3/4 }
.pf-panel[data-ratio="4x5"]{ --pf-ar:4/5 }
.pf-panel[data-ratio="3x2"]{ --pf-ar:3/2 }

.pf-line{
  font-size:var(--t-micro); letter-spacing:.06em; color:var(--ink-3);
  line-height:1.5; margin:0 0 clamp(1.1rem,2.6vw,1.7rem);
  width:min(40rem, 100%);
}
/* auto-fit counts its repetitions against the track's MAX when that max is a
   definite length, so a max of 38rem would only ever fit one track in an
   1180px column. The max is 1fr and the ceiling lives on the figure instead —
   which also keeps a lone frame from stretching to 900px on a mid-size laptop. */
.pf-river{
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(min(30rem, 100%), 1fr));
  justify-content:center; align-items:start;
  column-gap:clamp(1.2rem,2.2vw,2rem);
  row-gap:clamp(1.6rem,3.4vw,3rem);
}
.pf-shot{
  margin:0; width:100%; max-width:38rem; justify-self:center;
  opacity:0; transform:translateY(6px);
  transition:opacity .5s var(--ease), transform .5s var(--ease);
}
.pf-shot.is-shown{ opacity:1; transform:none }
.pf-shot .plate__inner{ aspect-ratio:var(--pf-ar) }
.pf-shot img{ width:100%; height:100%; object-fit:cover; object-position:50% 50% }

/* the hand-laid offset on the right-hand frame */
.pf-shot:nth-child(even){ margin-top:clamp(1.4rem,3vw,3rem) }

/* A chapter with an odd number of photographs — and the wedding chapter, which
   has exactly one until she sends the rest — ends on a frame mounted alone in
   the middle of the spread. Slightly wider than a paired frame, so it reads as
   a decision and not as a missing neighbour. */
.pf-shot:last-child:nth-child(odd){
  grid-column:1 / -1; justify-self:center; margin-top:0;
  width:100%; max-width:38rem;
}

/* ---------- 3. the ground ------------------------------------------------ */
/* Never a flat field behind the photographs: the site's own film grain over
   the paper at 5%, so it reads as paper and not as an effect. Inverted in the
   dark theme, where dark specks would be invisible. */
/* the river starts as close to the rail as the rhythm allows: the point of
   this page is that photographs are visible, not that a heading is */
.pf-field{ position:relative; isolation:isolate; padding-top:var(--gap-s) }
.pf-field::before{
  content:""; position:absolute; inset:0; z-index:-1; pointer-events:none;
  background-image:url("../textures/film-grain-1024.png?v=v5-1");
  background-size:300px; opacity:.05;
}
html[data-theme="dark"] .pf-field::before{ filter:invert(1); opacity:.06 }

/* ---------- 4. one frame across -------------------------------------------
   Below roughly 1060px the track no longer fits twice and the spread becomes a
   single column on its own. The hand-laid offset only means something between
   two frames, so it comes off. */
@media (max-width:1060px){
  .pf-shot:nth-child(even){ margin-top:0 }
}

/* ---------- 5. phones ---------------------------------------------------- */
@media (max-width:700px){
  .pf-rail__inner{
    /* on a phone the rail scrolls sideways instead of wrapping, so it stays one
       line high and never eats the top of the screen */
    flex-wrap:nowrap; column-gap:1.3rem; padding:.7rem 0;
    overflow-x:auto; scrollbar-width:none; scroll-snap-type:x proximity;
  }
  .pf-rail__inner::-webkit-scrollbar{ display:none }
  .pf-chapter{ scroll-snap-align:start }
  /* a soft edge on the right so it is obvious the rail carries on */
  .pf-rail{ position:sticky }
  .pf-rail::after{
    content:""; position:absolute; right:0; top:0; bottom:1px; width:2.4rem;
    pointer-events:none;
    background:linear-gradient(to right, rgba(0,0,0,0), var(--paper) 78%);
  }
  .pf-river{ row-gap:clamp(1.4rem,5vw,2rem) }
}

/* ---------- 6. motion opt-out -------------------------------------------- */
@media (prefers-reduced-motion:reduce){
  .pf-shot{ opacity:1; transform:none; transition:none }
  .pf-chapter::after{ transition:none }
}
