/*
 * NEWKID V2 — base foundation.
 *
 * Minimum CSS foundation for this phase: reset + design tokens from
 * docs/design-guidelines.md. Not the full design system — layout, components
 * and page-specific styling are built progressively per component, not here.
 */

:root {
	/* Colors (design-guidelines.md §3) */
	--color-bg: #000000;
	--color-fg: #F0F2E4;

	/* Foreground opacity hierarchy (design-guidelines.md §3) */
	--opacity-secondary: 0.7;
	--opacity-muted: 0.55;

	/* Structural grid (design-guidelines.md §8) */
	--grid-columns-desktop: 12;
	--grid-columns-mobile: 4;

	/* Page margin / grid gutter (design-guidelines.md §9-10) */
	--page-margin: clamp(14px, 1vw, 24px);
	--grid-gutter: 16px;

	/* Typography */
	--font-base: 'Poppins', sans-serif;

	/* Font weights (design-guidelines.md §67 "font weights" — a recommended
	   token group that didn't exist yet; added here rather than hardcoding
	   300 across ~20 individual rules). Site-wide lightening pass: body
	   copy, descriptions, labels, metadata and small UI text move from
	   Regular 400 to Light 300 through this one token; headings/major
	   editorial statements and <strong> emphasis keep their own explicit
	   weights declared directly on those rules — this token is never
	   applied to them. Real Poppins Light is already loaded (inc/enqueue.php
	   requests weight 300 in the Google Fonts URL), so this isn't a
	   browser-synthesized weight. */
	--weight-body: 300;

	/* Navigation/control type scale (design-guidelines.md §6 "Navigation",
	   upper end of its documented 12-14px range). Flat 14px, not fluid —
	   standardized per visual feedback so Header nav, Work filters and the
	   Grid/List toggle all read as one consistent small-UI scale. Shared by
	   .v2-header__nav-link/.v2-header__lang-link (components.css) and
	   .v2-work__filter/.v2-work__view-btn/.v2-section-pill/.v2-single-work__
	   nav-link (pages.css). Weight now sourced from --weight-body rather
	   than its own hardcoded value — this is the same "light UI text" family
	   as body copy, so it moves with that one token instead of needing its
	   own separate change. */
	--type-nav-size: 14px;
	--type-nav-weight: var(--weight-body);
	--type-nav-tracking: -0.01em;

	/* Small utility type scale (design-guidelines.md §6 "Small utility text") */
	--type-utility-size: clamp(10px, 0.8vw, 12px);

	/* Metadata/label type scale (design-guidelines.md §6 "Metadata / labels"
	   — About, Client, Category, Directed by, Director of photography...).
	   Used by Single Work's info-column labels (pages.css). */
	--type-meta-size: clamp(11px, 0.9vw, 13px);

	/* Body copy type scale (design-guidelines.md §6 "Body"). Used by Single
	   Work's description and information-row values (pages.css). */
	--type-body-size: clamp(13px, 1vw, 16px);

	/* UI transition timing (design-guidelines.md §54) */
	--transition-ui: 200ms ease;

	/* Shared subtle media-corner radius — Work thumbnails/hover-preview
	   (pages.css .v2-work-card__media) and the Single Work player's outer
	   frame (components.css .v2-player) both reference this one value so
	   they stay identical by construction rather than two hand-matched
	   numbers. Deliberately subtle (not a rounded-card look) — same 6px
	   already validated for Info's Workflow images (pages.css
	   --info-workflow-radius), kept as that section's own token there since
	   it isn't shared with anything else. */
	--v2-media-radius: 6px;

	/* Shared sticky Header-veil intensity — the single source of truth for
	   how strong the blur/darkening behind a fixed sticky UI zone (Header
	   alone on Info, Header+filters together on Work) is allowed to feel.
	   Both pages' own backdrop tokens (pages.css: --work-toolbar-blur/-bg,
	   --info-header-backdrop-blur/-bg) resolve to these, so tuning the
	   intensity in one place keeps Info and Work visually harmonized by
	   construction rather than by matching two numbers by hand. Refined down
	   from an earlier, much stronger first pass (14px / 0.4) that read as an
	   obvious frosted-glass panel — this is meant to sit at the edge of
	   noticeable, a depth cue rather than an effect. */
	--sticky-veil-blur: 7px;
	--sticky-veil-bg: rgba(0, 0, 0, 0.18);

	/* Shared "premium" entrance/reveal easing — a soft, decelerating curve
	   (close to "easeOutQuart") for the plain IntersectionObserver +
	   CSS-transition scroll reveals that deliberately don't use GSAP
	   (work-reveal.js), so that system still reads as the same motion
	   language as GSAP's power3.out page-entrance timelines (Home's
	   home-entrance.js, Work's work-entrance.js) without literally sharing
	   code with them. Gentler than a first pass at this token (0.22,1,.36,1,
	   an expo/quint-like curve) — softer deceleration reads calmer or
	   "premium, restrained" than "snappy". Not a design-guidelines.md value —
	   motion easing is implementation judgement there (§53/§54 define
	   philosophy/timing ranges, not a curve). */
	--ease-premium: cubic-bezier(0.165, 0.84, 0.44, 1);

	/* Media aspect ratios (design-guidelines.md §67) */
	--ratio-work: 16 / 9;
}

*,
*::before,
*::after {
	box-sizing: border-box;
}

html {
	-webkit-text-size-adjust: 100%;
}

