/* ── tokens ─────────────────────────────────────────────
   Everything visual starts here. Tune these first.      */
:root {
  --paper: #ffffff;
  --ink:   #000000;
  --accent:#1800ad;
  --hair:  #e6e6e6;
  --plate: #f2f2f2;

  --font: "Helvetica Neue", Helvetica, Arial, sans-serif;

  --step-title: clamp(2.5rem, 7vw, 5.5rem);
  --step-head:  clamp(1.6rem, 4vw, 3rem);
  --step-nav:   clamp(1.1rem, 2.2vw, 1.6rem);
  --step-body:  clamp(1rem, 1.5vw, 1.25rem);

  --gutter: clamp(1rem, 4vw, 3rem);
  --measure: 34ch;

  /* The least a picture is allowed to come to the edge of the screen. At its
     narrowest the side gutter is exactly this, so a photograph on a phone now
     sits in an even margin all the way round; above that the sides open out and
     the frame goes on holding the top and bottom. It is the whole margin for a
     PDF page, which reads outside `main` and so has no gutter of its own.
     Doubled wherever it is subtracted, because it applies to both edges. */
  --frame: 1rem;

  /* collection strips */
  --banner-scrim: rgba(0,0,0,.28);        /* keeps the white label readable over footage */
  --banner-scrim-hover: rgba(0,0,0,.12);

  /* home / video stage */
  --stage-ink: #ffffff;
  --stage-scrim: transparent;        /* video plays untouched at rest */
  --stage-scrim-open: rgba(0,0,0,.35); /* only while the menu is open, so white type reads.
                                          set to transparent for a fully bare menu. */
  --stage-menu-step: clamp(1.75rem, 5vw, 3.25rem);
}

/* ── base ─────────────────────────────────────────────── */
* { box-sizing: border-box; }

/* `hidden` has to win. The browser's own rule for it is `[hidden]{display:none}`,
   which an author stylesheet beats with any `display` at all — so `.portfolio`
   setting `display: grid` quietly made the attribute do nothing, and opening a
   portfolio left the cover sitting above the pages. */
[hidden] { display: none !important; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
}
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
img { display: block; max-width: 100%; }

/* ── framing ──────────────────────────────────────────── */
.bar {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: 1rem var(--gutter);
  flex-wrap: wrap;
}
.bar a.mark { color: var(--ink); font-weight: 700; letter-spacing: .02em; }
.bar nav { display: flex; gap: 1.25rem; flex-wrap: wrap; font-size: .8rem; letter-spacing: .08em; text-transform: uppercase; }

/* The label alone is only 15px tall — far under the 44px touch minimum, and
   short labels like ABOUT were the hardest to hit. Padding doubles the tap
   target; the bar grows a few px taller as a result. */
.bar nav a { padding: .55rem 0; }
@media (pointer: coarse) {
  .bar nav a { padding: .95rem 0; }   /* ~45px tall, above the 44px touch minimum */
}

.bar nav a[aria-current="page"] { text-decoration: underline; }

main { padding: 0 var(--gutter) 6rem; }

h1.page {
  font-size: var(--step-head);
  font-weight: 700;
  text-align: center;
  margin: 2rem 0 3rem;
  letter-spacing: -.01em;
  /* Headings are stored in natural case — "Western Wear" — and shouted here,
     the way .index a and .banner span already do. Editing shows the real name;
     the page still reads WESTERN WEAR. */
  text-transform: uppercase;
}

.lede {
  max-width: var(--measure);
  margin: 0 auto 4rem;
  text-align: center;
  color: var(--accent);
  font-style: italic;
  font-weight: 700;
  font-size: var(--step-body);
  line-height: 1.6;
}

/* ── home ─────────────────────────────────────────────── */
.home { min-height: 100svh; display: grid; align-content: start; padding-top: clamp(2rem, 8vh, 6rem); text-align: center; }
.home h1 { font-size: var(--step-title); font-weight: 700; margin: 0; letter-spacing: -.02em; }
.home .byline { margin: .75rem 0 0; font-size: .9rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; }
.menu { list-style: none; margin: clamp(2rem, 8vh, 5rem) 0 0; padding: 0; display: grid; gap: .5rem; }
.menu a { font-size: var(--step-nav); font-weight: 700; letter-spacing: .02em; text-transform: uppercase; }

