@import './tokens.css';

/* ── Art section: bespoke patterns within the cs-system ─────────────────
 * Art project pages and the art index use the same .cs-page--centered
 * scaffolding as case studies (case-study.css). This file only owns the
 * patterns that are unique to the art section:
 *
 *   .cs-works         — asymmetric staggered work stack (project pages)
 *   .cs-work          — a single work figure
 *   .cs-archive-grid  — index page two-up project grid
 *   .lightbox         — multi-image gallery viewer (prev/next/counter)
 *
 * Everything else (cs-page, cs-intro, cs-meta-list, cs-back, cs-lede,
 * cs-section, cs-pager) is defined in case-study.css and used as-is.
 * Art pages load: tokens → styles → case-study → art. */


/* ── Works stack — asymmetric column walk ───────────────────────────────
 * Bespoke full-content band inside .cs-page--centered. Overrides the
 * centered grid's text-band / spill-band indents so the work stack
 * walks across the full 12-col page grid — the wide horizontal range
 * is what makes the asymmetric offset cycle read as rhythm rather
 * than as cards stacking down a column.
 *
 * Wraps the work figures in a flex column (align-items: flex-start so
 * each figure sits at its own start line without the flex container
 * stretching it back to the gutter). Each .cs-work snaps to an
 * integer column span and pushes right by --art-offset (5-step
 * cycle), with vertical breathing on a 7-step cycle — coprime so
 * combined positions don't repeat across a normal exhibition's
 * worth of works. */
.cs-page--centered .cs-section-content > .cs-works {
  width: auto;
  max-width: none;
  margin-left: 0;
  margin-right: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  /* Width of one column inside the works area. Mirrors the page-grid:
   * 12 cols of 1fr with var(--space-4) gap. Each .cs-work uses this
   * to snap its width to column boundaries via
   * calc(N * --art-col + (N-1) * gap). */
  --art-col: calc((100% - 11 * var(--space-4)) / 12);
}

.cs-work {
  display: flex;
  flex-direction: column;
  /* 6-col span by default (portrait / square). Landscape works get
   * .is-landscape from JS (initArtAspect in main.js) and bump to 7
   * cols so they don't read undersized at wide aspect ratios. */
  width: calc(6 * var(--art-col) + 5 * var(--space-4));
  max-width: 100%;
  /* Asymmetric placement: each work pushes right by --art-offset
   * page-grid columns. The offset cycles every 5 works, so a long
   * stack walks 0 → 4 → 1 → 5 → 2 → 0 → … across the grid.
   * Max offset is bounded so a 7-col landscape at offset 5 ends
   * exactly on col 12 — the rhythm never clips off the right edge. */
  --art-offset: 0;
  margin-left: calc(var(--art-offset) * (var(--art-col) + var(--space-4)));
  /* Varied vertical breathing — token-snapped between --space-20
   * (80px) and --space-48 (192px) so the stack stays on the 4px grid
   * even as the rhythm shifts. Default sits at --space-32 (128px). */
  --art-spacing: var(--space-32);
  margin-top: var(--art-spacing);
}

.cs-work:first-child {
  margin-top: 0;
}

.cs-work.is-landscape {
  width: calc(7 * var(--art-col) + 6 * var(--space-4));
}

/* Horizontal 5-step asymmetric cycle: 0, 4, 1, 5, 2 — alternates
 * between the left and right halves of the grid so adjacent works
 * never share a start line. */
.cs-works > .cs-work:nth-child(5n+1) { --art-offset: 0; }
.cs-works > .cs-work:nth-child(5n+2) { --art-offset: 4; }
.cs-works > .cs-work:nth-child(5n+3) { --art-offset: 1; }
.cs-works > .cs-work:nth-child(5n+4) { --art-offset: 5; }
.cs-works > .cs-work:nth-child(5n+5) { --art-offset: 2; }

/* Vertical 7-step spacing cycle — non-monotonic walk across five
 * spacing tokens (20/24/32/40/48), 80–192px. The big 48 hits feel
 * like a held beat between works and let the small 20s read as
 * deliberate pairings rather than just tight stacking. Sequence is
 * tuned so neighbouring values always differ by at least one step on
 * the token scale. */
