.ezui-button {
  /* Colour comes from the palette in ezui-colour.css, never from a
     hex here (Foundations rule 9). These are the accent values; .secondary
     and .tertiary swap in the grey set, data-variant swaps in another
     colour. There is no pale accent button (secondary is always grey), so
     the accent sets no -normal tokens. There is no -active: a pointer is
     already showing hover while the button is held down, and touch gets
     the shrink further down. */
  --ezui-fill-loud: var(--ezui-accent);
  --ezui-fill-loud-hover: var(--ezui-accent-hover);
  --ezui-on-loud: var(--ezui-text-inverse);
  --ezui-fill-quiet: transparent;
  --ezui-fill-quiet-hover: var(--ezui-accent-soft);
  --ezui-on-quiet: var(--ezui-accent);
  --ezui-border-loud: transparent;
  --ezui-border-normal: transparent;
  --ezui-border-quiet: var(--ezui-accent);

  --ezui-on-accent: var(--ezui-accent);

  --ezui-height: 36px;
  --ezui-padding-inline: 14px;
  --ezui-font-size: var(--ezui-type-m);
  --ezui-gap: 6px;
  --ezui-icon-size: 16px;
  /* Line weight for that icon size, from the icon set: 1.125 + 15.75/size. */
  --ezui-icon-stroke: 2.11;

  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--ezui-gap);
  height: var(--ezui-height);
  padding: 0 var(--ezui-padding-inline);
  border-radius: 6px;
  border: 1px solid var(--ezui-border-loud);
  background: var(--ezui-fill-loud);
  color: var(--ezui-on-loud);
  font: var(--ezui-type-semibold) var(--ezui-font-size) / 1.2 var(--ezui-font);
  letter-spacing: normal;
  text-decoration: none;
  white-space: nowrap;
  user-select: none;
  cursor: pointer;
  position: relative;
  vertical-align: middle;
  box-sizing: border-box;
  transition: background-color .12s, color .12s, border-color .12s;
}
@media (hover: hover) {
  .ezui-button:hover { background: var(--ezui-fill-loud-hover); }
}

.ezui-button.primary {
  background: var(--ezui-fill-loud);
  color: var(--ezui-on-loud);
  border-color: var(--ezui-border-loud);
}
@media (hover: hover) {
  .ezui-button.primary:hover { background: var(--ezui-fill-loud-hover); }
}

.ezui-button.secondary {
  --ezui-fill-normal: var(--ezui-fill-hover);
  --ezui-fill-normal-hover: var(--ezui-fill-strong);
  --ezui-on-normal: var(--ezui-text-primary);
  --ezui-fill-quiet: transparent;
  --ezui-fill-quiet-hover: var(--ezui-fill);
  --ezui-on-quiet: var(--ezui-text-secondary);
  --ezui-border-quiet: var(--ezui-border);

  background: var(--ezui-fill-normal);
  color: var(--ezui-on-normal);
  border-color: transparent;
}
@media (hover: hover) {
  .ezui-button.secondary:hover { background: var(--ezui-fill-normal-hover); }
}

.ezui-button.tertiary {
  --ezui-fill-normal: var(--ezui-fill-hover);
  --ezui-fill-normal-hover: var(--ezui-fill-strong);
  --ezui-on-normal: var(--ezui-text-primary);
  --ezui-fill-quiet: transparent;
  --ezui-fill-quiet-hover: var(--ezui-fill);
  --ezui-on-quiet: var(--ezui-text-secondary);
  --ezui-border-quiet: var(--ezui-border);

  background: var(--ezui-fill-quiet);
  color: var(--ezui-on-quiet);
  border-color: var(--ezui-border-quiet);
}
@media (hover: hover) {
  .ezui-button.tertiary:hover { background: var(--ezui-fill-quiet-hover); }
}

