/* The Estate at Sweetwater Creek — IMAGE REVEALS on every Estate page (2026-10-15 MDT).
   Moved VERBATIM out of css/estate/home-concept.css when Craig approved it site-wide ("yes all SC pages now");
   the homepage loads it through the Estate Template like every other page. PAIRED WITH js/estate/reveals.js.
   Skill: tlc-image-reveals. A photo with no frame (an editor's <img>, data-hc-rv="flat") only clips. */
/* ============================================================
   IMAGE REVEALS — Craig 2026-10-15: "i really want to use this animation of images as we scroll down the
   home page ... Looking for that consistent luxury feel as user navigates the page" (YouTube ot93rO2flS8,
   Ruben Stom, "Claude for Animated Website Designs"). The recipe is the creator's own spec, read off the
   video at 5:08-5:33: card photos "rise like a blind, revealed with clip-path from the bottom, while scaling
   from 1.25 to 1 ... 120ms apart", their text fading up after; a split section's photo "wipes in from the
   left"; a full-bleed photo "settles from scale 1.08 to 1"; two curves only, cubic-bezier(.16,1,.3,1) out
   and (.76,0,.24,1) in-out — "nothing bounces or overshoots".
   Left out on purpose (declared): the intro curtain (blanks the page ~2.6s and holds back LCP), the hero
   parallax and the footer marquee (continuous motion — Craig's motion-sickness rule), the eyebrow wipe and
   the letter blur (text, not images).
   - The FRAME clips; the photo inside it scales. A frame never takes a transform: photo-edit.js measures
     .ph-img as the frame, and a transformed frame is how the edit pencil went missing before.
   - The scale is the individual `scale` property, so it MULTIPLIES with the transforms these photos already
     carry (--ph-zoom crops, the tile and card hover grow) instead of replacing them, and no transition list
     is restated. The LQIP blur (::before) scales in step, so a photo that decodes mid-reveal never
     crossfades over a placeholder standing still.
   - Craig, the same day, once he saw it: "it seems like they're all wiping from bottom up. It's overdoing it
     when they are all the same across the entire page ... see about wiping each group differently from the
     others." So the DIRECTION is its own attribute, [data-hc-from], set per group in js/estate/reveals.js (HOME; AUTO elsewhere),
     neighboring groups never share one, and the hero's three tiles open three different ways (the vertical
     photo rises, as he asked). [data-hc-rv] now only says how far the photo settles: lg 1.25, md 1.15, sm 1.08.
   - fill-mode BACKWARDS only: when a reveal ends the element is back on its own styles; no final keyframe
     is left holding a clip or a scale. reveals.js then swaps .hc-in for .hc-done.
   - Nothing is hidden by CSS alone except the hero tiles, which are on screen at first paint: gated on .lqip
     (the template's inline head script), with a failsafe that opens them anyway if reveals.js never
     claims them. Everything else hides only under html.hc-rv, added by reveals.js in the same task as its
     tags. Print and reduced motion get the plain page.
   ============================================================ */
/* the closed state of each direction is the FROM frame of its keyframe — keep the two lists in step */
@keyframes hc-from-up{ from{ clip-path:inset(100% 0 0 0); } to{ clip-path:inset(0 0 0 0); } }
@keyframes hc-from-down{ from{ clip-path:inset(0 0 100% 0); } to{ clip-path:inset(0 0 0 0); } }
@keyframes hc-from-ltr{ from{ clip-path:inset(0 100% 0 0); } to{ clip-path:inset(0 0 0 0); } }
@keyframes hc-from-rtl{ from{ clip-path:inset(0 0 0 100%); } to{ clip-path:inset(0 0 0 0); } }
@keyframes hc-from-curtain{ from{ clip-path:inset(0 50% 0 50%); } to{ clip-path:inset(0 0 0 0); } }
@keyframes hc-from-split{ from{ clip-path:inset(50% 0 50% 0); } to{ clip-path:inset(0 0 0 0); } }
@keyframes hc-s125{ from{ scale:1.25; } to{ scale:1; } }
@keyframes hc-s115{ from{ scale:1.15; } to{ scale:1; } }
@keyframes hc-s108{ from{ scale:1.08; } to{ scale:1; } }
@keyframes hc-up{ from{ opacity:0; translate:0 14px; } to{ opacity:1; translate:0 0; } }