.cs-works > .cs-work:nth-child(7n+1) { --art-spacing: var(--space-32); }
.cs-works > .cs-work:nth-child(7n+2) { --art-spacing: var(--space-20); }
.cs-works > .cs-work:nth-child(7n+3) { --art-spacing: var(--space-48); }
.cs-works > .cs-work:nth-child(7n+4) { --art-spacing: var(--space-24); }
.cs-works > .cs-work:nth-child(7n+5) { --art-spacing: var(--space-40); }
.cs-works > .cs-work:nth-child(7n+6) { --art-spacing: var(--space-20); }
.cs-works > .cs-work:nth-child(7n+7) { --art-spacing: var(--space-48); }

.cs-work-img-wrap {
  background: var(--color-surface-tertiary);
  border-radius: var(--radius-sharp);
  overflow: hidden;
  cursor: zoom-in;
  margin-bottom: var(--space-4);
  display: block;
}

.cs-work-img {
  display: block;
  width: 100%;
  height: auto;
  transition: opacity 260ms var(--ease-smooth);
}

.cs-work-img-wrap:hover .cs-work-img { opacity: 0.92; }

.cs-work-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  font-size: var(--font-size-caption);
  line-height: var(--line-height-caption);
  letter-spacing: var(--letter-spacing-caption);
  color: var(--color-text-secondary);
  font-weight: var(--font-light);
}

.cs-work-title {
  color: var(--color-text-primary);
  font-weight: var(--font-book);
}

.cs-work-meta-sep {
  color: var(--color-text-tertiary);
}

/* ── Wide-screen tier (≥1600px) ──────────────
 * At this width the centered grid's text band sits in cols 4–9 (3-col
 * indent each side). The works band stays full content width, but the
 * asymmetric offsets damp slightly to avoid pushing wide landscapes
 * off the right edge — same defensive clamp the old .art-page used at
 * its 1600px tier. */
@media (min-width: 1600px) {
  .cs-page--centered .cs-section-content > .cs-works > .cs-work:nth-child(5n+4) {
    --art-offset: 4;
  }
}


/* ── Archive grid (art index page) ──────────────────────────────────────
 * Two-up grid of every project. Sister to .cs-works but tighter:
 * cards sit shoulder-to-shoulder rather than stacked. Each card is a
 * fixed-aspect cover + title + year, and the whole card is the link.
 * No card chrome — the hover dim on the cover matches the dim on
 * individual works inside .cs-works for continuity.
 *
 * Snaps to the page's 12-col grid: each card spans 6 cols, column gap
 * = var(--space-4). Row gap stays generous so the grid still reads as
 * a vertical scroll, not a dense matrix. */
.cs-page--centered .cs-section-content > .cs-archive-grid {
  width: auto;
  max-width: none;
  margin-left: 0;
  margin-right: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--space-4);
  row-gap: var(--space-16);
}

.cs-archive-grid > li {
  grid-column: span 6;
}

.cs-archive-link {
  display: block;
  text-decoration: none;
  color: inherit;
}

.cs-archive-cover {
  background: var(--color-surface-tertiary);
  border-radius: var(--radius-sharp);
  overflow: hidden;
  aspect-ratio: 4 / 3;
  margin-bottom: var(--space-4);
}

.cs-archive-cover-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: opacity 260ms var(--ease-smooth);
}

.cs-archive-link:hover .cs-archive-cover-img { opacity: 0.92; }

.cs-archive-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-1) var(--space-3);
}

.cs-archive-title {
  font-size: var(--font-size-h3);
  line-height: var(--line-height-h3);
  letter-spacing: var(--letter-spacing-h3);
  font-weight: var(--font-semi-bold);
  color: var(--color-text-primary);
}

.cs-archive-year {
  font-size: var(--font-size-caption);
  line-height: var(--line-height-caption);
  letter-spacing: var(--letter-spacing-caption);
  font-weight: var(--font-light);
  color: var(--color-text-tertiary);
  font-variant-numeric: tabular-nums;
}


/* ── Responsive ─────────────────────────────────────────────────────────
 * Tablet (≤1024px): the asymmetric stack loses its rhythm at narrower
 * widths — the landscape variant would overflow once the page narrows
 * past the 12-col content area. Damp the cycle to keep everything in
 * frame, and collapse the archive grid to a tighter two-up.
 *
 * Mobile (≤640px): drop the column-span snap entirely — works go full
 * width, no asymmetry, archive becomes single-column. */
