/* =========================================================
   Pixalot Labs — Projects v2 (category browse + selection grid)
   Reuses --plv2-* tokens from home-v2.css where possible.
   ========================================================= */

:root {
  --plv2-bg: #0b0b0f;
  --plv2-card: #16161d;
  --plv2-text: #f5f5f7;
  --plv2-text-muted: #b7b7c3;
  /* Brand palette, sampled from /front/images/logo.png (grey #7a7a7a, orange #ee7f0b) */
  --plv2-3d: #a3a3a8;
  --plv2-2d: #ee7f0b;
  --plv2-anim: #e8e8ea;
}

.pv2-intro {
  padding: clamp(28px, 6vw, 64px) 0 clamp(16px, 3vw, 28px);
  text-align: center;
}

.pv2-eyebrow {
  display: inline-block;
  font-size: clamp(12px, .65vw, 14px);
  letter-spacing: .28em;
  text-transform: uppercase;
  color: var(--plv2-2d);
  font-weight: 700;
  margin-bottom: 14px;
}

.pv2-heading {
  font-size: clamp(30px, 2.6vw, 52px);
  font-weight: 800;
  color: var(--plv2-text);
  margin: 0 0 14px;
  letter-spacing: -0.01em;
}

.pv2-sub {
  color: var(--plv2-text-muted);
  font-size: clamp(15px, .85vw, 17px);
  max-width: 60ch;
  margin: 0 auto;
  line-height: 1.6;
}

/* ---------- FILTER BAR ---------- */
.pv2-filter-bar {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  padding: clamp(20px, 3vw, 36px) 6vw clamp(28px, 4vw, 48px);
}

.pv2-filter-btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 11px 22px;
  border-radius: 100px;
  border: 1.5px solid rgba(245,245,247,.18);
  background: rgba(245,245,247,.04);
  color: var(--plv2-text-muted);
  font-size: clamp(12px, .68vw, 14px);
  font-weight: 700;
  letter-spacing: .03em;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color .2s ease, color .2s ease, background .2s ease, transform .2s ease;
}

.pv2-filter-btn::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
  opacity: .8;
}

.pv2-filter-btn[data-filter="all"] { color: var(--plv2-text-muted); }
.pv2-filter-btn[data-filter="3d"] { color: var(--plv2-3d); }
.pv2-filter-btn[data-filter="2d"] { color: var(--plv2-2d); }
.pv2-filter-btn[data-filter="anim"] { color: var(--plv2-anim); }

.pv2-filter-btn:hover {
  transform: translateY(-2px);
  border-color: currentColor;
}

.pv2-filter-btn.is-active {
  background: currentColor;
}

.pv2-filter-btn.is-active[data-filter="all"] { color: #0b0b0f; background: var(--plv2-text); }
.pv2-filter-btn.is-active[data-filter="3d"] { color: #fff; background: var(--plv2-3d); border-color: var(--plv2-3d); }
.pv2-filter-btn.is-active[data-filter="2d"] { color: #fff; background: var(--plv2-2d); border-color: var(--plv2-2d); }
.pv2-filter-btn.is-active[data-filter="anim"] { color: #101012; background: var(--plv2-anim); border-color: var(--plv2-anim); }

/* ---------- PROJECT GRID ----------
   Bento layout: a feature tile (2x2), a couple of wide tiles (2x1) for
   thumbnails with a naturally wide/spread composition, one tall tile
   (1x2) for a naturally vertical portrait, the rest uniform 1x1 —
   grid-auto-rows + dense flow (not per-card aspect-ratio) so row-spanning
   tiles actually have a concrete row height to span, same pattern as the
   homepage's Featured Projects .proj-grid. */
.pv2-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: clamp(220px, 20vw, 320px);
  grid-auto-flow: dense;
  gap: 20px;
  max-width: 1480px;
  margin: 0 auto;
  padding: 0 6vw clamp(50px, 6vw, 90px);
}

.pv2-card {
  position: relative;
  display: block;
  border-radius: 16px;
  overflow: hidden;
  text-decoration: none;
  cursor: pointer;
  isolation: isolate;
  box-shadow: 0 16px 36px -18px rgba(0,0,0,.6);
  transition: transform .3s ease, opacity .25s ease;
}

.pv2-card-feature {
  grid-column: span 2;
  grid-row: span 2;
}

.pv2-card-tall {
  grid-row: span 2;
}

/* object-fit:contain on these two shows the full source thumbnail edge-to-edge
   (see rule below), which exposes a few px of the icon art's own rounded-corner
   background bleeding past the card's 16px clip. Rounding the tile itself well
   past that bleed (instead of touching the image files) hides it regardless of
   any given source image's own corner treatment. */
.pv2-card-feature,
.pv2-card-tall {
  border-radius: 28px;
}

/* Every source thumbnail here is a square (near-1:1) app-icon-style crop,
   and the feature/tall tiles themselves are also near-square at every
   breakpoint now (no more wide 2:1 shape) — so contain's tiny leftover
   sliver (a couple % of the box) was showing as a visible dark seam
   wherever the source art was bright near its own edge (Returnal's sky,
   Free Fire's logo glow), even though the mismatch is small. Cover trims
   only that same couple of percent off two edges instead of leaving it
   as a visible gap — negligible here, unlike the old wide-tile crop. */
.pv2-card-feature .pv2-card-img,
.pv2-card-tall .pv2-card-img {
  object-fit: cover;
}

.pv2-card-feature .pv2-card-title {
  font-size: clamp(18px, 1.4vw, 24px);
}

.pv2-card.is-filtered-out {
  display: none;
}

.pv2-card:hover {
  transform: translateY(-4px);
}

.pv2-card.is-selected {
  outline: 2px solid var(--plv2-text);
  outline-offset: 3px;
}

.pv2-card-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .5s cubic-bezier(.19,1,.22,1);
}

.pv2-card:hover .pv2-card-img {
  transform: scale(1.08);
}

.pv2-card-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(11,11,15,.05) 0%, rgba(11,11,15,.25) 55%, rgba(11,11,15,.92) 100%);
}

