/* ============================================================
   Playground (/playground) — a sorted masonry grid of visual work.
   Reference: an edge-to-edge 3-up masonry of soft cards, title +
   date over the media, an optional "View prototype" bar.

   The grid sits in the site's 1200px column (1248 max with 24px
   gutters, like /ai-labs and every other page). It used to break out
   rail-to-rail; the user asked for the shared width (2026-10-23).

   Layout is progressive: CSS alone renders a plain N-column grid;
   playground.js upgrades it to a packed masonry (.is-masonry), a
   scroll-in reveal and a lightbox.

   Adding a piece — copy any <article class="pg-card"> in
   playground.html and swap the .pg-ph placeholder for the media:
     <img src="/images/opt/x.webp" alt="…" loading="lazy" decoding="async">
     <video data-src="/videos/opt/x.mp4" data-autoplay poster="…"
            preload="none" loop muted playsinline></video>
   Keep style="--r: W/H" on .pg-media at the media's aspect ratio
   (the masonry packs from it, so nothing jumps while media loads).
   data-tone="dark" on the card = white caption, for dark media.
   Scoped under .pg-* so nothing leaks to other pages.
   ============================================================ */
/* handwriting for the header's notes (same face as the homepage notes) */
@font-face { font-family: 'Caveat Note'; font-style: normal; font-weight: 400 700; font-display: swap;
  src: url('/assets/fonts/caveat/caveat-latin-wght-normal.woff2') format('woff2'); }

.pg-wrap {
  --pg-ink:    #1a1a1a;
  --pg-faint:  rgba(26, 26, 26, 0.4);
  --pg-line:   rgba(0, 0, 0, 0.12);
  --pg-card:   #f6f6f6;
  --pg-edge:   rgba(0, 0, 0, 0.06);
  --pg-accent: #de3b26;              /* the solid accent (accent.css) */
  --pg-radius: 0px;                  /* sharp, like the rest of the site */
  --pg-ease:   cubic-bezier(0.2, 0.6, 0.2, 1);
  --pg-glide:  cubic-bezier(0.25, 0.8, 0.25, 1);

  box-sizing: border-box;
  width: 100%;
  padding-bottom: 168px;
}
.pg-wrap *, .pg-wrap *::before, .pg-wrap *::after { box-sizing: border-box; }

/* ---- header — same treatment as /ai-labs, with the sketched "windows"
   art playground-windows.js draws behind it (on the cards' column; the
   script clips the canvas to it) ---- */
.pg-wrap { position: relative; }
.pg-fx {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 0;
  display: block;
  pointer-events: none;
}
.pg-head {
  position: relative;
  z-index: 1;
  max-width: 1248px;
  margin: 0 auto;
  /* the header is a row on the cards' grid: art in columns 1 and 3, words
     in 2. The bottom padding tracks the art's scale (it shrinks with the
     columns) so the ink floor line sits ~96px above the cards at every
     three-column width (2026-11-10: the user wanted more air there). */
  padding: 44px 24px min(133px, 12.25vw - 20px, 18.1vw - 84.3px);
  text-align: center;
}
.pg-field { position: relative; z-index: 1; }
.pg-title {
  margin: 0;
  font-size: 40px;
  line-height: 1.14;
  font-weight: 700;
  letter-spacing: -0.76px;
  color: var(--pg-ink);
}
.pg-intro {
  margin: 8px auto 0;
  font-size: 16px;
  line-height: 20px;
  color: var(--pg-faint);
  text-transform: lowercase;
}

/* ---- the field: the grid, in the site column ---- */
.pg-field {
  max-width: 1248px;                  /* 1200 content + 24px gutters — the site grid */
  margin: 64px auto 0;
  padding: 0 24px;
}

/* ---- the grid ---- */
.pg-grid {
  --pg-cols: 1;
  --pg-gap: 8px;
  display: grid;                      /* no-JS fallback: a plain grid */
  grid-template-columns: repeat(var(--pg-cols), minmax(0, 1fr));
  align-items: start;
  gap: var(--pg-gap);
  position: relative;
}
@media (min-width: 560px)  { .pg-grid { --pg-cols: 2; } }
@media (min-width: 860px)  { .pg-grid { --pg-cols: 3; --pg-gap: 12px; } }

