/* ============================================================
   Artisan Website Co — motion system
   Owns all animation: load-in, scroll reveals, parallax hooks,
   nav glass, and elevated hover states. Vanilla companion:
   js/effects.js. Reveal initial states are scoped to html.js so
   content is never hidden without JavaScript.
   ============================================================ */

:root {
  --ease-artisan: cubic-bezier(0.22, 1, 0.36, 1);
  --reveal-duration: 0.9s;
}

/* --- global feel ------------------------------------------- */

html {
  scroll-behavior: smooth;
  color-scheme: dark;
  scrollbar-color: #2a2a2a #000;
}

[id] {
  scroll-margin-top: 7.5rem;
}

@media (max-width: 767px) {
  [id] {
    scroll-margin-top: 6.5rem;
  }
}

::selection {
  background: var(--color--artisan-gold);
  color: var(--color--artisan-black);
}

:focus-visible {
  outline: 2px solid var(--color--artisan-gold);
  outline-offset: 3px;
}

/* --- navbar: fixed, glass on scroll ------------------------- */

.navbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  background-color: transparent;
  transition: background-color 0.45s ease, box-shadow 0.45s ease;
}

.navbar.nav-scrolled {
  background-color: rgba(0, 0, 0, 0.55);
  -webkit-backdrop-filter: blur(14px) saturate(1.3);
  backdrop-filter: blur(14px) saturate(1.3);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.08);
}

/* nav load-in cascade */
html.js .nav-wrapper > * {
  opacity: 0;
  transform: translateY(-18px);
  animation: nav-in 0.9s var(--ease-artisan) forwards;
}

html.js .nav-wrapper > :nth-child(1) { animation-delay: 0.15s; }
html.js .nav-wrapper > :nth-child(2) { animation-delay: 0.28s; }
html.js .nav-wrapper > :nth-child(3) { animation-delay: 0.41s; }

@keyframes nav-in {
  to {
    opacity: 1;
    transform: none;
  }
}

/* --- hero: focus-pull load-in (transform stays free for
       parallax, which js/effects.js owns) --------------------- */

.section-header-background {
  overflow: hidden; /* masks the parallax drift of the video layer,
                       without clipping the rough edge's -2px seam
                       overlap (the edge is this layer's sibling) */
}

html.js .section-header .background-video {
  animation: hero-in 1.6s var(--ease-artisan) both;
  animation-delay: 0.1s;
}

@keyframes hero-in {
  from {
    opacity: 0;
    filter: blur(16px) brightness(0.55);
  }
  to {
    opacity: 1;
    filter: blur(0) brightness(1);
  }
}

/* the torn edge rips across the screen as the video focuses */
html.js .section-header .rough-edge {
  animation: tear-in 1.4s var(--ease-artisan) 0.45s both;
}

@keyframes tear-in {
  from {
    clip-path: inset(0 100% 0 0);
  }
  to {
    clip-path: inset(0 0 0 0);
  }
}

/* scroll cue: a gold thread drawing itself toward the tear */
.scroll-cue {
  z-index: 11;
  position: absolute;
  bottom: 8%;
  left: 50%;
  width: 1px;
  height: 44px;
  background-color: var(--color--artisan-gold);
  transition: opacity 0.4s ease;
}

@media (prefers-reduced-motion: no-preference) {
  .scroll-cue {
    animation: cue-drift 2.2s var(--ease-artisan) 2s infinite;
  }
}

@keyframes cue-drift {
  0% {
    transform: scaleY(0);
    transform-origin: top;
  }
  45% {
    transform: scaleY(1);
    transform-origin: top;
  }
  55% {
    transform: scaleY(1);
    transform-origin: bottom;
  }
  100% {
    transform: scaleY(0);
    transform-origin: bottom;
  }
}

html.has-scrolled .scroll-cue {
  opacity: 0;
}

/* --- scroll reveals ------------------------------------------
   Variants via data-reveal value:
     (default) rise: fade + translate up
     blur:  rise + blur-to-sharp
     pop:   rise + scale, for grid items
     line:  scale-x from the left, for dividers
     fade:  opacity only, for containers holding parallax media
     img:   scale settle inside an overflow-hidden mask
   js/effects.js adds .is-inview, then removes the attribute
   once settled so these rules stop applying entirely. */

html.js [data-reveal] {
  opacity: 0;
  transform: translateY(var(--rise, 38px));
  transition:
    opacity var(--reveal-duration) var(--ease-artisan) var(--rd, 0s),
    transform var(--reveal-duration) var(--ease-artisan) var(--rd, 0s),
    filter var(--reveal-duration) var(--ease-artisan) var(--rd, 0s);
  will-change: opacity, transform;
}

/* motion scaled to role: headings keep the full 38px marquee
   gesture, supporting elements move less */
html.js .w-richtext[data-reveal],
html.js .button[data-reveal] {
  --rise: 20px;
}

html.js .service-item[data-reveal] {
  --rise: 24px;
}

html.js .footer-credit[data-reveal] {
  --rise: 12px;
}

/* blur is the hero's motif — the h1 alone shares it */
html.js [data-reveal="blur"] {
  filter: blur(10px);
}

