/* =====================================================================
   INTERACTIONS — every hover / mouse-over state on the site (#1001688),
   then press, focus, open/close and page-change motion (#1001689, part 2).
   Loaded on every page by base.njk, LAST of the core sheets, so a state
   here sits on top of the component's resting style.

   The three rules every state below follows:
   1. Hover lives inside @media (hover: hover). Phones and tablets never
      match it, so a tap can't leave a button lifted or a card raised.
   2. Every hover selector has a :focus-visible twin in the same rule, so a
      keyboard user sees exactly what a mouse user sees. (The focus RING
      from base.css is separate and always on, on every device.)
   3. Motion is tokens only: --dur-fast for colour, --dur for lift/shadow,
      --dur-slowest for photo zoom; --lift / --zoom (tokens.css §7) go to
      0 / 1 under prefers-reduced-motion, so the colour change stays and
      nothing moves. Only things you can click lift; static cards don't.

   Transitions live on the component (base/components/site-shell) or in
   animations.css §1 — this file only changes the "on" values.
   Docs: docs/COMPONENTS.md → "Hover & focus".
   ===================================================================== */

@media (hover: hover) {

  /* ---- Links: colour + a slightly heavier underline ---- */
  a:hover, a:focus-visible { color: var(--color-link-hover); text-decoration-thickness: 2px; }
  .section--dark a:hover, .section--dark a:focus-visible { color: var(--color-dark-accent); }
  .site-footer a:hover, .site-footer a:focus-visible { color: var(--color-night-accent); }
  .footer-col a:hover, .footer-col a:focus-visible { text-decoration: underline; }
  .contact-band__lines a:hover, .contact-band__lines a:focus-visible { text-decoration: underline; color: var(--color-dark-text); }
  .crumbs a:hover, .crumbs a:focus-visible { color: var(--color-link-hover); }
  .legal__toc-list a:hover, .legal__toc-list a:focus-visible { color: var(--color-link-hover); text-decoration: underline; text-underline-offset: 4px; }
  .wordmark:hover, .wordmark:focus-visible { color: var(--color-primary); }
  .site-footer .wordmark:hover, .site-footer .wordmark:focus-visible { color: var(--color-night-accent); }

  /* ---- Buttons: colour + a 2px lift + soft shadow; press settles back ---- */
  .btn:hover, .btn:focus-visible { transform: translateY(var(--lift)); box-shadow: var(--shadow-card); }
  .btn--primary:hover, .btn--primary:focus-visible { background: var(--color-primary-hover); color: var(--color-on-primary); }
  .btn--secondary:hover, .btn--secondary:focus-visible { border-color: var(--color-primary); background: var(--color-primary); color: var(--color-on-primary); }
  .btn--light:hover, .btn--light:focus-visible { background: var(--green-300); color: var(--color-on-light-btn); }
  .btn--ghost-light:hover, .btn--ghost-light:focus-visible { border-color: var(--color-night-accent); color: var(--color-night-text); }
  .btn--arrow:hover::after, .btn--arrow:focus-visible::after { transform: translateX(var(--shift-sm)); }
  /* On the dark bands a shadow reads as a smudge — lift only */
  :is(.section--dark, .cta--dark, .site-footer, .contact-band, .home-how) .btn:is(:hover, :focus-visible) { box-shadow: none; }

  .wa-float:hover, .wa-float:focus-visible { background: var(--color-primary-hover); color: var(--color-on-primary); transform: translateY(var(--lift)); }

  /* ---- Nav ---- */
  .site-nav__link:hover, .site-nav__link:focus-visible,
  .subnav a:hover, .subnav a:focus-visible { color: var(--color-primary); }
  :is(.nav-toggle, .subnav-toggle):is(:hover, :focus-visible) { border-color: var(--color-primary); color: var(--color-primary); }

  /* ---- Issue / service cards: lift + shadow, title goes green ----
     The whole card is the link (stretched title), so the card lifts when
     the pointer is anywhere on it or the title link has keyboard focus. */
  .issue-card:hover,
  .issue-card:has(.issue-card__link:focus-visible) { border-color: var(--color-border-strong); box-shadow: var(--shadow-card); transform: translateY(var(--lift)); }
  .issue-card:hover .issue-card__link,
  .issue-card:has(.issue-card__link:focus-visible) .issue-card__link { color: var(--color-primary); }
  .issue-card:hover .issue-card__cue,
  .issue-card:has(.issue-card__link:focus-visible) .issue-card__cue { color: var(--color-primary-hover); text-decoration-thickness: 2px; }

  /* ---- Pathway cards (#1002124): one-link cards lift like issue cards;
     two-link cards only colour the hovered/focused link ---- */
  .pathway--single:hover,
  .pathway--single:has(.pathway__link:focus-visible) { border-color: var(--color-border-strong); box-shadow: var(--shadow-card); transform: translateY(var(--lift)); }
  .pathway__link:hover,
  .pathway__link:focus-visible { color: var(--color-primary-hover); text-decoration-thickness: 2px; }
  .pathway--single:hover .pathway__link { color: var(--color-primary-hover); text-decoration-thickness: 2px; }

  /* ---- FAQ question, video pause button ---- */
  .faq__btn:hover, .faq__btn:focus-visible { color: var(--color-primary); }
  .hero__pause:hover, .hero__pause:focus-visible { background: var(--color-bg); border-color: var(--color-border-strong); }

  /* ---- Form fields (/book/): the outline firms up under the pointer ---- */
  .field input:not([type=radio]):not([type=checkbox]):hover,
  .field textarea:hover,
  .pill:hover { border-color: var(--color-primary); }
  .pill:hover { background: var(--color-surface-alt); }
  .pill:has(input:checked):hover { background: var(--color-surface-quiet); }

  /* ---- Photos: a slow, gentle zoom inside their rounded frame ----
     Not focusable (they aren't links), so there's no keyboard twin. */
  :is(.hero__photo, .about-split__frame):hover img { transform: scale(var(--zoom)); }
}

