/* ==========================================================================
   Greensnake — the button system
   --------------------------------------------------------------------------
   ONE component. Every button on the site is `.btn` plus, at most, a variant
   and a size. Nothing here is styled by where it happens to sit.

   ------------------------------------------------------------------------
   THE FEEL
   ------------------------------------------------------------------------
   The circular disc stays — it is the most recognisable thing about this
   brand's buttons. Everything around it was slowed down and quietened.

   The previous version ran four effects at once on every hover: a colour
   wipe scaling 12x, the label swapping for a second copy, the arrow flying
   out while another flew in, and a magnetic pull. Individually clever;
   together, loud. It read as a demo of transitions rather than as a control.

   This version commits to one idea instead: THE DISC WAKES UP.

     · The pill deepens by one step. It does not flip to another colour.
     · The disc grows a little, warms to the accent, and lifts.
     · The arrow glides a few pixels and settles. It does not leave.
     · The whole button rises 1px on a soft, wide shadow.

   Timing is deliberately asymmetric, because that is what separates "calm"
   from "sluggish":

     hover in   520-620ms   slow, so it feels like a considered response
     hover out  340ms       quicker, so the button never feels sticky
     press      110ms       immediate — this is the one that says "clickable"

   Nothing overshoots. No bounce curve, no spring, no scale beyond 1.06.
   `--ease-soft` is a gentle deceleration with no undershoot at either end.

   ------------------------------------------------------------------------
   WHY IT READS AS PRESSABLE AT REST
   ------------------------------------------------------------------------
   A flat pill on a flat page gives the eye nothing to act on, so this one
   carries three quiet resting cues before any interaction happens:

     1. a soft, wide, low-opacity shadow — it sits ON the page, not IN it
     2. a 1px top inner highlight — a lit edge, the way a physical key has
     3. the disc, which is a different material from the pill around it

   ------------------------------------------------------------------------
   THE HIERARCHY — pick by intent, not by looks
   ------------------------------------------------------------------------
     Primary      .btn                the one action a screen is asking for.
                                      At most one per view.
     Secondary    .btn--secondary     the credible alternative. Outlined,
                                      same footprint, less weight.
     Ghost        .btn--ghost         for dark or image-backed panels.
     Text         .btn--text          low commitment: "read more", "skip".
     Icon         .btn-icon           utility only — close, next, menu, play.
                                      Always carries a visually-hidden label;
                                      an icon is not a name.

   Colour variants (--ink, --yellow, --light, --yellow-disc) sit alongside
   the hierarchy and only re-point the custom properties below. They never
   change size, weight or interaction.

   STATES — all six are defined, because a state that isn't defined is a
   state that gets improvised later:
   default · hover · active · focus-visible · disabled · loading

   ------------------------------------------------------------------------
   MARKUP
   ------------------------------------------------------------------------
     <a class="btn" href="...">
       <span class="btn__label"><span>Book a call</span></span>
       <span class="btn__arrow" aria-hidden="true">
         <svg><use href="#i-arrow"/></svg>
       </span>
     </a>

   A second <span> inside the label and a second <svg> inside the arrow are
   both optional. They only do anything on `.btn--swap`, where the label
   crossfades to different wording on hover — worth it on one or two hero
   CTAs, noise everywhere else. Without `--swap` they are simply ignored, so
   existing markup keeps working untouched.

   `.btn--bare` drops the arrow disc entirely.
   ========================================================================== */