/* ── banner list (collections / photography) ──────────── */
.banners { display: grid; gap: .5rem; margin: 0 calc(var(--gutter) * -1); }
.banner {
  position: relative;
  display: grid;
  place-items: center;
  min-height: clamp(9rem, 26vw, 18rem);
  background: var(--plate) center / cover no-repeat;
  color: #fff;
  text-decoration: none;
  overflow: hidden;
}
.banner-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
  opacity: 0;                        /* the still shows through until hover */
  transition: opacity .45s ease;
}
/* only on real pointers — a touch device keeps the still and never loads the video */
@media (hover: hover) {
  .banner:hover .banner-video.is-playing,
  .banner:focus-visible .banner-video.is-playing { opacity: 1; }
}
.banner::after { content: ""; position: absolute; inset: 0; z-index: 1; background: var(--banner-scrim); transition: background .3s ease; }
.banner span {
  position: relative; z-index: 2;
  font-size: var(--step-head);
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  text-align: center;
  padding: 0 1rem;
}
.banner:hover { text-decoration: none; }
.banner:hover::after { background: var(--banner-scrim-hover); }

/* ── index list (pieces within a collection) ──────────── */
.index-label { font-weight: 700; font-size: var(--step-body); margin: 0 0 1rem; }
.index { list-style: none; margin: 0; padding: 0; display: grid; gap: .35rem; }
.index a { font-weight: 700; text-transform: uppercase; letter-spacing: .02em; font-size: var(--step-body); }

/* ── plates (image slots, swap for real imagery) ──────── */
.grid { display: grid; gap: 1.5rem; grid-template-columns: repeat(auto-fill, minmax(min(100%, 16rem), 1fr)); }

/* The three-up row on a piece page. `auto-fill` makes as many tracks as the
   width allows and fills the first three, so from about 1100px up the row hung
   to the left of two empty tracks. `auto-fit` collapses the empties, and the
   max-width stops three plates stretching to fill a 1900px window — which is the
   other way this goes wrong. The auto margins then centre it under the heading.

   Below 1024px nothing changes: the grid is narrower than the cap, so the track
   count and plate size are exactly what they were. */
.grid.plates {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
  max-width: 54rem;
  margin-inline: auto;
}
.plate {
  aspect-ratio: 3 / 4;
  background: var(--plate) center / cover no-repeat;
  display: grid;
  place-items: center;
  color: #b3b3b3;
  font-size: .7rem;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.plate.wide { aspect-ratio: 3 / 2; }
/* A page can be several big images in a row now, not just one under the trio,
   so consecutive ones need the air the grid gives its own cells. Only ever
   applies where there is more than one, so the old pages are unchanged. */
.plate.wide + .plate.wide { margin-top: 1.5rem; }

/* ── portfolio panel (a PDF, shown as its first page) ──
   The same idea as a collection strip: a picture, a scrim, type over it, and the
   whole thing is the link. The aspect comes from the cover the server rendered,
   so an A3 landscape portfolio is shown at A3 landscape and a portrait one is
   not cropped into a shape it is not. */
.portfolio {
  position: relative;
  display: grid;
  place-content: center;
  gap: .9rem;
  aspect-ratio: 1.414 / 1;              /* A3 landscape until a cover says otherwise */
  margin: 0 0 1.5rem;
  padding: 2rem;
  background: var(--plate) center / cover no-repeat;
  color: #fff;
  text-align: center;
  overflow: hidden;
}
.portfolio::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--banner-scrim);
  transition: background .3s ease;
}
.portfolio > * { position: relative; z-index: 2; }
.portfolio:hover { text-decoration: none; }
.portfolio:hover::after { background: var(--banner-scrim-hover); }

.portfolio-cue {
  font-weight: 700;
  font-size: var(--step-body);
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: underline;
  text-underline-offset: .35em;
}
.portfolio-go {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: .6rem;
}
.portfolio-size { font-size: .7rem; letter-spacing: .08em; opacity: .75; }

/* Reading the portfolio in place. The panel is replaced by the page, at the
   same aspect, so nothing jumps when it opens. */
/* The portfolio reads in its own scroll. In the page's scroll it shared one
   scrollbar with the photographs, so turning its pages dragged the whole page
   along and closing left you far below where you started. Fixed and scrolling
   itself, the page behind never moves, so closing needs no restoring. */
