/* Parlour Haus Salon: hero, header and entrance motion styles.
   Owned by assets/motion/hero.js. Loads after the inline stylesheet in index.html.
   Every hidden state is scoped under html.motion, which the loader adds before modules run,
   and is released by JS (the hero gets .ph-ready). Without JS, nothing here hides content. */

/* The hero is always dark, even on the light theme, so the pre-init ground is literal noir.
   This stops a white flash on the light theme while fonts load. */
html.motion .hero { background: #15100C; }

/* Initial hidden state for the entrance. The delayed keyframe is a pure CSS safety net:
   if init never arrives within 3s, everything shows anyway. Once .ph-ready lands the
   selector stops matching and inline GSAP values take over. */
html.motion .hero:not(.ph-ready) .hero-bg,
html.motion .hero:not(.ph-ready) .label,
html.motion .hero:not(.ph-ready) h1,
html.motion .hero:not(.ph-ready) .sub,
html.motion .hero:not(.ph-ready) .cta-row .btn,
html.motion .hero:not(.ph-ready) .trust > * {
  opacity: 0;
  animation: ph-safety 0s linear 3s forwards;
}
@keyframes ph-safety { to { opacity: 1; } }

/* Brand curtain, injected by JS and removed when done. Literal noir for the same reason as above. */
.ph-curtain {
  position: fixed;
  inset: 0;
  z-index: 500;
  background: #15100C;
  display: flex;
  align-items: center;
  justify-content: center;
  clip-path: inset(0 0 0 0);
}
.ph-curtain-mark {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 22px;
}
.ph-curtain-mark img {
  width: min(220px, 46vw);
  height: auto;
  opacity: 0;
}
.ph-curtain-line {
  display: block;
  width: min(220px, 46vw);
  height: 1px;
  background: var(--metal, linear-gradient(120deg, #E7CBA3, #C08A5E 52%, #7A5639));
  transform: scaleX(0);
  transform-origin: center;
}

/* Masked line reveal wrappers created by SplitText during the h1 entrance, then reverted.
   The padding and negative margin give descenders room inside the clip without moving the layout. */
.ph-hero-mask {
  overflow: hidden;
  padding-bottom: .14em;
  margin-bottom: -.14em;
}
.ph-hero-line { will-change: transform; }

/* Metallic shine sweep on every .btn. Sits over the existing metal gradient and keeps the 2px radius.
   Non-hover state has no transition so the band resets out of view instantly. */
.btn {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.btn::after {
  content: "";
  position: absolute;
  inset: -1px;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(115deg, transparent 42%, rgba(255, 255, 255, .16) 50%, transparent 58%);
  transform: translateX(-130%) skewX(-8deg);
  transition: none;
}
.btn:hover::after,
.btn:focus-visible::after {
  transform: translateX(130%) skewX(-8deg);
  transition: transform .8s cubic-bezier(.22, 1, .36, 1);
}
.btn.ghost::after {
  background: linear-gradient(115deg, transparent 36%, var(--line) 50%, transparent 64%);
}

/* Magnetic mode, added by JS on pointer-fine desktops only. GSAP owns the transform there,
   so the inline stylesheet's transform transition and hover lift are released to avoid fighting. */
.btn.ph-mag { transition: box-shadow .3s ease, filter .3s ease; }
.btn.ph-mag:hover { transform: none; }

/* Reduced motion: everything visible, no shine, no curtain. */
@media (prefers-reduced-motion: reduce) {
  html.motion .hero:not(.ph-ready) .hero-bg,
  html.motion .hero:not(.ph-ready) .label,
  html.motion .hero:not(.ph-ready) h1,
  html.motion .hero:not(.ph-ready) .sub,
  html.motion .hero:not(.ph-ready) .cta-row .btn,
  html.motion .hero:not(.ph-ready) .trust > * { opacity: 1; animation: none; }
  .btn::after { display: none; }
  .ph-curtain { display: none; }
}
