/* ============================================================
 * Evoke — Showcase project layout.
 * Loaded only on single projects using the showcase layout
 * (see inc/meta-showcase.php).
 *
 * The nav and footer need NO overrides here: .nav__label and
 * .nav__bar-line are already var(--c-paper), .nav's bar is a
 * transparent dark that GSAP fades in, .footer is already
 * var(--c-ink), and both logo SVGs are white. The theme's chrome
 * was built light-on-dark from the start.
 *
 * Everything is laid out on the block axis — the reveal animations
 * move on Y and animate height, never X — so this file is
 * direction-agnostic and needs no RTL companion. Inline spacing
 * uses logical properties throughout.
 * ============================================================ */

body.project-showcase {
	/* --pshow-bg / --pshow-fg are printed per project in wp_head. */
	--pshow-w:        min(1200px, 100% - 2 * clamp(1rem, 4vw, 3rem));
	--pshow-logo-w:   min(720px,  100% - 2 * clamp(1rem, 4vw, 3rem));
	--pshow-gap:      clamp(4rem, 9vw, 7.5rem);

	/* Arabic descenders (ج ح خ ع غ م ن ي ة ر ز و) sit below the line
	   box. Without this the word masks clip them. Retune per font. */
	--pshow-mask-pad: .18em;
}

/* ---------- Shell ---------- */

.pshow {
	padding-block: clamp(7rem, 14vw, 11rem) clamp(4rem, 9vw, 7rem);
	background: var(--pshow-bg);
	color: var(--pshow-fg);
}

/* ---------- Media ---------- */

.pshow__media {
	display: block;
	width: 100%;
	aspect-ratio: var(--ar, 16 / 9);

	/* contain, never cover: if a stored dimension is wrong we'd rather
	   show a sliver of background than silently crop the board. */
	object-fit: contain;

	/* Stands in for a poster. Until the first frame decodes the element
	   is simply page-coloured, so there is no black rectangle and no
	   visible swap — which is why this layout ships without posters. */
	background: var(--pshow-bg);
}

/* ---------- Logo ---------- */

.pshow__logo {
	position: relative;
	width: var(--pshow-logo-w);
	margin-inline: auto;
	overflow: hidden;
}

/* ---------- Intro ---------- */

.pshow__intro {
	width: var(--pshow-w);
	margin-inline: auto;
	padding-block: clamp(3rem, 7vw, 5.5rem);
	text-align: center;
}

.pshow__title {
	margin: 0;
	font-family: var(--ff-display);
	font-size: clamp(2rem, 4.5vw, 3.75rem);
	font-weight: 400;
	line-height: 1.12;
	letter-spacing: -.01em;
	color: var(--pshow-fg);

	/* Keeps a Latin brand name inside Arabic copy from reordering once
	   each word becomes its own inline-block. */
	unicode-bidi: plaintext;
}

.pshow__copy {
	max-width: 62ch;
	margin-block-start: clamp(1.25rem, 3vw, 2rem);
	margin-inline: auto;
	font-family: var(--ff-sans);
	font-size: clamp(1rem, 1.15vw, 1.125rem);
	line-height: 1.75;
	unicode-bidi: plaintext;

	/* Softened with colour, NOT opacity — the reveal gate below owns
	   opacity on this element, and a design value sitting on the same
	   property would fight it. */
	color: var(--pshow-fg);
}

@supports (color: color-mix(in srgb, red 50%, transparent)) {
	.pshow__copy {
		color: color-mix(in srgb, var(--pshow-fg) 78%, transparent);
	}
}

.pshow__copy p {
	margin: 0;
}

.pshow__copy p + p {
	margin-block-start: 1em;
}

