/* ==========================================================================
   BookMyDay — Motion layer
   Precise, quiet motion that respects the design system's rules:
   transform/opacity only, short distances, no lift/scale/shadow on hover.
   Everything here is opt-in via html.js-motion, so the site is fully
   readable with JavaScript disabled or motion reduced.
   ========================================================================== */

:root {
  /* Easing */
  --ease-out: cubic-bezier(.22, .61, .36, 1);
  --ease-out-expo: cubic-bezier(.16, 1, .3, 1);
  --ease-in-out: cubic-bezier(.65, 0, .35, 1);

  /* Duration */
  --dur-micro: .18s;
  --dur-short: .18s;
  --dur-mid: .32s;
  --dur-long: .32s;

  /* Reveal geometry */
  --reveal-shift: 12px;
}

/* --------------------------------------------------------------------------
   1. Scroll reveal
   Elements are tagged by js/motion.js, so coverage does not depend on
   per-page markup. Hidden only when motion is actually running.
   -------------------------------------------------------------------------- */
html.js-motion [data-reveal] {
  opacity: 0;
  transition:
    opacity var(--dur-long) var(--ease-out) var(--reveal-delay, 0ms),
    transform var(--dur-long) var(--ease-out) var(--reveal-delay, 0ms);
}

html.js-motion [data-reveal="up"] {
  transform: translate3d(0, var(--reveal-shift), 0);
}

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

html.js-motion [data-reveal="left"] {
  transform: translate3d(-12px, 0, 0);
}

html.js-motion [data-reveal="right"] {
  transform: translate3d(12px, 0, 0);
}

/* Hairline that draws itself in */
html.js-motion [data-reveal="rule"] {
  opacity: 1;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur-long) var(--ease-out-expo) var(--reveal-delay, 0ms);
}

/* Bar fills grow from their left edge */
html.js-motion [data-reveal="bar"] {
  opacity: 1;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur-long) var(--ease-out-expo) var(--reveal-delay, 0ms);
}

/* No will-change here on purpose: a long page arms ~90 elements at once, and
   holding a compositing layer for each costs more than the paint it saves.
   Opacity and transform are composited anyway. */
html.js-motion [data-reveal].is-in {
  opacity: 1;
  transform: none;
}

html.js-motion [data-reveal="rule"].is-in,
html.js-motion [data-reveal="bar"].is-in {
  transform: scaleX(1);
}

/* --------------------------------------------------------------------------
   2. Route transition + progress bar
   -------------------------------------------------------------------------- */
html.js-motion #content-area.is-entering {
  animation: bmd-route-in var(--dur-mid) var(--ease-out) both;
}

