/* Emma Lee — project gallery lightbox. Config-driven (assets/gallery.json). */
.lightbox{position:fixed;inset:0;margin:auto;width:100vw;height:100vh;max-width:none;max-height:none;
  padding:0;border:0;background:var(--paper);color:var(--ink)}
.lightbox::backdrop{background:rgba(11,11,11,.72)}
.lightbox[open]{display:grid;grid-template-rows:minmax(0,1fr)}

.lb-close{position:absolute;top:20px;right:20px;z-index:5;padding:10px 14px;background:var(--paper)}
/* Over the image the chevrons need some backdrop to stay legible against
   whatever the photo happens to be, but a muted translucent dark disc does
   that without the solid near-white circle shouting over the artwork. */
.lb-nav{position:absolute;top:50%;transform:translateY(-50%);z-index:5;width:44px;height:44px;
  display:grid;place-items:center;padding:0;border-radius:50%;
  color:rgba(246,246,246,.6);background:rgba(11,11,11,.38);
  transition:color .2s var(--ease),background .2s var(--ease)}
.lb-nav svg{width:22px;height:22px;display:block}
.lb-nav:hover{color:var(--paper);background:rgba(11,11,11,.6)}
.lb-nav:focus-visible{outline:2px solid var(--paper);outline-offset:3px}
.lb-prev{left:20px}
.lb-next{right:20px}

.lb-body{display:grid;grid-template-columns:minmax(0,1.5fr) minmax(0,1fr);grid-template-rows:minmax(0,1fr);
  align-items:center;width:100%;height:100%;min-height:0;gap:0}
