:root {
  --card-bg-beige: #e2cfb7;
  --card-bg-gray: #d9d9d9;
  --card-bg-green: #ccffa4;
  --card-bg-orange: #ffc073;
  --card-bg-pink: #ff8f8f;
  --card-bg-teal: #b7dfe2;
}

/* ============================================================================ */
/* Redesign: slide-mount card, home strip, works grid, viewer, light modes      */
/* ============================================================================ */

/* ── Slide-mount card (shared by home strip + works grid + index list) ──────── */
/* The image's share of the mount is one rule: smaller slides get a larger film
   window. Driven by --fp (figure footprint, 0–1); home.js recomputes it per
   card on load/resize. Padding is a fixed length, never a %, since a card's
   containing block can be far wider than the card. */
.slide-card {
  --fp: 0.86;
  align-items: center;
  aspect-ratio: 1 / 1;
  background: #0c0c0c;
  border-radius: 10px;
  cursor: pointer;
  display: flex;
  justify-content: center;
  list-style: none;
  overflow: hidden;
  padding: 12px;
  position: relative;
  transition: background 0.2s ease;
}

.slide-card figure {
  align-items: center;
  background: #000;
  display: flex;
  justify-content: center;
  margin: 0;
  overflow: hidden;
  transition: background 0.2s ease;
}

/* Mount-to-image proportions of a real archival slide, scaled by --fp. The
   square window is the tightest crop, so it sits a touch inside the others. */
.slide-card[data-orientation="landscape"] figure { aspect-ratio: 3 / 2; width: calc(var(--fp) * 100%); height: auto; }
.slide-card[data-orientation="portrait"]  figure { aspect-ratio: 2 / 3; height: calc(var(--fp) * 100%); width: auto; }
.slide-card[data-orientation="square"]    figure { aspect-ratio: 1 / 1; width: calc((var(--fp) - 0.08) * 100%); height: auto; }

.slide-card img {
  display: block;
  height: 100%;
  object-fit: cover;
  width: 100%;
  transition: filter 0.2s ease;
}

/* Corner labels printed on the mount */
.slide-card .slide-meta {
  display: block;
  inset: 0;
  pointer-events: none;
  position: absolute;
}

