/* ==========================================================
   IROZON DESIGN SYSTEM — Signature CTA (canonical, v2)
   Public API:
     <a class="iz-signature-cta" href="...">
       <span class="iz-signature-cta__sizer" aria-hidden="true">Label</span>
       <span class="iz-signature-cta__base">
         <span class="iz-signature-cta__label">Label</span>
       </span>
       <span class="iz-signature-cta__panel" aria-hidden="true"></span>
     </a>
   Same markup also renders on a native <button type="submit"|"button">
   for act/submit contexts (the class is the opt-in either way) — use an
   anchor when navigating, a button when acting/submitting.
   See signature-cta.html / the Buttons doc page for the full markup.

   BREAKING CHANGE (unreleased, post-0.2.0): the decorative Three Dots
   mark is now generated entirely by this stylesheet (base::after /
   panel::before, via layered radial-gradient()). Consumers no longer
   provide any SVG/icon markup — `iz-signature-cta__dots` and
   `iz-signature-cta__dots--right` are gone, and `__sizer` now wraps the
   label text directly (`__sizer-spacer` is gone too, folded into the
   sizer's own reserved trailing width). The component owns its
   geometry; consumers own only semantic content.

   A brand-expression component, not a Button variant — promoted
   verbatim from irozon-website's PrimaryButton.tsx (the homepage Hero
   CTA), byte-for-byte reproduced in CSS: same geometry, same colors,
   same slide distances, same perceived motion. Reserved for rare,
   high-emphasis brand moments (a hero, a major campaign action) — it
   does not replace Primary; see Button's Signature CTA note.

   Colors are intentionally hardcoded to the primitives, not the
   semantic action-primary tokens Button v2 uses — this component's
   Ink/White rest state and Ink/Lime hover state are fixed brand
   values, not theme-adaptive, exactly matching the source (which
   itself hardcodes these two hex values rather than reading CSS
   variables, since Framer Motion's color interpolation can't resolve
   var() references). NOTE: the source names its hover-fill constant
   "GREEN" but its actual value (#9BE15D) is Irozon Lime, not Irozon
   Green (#02C685) — reproduced exactly as implemented, not as named.

   Motion: the source drives this with a Framer Motion spring
   (stiffness 420, damping 18, mass 0.6) — a react-only mechanism with
   no CSS equivalent. --ease-signature (design-tokens/motion.css) was
   already reserved for exactly this reveal; --iz-signature-duration
   below approximates that spring's settle time (~270ms, per damping
   ratio ≈0.57 / natural frequency ≈26.5 rad/s) with a single
   transition-duration. Scoped locally rather than promoted to a global
   motion token, since no other component needs it yet.
   ========================================================== */

.iz-signature-cta {
  --iz-signature-duration: 320ms;

  /* flex-shrink:0 is load-bearing, not decorative: this element's only
     in-flow child is __sizer, which is what gives it its intrinsic
     width (see __sizer below) — but `overflow: hidden` on THIS element
     makes ITS OWN automatic minimum size, as a flex item of whatever
     row a consumer places it in, resolve to 0 per the flexbox sizing
     spec (an item with non-visible overflow gets a 0 content-based
     minimum, regardless of what its own children need). Without this,
     default flex-shrink:1 lets a cramped ancestor flex row (e.g. a
     narrow viewport) compress this control below __sizer's reserved
     width, squeezing __base until __label — which has no width of its
     own to defend — wraps to two lines and the whole composition falls
     apart. flex-shrink:0 makes the browser honor __sizer's intrinsic
     width unconditionally: this control now overflows/wraps as a whole
     unit in a flex-wrap row instead of ever compressing internally. */

  /* Three Dots mark, generated once and shared by base::after and
     panel::before. Three hard-edged circles (currentColor -> transparent
     at the same offset) laid out in a 16x16px box, positions/radius
     carried over pixel-for-pixel from the original SVG's viewBox
     (0 0 254 392) as rendered inside a 16x16 box under
     preserveAspectRatio "xMidYMid meet" (i.e. letterboxed to the
     392-tall axis, scale = 16/392): centers at (32.3%, 14.7%),
     (67.6%, 50%), (32.3%, 85.3%), radius 2.35px. */
  --iz-dots:
    radial-gradient(2.35px at 32.3% 14.7%, currentColor 100%, transparent 100%),
    radial-gradient(2.35px at 67.6% 50%, currentColor 100%, transparent 100%),
    radial-gradient(2.35px at 32.3% 85.3%, currentColor 100%, transparent 100%);

  position: relative;
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  block-size: 48px;
  overflow: hidden;
  border-radius: 12px;
  text-decoration: none;
  cursor: pointer;
  transition: transform var(--motion-duration-instant) var(--motion-ease-standard);
}
.iz-signature-cta:active {
  transform: scale(0.97);
}
.iz-signature-cta:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}

/* Native <button> UA chrome (appearance/border/background/padding/font)
   would otherwise show through or resize the sizer-driven intrinsic
   width; the anchor never carries any of this, so it's scoped to the
   element selector, not the class alone. */
button.iz-signature-cta {
  appearance: none;
  -webkit-appearance: none;
  border: none;
  background: none;
  padding: 0;
  margin: 0;
  font: inherit;
  text-align: inherit;
  color: inherit;
}

/* Disabled — native `disabled` (buttons, e.g. a form submit) is already
   inert to clicks and keyboard focus, so it only needs the visual
   affordance; `aria-disabled` (anchors have no native disabled) still
   needs pointer-events suppressed to actually block navigation, and
   stays focusable, so its hover/focus-visible reveal is also guarded
   below. Opacity (not a muted color swap) matches the same disabled
   convention as Button v2 (button.css); the composited result over a
   light page background keeps the white label legible. */
