/* ==========================================================================
   Subhchintak Global Services — motion layer
   Loaded after style.css so it can refine, never fight, the design system.
   Rules here move only transform/opacity; paint-only properties (border,
   box-shadow, colour) are the sole exceptions and never affect layout.
   1. Tokens              4. Reveal variants
   2. Header / nav        5. Cards & sections
   3. Form fields         6. Micro-interactions
                          7. Reduced motion
   ========================================================================== */

/* 1. Tokens ============================================================== */

:root {
  /* Built the same way as the --sh-* scale in style.css: navy-900 at low
     alpha. A dedicated step because --sh-sm is too flat for a stuck header
     and --sh-md too heavy for a 1px-bordered bar. */
  --sh-header: 0 4px 18px rgba(6, 32, 67, .08);

  --dur-fast: .18s;
  --dur-base: .24s;
  --dur-slow: .6s;
}

/* 2. Header / nav ======================================================== */

/* backdrop-filter is deliberately absent from the transition list — blurring
   a full-width bar repaints on every scroll frame, and the 14px→18px step is
   imperceptible anyway. Only the cheap properties animate. */
.header {
  transition: box-shadow .3s var(--ease), background-color .3s var(--ease);
}
.header.is-stuck {
  backdrop-filter: saturate(190%) blur(18px);
  box-shadow: var(--sh-header);
}

/* -- Nav underline ------------------------------------------------------ */
/* Desktop only: below 961px the nav becomes an off-canvas accordion and
   style.css already hides the active underline there. */
@media (min-width: 961px) {
  /* Same geometry as the .is-active underline in style.css, so hover and
     active read as one system rather than two competing treatments. */
  .nav__link::after {
    content: "";
    position: absolute;
    left: 11px;
    right: 11px;
    bottom: 2px;
    height: 2px;
    border-radius: 2px;
    background: var(--teal-500);
    transform: scaleX(0);
    transform-origin: center;
    transition: transform var(--dur-base) var(--ease);
  }
  .nav__link:hover::after,
  .nav__link:focus-visible::after { transform: scaleX(1); }

  /* style.css draws this underline but sets no transform, so the base rule
     above would otherwise collapse it to nothing. */
  .nav__link.is-active::after { transform: scaleX(1); }

  /* Transform trails opacity slightly — the panel settles instead of snapping. */
  .dropdown {
    transition: opacity var(--dur-fast) var(--ease), transform var(--dur-base) var(--ease), visibility var(--dur-base);
  }
}

/* The CTA already lifts on hover; give the keyboard the same affordance. */
.nav__cta .btn:focus-visible {
  transform: translateY(-2px);
  box-shadow: var(--sh-md);
}

/* 3. Form fields ========================================================= */

.input, .textarea, .select {
  transition: border-color var(--dur-base) var(--ease), box-shadow var(--dur-base) var(--ease);
}
.input:focus, .textarea:focus, .select:focus {
  border-color: var(--teal-500);
  box-shadow: 0 0 0 4px rgba(20, 149, 143, .14);
}

/* A 1px lift is enough to make the focused row read as "live" without the
   surrounding fields appearing to shuffle. */
.field { transition: transform var(--dur-base) var(--ease); }
.field:focus-within { transform: translateY(-1px); }

.field__label { transition: color var(--dur-base) var(--ease); }
.field:focus-within .field__label { color: var(--teal-500); }

/* One pass, no fill: the animation must not leave a transform behind, or it
   would permanently override the focus-within lift above. */
.field--error { animation: fieldShake .42s var(--ease) 1; }

@keyframes fieldShake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-5px); }
  40% { transform: translateX(4px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(2px); }
}

/* -- Submit states (classes toggled by main.js) ------------------------- */

.btn.is-loading {
  opacity: .72;
  pointer-events: none;
}
.btn.is-loading::after {
  content: "";
  flex: none;
  width: 15px;
  height: 15px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: var(--r-full);
  animation: btnSpin .62s linear infinite;
}
@keyframes btnSpin { to { transform: rotate(1turn); } }

.btn.is-success {
  --btn-bg: var(--teal-500);
  --btn-fg: #fff;
  --btn-bd: var(--teal-500);
}
.btn.is-success::after { content: none; }

/* 4. Reveal variants ===================================================== */

/* Gated on .js exactly like the base .reveal rule in style.css — without the
   gate a failed script would blank every opted-in block. main.js applies the
   stagger with setTimeout, so no transition-delay is declared here; adding
   one would compound with the JS delay. */
.js .reveal--up,
.js .reveal--left,
.js .reveal--right,
.js .reveal--zoom,
.js .reveal--fade {
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease);
}

.js .reveal--up { transform: translateY(24px); }
.js .reveal--left { transform: translateX(-28px); }
.js .reveal--right { transform: translateX(28px); }
.js .reveal--zoom { transform: scale(.96); }
.js .reveal--fade { transform: none; }

.js .reveal--up.is-in,
.js .reveal--left.is-in,
.js .reveal--right.is-in,
.js .reveal--zoom.is-in,
.js .reveal--fade.is-in {
  opacity: 1;
  transform: none;
}

/* 5. Cards & sections ==================================================== */

/* Scoped to real pointers: style.css deliberately neutralises hover lifts on
   touch (they stick after a tap) and this layer must not undo that. */
@media (hover: hover) and (pointer: fine) {
  .svc-card, .dest-card, .feat, .quote-card, .board-card, .bento__card {
    transition: transform .28s var(--ease), box-shadow .28s var(--ease), border-color .28s var(--ease);
  }

  .svc-card:hover,
  .dest-card:hover,
  .quote-card:hover,
  .board-card:hover,
  .bento__card:hover {
    transform: translateY(-4px);
    box-shadow: var(--sh-md);
  }

  /* Image tiles carry a deeper shadow so they lift off the grid convincingly. */
  .feat:hover {
    transform: translateY(-4px);
    box-shadow: var(--sh-lg);
  }
}

/* .section-title is intentionally left alone. Section headings are already
   wrapped in .reveal on every page, so animating the title itself would run a
   second entrance on top of the first. */

/* 6. Micro-interactions ================================================== */

@media (hover: hover) and (pointer: fine) {
  /* Mirrors the scale(.985) tap feedback style.css gives coarse pointers. */
  .btn:active { transform: translateY(0) scale(.97); }
}

/* Keyboard parity with .link-arrow:hover */
.link-arrow:focus-visible .icon { transform: translateX(4px); }

/* 7. Reduced motion ====================================================== */
/* Neutralises everything introduced above and leaves all content visible.
   style.css clamps durations globally; this block removes the movement
   itself, which a near-zero duration alone does not do. */

@media (prefers-reduced-motion: reduce) {
  .header,
  .nav__link::after,
  .dropdown,
  .input, .textarea, .select,
  .field, .field__label,
  .svc-card, .dest-card, .feat, .quote-card, .board-card, .bento__card,
  .btn,
  .link-arrow .icon {
    transition: none;
  }

  .field--error { animation: none; }
  .field:focus-within { transform: none; }

  .btn.is-loading::after { animation: none; }
  .btn:active,
  .nav__cta .btn:focus-visible { transform: none; }

  .svc-card:hover,
  .dest-card:hover,
  .feat:hover,
  .quote-card:hover,
  .board-card:hover,
  .bento__card:hover { transform: none; }

  .link-arrow:focus-visible .icon { transform: none; }

  .js .reveal--up,
  .js .reveal--left,
  .js .reveal--right,
  .js .reveal--zoom,
  .js .reveal--fade {
    opacity: 1;
    transform: none;
    transition: none;
  }
}
