/* ==========================================================================
   Portfolio · 3D card scroller + grid view
   ========================================================================== */
:root {
  --card-w: 512px;          /* 4:3, same as the cover images */
  --card-h: 384px;
}
html, body { height: 100%; }
body { overflow: hidden; }

/* ---------- Scroll driver ---------- */
.scroller {
  position: fixed; inset: 0;
  overflow-y: scroll;
  overflow-x: hidden;
  scroll-snap-type: y mandatory;
  overscroll-behavior: contain;
  scrollbar-width: none;
}
.scroller::-webkit-scrollbar { display: none; }
.snap { height: var(--step); scroll-snap-align: start; scroll-snap-stop: always; }
.snap-tail { height: calc(100dvh - var(--step)); }

/* Everything visible lives in a sticky 100% viewport stage inside the scroller,
   so wheel / touch anywhere on the page drives the card scroll. */
.stage {
  position: sticky; top: 0;
  height: 100dvh; margin-bottom: -100dvh;
  width: 100%;
  overflow: hidden;
  z-index: 1;
}
.stage .lamp { z-index: 0; }

/* ---------- Left menu (category filter) ---------- */
.menu {
  position: absolute; left: 96px; top: 50%;
  transform: translateY(-50%);
  display: flex; flex-direction: column; gap: 24px;
  list-style: none; z-index: 4;
}
.menu .cat-btn {
  font-family: inherit;
  color: var(--fg); background: transparent; border: 0; cursor: pointer;
  padding: calc(12px + var(--cap-shift)) 24px calc(12px - var(--cap-shift)); border-radius: var(--radius-pill);
  position: relative; white-space: nowrap;
  transition: color .35s var(--ease), opacity .35s var(--ease);
}
@media (hover: hover) {   /* touch screens keep :hover after a tap, so hover fills are pointer-only */
.menu .cat-btn:hover { opacity: .7; }
}
.menu .cat-btn[aria-pressed="true"] { color: var(--bg); opacity: 1; }
.menu .cat-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.menu .pill {
  position: absolute; left: 0; top: 0; height: 40px;
  background: var(--fg); border-radius: var(--radius-pill); z-index: -1;
  transition: transform .5s var(--ease), width .5s var(--ease);
}

/* ---------- Project cards ---------- */
.cards { position: absolute; inset: 0; pointer-events: none; z-index: 2; perspective: 1400px; }
.card {
  position: absolute; left: 50%; top: 50%;
  width: var(--card-w); height: var(--card-h);
  margin: calc(var(--card-h) / -2) 0 0 calc(var(--card-w) / -2);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg);
  will-change: transform, opacity;
  pointer-events: none;
  text-decoration: none;
  box-shadow: var(--shadow-card);
}
.card.is-active { pointer-events: auto; cursor: pointer; }
.card:focus-visible { outline: 2px solid var(--accent); outline-offset: 8px; }
.card img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transform: scale(1.04);
  transition: transform 1.2s var(--ease);
}
.card.is-active:hover img { transform: scale(1.08); }
.card .veil {
  position: absolute; inset: 0; background: var(--bg);
  pointer-events: none;
}

/* ---------- Right label ---------- */
.label {
  position: absolute; top: 50%;
  left: calc(50% + var(--card-w) / 2 + 64px);
  transform: translateY(-50%);
  z-index: 4; pointer-events: none;
  min-width: 264px; height: 80px;
}
.label-item {
  position: absolute; left: 0; top: 0;
  transition: opacity .55s var(--ease), transform .7s var(--ease), filter .55s var(--ease);
}
/* Type: .client = t-meta, .name (post title) = t-h2 (classes set in portfolio.js) */
.label-item .client { margin-bottom: 16px; color: var(--muted); }
.label-item .name { max-width: 10em; }                 /* long Post titles wrap to a second line */
.label-item.out-up   { opacity: 0; transform: translateY(-24px); filter: blur(8px); }
.label-item.out-down { opacity: 0; transform: translateY(24px);  filter: blur(8px); }

