/* Lagos Life button. Owner 5c. Spec: buttons.html#button, 05-sections/5c-actions-inputs.md.
   Markup: <button class="ll-button ll-button--primary ll-button--lg ll-interactive">
             <span class="ll-button__icon ll-emoji" aria-hidden="true">✈️</span>
             <span class="ll-button__label">Book with cab</span>
             <span class="ll-button__trail">₦2,495,568</span>
             <span class="ll-spinner" aria-hidden="true"></span>
           </button>
   States come from state.css (.ll-interactive). This file only sets the default look per variant
   through three private variables: --_fill, --_label and --_shadow. */

.ll-button {
  --_fill: var(--secondary);
  --_label: var(--secondary-foreground);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--control-md);
  max-width: 100%;
  margin: 0;
  padding: 0 var(--space-5);
  border: 0;
  border-radius: var(--radius-full);
  background-color: var(--_fill);
  color: var(--_label);
  font: var(--type-label-lg);
  font-variant-numeric: tabular-nums;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  vertical-align: middle;
  user-select: none;
}

/* Parts */
.ll-button__icon {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: var(--icon-md);
  height: var(--icon-md);
  font-size: var(--icon-md);
  line-height: 1;
}
.ll-button__icon svg { width: 100%; height: 100%; }
.ll-button__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.ll-button__trail { margin-left: auto; padding-left: var(--space-3); font-weight: var(--weight-extrabold); }
.ll-button:has(.ll-button__trail) { justify-content: flex-start; }

/* Sizes: sm 36, md 44 (default), lg 56. Hit area is always 44 (state.css ::after). */
.ll-button--sm {
  min-height: var(--control-sm);
  padding: 0 var(--space-4);
  gap: var(--space-1-5);
  font: var(--type-label);
}
.ll-button--sm .ll-button__icon { width: var(--icon-sm); height: var(--icon-sm); font-size: var(--icon-sm); }
.ll-button--lg {
  min-height: var(--control-lg);
  padding: 0 var(--space-6);
}

/* Variants (the job, not the look) */
.ll-button--primary   { --_fill: var(--primary); --_label: var(--primary-foreground); --_shadow: var(--shadow-lip-rest); }
.ll-button--secondary { --_fill: var(--secondary); --_label: var(--secondary-foreground); }
.ll-button--floating  { --_fill: var(--paper); --_label: var(--ink); --_shadow: var(--shadow-flat); }
.ll-button--ghost     { --_fill: transparent; --_label: var(--ink); }
.ll-button--danger    { --_fill: var(--paper); --_label: var(--rose-deep); --_shadow: inset 0 0 0 1px var(--rose-deep); }
.ll-button--danger-confirm { --_fill: var(--button-danger-fill); --_label: var(--button-danger-label); }
.ll-button--special   { --_fill: var(--button-special-fill); --_label: var(--button-special-label); --_shadow: var(--glow-gold); }

/* Ghost buttons stay see-through when inactive; only the text dims. */
.ll-button--ghost:is([aria-disabled="true"], :disabled) { background-color: transparent; }

/* Loading: the content keeps its space (no width jump), the spinner sits centred. */
.ll-button > .ll-spinner { display: none; position: absolute; inset: 0; margin: auto; }
.ll-button[aria-busy="true"] > .ll-spinner { display: block; }
.ll-button[aria-busy="true"] > :not(.ll-spinner) { visibility: hidden; }
/* Loading keeps the variant's own colours (state.css would grey an aria-disabled button). */
.ll-button[aria-busy="true"][aria-disabled="true"] { background-color: var(--_fill); color: var(--_label); cursor: progress; }
.ll-button--primary[aria-busy="true"]  { --_shadow: var(--shadow-lip-rest); }
.ll-button--floating[aria-busy="true"] { --_shadow: var(--shadow-flat); }
.ll-button--danger[aria-busy="true"]   { --_shadow: inset 0 0 0 1px var(--rose-deep); }
.ll-button--special[aria-busy="true"]  { --_shadow: var(--glow-gold); }

/* Primary: the game lip (R7, decided by Mikky 15 Oct 2026). Spec: buttons.html#primary-decision.
   A solid --primary-lip edge sits under the button. Hover lifts it 1px and darkens the fill; press sinks it
   --lip-depth into the lip in --duration-lip-press, and it springs back in --duration-lip-release.
   The fill change replaces the white state layer, so the label only gains contrast (4.61 → 5.50 → 6.64:1).
   The button keeps --lip-depth of space below, so the lip never touches what follows.
   Inactive: mist fill, no lip (state.css). Loading: keeps the fill and the resting lip. */
.ll-button--primary {
  margin-bottom: var(--lip-depth);
  transition:
    transform var(--duration-lip-release) var(--ease-lip),
    box-shadow var(--duration-lip-release) var(--ease-lip),
    background-color var(--duration-lip-release) var(--ease-lip),
    color var(--duration-state) var(--ease-standard);
}
.ll-button--primary::before { display: none; }
@media (hover: hover) {
  .ll-button--primary:not([aria-disabled="true"], :disabled, [aria-busy="true"]):hover {
    --_fill: var(--primary-hover);
    --_shadow: var(--shadow-lip-hover);
    transform: translateY(-1px);
  }
}
.ll-button--primary[data-demo-state="hover"] {
  --_fill: var(--primary-hover);
  --_shadow: var(--shadow-lip-hover);
  transform: translateY(-1px);
}
.ll-button--primary:not([aria-disabled="true"], :disabled, [aria-busy="true"]):active,
.ll-button--primary[data-demo-state="pressed"] {
  --_fill: var(--primary-pressed);
  --_shadow: var(--shadow-lip-pressed);
  transform: translateY(var(--lip-depth));
  transition-duration: var(--duration-lip-press);
}

/* Reduced motion: no lift, no sink, no lip change. Only the fill colour changes. */
@media (prefers-reduced-motion: reduce) {
  .ll-button--primary { transition: background-color var(--duration-state) var(--ease-standard), color var(--duration-state) var(--ease-standard); }
  .ll-button--primary.ll-interactive:is(:hover, :active, [data-demo-state="hover"], [data-demo-state="pressed"]) {
    transform: none;
  }
  .ll-button--primary.ll-interactive:not([aria-disabled="true"], :disabled):is(:hover, :active, [data-demo-state="hover"], [data-demo-state="pressed"]) {
    --_shadow: var(--shadow-lip-rest);
  }
}
