/* Faith Hallgarth Photography — shared motion system
   One set of easings and durations for every page. Only transform, opacity
   and clip-path are animated. Everything is visible without JavaScript and
   everything calms down under prefers-reduced-motion. */
:root{
  --ease-out:cubic-bezier(.22,1,.36,1);     /* the house curve: quick start, long soft landing */
  --ease-in-out:cubic-bezier(.65,0,.35,1);  /* curtains: unveils, loader exit */
  --ease-in:cubic-bezier(.55,0,1,.45);      /* exits */
  --dur-fast:.3s;
  --dur-base:.5s;
  --dur-slow:.9s;
  --dur-reveal:1.1s;
  --dur-hero:1.2s;
  --dur-image:1.4s;
  --stagger:90ms;
  --rise:22px;
}

/* ---------- keyframes (same names as the page styles, retuned) ---------- */
@keyframes fh-up{from{opacity:0;transform:translate3d(0,var(--rise),0)}to{opacity:1;transform:none}}
@keyframes fh-fade{from{opacity:0}to{opacity:1}}
@keyframes fh-out{from{opacity:1}to{opacity:0}}
@keyframes fh-down{from{opacity:1;transform:none}to{opacity:0;transform:translate3d(0,-8px,0)}}
@keyframes fh-unveil{from{clip-path:inset(100% 0 0 0)}to{clip-path:inset(0 0 0 0)}}
@keyframes fh-settle{from{transform:scale(1.06)}to{transform:none}}
@keyframes fh-soft-in{from{opacity:0;transform:translate3d(0,8px,0)}to{opacity:1;transform:none}}

/* ---------- small interactions ---------- */
a{transition:opacity var(--dur-fast) var(--ease-out)}
.fh-navlink{transition:opacity var(--dur-fast) var(--ease-out),background-color var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out)}
a > svg[width="18"][height="10"]{transition:transform var(--dur-base) var(--ease-out)}
.fh-idx span:first-child{transition:transform var(--dur-base) var(--ease-out)}
.fh-chip{transition:opacity var(--dur-fast) var(--ease-out),background-color var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out),border-color var(--dur-fast) var(--ease-out)}
.fh-input{transition:border-color var(--dur-fast) var(--ease-out),box-shadow var(--dur-fast) var(--ease-out)}
.fh-faq-icon::before,.fh-faq-icon::after{transition:transform var(--dur-base) var(--ease-out)}

/* Image hover zoom: one curve, GPU-friendly, only on devices that really hover
   (stops "sticky" zooms after a tap on phones). */
.fh-frame img,.fh-gal-item img,.fh-tile-frame img,.fh-jr-feat img,.fh-jr-card img{
  transition:transform var(--dur-image) var(--ease-out);backface-visibility:hidden}
@media (hover:none){
  .fh-plate:hover .fh-frame img,.fh-gal-item:hover img,.fh-tile:hover .fh-tile-frame img,
  .fh-jr-feat:hover img,.fh-jr-card:hover img{transform:none}
}

/* Header: fixed geometry, compositor-only motion.
   - Compact state = the whole bar lifts by the padding difference (2rem -> .875rem
     = 1.125rem) while its background layer lifts the same again, so the bar looks
     exactly like the old padded version without ever animating padding/height.
   - Hidden state = translate3d(0,-100%,0). Hide is a touch quicker than show.
   - Background and hairline live on pseudo-elements; the hairline fades by opacity. */
.fh-head{--head-lift:-1.125rem;
  transform:translate3d(0,0,0);will-change:transform;backface-visibility:hidden;
  transition:transform var(--head-show,.56s) var(--ease-out)}
.fh-head::before,.fh-head::after{content:"";position:absolute;left:0;right:0;pointer-events:none;
  transform:translate3d(0,0,0);transition:transform var(--head-show,.56s) var(--ease-out),opacity var(--head-show,.56s) var(--ease-out)}