/* ---------- Dot nav: .dot-nav component in site.css ---------- */
.empty {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%);
  color: var(--muted); display: none;                     /* type: t-meta */
}

/* ---------- Medium screens ---------- */
@media (max-width: 1200px) {
  :root { --card-w: 416px; --card-h: 312px; }
  .menu { left: 40px; }
  .label { left: calc(50% + var(--card-w) / 2 + 40px); min-width: 200px; }
  .label-item .name { font-size: var(--fs-h3); line-height: 32px; }
}
@media (max-width: 1024px) {
  :root { --card-w: 352px; --card-h: 264px; }
  .label-item .name { font-size: var(--fs-h3); line-height: 32px; white-space: normal; }
  .label { min-width: 0; width: calc(50% - var(--card-w) / 2 - 64px); }
}

/* ---------- Mobile ---------- */
@media (max-width: 768px) {
  :root { --card-w: min(520px, calc(100vw - 64px)); --card-h: calc(var(--card-w) * .75); }

  .menu {
    top: 72px; left: 0; right: 0; transform: none;
    flex-direction: row; gap: 4px;
    padding: 0 16px;
    overflow-x: auto; scrollbar-width: none;
    -webkit-mask-image: linear-gradient(90deg, #1D1B1A 85%, transparent);
            mask-image: linear-gradient(90deg, #1D1B1A 85%, transparent);
  }
  .menu::-webkit-scrollbar { display: none; }
  .menu .cat-btn { padding-left: 16px; padding-right: 16px; }
  .menu .pill { height: 40px; }

  .card { top: 47%; }
  .cards { perspective: 904px; }
  .label {
    left: 16px; right: 16px; width: auto; min-width: 0;
    top: auto; bottom: calc(24px + env(safe-area-inset-bottom));
    transform: none; height: 72px; text-align: center;
  }
  .label-item { left: 0; right: 0; }
  .label-item .client { font-size: var(--fs-sm); line-height: 16px; margin-bottom: 8px; }   /* caption size on mobile */
  .label-item .name { max-width: none; }
}

/* ---------- View toggle (grid / vertical) ---------- */
.menu .view-li { position: absolute; left: 0; bottom: 100%; margin-bottom: 32px; }
/* The button itself is the shared .icon-btn component (site.css); this only adds the icon swap */
.view-toggle { position: relative; }
.view-toggle svg {
  position: absolute;
  transition: opacity .35s var(--ease), transform .5s var(--ease);
}
.view-toggle .ico-vertical { opacity: 0; transform: rotate(-90deg) scale(.6); }
.is-grid .view-toggle .ico-grid { opacity: 0; transform: rotate(90deg) scale(.6); }
.is-grid .view-toggle .ico-vertical { opacity: 1; transform: none; }

/* ---------- Grid view ---------- */
.cards, .label, .dots { transition: opacity .5s var(--ease), transform .7s var(--ease), visibility 0s linear 0s; }
.is-grid .cards { opacity: 0; transform: scale(.9); visibility: hidden; transition: opacity .45s var(--ease), transform .6s var(--ease), visibility 0s linear .6s; }
.is-grid .label, .is-grid .dots { opacity: 0; visibility: hidden; transition: opacity .3s var(--ease), visibility 0s linear .3s; }
.is-grid .card.is-active { pointer-events: none; }
.is-grid .snaps { display: none; }
.is-grid .scroller { scroll-snap-type: none; }

.grid {
  position: absolute; z-index: 3;
  top: 0; bottom: 0; left: 336px; right: 72px;
  padding: 120px 0 64px;
  overflow-y: auto; overscroll-behavior: contain;
  scrollbar-width: none;
  opacity: 0; visibility: hidden;
  transition: opacity .4s var(--ease), visibility 0s linear .4s;
  -webkit-mask-image: linear-gradient(180deg, transparent 64px, #000 104px, #000 calc(100% - 48px), transparent);
          mask-image: linear-gradient(180deg, transparent 64px, #000 104px, #000 calc(100% - 48px), transparent);
}
.grid::-webkit-scrollbar { display: none; }
.is-grid .grid { opacity: 1; visibility: visible; transition: opacity .4s var(--ease) .1s, visibility 0s; }
.grid-inner {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 40px 32px;
  max-width: 1200px;
}
.tile {
  display: block; color: var(--fg); text-decoration: none;
  opacity: 0; transform: translateY(32px) scale(.97);
  transition: opacity .6s var(--ease), transform .8s var(--ease);
  transition-delay: calc(var(--i, 0) * 55ms);
}
.tile.in { opacity: 1; transform: none; }
.tile-img {
  aspect-ratio: 4 / 3; border-radius: var(--radius-md); overflow: hidden;
  background: rgba(255,255,255,.04);
  box-shadow: var(--shadow-tile);
}
.tile-img img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform 1s var(--ease), filter .6s var(--ease);
}
.tile:hover .tile-img img { transform: scale(1.05); }
.grid-inner:hover .tile:not(:hover) .tile-img img { filter: brightness(.6) saturate(.8); }
.tile-meta { margin-top: 16px; display: flex; flex-direction: column; gap: 4px; }
/* Type: .client = t-caption, .name (post title) = t-meta (classes set in portfolio.js) */
.tile-meta .client { color: var(--muted); }
.tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 8px; border-radius: var(--radius-md); }

@media (max-width: 1200px) { .grid { left: 256px; right: 40px; } }
@media (max-width: 1024px) { .grid { left: 240px; right: 24px; } .grid-inner { grid-template-columns: repeat(auto-fill, minmax(224px, 1fr)); } }
@media (max-width: 768px) {
  .menu { align-items: center; }
  .menu .view-li { position: static; margin: 0 8px 0 0; flex: none; }
  .grid {
    left: 0; right: 0; padding: 136px 16px 40px;
    -webkit-mask-image: linear-gradient(180deg, transparent 112px, #000 136px);
            mask-image: linear-gradient(180deg, transparent 112px, #000 136px);
  }
  .grid-inner { grid-template-columns: 1fr; gap: 32px; }
  .tile-meta { margin-top: 12px; }
}

/* ---------- Entrance ----------
   Lamp clicks on, menu rises in, the focused card pops, then the label and dots follow.
   Uses the individual translate / scale properties so it never fights the
   JS-driven transforms on the cards, pill and label. Header is left static. */
.menu > li:not(.view-li), .menu .pill { opacity: 0; }
.is-ready .menu > li:not(.view-li) { opacity: 1; animation: riseProp 1s var(--ease) backwards; animation-delay: calc(.3s + var(--r) * 120ms); }
.is-ready .menu .pill { opacity: 1; animation: riseProp 1s var(--ease) .42s backwards; }

.view-li { opacity: 0; }
.is-ready .view-li { opacity: 1; animation: popProp .8s var(--ease) .3s backwards; }

.card.enter { animation: popProp .8s var(--ease) backwards; animation-delay: var(--d, .85s); }
body:not(.is-ready) .card.enter { visibility: hidden; }

.label { opacity: 0; }
.is-ready .label { opacity: 1; animation: riseProp .9s var(--ease) 1.1s backwards; }
.is-ready.is-grid .label { opacity: 0; }

.dots.intro button { opacity: 0; }
.is-ready .dots button { opacity: 1; }
.is-ready .dots.intro button { animation: popProp .6s var(--ease) backwards; animation-delay: calc(1.25s + var(--k, 0) * 50ms); }

/* No footer on this page (removed from templates/page-portfolio.html) */
@media (max-width: 768px) {
  .label { bottom: calc(56px + env(safe-area-inset-bottom)); }
}

/* Project data source (WordPress Query Loop / prototype list): read by JS, never shown */
.project-data { display: none !important; }