.pv2-card-body {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 18px;
  z-index: 2;
}

.pv2-card-tags {
  display: flex;
  gap: 6px;
  margin-bottom: 8px;
}

.pv2-card-tag {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: 100px;
  color: #fff;
}

.pv2-card-tag.tag-3d { background: var(--plv2-3d); color: #1a1a1a; }
.pv2-card-tag.tag-2d { background: var(--plv2-2d); }
.pv2-card-tag.tag-anim { background: var(--plv2-anim); color: #101012; }

.pv2-card-title {
  font-size: clamp(14px, .78vw, 16px);
  font-weight: 800;
  color: var(--plv2-text);
  margin: 0;
}

.pv2-card-cta {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: rgba(11,11,15,.5);
  border: 1px solid rgba(245,245,247,.3);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--plv2-text);
  font-size: 13px;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity .25s ease, transform .25s ease;
}

.pv2-card:hover .pv2-card-cta {
  opacity: 1;
  transform: translateY(0);
}

/* At the full 4-column desktop width, dense auto-flow packs each feature
   (2x2) into the very next open gap it finds — which, depending on DOM
   order, can stack two or three feature tiles straight down the same
   columns with only the grid gap between them (exactly the "big tiles
   continue" look). Pinning explicit coordinates for all 12 cards guarantees
   the intended diagonal/pinwheel spread instead of leaving it to chance.
   DOM order above must stay: Returnal, GSN, Bricks Royale, Dragon City,
   Little Legends, City X, World Chef, Angry Birds, League of Legends,
   Free Fire, Farm Ville 2, Joyinet. */
@media (min-width: 1201px) {
  .pv2-grid { grid-auto-flow: row; }
  .pv2-card:nth-child(1)  { grid-column: 1 / 3; grid-row: 1 / 3; }  /* Returnal */
  .pv2-card:nth-child(2)  { grid-column: 3;      grid-row: 1; }      /* GSN */
  .pv2-card:nth-child(3)  { grid-column: 4;      grid-row: 1; }      /* Bricks Royale */
  .pv2-card:nth-child(4)  { grid-column: 3;      grid-row: 2; }      /* Dragon City */
  .pv2-card:nth-child(5)  { grid-column: 4;      grid-row: 2; }      /* Little Legends */
  .pv2-card:nth-child(6)  { grid-column: 1;      grid-row: 3; }      /* City X */
  .pv2-card:nth-child(7)  { grid-column: 2;      grid-row: 3; }      /* World Chef */
  .pv2-card:nth-child(8)  { grid-column: 1;      grid-row: 4; }      /* Angry Birds */
  .pv2-card:nth-child(9)  { grid-column: 2;      grid-row: 4; }      /* League of Legends */
  .pv2-card:nth-child(10) { grid-column: 3 / 5;  grid-row: 3 / 5; }  /* Free Fire */
  .pv2-card:nth-child(11) { grid-column: 1 / 3;  grid-row: 5 / 7; }  /* Farm Ville 2 */
  .pv2-card:nth-child(12) { grid-column: 3 / 5;  grid-row: 5 / 7; }  /* Joyinet */
}

/* Same reasoning as the 4-column block above, worked out for 3 columns —
   dense auto-flow stacked all 4 feature tiles straight down the same
   column at this width. Explicit coordinates give a clean alternating
   pinwheel instead (each feature overlaps its neighbor by only one
   column, same look as the desktop diagonal spread). */
@media (min-width: 821px) and (max-width: 1200px) {
  .pv2-grid { grid-template-columns: repeat(3, 1fr); grid-auto-flow: row; }
  .pv2-card:nth-child(1)  { grid-column: 1 / 3; grid-row: 1 / 3; }  /* Returnal */
  .pv2-card:nth-child(2)  { grid-column: 3;      grid-row: 1; }      /* GSN */
  .pv2-card:nth-child(3)  { grid-column: 3;      grid-row: 2; }      /* Bricks Royale */
  .pv2-card:nth-child(4)  { grid-column: 1;      grid-row: 3; }      /* Dragon City */
  .pv2-card:nth-child(5)  { grid-column: 1;      grid-row: 4; }      /* Little Legends */
  .pv2-card:nth-child(6)  { grid-column: 3;      grid-row: 5; }      /* City X */
  .pv2-card:nth-child(7)  { grid-column: 3;      grid-row: 6; }      /* World Chef */
  .pv2-card:nth-child(8)  { grid-column: 1;      grid-row: 7; }      /* Angry Birds */
  .pv2-card:nth-child(9)  { grid-column: 1;      grid-row: 8; }      /* League of Legends */
  .pv2-card:nth-child(10) { grid-column: 2 / 4;  grid-row: 3 / 5; }  /* Free Fire */
  .pv2-card:nth-child(11) { grid-column: 1 / 3;  grid-row: 5 / 7; }  /* Farm Ville 2 */
  .pv2-card:nth-child(12) { grid-column: 2 / 4;  grid-row: 7 / 9; }  /* Joyinet */
}

@media (max-width: 1200px) {
  .pv2-grid { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 820px) {
  /* A 2x2 feature + 2x1 wides don't leave a clean pack at 2 columns —
     drop every span so it's a uniform grid instead of ragged gaps. */
  .pv2-grid { grid-template-columns: repeat(2, 1fr); grid-auto-rows: clamp(170px, 40vw, 220px); gap: 14px; }
  .pv2-card-feature,
  .pv2-card-tall {
    grid-column: span 1;
    grid-row: span 1;
  }
}

@media (max-width: 480px) {
  .pv2-filter-btn { padding: 9px 16px; }
}

/* Set by front/js/cms-projects.js when CMS project count/titles no longer match the
   default 12-item bento layout above (an admin added/removed a project). The nth-child
   pins assume exactly that DOM order, so fall back to a plain auto-flow dense grid
   instead of pinning the wrong cards into the feature/tall slots. */
.pv2-grid.pv2-dynamic {
  grid-auto-flow: dense;
}

.pv2-grid.pv2-dynamic .pv2-card {
  grid-column: auto !important;
  grid-row: auto !important;
}

.pv2-grid.pv2-dynamic .pv2-card-feature {
  grid-column: span 2 !important;
  grid-row: span 2 !important;
}

/* Visually retire the legacy carousel selector strip — the grid above replaces it,
   but we keep its markup + JS wiring intact since the gallery/lightbox depend on it. */
.pl-projects-top-carousel {
  display: none;
}

/* Footer used a global flat #221f1f that clashes with this page's own
   background gradient (inherited from body, same as the homepage) */
.footer_section{background:transparent!important}

/* ---------- PER-PROJECT GALLERY: masonry columns ----------
   Was a fixed-height bento grid (grid-auto-rows:160px + object-fit:cover),
   which forced every image — including tall character-portrait concept
   art — to crop to that row height, cutting off heads/faces. CSS multi-
   column masonry instead sizes each tile by width only and lets height
   follow the image's own aspect ratio, so nothing gets cropped regardless
   of whether the source art is a wide screenshot or a tall portrait sheet.
   Corner radius, hover scale and the lightbox (simple-lightbox, unchanged)
   still come from the existing .gallerys ul li img rules in
   all-B8akwwDw.css. */
/* Was columns:4 with no max-width — stretched edge-to-edge on wide screens,
   and with an auto-height container browsers fill columns sequentially
   rather than truly balancing across all 4, so a project with only 5-9
   images packed into the first couple of columns and left the rest of a
   1900px-wide screen empty. Capping max-width keeps the block from
   over-stretching, and dropping to 3 columns (verified against a 5-image
   project and a 28-image one) reliably fills every column instead of
   leaving a trailing one empty — 4 only ever looked right when a project
   happened to have a item count that balanced evenly across it. */
.gallerys ul {
  display: block;
  columns: 3;
  column-gap: 10px;
  max-width: 1480px;
  margin: 0 auto;
}

.gallerys ul li {
  width: 100%;
  max-width: none;
  height: auto;
  break-inside: avoid;
  margin-bottom: 10px;
}

.gallerys ul li a {
  display: block;
  width: 100%;
}

.gallerys ul li img {
  width: 100%;
  height: auto;
  object-fit: contain;
  display: block;
}

@media (max-width: 991px) {
  .gallerys ul { columns: 3; }
}

@media (max-width: 640px) {
  .gallerys ul {
    columns: 2;
    column-gap: 6px;
  }
  .gallerys ul li {
    margin-bottom: 6px;
  }
}