.btn {
  /* ---- the eight properties every variant re-points ---- */
  /* --olive at 14px white text is 4.07:1 — under AA. The primary therefore
     rests on --olive-deep (5.2:1) and hovers to --olive-deeper (7.1:1).
     --olive itself is untouched and still the brand accent everywhere else. */
  --btn-bg:            var(--olive-deep);
  --btn-fg:            var(--white);
  --btn-bg-hover:      var(--olive-deeper);
  --btn-fg-hover:      var(--white);
  --btn-disc-bg:       var(--cream);
  --btn-disc-fg:       var(--olive-deep);
  --btn-disc-bg-hover: var(--lime);
  --btn-disc-fg-hover: var(--green-900);

  /* ---- feel ---- */
  --btn-ease: var(--ease-soft);
  --btn-in:   560ms;   /* hover in  — slow */
  --btn-out:  340ms;   /* hover out — quicker, never sticky */
  --btn-glow: rgba(13, 13, 57, 0.16);

  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  height: 52px;
  padding: 5px 5px 5px 26px;
  border-radius: var(--radius-pill);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: var(--font-ui);
  font-weight: 500;
  font-size: 14px;
  line-height: 1.2;
  letter-spacing: -0.02em;
  white-space: nowrap;
  isolation: isolate;

  /* Resting cues 1 and 2: a wide soft shadow, and a lit top edge. */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.16),
    0 1px 2px rgba(13, 13, 57, 0.07),
    0 6px 16px -6px var(--btn-glow);

  transform: translate3d(var(--btn-mx, 0), var(--btn-my, 0), 0);
  transition:
    background-color var(--btn-out) var(--btn-ease),
    color            var(--btn-out) var(--btn-ease),
    box-shadow       var(--btn-out) var(--btn-ease),
    transform        220ms var(--btn-ease);
}

/* ---------- hover: slow in ---------- */
.btn:hover,
.btn:focus-visible {
  background-color: var(--btn-bg-hover);
  color: var(--btn-fg-hover);
  transition-duration: var(--btn-in), var(--btn-in), var(--btn-in), 320ms;
  /* the lift: 1px, and a shadow that spreads rather than darkens */
  transform: translate3d(var(--btn-mx, 0), calc(var(--btn-my, 0px) - 1px), 0);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.2),
    0 2px 4px rgba(13, 13, 57, 0.07),
    0 14px 30px -12px var(--btn-glow);
}

/* ---------- press: fast, and it settles back down ----------
   110ms is the whole point. Hover can afford to be slow because nobody is
   waiting on it; a press cannot, because the press IS the feedback. */
.btn:active {
  transform: translate3d(var(--btn-mx, 0), 1px, 0) scale(0.985);
  transition-duration: 110ms;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.12),
    0 1px 1px rgba(13, 13, 57, 0.10),
    0 2px 6px -4px var(--btn-glow);
}

/* ==========================================================================
   The label
   --------------------------------------------------------------------------
   Static by default. It travels 2px toward the disc on hover — just enough
   to feel connected to the movement, not enough to read as an animation.
   ========================================================================== */
.btn__label {
  position: relative;
  display: grid;
  transition: transform var(--btn-out) var(--btn-ease);
}
.btn:hover .btn__label,
.btn:focus-visible .btn__label {
  transform: translateX(-2px);
  transition-duration: var(--btn-in);
}

.btn__label > span { grid-area: 1 / 1; }
/* The hover copy only exists on .btn--swap; elsewhere it is inert. */
.btn__label > span:last-child:not(:first-child) { display: none; }

/* ---------- opt-in: the label crossfades to different wording ---------- */
.btn--swap .btn__label { overflow: hidden; height: 1.2em; }
.btn--swap .btn__label > span:last-child:not(:first-child) { display: block; }
.btn--swap .btn__label > span {
  transition: transform var(--btn-in) var(--btn-ease),
              opacity 300ms var(--btn-ease);
}
.btn--swap .btn__label > span:last-child { transform: translateY(105%); opacity: 0; }
.btn--swap:hover .btn__label > span:first-child,
.btn--swap:focus-visible .btn__label > span:first-child { transform: translateY(-105%); opacity: 0; }
.btn--swap:hover .btn__label > span:last-child,
.btn--swap:focus-visible .btn__label > span:last-child { transform: none; opacity: 1; }
.btn--swap:hover .btn__label,
.btn--swap:focus-visible .btn__label { transform: none; }

/* ==========================================================================
   The disc — the one thing that actually performs
   ========================================================================== */