.lb-stage{position:relative;display:grid;place-items:center;height:100%;padding:64px 5vw;background:#111;overflow:hidden}
.lb-img{max-width:100%;max-height:82vh;width:auto;height:auto;object-fit:contain;box-shadow:0 30px 60px rgba(0,0,0,.35);
  touch-action:pan-y;-webkit-user-drag:none;user-select:none}
.lb-meta{padding:6vh 4vw;align-self:stretch;min-height:0;overflow-y:auto;overscroll-behavior:contain}
/* The resize divider is a mobile-only affordance: on desktop the panel sits
   beside the image in its own column, so there is no space for the two to
   trade. The media query below turns it on. */
.lb-grip{display:none}
.lb-thumb-row{touch-action:pan-x pan-y;user-select:none;cursor:grab}
.lb-thumb-row:active{cursor:grabbing}
.lb-count{margin-bottom:24px;color:#777}
.lb-meta h2{font:900 clamp(28px,3vw,44px)/.95 var(--display);letter-spacing:-.035em;text-transform:uppercase;margin-bottom:20px}
/* pre-line so line breaks typed into the admin's description textarea survive
   (it's set via textContent, so a newline would otherwise collapse to a
   space); runs of stray spaces still collapse, unlike pre-wrap. */
.lb-desc{font:400 clamp(15px,1.3vw,19px)/1.5 var(--serif);margin-bottom:28px;white-space:pre-line}
/* Links are auto-detected in the description text. A full article URL is
   long and has no line-break opportunities of its own, so overflow-wrap is
   what stops it pushing the panel wider than its column. */
.lb-desc a{color:inherit;text-decoration:underline;text-underline-offset:3px;
  text-decoration-thickness:1px;text-decoration-color:rgba(11,11,11,.35);
  overflow-wrap:anywhere;transition:text-decoration-color .18s var(--ease)}
.lb-desc a:hover{text-decoration-color:currentColor}
.lb-desc a:focus-visible{outline:2px solid var(--ink);outline-offset:2px;border-radius:2px}
.lb-facts{display:flex;flex-direction:column;gap:8px;padding-top:20px;border-top:1px solid var(--soft)}
.lb-flipbook{display:inline-block;margin-top:22px;padding:0;text-align:left;
  text-decoration:underline;text-underline-offset:5px;color:var(--ink);
  transition:opacity .2s var(--ease)}
.lb-flipbook:hover{opacity:.6}
/* Same treatment as the flipbook link: both are "there is more to read
   about this piece", and two differently-styled actions in one small panel
   would read as two different kinds of thing. */
.lb-link{display:inline-block;margin-top:22px;padding:0;text-align:left;
  text-decoration:underline;text-underline-offset:5px;color:var(--ink);
  transition:opacity .2s var(--ease)}
.lb-link:hover{opacity:.6}
.lb-link:focus-visible{outline:2px solid var(--ink);outline-offset:3px;border-radius:2px}
.lb-link[hidden]{display:none}

/* ---------- gallery mode: thumbnail carousel beneath the main image ---------- */
/* The stage gains a second row for the strip, and the prev/next buttons are
   moved into that strip by lightbox.js (position:static here) rather than
   floating over the image, so they read as the carousel's controls. */
/* Flex column rather than the grid the stage uses otherwise: it centres the
   image and the strip together as one block, so the strip sits directly under
   the image instead of pinning to the bottom of the stage with dead black
   between them. min-height:0 lets the image shrink when a tall one would
   otherwise push the strip out of view; object-fit:contain on .lb-img keeps
   the picture itself undistorted whatever the box does. */
.lightbox.has-gallery .lb-stage{display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:14px;padding:60px 3vw 24px}
/* A FIXED box rather than one that follows each picture's aspect ratio.
   Stepping from a landscape frame to a portrait one used to change the
   image's height, which shoved the filmstrip up and down under it.
   object-fit:contain letterboxes the picture inside the constant box, so
   the strip never moves. The subtraction is the stage padding, the gap,
   one tile row and the dots. */
.lightbox.has-gallery .lb-img{
  flex:none;width:100%;height:calc(100svh - 240px);min-height:180px;
  max-height:none;object-fit:contain}
.lightbox.has-gallery .lb-gallery{flex:none}
/* In the strip they sit on the stage's flat black, so they need no disc at
   all until hovered. */
.lightbox.has-gallery .lb-nav{position:static;transform:none;flex:none;width:40px;height:40px;background:none}
.lightbox.has-gallery .lb-nav:hover{background:rgba(246,246,246,.1)}

.lb-gallery{width:100%;min-width:0;display:flex;flex-direction:column;align-items:center;gap:12px}
.lb-thumb-row{display:flex;align-items:center;justify-content:center;gap:14px;width:100%;min-width:0}
/* Flex with a percentage tile rather than grid tracks. Each tile is one
   tenth of the row's ACTUAL width, so ten always fit on one line however
   wide the row ends up — an absolute 68.8px overflowed, because the row
   also holds the two arrows and their gaps, and the eleventh thing wrapped.
   Being a share of the row rather than a share of the CONTENT also means
   the size doesn't change with the image count: four images draw four
   tenth-width tiles and centre, instead of stretching to fill. */
.lb-thumb-grid{--per-row:10;
  display:flex;flex-wrap:wrap;justify-content:center;
  gap:8px;flex:1 1 auto;min-width:0;max-width:760px}
.lb-thumb-grid > .lb-thumb{
  flex:none;
  width:calc((100% - (var(--per-row) - 1) * 8px) / var(--per-row))}
.lb-thumb{position:relative;aspect-ratio:1;overflow:hidden;background:#222;padding:0;border:0;border-radius:3px;
  opacity:.45;transition:opacity .25s var(--ease)}
.lb-thumb img{width:100%;height:100%;object-fit:cover;-webkit-user-drag:none}
.lb-thumb:hover{opacity:.8}
.lb-thumb[aria-current="true"]{opacity:1;outline:2px solid var(--pink);outline-offset:1px}
.lb-thumb:focus-visible{outline:2px solid var(--paper);outline-offset:2px}

.lb-dots{display:flex;justify-content:center;gap:8px}
.lb-dot{width:8px;height:8px;padding:0;border:0;border-radius:50%;background:rgba(246,246,246,.28);
  transition:background .25s var(--ease)}
.lb-dot:hover{background:rgba(246,246,246,.6)}
.lb-dot[aria-current="true"]{background:var(--paper)}
.lb-dot:focus-visible{outline:2px solid var(--paper);outline-offset:3px}

@media(max-width:850px){
  .lb-thumb-grid{--per-row:6}
}
@media(max-width:560px){
  .lb-thumb-grid{--per-row:4}
}

/* Cross-fade between images. Opacity only — the old rule also scaled the
   image to .98, and that zoom-pop on every step is what made navigating feel
   like a jolt rather than a dissolve. The out leg is deliberately quicker
   than the in leg (.17s vs .34s, and lightbox.js swaps src at the 170ms mark)
   so the incoming frame does most of the visible work; against the stage's
   flat black that reads as a cross-fade. */
/* The image's own fade is driven by lightbox.js via the Web Animations API,
   not from here — a CSS class toggle couldn't guarantee the src swap landed
   exactly at opacity 0. Only the meta column fades via .switching. */
.lb-meta > *{transition:opacity .32s var(--ease),transform .32s var(--ease)}
.lightbox.switching .lb-meta > *{opacity:0;transform:translateY(6px)}

@media(max-width:850px){
  /* The two panes TRADE space rather than either one growing. The stage is
     sized to its contents, the meta takes whatever is left, and the
     description inside it absorbs the remainder. Nothing here can grow, so
     the sheet can never exceed one screen and there is only ever one
     scrollbar — the description's. Earlier attempts let .lb-body grow and
     scroll, which kept the dots but produced a second scrollbar and pushed
     the bottom of the panel off-screen. */
  .lb-body{grid-template-columns:1fr;grid-template-rows:auto minmax(0,1fr);
    height:100%;min-height:0;overflow:hidden;align-items:stretch}
  .lb-stage{height:auto;overflow:visible;padding:52px 6vw 18px}
  .lb-img{max-height:48svh}
  /* Driven by a custom property so the drag handle can move it. The default
     is the balanced split; .lb-grip rewrites it per reader. */
  .lightbox.has-gallery .lb-img{height:var(--lb-img-h,39svh);min-height:0;max-height:none}
  .lightbox.has-gallery .lb-stage{gap:12px}
  .lb-gallery{padding-bottom:2px}

  /* Tile width is a share of the row, so on a wide phone or a tablet the
     squares grew to ~100px. They only looked small before because the stage
     clipped them. Capping the tile and letting justify-content centre the
     short row keeps a filmstrip rather than a second gallery, and keeps the
     stage short enough that the dots stay on screen. */
  .lb-thumb-grid > .lb-thumb{max-width:60px}
  .lb-nav svg{width:20px;height:20px}

  /* Flex column so the description can be the one element that flexes. */
  .lb-meta{display:flex;flex-direction:column;padding:0 6vw 18px;overflow:hidden;min-height:0}

  /* flex:1 + min-height:0 rather than a hardcoded height: the description
     takes exactly what the fixed parts leave, which is constant for a given
     screen. That keeps the no-shift behaviour — a 29-character caption
     leaves the facts where a 700-character one does — without a magic
     number, and it is what lets the divider work at all.
     touch-action:pan-y lets a vertical drag scroll the text while a
     horizontal swipe still reaches the lightbox's own next/prev gesture. */
  .lb-desc{flex:1 1 auto;min-height:0;margin-bottom:0;overflow-y:auto;
    overscroll-behavior:contain;-webkit-overflow-scrolling:touch;touch-action:pan-y;
    padding-right:10px;scrollbar-width:thin;scrollbar-color:rgba(11,11,11,.22) transparent}
  .lb-desc::-webkit-scrollbar{width:3px}
  .lb-desc::-webkit-scrollbar-thumb{background:rgba(11,11,11,.22);border-radius:99px}
  .lb-desc::-webkit-scrollbar-track{background:transparent}

  .lb-count{flex:none;margin-bottom:8px}
  /* Reserving two lines keeps the description's top edge still as well as
     its bottom, since titles wrap to two lines on some images and one on
     others within the same gallery. */
  .lb-title{flex:none;min-height:1.9em;margin-bottom:10px}
  .lb-facts{flex:none;min-height:46px;margin-top:12px;padding-top:12px}
  .lb-flipbook{flex:none;margin-top:12px}
  .lb-link{flex:none;margin-top:12px}

  /* The divider. Hidden above this breakpoint, where the panel is a column
     beside the image and there is nothing to trade. */
  .lb-grip{display:grid;place-items:center;flex:none;height:22px;margin:0 -6vw;
    cursor:ns-resize;touch-action:none;background:none;border:0;padding:0;width:auto}
  .lb-grip::before{content:"";width:38px;height:4px;border-radius:99px;background:#cfcfcf;
    transition:background .15s var(--ease),width .15s var(--ease)}
  .lb-grip:hover::before{background:#a8a8a8;width:52px}
  .lightbox.lb-resizing .lb-grip::before{background:var(--ink);width:52px}
  .lb-grip:focus-visible{outline:2px solid var(--ink);outline-offset:-4px;border-radius:4px}
  /* While dragging, the text must not swallow the pointer or start scrolling. */
  .lightbox.lb-resizing .lb-desc{pointer-events:none}
  .lightbox.lb-resizing .lb-img{transition:none}
}
@media(prefers-reduced-motion:reduce){
  .lb-img,.lb-meta > *{transition:none!important}
  .lightbox.switching .lb-img,.lightbox.switching .lb-meta > *{opacity:1!important;transform:none!important}
}