@media screen and (prefers-reduced-motion:no-preference){
  /* the H1 photo is the LCP image: never hidden, it only settles as the page arrives */
  .lqip .hc-hero .hc-main .ph-img img,
  .lqip .hc-hero .hc-main .ph-img.lq::before{ animation:hc-s108 2.4s cubic-bezier(.16,1,.3,1) backwards; }

  /* hero tiles, from first paint until the script claims them — and the failsafe if it never does.
     Keyed on the TILE being unclaimed, not on html.hc-rv: on a slow load the script leaves a tile whose failsafe
     is already opening untagged, so the opening finishes instead of snapping (FAILSAFE_AT in js/estate/reveals.js).
     Same three directions as HOME in js/estate/reveals.js. */
  html.lqip .hc-hero .hc-tile:not([data-hc-rv]){ animation:hc-from-up 1.4s cubic-bezier(.76,0,.24,1) 2.4s backwards; }
  html.lqip .hc-hero .hc-a1:not([data-hc-rv]){ animation-name:hc-from-ltr; }
  html.lqip .hc-hero .hc-a3:not([data-hc-rv]){ animation-name:hc-from-down; }

  /* waiting: closed toward its direction (default: up) */
  html.hc-rv [data-hc-rv]:not(.hc-in):not(.hc-done){ clip-path:inset(100% 0 0 0); }
  html.hc-rv [data-hc-from="down"]:not(.hc-in):not(.hc-done){ clip-path:inset(0 0 100% 0); }
  html.hc-rv [data-hc-from="ltr"]:not(.hc-in):not(.hc-done){ clip-path:inset(0 100% 0 0); }
  html.hc-rv [data-hc-from="rtl"]:not(.hc-in):not(.hc-done){ clip-path:inset(0 0 0 100%); }
  html.hc-rv [data-hc-from="curtain"]:not(.hc-in):not(.hc-done){ clip-path:inset(0 50% 0 50%); }
  html.hc-rv [data-hc-from="split"]:not(.hc-in):not(.hc-done){ clip-path:inset(50% 0 50% 0); }
  html.hc-rv [data-hc-rv="settle"]:not(.hc-in):not(.hc-done),
  html.hc-rv [data-hc-rv="text"]:not(.hc-in):not(.hc-done){ clip-path:none; }
  html.hc-rv [data-hc-rv="settle"]:not(.hc-in):not(.hc-done) :is(img,video),
  html.hc-rv [data-hc-rv="settle"].lq:not(.hc-in):not(.hc-done)::before{ scale:1.08; }
  html.hc-rv [data-hc-rv="text"]:not(.hc-in):not(.hc-done){ opacity:0; translate:0 14px; }

  /* revealing: the frame opens from its side ... */
  html.hc-rv [data-hc-rv].hc-in{ animation:hc-from-up 1.4s cubic-bezier(.76,0,.24,1) var(--hc-d,0ms) backwards; }
  html.hc-rv [data-hc-from="down"].hc-in{ animation-name:hc-from-down; }
  html.hc-rv [data-hc-from="ltr"].hc-in{ animation-name:hc-from-ltr; }
  html.hc-rv [data-hc-from="rtl"].hc-in{ animation-name:hc-from-rtl; }
  html.hc-rv [data-hc-from="curtain"].hc-in{ animation-name:hc-from-curtain; }
  html.hc-rv [data-hc-from="split"].hc-in{ animation-name:hc-from-split; }
  html.hc-rv [data-hc-rv="settle"].hc-in{ animation:none; }
  html.hc-rv [data-hc-rv="text"].hc-in{ animation:hc-up 1s cubic-bezier(.16,1,.3,1) var(--hc-d,0ms) backwards; }
  /* ... while the photo settles inside it (lg 1.25 is the video's card figure; md for split photos; sm for wide ones) */
  html.hc-rv [data-hc-rv].hc-in :is(img,video),
  html.hc-rv [data-hc-rv].hc-in.lq::before,
  html.hc-rv [data-hc-rv].hc-in .lq::before{ animation:hc-s125 1.9s cubic-bezier(.16,1,.3,1) var(--hc-d,0ms) backwards; }
  html.hc-rv [data-hc-rv="md"].hc-in :is(img,video),
  html.hc-rv [data-hc-rv="md"].hc-in.lq::before,
  html.hc-rv [data-hc-rv="md"].hc-in .lq::before{ animation-name:hc-s115; }
  html.hc-rv [data-hc-rv="sm"].hc-in :is(img,video),
  html.hc-rv [data-hc-rv="sm"].hc-in.lq::before,
  html.hc-rv [data-hc-rv="sm"].hc-in .lq::before{ animation-name:hc-s108; }
  html.hc-rv [data-hc-rv="settle"].hc-in :is(img,video),
  html.hc-rv [data-hc-rv="settle"].hc-in.lq::before,
  html.hc-rv [data-hc-rv="settle"].hc-in .lq::before{ animation:hc-s108 2.4s cubic-bezier(.16,1,.3,1) var(--hc-d,0ms) backwards; }
}