/* section h2s settle typographically instead: Antonio tracking
   tightens into place as they rise */
html.js h2[data-reveal="blur"] {
  filter: none;
  letter-spacing: 0.06em;
  --rise: 28px;
  transition:
    opacity var(--reveal-duration) var(--ease-artisan) var(--rd, 0s),
    transform var(--reveal-duration) var(--ease-artisan) var(--rd, 0s),
    letter-spacing 1.1s var(--ease-artisan) var(--rd, 0s);
}

html.js h2[data-reveal].is-inview {
  letter-spacing: 0;
}

/* pop gets its own spring physics — the only curve on the page
   allowed to overshoot */
html.js [data-reveal="pop"] {
  transform: translateY(16px) scale(0.8);
  transition-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1);
  transition-duration: 0.65s;
}

html.js [data-reveal="line"] {
  opacity: 1;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 1.1s var(--ease-artisan) var(--rd, 0s);
}

/* centered sections draw their lines from the middle out */
html.js .services-wrapper .divider[data-reveal="line"],
html.js .getstarted-divider[data-reveal="line"] {
  transform-origin: 50% 50%;
}

html.js [data-reveal="fade"] {
  transform: none;
}

html.js [data-reveal="img"] {
  opacity: 1;
  transform: scale(1.12);
  transition: transform 1.3s var(--ease-artisan) var(--rd, 0s);
}

html.js [data-reveal].is-inview {
  opacity: 1;
  transform: none;
  filter: none;
}

/* --- elevated hovers ---------------------------------------- */

.button {
  transition:
    background-color 0.25s ease,
    color 0.25s ease,
    transform 0.35s var(--ease-artisan),
    box-shadow 0.35s var(--ease-artisan);
}

.button:hover,
.button:focus-visible {
  background-color: var(--color--artisan-black);
  color: var(--color--artisan-white);
  transform: translateY(-2px);
  box-shadow: 0 12px 32px -10px rgba(234, 180, 41, 0.45);
}

/* the sparkle glints a half-turn; only the nav's primary CTA
   keeps the full signature spin */
.button img {
  transition: transform 0.7s var(--ease-artisan);
}

.button:hover img,
.button:focus-visible img {
  transform: rotate(180deg);
}

.navbar .button:hover img,
.navbar .button:focus-visible img {
  transform: rotate(360deg);
}

/* keep the lift working during a reveal's settle window */
html.js .button[data-reveal].is-inview:hover,
html.js .button[data-reveal].is-inview:focus-visible {
  transform: translateY(-2px);
}

/* scroll-spy: the hover language, now meaning "you are here" */
.navlink-item.is-current .navlink-underline {
  transform: translateY(5px);
}

.navlink-item.is-current .navlink {
  color: var(--color--artisan-gold);
}

.navlink {
  transition: color 0.3s ease;
}

.navlink-item:hover .navlink,
.navlink-item:focus-within .navlink {
  color: var(--color--artisan-gold);
}

/* gold underline hides below the item's overflow mask and slides
   up on hover/focus (and via scroll-spy's .is-current below) */
.navlink-underline {
  transform: translateY(20px);
  transition: transform 0.35s var(--ease-artisan);
}

.navlink-item:hover .navlink-underline,
.navlink-item:focus-within .navlink-underline {
  transform: translateY(5px);
}

.logo-grid img {
  opacity: 0.65;
  transition: opacity 0.35s ease, transform 0.35s var(--ease-artisan);
}

.logo-grid img:hover {
  opacity: 1;
  transform: translateY(-4px);
}

/* footer bookend: the tear that opened the site closes it */
.split-slot.img-margin {
  position: relative;
}

.rough-edge--top {
  top: -2px;
  bottom: auto;
  transform: rotate(180deg);
}

/* the footer sparkle flickers like neon down the street */
@media (prefers-reduced-motion: no-preference) {
  .footer-credit img {
    animation: twinkle 4s ease-in-out infinite;
  }
}

@keyframes twinkle {
  0%,
  100% {
    transform: scale(1) rotate(0deg);
    opacity: 1;
  }
  50% {
    transform: scale(0.82) rotate(25deg);
    opacity: 0.65;
  }
}

/* work showcase: slow zoom + lift inside its mask */
.section_full a .img-cover {
  transition: transform 1.1s var(--ease-artisan), filter 0.6s ease;
}

.section_full a:hover .img-cover,
.section_full a:focus-visible .img-cover {
  transform: scale(1.03);
  filter: brightness(1.08);
}

/* --- reduced motion ------------------------------------------
   The site stylesheet already zeroes animation/transition
   durations; these guards also neutralize initial states so
   nothing is hidden or offset. js/effects.js additionally skips
   parallax and reveals instantly. */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  html {
    scroll-behavior: auto;
  }

  html.js [data-reveal] {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
  }

  html.js .nav-wrapper > *,
  html.js .section-header .background-video,
  html.js .section-header .rough-edge {
    animation: none !important;
    opacity: 1;
    transform: none;
    clip-path: none;
  }

  .scroll-cue {
    display: none;
  }
}
