/* ZincArt — Skeleton system (BELOW-FOLD + HERO IMAGES)
 *
 * Hero (first section of <main>) renders text/buttons/cards from first
 * paint with no placeholder — they slide in via GSAP only.
 * EXCEPTION: hero <img>/iframe elements ARE hidden by the skeleton
 * (opacity:0) so they never flash visible before the GSAP fade-in
 * starts. The hero timeline takes over with a longer ~1s fade-in for
 * a cinematic image entry.
 * Below-fold sections show a full skeleton (text, buttons, cards,
 * images) until they scroll into view, then fade out as content
 * animates in.
 *
 * Lifecycle:
 *   1. First paint: <html class="zinc-anim-pending"> applies skeleton
 *      styling to every main > section EXCEPT :first-of-type. The hero
 *      paints normally (no placeholder).
 *   2. animations.js runs ~80ms after window.load:
 *      a. Adds .zinc-skel-pending to every below-fold section (so they
 *         stay in skeleton state even after .zinc-anim-pending is gone).
 *      b. Removes .zinc-anim-pending from <html>.
 *   3. As user scrolls, IntersectionObserver fires per section:
 *      a. Removes .zinc-skel-pending from the section (skeleton fades
 *         over 0.28s via CSS transitions).
 *      b. GSAP simultaneously slides/scales content into place.
 *   4. The two effects OVERLAP smoothly — real text/content appears
 *      ABOVE the still-visible skeleton via alpha interpolation of
 *      `color` (transparent → natural) and `background-color` (skeleton
 *      → natural). The skeleton fades while content emerges on top.
 *
 * CRITICAL: GSAP must NOT animate opacity on skeletonized elements.
 * Opacity on the element itself would hide BOTH the text and the
 * skeleton bg (since the bg is painted on the element). Let CSS handle
 * the fade via color/bg transitions; let GSAP handle motion only.
 *
 * Skeleton appearance: opaque, very subtle (close to surface colour),
 * not flashy. A hint of structure, not a loading shimmer.
 */

:root {
  /* Skeleton surface colours.
   * - Light: subtle, close to background → barely visible placeholder.
   * - Dark:  clearly visible blueish-slate that contrasts against the
   *          near-black zinc-900/zinc-950 gradients used on dark cards. */
  --skeleton-bg:      oklch(94% 0.003 286);   /* on light surfaces — barely visible */
  --skeleton-bg-dark: oklch(55% 0.10 245 / 0.05); /* on dark surfaces — very translucent blueish-dark wash */

  /* Per-primitive radii */
  --skeleton-radius-text:    0.25rem;
  --skeleton-radius-heading: 0.5rem;
  --skeleton-radius-button:  9999px;
  --skeleton-radius-card:    0.75rem;
  --skeleton-radius-image:   0.75rem;

  /* Fade-out duration — fast (skeleton shouldn't linger) */
  --skeleton-fade: 0.28s;
}

/* Dark-background detection — swap the token to the dark variant.
 * Matches dark wrappers at ANY depth inside <main> (sections, cards,
 * gradient panels, etc.) so the skeleton-bg cascades correctly into
 * nested dark blocks like the "Consulta gratuita" card on the home. */
main [class*="bg-zinc-9"],
main [class*="bg-black"],
main [class*="bg-[url"],
main [class*="from-zinc-9"],
main [class*="from-zinc-950"],
main [class*="to-zinc-950"],
main [class*="bg-foreground"] {
  --skeleton-bg: var(--skeleton-bg-dark);
}

/* ── 1. CSS TRANSITIONS — always defined so that when .zinc-anim-pending
 *      (html) or .zinc-skel-pending (section) is removed, the properties
 *      smoothly transition from skeleton state back to natural state.
 *      `color` transition interpolates alpha, so text fades in ON TOP of
 *      the skeleton bg which simultaneously fades out. ─────────────── */
main > section h1,
main > section h2,
main > section h3,
main > section h4,
main > section p,
main > section blockquote,
main > section a[class*="inline-flex"][class*="rounded"],
main > section button[class*="inline-flex"][class*="rounded"],
main > section .grid > *,
main > section [class*="grid-cols"] > *,
main > section details,
main > section figure {
  transition:
    color           var(--skeleton-fade) ease-out,
    background-color var(--skeleton-fade) ease-out,
    border-color    var(--skeleton-fade) ease-out;
}

/* Nested children also transition opacity so they fade in smoothly
 * (instead of snapping visible like `visibility: hidden` → visible). */