/* Desktop nav: a green underline grows under the link (the current page
   keeps its full underline). Mobile drawer keeps its dot. */
@media (min-width: 1280px) and (hover: hover) {
  .site-nav__link::after {
    content: "";
    position: absolute; left: 0; right: 0; bottom: 6px;
    height: 2px; border-radius: 2px;
    background: var(--color-primary);
    transform: scaleX(0); transform-origin: left center;
    transition: transform var(--dur) var(--ease);
  }
  .site-nav__link:hover::after, .site-nav__link:focus-visible::after,
  .site-nav__link[aria-current]::after { transform: none; }
  .subnav a:hover, .subnav a:focus-visible { background: var(--color-surface-alt); color: var(--color-heading); }
}

/* Transitions for the pieces above that have none of their own (buttons,
   links and fields already get one from animations.css §1) */
.hero__photo img, .about-split__frame img { transition: transform var(--dur-slowest) var(--ease); }
.pill { transition: border-color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease), transform var(--dur-instant) var(--ease); }

/* =====================================================================
   PART 2 — PRESS, FOCUS, OPEN/CLOSE + PAGE CHANGES (#1001689)
   Same rules as above: tokens only (every one goes to 0 / 1 under
   prefers-reduced-motion), transform + opacity only, nothing that shifts
   layout. One motion "voice" for the whole site:
     · press            → --dur-instant squeeze (--press)
     · state change     → --dur, --ease (menus, dropdowns, accordions)
     · page change      → old page fades out in --dur; the new page's own
                          hero entrance (animations.css §6) is the "in"
   Photo bands (#1001683) and the hero video (#1001682) are deliberately
   left still here — the video's own slow fade is the only background
   motion on a page, so nothing competes with it.
   Docs: docs/COMPONENTS.md → "Transitions & micro-interactions".
   ===================================================================== */

/* ---- Press: a small squeeze on every device (touch has no hover, so this
   is the only feedback a phone gets). Sits after the hover block and wins
   the tie, so a pressed button drops its lift + shadow too. ---- */
.btn:active, .wa-float:active, .pill:active, .subnav-toggle:active, .nav-toggle:active, .hero__pause:active {
  transform: scale(var(--press));
  box-shadow: none;
  transition-duration: var(--dur-instant);
}