.iz-signature-cta:disabled,
.iz-signature-cta[aria-disabled="true"] {
  cursor: not-allowed;
  opacity: 0.5;
}
.iz-signature-cta[aria-disabled="true"] {
  pointer-events: none;
}
.iz-signature-cta:is(:disabled, [aria-disabled="true"]):active {
  transform: none;
}
.iz-signature-cta:is(:disabled, [aria-disabled="true"]):is(:hover, :focus-visible) .iz-signature-cta__base {
  background-color: var(--irozon-ink);
  color: var(--irozon-white);
  transform: translateX(0);
}
.iz-signature-cta:is(:disabled, [aria-disabled="true"]):is(:hover, :focus-visible) .iz-signature-cta__label {
  transform: translateX(0);
}
.iz-signature-cta:is(:disabled, [aria-disabled="true"]):is(:hover, :focus-visible) .iz-signature-cta__base::after {
  opacity: 1;
  transform: none;
}
.iz-signature-cta:is(:disabled, [aria-disabled="true"]):is(:hover, :focus-visible) .iz-signature-cta__panel {
  transform: translateX(-100%);
  opacity: 0;
}

/* Sizer — invisible (visibility:hidden, not display:none, so its box
   still occupies space). Establishes the button's real width: label,
   plus the dot mark's 16px + the 12px gap in front of it + the
   3.5rem/56px trailing allowance the base layer slides into on hover
   — folded into a single reserved-width ::after so the sizer no longer
   needs to reproduce the dot mark or a separate spacer element itself.
   Without this the button would need to grow on hover instead of the
   pre-reserved space just being revealed. */
.iz-signature-cta__sizer {
  visibility: hidden;
  display: flex;
  align-items: center;
  gap: 12px;
  white-space: nowrap;
  padding-inline: 24px;
}
.iz-signature-cta__sizer::after {
  content: "";
  display: block;
  /* dot mark (16px) + gap to spacer (12px) + slide allowance (56px) */
  inline-size: 84px;
  flex-shrink: 0;
}

/* Base layer — the visible text pill. Ink/White at rest; slides right
   by the sizer's 56px allowance and recolors Ink -> Lime on
   hover/focus (never on :active alone — pressed is a plain scale on
   the whole button, independent of this color/slide state). */
.iz-signature-cta__base {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  border-radius: 12px;
  padding-inline: 24px;
  font-weight: 500;
  white-space: nowrap;
  background-color: var(--irozon-ink);
  color: var(--irozon-white);
  transform: translateX(0);
  transition:
    background-color var(--iz-signature-duration) var(--ease-signature),
    color var(--iz-signature-duration) var(--ease-signature),
    transform var(--iz-signature-duration) var(--ease-signature);
}
.iz-signature-cta:hover .iz-signature-cta__base,
.iz-signature-cta:focus-visible .iz-signature-cta__base {
  background-color: var(--irozon-lime);
  color: var(--irozon-ink);
  transform: translateX(56px);
}

/* Nudges left during hover/focus so it stays centered inside the
   now-narrower visible portion of the pill. */
.iz-signature-cta__label {
  transition: transform var(--iz-signature-duration) var(--ease-signature);
}
.iz-signature-cta:hover .iz-signature-cta__label,
.iz-signature-cta:focus-visible .iz-signature-cta__label {
  transform: translateX(-16px);
}

/* The base layer's own trailing dot mark (generated, see --iz-dots)
   fades out on hover/focus so it doesn't peek past the shrunken
   visible edge. */
.iz-signature-cta__base::after {
  content: "";
  inline-size: 16px;
  block-size: 16px;
  flex: none;
  background-image: var(--iz-dots);
  background-repeat: no-repeat;
  transition:
    opacity var(--iz-signature-duration) var(--ease-signature),
    transform var(--iz-signature-duration) var(--ease-signature);
}
.iz-signature-cta:hover .iz-signature-cta__base::after,
.iz-signature-cta:focus-visible .iz-signature-cta__base::after {
  opacity: 0;
  transform: scale(0.8);
}

/* Left panel — the dot mark. Off-canvas left and invisible at rest;
   slides in + fades in on hover/focus, revealed in the gap the base
   layer's slide leaves behind. */
.iz-signature-cta__panel {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  inline-size: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 12px;
  background-color: var(--irozon-ink);
  color: var(--irozon-white);
  transform: translateX(-100%);
  opacity: 0;
  transition:
    transform var(--iz-signature-duration) var(--ease-signature),
    opacity var(--iz-signature-duration) var(--ease-signature);
}
.iz-signature-cta:hover .iz-signature-cta__panel,
.iz-signature-cta:focus-visible .iz-signature-cta__panel {
  transform: translateX(0);
  opacity: 1;
}
.iz-signature-cta__panel::before {
  content: "";
  inline-size: 16px;
  block-size: 16px;
  background-image: var(--iz-dots);
  background-repeat: no-repeat;
}

/* Reduced motion drops the slide/color spring to a near-instant
   change — the hover/focus state still resolves (recognizable), but
   nothing travels or eases. Pressed feedback is removed entirely,
   matching the source's whileTap being undefined under
   prefers-reduced-motion. */
@media (prefers-reduced-motion: reduce) {
  .iz-signature-cta {
    transition: none;
  }
  .iz-signature-cta:active {
    transform: none;
  }
  .iz-signature-cta__base,
  .iz-signature-cta__label,
  .iz-signature-cta__base::after,
  .iz-signature-cta__panel {
    transition-duration: 1ms;
  }
}