.btn__arrow {
  position: relative;
  flex: none;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: var(--btn-disc-bg);
  color: var(--btn-disc-fg);
  transition:
    background-color var(--btn-out) var(--btn-ease),
    color            var(--btn-out) var(--btn-ease),
    transform        var(--btn-out) var(--btn-ease),
    box-shadow       var(--btn-out) var(--btn-ease);
}

/* A halo that blooms out of the disc. It is a shadow, not a scaling element,
   so it costs nothing and cannot clip against the pill's rounded edge. */
.btn__arrow::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  box-shadow: 0 0 0 0 var(--btn-disc-bg-hover);
  opacity: 0;
  transition: box-shadow var(--btn-in) var(--btn-ease),
              opacity var(--btn-in) var(--btn-ease);
}

.btn:hover .btn__arrow,
.btn:focus-visible .btn__arrow {
  background-color: var(--btn-disc-bg-hover);
  color: var(--btn-disc-fg-hover);
  transform: scale(1.06);
  transition-duration: var(--btn-in);
}
.btn:hover .btn__arrow::before,
.btn:focus-visible .btn__arrow::before {
  box-shadow: 0 0 0 7px var(--btn-disc-bg-hover);
  opacity: 0.16;
}
.btn:active .btn__arrow {
  transform: scale(0.97);
  transition-duration: 110ms;
}

/* ---------- the glyph: it glides, it does not leave ---------- */
.btn__arrow svg {
  grid-area: 1 / 1;
  width: 22px;
  height: 15px;
  transition: transform var(--btn-out) var(--btn-ease);
}
/* the second glyph is legacy markup — inert unless .btn--swap wants it */
.btn__arrow svg:last-child:not(:first-child) { display: none; }

.btn:hover .btn__arrow svg,
.btn:focus-visible .btn__arrow svg {
  transform: translateX(3px);
  transition-duration: var(--btn-in);
}

/* ==========================================================================
   Focus
   --------------------------------------------------------------------------
   The hover choreography alone is not a focus indicator — it reads as decor,
   not as "you are here". A real ring, offset far enough to clear the shadow.
   Blue on light grounds; on dark ones only lime survives #021f11 at 3:1, so
   the ring colour is a variable rather than a constant.
   ========================================================================== */
.btn:focus-visible,
.btn-icon:focus-visible {
  outline: 2px solid var(--btn-ring, var(--blue-assist));
  outline-offset: 3px;
}

.on-dark .btn,
.on-dark .btn-icon,
.btn--light,
.btn--ghost,
.btn--yellow-disc { --btn-ring: var(--lime); }

/* ==========================================================================
   Colour variants
   --------------------------------------------------------------------------
   Every one moves by ONE step on hover — a deepening, never a flip. That is
   the whole reason the hover feels soft: the eye is not asked to re-read the
   button as a different object.
   ========================================================================== */

/* navy label on the brand olive. Kept for continuity with the original
   build; 4.55:1, so it passes AA but has no headroom — do not shrink the
   label below 14px on it, and prefer --secondary for a genuine alternative
   action. */
.btn--ink {
  --btn-bg: var(--olive);
  --btn-fg: var(--navy);
  --btn-bg-hover: var(--lime);
  --btn-fg-hover: var(--green-900);
  --btn-disc-bg: var(--green-900);
  --btn-disc-fg: var(--lime);
  --btn-disc-bg-hover: var(--green-900);
  --btn-disc-fg-hover: var(--lime);
}

/* yellow pill, e.g. "Book Free Call", "Join Greensnake" */
.btn--yellow {
  --btn-bg: var(--yellow);
  --btn-fg: var(--green-900);
  --btn-bg-hover: var(--lime);
  --btn-fg-hover: var(--green-900);
  --btn-disc-bg: var(--green-900);
  --btn-disc-fg: var(--yellow);
  --btn-disc-bg-hover: var(--green-900);
  --btn-disc-fg-hover: var(--lime);
  --btn-glow: rgba(120, 133, 8, 0.5);
}