.slide-card .slide-meta > span {
  font-size: var(--font-size-b1);
  max-width: 45%;
  overflow: hidden;
  position: absolute;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.slide-card .slide-meta-tl { left: 10px;  top: 6px; }
.slide-card .slide-meta-tr { right: 10px; top: 6px; }
.slide-card .slide-meta-bl { left: 10px;  bottom: 6px; }

/* Portrait slides: the whole landscape label layout is rotated 90° clockwise so
   it reads identically — title + year stay paired on one mount band (now the
   right edge), category on the other (now the left edge). */
.slide-card[data-orientation="portrait"] .slide-meta > span {
  max-height: 45%;
  max-width: none;
  writing-mode: vertical-rl;
}
.slide-card[data-orientation="portrait"] .slide-meta-tl { top: 10px;    right: 6px; left: auto;  bottom: auto; } /* title  → top-right */
.slide-card[data-orientation="portrait"] .slide-meta-tr { bottom: 10px; right: 6px; left: auto;  top: auto; }    /* year   → bottom-right */
.slide-card[data-orientation="portrait"] .slide-meta-bl { top: 10px;    left: 6px;  right: auto; bottom: auto; } /* category → top-left */

/* Light ON (Slide): backlit film — vivid images on a dark carrier. The carrier
   is not flat black: each category's colour survives in it, nearly extinguished
   (see the color-mix rules generated in home.php); #0c0c0c is the fallback for
   uncategorised slides. Labels are printed faint and brighten on hover. */
html[data-light="on"] .slide-card { background: #0c0c0c; }
html[data-light="on"] .slide-card figure { background: #000; }
html[data-light="on"] .slide-card img { filter: brightness(1.05) saturate(1.1) contrast(1.02); }
html[data-light="on"] .slide-card .slide-meta {
  color: #d8d8d8;
  opacity: 0.4;
  transition: opacity 0.35s ease, color 0.35s ease;
}
html[data-light="on"] .slide-card:hover { background: #2a2a2a; }
html[data-light="on"] .slide-card:hover .slide-meta { opacity: 0.85; }

/* Light OFF (Slide + Text): mounts take the colour assigned to each category,
   the title / year / category labels are printed on the mount. */
html[data-light="off"] .slide-card { background: var(--card-bg-gray); }
html[data-light="off"] .slide-card figure { background: #1c1c1c; }
html[data-light="off"] .slide-card img { filter: brightness(0.62) saturate(0.75); }
html[data-light="off"] .slide-card .slide-meta {
  color: #141414;
  opacity: 1;
  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.45);
}

/* Hovering a resting slide holds it up to the lamp: the image alone pops to
   full brightness while the mount stays printed. */
html[data-light="off"] .slide-card:hover img { filter: brightness(1) saturate(1); }

/* Per-category mount colours are generated dynamically from the panel-managed
   list (Site > Categories) — see the inline <style> block in home.php. The
   grey above is the fallback for uncategorised images. */

/* ── Home view: banner + auto-scroll strip sit in the lower-middle, with a
   tall footer occupying the bottom 30% of the page. ─────────────────────────── */
.home-view {
  display: flex;
  flex-direction: column;
  justify-content: flex-end; /* push banner + strip down toward the footer */
  min-height: 100vh;
  min-height: 100dvh;        /* track the real visible viewport on mobile */
  padding-bottom: var(--footer-h); /* reserve room for the footer band */
  width: 100%;
}

/* The home page is sized to the viewport — lock document scroll so a sub-pixel
   overflow or an overscroll bounce can't nudge the page up and down when the
   wheel/trackpad is used vertically. (Scoped to the home view only.) */
html:has(body[data-view="home"]) {
  overflow-y: hidden;
  overscroll-behavior: none;
}

/* Banner component, shared by Home (in-flow, lower-middle) and Works (pinned to
   the top). Fixed height with the inner bottom-aligned so the inset rule (line #1)
   always sits at the banner's bottom edge. */
.wzw-banner {
  display: flex;
  flex-direction: column;
  height: var(--banner-height);
  justify-content: flex-end;
  position: relative;
  width: 100%;
  z-index: 901; /* above banner-mask (800); .is-top overrides to fixed/900 */
}

.wzw-banner.is-top {
  background: var(--main-bg-color);
  left: 0;
  position: fixed;
  top: 0;
  transition: background-color 0.2s ease;
  z-index: 900;
}

/* .banner-inner lives in index.css (shared with the viewer chrome). */

.home-strip {
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  width: 100%;
}

.home-strip::-webkit-scrollbar { height: 0; width: 0; }

.strip-track {
  align-items: center;
  display: inline-flex;
  gap: 28px;
  list-style: none;
  padding: var(--content-gap) 16px;
}

.home-strip .slide-card {
  flex-shrink: 0;
  height: 46vh;
  max-height: 480px;
}

/* Mobile: the strip keeps its horizontal swipe (native touch scroll — the JS
   drag-pan stands down for touch pointers), sized to the visible viewport. */
@media (max-width: 700px) {
  .home-strip { touch-action: pan-x; }
  .home-strip .slide-card {
    height: 40vh;
    height: 40dvh;
  }
}

/* Touch devices: no hover. The corner labels print legibly at rest — they are
   the touch stand-in for the works-grid hover metadata in the footer centre —
   and a press holds a resting slide up to the lamp. */
@media (hover: none) {
  html[data-light="on"] .slide-card .slide-meta { opacity: 0.85; }
  html[data-light="off"] .slide-card:active img { filter: brightness(1) saturate(1); }
}

/* Gallery fade: a 10px band just inside each rule that fades from the page
   colour (at the rule) to transparent, so slides dissolve into the chrome
   instead of cutting off hard. */
.wzw-banner.is-top::after {
  background: linear-gradient(to bottom, var(--main-bg-color), transparent);
  content: "";
  height: 10px;
  left: 0;
  pointer-events: none;
  position: absolute;
  right: 0;
  top: 100%;
}

body[data-view="works"] .bottom-bar::before {
  background: linear-gradient(to top, var(--main-bg-color), transparent);
  bottom: 100%;
  content: "";
  height: 10px;
  left: 0;
  pointer-events: none;
  position: absolute;
  right: 0;
}

/* ── Works view: horizontally-scrolling slide-mount contact sheet ───────────── */
/* Reuses the home banner (pinned to the top via .is-top) and the shared 20%
   footer. The grid fills the band between them and scrolls sideways: cards stack
   into rows top-to-bottom, then flow into the next column to the right. */
.works-view {
  box-sizing: border-box;
  height: 100vh;
  padding: calc(var(--banner-height) + var(--content-gap)) 0 calc(var(--footer-h) + var(--content-gap));
  width: 100%;
}

.works-grid {
  display: grid;
  gap: 16px;
  grid-auto-columns: max-content;
  grid-auto-flow: column;
  grid-template-rows: repeat(var(--works-rows, 3), 1fr);
  height: 100%;
  list-style: none;
  overflow-x: auto;
  overflow-y: hidden;
  padding: 0 16px;
  scrollbar-width: none;
  touch-action: pan-x; /* hybrid devices: sideways swipes stay on the grid */
}

.works-grid::-webkit-scrollbar { height: 0; width: 0; }

.works-grid .slide-card {
  aspect-ratio: 1 / 1;
  height: 100%;
  width: auto;
}

/* Mobile: the contact sheet becomes a single column of full-width mounts
   scrolling vertically. Block flow, NOT grid-auto-flow:row — Chrome sizes auto
   row tracks from content (24px padding; cyclic-percentage figures) not the
   aspect-ratio-transferred size, so rows collapse and mounts overlap. Block
   boxes take height straight from aspect-ratio × width. */
@media (max-width: 700px) {
  .works-view {
    height: 100vh;
    height: 100dvh;
  }

  .works-grid {
    display: block;
    overflow-x: hidden;
    overflow-y: auto;
    touch-action: pan-y;
  }

  .works-grid .slide-card {
    height: auto;
    margin-bottom: 16px;
    width: 100%;
  }

  /* Corner labels one size up — a full-width mount carries larger print. */
  .slide-card .slide-meta > span { font-size: var(--font-size-0); }
}

/* ── Index view: stacked project rows (header + clipped slide row) ──────────── */
/* A vertically-scrolling list under the fixed top banner. Each project shows its
   title / category / year, then a single row of small slide-mounts that is
   CLIPPED to the page width — the overflow "+N" mount (built in home.js) takes
   the last visible slot. */
.index-view {
  box-sizing: border-box;
  height: 100vh;
  height: 100dvh;
  padding: calc(var(--banner-height) + var(--content-gap)) 16px calc(var(--footer-h) + var(--content-gap));
  width: 100%;
}

/* The list scrolls within the band between the banner and the toolbar, so the
   scrollbar sits inside the index area rather than on the document edge. */
.index-list {
  height: 100%;
  overflow-y: auto;
  touch-action: pan-y;
  width: 100%;
}

.index-project {
  border-top: 1px solid var(--rule-color);
  padding: 16px 0 22px;
}

/* No rule above the first project — it meets the banner's own rule. */
.index-list > .index-project:first-child { border-top: 0; padding-top: 0; }

/* Header row: title on the left, category + year pushed to the right (mirrors
   the banner's right-aligned name). Columns are proportional so the cluster
   lands in the same place regardless of title length. */
/* Sits between the banner (h4, 18.75px) and the footer toolbar (15.5px). */
.index-head {
  align-items: baseline;
  column-gap: 24px;
  display: grid;
  font-size: 16.5px;
  grid-template-columns: 1fr 16% 9%;
  margin-bottom: 14px;
}

.index-title {
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.index-cat { text-transform: capitalize; white-space: nowrap; }
.index-year { text-align: right; white-space: nowrap; }

/* The image row never wraps or scrolls — extras are clipped and replaced by the
   "+N" tile (home.js fits the variable-width images greedily to the row width). */
.index-slides {
  align-items: center;
  display: flex;
  flex-wrap: nowrap;
  gap: 16px;
  list-style: none;
  overflow: hidden;
}

/* No slide mount on the index — just the images, all at a uniform HEIGHT with
   their natural width. The shared mount styling (square frame, padding, light-
   mode backgrounds, letterboxed figure) is unwound here so the bare image shows. */
.index-slides .slide-card {
  aspect-ratio: auto;
  background: none;
  border-radius: 0;
  flex: 0 0 auto;
  height: clamp(122px, 15vw, 184px);
  overflow: visible;
  padding: 0;
  width: auto;
}

.index-slides .slide-card figure {
  aspect-ratio: auto;
  background: none;
  height: 100%;
  width: auto;
}

.index-slides .slide-card img {
  height: 100%;
  object-fit: contain;
  width: auto;
}

/* Unset the mount backgrounds, more specific than the shared light-mode rules
   AND the per-category rules inlined by home.php (loaded after this file —
   hence the extra .index-project level), so the index shows the bare image.
   Light ON: natural. Light OFF: image rests dim; hover holds it to the lamp. */
html[data-light="on"] .index-project .index-slides .slide-card,
html[data-light="off"] .index-project .index-slides .slide-card,
html[data-light="on"] .index-project .index-slides .slide-card figure,
html[data-light="off"] .index-project .index-slides .slide-card figure { background: none; }
html[data-light="on"] .index-slides .slide-card img { filter: none; }
html[data-light="off"] .index-slides .slide-card img { filter: brightness(0.62) saturate(0.75); }
html[data-light="off"] .index-slides .slide-card:hover img { filter: none; }

/* Metadata is omitted on the index. */
.index-slides .slide-card .slide-meta { display: none; }

/* Overflow: a square "+N" tile at the row height, outlined so it reads in either
   light mode. */
.index-slides .slide-more {
  align-items: center;
  aspect-ratio: 1 / 1;
  background: none;
  border: 1px solid currentColor;
  display: flex;
  justify-content: center;
  opacity: 0.7;
}

.slide-more .more-count {
  font-size: var(--font-size-h5);
  font-weight: 500;
}

@media (max-width: 700px) {
  .index-head { column-gap: 18px; grid-template-columns: 1fr auto auto; }
  .index-slides .slide-card { height: clamp(104px, 22vw, 150px); }
}

/* Toolbar group styles (.bar-group / .bar-center / .hover-*) live in index.css,
   shared between the Works footer and the Viewer footer. */

/* Filter / Sort / Search panel styles moved to index.css (shared by Works,
   Index, Notes and Archive tools footers). */
