/* Garrison Revenue — motion layer.
   Shared by every page. Nothing here changes layout or copy; it only
   governs how things move. Every effect is wrapped so that a visitor
   with "reduce motion" turned on gets a still, instant site. */

:root {
  /* expo-out: fast start, long soft landing. this is the "butter" curve */
  --ease-out: cubic-bezier(0.16, 1, 0.30, 1);
  --ease:     cubic-bezier(0.22, 0.61, 0.36, 1);
  --t-press:  90ms;
  --t-hover:  220ms;
  --t-reveal: 620ms;
}

/* ---------------------------------------------------------------
   1. Smooth scrolling
   --------------------------------------------------------------- */

html { scroll-behavior: smooth; }

/* stop anchor targets from landing underneath the sticky header */
[id] { scroll-margin-top: 104px; }

/* ---------------------------------------------------------------
   2. Cross-document page transitions

   One CSS rule gets real animated navigation between separate HTML
   files in Chrome, Edge and Safari 18+. Browsers without it simply
   navigate normally and pick up the @supports fallback further down.
   --------------------------------------------------------------- */

@view-transition { navigation: auto; }

::view-transition-old(root) { animation: gr-page-out 240ms var(--ease) both; }
::view-transition-new(root) { animation: gr-page-in  400ms var(--ease-out) both; }

@keyframes gr-page-out { to   { opacity: 0; transform: translateY(-8px); } }
@keyframes gr-page-in  { from { opacity: 0; transform: translateY(12px); } }

/* Pull the header and footer out of the page snapshot so they stay
   anchored while only the content between them moves. This is what
   makes navigation read as one continuous surface instead of a reload. */
header { view-transition-name: gr-header; }
footer { view-transition-name: gr-footer; }

/* Fallback for browsers with no view-transition support. Opacity only,
   deliberately: a transform on <body> would create a containing block
   and break the sticky header. */
@supports not (view-transition-name: none) {
  @media (prefers-reduced-motion: no-preference) {
    body { animation: gr-fade-in 360ms var(--ease-out) both; }
  }
}
@keyframes gr-fade-in { from { opacity: 0; } }

/* ---------------------------------------------------------------
   3. Sticky header
   --------------------------------------------------------------- */

header {
  position: sticky;
  top: 0;
  z-index: 50;
  transition: box-shadow 260ms var(--ease);
}
header.gr-scrolled { box-shadow: 0 10px 30px -22px rgba(18, 42, 30, 0.7); }

/* ---------------------------------------------------------------
   4. Hover and press

   The hover shim rewrites the inline style attribute. Declaring the
   transitions here means those swaps animate instead of snapping.
   --------------------------------------------------------------- */

a, button, input, .chip, .pill, [style-hover], [style-focus] {
  transition:
    background-color var(--t-hover) var(--ease),
    color            var(--t-hover) var(--ease),
    border-color     var(--t-hover) var(--ease),
    box-shadow       var(--t-hover) var(--ease),
    filter           var(--t-hover) var(--ease),
    opacity          var(--t-hover) var(--ease),
    transform        160ms          var(--ease);
}

/* the tactile part: a real push on mousedown */
a[href]:active,
button:active,
.chip:active,
.pill:active {
  transform: translateY(1px) scale(0.988);
  transition-duration: var(--t-press);
}

button, .chip, .pill, a[href] { -webkit-tap-highlight-color: transparent; }

/* keyboard users get the same affordance, visibly */
a:focus-visible, button:focus-visible, input:focus-visible, .chip:focus-visible, .pill:focus-visible {
  outline: 2px solid oklch(0.62 0.12 75);
  outline-offset: 3px;
  border-radius: 3px;
}

/* ---------------------------------------------------------------
   5. Cards lift on hover
   Applied by motion.js only to cards that sit inside a grid, so large
   section containers never lift.
   --------------------------------------------------------------- */

.gr-card {
  transition:
    transform  260ms var(--ease-out),
    box-shadow 260ms var(--ease-out),
    border-color var(--t-hover) var(--ease);
  will-change: transform;
}
.gr-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 22px 44px -30px rgba(18, 42, 30, 0.55);
}

/* the six case-study cards on the results page */
a[data-cat] { transition: transform 260ms var(--ease-out), box-shadow 260ms var(--ease-out), border-color var(--t-hover) var(--ease); }
a[data-cat]:hover { transform: translateY(-4px); }

/* ---------------------------------------------------------------
   6. Scroll reveal
   motion.js adds .gr-reveal only to elements below the fold, so the
   hero is never hidden and no-JS visitors see everything.
   --------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  .gr-reveal {
    opacity: 0;
    transform: translateY(20px);
  }
  .gr-reveal.gr-in {
    opacity: 1;
    transform: none;
    transition:
      opacity   var(--t-reveal) var(--ease-out),
      transform var(--t-reveal) var(--ease-out);
  }
}

/* ---------------------------------------------------------------
   7. Page-specific motion
   --------------------------------------------------------------- */

/* results: a card easing back in when a filter includes it */
.gr-pop { animation: gr-pop-in 340ms var(--ease-out) both; }
@keyframes gr-pop-in {
  from { opacity: 0; transform: translateY(10px) scale(0.985); }
}

/* book a call: each step sliding in, and a progress bar that fills */
.gr-step { animation: gr-step-in 380ms var(--ease-out) both; }
@keyframes gr-step-in {
  from { opacity: 0; transform: translateY(14px); }
}
#progress { transition: width 460ms var(--ease-out); }

/* ---------------------------------------------------------------
   8. Reduce motion. This wins over everything above.
   --------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .gr-card:hover, a[data-cat]:hover { transform: none; }
  a[href]:active, button:active, .chip:active, .pill:active { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
}