/* masonry mode (playground.js): cards are absolutely placed with the
   independent `translate` property, so `transform` stays free for the
   reveal */
.pg-grid.is-masonry { display: block; }
.pg-grid.is-masonry .pg-card {
  position: absolute;
  top: 0;
  left: 0;
  width: var(--pg-colw, 33%);
  z-index: 1;
  /* --d: per-card stagger for the scroll-in reveal (set by the script) */
  transition:
    translate 0.6s var(--pg-glide),
    opacity 0.45s ease var(--d, 0s),
    transform 0.7s var(--pg-ease) var(--d, 0s);
}
.pg-grid.is-resizing .pg-card { transition: none !important; }

/* first reveal as cards scroll in */
.pg-grid.is-masonry .pg-card.is-pre {
  opacity: 0;
  transform: translateY(16px);
}
/* the card whose media is "lifted" into the open lightbox */
.pg-card.is-lifted .pg-media { visibility: hidden; }

/* with JS, hold the grid back until it has been packed (one frame) so the
   plain fallback grid never flashes; a failsafe reveals it regardless */
html.pg-js .pg-grid:not(.is-masonry) { opacity: 0; animation: pg-failsafe 0s linear 2.5s forwards; }
@keyframes pg-failsafe { to { opacity: 1; } }

/* ---- card ---- */
.pg-card {
  position: relative;
  margin: 0;
  background: var(--pg-card);
  border: 1px solid var(--pg-edge);
  border-radius: var(--pg-radius);
  overflow: hidden;
}
.pg-card:has(.pg-cta) { padding: 8px; }   /* framed: media inset, bar below */

.pg-media {
  position: relative;
  aspect-ratio: var(--r, 1);
  overflow: hidden;
  border-radius: calc(var(--pg-radius) * 0.6);
  background: #efefef;
  cursor: zoom-in;
}
.pg-media > img,
.pg-media > video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.6s var(--pg-ease);
}
@media (hover: hover) {
  .pg-card:hover .pg-media > img,
  .pg-card:hover .pg-media > video { transform: scale(1.015); }
}

/* the click target covers the media; captions/media sit under it */
.pg-hit {
  position: absolute;
  inset: 0;
  z-index: 2;
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: zoom-in;
}
.pg-hit:focus-visible { outline: 2px solid var(--pg-accent); outline-offset: -2px; }

/* caption: title bottom-left, date bottom-right, over the media */
/* Caption: the piece's name in a liquid-glass pill, bottom centre —
   the same recipe as the homepage ticker labels (hero-intro.css). Light
   glass by default; dark glass on dark media (data-tone="dark"). */
