/*
 * Page-level styles shared by index.html, services.html and process.html.
 * Loaded after _ds/styles.css and theme.css, so design-system tokens are available.
 *
 * Two jobs:
 *   1. The WhatsApp controls and the mobile drawer (markup the design system has no class for).
 *   2. The motion system: entrances, hovers, and the reduced-motion / pause rules.
 *
 * Motion rules, held to 10k-websites/references/scrub-pipeline.md:
 *   - transform and opacity only
 *   - nothing snaps; two easing tokens used everywhere
 *   - entrance states are scoped to .js so the page is complete if the script never runs
 *   - stagger delays are retired after the entrance, or every later hover lags
 *   - reduced motion is honored completely, including ::before/::after
 */

:root {
  --ease-out: cubic-bezier(.16, .84, .44, 1);
  --ease-soft: cubic-bezier(.4, 0, .2, 1);
  --motion-fast: 150ms;
  --motion-mid: 320ms;
  --motion-slow: 700ms;

  /* WhatsApp green: the channel's own brand, deliberately outside the palette */
  --wa: #25D366;
  --wa-pressed: #1da851;
}

html, body { overflow-x: hidden; overflow-x: clip; }
body { margin: 0; }

/* The quote form carries .ds-card, whose `display: flex` beats the browser's own
   [hidden] { display: none }, so a "hidden" form stayed on screen and the success
   card appeared below it instead of in its place. Any author display rule does this,
   so the guard is global. */
[hidden] { display: none !important; }
a { color: var(--color-link); }
a:hover { color: var(--color-link-pressed); }

:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: var(--radius-xs);
}

/* ----------------------------------------------------------- WhatsApp */
.wa-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: var(--control-height);
  padding: 0 26px;
  border-radius: var(--radius-full);
  background: var(--wa);
  color: #fff;
  font: var(--type-button-md);
  letter-spacing: .01em;
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--motion-fast) var(--ease-soft),
              transform var(--motion-fast) var(--ease-soft);
}
.wa-btn:hover { background: var(--wa-pressed); color: #fff; }
.wa-btn:active { transform: translateY(1px); }
.wa-btn--block { width: 100%; }

.wa-icon {
  display: grid;
  place-items: center;
  width: var(--control-height);
  height: var(--control-height);
  border-radius: var(--radius-full);
  color: var(--wa);
  transition: color var(--motion-fast) var(--ease-soft),
              transform var(--motion-fast) var(--ease-soft);
}
.wa-icon:hover { color: var(--wa-pressed); transform: scale(1.08); }

.wa-fab { display: none; }
@media (max-width: 720px) {
  .wa-fab {
    display: grid;
    place-items: center;
    position: fixed;
    right: 16px;
    bottom: 16px;
    z-index: 60;
    width: 58px;
    height: 58px;
    border-radius: var(--radius-full);
    background: var(--wa);
    color: #fff;
    box-shadow: var(--shadow-float);
    transition: transform var(--motion-mid) var(--ease-out);
  }
  .wa-fab:hover { color: #fff; }
  .wa-fab:active { transform: scale(.94); }
}

/* ---------------------------------------------------------------- nav */
/* On a phone the utility strip wraps to three lines and pushes the hero down for
   information the visitor already has: the drawer carries the call link, the hero says
   "or call", and the footer repeats both. Desktop keeps it. */
@media (max-width: 767px) {
  .ds-utility-strip { display: none; }
}

.ds-nav {
  transition: box-shadow var(--motion-mid) var(--ease-soft),
              background-color var(--motion-mid) var(--ease-soft);
}
.ds-nav.is-scrolled { box-shadow: var(--shadow-soft); }

/* Brand and links sit together on the left so the quote button can hold the right
   edge on its own. The design system puts `margin-right: auto` on the brand, which
   spread the links across the middle; this moves that spacer onto the link list. */
.ds-nav__brand { margin-right: auto; }
/* The nav row gaps its three children by --space-xl (24px), while the actions group
   gaps itself by --space-md (16px). Cancelling the row gap for the link list leaves
   "Contact Us" the same visual distance from the WhatsApp icon as that icon is from
   the quote button, once each element's own padding is counted. */
.ds-nav__links { margin-right: calc(var(--space-xl) * -1); }

/* The design system hides `.ds-nav__phone` below 1024px, which was right while the
   number sat in the header. It now also suppresses the call link INSIDE the drawer,
   so on a phone the menu offers no way to dial. Overridden here rather than in
   _ds/_ds_bundle.css, which is generated and would lose the change on the next sync. */
@media (max-width: 1023px) {
  #nav-drawer .ds-nav__phone { display: block; }
}

.nav-drawer {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  background: var(--color-canvas);
  border-bottom: 1px solid var(--color-hairline);
  box-shadow: var(--shadow-soft);
}
.nav-drawer__inner {
  display: grid;
  gap: var(--space-xs);
  padding-block: var(--space-md);
}
.js .nav-drawer {
  transform-origin: top;
  animation: drawer-in var(--motion-mid) var(--ease-out);
}
@keyframes drawer-in {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: none; }
}

/* --------------------------------------------------------- entrances */
/* Scoped to .js: without the script every element stays visible. */
.js .reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity var(--motion-slow) var(--ease-out),
              transform var(--motion-slow) var(--ease-out);
}
.js .reveal.in { opacity: 1; transform: none; }