@media (max-width: 1024px) {
  .cs-page--centered .cs-section-content > .cs-works > .cs-work:nth-child(5n+2) { --art-offset: 3; }
  .cs-page--centered .cs-section-content > .cs-works > .cs-work:nth-child(5n+4) { --art-offset: 3; }
}

@media (max-width: 768px) {
  .cs-page--centered .cs-section-content > .cs-works > .cs-work,
  .cs-page--centered .cs-section-content > .cs-works > .cs-work.is-landscape {
    width: 100%;
    --art-offset: 0;
    margin-left: 0;
    --art-spacing: var(--space-20);
  }
  .cs-page--centered .cs-section-content > .cs-works > .cs-work:nth-child(7n+2),
  .cs-page--centered .cs-section-content > .cs-works > .cs-work:nth-child(7n+6) { --art-spacing: var(--space-16); }
  .cs-page--centered .cs-section-content > .cs-works > .cs-work:nth-child(7n+3),
  .cs-page--centered .cs-section-content > .cs-works > .cs-work:nth-child(7n+5) { --art-spacing: var(--space-24); }
}

@media (max-width: 640px) {
  .cs-page--centered .cs-section-content > .cs-archive-grid {
    grid-template-columns: 1fr;
    row-gap: var(--space-16);
  }
  .cs-archive-grid > li {
    grid-column: auto;
  }
}


/* ── Multi-image lightbox (gallery viewer) ──────────────────────────────
 * Full-bleed overlay. Single image at a time, fits viewport with a
 * generous safe area. Arrow keys / on-screen buttons / swipe to move.
 * No fancy zoom — minimal chrome, page colour underneath, esc to close.
 * Lives in body so it's outside any stacking context.
 *
 * Distinct from the case-study .cs-lightbox in case-study.css: this
 * one supports multi-image navigation (prev/next/counter), the
 * case-study one is single-image. Art pages use this; case studies
 * use the simpler one. */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: none;
  background: var(--color-surface-page);
  opacity: 0;
  transition: opacity 220ms var(--ease-smooth);
}

.lightbox.is-open {
  display: flex;
  opacity: 1;
  flex-direction: column;
}

.lightbox-stage {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-16) var(--space-12) var(--space-8);
  min-height: 0;
}

.lightbox-img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  display: block;
  transition:
    opacity 200ms var(--ease-smooth),
    transform 280ms var(--ease-smooth),
    filter 280ms var(--ease-smooth);
}

/* Image swap — `--lb-dir` is set in JS to +1 (next) or -1 (prev). The
 * leaving image translates toward the direction of travel; the
 * entering image starts from the opposite side and settles to 0. */
.lightbox-img.is-leaving {
  opacity: 0;
  filter: blur(8px);
  transform: translateX(calc(var(--lb-dir, 1) * -16px));
}

.lightbox-img.is-entering {
  opacity: 0;
  filter: blur(8px);
  transform: translateX(calc(var(--lb-dir, 1) * 16px));
}

@media (prefers-reduced-motion: reduce) {
  .lightbox-img { transition: opacity 120ms linear; }
  .lightbox-img.is-leaving,
  .lightbox-img.is-entering { filter: none; transform: none; }
}

/* Caption + counter share a single bottom row — caption takes the
 * left, counter parks bottom-right (in line with the menu /
 * case-study UI convention of "metadata in the lower-right"). */
.lightbox-bottom {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-6);
  padding: 0 var(--space-12) var(--space-8);
}

.lightbox-caption {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  font-size: var(--font-size-caption);
  line-height: var(--line-height-caption);
  letter-spacing: var(--letter-spacing-caption);
  color: var(--color-text-secondary);
  font-weight: var(--font-light);
}

.lightbox-caption-title {
  color: var(--color-text-primary);
  font-weight: var(--font-book);
}

.lightbox-counter {
  flex-shrink: 0;
  font-size: var(--font-size-caption);
  line-height: var(--line-height-caption);
  letter-spacing: var(--letter-spacing-caption);
  color: var(--color-text-tertiary);
  font-weight: var(--font-light);
  font-variant-numeric: tabular-nums;
}

/* Close button — mirrors the menu's .site-menu-close: 44px circle,
 * inverse surface, two crossed bars for the X, 90° hover rotate.
 * Same visual language so the user only learns one "close" gesture. */