/* pale pill on a dark ground, e.g. "Start case review", "See more FAQ" */
.btn--light {
  --btn-bg: var(--cream);
  --btn-fg: var(--olive-deep);
  --btn-bg-hover: var(--white);
  --btn-fg-hover: var(--green-900);
  --btn-disc-bg: var(--olive);
  --btn-disc-fg: var(--cream);
  --btn-disc-bg-hover: var(--green-900);
  --btn-disc-fg-hover: var(--lime);
  --btn-glow: rgba(0, 0, 0, 0.5);
}

/* white pill with a yellow disc, e.g. the community CTA */
.btn--yellow-disc {
  --btn-bg: var(--white);
  --btn-fg: var(--olive-deep);
  --btn-bg-hover: var(--cream);
  --btn-fg-hover: var(--green-900);
  --btn-disc-bg: var(--yellow);
  --btn-disc-fg: var(--green-900);
  --btn-disc-bg-hover: var(--olive);
  --btn-disc-fg-hover: var(--white);
  --btn-glow: rgba(0, 0, 0, 0.45);
}

/* outline treatment for dark, image-backed panels */
.btn--ghost {
  --btn-bg: rgba(255, 255, 255, 0.07);
  --btn-fg: var(--white);
  --btn-bg-hover: rgba(255, 255, 255, 0.14);
  --btn-fg-hover: var(--white);
  --btn-disc-bg: rgba(255, 255, 255, 0.9);
  --btn-disc-fg: var(--green-900);
  --btn-disc-bg-hover: var(--lime);
  --btn-disc-fg-hover: var(--green-900);
  --btn-glow: rgba(0, 0, 0, 0.5);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.28),
    inset 0 1px 0 rgba(255, 255, 255, 0.16);
  backdrop-filter: blur(10px);
}
.btn--ghost:hover,
.btn--ghost:focus-visible {
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.4),
    inset 0 1px 0 rgba(255, 255, 255, 0.2),
    0 14px 30px -12px var(--btn-glow);
}

/* label-only button (no arrow disc) */
.btn--bare { padding-inline: 26px; }
.btn--bare .btn__arrow { display: none; }

/* ==========================================================================
   Secondary — the credible alternative
   --------------------------------------------------------------------------
   Same footprint as primary, so a pair sits on one baseline, but it reads as
   an outline until you touch it. It gains a surface on hover rather than a
   saturated fill, so it never competes with the primary beside it.
   ========================================================================== */
.btn--secondary {
  --btn-bg: transparent;
  --btn-fg: var(--navy);
  --btn-bg-hover: rgba(13, 13, 57, 0.05);
  --btn-fg-hover: var(--navy);
  --btn-disc-bg: rgba(13, 13, 57, 0.07);
  --btn-disc-fg: var(--navy);
  --btn-disc-bg-hover: var(--olive);
  --btn-disc-fg-hover: var(--white);
  --btn-glow: rgba(13, 13, 57, 0.10);
  box-shadow: inset 0 0 0 1.5px rgba(13, 13, 57, 0.18);
}
.btn--secondary:hover,
.btn--secondary:focus-visible {
  box-shadow:
    inset 0 0 0 1.5px rgba(13, 13, 57, 0.3),
    0 10px 24px -14px var(--btn-glow);
}
.btn--secondary:active { box-shadow: inset 0 0 0 1.5px rgba(13, 13, 57, 0.3); }