main > section h1 > *,
main > section h2 > *,
main > section h3 > *,
main > section h4 > *,
main > section p > *,
main > section blockquote > *,
main > section a[class*="inline-flex"][class*="rounded"] > *,
main > section button[class*="inline-flex"][class*="rounded"] > *,
main > section .grid > * > *,
main > section [class*="grid-cols"] > * > *,
main > section details > *,
main > section figure > * {
  transition: opacity var(--skeleton-fade) ease-out;
}

main > section img:not([src*="logo"]),
main > section iframe {
  transition: opacity var(--skeleton-fade) ease-out;
}

/* Form fields — match the same color/bg transition so they fade out
 * coherently when their section's skeleton class is removed. */
main > section label,
main > section input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):not([type="submit"]),
main > section textarea,
main > section select {
  transition:
    color           var(--skeleton-fade) ease-out,
    background-color var(--skeleton-fade) ease-out,
    border-color    var(--skeleton-fade) ease-out;
}

/* ── 2. SKELETON STATE ─────────────────────────────────────────────
 *   Active when EITHER:
 *     (a) html.zinc-anim-pending  — first-paint, covers all sections
 *     (b) section.zinc-skel-pending — per-section, applied to below-fold
 *         sections by JS so they stay in skeleton state after (a) is gone
 * ───────────────────────────────────────────────────────────────── */

/* --- Text primitives: transparent text + subtle bg block --- */
html.zinc-anim-pending main > section:not(:first-of-type) h1,
html.zinc-anim-pending main > section:not(:first-of-type) h2,
html.zinc-anim-pending main > section:not(:first-of-type) h3,
html.zinc-anim-pending main > section:not(:first-of-type) h4,
html.zinc-anim-pending main > section:not(:first-of-type) p,
html.zinc-anim-pending main > section:not(:first-of-type) blockquote,
main > section.zinc-skel-pending h1,
main > section.zinc-skel-pending h2,
main > section.zinc-skel-pending h3,
main > section.zinc-skel-pending h4,
main > section.zinc-skel-pending p,
main > section.zinc-skel-pending blockquote {
  color: transparent !important;
  background-color: var(--skeleton-bg);
  border-radius: var(--skeleton-radius-text);
}

html.zinc-anim-pending main > section:not(:first-of-type) h1,
html.zinc-anim-pending main > section:not(:first-of-type) h2,
html.zinc-anim-pending main > section:not(:first-of-type) h3,
html.zinc-anim-pending main > section:not(:first-of-type) h4,
main > section.zinc-skel-pending h1,
main > section.zinc-skel-pending h2,
main > section.zinc-skel-pending h3,
main > section.zinc-skel-pending h4 {
  border-radius: var(--skeleton-radius-heading);
}

html.zinc-anim-pending main > section:not(:first-of-type) blockquote,
main > section.zinc-skel-pending blockquote {
  border-radius: var(--skeleton-radius-card);
}

/* Hide nested children of text elements (icons, nested spans) — fades out smoothly */
html.zinc-anim-pending main > section:not(:first-of-type) h1 > *,
html.zinc-anim-pending main > section:not(:first-of-type) h2 > *,
html.zinc-anim-pending main > section:not(:first-of-type) h3 > *,
html.zinc-anim-pending main > section:not(:first-of-type) h4 > *,
html.zinc-anim-pending main > section:not(:first-of-type) p > *,
html.zinc-anim-pending main > section:not(:first-of-type) blockquote > *,
main > section.zinc-skel-pending h1 > *,
main > section.zinc-skel-pending h2 > *,
main > section.zinc-skel-pending h3 > *,
main > section.zinc-skel-pending h4 > *,
main > section.zinc-skel-pending p > *,
main > section.zinc-skel-pending blockquote > * {
  opacity: 0;
}