.pg-cap {
  position: absolute;
  left: 50%;
  bottom: 16px;
  z-index: 1;
  max-width: calc(100% - 32px);
  margin: 0;
  padding: 7px 15px;
  border-radius: 999px;
  transform: translateX(-50%);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.005em;
  color: #1a1a1a;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.62), rgba(255, 255, 255, 0.34));
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.6);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.85),
    inset 0 -1px 1px rgba(255, 255, 255, 0.2),
    0 8px 24px rgba(0, 0, 0, 0.14),
    0 1px 2px rgba(0, 0, 0, 0.08);
  pointer-events: none;
}
.pg-t { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pg-card[data-tone="dark"] .pg-media { background: #121212; }
.pg-card[data-tone="dark"] .pg-cap {
  color: #fff;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.05));
  border-color: rgba(255, 255, 255, 0.22);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.32),
    inset 0 -1px 1px rgba(255, 255, 255, 0.06),
    0 8px 24px rgba(0, 0, 0, 0.35);
}

/* "View prototype" bar */
.pg-cta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 44px;
  margin-top: 8px;
  border-radius: calc(var(--pg-radius) * 0.6);
  background: #ececec;
  font-size: 15px;
  line-height: 20px;
  font-weight: 500;
  color: var(--pg-ink);
  text-decoration: none;
  transition: background-color 0.18s ease;
}
.pg-cta-arrow {
  font-size: 13px;
  color: rgba(26, 26, 26, 0.45);
  transition: transform 0.25s var(--pg-ease), color 0.18s ease;
}
@media (hover: hover) {
  .pg-cta:hover { background: #e3e3e3; }
  .pg-cta:hover .pg-cta-arrow { transform: translate(2px, -2px); color: var(--pg-accent); }
}
.pg-cta:focus-visible { outline: 2px solid var(--pg-accent); outline-offset: 2px; }
.pg-cta[aria-disabled="true"] { cursor: default; }

/* ---- placeholder frames (until the real visuals land) ---- */
.pg-ph {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 24px 24px 48px;
  text-align: center;
  background-color: #efefef;
  background-image: radial-gradient(rgba(0, 0, 0, 0.09) 1px, transparent 1.2px);
  background-size: 14px 14px;
  background-position: center;
  color: rgba(26, 26, 26, 0.32);
}
.pg-ph-r {
  font-size: 34px;
  line-height: 1;
  font-weight: 300;
  letter-spacing: -0.5px;
  font-variant-numeric: tabular-nums;
}
.pg-ph-k {
  font-size: 11px;
  line-height: 14px;
  letter-spacing: 0.9px;
  text-transform: uppercase;
}
.pg-ph[data-ph="dark"] {
  background-color: #121212;
  background-image: radial-gradient(rgba(255, 255, 255, 0.1) 1px, transparent 1.2px);
  color: rgba(255, 255, 255, 0.34);
}
.pg-ph[data-ph="warm"] {
  background-color: #f7e6da;
  background-image: radial-gradient(rgba(176, 72, 40, 0.14) 1px, transparent 1.2px);
  color: rgba(140, 56, 30, 0.45);
}
.pg-ph[data-ph="accent"] {
  background-color: #f2876a;
  background-image:
    radial-gradient(rgba(255, 255, 255, 0.22) 1px, transparent 1.2px),
    linear-gradient(135deg, #f5c19e, #fa1616);
  background-size: 14px 14px, 100% 100%;
  color: rgba(255, 255, 255, 0.78);
}
.pg-ph[data-ph="cool"] {
  background-color: #e4e9ec;
  background-image: radial-gradient(rgba(30, 60, 80, 0.12) 1px, transparent 1.2px);
  color: rgba(30, 50, 64, 0.38);
}

/* ---- nav: Playground is the current page here. The page reuses the
   "About" nav variant, whose current-<p> pin (sticky-nav.css) would
   park it in About's slot — re-pin it to Playground's. ---- */
#main nav.framer-WLHpg .framer-1gxxlpg > div:has(p):not(:has(a)) { order: 3 !important; }

/* ============================================================
   Lightbox (built by playground.js, appended to <body>)
   ============================================================ */
html.pg-lock { overflow: hidden; }
.pg-lb {
  position: fixed;
  inset: 0;
  z-index: 1200;                       /* above the edge rails (999) */
  font-family: "Figtree", sans-serif;
}
.pg-lb[hidden] { display: none; }
.pg-lb-back {
  position: absolute;
  inset: 0;
  background: rgba(250, 250, 250, 0.9);
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
  backdrop-filter: blur(14px) saturate(1.2);
  opacity: 0;
  transition: opacity 0.32s ease;
}
.pg-lb.is-open .pg-lb-back { opacity: 1; }
.pg-lb-stage {
  position: absolute;
  margin: 0;
  overflow: hidden;
  border-radius: var(--pg-radius, 0);
  background: #efefef;
  box-shadow: 0 30px 80px -30px rgba(0, 0, 0, 0.35), 0 0 0 1px rgba(0, 0, 0, 0.05);
  transform-origin: 0 0;
  will-change: transform;
}
.pg-lb-stage.is-anim { transition: transform 0.46s cubic-bezier(0.2, 0.75, 0.2, 1), opacity 0.3s ease; }
.pg-lb-stage > img,
.pg-lb-stage > video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.pg-lb-stage .pg-ph { padding-bottom: 24px; }
.pg-lb-stage .pg-ph-r { font-size: clamp(34px, 6vw, 72px); }
.pg-lb-stage .pg-ph-k { font-size: 12px; }
.pg-lb-swap { animation: pg-lb-swap 0.32s var(--pg-ease, ease) both; }
@keyframes pg-lb-swap {
  from { opacity: 0; transform: translateX(calc(var(--dir, 1) * 18px)); }
}

.pg-lb-bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  height: 72px;
  padding: 0 28px;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.3s ease 0.08s, transform 0.3s ease 0.08s;
}
.pg-lb.is-open .pg-lb-bar { opacity: 1; transform: none; }
.pg-lb-info { min-width: 0; display: flex; align-items: baseline; gap: 12px; }
.pg-lb-t {
  font-size: 16px;
  line-height: 20px;
  font-weight: 600;
  color: #1a1a1a;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pg-lb-m {
  font-size: 14px;
  line-height: 20px;
  color: rgba(26, 26, 26, 0.45);
  white-space: nowrap;
}
.pg-lb-ctrls { flex: none; display: flex; align-items: center; gap: 8px; }
.pg-lb-n {
  margin-right: 6px;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: rgba(26, 26, 26, 0.45);
}
.pg-lb-cta {
  display: inline-flex;
  align-items: center;
  height: 36px;
  margin-right: 4px;
  padding: 0 14px;
  border: 1px solid rgba(0, 0, 0, 0.12);
  font-size: 14px;
  font-weight: 500;
  color: #1a1a1a;
  text-decoration: none;
  transition: border-color 0.18s ease;
}
.pg-lb-cta[hidden] { display: none; }
.pg-lb-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  margin: 0;
  padding: 0;
  border: 1px solid rgba(0, 0, 0, 0.12);
  background: #fff;
  color: #1a1a1a;
  cursor: pointer;
  transition: border-color 0.18s ease, background-color 0.18s ease;
}
.pg-lb-btn svg { width: 16px; height: 16px; display: block; }
@media (hover: hover) {
  .pg-lb-btn:hover, .pg-lb-cta:hover { border-color: rgba(0, 0, 0, 0.3); }
}
.pg-lb-btn:focus-visible, .pg-lb-cta:focus-visible { outline: 2px solid #de3b26; outline-offset: 2px; }

/* ---- responsive ---- */
@media (max-width: 809.98px) {
  .pg-wrap { padding-bottom: 120px; }
  .pg-head { padding: 136px 18px 128px; }
  .pg-title { font-size: 28px; }
  .pg-intro { font-size: 15px; }
  .pg-field { margin-top: 40px; padding: 0 18px; }
  .pg-cap { bottom: 12px; max-width: calc(100% - 24px); padding: 6px 12px; font-size: 12px; }
  .pg-lb-bar { height: auto; padding: 14px 16px calc(14px + env(safe-area-inset-bottom)); flex-wrap: wrap; gap: 10px; }
  .pg-lb-info { flex: 1 1 100%; }
  .pg-lb-ctrls { flex: 1 1 100%; }
  .pg-lb-n { margin-right: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .pg-grid.is-masonry .pg-card { transition: opacity 0.2s ease; }
  .pg-grid.is-masonry .pg-card.is-pre { transform: none; }
  .pg-media > img, .pg-media > video, .pg-cta-arrow { transition: none; }
  .pg-lb-stage.is-anim { transition: opacity 0.2s ease; }
  .pg-lb-swap { animation: none; }
}

/* With three card columns the words take the middle column's width, so the
   header lines up with the grid below. Under three, the art stacks above and
   below the words instead. */
@media (min-width: 860px) {
  .pg-intro { max-width: calc((100% - 24px) / 3); text-wrap: balance; }
}
@media (min-width: 810px) and (max-width: 859.98px) {
  .pg-head { padding-top: 136px; padding-bottom: 128px; }
}
