@layer dx-component-base {
/* ==========================================================================
   Button — basic component + the shared button element

   This file owns BOTH:
     • `.dx-button-component` — the section wrapper rendered by the
       standalone Button basic component (`components/button.php`). Just a
       centering layout helper; visual styling comes from the element below.
     • `.dx-button` — the actual button/link element. Used everywhere a
       button appears: standalone Button component, Hero CTA, core block's
       button slots (`.dx-core__buttons` row inside core), Text + Media, etc.

   Until the basic-component split, this lived in `core.css` as
   `.dx-core__button` because buttons only ever appeared inside the core
   block. Now that Button has graduated to its own basic component and
   gets composed into other components by reference, the class belongs to
   button.css and drops the `core` namespace.

   Variants are mode-coupled (post-refactor):
     • `solid` / `outline` / `alpha` — fill / border / tint sourced from
       `--dx-button` and `--dx-button-hover`. Mode-aware: each mode's
       button colour is configured in the Variable Manager (one row each for
       `dynamic_button` and `dynamic_button_hover`).
     • `neutral` — palette-independent monochrome: heading colour on
       background colour. Mode-coupled via `--dx-heading` / `--dx-bg`.
   ========================================================================== */

/* ---------- Button-component layout (centering wrapper) ---------- */

.dx-button-component__inner {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 1rem;
}

/* ---------- Button element ---------- */

.dx-button {
  /* Flex container so text + any ::before/::after content (arrows, icons,
       spinners) line up on the vertical center. inline-block would sit the
       pseudo glyphs on the text baseline instead — arrows like → appear
       high on the line because their visual center is above the baseline.
       Line-height is intentionally inherited (not pinned to 1) so button
       height stays consistent with the rest of the design; pseudo content
       that needs tighter line-height can set it on the pseudo itself. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Block + inline padding split — each var resolves through a step
     of the global spacing scale (`var(--dx-space-{step})`) via the
     emission in inc/tokens.php. The user picks block and inline
     independently on the Button panel. */
  padding: var(--dx-button-padding-block) var(--dx-button-padding-inline);
  font-size: var(--dx-button-size);
  font-weight: var(--dx-button-weight);
  /* Empty token = inherit (line-height tracks the body Global value).
     Non-empty token overrides for every button site-wide. Same pattern
     as Rich Text's --dx-text-line-height. The comment above about
     "intentionally inherited" is still satisfied — inherit is the
     default; the user gets an override knob if they need one. */
  line-height: var(--dx-button-line-height, inherit);
  text-decoration: none;
  /* Always render a border of the same width so solid and outline variants
       line up to the same pixel grid. Solid buttons use a transparent border
       that the outline modifier later paints. Width follows the global
       Border Width token so the user can tune it once for all buttons. */
  border: var(--dx-effect-border-width) solid transparent;
  /* Button radius overrides the global Border Radius. Token chain:
       --dx-button-radius      (Button panel — None / 2XS…5XL / Pill / Custom)
       --dx-effect-border-radius (Miscellaneous panel — site-wide default)
     The Button panel's dropdown shows "(Inherit global)" on whichever
     scale step matches the global, so an empty stored value renders
     identically to the global; the `var(…, fallback)` chain here means
     the user only pays for an emission when they've actually overridden. */
  border-radius: var(--dx-button-radius, var(--dx-effect-border-radius));
  /* `background-clip: padding-box` is set UNLAYERED on `.dx-button` in
     dx-defaults.css — see the comment block there. It can't live in this
     rule because component-defaults layer rules using the `background:`
     shorthand (user-saved gradient variants etc.) would silently reset
     it back to the initial `border-box` and the artifact would return. */
  transition:
    background-color var(--dx-effect-transition-duration) ease,
    border-color var(--dx-effect-transition-duration) ease,
    color var(--dx-effect-transition-duration) ease,
    box-shadow var(--dx-effect-transition-duration) ease;
  cursor: pointer;
}

.dx-button:focus-visible {
  /* Focus outline follows the button colour — same accent the button
     itself is using in this mode. Falls back to brand primary outside
     a mode scope. */
  outline: 2px solid hsl(var(--dx-button, var(--dx-primary)));
  outline-offset: 3px;
}

/* ──────────────────────────────────────────────────────────────────────
   Solid variant — base button class with no modifier.

   Fill: the mode's button colour (`--dx-button`, which itself aliases
   `--dx-color-dynamic-button` per `[class*="dx-mode-"]` in dx-defaults.css).
   Text: primitive white. Guaranteed high contrast against the fill,
   palette-independent, mode-independent.

   ONE indirection (alias → dynamic var). No typography-token layer
   between the consumer and the Dynamic alias — if you want to change
   the button colour in mode N, you set it ONCE in the Variable Manager
   on `--dx-color-dynamic-button` for mode N. That's the entire chain.
   ────────────────────────────────────────────────────────────────────── */

.dx-button--solid {
  background-color: hsl(var(--dx-button));
  /* `--dx-button-solid-fg` is set per-site on `.dx-button--solid` by
     dx_output_component_defaults_css() when the user picks a Foreground
     value on the Button panel's Solid variant card (Settings →
     Foreground). The fallback `hsl(var(--dx-color-primitive-white))`
     preserves the historical white-on-fill default on fresh installs
     and on every site that hasn't overridden it. Empty / "Inherit" on
     the panel writes no override → fallback wins → default appearance
     is unchanged. See inc/component-defaults.php's dx_generate_settings_css(). */
  color: var(--dx-button-solid-fg, hsl(var(--dx-color-primitive-white)));
}

.dx-button--solid:hover {
  /* Hover state pulls from `--dx-button-hover` (the mode's button hover
     colour, also configured in the Variable Manager). Box-shadow lift completes
     the press-affordance signal. */
  background-color: hsl(var(--dx-button-hover));
  box-shadow: var(--dx-effect-shadow);
}

/* Neutral = palette-independent monochrome. Background = mode's
   heading colour, text = mode's background colour. Max contrast within
   the active mode without any further configuration — this variant is
   the brand-agnostic alternative to the mode-coupled `solid` family.
   Hover dims the fill to 85% alpha so the button visually lifts against
   the section bg while keeping text contrast intact. */
.dx-button--neutral {
  background-color: hsl(var(--dx-heading));
  color: hsl(var(--dx-bg));
}

.dx-button--neutral:hover {
  /* Dim the fill with color-mix, NOT `hsl(var(--dx-heading) / 0.85)`.
     `--dx-heading` is a mode-aware Dynamic alias the user can point at
     an ALPHA-ramp token (e.g. Black Alpha 9, emitted as
     `0 0% 0% / 0.88`). When the alias already carries an alpha,
     `hsl(var(--dx-heading) / 0.85)` expands to
     `hsl(0 0% 0% / 0.88 / 0.85)` — two slash-alpha segments, which is
     invalid at computed-value time. The browser then resets
     background-color to its initial `transparent`, so the button face
     disappears on hover (white-on-white in light modes). color-mix
     applies the extra alpha by COMPOSITION, valid whether or not the
     alias already has one — same idiom as the danger-tint in dx-ui.css.
     This is the alpha-safe replacement for the `hsl(var(--alias) / N)`
     pattern everywhere a Dynamic alias is the colour source. */
  background-color: color-mix(in srgb, hsl(var(--dx-heading)) 85%, transparent);
  box-shadow: var(--dx-effect-shadow);
}

/* ──────────────────────────────────────────────────────────────────────
   Outline modifier — stackable on any solid variant.
   Specificity (.a.b > .a) lets this override the solid defaults cleanly.
   ────────────────────────────────────────────────────────────────────── */

.dx-button--outline {
  background-color: transparent;
}

.dx-button--solid.dx-button--outline {
  /* Border AND text both pull directly from `--dx-button` — no
     intermediate `--dx-button-outline-text` typography-token layer.
     Set `--dx-color-dynamic-button` per mode in the Variable Manager
     and both follow on the next render. */
  border-color: hsl(var(--dx-button));
  color:        hsl(var(--dx-button));
}

.dx-button--solid.dx-button--outline:hover {
  /* 10% tint of the button colour. Mirrors the alpha variant's hover
     direction — light wash of the button colour rather than a fill flip.
     color-mix keeps this alpha-safe when `--dx-button` points at an
     alpha-ramp token — see the `.dx-button--neutral:hover` note above. */
  background-color: color-mix(in srgb, hsl(var(--dx-button)) 10%, transparent);
  box-shadow: none;
}

.dx-button--neutral.dx-button--outline {
  border-color: hsl(var(--dx-heading));
  color: hsl(var(--dx-heading));
}

.dx-button--neutral.dx-button--outline:hover {
  /* alpha-safe tint — see the `.dx-button--neutral:hover` note above. */
  background-color: color-mix(in srgb, hsl(var(--dx-heading)) 10%, transparent);
  box-shadow: none;
}

/* ──────────────────────────────────────────────────────────────────────
   Alpha modifier — semi-transparent tinted fill.
   Base state sits at 20% tint of the button colour; hover bumps to 35%.
   Text uses the button colour itself so it stays readable over the tint.
   ────────────────────────────────────────────────────────────────────── */

.dx-button--solid.dx-button--alpha {
  /* Fill = 20% tint of the button colour, text = the button colour
     itself so it reads cleanly over the tint. Same one-indirection
     rule as the outline variant — no typography-token layer. color-mix
     keeps the tint alpha-safe when `--dx-button` points at an alpha-ramp
     token — see the `.dx-button--neutral:hover` note above. */
  background-color: color-mix(in srgb, hsl(var(--dx-button)) 20%, transparent);
  color:            hsl(var(--dx-button));
  border-color:     transparent;
}

.dx-button--solid.dx-button--alpha:hover {
  background-color: color-mix(in srgb, hsl(var(--dx-button)) 35%, transparent);
  box-shadow: none;
}