.ezui-button.quaternary {
  --ezui-on-quiet: var(--ezui-text-secondary);
  --ezui-fill-quiet: transparent;
  --ezui-fill-quiet-hover: transparent;
  --ezui-border-quiet: transparent;

  height: auto;
  padding: 0;
  border: none;
  border-radius: 0;
  background: var(--ezui-fill-quiet);
  color: var(--ezui-on-quiet);
  font-weight: var(--ezui-type-regular);
  text-decoration: underline;
}
@media (hover: hover) {
  .ezui-button.quaternary:hover { color: var(--ezui-text-primary); }
}
@media (hover: hover) {
  .ezui-button.quaternary[data-variant="danger"]:hover,
  .ezui-button.quaternary[data-variant="destructive"]:hover { color: var(--ezui-text-destructive); }
}

/* ---- quinary: a row -------------------------------------------------------
   Quaternary's quietness in a button's shape: no box, but the height, the
   padding and the corner of a real button, and no underline, because this
   is not pretending to be a link. It is the row in a column of rows, a nav
   or a list of choices, which is why it is the one tier with somewhere to
   be "on": aria-current for the page you are on, aria-pressed for the
   choice that is picked. Both are the browser's own words for those two
   meanings, so a row cannot look picked without saying it is.
   -------------------------------------------------------------------- */
.ezui-button.quinary {
  /* A row's own spacing, not a button's: less at the sides, more between
     the icon and the label, so a column of rows reads as a list and lines
     up with a dropdown's menu rows. */
  --ezui-padding-inline: 10px;
  --ezui-gap: 10px;

  --ezui-on-quiet: var(--ezui-text-primary);
  --ezui-fill-quiet: transparent;
  --ezui-fill-quiet-hover: var(--ezui-fill);
  --ezui-border-quiet: transparent;

  background: var(--ezui-fill-quiet);
  border-color: var(--ezui-border-quiet);
  color: var(--ezui-on-quiet);
  font-weight: var(--ezui-type-regular);
  text-decoration: none;
}
@media (hover: hover) {
  .ezui-button.quinary:hover { background: var(--ezui-fill-quiet-hover); color: var(--ezui-on-quiet); }
}
.ezui-button.quinary[data-variant="danger"],
.ezui-button.quinary[data-variant="destructive"] { color: var(--ezui-text-destructive); }

/* Where you are: the text and the icon with it, and no fill. A page you are
   already on is not a thing to press, so it does not look pressable. */
.ezui-button.quinary[aria-current] { --ezui-on-quiet: var(--ezui-text-accent); }
/* What is picked: filled, the way a chosen thing is everywhere else. */
.ezui-button.quinary[aria-pressed="true"] {
  --ezui-fill-quiet: var(--ezui-accent);
  --ezui-fill-quiet-hover: var(--ezui-accent-hover);
  --ezui-on-quiet: var(--ezui-text-inverse);
  background: var(--ezui-fill-quiet);
  color: var(--ezui-on-quiet);
}

.ezui-button.quinary[data-size="s"] { --ezui-padding-inline: 8px; --ezui-gap: 8px; }
.ezui-button.quinary[data-size="l"] { --ezui-padding-inline: 12px; --ezui-gap: 12px; }

/* ---- data-align="start": the label against the left ---- */
.ezui-button[data-align="start"] { justify-content: flex-start; text-align: start; }
.ezui-button[data-align="end"] { justify-content: flex-end; text-align: end; }
/* A count or a shortcut at the far end of the button, whatever the label
   does. */
.ezui-button__end {
  margin-inline-start: auto;
  padding-inline-start: var(--ezui-gap);
  font-variant-numeric: tabular-nums;
  opacity: .7;
}

/* ---- a stack: buttons under one another ----------------------------------
   The same idea as .ezui-field-stack, and the same word for it. Each button
   takes the width, so their labels line up down the column. ---- */
.ezui-button-stack {
  --ezui-button-stack-gap: 2px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--ezui-button-stack-gap);
  min-width: 0;
}
.ezui-button-stack > .ezui-button { width: 100%; }
.ezui-button-stack > hr {
  height: 1px;
  margin: 6px 4px;
  border: 0;
  background: var(--ezui-border);
}