.fh-head::before{top:0;bottom:-1px;z-index:-1;background:#2E3023}
.fh-head::after{bottom:-1px;height:1px;background:rgba(241,234,219,0.12);opacity:0}
.fh-head.is-compact{transform:translate3d(0,var(--head-lift),0)}
.fh-head.is-compact::before,.fh-head.is-compact::after{transform:translate3d(0,var(--head-lift),0)}
.fh-head.is-compact::after{opacity:1}
.fh-head.is-hidden{transform:translate3d(0,-100%,0);transition-duration:.42s}
/* background layer extends upward so nothing shows above the lifted bar */
.fh-head::before{top:-2rem}

/* ---------- loader ---------- */
.fh-loader{transition:opacity .7s var(--ease-in-out),visibility 0s linear .7s}
.fh-loader.is-out{opacity:0;visibility:hidden}
.fh-loader > *{transition:opacity .5s var(--ease-out),transform .7s var(--ease-in-out)}
.fh-loader.is-out > *{opacity:0;transform:translate3d(0,-10px,0)}
.fh-ld-arc{will-change:transform}

@media (prefers-reduced-motion: no-preference){
  html{scroll-behavior:smooth}

  /* hero entrance */
  .fh-in{animation:fh-up var(--dur-hero) var(--ease-out) both;animation-delay:var(--d,0ms)}
  .fh-unveil{animation:fh-unveil var(--dur-image) var(--ease-in-out) both;animation-delay:var(--d,0ms)}
  .fh-unveil img{animation:fh-settle 2s var(--ease-out) both;animation-delay:var(--d,0ms)}
  /* the header fades in on the first page of a visit only, never on every click */
  .fh-head.fh-in{animation:none}
  html.fh-first .fh-head.fh-in{animation:fh-fade var(--dur-slow) var(--ease-out) both}
  /* hold the hero until the loader lifts, so it is not wasted behind it */
  html.fh-hold .fh-in,html.fh-hold .fh-unveil,html.fh-hold .fh-unveil img{animation-play-state:paused}

  /* mobile menu */
  .fh-mmenu{animation:fh-fade var(--dur-base) var(--ease-out) both}
  .fh-mlist li{animation:fh-up var(--dur-slow) var(--ease-out) both}
  .fh-mlist li:nth-child(1){animation-delay:60ms}
  .fh-mlist li:nth-child(2){animation-delay:110ms}
  .fh-mlist li:nth-child(3){animation-delay:160ms}
  .fh-mlist li:nth-child(4){animation-delay:210ms}
  .fh-mlist li:nth-child(5){animation-delay:260ms}
  .fh-mmenu > div:last-child{animation:fh-soft-in var(--dur-slow) var(--ease-out) 320ms both}
  .fh-mmenu.fh-mmenu-out{animation:fh-out .36s var(--ease-in) .1s both}
  .fh-mmenu-out .fh-mlist li,.fh-mmenu-out > div:last-child{animation:fh-down .3s var(--ease-in) both}
  .fh-mmenu-out .fh-mlist li:nth-child(n){animation-delay:0s}

  /* FAQ answers ease in when opened */
  .fh-faq[open] > :not(summary){animation:fh-soft-in var(--dur-base) var(--ease-out) both}

  /* ---------- scroll reveals ----------
     Only hidden once JS has flagged the page (html.fh-js, set in <head>, removed
     again after 3s if site.js never runs), so content is never lost. */
  html.fh-js .fh-rv,
  html.fh-js #work > div:first-child, html.fh-js #work .fh-plate, html.fh-js #work .fh-close,
  html.fh-js #about .fh-meet > *,
  html.fh-js #experience > div:first-child, html.fh-js #experience li,
  html.fh-js section[aria-label="Client kind words"] figure,
  html.fh-js #investment > div:first-child, html.fh-js #investment > div:last-child, html.fh-js #investment article,
  html.fh-js #journal > div:first-child, html.fh-js #journal article,
  html.fh-js #inquire > div, html.fh-js footer > div,
  html.fh-js .fh-port .fh-tile, html.fh-js .fh-jr-card{
    opacity:0;transform:translate3d(0,var(--rise),0);
    transition:opacity var(--dur-slow) var(--ease-out),transform var(--dur-reveal) var(--ease-out);
    transition-delay:var(--rv-d,0ms)}
  html.fh-js .is-in{opacity:1!important;transform:none!important}
  /* once settled, drop the delay so hover/filters respond instantly */
  html.fh-js .is-done{transition-delay:0ms!important}

  /* ---------- page-to-page: a calm cross-fade (Chrome/Edge/Safari 18.2+; others just navigate) ---------- */
  @view-transition{navigation:auto}
  ::view-transition-old(root){animation:fh-out .35s var(--ease-out) both}
  ::view-transition-new(root){animation:fh-fade .5s var(--ease-out) both}
  .fh-head{view-transition-name:fh-head}
  ::view-transition-group(fh-head){animation-duration:.35s;animation-timing-function:var(--ease-out)}
  /* same-page view transitions (filters) */
  ::view-transition-group(*){animation-timing-function:var(--ease-out)}
  html.fh-vt-filter .fh-head{view-transition-name:none}
  html.fh-vt-filter::view-transition-group(*){animation-duration:.6s}
  html.fh-vt-filter::view-transition-old(*),html.fh-vt-filter::view-transition-new(*){height:100%;object-fit:cover}
  html.fh-vt-filter::view-transition-old(root),html.fh-vt-filter::view-transition-new(root){animation:none}
}

/* ---------- reduced motion: no movement, nothing hidden ---------- */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-delay:0s!important;animation-iteration-count:1!important;transition-duration:.01ms!important;transition-delay:0s!important}
  .fh-plate:hover .fh-frame img,.fh-gal-item:hover img,.fh-tile:hover .fh-tile-frame img,
  .fh-jr-feat:hover img,.fh-jr-card:hover img,.fh-idx:hover span:first-child,
  a:hover > svg[width="18"][height="10"]{transform:none}
  .fh-loader{transition:opacity .3s linear!important}
  .fh-head,.fh-head::before,.fh-head::after{transition:none!important}
}