/* Children arrive in sequence. Delay lives on the child, entrance on the parent. */
.js .stagger > * {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity var(--motion-slow) var(--ease-out),
              transform var(--motion-slow) var(--ease-out);
}
.js .stagger.in > * { opacity: 1; transform: none; }
.js .stagger.in > :nth-child(1) { transition-delay: 0ms; }
.js .stagger.in > :nth-child(2) { transition-delay: 80ms; }
.js .stagger.in > :nth-child(3) { transition-delay: 160ms; }
.js .stagger.in > :nth-child(4) { transition-delay: 240ms; }
.js .stagger.in > :nth-child(5) { transition-delay: 320ms; }
.js .stagger.in > :nth-child(6) { transition-delay: 400ms; }
.js .stagger.in > :nth-child(7) { transition-delay: 480ms; }
.js .stagger.in > :nth-child(8) { transition-delay: 560ms; }
/* Retire the delays once the entrance is done, or every later hover lags by them.
   Matches the nth-child specificity and wins with !important. */
.js .stagger.in.done > *:nth-child(n) { transition-delay: 0ms !important; }

/* Hero content arrives on load, not on scroll: it is already in view. */
.js .hero-in > * {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--motion-slow) var(--ease-out),
              transform var(--motion-slow) var(--ease-out);
}
.js .hero-in.in > * { opacity: 1; transform: none; }
.js .hero-in.in > :nth-child(1) { transition-delay: 60ms; }
.js .hero-in.in > :nth-child(2) { transition-delay: 160ms; }
.js .hero-in.in > :nth-child(3) { transition-delay: 260ms; }
.js .hero-in.in > :nth-child(4) { transition-delay: 360ms; }
.js .hero-in.in > :nth-child(5) { transition-delay: 460ms; }
.js .hero-in.in.done > *:nth-child(n) { transition-delay: 0ms !important; }

/* Float-stat chips pop rather than rise, so they read as applied labels. */
.js .ds-float-stat {
  opacity: 0;
  transform: scale(.92);
  transition: opacity var(--motion-mid) var(--ease-out),
              transform var(--motion-mid) var(--ease-out);
  transition-delay: 220ms;
}
.js .reveal.in .ds-float-stat,
.js .stagger.in .ds-float-stat { opacity: 1; transform: none; }

/* ------------------------------------------------------------ hovers */
.ds-card {
  transition: transform var(--motion-mid) var(--ease-out),
              box-shadow var(--motion-mid) var(--ease-out);
}
.ds-card:hover { transform: translateY(-4px); }
.ds-section--cloud .ds-card--flat:hover,
.ds-card--flat:hover { box-shadow: var(--shadow-soft); }

.ds-image-card { overflow: hidden; }
.ds-image-card__media {
  transition: transform 900ms var(--ease-out);
  will-change: transform;
}
.ds-image-card:hover .ds-image-card__media { transform: scale(1.05); }

.ds-btn {
  transition: background-color var(--motion-fast) var(--ease-soft),
              border-color var(--motion-fast) var(--ease-soft),
              color var(--motion-fast) var(--ease-soft),
              transform var(--motion-fast) var(--ease-soft);
}
.ds-btn:active { transform: translateY(1px); }

.ds-link { transition: color var(--motion-fast) var(--ease-soft); }
.ds-link--arrow::after { transition: transform var(--motion-fast) var(--ease-out); }
.ds-link--arrow:hover::after { transform: translateX(4px); }

.ds-nav__link::after { transition: transform var(--motion-mid) var(--ease-out); }

/* --------------------------------------------------------------- FAQ */
.ds-faq__item {
  transition: border-color var(--motion-fast) var(--ease-soft),
              box-shadow var(--motion-fast) var(--ease-soft);
}
.ds-faq__item:hover { border-color: var(--color-hairline-strong); }
.ds-faq__item[open] { box-shadow: var(--shadow-soft); }
.ds-faq__item > summary::after { transition: transform var(--motion-mid) var(--ease-out); }
.js .ds-faq__item[open] > .ds-faq__answer { animation: faq-in var(--motion-mid) var(--ease-out); }
@keyframes faq-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

/* -------------------------------------------------------- quote form */
/* Spam trap: off screen rather than display:none, which some bots detect and skip. */
.hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.js .quote-sent { animation: sent-in var(--motion-mid) var(--ease-out); }
@keyframes sent-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

/* --------------------------------------------- pause and reduced motion */
/* animation-play-state does not inherit, so name the descendants and pseudos. */
body.paused *,
body.paused *::before,
body.paused *::after { animation-play-state: paused !important; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }
  .js .reveal,
  .js .stagger > *,
  .js .hero-in > *,
  .js .ds-float-stat { opacity: 1 !important; transform: none !important; }
  .ds-card:hover { transform: none; }
  .ds-image-card:hover .ds-image-card__media { transform: none; }
}
