/* ═══════════════════════════════════════════════════════════════════════
   NeeTee Studio — Portfolio · B · Stage (portfolio-stage.js)

   One project per stage. Every stage reserves its own height and its media
   box is sized from the media's real aspect ratio, so nothing reflows while
   scrolling; scale, lift and tilt are transforms only (set by the script).
   Reduced motion: a static stack at full strength — no transforms at all.
   Uses the page's tokens (--ink, --green, --font-head …) with fallbacks,
   so the Admin preview renders it the same way.
   ═══════════════════════════════════════════════════════════════════════ */

.ps {
  --ps-ink: var(--ink, #1a1614); --ps-mid: var(--mid, #6b6560); --ps-cream: var(--cream, #F6F3E8);
  --ps-green: var(--green, #7D946D); --ps-green-dk: var(--green-dk, #5e7052); --ps-burgundy: var(--burgundy, #4A1E1E);
  --ps-border: var(--border, rgba(26,22,20,.10));
  --ps-head: var(--font-head, 'Syne', system-ui, sans-serif); --ps-body: var(--font-body, 'Inter', system-ui, sans-serif);
  --ps-he: var(--font-he, 'Heebo', system-ui, sans-serif);
  --ps-ease: cubic-bezier(.23, 1, .32, 1);
  position: relative;
  min-height: 40svh;
}
.ps[data-state="ready"], .ps[data-state="empty"] { min-height: 0; }

.ps-list { display: flex; flex-direction: column; }

/* ── A stage ──────────────────────────────────────────────────────────── */
.ps-stage {
  position: relative; display: grid; gap: 1.4rem;
  padding: 2.5rem 0;
}
.ps-stage + .ps-stage { border-top: 1px solid transparent; }
.ps-frame {
  display: grid; justify-items: center; align-items: center;
  transform-origin: center center; will-change: transform;
}
.ps[data-motion="reduced"] .ps-frame { will-change: auto; }

/* The media box: width follows the true aspect under a height cap. --ar is
   width / height, set per item by the script; --cap is the tallest the
   lead may be. No crop, no letterbox, no reflow. */
.ps-media {
  --cap: 72svh;
  position: relative; display: block; overflow: hidden;
  width: min(100%, calc(var(--cap) * var(--ar, .8)));
  aspect-ratio: var(--ar, .8);
  border-radius: 6px;
  background: rgba(26,22,20,.06);
}
.ps-stage[data-weight="flagship"] .ps-media { --cap: 80svh; }
.ps-stage[data-weight="quiet"]    .ps-media { --cap: 60svh; }

.ps-img {
  display: block; width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transition: opacity 360ms var(--ps-ease);
}
.ps-img[data-loaded] { opacity: 1; }

/* A still that leads: the whole image is the button (opens it larger). */
.ps-still { padding: 0; border: 0; cursor: zoom-in; }
.ps-still:focus-visible, .ps-thumb:focus-visible { outline: 2px solid var(--ps-green-dk); outline-offset: 3px; }

/* ── Film ─────────────────────────────────────────────────────────────── */
/* Layers, bottom to top: video · neutral surface · poster · shade, Play,
   controls. The cover (surface + poster) stays above the video until a frame
   is really on screen (data-frame, set by the script), so loading never shows
   a black box: poster → film, or neutral surface → first frame → the same
   frame moving. No mark on the surface: nothing that reads as a Play button. */
.ps-film { color: #F6F3E8; }
.ps-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Safari's own start-playback glyph never shows over a B · Stage film. */
.ps-video::-webkit-media-controls,
.ps-video::-webkit-media-controls-start-playback-button,
.ps-video::-webkit-media-controls-overlay-play-button,
.ps-video::-webkit-media-controls-panel { display: none !important; -webkit-appearance: none; }
.ps-surface {
  position: absolute; inset: 0; pointer-events: none;
  /* The Stage's media placeholder tone (as the image frames), opaque. */
  background: linear-gradient(180deg, #ECE9DF 0%, #E5E1D5 100%);
  transition: opacity 200ms ease-out;
}
.ps-poster { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 200ms ease-out; }
/* The poster covers once it is decoded (data-poster-ready, set by the
   script) — never a half-loaded image. */
.ps-film[data-poster-ready] .ps-poster { opacity: 1; }
/* A prepared film (loaded early, first frame decoded) whose poster isn't
   ready — or that has none — shows that real frame as soon as it has it,
   before its stage is active, so the visitor never meets an empty surface.
   A ready poster stays until the film is active (data-live) AND its frame is
   on screen, then gives way to that frame: poster → poster over the ready
   frame → film. Never poster → empty → film. */
.ps-film[data-frame]:not([data-poster-ready]) .ps-surface,
.ps-film[data-frame][data-live] .ps-surface, .ps-film[data-frame][data-live] .ps-poster { opacity: 0; }
.ps-shade {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to top, rgba(10,8,7,.55), transparent 42%);
  opacity: 0; transition: opacity 220ms var(--ps-ease);
}
.ps-film[data-state="paused"] .ps-shade, .ps-film[data-state="blocked"] .ps-shade, .ps-film[data-ctl] .ps-shade, .ps-film:has(.ps-ctl-btn:focus-visible) .ps-shade { opacity: 1; }
.ps-play {
  position: absolute; inset: 0; margin: auto; z-index: 3;
  width: 64px; height: 64px; border-radius: 50%; border: 0; cursor: pointer;
  display: none; place-items: center; color: #F6F3E8;
  background: rgba(246,243,232,.16); box-shadow: 0 0 0 1px rgba(246,243,232,.34) inset;
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  transition: transform 160ms var(--ps-ease), background-color 160ms ease-out;
}
.ps-play svg { width: 20px; margin-inline-start: 3px; }
/* Central Play: only when manual playback is genuinely needed — the visitor
   paused, reduced motion holds the film, or it can't start without a real
   gesture. Never while loading. */
.ps-film[data-state="paused"] .ps-play, .ps-film[data-state="blocked"] .ps-play { display: grid; }
/* Over the light neutral surface (no ready poster, no frame yet) it stays legible. */
.ps-film:not([data-frame]):not([data-poster-ready]) .ps-play { color: var(--ps-ink); background: rgba(255,253,248,.72); box-shadow: 0 0 0 1px rgba(26,22,20,.14) inset; }
.ps-film:not([data-frame]):not([data-poster-ready]) .ps-shade { opacity: 0; }
.ps-play:hover { background: rgba(246,243,232,.26); }
.ps-play:active { transform: scale(.96); }
/* Pause / Sound: hidden at rest. Shown with the pointer over the film (mouse
   only — see the hover media query), with keyboard focus on a control, or on
   touch for a moment after a tap (data-ctl, set by the script). Hidden by
   opacity, never display, so the controls stay in the tab order; the film
   itself never moves or resizes. */
.ps-ctl {
  position: absolute; inset-inline-end: .7rem; bottom: .8rem; z-index: 4; display: flex; gap: .4rem;
  opacity: 0; transform: translateY(6px); pointer-events: none;
  transition: opacity 200ms var(--ps-ease), transform 200ms var(--ps-ease);
}
.ps-film[data-ctl] .ps-ctl, .ps-film:has(.ps-ctl-btn:focus-visible) .ps-ctl { opacity: 1; transform: none; pointer-events: auto; }
@supports not selector(:has(*)) {
  .ps-film:focus-within .ps-ctl { opacity: 1; transform: none; pointer-events: auto; }
  .ps-film:focus-within .ps-shade { opacity: 1; }
}
.ps-ctl-btn {
  width: 34px; height: 34px; border-radius: 50%; border: 0; cursor: pointer; padding: 0;
  display: grid; place-items: center; color: #F6F3E8;
  background: rgba(26,22,20,.42); box-shadow: 0 0 0 1px rgba(246,243,232,.24) inset;
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  transition: transform 150ms var(--ps-ease), background-color 150ms ease-out;
}
.ps-ctl-btn svg { width: 15px; height: 15px; }
.ps-ctl-btn:hover { background: rgba(26,22,20,.6); }
.ps-ctl-btn:active { transform: scale(.95); }
.ps-play:focus-visible, .ps-ctl-btn:focus-visible { outline: 2px solid #F6F3E8; outline-offset: 2px; }
.ps-tick { position: absolute; inset-inline: 0; bottom: 0; height: 2px; z-index: 3; background: rgba(246,243,232,.14); opacity: 0; transition: opacity 200ms ease-out; }
.ps-film[data-state="playing"] .ps-tick { opacity: 1; }
.ps-tick i { display: block; height: 100%; background: var(--ps-green); transform: scaleX(0); transform-origin: left center; }
[dir="rtl"] .ps-tick i { transform-origin: right center; }

/* ── Editorial ────────────────────────────────────────────────────────── */
.ps-ed { display: grid; gap: .9rem; align-content: center; min-width: 0; will-change: opacity; }
.ps[data-motion="reduced"] .ps-ed { will-change: auto; }
.ps-ed-head { display: grid; gap: .55rem; justify-items: start; }
.ps-kicker {
  margin: 0; font: 600 .66rem/1.6 var(--ps-body); letter-spacing: .17em; text-transform: uppercase; color: var(--ps-mid);
}
[dir="rtl"] .ps-kicker { letter-spacing: .04em; }
.ps-who { color: var(--ps-ink); }
.ps-sep { opacity: .45; margin: 0 .6em; }
.ps-title {
  margin: 0; font: 800 clamp(1.75rem, 3.4vw, 2.7rem)/1 var(--ps-head); letter-spacing: -.035em; color: var(--ps-ink);
  text-wrap: balance;
}
[dir="rtl"] .ps-title { font-family: var(--ps-he); letter-spacing: -.012em; line-height: 1.08; }
[dir="rtl"] .ps-title[dir="ltr"] { font-family: var(--ps-head); letter-spacing: -.035em; }
.ps-disclose {
  margin: 0; font: 600 .62rem/1.5 var(--ps-body); letter-spacing: .1em; color: var(--ps-burgundy);
}
[dir="rtl"] .ps-disclose { letter-spacing: 0; }
.ps-desc { margin: 0; font-size: .95rem; line-height: 1.72; color: var(--ps-mid); max-width: 46ch; white-space: pre-line; }
[dir="rtl"] .ps-desc { line-height: 1.85; }

/* Supporting images: a quiet row in project order. Nothing when empty. */
.ps-strip {
  list-style: none; margin: .4rem 0 0; padding: 0 0 .5rem;
  display: flex; gap: .55rem; overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x proximity; scrollbar-width: thin; max-width: 100%;
}
.ps-strip::-webkit-scrollbar { height: 3px; }
.ps-strip::-webkit-scrollbar-thumb { background: var(--ps-border); border-radius: 99px; }
.ps-strip li { flex: none; scroll-snap-align: start; }
.ps-thumb {
  display: block; padding: 0; border: 0; cursor: zoom-in; overflow: hidden; border-radius: 3px;
  height: clamp(96px, 13vw, 132px); aspect-ratio: var(--ar, .8); background: rgba(26,22,20,.06);
}
@media (hover: hover) and (pointer: fine) {
  .ps-thumb .ps-img { transition: opacity 360ms var(--ps-ease), transform 180ms var(--ps-ease); }
  .ps-thumb:hover .ps-img { transform: scale(1.035); }
  /* The film's controls follow the pointer (touch has no hover: a tap shows them). */
  .ps-film:hover .ps-ctl { opacity: 1; transform: none; pointer-events: auto; }
  .ps-film:hover .ps-shade { opacity: 1; }
}

/* Admin preview only: the draft state of a project. */
.ps-badge {
  position: absolute; top: 1.2rem; inset-inline-start: 0; z-index: 5;
  font: 600 .62rem/1 var(--ps-body); letter-spacing: .08em; text-transform: uppercase;
  padding: .45rem .6rem; border-radius: 999px; background: var(--ps-ink); color: var(--ps-cream);
}

/* ── Empty state: a composed pause, not an error ──────────────────────── */
.ps-empty {
  display: grid; gap: 2rem; align-items: center; padding: 3rem 0 1rem;
}
.ps-empty-art { position: relative; height: 180px; max-width: 320px; width: 100%; }
.ps-empty-art span {
  position: absolute; border: 1px solid rgba(26,22,20,.16); border-radius: 6px; background: rgba(255,253,248,.35);
}
.ps-empty-art span:nth-child(1) { inset: 18px 38% 0 0; transform: rotate(-3deg); }
.ps-empty-art span:nth-child(2) { inset: 0 18% 26px 30%; }
.ps-empty-art span:nth-child(3) { inset: 44px 0 8px 62%; transform: rotate(4deg); border-style: dashed; }
.ps-empty-t { margin: 0 0 .6rem; font: 800 clamp(1.5rem, 3vw, 2.1rem)/1.08 var(--ps-head); letter-spacing: -.03em; color: var(--ps-ink); }
[dir="rtl"] .ps-empty-t { font-family: var(--ps-he); letter-spacing: -.01em; }
.ps-empty-n { margin: 0; color: var(--ps-mid); max-width: 44ch; line-height: 1.7; }

/* ── Viewer ───────────────────────────────────────────────────────────── */
html.ps-lock { overflow: hidden; }
.ps-viewer {
  width: 100vw; height: 100dvh; max-width: none; max-height: none; margin: 0; padding: 0; border: 0;
  background: rgba(10,8,7,.96); color: #F6F3E8;
  display: none; align-items: center; justify-content: center;
}
.ps-viewer[open] { display: flex; }
.ps-viewer::backdrop { background: rgba(10,8,7,.6); }
.ps-v-img { max-width: 92vw; max-height: 84dvh; object-fit: contain; border-radius: 3px; }
.ps-v-btn {
  position: absolute; width: 46px; height: 46px; border-radius: 50%; cursor: pointer; padding: 0;
  display: grid; place-items: center; color: #F6F3E8;
  border: 1px solid rgba(246,243,232,.28); background: rgba(246,243,232,.08);
  transition: background-color 150ms ease-out, opacity 150ms ease-out;
}
.ps-v-btn svg { width: 18px; height: 18px; }
.ps-v-btn:hover { background: rgba(246,243,232,.18); }
.ps-v-btn:disabled { opacity: .22; pointer-events: none; }
.ps-v-btn:focus-visible { outline: 2px solid #F6F3E8; outline-offset: 3px; }
.ps-v-close { top: 1rem; inset-inline-end: 1rem; }
.ps-v-prev { inset-inline-start: 1rem; top: 50%; transform: translateY(-50%); }
.ps-v-next { inset-inline-end: 1rem; top: 50%; transform: translateY(-50%); }
[dir="rtl"] .ps-v-prev svg, [dir="rtl"] .ps-v-next svg { transform: scaleX(-1); }
.ps-v-count { position: absolute; bottom: 1.3rem; inset-inline: 0; margin: 0; text-align: center; font-size: .66rem; letter-spacing: .2em; color: rgba(246,243,232,.6); }

/* ── Tablet and up ────────────────────────────────────────────────────── */
@media (min-width: 640px) {
  .ps-empty { grid-template-columns: minmax(0, 320px) minmax(0, 1fr); gap: 3rem; }
}
/* ── Desktop: media and editorial side by side, alternating ──────────────
   [data-narrow] forces the phone layout whatever the window size (the
   Admin preview's phone frame). */
@media (min-width: 900px) {
  .ps:not([data-narrow]) .ps-stage {
    grid-template-columns: minmax(0, 1fr) minmax(240px, 380px);
    column-gap: clamp(2.5rem, 5vw, 4.5rem); align-items: center;
    min-height: 88svh; padding: 3rem 0;
  }
  .ps:not([data-narrow]) .ps-stage[data-weight="flagship"] { min-height: 100svh; }
  .ps:not([data-narrow]) .ps-stage[data-weight="quiet"]    { min-height: 74svh; }
  .ps:not([data-narrow]) .ps-stage[data-side="b"] { grid-template-columns: minmax(240px, 380px) minmax(0, 1fr); }
  .ps:not([data-narrow]) .ps-stage[data-side="b"] .ps-frame { order: 2; }
  .ps:not([data-narrow]) .ps-media { --cap: 74svh; }
  .ps:not([data-narrow]) .ps-stage[data-weight="flagship"] .ps-media { --cap: 82svh; }
  .ps:not([data-narrow]) .ps-stage[data-weight="quiet"]    .ps-media { --cap: 62svh; }
  .ps:not([data-narrow]) .ps-badge { top: 3rem; }
}
/* ── Phones: one predictable column; media first, then words ─────────── */
@media (max-width: 899px) {
  .ps-media { --cap: 70svh; }
  .ps-stage[data-weight="flagship"] .ps-media { --cap: 74svh; }
  .ps-stage[data-weight="quiet"]    .ps-media { --cap: 60svh; }
  .ps-stage { padding: 2.75rem 0; }
  .ps-ed { padding-inline: .1rem; }
  .ps-ctl-btn { width: 40px; height: 40px; }      /* comfortable touch targets */
}
.ps[data-narrow] .ps-media { --cap: 70svh; }
.ps[data-narrow] .ps-stage { padding: 2.75rem 0; }
.ps[data-narrow] .ps-ctl-btn { width: 40px; height: 40px; }

/* ── Reduced motion ───────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .ps-img, .ps-poster, .ps-surface, .ps-shade, .ps-tick, .ps-play, .ps-ctl, .ps-ctl-btn, .ps-v-btn { transition: none; }
  .ps-thumb:hover .ps-img { transform: none; }
}
.ps[data-motion="reduced"] .ps-img, .ps[data-motion="reduced"] .ps-poster, .ps[data-motion="reduced"] .ps-surface, .ps[data-motion="reduced"] .ps-ctl { transition: none; }