/* ---- Form focus: the label picks up the field's green as you enter it ---- */
.field > label, .field > legend { transition: color var(--dur-fast) var(--ease); }
.field:focus-within > label,
.enquiry__choice:focus-within > legend { color: var(--color-primary); }
.field--check:focus-within > label { color: var(--color-text); }
/* A new error message eases in rather than snapping (replays each time it's shown) */
.field__error:not([hidden]) { animation: otil-fade-in var(--dur) var(--ease-out); }

/* ---- Submit / loading (enquiry form) ----
   JS adds .is-sending + aria-busy and swaps the label to "Sending…"; the
   arrow turns into a small spinner. Reduced motion: the net in
   animations.css §5 stops the spin, leaving a still ring + the label. */
@keyframes otil-spin { to { transform: rotate(1turn); } }
.enquiry.is-sending .btn--arrow::after {
  -webkit-mask: none; mask: none;
  background: none;
  border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%;
  width: 16px; height: 16px;
  animation: otil-spin var(--dur-slower) var(--ease-linear) infinite;
}
@media (prefers-reduced-motion: reduce) {
  .enquiry.is-sending .btn--arrow::after { border-right-color: currentColor; opacity: 0.6; }
}
/* The result message arrives with the site's standard entrance */
.enquiry__status.is-new { animation: otil-fade-up var(--dur-slow) var(--ease-out); }

/* ---- Open / close ----
   Drawer + hamburger morph: site-shell.css. FAQ accordion: height slide
   in js/components.js (reads --dur / --ease). Counselling dropdown: fades
   and drops in on open, both in the drawer and on desktop. */
@media (prefers-reduced-motion: no-preference) {   /* reduced: not even a 1ms blank frame */
  .js .has-sub .subnav { transition: opacity var(--dur) var(--ease), translate var(--dur) var(--ease); }
  @starting-style {
    .js .has-sub .subnav { opacity: 0; translate: 0 calc(var(--shift-sm) * -1); }
  }
}
.faq__a.is-sliding { overflow: clip; }
/* Video pause ↔ play icon swaps with a small scale-in */
.hero__pause svg { animation: otil-scale-in var(--dur) var(--ease-out); }

/* ---- In-page anchors ----
   Smooth scroll + header offset live in base.css (html). The section you
   land on gets a soft wash that fades, so the eye finds it — legal
   clauses and deep-linked FAQ answers. */
@keyframes otil-target { from { background-color: var(--color-primary-wash); } }
:is(.legal__item, .faq__a):target {
  animation: otil-target var(--dur-slowest) var(--ease-in-out) var(--dur) both;
  border-radius: var(--radius-sm);
}

/* ---- Page to page ----
   Same-site navigations cross-fade (View Transitions, Chrome/Edge/Safari
   18.2+; other browsers just load the page as before). Only the old page
   animates — it fades out in --dur — so the new page's hero entrance is the
   single "arrival" motion, not a second fade on top of it. Off entirely
   under reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
  ::view-transition-old(root) { animation: otil-fade-out var(--dur) var(--ease-in) both; }
  ::view-transition-new(root) { animation: none; }
}

/* =====================================================================
   PART 3 — AMBIENT LOOPS (#1001694, Mike's homepage feedback)
   Two slow, quiet loops, both motion-only (nothing at all under reduced
   motion — not even the 1ms net frame):
     · primary buttons breathe: a soft ring spreads out and fades, then a
       long rest. It stops while the button is hovered, focused, pressed
       or sending, so it never fights the lift / press / spinner.
     · the contact band's arcs ripple outwards, one ring after another.
   Both sit well away from the hero video's own motion (the only other
   loop), and use transform / opacity / box-shadow on a pseudo-element or
   decoration only, so nothing shifts layout.
   ===================================================================== */