.pager {
  position: fixed;
  inset: 0;
  z-index: 60;
  overflow-y: auto;
  overscroll-behavior: contain;    /* a flick past the last page stays here */
  scroll-snap-type: y mandatory;   /* a reader turns one page at a time */
  background: var(--paper);
  /* the overlay is its own scrollport, outside main, so the frame is its
     padding rather than something subtracted from the sheet's width.
     The top padding is what gives page one its frame: every other page centres
     itself in the scrollport when it snaps, but the first cannot scroll above
     the start, so without this it opens flush against the top edge while all
     its neighbours sit framed. With it, centring page one works out to scroll
     position zero, which is exactly where the overlay opens. */
  padding-inline: var(--frame);
  padding-top: var(--frame);
  padding-bottom: 3.5rem;
  outline: none;
}
body.reading { overflow: hidden; }
.pager-sheet {
  display: block;
  margin: 0 auto 2px;
  max-height: 100vh;
  max-height: calc(100svh - var(--frame) * 2);
  max-width: 100%;
  width: auto;
  height: auto;
  scroll-snap-align: center;
}
.pager-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 61;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .6rem 1rem;
  padding: .7rem 1rem;
  background: var(--paper);
  border-top: 1px solid var(--hair);
  font-size: .75rem;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.pager-bar button,
.pager-bar a {
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  padding: .45rem .7rem;
  border: 1px solid var(--hair);
  border-radius: 4px;
  background: none;
  color: var(--ink);
  cursor: pointer;
  text-decoration: none;
}
.pager-bar button:hover,
.pager-bar a:hover { border-color: var(--ink); }
.pager-count { min-width: 5ch; opacity: .6; font-variant-numeric: tabular-nums; }
.pager-file { margin-left: auto; }

/* ── reading: one thing per screen ─────────────────────
   A photograph at full width was taller than any screen, so every one of them
   was seen two thirds at a time and the page was eight screens of scrolling.
   Capped to the viewport instead, each is whole, and the scroll snaps between
   them.

   `proximity`, not `mandatory`: a flick carries you into range of the next
   photograph and it pulls you in, while a deliberate nudge leaves you where you
   put it. Mandatory also forces the browser to resolve to a snap point on load,
   which scrolled the header away before anyone had touched anything — hence the
   snap point on `.bar`, so the top of the page is a place you are allowed to
   stop. The editor turns all of this off in artist.css; a page that pulls itself
   to the nearest photograph cannot be edited. */
html { scroll-snap-type: y proximity; scroll-behavior: smooth; }
.bar { scroll-snap-align: start; }

.plate.wide {
  aspect-ratio: auto;              /* the photograph sets the height now */
  background: none;
  padding: 0;
  margin-inline: auto;
  display: grid;
  place-items: center;
  scroll-snap-align: center;
}
.plate.wide img {
  max-height: 100vh;
  /* the visible viewport, address bar and all, less the frame */
  max-height: calc(100svh - var(--frame) * 2);
  max-width: 100%;                 /* sides are already inside main's gutter */
  width: auto;
  height: auto;
}

/* The frame takes the photograph's height rather than forcing a full screen. A
   fixed 100svh frame looked right on a laptop and wasted 44-68% of a phone
   screen, because a portrait photograph in a portrait viewport is bounded by
   width, not height — and that empty space still has to be scrolled past. */
.portfolio {
  height: auto;
  max-height: calc(100svh - var(--frame) * 2);
  /* the width cap is derived from the height cap, so it takes the frame too */
  max-width: min(100%, calc((100svh - var(--frame) * 2) * 0.8));
  margin: 0 auto 3rem;             /* air before the photographs begin */
  scroll-snap-align: center;
}

/* ── reel (a clip at the top of a piece) ───────────────
   Scenery, not a player. No controls, and pointer events off, so there is
   nothing to click, pause or scrub and a tap reaches the page underneath — the
   same way a strip's footage is a surface rather than something you operate.

   A <video> is a replaced element, so it takes exactly the rules a photograph
   takes: its own dimensions, bounded by the viewport, inside the same frame.
   That is the point — a piece that opens with a clip and a piece that opens
   with a photograph read the same on the way down the page. */