/* the same idea, inverted, for dark sections */
.on-dark .btn--secondary,
.btn--secondary-dark {
  --btn-fg: var(--on-dark);
  --btn-bg-hover: rgba(255, 255, 255, 0.07);
  --btn-fg-hover: var(--white);
  --btn-disc-bg: rgba(255, 255, 255, 0.1);
  --btn-disc-fg: var(--on-dark);
  --btn-disc-bg-hover: var(--lime);
  --btn-disc-fg-hover: var(--green-900);
  --btn-glow: rgba(0, 0, 0, 0.6);
  box-shadow: inset 0 0 0 1.5px var(--on-dark-line);
}
.on-dark .btn--secondary:hover,
.on-dark .btn--secondary:focus-visible,
.btn--secondary-dark:hover,
.btn--secondary-dark:focus-visible {
  box-shadow:
    inset 0 0 0 1.5px rgba(255, 255, 255, 0.28),
    0 10px 24px -14px var(--btn-glow);
}

/* ==========================================================================
   Text — lowest commitment. No pill, no disc, no shadow.
   ========================================================================== */
.btn--text {
  --btn-bg: transparent;
  --btn-bg-hover: transparent;
  --btn-fg: var(--navy);
  --btn-fg-hover: var(--olive-deep);
  height: auto;
  padding: 6px 2px;
  gap: 7px;
  border-radius: var(--radius-xs);
  box-shadow: none;
  color: var(--btn-fg);
}
.btn--text:hover,
.btn--text:focus-visible { box-shadow: none; transform: none; }
.btn--text:active { transform: none; box-shadow: none; }
.btn--text .btn__label { overflow: visible; height: auto; }
.btn--text:hover .btn__label { transform: none; }

/* the underline draws in from the left rather than switching on */
.btn--text .btn__label > span:first-child {
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 1.5px;
  transition: background-size var(--btn-in) var(--btn-ease);
}
.btn--text:hover .btn__label > span:first-child,
.btn--text:focus-visible .btn__label > span:first-child { background-size: 100% 1.5px; }

.btn--text .btn__arrow {
  width: auto;
  height: auto;
  background: none;
  color: currentColor;
  box-shadow: none;
}
.btn--text .btn__arrow::before { display: none; }
.btn--text .btn__arrow svg { width: 17px; height: 12px; }
.btn--text:hover .btn__arrow,
.btn--text:focus-visible .btn__arrow { transform: none; }
.on-dark .btn--text { --btn-fg: var(--on-dark); --btn-fg-hover: var(--lime); }

/* ==========================================================================
   Icon button
   --------------------------------------------------------------------------
   Utility interactions only: close, next/previous, open menu, play. A real
   component rather than a dozen one-off buttons, so the hit area, the focus
   ring and the press feedback are identical everywhere.

     <button class="btn-icon" type="button">
       <span class="visually-hidden">Close menu</span>
       <svg aria-hidden="true"><use href="#i-close"/></svg>
     </button>

   The 44px floor is not decorative — it is the smallest target reliably
   hittable with a thumb.
   ========================================================================== */
.btn-icon {
  --icon-bg: transparent;
  --icon-fg: var(--navy);
  --icon-bg-hover: rgba(13, 13, 57, 0.06);
  --icon-fg-hover: var(--navy);
  --icon-ring: rgba(13, 13, 57, 0.14);

  position: relative;
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 50%;
  background: var(--icon-bg);
  color: var(--icon-fg);
  box-shadow: inset 0 0 0 1px var(--icon-ring);
  cursor: pointer;
  transition:
    background-color var(--t-slow) var(--ease-soft),
    color            var(--t-slow) var(--ease-soft),
    box-shadow       var(--t-slow) var(--ease-soft),
    transform        180ms var(--ease-soft);
}
.btn-icon svg { width: 18px; height: 18px; pointer-events: none; }
.btn-icon:hover {
  background-color: var(--icon-bg-hover);
  color: var(--icon-fg-hover);
  box-shadow: inset 0 0 0 1px transparent;
}
.btn-icon:active { transform: scale(0.94); transition-duration: 100ms; }

.btn-icon--sm { width: 36px; height: 36px; }
.btn-icon--sm svg { width: 15px; height: 15px; }
.btn-icon--lg { width: 56px; height: 56px; }
.btn-icon--lg svg { width: 22px; height: 22px; }