/* --- Cards / grid children / details / figures --- */
html.zinc-anim-pending main > section:not(:first-of-type) .grid > *,
html.zinc-anim-pending main > section:not(:first-of-type) [class*="grid-cols"] > *,
html.zinc-anim-pending main > section:not(:first-of-type) details,
html.zinc-anim-pending main > section:not(:first-of-type) figure,
main > section.zinc-skel-pending .grid > *,
main > section.zinc-skel-pending [class*="grid-cols"] > *,
main > section.zinc-skel-pending details,
main > section.zinc-skel-pending figure {
  background-color: var(--skeleton-bg) !important;
  background-image: none !important;
  border-radius: var(--skeleton-radius-card);
  box-shadow: none !important;
  border-color: transparent !important;
}
html.zinc-anim-pending main > section:not(:first-of-type) .grid > * > *,
html.zinc-anim-pending main > section:not(:first-of-type) [class*="grid-cols"] > * > *,
html.zinc-anim-pending main > section:not(:first-of-type) details > *,
html.zinc-anim-pending main > section:not(:first-of-type) figure > *,
main > section.zinc-skel-pending .grid > * > *,
main > section.zinc-skel-pending [class*="grid-cols"] > * > *,
main > section.zinc-skel-pending details > *,
main > section.zinc-skel-pending figure > * {
  opacity: 0;
}

/* --- Buttons / CTAs: pill skeletons, hide content --- */
html.zinc-anim-pending main > section:not(:first-of-type) a[class*="inline-flex"][class*="rounded"],
html.zinc-anim-pending main > section:not(:first-of-type) button[class*="inline-flex"][class*="rounded"],
main > section.zinc-skel-pending a[class*="inline-flex"][class*="rounded"],
main > section.zinc-skel-pending button[class*="inline-flex"][class*="rounded"] {
  background-color: var(--skeleton-bg) !important;
  background-image: none !important;
  color: transparent !important;
  border-color: transparent !important;
  box-shadow: none !important;
  border-radius: var(--skeleton-radius-button);
}
html.zinc-anim-pending main > section:not(:first-of-type) a[class*="inline-flex"][class*="rounded"] > *,
html.zinc-anim-pending main > section:not(:first-of-type) button[class*="inline-flex"][class*="rounded"] > *,
main > section.zinc-skel-pending a[class*="inline-flex"][class*="rounded"] > *,
main > section.zinc-skel-pending button[class*="inline-flex"][class*="rounded"] > * {
  opacity: 0;
}

/* --- Form fields: same skeleton treatment as text/buttons.
 *     Labels become transparent text + bg block; inputs/textareas/selects
 *     become solid skeleton blocks (their text content / placeholder is
 *     hidden by the color:transparent override). Keeps the form looking
 *     uniformly placeholder'd until the skeleton class is removed. --- */
html.zinc-anim-pending main > section label,
main > section.zinc-skel-pending label {
  color: transparent !important;
  background-color: var(--skeleton-bg);
  border-radius: var(--skeleton-radius-text);
}
html.zinc-anim-pending main > section input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):not([type="submit"]),
html.zinc-anim-pending main > section textarea,
html.zinc-anim-pending main > section select,
main > section.zinc-skel-pending input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):not([type="submit"]),
main > section.zinc-skel-pending textarea,
main > section.zinc-skel-pending select {
  color: transparent !important;
  background-color: var(--skeleton-bg) !important;
  border-color: transparent !important;
  box-shadow: none !important;
  border-radius: var(--skeleton-radius-text);
}
/* Hide select arrow / file picker button inside skeletonized fields */
html.zinc-anim-pending main > section select::-ms-expand,
main > section.zinc-skel-pending select::-ms-expand {
  display: none;
}
html.zinc-anim-pending main > section input[type="file"]::file-selector-button,
main > section.zinc-skel-pending input[type="file"]::file-selector-button {
  visibility: hidden;
}

/* --- Images and iframes: opacity-based hide so CSS transition fades them in.
 *     opacity:0 hides the element entirely (incl pixels) BEFORE the browser
 *     has a chance to render the loaded image — no flash.
 *
 *     EXCEPTION: hero (first-of-type) is otherwise excluded from the skeleton
 *     system, but we DO keep the image-hide there so hero images don't flash
 *     visible before the GSAP fade-in takes over. The hero timeline's
 *     gsap.set(heroExtras, {opacity: 0}) bakes the inline state, then animates
 *     opacity 0→1 over ~1s (slower, cinematic fade — distinct from the
 *     0.28s CSS fade used by below-fold images). --- */
html.zinc-anim-pending main > section img:not([src*="logo"]),
html.zinc-anim-pending main > section iframe,
main > section.zinc-skel-pending img:not([src*="logo"]),
main > section.zinc-skel-pending iframe {
  opacity: 0;
}

