/**
 * Post-entry chrome intro — nav fade + H1 per-letter spin.  (MIKO-owned, theme-side, entry seam.)
 *
 * Pairs with assets/entry/20-hero-intro.js. MIKO 2026-07-13: the header/nav and the hero H1 come in
 * AFTER the opening (in-field coalesce) settles — the nav a simple fade, the H1 a per-letter spin.
 *
 * HIDE-THEN-REVEAL IS FIELD-MOUNT-ONLY AND JS-ONLY. The hold rules below are ALL scoped under
 * `html.vz-intro-armed`, a class the JS adds ONLY on the field-mount path, only at parse. With JS
 * off, or on any fallback row (mobile ≤781px / no-WebGL2 / reduced-motion / save-data), the class is
 * never present, so nav + H1 render at their normal full visibility — server HTML untouched, no
 * flash-of-hidden-content, fallback matrix intact. `html.vz-intro-shown` releases the nav fade.
 *
 * SPECIFICITY NOTE: the H1 hold uses `!important` deliberately. The hero-floor sheet
 * (10-hero-floor.css) runs its OWN settle-independent reveal (`.js .vz-hero-floor.is-in
 * .vz-hero-h1 { opacity:1 }`) on a rAF ~900ms after paint. To hold the H1 hidden until the entry
 * SETTLES (~4–6s), the armed hold must beat that rule — hence `!important`. Once the JS swaps
 * armed→shown and splits the letters, the hero-floor rule and the per-letter reveal take over
 * normally.
 *
 * Fabão seam: NONE (assets/entry/).
 */

/* ─────────────────────────────────────────────────────────────────────────────
   ARMED HOLD — field-mount path only, applied by JS at parse (html.vz-intro-armed).

   PAINT-CRITICAL DUPLICATE (2026-07-13, MIKO flash fix): the two armed-hold rules below
   (.site-header + .vz-hero-h1) are ALSO emitted as an inline <style id="vz-intro-hold"> by
   vizaion_hero_intro_arm() in functions.php (wp_head priority 1). That inline copy is the one
   that actually prevents the flash — this external sheet loads too late in the head to hold the
   H1 before first paint on a COLD load. These stay here as the readable source of record and for
   any path that reaches the sheet first; KEEP THE TWO IN LOCKSTEP (same selectors + values).
   ───────────────────────────────────────────────────────────────────────────── */

/* NAV / header held out until settle. Fades opacity only (no layout shift, no transform that would
   move the fixed header). The whole .site-header dims — brand mark, nav, social — as one panel, per
   MIKO's "simple fade in for the navigation panel". pointer-events off while hidden so the invisible
   header can't eat clicks over the hero. visibility:hidden (WCAG 2.4.3, critic HIGH) removes the nav
   links from the TAB ORDER while held — opacity:0 + pointer-events:none alone still let a keyboard
   user tab into invisible links. visibility is animatable-safe here (no transition on it → it flips
   at the armed→shown swap), and the shown rule below restores visibility:visible. */
html.vz-intro-armed .site-header {
  opacity: 0;
  pointer-events: none;
  visibility: hidden;
}

/* H1 held fully hidden until the spin plays. Beats the hero-floor settle-independent .is-in reveal
   (see specificity note). No transform — the per-letter spin carries the motion, not a slide.
   visibility:hidden so nothing inside the H1 is focusable/announced mid-hold; lifted on shown. */
html.vz-intro-armed .vz-hero .vz-hero-h1 {
  opacity: 0 !important;
  visibility: hidden !important;
}

/* ─────────────────────────────────────────────────────────────────────────────
   SHOWN — nav fade-in released (JS swaps armed→shown on the reveal signal).
   The fade TRANSITION is written INLINE by the JS from CFG.navFadeMs / navFadeDelayMs
   (2026-07-13, critic MEDIUM — those knobs are now live), so this rule only sets the
   end-state (opacity/pointer-events/visibility). The transition below is a fallback
   for the (impossible in practice) case the inline write didn't run.
   ───────────────────────────────────────────────────────────────────────────── */
html.vz-intro-shown .site-header {
  opacity: 1;
  pointer-events: auto;
  visibility: visible;
  transition: opacity 900ms cubic-bezier(.2, .7, .2, 1) 0ms;
}

/* Once shown, lift the H1's armed visibility/opacity hold. Opacity is then governed by the hero-floor
   .is-in reveal; visibility must be explicitly restored here because the armed rule set it !important.
   The letters animate their own scramble→land on top. */
html.vz-intro-shown .vz-hero .vz-hero-h1 {
  visibility: visible !important;
}

/* ─────────────────────────────────────────────────────────────────────────────
   H1 PER-LETTER SPIN — the visual letter layer the JS builds (aria-hidden).
   ───────────────────────────────────────────────────────────────────────────── */

/* The letter container inherits the H1's type; it just holds the per-char spans inline. */
.vz-h1-letters {
  display: inline;
}