/* "accent" is the name; "brand" is kept working so older markup does
   not break. */
.ezui-button[data-text="accent"],
.ezui-button[data-text="brand"] { color: var(--ezui-on-accent); }
@media (hover: hover) {
  .ezui-button[data-text="accent"]:hover,
  .ezui-button[data-text="brand"]:hover { color: var(--ezui-text-accent); }
}

/* "destructive" is the name; "danger" is kept working so older markup
   does not break. */
.ezui-button[data-variant="destructive"],
.ezui-button[data-variant="danger"] {
  --ezui-fill-loud: var(--ezui-destructive);
  --ezui-fill-loud-hover: var(--ezui-destructive-hover);
  --ezui-on-loud: var(--ezui-text-inverse);
  --ezui-fill-normal: var(--ezui-destructive-soft);
  --ezui-fill-normal-hover: var(--ezui-destructive-soft-hover);
  --ezui-on-normal: var(--ezui-text-destructive);
  --ezui-fill-quiet: transparent;
  --ezui-fill-quiet-hover: var(--ezui-destructive-soft);
  --ezui-on-quiet: var(--ezui-destructive);
  --ezui-border-loud: transparent;
  --ezui-border-normal: transparent;
  --ezui-border-quiet: var(--ezui-destructive);
}

.ezui-button[data-size="s"] { --ezui-height: 32px; --ezui-padding-inline: 10px; --ezui-font-size: var(--ezui-type-s); --ezui-gap: 5px; --ezui-icon-size: 14px; --ezui-icon-stroke: 2.25; }
.ezui-button[data-size="l"] { --ezui-height: 42px; --ezui-padding-inline: 18px; --ezui-font-size: var(--ezui-type-l); --ezui-gap: 8px; --ezui-icon-size: 18px; --ezui-icon-stroke: 2; }

.ezui-button[data-pill] { border-radius: 9999px; }

.ezui-button:disabled,
.ezui-button[aria-disabled="true"] {
  opacity: .5;
  cursor: default;
  pointer-events: none;
}

.ezui-button--icon {
  width: var(--ezui-height);
  padding: 0;
}
.ezui-button--icon svg,
.ezui-button--icon img { width: var(--ezui-icon-size); height: var(--ezui-icon-size); }

.ezui-button__start,
.ezui-button__end {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}
.ezui-button__start svg,
.ezui-button__end svg { width: var(--ezui-icon-size); height: var(--ezui-icon-size); }

.ezui-button[data-with-caret]::after {
  content: "";
  display: inline-block;
  width: 0.7em;
  height: 0.7em;
  flex-shrink: 0;
  background-color: currentColor;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 5.5L8 10L12.5 5.5' stroke='black' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 5.5L8 10L12.5 5.5' stroke='black' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}

.ezui-button[data-loading] {
  cursor: default;
}
.ezui-button[data-loading] .ezui-button__label,
.ezui-button[data-loading] .ezui-button__start,
.ezui-button[data-loading] .ezui-button__end {
  opacity: 0;
  pointer-events: none;
}
.ezui-button[data-loading]::after {
  display: none;
}
.ezui-button__spinner {
  display: none;
  position: absolute;
  top: calc(50% - 0.5em);
  left: calc(50% - 0.5em);
  width: 1em;
  height: 1em;
  flex: none;
  animation: ezui-spinner-spin 2s linear infinite;
}
.ezui-button[data-loading] .ezui-button__spinner {
  display: block;
}
.ezui-button__spinner svg { width: 100%; height: 100%; display: block; }
.ezui-button__spinner .ezui-spinner-track,
.ezui-button__spinner .ezui-spinner-indicator {
  fill: none;
  stroke-width: 2px;
  cx: 8px;
  cy: 8px;
  r: 7px;
}
.ezui-button__spinner .ezui-spinner-track {
  stroke: color-mix(in oklab, currentColor, transparent 90%);
}
.ezui-button__spinner .ezui-spinner-indicator {
  stroke: currentColor;
  stroke-linecap: round;
  stroke-dasharray: 26.3, 35.2;
  stroke-dashoffset: -1.76;
  animation: ezui-spinner-dash 1.5s ease-in-out infinite;
}
@keyframes ezui-spinner-spin {
  100% { transform: rotate(360deg); }
}
@keyframes ezui-spinner-dash {
  0%   { stroke-dasharray: 0.35, 52.6;  stroke-dashoffset: 0; }
  50%  { stroke-dasharray: 31.5, 52.6;  stroke-dashoffset: -12.2; }
  100% { stroke-dasharray: 31.5, 52.6;  stroke-dashoffset: -43.4; }
}