.reel {
  /* Its own shape and its own width, by the same arithmetic .portfolio uses: as
     wide as the viewport allows, or as wide as the clip can be while its full
     height still fits inside the frame — whichever is smaller. Both numbers are
     written inline from the stored dimensions, so the box is correct before any
     footage arrives and the photographs below never jump. The fallback is a
     landscape clip, which is the shape an empty panel shows. */
  aspect-ratio: 16 / 9;
  width: min(100%, calc((100svh - var(--frame) * 2) * var(--ar, 1.7778)));
  margin: 0 auto 3rem;             /* air before the photographs begin */
  scroll-snap-align: center;
}
.reel-video {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--plate);        /* grey, never white, while it loads */
  pointer-events: none;
}
/* nothing uploaded yet: the same frame, grey, at a shape a clip might be */
.reel-empty {
  display: grid;
  place-items: center;
  background: var(--plate);
  color: #b3b3b3;
  font-size: .7rem;
  letter-spacing: .12em;
  text-transform: uppercase;
}

/* nothing uploaded yet: the same panel, grey, with no type over a photograph */
.portfolio-empty { color: #b3b3b3; }
.portfolio-empty::after { background: none; }
.caption { display: flex; justify-content: space-between; gap: 1rem; margin-top: .6rem; font-size: .7rem; letter-spacing: .08em; text-transform: uppercase; }

/* ── prose (about / resume) ───────────────────────────── */
.prose { max-width: 60ch; margin: 0 auto; font-size: var(--step-body); line-height: 1.7; }
.prose h2 { font-size: 1rem; letter-spacing: .1em; text-transform: uppercase; margin: 2.5rem 0 .75rem; }
.prose ul { padding-left: 1.1rem; }

footer { padding: 2rem var(--gutter) 3rem; font-size: .7rem; letter-spacing: .1em; text-transform: uppercase; color: #999; text-align: center; }


/* ── home stage (video + hamburger) ──────────────────────
   index.html only. The video is the page; the hamburger and
   the video surface both toggle the menu.                */
.stage-page { overflow: hidden; }

.stage {
  position: relative;
  height: 100svh;
  width: 100%;
  cursor: pointer;
  color: var(--stage-ink);
  background: #000;   /* so white type is readable before the video paints */
}

.stage-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
.stage::after {           /* scrim — transparent by default */
  content: "";
  position: absolute;
  inset: 0;
  background: var(--stage-scrim);
  z-index: 1;
  pointer-events: none;
  transition: background .3s ease;
}

.stage-bar,
.stage-center { position: relative; z-index: 2; }

.stage-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1.25rem var(--gutter);
}
.stage-mark {
  font-weight: 700;
  font-size: .8rem;
  letter-spacing: .12em;
  text-transform: uppercase;
}

/* hamburger */
.burger {
  appearance: none;
  background: none;
  border: 0;
  padding: .5rem;
  margin: -.5rem;
  cursor: pointer;
  color: inherit;
}
.burger-box { display: grid; gap: 5px; width: 30px; }
.burger-box i {
  display: block;
  height: 2px;
  background: currentColor;
  transition: transform .3s ease, opacity .2s ease;
}
.menu-open .burger-box i:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.menu-open .burger-box i:nth-child(2) { opacity: 0; }
.menu-open .burger-box i:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* title and menu share the centre; one fades as the other arrives */
.stage-center {
  height: calc(100svh - 5.5rem);
  display: grid;
  place-items: center;
  text-align: center;
  padding: 0 var(--gutter);
}
.stage-title,
.stage-menu {
  grid-area: 1 / 1;
  transition: opacity .35s ease;
}

.stage-title h1 {
  margin: 0;
  font-size: var(--step-title);
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: .95;
}
.stage-title p {
  margin: .9rem 0 0;
  font-size: .8rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
}

/* menu: transparent ground, white bold letters */
.stage-menu { opacity: 0; pointer-events: none; }
.stage-menu ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .35rem; }
.stage-menu a {
  color: var(--stage-ink);
  font-size: var(--stage-menu-step);
  font-weight: 700;
  letter-spacing: .01em;
  text-transform: uppercase;
  line-height: 1.15;
}
.stage-menu a:hover { text-decoration: underline; }

.menu-open .stage::after { background: var(--stage-scrim-open); }
/* The faded title must also stop catching clicks. opacity:0 creates a stacking
   context, so the invisible title paints ABOVE the in-flow menu and swallows
   the two links it overlaps — on this layout, Photography and About. */
.menu-open .stage-title { opacity: 0; pointer-events: none; }
.menu-open .stage-menu  { opacity: 1; pointer-events: auto; }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

@media (prefers-reduced-motion: reduce) {
  .banner-video,
  .burger-box i,
  .stage-title,
  .stage-menu,
  .stage::after { transition: none; }
}