/* Each character cell. inline-block so a spinning glyph can't nudge its neighbours (a wide 'W'
   swapping to a thin 'i' would otherwise reflow the line every glyphSwapMs). A min-width keeps the
   cell from collapsing on the narrow real char while spinning wider glyphs, so the line width does
   not breathe much as glyphs cycle.
   2026-07-13 (critic HIGH, H1 wrap): min-width was `1ch`, which is the '0' advance — WIDER than most
   letters, so it inflated every line ~40% (measured: "Art Collective" 326px natural → 462px at 1ch).
   That inflation, not the cap, was what forced the intended <br> lines to SUB-WRAP ("Art Collecti /
   ve") once the max-inline cap fell below ~460px (≤~1150px). Lowered to 0.6ch (measured: 352px for
   "Art Collective" — still curbs the per-45ms breathing for the common narrow letters, only the very
   widest pool glyphs W/M can nudge, which is imperceptible) so the split lines fit the cap and never
   sub-wrap. Space cells opt out so word gaps stay natural. */
.vz-h1-ch {
  display: inline-block;
  min-width: 0.6ch;
  text-align: center;
  white-space: pre; /* preserve the &nbsp; space cells */
}
.vz-h1-ch.vz-h1-space {
  min-width: 0;
}

/* A cell mid-spin: the cycling glyph reads a touch dimmer + lilac-tinted so the scramble looks like
   it's resolving toward the real ink, then snaps to full ink on land. */
.vz-h1-ch.is-cycling {
  color: var(--lilac, #C6B6F2);
  opacity: 0.72;
}

/* Landed cell: full ink, brief settle. */
.vz-h1-ch.is-landed {
  color: #F3F1FA;
  opacity: 1;
  transition: color 160ms ease, opacity 160ms ease;
}

/* ─────────────────────────────────────────────────────────────────────────────
   VERTICAL "VizAion" WORDMARK — decorative, aria-hidden, injected by the JS into
   .vz-hero on the field-mount path only (2026-07-13, MIKO). Counterbalances the
   lower-left H1; same type family; typewriter reveal in the H1 spin family.
   Kept clear of the social icons (top-right of the header) and the centred logo
   disc: pinned to the RIGHT EDGE, vertically centred in the lower band.
   Position/size are custom-prop tunables (MIKO fine-tunes).
   ───────────────────────────────────────────────────────────────────────────── */
.vz-hero-vmark {
	position: absolute;
	z-index: 3; /* same band as the floor/scrollcue, over the veil */
	right: var(--vz-vmark-right, clamp(1rem, 2.5vw, 2.25rem));
	top: var(--vz-vmark-top, 50%);
	transform: translateY(var(--vz-vmark-shift-y, -30%));
	writing-mode: vertical-rl; /* stacks the letters top→bottom on the right side */
	text-orientation: upright; /* each Latin glyph stays UPRIGHT (readable "VizAion" reading down),
	                              not rotated 90° — the legible convention for a Latin vertical mark. */
	pointer-events: none;
	font-family: var(--wp--preset--font-family--ibm-plex-sans); /* same as the H1 */
	font-weight: 400;
	font-size: var(--vz-vmark-size, clamp(1.1rem, 0.7rem + 1.1vw, 1.75rem));
	/* upright text sets its own inter-glyph gap; keep tracking small so the column stays tight. */
	letter-spacing: var(--vz-vmark-tracking, 0.04em);
	line-height: 1.05;
	color: #F3F1FA;
	text-shadow: 0 1px 24px rgba(7, 3, 18, 0.55); /* legibility over bright field cores */
}

/* Each vertical letter cell. In a vertical writing-mode the INLINE axis runs top→bottom, so the
   cells must be inline-flowing (inline-block) to stack DOWN the column — display:block would stack
   them along the BLOCK axis (horizontal here) and lay the word out sideways. inline-block also lets a
   wide spinning glyph swap without nudging neighbours. min-height (~1em on the inline axis) keeps the
   column from breathing as glyphs cycle. */
.vz-vmark-ch {
	display: inline-block;
	text-align: center;
	min-block-size: 1em;
}
.vz-vmark-ch.is-cycling {
	color: var(--lilac, #C6B6F2);
	opacity: 0.72;
}
.vz-vmark-ch.is-landed {
	color: #F3F1FA;
	opacity: 1;
	transition: color 160ms ease, opacity 160ms ease;
}

/* Hide the decoration below the mobile gate so it never crowds the H1 (belt-and-braces:
   the JS also never injects it on ≤781px since the whole file is gated off the field-mount
   path, but if a future path ever injects it, keep it off small screens). Aligned to the
   781px mobile gate (2026-07-13, critic LOW — was 600px, out of step with the JS guard). */
@media (max-width: 781px) {
	.vz-hero-vmark { display: none; }
}

/* ─────────────────────────────────────────────────────────────────────────────
   REDUCED MOTION — never hide, never spin. (The JS also excludes this path from
   arming, so these rules are belt-and-braces: even if the armed class somehow
   appears, reduced-motion users see everything instantly, no scramble.)
   ───────────────────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  html.vz-intro-armed .site-header,
  html.vz-intro-armed .vz-hero .vz-hero-h1 {
    opacity: 1 !important;
    pointer-events: auto !important;
    visibility: visible !important; /* pair with the armed visibility:hidden — never leave a
                                       reduced-motion user with visible opacity but hidden visibility */
  }
  .vz-h1-ch.is-cycling {
    color: #F3F1FA;
    opacity: 1;
  }
}