/* ── 3. HERO PRE-HIDE (anti-FOUC) ──────────────────────────────────
 *   The hero is otherwise excluded from the skeleton system, but we
 *   still need to prevent its text from painting at natural opacity
 *   BEFORE the GSAP scripts (loaded via deferred CDN) finish loading
 *   and apply their initial state via gsap.set(). Without this, on
 *   slower-loading pages users see a "blink" — text appears full
 *   opacity, then GSAP sets it to 0.1 and animates back in.
 *
 *   These rules are scoped to html.zinc-anim-pending which is added
 *   SYNCHRONOUSLY by the inline <script> in <head> before first paint,
 *   so the hero's initial state is already applied at FCP. Once GSAP
 *   runs, its inline gsap.set() values (matching these) take over,
 *   then animate to natural state. The class is removed once the JS
 *   has set the inline state, ending the CSS contribution.
 * ───────────────────────────────────────────────────────────────── */
html.zinc-anim-pending main > section:first-of-type h1,
html.zinc-anim-pending main > section:first-of-type h2,
html.zinc-anim-pending main > section:first-of-type h3,
html.zinc-anim-pending main > section:first-of-type h4,
html.zinc-anim-pending main > section:first-of-type p,
html.zinc-anim-pending main > section:first-of-type li,
html.zinc-anim-pending main > section:first-of-type dt,
html.zinc-anim-pending main > section:first-of-type dd,
html.zinc-anim-pending main > section:first-of-type blockquote,
html.zinc-anim-pending main > section:first-of-type span.uppercase,
html.zinc-anim-pending main > section:first-of-type span[class*="tracking-"],
html.zinc-anim-pending main > section:first-of-type a[class*="inline-flex"][class*="rounded"],
html.zinc-anim-pending main > section:first-of-type button[class*="inline-flex"][class*="rounded"],
html.zinc-anim-pending main > section:first-of-type [class*="rounded-full"]:not(a):not(button),
html.zinc-anim-pending main > section:first-of-type input:not([type="hidden"]),
html.zinc-anim-pending main > section:first-of-type select,
html.zinc-anim-pending main > section:first-of-type textarea,
html.zinc-anim-pending main > section:first-of-type label {
  opacity: 0.1;
}

/* H1 also starts blurred to match the GSAP filter: blur(4px) initial state */
html.zinc-anim-pending main > section:first-of-type h1 {
  filter: blur(4px);
}

/* Subtitle (paragraph immediately following the H1) gets a softer blur
 * so it animates in coherently with the title above it. */
html.zinc-anim-pending main > section:first-of-type h1 + p {
  filter: blur(2px);
}

/* Per-page override: portfolio is heavy (gallery markup + marquee animations).
 * We skip the entire hero pre-hide there — text + buttons appear immediately
 * at full opacity, no blur, no slide-up animation. */
html.zinc-anim-pending body.page-portfolio main > section:first-of-type h1,
html.zinc-anim-pending body.page-portfolio main > section:first-of-type h2,
html.zinc-anim-pending body.page-portfolio main > section:first-of-type h3,
html.zinc-anim-pending body.page-portfolio main > section:first-of-type h4,
html.zinc-anim-pending body.page-portfolio main > section:first-of-type p,
html.zinc-anim-pending body.page-portfolio main > section:first-of-type li,
html.zinc-anim-pending body.page-portfolio main > section:first-of-type dt,
html.zinc-anim-pending body.page-portfolio main > section:first-of-type dd,
html.zinc-anim-pending body.page-portfolio main > section:first-of-type blockquote,
html.zinc-anim-pending body.page-portfolio main > section:first-of-type span.uppercase,
html.zinc-anim-pending body.page-portfolio main > section:first-of-type span[class*="tracking-"],
html.zinc-anim-pending body.page-portfolio main > section:first-of-type a[class*="inline-flex"][class*="rounded"],
html.zinc-anim-pending body.page-portfolio main > section:first-of-type button[class*="inline-flex"][class*="rounded"],
html.zinc-anim-pending body.page-portfolio main > section:first-of-type [class*="rounded-full"]:not(a):not(button),
html.zinc-anim-pending body.page-portfolio main > section:first-of-type input:not([type="hidden"]),
html.zinc-anim-pending body.page-portfolio main > section:first-of-type select,
html.zinc-anim-pending body.page-portfolio main > section:first-of-type textarea,
html.zinc-anim-pending body.page-portfolio main > section:first-of-type label {
  opacity: 1;
  filter: none;
}

/* Reduced-motion users: no skeletons, no inline script adds the class,
 * and animations.js never adds .zinc-skel-pending. Real content renders
 * directly. No rules needed here. */