/* solid: the primary utility action in a cluster */
.btn-icon--solid {
  --icon-bg: var(--yellow);
  --icon-fg: var(--green-900);
  --icon-bg-hover: var(--lime);
  --icon-fg-hover: var(--green-900);
  --icon-ring: transparent;
}

/* quiet: sits inside a card or a toolbar without competing with it */
.btn-icon--quiet { --icon-ring: transparent; }

/* on a dark ground */
.on-dark .btn-icon,
.btn-icon--dark {
  --icon-fg: var(--on-dark);
  --icon-ring: var(--on-dark-line);
  --icon-bg-hover: rgba(255, 255, 255, 0.09);
  --icon-fg-hover: var(--white);
}

/* ==========================================================================
   Sizes
   ========================================================================== */
.btn--sm {
  height: 42px;
  padding-left: 20px;
  gap: 8px;
  font-size: 13px;
}
.btn--sm .btn__arrow { width: 34px; height: 34px; }
.btn--sm .btn__arrow svg { width: 18px; height: 12px; }

.btn--lg {
  height: 60px;
  padding-left: 32px;
  font-size: 15px;
}
.btn--lg .btn__arrow { width: 50px; height: 50px; }
.btn--lg .btn__arrow svg { width: 24px; height: 16px; }

.btn--block { display: flex; width: 100%; }

/* ==========================================================================
   Disabled
   --------------------------------------------------------------------------
   Reduced contrast AND a not-allowed cursor AND no pointer events AND no
   shadow — four signals, because opacity on its own is routinely missed.
   The lost shadow matters most: it stops looking raised, so it stops looking
   pressable. `aria-disabled` is honoured too, for links, which cannot carry
   `disabled`.
   ========================================================================== */
.btn:disabled,
.btn[aria-disabled="true"],
.btn-icon:disabled,
.btn-icon[aria-disabled="true"] {
  opacity: 0.4;
  cursor: not-allowed;
  pointer-events: none;
  filter: saturate(0.5);
  box-shadow: none;
  transform: none;
}

/* ==========================================================================
   Loading
   --------------------------------------------------------------------------
   The label stays put — swapping it for a spinner collapses the button and
   shifts everything after it. The disc becomes the spinner instead, so the
   footprint never changes. The ring turns slowly, in keeping with the rest.
   ========================================================================== */
.btn[data-loading="true"],
.btn-icon[data-loading="true"] { cursor: progress; pointer-events: none; }
.btn[data-loading="true"] .btn__arrow svg,
.btn-icon[data-loading="true"] svg { opacity: 0; }

.btn[data-loading="true"] .btn__arrow::after,
.btn-icon[data-loading="true"]::after {
  content: "";
  position: absolute;
  inset: 28%;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-top-color: transparent;
  animation: btn-spin 900ms linear infinite;
}

@keyframes btn-spin { to { transform: rotate(360deg); } }

/* ==========================================================================
   Groups
   ========================================================================== */
.btn-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}

/* ==========================================================================
   Responsive & reduced motion
   ========================================================================== */
@media (max-width: 560px) {
  .btn { height: 48px; padding-left: 20px; font-size: 13px; }
  .btn__arrow { width: 38px; height: 38px; }
  .btn--lg { height: 54px; padding-left: 24px; }
  .btn--lg .btn__arrow { width: 44px; height: 44px; }
}

/* Coarse pointers have no hover, so the resting state has to carry the whole
   affordance — the press feedback becomes the only interaction there is. */
@media (hover: none) {
  .btn:active { transform: scale(0.97); }
}

@media (prefers-reduced-motion: reduce) {
  .btn, .btn__label, .btn__arrow, .btn__arrow::before, .btn__arrow svg, .btn-icon {
    transition-duration: 1ms !important;
  }
  .btn:hover, .btn:focus-visible { transform: translate3d(0, 0, 0); }
  .btn[data-loading="true"] .btn__arrow::after,
  .btn-icon[data-loading="true"]::after { animation-duration: 2200ms; }
}
