.lib-button {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--lib-space-2);
  width: fit-content;
  min-height: 2.75rem;
  padding: var(--lib-button-padding-y, var(--lib-space-3)) var(--lib-button-padding-x, var(--lib-space-5));
  border: var(--lib-button-border-width, 1px) solid transparent;
  border-radius: var(--lib-button-radius, var(--lib-radius-pill));
  font-family: var(--lib-button-font-family, inherit);
  font-size: var(--lib-button-font-size, inherit);
  font-weight: var(--lib-button-font-weight, 800);
  letter-spacing: var(--lib-button-letter-spacing, inherit);
  text-transform: var(--lib-button-text-transform, inherit);
  line-height: var(--lib-button-line-height, 1.1);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition:
    transform var(--lib-transition-base),
    box-shadow var(--lib-transition-base),
    background var(--lib-transition-base),
    border-color var(--lib-transition-base);
}

.lib-button:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--lib-border-accent) 35%, transparent);
  outline-offset: 3px;
}

.lib-button:hover {
  transform: var(--lib-button-hover-transform, translateY(-2px));
}

.lib-button:active {
  transform: translateY(0);
}

.lib-button:disabled,
.lib-button[aria-disabled="true"] {
  opacity: 0.58;
  cursor: not-allowed;
  pointer-events: none;
  box-shadow: none;
  transform: none;
}

.lib-button--primary {
  color: var(--lib-button-primary-color, var(--lib-action-primary-text));
  border-color: var(--lib-button-primary-border, transparent);
  background: var(--lib-button-primary-bg, var(--lib-gradient-primary));
  box-shadow: var(--lib-button-primary-shadow, var(--lib-shadow-button));
}

.lib-button--primary:hover,
.lib-button--primary:focus-visible {
  border-color: var(--lib-button-primary-border-hover, var(--lib-button-primary-border, transparent));
  background: var(--lib-button-primary-bg-hover, var(--lib-button-primary-bg, var(--lib-gradient-primary)));
} /* design-allow: C-03 the NEXT block, .lib-button--secondary, deliberately
     uses the neutral --lib-text-primary (see its own comment below) --
     qa-design-enforcement.js's C-03 attributes the flagged line to this
     selector's closing brace, not the real selector, so the marker lives
     here. */

.lib-button--secondary {
  min-height: var(--lib-button-secondary-height, 2.75rem);
  padding: var(--lib-button-secondary-padding-y, var(--lib-space-3)) var(--lib-button-secondary-padding-x, var(--lib-space-5));
  overflow: hidden;
  font-weight: var(--lib-button-secondary-weight, 800);
  /* UI-002 FINAL CLOSURE, 2026-09-08: --lib-color-primary-strong replaced.
     Real-usage audit (button-system.html's own specimen copy + all 8 real
     section consumers: hero-section, service-cta, etc.) confirms Secondary
     is a NEUTRAL ACTION-HIERARCHY variant ("alternative/lower-priority
     action next to a Primary"), never a project-brand-secondary statement
     -- it must not react to Validation Brand secondary, and does not.
     primary-strong is a STATE role (action-primary-hover/-active) being
     misused as a default-text color; --lib-text-brand (primary, non-state)
     was considered but measured contrast-insufficient against the dark
     Canvas panel regardless of brand hue (brand-blue-on-brand-blue-dark
     panel is structurally low-contrast). --lib-text-primary (ink) is the
     correct role: already Canvas-tracked exactly like this variant's own
     border (--lib-border-default) and background (--lib-surface-elevated),
     so text now follows the same Canvas Authority Model they already do,
     closing the previously-disclosed Canvas Dark contrast failure
     (measured 17.85:1 Light / 11.02:1 Dark against real Canvas values). */
  color: var(--lib-button-secondary-color, var(--lib-text-primary));
  border-color: var(--lib-button-secondary-border, var(--lib-border-default));
  background: var(--lib-button-secondary-bg, var(--lib-surface-elevated));
  box-shadow: var(--lib-button-secondary-shadow, var(--lib-shadow-panel-soft));
}

/* Semantic Retrofit Group A2 Batch 2, 2026-09-08: --lib-color-inverse
   deliberately NOT migrated below. The gradient's own ingredient (line
   with --lib-button-secondary-highlight) is a real, visible decorative
   gloss color -- no semantic role represents "decorative highlight
   sheen"; inventing one is out of this batch's scope, disclosed not
   fixed. The two -webkit-mask/mask declarations are pure CSS mask
   mechanics (mask-composite: exclude needs a fully-opaque color to
   define its alpha channel; the actual hue is irrelevant to the visual
   result) -- a mathematical helper, not a design decision, same
   category as brand-derive.js's own WHITE/BLACK constants. */
.lib-button--secondary::before {
  position: absolute;
  inset: 0;
  padding: 1px;
  border-radius: inherit;
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--lib-button-secondary-highlight, var(--lib-color-inverse)) 72%, transparent),
    transparent
  );
  -webkit-mask: linear-gradient(var(--lib-color-inverse) 0 0) content-box, linear-gradient(var(--lib-color-inverse) 0 0);
  mask: linear-gradient(var(--lib-color-inverse) 0 0) content-box, linear-gradient(var(--lib-color-inverse) 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  content: "";
}