/* ---------- Reveal gate (kills the flash) ----------
   The words can only be hidden once JS has split them, which is one
   frame too late — the raw text paints first and then vanishes. So the
   CONTAINER starts at opacity 0 and JS switches it on the moment the
   masks are in place.

   This deliberately copies the theme's own convention: a bare
   [data-anim="…"] initial state, protected by the generic overrides
   already in evoke.css —

     html:not(.js) [data-anim]      → JS never ran
     html.js-no-anim [data-anim]    → evoke.js found no GSAP, or reduced motion
     @media (prefers-reduced-motion) [data-anim]

   — all of which set opacity:1 !important. Writing the rule this way
   inherits every one of those guards for free instead of re-deriving
   them, so there is no path where the text stays invisible. */

[data-anim="text-reveal"] {
	opacity: 0;
	will-change: opacity;
}

[data-anim="text-reveal"].is-revealed {
	opacity: 1;
	will-change: auto;
}

/* ---------- Word masks (JS-generated) ---------- */

.pw {
	display: inline-block;
	overflow: hidden;
	vertical-align: top;

	/* Widen the clip box, then cancel the widening in layout. */
	padding-block:  var(--pshow-mask-pad);
	margin-block:   calc(var(--pshow-mask-pad) * -1);
}

.pw__i {
	display: inline-block;
	will-change: transform;
}

/* Initial hidden state, applied by JS only — if GSAP never loads the
   class is never added and the text simply stays readable.

   160%, not 110%: the mask is taller than the word by 2 × --pshow-mask-pad,
   so an offset of one word-height leaves the top of the glyphs peeking out.
   This only has to guarantee "fully hidden" — GSAP replaces it with an
   exact pixel offset measured off the mask the moment the tween starts. */
.pshow__title.is-split .pw__i,
.pshow__copy.is-split  .pw__i {
	transform: translateY(160%);
}

/* ---------- Reel ---------- */

.pshow__reel {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--pshow-gap);
}

.pshow__item {
	position: relative;
	width: var(--pshow-w);
	margin: 0;
	overflow: hidden;
}

/* The board is a real button so full-screen is keyboard-reachable.
   Strip every default without killing the focus ring. */
.pshow__frame {
	display: block;
	width: 100%;
	padding: 0;
	border: 0;
	background: none;
	font: inherit;
	color: inherit;
	cursor: zoom-in;
	-webkit-appearance: none;
	appearance: none;
}

.pshow__frame:focus-visible {
	outline: 2px solid var(--c-focus);
	outline-offset: 3px;
}

/* ---------- Reveal covers ---------- */

.pshow__cover {
	position: absolute;
	inset-inline: 0;
	inset-block-start: 0;
	height: 100%;
	background: var(--pshow-bg);
	z-index: 2;
	pointer-events: none;
}

/* Matches the theme's existing no-JS convention (see the
   html:not(.js) .work-head__cover block in evoke.css). */
html:not(.js) .pshow__cover,
html.js-no-anim .pshow__cover {
	height: 0;
}

/* ---------- CTA ---------- */

.pshow__cta {
	display: flex;
	justify-content: center;
	margin-block-start: clamp(4rem, 9vw, 7rem);
}

/* ---------- Full screen ---------- */

.pshow__frame:fullscreen {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
	background: var(--pshow-bg);
	cursor: zoom-out;
}

.pshow__frame:fullscreen .pshow__media {
	width: auto;
	height: auto;
	max-width: 100%;
	max-height: 100%;
	aspect-ratio: auto;
}

/* ---------- Reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
	.pshow__cover {
		height: 0;
	}
	.pshow__title.is-split .pw__i,
	.pshow__copy.is-split  .pw__i {
		transform: none;
	}
	.pw {
		overflow: visible;
	}
}

/* ---------- Narrow ---------- */

@media (max-width: 600px) {
	body.project-showcase {
		--pshow-gap: clamp(2.5rem, 11vw, 4rem);
	}

	.pshow {
		padding-block-start: clamp(5rem, 22vw, 7rem);
	}

	/* At phone width the logo has no reason to be narrower than the
	   boards — the inset alone already frames it. */
	.pshow__logo {
		width: var(--pshow-w);
	}
}