.lightbox-close {
  position: absolute;
  top: var(--space-6);
  /* `gutter - 10px` mirrors .site-menu-close: 44px circle whose centre
   * lands on the same x-axis as the 24px header hamburger (gutter +
   * 12px from the viewport edge). Keeps every "close" in the site on
   * one axis. */
  right: calc(var(--space-12) - 10px);
  width: 44px;
  height: 44px;
  border-radius: 999px;
  background: var(--color-surface-inverse);
  color: var(--color-text-inverse);
  border: 0;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: transform 200ms var(--ease-smooth);
  /* Sit above .lightbox-nav so the right-side click zone never
   * swallows the close hit area at the top of the screen. */
  z-index: 2;
}

.lightbox-close-bar {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 16px;
  height: 1.5px;
  background: currentColor;
  border-radius: 1px;
}

.lightbox-close-bar:nth-child(1) { transform: translate(-50%, -50%) rotate(45deg); }
.lightbox-close-bar:nth-child(2) { transform: translate(-50%, -50%) rotate(-45deg); }

.lightbox-close:hover { transform: rotate(90deg); }

.lightbox-close:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--color-surface-page),
              0 0 0 4px var(--btn-focus-ring);
}

/* Nav zones — wide column-shaped click targets on each side of the
 * stage. Sized to roughly 1–2 grid columns so clicking anywhere in
 * that band advances. The whole zone is the hit target; the indicator
 * circle is a visual hint that fades in on hover so the affordance
 * reveals itself without cluttering the resting view. Top edge sits
 * below the close button (which has its own z-index); bottom edge
 * sits above the caption. */
.lightbox-nav {
  position: absolute;
  top: var(--space-20);
  bottom: var(--space-20);
  width: clamp(120px, 18vw, 320px);
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Indicator pad = `gutter - 10px` so the 44px chevron circles share
 * an x-axis with .lightbox-close and the header hamburger. */
.lightbox-nav.is-prev { left: 0; justify-content: flex-start; padding-left: calc(var(--space-12) - 10px); }
.lightbox-nav.is-next { right: 0; justify-content: flex-end; padding-right: calc(var(--space-12) - 10px); }

.lightbox-nav-indicator {
  width: 44px;
  height: 44px;
  border-radius: 999px;
  background: var(--color-surface-inverse);
  color: var(--color-text-inverse);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transform: translateX(calc(var(--lb-ind-dir, 1) * 6px));
  transition:
    opacity 220ms var(--ease-smooth),
    transform 280ms var(--ease-smooth);
}

.lightbox-nav.is-prev .lightbox-nav-indicator { --lb-ind-dir: -1; }
.lightbox-nav.is-next .lightbox-nav-indicator { --lb-ind-dir: 1; }

.lightbox-nav:hover .lightbox-nav-indicator,
.lightbox-nav:focus-visible .lightbox-nav-indicator {
  opacity: 1;
  transform: translateX(0);
}

.lightbox-nav:focus-visible { outline: none; }
.lightbox-nav:focus-visible .lightbox-nav-indicator {
  box-shadow: 0 0 0 2px var(--color-surface-page),
              0 0 0 4px var(--btn-focus-ring);
}

.lightbox-nav:disabled { cursor: default; }
.lightbox-nav:disabled .lightbox-nav-indicator { opacity: 0; }

/* Tablet: site gutter steps to --space-6. Keep the close + chevrons
 * on the hamburger axis (gutter - 10px). */
@media (max-width: 1199px) {
  .lightbox-close { right: calc(var(--space-6) - 10px); }
  .lightbox-nav.is-prev { padding-left: calc(var(--space-6) - 10px); }
  .lightbox-nav.is-next { padding-right: calc(var(--space-6) - 10px); }
}

@media (max-width: 768px) {
  .lightbox-stage {
    padding: var(--space-16) var(--space-5) var(--space-4);
  }
  .lightbox-bottom {
    padding: 0 var(--space-5) var(--space-4);
  }
  /* Mobile site gutter is --space-5; same `gutter - 10px` axis. */
  .lightbox-close { right: calc(var(--space-5) - 10px); }
  .lightbox-nav {
    width: clamp(56px, 18vw, 120px);
    top: var(--space-16);
    bottom: var(--space-16);
  }
  .lightbox-nav.is-prev { padding-left: calc(var(--space-5) - 10px); }
  .lightbox-nav.is-next { padding-right: calc(var(--space-5) - 10px); }
}