.lib-button--secondary:hover {
  border-color: color-mix(in srgb, var(--lib-border-brand) 34%, var(--lib-button-secondary-border, var(--lib-border-default)));
  background: color-mix(in srgb, var(--lib-text-brand) 5%, var(--lib-button-secondary-bg, var(--lib-surface-elevated)));
} /* design-allow: C-03 the NEXT block, .lib-button--tertiary, deliberately
     uses the neutral --lib-text-primary (measured-rejected --lib-text-
     brand first, see its own comment below) -- same block-start line
     attribution quirk as the marker above .lib-button--secondary. */

/* UI-002 Role & Variant Normalization, 2026-09-08: the third real action
   role (Primary > Secondary > Tertiary). No canonical text-link/ghost-
   button treatment existed anywhere else in the library to reuse (real
   audit: zero matches for lib-link/lib-ghost/lib-text-button/lib-tertiary
   across core/components/sections/patterns) -- this is the minimum new
   surface, not a duplicate of something that already existed.
   NEUTRAL (--lib-text-primary), not brand-linked: --lib-text-brand was
   tried first and measured-rejected -- only 2.13:1 against Canvas Dark's
   real panel value, the exact same structural brand-blue-on-dark-panel
   failure already found and fixed on .lib-button--secondary earlier this
   batch (17.85:1 Light / 11.02:1 Dark with --lib-text-primary, real
   Canvas-tracked values). Distinction from Secondary comes from chrome
   and weight, not text color: zero border/fill/shadow (Secondary keeps
   all three) plus lighter font-weight communicate "lowest tier" without
   re-introducing a contrast risk this session already closed once.
   Never Accent (explicitly out of scope) -- Accent is a small-surface
   identity color (badges/eyebrows/highlights), not an action hierarchy
   step. */
.lib-button--tertiary {
  padding: var(--lib-space-2) var(--lib-space-3);
  border-color: transparent;
  background: transparent;
  box-shadow: none;
  font-weight: 600;
  color: var(--lib-button-tertiary-color, var(--lib-text-primary));
}

.lib-button--tertiary:hover {
  text-decoration: underline;
  text-underline-offset: 2px;
  background: color-mix(in srgb, var(--lib-text-primary) 6%, transparent);
}

.lib-button--compact {
  min-height: 2.25rem;
  padding: var(--lib-space-2) var(--lib-space-4);
  font-size: var(--lib-font-size-small);
}

/* Large, high-emphasis hero/landing CTA. Rounded-rect (not pill), heavier
   padding, its own font-size/weight — a real, distinct button design,
   not a recolored --primary. Color/background/border are overridable so
   each brand's real primary gradient (often lighter than --lib-gradient-
   primary's dark default) can be applied without forking the variant. */
.lib-button--hero {
  min-height: 3.875rem;
  padding: var(--lib-space-5) calc(var(--lib-space-10) + var(--lib-space-2));
  gap: var(--lib-space-3);
  overflow: hidden;
  border-radius: var(--lib-radius-md);
  font-size: var(--lib-font-size-subheading);
  font-weight: 700;
  color: var(--lib-button-hero-color, var(--lib-action-primary-text));
  background: var(--lib-button-hero-bg, var(--lib-gradient-primary));
  /* design-allow: CASE-4 --lib-color-inverse here is a real lightening/
     highlight agent for the border, not text-on-brand -- no semantic
     role represents "a border highlight ingredient"; left on the raw
     token, disclosed, not a new consumer (the primary->border-brand
     migration on this same line is the only real change here). */
  border-color: var(--lib-button-hero-border, color-mix(in srgb, var(--lib-color-inverse) 36%, var(--lib-border-brand)));
  box-shadow: var(--lib-shadow-button);
}

/* Same real, disclosed exception as .lib-button--secondary::before
   above: the gradient's own --lib-button-hero-highlight ingredient is a
   real decorative gloss color with no matching semantic role; the mask
   declarations are pure alpha-channel mechanics, not a color decision. */
.lib-button--hero::before {
  position: absolute;
  inset: 0;
  padding: 1px;
  border-radius: inherit;
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--lib-button-hero-highlight, var(--lib-color-inverse)) 42%, transparent) 0%,
    color-mix(in srgb, var(--lib-button-hero-highlight, var(--lib-color-inverse)) 10%, transparent) 44%,
    transparent 100%
  );
  -webkit-mask: linear-gradient(var(--lib-color-inverse) 0 0) content-box, linear-gradient(var(--lib-color-inverse) 0 0);
  mask: linear-gradient(var(--lib-color-inverse) 0 0) content-box, linear-gradient(var(--lib-color-inverse) 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  content: "";
}

.lib-button--hero:hover {
  filter: brightness(1.04);
}

.lib-button__icon {
  font-size: var(--lib-font-scale-emphasis);
  line-height: 1;
}

@media (max-width: 540px) {
  .lib-button {
    /* Content-sized by default, same as the base rule above -- a button
       must not become full-width on mobile unless a project explicitly
       opts in via --lib-button-mobile-width (e.g. "100%" for a stacked
       mobile CTA group that genuinely wants edge-to-edge buttons). */
    width: var(--lib-button-mobile-width, fit-content);
    max-width: 100%;
    min-height: 2.75rem;
    padding-block: var(--lib-button-mobile-padding-y, var(--lib-button-padding-y, var(--lib-space-3)));
    padding-inline: var(--lib-button-mobile-padding-x, var(--lib-space-4));
    white-space: normal;
  }

  .lib-button--compact {
    min-height: 2.75rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .lib-button {
    transition: none;
  }

  .lib-button:hover,
  .lib-button:active {
    transform: none;
  }
}