body {
	margin: 0;
	min-height: 100dvh;
	display: flex;
	flex-direction: column;
	background: var(--color-bg);
	color: var(--color-fg);
	font-family: var(--font-base);
	font-weight: var(--weight-body);
}

img,
video {
	max-width: 100%;
	display: block;
}

a {
	color: inherit;
}

/* Guarantees the `hidden` attribute wins even against an equal-specificity
   `display` rule on the same element (e.g. `.v2-work__grid { display: grid }`
   toggled via `el.hidden` in JS) — author-origin rules otherwise override the
   UA stylesheet's own [hidden] rule at equal specificity. */
[hidden] {
	display: none !important;
}

/* ─── Motion: shared pre-paint reveal state ─────────────────────────────── */
/*
 * `.v2-reveal` is the ONE hidden-state class behind every NEWKID V2 page
 * entrance/reveal (Home's home-entrance.js, Work's work-entrance.js and
 * work-reveal.js). It lives here, not in a page-specific stylesheet,
 * because the whole point is that it's already loaded — and already
 * applied, since base.css is a render-blocking stylesheet — before any page
 * body content paints, on any current or future page that opts in.
 *
 * The FOUC this fixes: an element that starts fully visible in the DOM and
 * is only hidden by JS once a (footer-loaded, CDN-fetched) script finally
 * runs will often paint once at full visibility first, then visibly snap to
 * hidden right before animating back in. Gating the hidden state on
 * `html.motion-enabled` — a class a tiny synchronous inline <script> in
 * <head> adds before body content is even parsed (newkid_v2_motion_bootstrap(),
 * inc/enqueue.php) — removes that race entirely: the hidden state is live
 * from the very first frame, sourced from a stylesheet the browser already
 * blocks first paint on, not from a script that may run late.
 *
 * Progressive enhancement is the reason this is a class-on-html gate rather
 * than a bare `.v2-reveal { opacity: 0 }` rule: with no JS at all, the
 * inline script never runs, `.motion-enabled` never exists, and this rule
 * never matches — `.v2-reveal` elements stay at their normal default
 * visibility regardless of markup.
 *
 * `html`'s own type-selector specificity (this selector is 2 classes + 1
 * type) keeps this reliably above component rules like
 * `.v2-home__title.is-active` (2 classes, 0 types) without `!important` —
 * which matters, since `!important` here would also block GSAP's own
 * inline-style tweens on the same property (see below).
 *
 * Elements GSAP animates via `gsap.to()` (Home's whole sequence; Work's
 * heading/intro/toolbar/first Grid row; Single Work's nav/player/title/info
 * groups) must have exactly one owner for opacity/transform, not a
 * competing CSS transition also trying to interpolate every inline style
 * change GSAP makes (brief "avoid double animation systems") — several of
 * these elements (`.v2-home__title`, `.v2-single-work__nav-link`,
 * `.v2-work-row`) already carry their own small, unconditional
 * `transition: opacity` for an unrelated hover/active-state swap, so
 * `:not(.v2-reveal--transition)` below forces `transition: none` for the
 * whole time such an element is GSAP-owned (i.e. has `.v2-reveal` but not
 * the IO-reveal opt-in), overriding that unrelated rule for exactly as long
 * as it matters. Once a GSAP tween settles, the owning script strips
 * `.v2-reveal` (`classList.remove`) and clears the inline styles GSAP added
 * (`clearProps`) — at that point this rule no longer matches either, so the
 * element's own transition (hover, active-state swap, ...) works normally
 * again, same as if this system had never touched it.
 *
 * `.v2-reveal--transition` opts an element INTO a real CSS transition —
 * used only by the separate IntersectionObserver-driven reveal
 * (work-reveal.js: remaining Grid cards, List rows, Footer), where a plain
 * class toggle (`.is-revealed`), not GSAP, is what needs to animate
 * smoothly; the `:not()` above deliberately excludes these so the rule
 * below never fights that one. That system also fully removes every
 * `.v2-reveal*`/`.is-revealed` class once its own transition ends, so a
 * later, unrelated opacity change (e.g. Work's filter fade) is never
 * accidentally slowed down by a transition rule left over from the reveal
 * system.
 */

html.motion-enabled .v2-reveal {
	--reveal-y: 16px;
	opacity: 0;
	transform: translateY(var(--reveal-y));
}

html.motion-enabled .v2-reveal:not(.v2-reveal--transition) {
	transition: none;
}

html.motion-enabled .v2-reveal.is-revealed {
	opacity: 1;
	transform: translateY(0);
}

/* Two classes in the selector, not one, deliberately: .v2-work-row
   (pages.css) already carries its own unconditional `transition: opacity`
   for its hover fade. At equal (single-class) specificity pages.css's later
   source order would win, silently swapping this reveal's duration/ease for
   the 200ms hover one. The compound selector's higher specificity wins
   regardless of source order, without having to touch that existing rule. */
.v2-reveal.v2-reveal--transition {
	--reveal-duration: 0.9s;
	transition: opacity var(--reveal-duration) var(--ease-premium),
		transform var(--reveal-duration) var(--ease-premium);
}

/* Smaller/denser elements — Home's progress/footer, Work's intro/toolbar/
   List rows/footer. */
.v2-reveal--tight {
	--reveal-y: 10px;
	--reveal-duration: 0.8s;
}

@media (prefers-reduced-motion: reduce) {
	html.motion-enabled .v2-reveal {
		opacity: 1;
		transform: none;
		transition: none;
	}
}