@keyframes bmd-route-in {
  from {
    opacity: 0;
    transform: translate3d(0, 10px, 0);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

/* Thin route progress bar, pinned above everything */
.route-progress {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 2000;
  width: 100%;
  height: 2px;
  background: transparent;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur-short) var(--ease-out);
}

.route-progress.is-active {
  opacity: 1;
}

.route-progress > span {
  display: block;
  height: 100%;
  width: 0;
  background: linear-gradient(90deg, var(--accent) 0%, var(--cta) 100%);
  transition: width var(--dur-mid) var(--ease-out);
}

/* --------------------------------------------------------------------------
   3. Header scroll state
   -------------------------------------------------------------------------- */
.site-header {
  transition: box-shadow var(--dur-short) var(--ease-out), border-color var(--dur-short) var(--ease-out);
}

.site-header .container {
  transition: padding-block var(--dur-short) var(--ease-out);
}

.site-header.is-scrolled {
  border-bottom-color: var(--ink);
}

.site-header.is-scrolled .container {
  padding-block: 9px;
}

.site-header .logo img {
  transition: max-width var(--dur-short) var(--ease-out);
}

.site-header.is-scrolled .logo img {
  max-width: 160px;
}

/* --------------------------------------------------------------------------
   4. Micro-interactions
   -------------------------------------------------------------------------- */

/* Arrow links slide their arrow, never the label */
.link-arrow::after,
.compare-list > a::after,
a.feature-card h3::after,
a.help-category-card h3::after {
  display: inline-block;
  transition: transform var(--dur-short) var(--ease-out);
}

.link-arrow:hover::after,
.compare-list > a:hover::after,
a.feature-card:hover h3::after,
a.help-category-card:hover h3::after {
  transform: translateX(4px);
}

.blog-read-more,
.back-link {
  transition: color var(--dur-micro) var(--ease-out), border-color var(--dur-micro) var(--ease-out);
}

/* Buttons: a real press, no hover lift */
.btn,
.footer-cta,
.nav-cta {
  transition:
    background-color var(--dur-micro) var(--ease-out),
    border-color var(--dur-micro) var(--ease-out),
    color var(--dur-micro) var(--ease-out),
    transform var(--dur-micro) var(--ease-out);
}

.btn:active,
.footer-cta:active,
.nav-cta:active {
  transform: translateY(1px);
}

/* Chips and tabs */
.chip,
.tab-nav button {
  transition:
    background-color var(--dur-micro) var(--ease-out),
    color var(--dur-micro) var(--ease-out),
    border-color var(--dur-micro) var(--ease-out);
}

/* Tab panels cross-fade in */
html.js-motion .tab-panel:not([hidden]) {
  animation: bmd-panel-in var(--dur-short) var(--ease-out) both;
}

@keyframes bmd-panel-in {
  from {
    opacity: 0;
    transform: translate3d(0, 6px, 0);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

/* Nav dropdowns — Bootstrap flips display, so animate rather than transition */
html.js-motion .site-header .dropdown-menu.show {
  animation: bmd-drop-in var(--dur-short) var(--ease-out) both;
}

@keyframes bmd-drop-in {
  from {
    opacity: 0;
    transform: translate3d(0, -6px, 0);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

/* Footer + nav links */
.footer-links a,
.site-header .nav-link,
.site-header .dropdown-item {
  transition: color var(--dur-micro) var(--ease-out), background-color var(--dur-micro) var(--ease-out);
}

/* Form focus */
.form-control,
.form-select,
textarea,
input {
  transition:
    border-color var(--dur-micro) var(--ease-out),
    box-shadow var(--dur-micro) var(--ease-out);
}

/* Controls */
.toggle,
.toggle > span,
.check-box,
.radio-dot {
  transition:
    background-color var(--dur-short) var(--ease-out),
    border-color var(--dur-short) var(--ease-out),
    color var(--dur-short) var(--ease-out),
    transform var(--dur-short) var(--ease-out);
}

/* Cards keep the system's hover rule — only the transition is tuned here */
.feature-card,
.service-detail-card,
.step-card,
.help-category-card,
.team-card,
.blog-card,
.contact-info-card {
  transition:
    border-color var(--dur-short) var(--ease-out),
    background-color var(--dur-short) var(--ease-out),
    box-shadow var(--dur-short) var(--ease-out);
}

/* --------------------------------------------------------------------------
   5. Accordion — animated open/close via grid rows
   Markup: .faq-a wraps .faq-a-inner. No [hidden], so the content is
   readable and open by default when JavaScript never runs.
   -------------------------------------------------------------------------- */
html.js-motion .faq-a {
  display: grid;
  grid-template-rows: 1fr;
  transition:
    grid-template-rows var(--dur-mid) var(--ease-out),
    opacity var(--dur-short) var(--ease-out),
    visibility 0s;
}

html.js-motion .faq-item:not(.is-open) .faq-a {
  grid-template-rows: 0fr;
  opacity: 0;
  visibility: hidden;
  transition:
    grid-template-rows var(--dur-mid) var(--ease-out),
    opacity var(--dur-short) var(--ease-out),
    visibility 0s var(--dur-mid);
}

.faq-a-inner {
  overflow: hidden;
  min-height: 0;
}

/* The affordance is the +/- glyph swap itself (per the kit), so there is no
   rotation here — rotating either glyph 180deg is identity and would animate
   nothing. The panel's height change carries the motion. */
.faq-item > .faq-q::after {
  transition: color var(--dur-micro) var(--ease-out);
}

.faq-item > .faq-q {
  transition: color var(--dur-micro) var(--ease-out);
}

.faq-item > .faq-q:hover {
  color: var(--accent-deep);
}

/* --------------------------------------------------------------------------
   6. Booking console choreography (home hero)
   -------------------------------------------------------------------------- */
html.js-motion .booking-console .cal-date,
html.js-motion .booking-console .slot-chip {
  animation: bmd-cell-in var(--dur-short) var(--ease-out) both;
  animation-delay: var(--cell-delay, 0ms);
}

@keyframes bmd-cell-in {
  from {
    opacity: 0;
    transform: translate3d(0, 4px, 0);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

.slot-chip,
.cal-date {
  transition: background-color var(--dur-micro) var(--ease-out), color var(--dur-micro) var(--ease-out);
}

/* Floating notes drift in, then breathe */
html.js-motion .floating-note {
  animation:
    bmd-note-in var(--dur-long) var(--ease-out-expo) both,
    bmd-float 6s var(--ease-in-out) infinite;
  animation-delay: var(--note-delay, 700ms), calc(var(--note-delay, 700ms) + var(--dur-long));
}

@keyframes bmd-note-in {
  from {
    opacity: 0;
    transform: translate3d(0, 10px, 0);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes bmd-float {
  0%, 100% {
    transform: translate3d(0, 0, 0);
  }

  50% {
    transform: translate3d(0, -6px, 0);
  }
}

/* The live marker on the timeline keeps a slow pulse */
html.js-motion .timeline-now::before {
  animation: bmd-pulse 2.4s var(--ease-in-out) infinite;
}

@keyframes bmd-pulse {
  0%, 100% {
    transform: scale(1);
    opacity: 1;
  }

  50% {
    transform: scale(1.5);
    opacity: .55;
  }
}

/* Status dot on the "all systems operational" band */
html.js-motion .status-overall .status-dot {
  animation: bmd-pulse 2.4s var(--ease-in-out) infinite;
}

/* --------------------------------------------------------------------------
   7. Logo strip — a gentle lift out of greyscale on hover
   -------------------------------------------------------------------------- */
.logo-row span {
  transition: opacity var(--dur-short) var(--ease-out), color var(--dur-short) var(--ease-out);
}

.logo-row:hover span {
  opacity: .55;
}

.logo-row span:hover {
  opacity: 1;
  color: var(--accent-deep);
}

/* --------------------------------------------------------------------------
   8. Rail
   -------------------------------------------------------------------------- */
.rail {
  scroll-behavior: smooth;
}

.rail.is-dragging {
  scroll-behavior: auto;
}

.rail > * {
  transition: border-color var(--dur-short) var(--ease-out);
}

/* --------------------------------------------------------------------------
   9. Reduced motion — a complete off-switch
   The reveal layer is never armed (js/motion.js checks the same query),
   and anything declarative is neutralised here.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html.js-motion [data-reveal],
  html.js-motion [data-reveal].is-in {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  html.js-motion #content-area.is-entering,
  html.js-motion .tab-panel:not([hidden]),
  html.js-motion .site-header .dropdown-menu.show,
  html.js-motion .booking-console .cal-date,
  html.js-motion .booking-console .slot-chip,
  html.js-motion .floating-note,
  html.js-motion .timeline-now::before,
  html.js-motion .status-overall .status-dot {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }

  .route-progress {
    display: none;
  }

  html.js-motion .faq-a,
  html.js-motion .faq-item:not(.is-open) .faq-a {
    transition: none !important;
  }
}