@keyframes otil-pulse {
  0%        { box-shadow: 0 0 0 0 color-mix(in srgb, var(--color-primary) 45%, transparent); }
  45%, 100% { box-shadow: 0 0 0 var(--pulse-ring) color-mix(in srgb, var(--color-primary) 0%, transparent); }
}
@keyframes otil-ripple {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.45; transform: scale(1.035); }
}
@keyframes otil-ripple-soft {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.6; transform: scale(1.025); }
}
@media (prefers-reduced-motion: no-preference) {
  .btn--primary { position: relative; }
  .btn--primary::before {
    content: ""; position: absolute; inset: calc(-1 * var(--border-w)); border-radius: inherit; pointer-events: none;
    animation: otil-pulse var(--dur-pulse) var(--ease-out) infinite;
  }
  /* On the deep-green bands the ring is sage, so it shows against green */
  :is(.section--dark, .contact-band, .cta--dark) .btn--primary::before { --color-primary: var(--green-300); }
  .btn--primary:is(:hover, :focus-visible, :active)::before,
  .btn--primary[aria-busy="true"]::before,
  .btn--primary:disabled::before,
  .is-sending .btn--primary::before { animation: none; }

  /* EVERY band's background arcs ripple softly (#1001708, Mike: "vectors
     in background on all sections should animate subtly"). One rule for
     any `.arcs` svg: each ring scales about its own centre (fill-box, so
     whichever corner the arcs sit in), rings offset by --ring. */
  .arcs circle {
    transform-box: fill-box; transform-origin: center;
    animation: otil-ripple-soft calc(var(--dur-drift) * 1.4) var(--ease-in-out)
      calc(var(--dur-drift) * 0.14 * var(--ring, 0)) infinite;
  }
  .arcs circle:nth-child(2) { --ring: 1; }
  .arcs circle:nth-child(3) { --ring: 2; }
  .arcs circle:nth-child(4) { --ring: 3; }
  .arcs circle:nth-child(5) { --ring: 4; }
  .arcs circle:nth-child(6) { --ring: 5; }
  /* Privacy hero drawing (#1002630): its rings ripple the same way */
  .hero__decor-rings circle {
    transform-box: fill-box; transform-origin: center;
    animation: otil-ripple-soft calc(var(--dur-drift) * 1.4) var(--ease-in-out)
      calc(var(--dur-drift) * 0.14 * var(--ring, 0)) infinite;
  }
  .hero__decor-rings circle:nth-child(2) { --ring: 1; }
  .hero__decor-rings circle:nth-child(3) { --ring: 2; }
  /* The contact band keeps its slightly stronger, quicker ripple */
  .contact-band__arcs circle {
    animation: otil-ripple var(--dur-drift) var(--ease-in-out) calc(var(--dur-drift) * 0.1 * var(--ring, 0)) infinite;
  }
  /* Split-hero arcs: the entrance ring-in (animations.css) plays first,
     then the soft ripple takes over once every ring has landed. */
  .hero__arcs circle {
    animation:
      otil-hero-ring var(--dur-slowest) var(--ease-out) calc(var(--stagger) * 4 + var(--anim-delay, 0ms)) backwards,
      otil-ripple-soft calc(var(--dur-drift) * 1.4) var(--ease-in-out)
        calc(var(--stagger) * 10 + var(--dur-slowest) + var(--dur-drift) * 0.14 * var(--ring, 0)) infinite;
  }
  /* The how-I-work cards' corner rings (a CSS gradient, not an svg)
     breathe from their top-right corner on the same slow beat. */
  .home-how__card::after {
    transform-origin: 100% 0;
    animation: otil-ripple-soft calc(var(--dur-drift) * 1.4) var(--ease-in-out) infinite;
  }
  .home-how__card:nth-child(2)::after { animation-delay: calc(var(--dur-drift) * 0.3); }
  .home-how__card:nth-child(3)::after { animation-delay: calc(var(--dur-drift) * 0.6); }

  /* Scroll reveal distances (#1001694): Brian's portrait slides in from
     the left; the footer wordmark rises a good way up into place. */
  .about-split__media.anim-fade-right { --shift: calc(var(--shift-lg) * 2.5); }
  .footer-sign__word.anim-fade-up { --shift: 0.5em; --anim-dur: var(--dur-slowest); }
}