.ezui-button--block { width: 100%; }

/* ---- Touch ----------------------------------------------------------
   A touch screen has no hover, so a tap has to show something itself.
   The button shrinks to 96% and lightens to its hover colour.

   The shrink carries it. A colour change on its own reads as a flash
   rather than a press, which is why the lightening is only a lift on top
   of the movement.

   The amount and the timings are Foundations' (rule 8), not the button's:
   a button and a card should shrink by the same amount. A field does not
   shrink at all, it darkens its fill, because you enter a field rather
   than push it.
   ezui-foundations.js sets data-ezui-pressed and holds it for 200ms,
   because :active can end sooner than the eye can follow and a quick tap
   would otherwise show nothing at all. That hold is the only part CSS
   cannot do by itself.
   ------------------------------------------------------------------- */
@media (hover: none) {
  .ezui-button {
    transition: background-color var(--ezui-press-out) ease-out,
                color var(--ezui-press-out) ease-out,
                border-color var(--ezui-press-out) ease-out,
                transform var(--ezui-press-out) ease-out;
  }
  /* The shrink is what reads as pushing in. Colour alone read as a flash,
     whichever direction it went. Chosen on a real iPhone against 97%, and
     against both with a 1px sink, which felt like the button was falling
     rather than being pressed. */
  /* data-no-shrink: the colour still changes, the button stays put. For a
     button that is holding something open underneath it, where shrinking
     the button would drag the thing it opened about with it. The dropdown
     sets this on its own trigger. */
  .ezui-button[data-ezui-pressed]:not([data-no-shrink]):not(.quinary) {
    transform: scale(var(--ezui-press-scale));
    transition: background-color var(--ezui-press-in) ease-out,
                color var(--ezui-press-in) ease-out,
                border-color var(--ezui-press-in) ease-out,
                transform var(--ezui-press-in) ease-out;
  }
  /* A tier takes the fill it has on hover. No tier named is the loud look,
     so those two go together, and every tier is named here so that a fill
     is only ever put on a button that has one at rest. Written as a plain
     .ezui-button this painted the loud fill onto quaternary, which has no
     box at all, so a tap put an accent-coloured block behind the words. */
  .ezui-button[data-ezui-pressed]:not(.secondary):not(.tertiary):not(.quaternary):not(.quinary),
  .ezui-button.primary[data-ezui-pressed] { background: var(--ezui-fill-loud-hover); }
  .ezui-button.secondary[data-ezui-pressed] { background: var(--ezui-fill-normal-hover); }
  .ezui-button.tertiary[data-ezui-pressed] { background: var(--ezui-fill-quiet-hover); }
  .ezui-button.quinary[data-ezui-pressed] { background: var(--ezui-fill-quiet-hover); }
  .ezui-button.quinary[aria-pressed="true"][data-ezui-pressed] { background: var(--ezui-accent-hover); }
  /* Quaternary shows the shrink and nothing else. It is words, and the
     shrink already says it was pushed; a colour on top says it twice. The
     one exception is a page asking for it by name with data-text. */
  .ezui-button[data-text="accent"][data-ezui-pressed],
  .ezui-button[data-text="brand"][data-ezui-pressed] { color: var(--ezui-text-accent); }
}
