/* GENERATED by web/build.mjs from core/tokens.json — do not edit by hand. */
/*
 * Structural component CSS — the parts that DON'T vary by color role.
 * Hand-authored. build.mjs concatenates this with the generated per-role
 * variant classes (.mp-btn-primary, .mp-alert-danger, …) into dist/components.css.
 *
 * RULES (see COMPONENTS.md):
 *   1. Every value is a var(--…) from theme.css. No literal hex, no magic px
 *      that should be a token. If a value is missing, add the token to
 *      core/tokens.json — never hardcode it here.
 *   2. Zero JavaScript. Interactive components style NATIVE elements
 *      (<details>, <dialog>) so the browser owns behavior and this file stays
 *      SSR-safe and framework-agnostic.
 *   3. Class prefix is `mp-` to avoid collisions with a consumer's own CSS.
 *   4. NOTHING in this file branches on light or dark. There is no
 *      [data-theme=dark] selector here and there must never be one: a rule
 *      keyed to the root's mode is wrong inside a nested scope, which is the
 *      whole point of the mode being a token. Pick the token that carries the
 *      MEANING and both modes follow:
 *        --bg-body      the page ground        --bg-raised   a card/panel/menu/input on it
 *        --bg-alt       the other ground       --bg-accent   a selected or hovered row
 *        --ink-<role>   the role as ink        --c-<role>    the role as a fill
 *        --surface-<role>-tint  a role-tinted surface, with --ink-<role>-tint on it
 *      Using --c-primary as INK is the mistake to watch for: it is a mid-dark
 *      purple, so it reads on white and disappears on navy. --ink-primary is the
 *      same hex in light and shifts to the 300 in dark.
 *      The ONE exception is the always-dark band (.mp-btn-outline-white,
 *      .mp-accordion-dark, .mp-surface-dark/-footer): those are dark in both
 *      modes by definition, so they key off --c-white and the --*-on-dark roles.
 *
 * Ports the patterns proven in the Overlook marketing site, re-skinned onto
 * MakePop tokens.
 */

/* ==========================================================================
   Box model — components own theirs.
   We cannot assume a consumer ships a `* { box-sizing: border-box }` reset, and
   we must not impose a global one on their page. So scope it to our own classes.
   Without this, anything combining an explicit width with padding + border
   (.mp-input, .mp-btn-block, .mp-dialog, .mp-card in a grid track) overflows its
   container — e.g. a 100%-wide input blows past its column by padding + border.
   ========================================================================== */

[class^="mp-"],
[class*=" mp-"] {
  box-sizing: border-box;
}

/* ==========================================================================
   Buttons — base + sizes. Color variants are generated per role.
   ========================================================================== */

.mp-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  font-family: var(--font-body);
  font-size: var(--fs-3);
  font-weight: var(--fw-700);
  line-height: var(--lh-normal);
  text-decoration: none;
  text-align: center;
  cursor: pointer;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-4);
  transition:
    transform 0.2s ease,
    box-shadow 0.2s ease,
    background-color 0.2s ease,
    border-color 0.2s ease,
    color 0.2s ease;
}

.mp-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgb(0 0 0 / 15%);
}

.mp-btn:active {
  transform: translateY(0);
  box-shadow: 0 2px 4px rgb(0 0 0 / 10%);
}

.mp-btn:focus-visible {
  outline: 2px solid var(--ink-primary);
  outline-offset: 2px;
}

.mp-btn:disabled,
.mp-btn[aria-disabled="true"] {
  opacity: 0.6;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

/* Respect users who don't want motion — the lift is decorative. */
@media (prefers-reduced-motion: reduce) {
  .mp-btn {
    transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
  }

  .mp-btn:hover,
  .mp-btn:active {
    transform: none;
  }
}

.mp-btn-xs {
  padding: var(--space-1) var(--space-2);
  font-size: var(--fs-1);
}

.mp-btn-sm {
  padding: var(--space-1) var(--space-3);
  font-size: var(--fs-2);
}

.mp-btn-lg {
  padding: var(--space-3) var(--space-6);
  font-size: var(--fs-5);
}

.mp-btn-xl {
  padding: var(--space-4) var(--space-7);
  font-size: var(--fs-6);
}

.mp-btn-block {
  display: flex;
  width: 100%;
}

.mp-btn-rounded {
  border-radius: var(--radius-pill);
}

/* On dark backgrounds — the one variant that keys off a neutral, not a role. */
.mp-btn-outline-white {
  background-color: transparent;
  color: var(--c-white);
  border-color: var(--c-white);
}

.mp-btn-outline-white:hover,
.mp-btn-outline-white:active {
  background-color: var(--c-white);
  color: var(--c-primary);
}

/* ==========================================================================
   Badges / tags / status dots — base. Color variants generated per role.
   ========================================================================== */

.mp-badge {
  display: inline-block;
  padding: 0.25em 0.6em;
  font-family: var(--font-body);
  font-size: var(--fs-1);
  font-weight: var(--fw-700);
  line-height: 1;
  text-align: center;
  white-space: nowrap;
  vertical-align: baseline;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
}

.mp-badge:empty {
  display: none;
}

.mp-badge-pill {
  padding-left: 0.8em;
  padding-right: 0.8em;
  border-radius: var(--radius-pill);
}

.mp-badge-square {
  border-radius: 0;
}

.mp-badge-rounded {
  border-radius: var(--radius-md);
}

.mp-badge-sm {
  padding: 0.125em 0.4em;
  font-size: 0.65rem;
}

.mp-badge-lg {
  padding: 0.35em 0.8em;
  font-size: var(--fs-2);
}

.mp-tag {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 0.125rem 0.625rem;
  font-family: var(--font-body);
  font-size: var(--fs-2);
  border-radius: var(--radius-pill);
}

.mp-status {
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
}

@keyframes mp-status-pulse {
  0%,
  100% {
    opacity: 1;
  }

  50% {
    opacity: 0.4;
  }
}

.mp-status-pulse {
  animation: mp-status-pulse 2s infinite;
}

@media (prefers-reduced-motion: reduce) {
  .mp-status-pulse {
    animation: none;
  }
}

/* ==========================================================================
   Alerts + callouts — base. Color variants generated per role.
   ========================================================================== */

/* Sizing tracks Phoenix's alert: even 24px padding on all four sides and a md
   radius read as a substantial panel, not a thin strip. The three variant
   families are generated per role: .mp-alert-<role> (soft tint),
   .mp-alert-subtle-<role> (transparent + accent left border),
   .mp-alert-solid-<role> (filled). */
.mp-alert {
  position: relative;
  padding: var(--space-4);
  margin-bottom: var(--space-3);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  font-family: var(--font-body);
}

/* Let an alert hold a heading + body without fighting the consumer's margins:
   the first/last child's outer margins collapse into the alert's own padding. */
.mp-alert > :first-child { margin-top: 0; }
.mp-alert > :last-child { margin-bottom: 0; }

.mp-alert-heading {
  margin: 0 0 var(--space-1);
  font-family: var(--font-heading);
  font-size: var(--fs-5);
  font-weight: var(--fw-600);
  color: inherit;
}

.mp-alert a,
.mp-alert-link {
  color: inherit;
  font-weight: var(--fw-600);
  text-decoration: underline;
}

.mp-alert-sm {
  padding: var(--space-2) var(--space-3);
  font-size: var(--fs-2);
}

.mp-alert-dismissible {
  padding-right: var(--space-7);
}

.mp-alert-close {
  position: absolute;
  top: var(--space-2);
  right: var(--space-3);
  padding: var(--space-1);
  background: none;
  border: none;
  font-size: var(--fs-6);
  line-height: 1;
  color: inherit;
  opacity: 0.5;
  cursor: pointer;
}

.mp-alert-close:hover {
  opacity: 0.9;
}

.mp-callout {
  padding: var(--space-3);
  border: 1px solid transparent;
  border-left-width: 4px;
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
}

.mp-callout-title {
  font-family: var(--font-heading);
  font-weight: var(--fw-700);
  margin: 0 0 var(--space-1);
}

.mp-callout-text {
  margin: 0;
}

/* ==========================================================================
   Card
   ========================================================================== */

.mp-card {
  display: flex;
  flex-direction: column;
  background-color: var(--bg-raised);
  border: 1px solid var(--border-card);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  transition: box-shadow 0.2s ease, transform 0.2s ease;
}

.mp-card-title {
  font-family: var(--font-heading);
  font-size: var(--fs-5);
  font-weight: var(--fw-600);
  color: var(--text-heading);
  margin: 0 0 var(--space-2);
}

.mp-card-body {
  color: var(--text-body);
  margin: 0;
}

.mp-card-footer {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--border-divider);
}

/* Opt-in hover lift — only for cards that are actually clickable. */
.mp-card-interactive {
  cursor: pointer;
}

.mp-card-interactive:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 16px rgb(0 0 0 / 10%);
}

.mp-card-dark {
  background-color: var(--bg-dark);
  border-color: transparent;
  color: var(--text-on-dark);
}

.mp-card-dark .mp-card-title {
  color: var(--text-on-dark);
}

.mp-card-dark .mp-card-body {
  color: var(--text-on-dark-muted);
}

@media (prefers-reduced-motion: reduce) {
  .mp-card-interactive:hover {
    transform: none;
  }
}

/* ==========================================================================
   Forms — styles native inputs, so they work in any framework and any <form>.
   ========================================================================== */

.mp-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin-bottom: var(--space-3);
}

.mp-label {
  font-family: var(--font-body);
  font-size: var(--fs-2);
  font-weight: var(--fw-600);
  color: var(--text-body);
}

.mp-input,
.mp-textarea,
.mp-select {
  font-family: var(--font-body);
  font-size: var(--fs-3);
  color: var(--text-body);
  background-color: var(--bg-raised);
  border: 1px solid var(--border-input);
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3);
  width: 100%;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.mp-input::placeholder,
.mp-textarea::placeholder {
  color: var(--text-muted);
}

.mp-input:focus-visible,
.mp-textarea:focus-visible,
.mp-select:focus-visible {
  outline: none;
  border-color: var(--ink-primary);
  box-shadow: 0 0 0 3px var(--surface-primary-tint);
}

.mp-input:disabled,
.mp-textarea:disabled,
.mp-select:disabled {
  background-color: var(--bg-alt);
  opacity: 0.7;
  cursor: not-allowed;
}

.mp-input[aria-invalid="true"],
.mp-textarea[aria-invalid="true"] {
  border-color: var(--ink-danger);
}

.mp-input[aria-invalid="true"]:focus-visible,
.mp-textarea[aria-invalid="true"]:focus-visible {
  box-shadow: 0 0 0 3px var(--surface-danger-tint);
}

.mp-textarea {
  min-height: 100px;
  resize: vertical;
}

/* Native <select> renders a dated OS-drawn arrow. Suppress it and paint our own
   caret as a background SVG — the same technique Bootstrap uses — so the control
   matches the inputs. The caret hex is the muted-gray token's value: an SVG
   background can't take a var(), so it's the one spot a literal is unavoidable;
   keep it in sync with --c-gray-600 / --text-muted. */
.mp-select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: var(--space-6);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%236B6F8C' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m4 6 4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-3) center;
  background-size: 1em;
}

/* Size variants — mirror Bootstrap's .form-control-sm / -lg. Pair with any of
   .mp-input / .mp-select / .mp-textarea. */
.mp-input-sm,
.mp-select-sm,
.mp-textarea-sm {
  padding: var(--space-1) var(--space-2);
  font-size: var(--fs-2);
  border-radius: var(--radius-sm);
}

.mp-input-lg,
.mp-select-lg,
.mp-textarea-lg {
  padding: var(--space-3) var(--space-4);
  font-size: var(--fs-5);
}

/* Give the sized selects room for the caret again (padding-right was overridden). */
.mp-select-sm { padding-right: var(--space-5); }
.mp-select-lg { padding-right: var(--space-7); }

.mp-hint {
  font-size: var(--fs-2);
  color: var(--text-muted);
}

.mp-error {
  font-size: var(--fs-2);
  color: var(--ink-danger-strong);
}

/* --- Checkboxes, radios, switches ----------------------------------------
   Styles native <input type=checkbox|radio> so v-model and native form
   submission still work. Same appearance:none + background-SVG approach as
   Bootstrap's .form-check-input; the checked fill is --c-primary and the glyph
   is white (primary is a filled surface that takes white ink). */

.mp-check {
  appearance: none;
  -webkit-appearance: none;
  flex-shrink: 0;
  width: 1.15em;
  height: 1.15em;
  margin: 0;
  vertical-align: -0.2em;
  background-color: var(--bg-raised);
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  border: 1px solid var(--border-input);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.mp-check[type="radio"] {
  border-radius: 50%;
}

.mp-check:focus-visible {
  outline: none;
  border-color: var(--ink-primary);
  box-shadow: 0 0 0 3px var(--surface-primary-tint);
}

.mp-check:checked {
  background-color: var(--c-primary);
  border-color: var(--c-primary);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round' d='M5 10l3.5 3.5L15 6.5'/%3E%3C/svg%3E");
}

.mp-check[type="radio"]:checked {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Ccircle cx='10' cy='10' r='4' fill='%23fff'/%3E%3C/svg%3E");
}

.mp-check:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Switch — a wider pill with a knob that slides on :checked. */
.mp-switch {
  width: 2em;
  border-radius: var(--radius-pill);
  background-position: left center;
  background-size: auto 100%;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='5' fill='%236B6F8C'/%3E%3C/svg%3E");
  transition: background-color 0.15s ease, background-position 0.15s ease, border-color 0.15s ease;
}

.mp-switch:checked {
  background-position: right center;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='5' fill='%23fff'/%3E%3C/svg%3E");
}

@media (prefers-reduced-motion: reduce) {
  .mp-check,
  .mp-switch {
    transition: none;
  }
}

/* A row: control + its label, aligned. */
.mp-check-field {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.mp-check-field label {
  font-family: var(--font-body);
  font-size: var(--fs-3);
  color: var(--text-body);
  cursor: pointer;
}

/* --- Input group — prepend/append addons to an input ----------------------
   Mirrors Bootstrap's .input-group. Cells butt together with collapsed inner
   radii; the -1px pull keeps a single shared border between them. */
.mp-input-group {
  display: flex;
  align-items: stretch;
  width: 100%;
}

.mp-input-group > .mp-input,
.mp-input-group > .mp-select {
  position: relative;
  flex: 1 1 auto;
  width: 1%;
  min-width: 0;
}

.mp-input-group-text {
  display: flex;
  align-items: center;
  white-space: nowrap;
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-body);
  font-size: var(--fs-3);
  color: var(--text-muted);
  background-color: var(--bg-alt);
  border: 1px solid var(--border-input);
  border-radius: var(--radius-md);
}

.mp-input-group > :not(:first-child) {
  margin-left: -1px;
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
}

.mp-input-group > :not(:last-child) {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}

/* The focused input has to sit above its neighbours so its focus ring isn't
   clipped by the addon's border. */
.mp-input-group > .mp-input:focus-visible,
.mp-input-group > .mp-select:focus-visible {
  z-index: 1;
}

/* ==========================================================================
   Table
   ========================================================================== */

.mp-table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-body);
  font-size: var(--fs-2);
  color: var(--text-body);
}

.mp-table th,
.mp-table td {
  padding: var(--space-2) var(--space-3);
  text-align: left;
  border-bottom: 1px solid var(--border-divider);
}

.mp-table thead th {
  background-color: var(--bg-dark);
  color: var(--text-on-dark);
  font-family: var(--font-heading);
  font-weight: var(--fw-600);
}

.mp-table thead th:first-child {
  border-top-left-radius: var(--radius-md);
}

.mp-table thead th:last-child {
  border-top-right-radius: var(--radius-md);
}

.mp-table-striped tbody tr:nth-child(odd) {
  background-color: var(--bg-alt);
}

/* --- Bootstrap-esque table utilities — additive, combine freely ----------- */

/* Condensed: half the cell padding. */
.mp-table-sm th,
.mp-table-sm td {
  padding: var(--space-1) var(--space-2);
}

/* Bordered: a box around every cell, not just row rules. */
.mp-table-bordered th,
.mp-table-bordered td {
  border: 1px solid var(--border-divider);
}

/* Borderless: drop the row rules entirely. */
.mp-table-borderless th,
.mp-table-borderless td {
  border: 0;
}

/* Row hover — the highlight lands after striping, so it wins on striped tables. */
.mp-table-hover tbody tr:hover {
  background-color: var(--bg-accent);
}

/* Opt-in highlighted row/cell. */
.mp-table-active {
  background-color: var(--bg-accent);
}

/* Wrap a table in .mp-table-responsive to let it scroll on narrow screens
   instead of forcing the page to. */
.mp-table-responsive {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* ==========================================================================
   Accordion — native <details>/<summary>. Browser owns open/close + a11y.
   Zero JS, renders correctly server-side.
   ========================================================================== */

.mp-accordion {
  background-color: var(--bg-raised);
  border: 1px solid var(--border-card);
  border-radius: var(--radius-md);
  overflow: hidden;
  transition: box-shadow 0.2s ease;
  /* Let block-size: auto animate on ::details-content below. Inherited, so
     declaring it here covers the whole disclosure. */
  interpolate-size: allow-keywords;
}

.mp-accordion + .mp-accordion {
  margin-top: var(--space-2);
}

.mp-accordion:hover {
  box-shadow: 0 2px 8px rgb(0 0 0 / 10%);
}

.mp-accordion > summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  cursor: pointer;
  user-select: none;
  font-family: var(--font-heading);
  font-size: var(--fs-4);
  font-weight: var(--fw-600);
  color: var(--text-heading);
  list-style: none;
  transition: background-color 0.2s ease, padding 0.3s ease;
}

/* Hide the native disclosure triangle in both engines. */
.mp-accordion > summary::-webkit-details-marker {
  display: none;
}

.mp-accordion > summary::marker {
  content: "";
}

.mp-accordion > summary:hover {
  background-color: var(--bg-alt);
}

.mp-accordion > summary:focus-visible {
  outline: 2px solid var(--ink-primary);
  outline-offset: -2px;
}

/* CSS-drawn chevron — no icon font or SVG dependency. Deliberately muted ink,
   not the loud --c-cta: the chevron is an affordance, not a call to action, so it
   should recede rather than compete with the summary text for attention. */
.mp-accordion > summary::after {
  content: "";
  flex-shrink: 0;
  width: 0.5em;
  height: 0.5em;
  border-right: 2px solid var(--text-muted);
  border-bottom: 2px solid var(--text-muted);
  transform: rotate(45deg) translate(-0.125em, -0.125em);
  transition: transform 0.2s ease;
}

.mp-accordion[open] > summary::after {
  transform: rotate(-135deg) translate(-0.125em, -0.125em);
}

/* Open: the header's own bottom padding would stack on top of the content's
   top padding, so the gap above the content reads larger than the gap below.
   Drop it while open — the content box now owns a symmetric gap top and bottom. */
.mp-accordion[open] > summary {
  padding-bottom: 0;
}

.mp-accordion-content {
  padding: var(--space-3);
  color: var(--text-body);
}

/* Vertical expand/collapse. The browser animates the native disclosure via
   ::details-content (paired with interpolate-size on .mp-accordion, which lets
   its block-size: auto animate). Zero JS. Engines without ::details-content
   simply snap open — progressive enhancement, in keeping with "the browser
   owns the behavior". */
.mp-accordion::details-content {
  block-size: 0;
  overflow: hidden;
  transition:
    block-size 0.3s ease,
    content-visibility 0.3s ease allow-discrete;
}

.mp-accordion[open]::details-content {
  block-size: auto;
}

@media (prefers-reduced-motion: reduce) {
  .mp-accordion > summary,
  .mp-accordion > summary::after,
  .mp-accordion::details-content {
    transition: none;
  }
}

/* Dark-surface accordion */
.mp-accordion-dark {
  background-color: color-mix(in srgb, var(--c-white) 5%, transparent);
  border-color: color-mix(in srgb, var(--c-white) 10%, transparent);
}

.mp-accordion-dark > summary {
  color: var(--text-on-dark);
}

/* The muted gray chevron can't clear the navy surface — key it to the on-dark
   muted ink so it stays visible without shouting. */
.mp-accordion-dark > summary::after {
  border-right-color: var(--text-on-dark-muted);
  border-bottom-color: var(--text-on-dark-muted);
}

.mp-accordion-dark > summary:hover {
  background-color: color-mix(in srgb, var(--c-white) 3%, transparent);
}

.mp-accordion-dark .mp-accordion-content {
  color: var(--text-on-dark-muted);
}

/* ==========================================================================
   Dialog — native <dialog>. Browser owns focus trap, backdrop, Esc.
   Open with el.showModal(); no library needed.
   ========================================================================== */

.mp-dialog {
  border: none;
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  background-color: var(--bg-raised);
  color: var(--text-body);
  font-family: var(--font-body);
  max-width: 32rem;
  width: calc(100% - var(--space-5));
  box-shadow: 0 12px 40px rgb(0 0 0 / 25%);
  /* Fade + gentle rise on open, instead of snapping in. The browser toggles
     [open] and lifts the dialog into the top layer; @starting-style gives the
     opening frame a state to animate FROM, and allow-discrete on display/overlay
     lets the CLOSE fade too rather than vanishing. Zero JS beyond showModal().
     Engines without @starting-style just show it instantly — progressive. */
  opacity: 0;
  transform: translateY(1rem) scale(0.98);
  transition:
    opacity 0.2s ease,
    transform 0.2s ease,
    overlay 0.2s ease allow-discrete,
    display 0.2s ease allow-discrete;
}

.mp-dialog[open] {
  opacity: 1;
  transform: none;
}

@starting-style {
  .mp-dialog[open] {
    opacity: 0;
    transform: translateY(1rem) scale(0.98);
  }
}

.mp-dialog::backdrop {
  background: rgb(0 0 0 / 50%);
  opacity: 0;
  transition:
    opacity 0.2s ease,
    overlay 0.2s ease allow-discrete,
    display 0.2s ease allow-discrete;
}

.mp-dialog[open]::backdrop {
  opacity: 1;
}

@starting-style {
  .mp-dialog[open]::backdrop {
    opacity: 0;
  }
}

/* Blur the page behind the dialog. Opt-in class — backdrop-filter has a real
   paint cost, so the default stays a plain dim. */
.mp-dialog-blur::backdrop {
  backdrop-filter: blur(5px);
}

/* Width options — override the 32rem default. Width stays fluid, so each still
   shrinks to fit small screens. */
.mp-dialog-sm { max-width: 22rem; }
.mp-dialog-lg { max-width: 48rem; }
.mp-dialog-xl { max-width: 64rem; }

/* Reduced motion: no fade or slide, just appear. */
@media (prefers-reduced-motion: reduce) {
  .mp-dialog,
  .mp-dialog::backdrop {
    transition: none;
  }

  .mp-dialog {
    transform: none;
  }
}

.mp-dialog-title {
  font-family: var(--font-heading);
  font-size: var(--fs-6);
  font-weight: var(--fw-700);
  color: var(--text-heading);
  margin: 0 0 var(--space-2);
}

.mp-dialog-body {
  margin: 0 0 var(--space-4);
}

.mp-dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
}

/* ==========================================================================
   Progress — purely presentational. A track with a fill whose width the
   consumer drives (style="width:…" or a var). Zero JS. Bar color variants
   (.mp-progress-bar-<role>) are generated; the default bar is primary.
   ========================================================================== */

.mp-progress {
  display: flex;
  height: var(--space-2);
  overflow: hidden;
  background-color: var(--bg-alt);
  border-radius: var(--radius-pill);
}

.mp-progress-bar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 0;
  height: 100%;
  background-color: var(--c-primary);
  color: var(--ink-primary-fill);
  font-size: var(--fs-1);
  font-weight: var(--fw-600);
  white-space: nowrap;
  transition: width 0.4s ease;
}

.mp-progress-sm { height: var(--space-1); }
.mp-progress-lg { height: var(--space-3); }

/* Diagonal candy-stripe, drawn with a repeating gradient — no image. */
.mp-progress-striped .mp-progress-bar {
  background-image: linear-gradient(
    45deg,
    rgb(255 255 255 / 15%) 25%,
    transparent 25%,
    transparent 50%,
    rgb(255 255 255 / 15%) 50%,
    rgb(255 255 255 / 15%) 75%,
    transparent 75%,
    transparent
  );
  background-size: 1rem 1rem;
}

@keyframes mp-progress-stripes {
  from { background-position: 1rem 0; }
  to { background-position: 0 0; }
}

.mp-progress-animated .mp-progress-bar {
  animation: mp-progress-stripes 1s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
  .mp-progress-bar { transition: none; }
  .mp-progress-animated .mp-progress-bar { animation: none; }
}

/* ==========================================================================
   Spinners — CSS-only loading indicators. Both inherit currentColor, so a
   spinner takes the surrounding text color by default (visible inside a filled
   .mp-btn without any extra class) and .mp-text-<role> recolors it — no per-role
   variants, and nothing forces a color that could vanish on its own background.
   ========================================================================== */

@keyframes mp-spin {
  to { transform: rotate(360deg); }
}

.mp-spinner {
  display: inline-block;
  width: var(--space-4);
  height: var(--space-4);
  vertical-align: -0.125em;
  border: 3px solid color-mix(in srgb, currentColor 25%, transparent);
  border-right-color: currentColor;
  border-radius: 50%;
  animation: mp-spin 0.75s linear infinite;
}

.mp-spinner-sm { width: var(--space-3); height: var(--space-3); border-width: 2px; }
.mp-spinner-lg { width: var(--space-6); height: var(--space-6); border-width: 5px; }

/* Pulsing dot — a quieter, label-adjacent alternative to the ring. */
@keyframes mp-spinner-grow {
  0% { transform: scale(0); }
  50% { opacity: 1; transform: none; }
  100% { opacity: 0; }
}

.mp-spinner-grow {
  display: inline-block;
  width: var(--space-4);
  height: var(--space-4);
  vertical-align: -0.125em;
  background-color: currentColor;
  border-radius: 50%;
  opacity: 0;
  animation: mp-spinner-grow 0.75s linear infinite;
}

.mp-spinner-grow-sm { width: var(--space-3); height: var(--space-3); }
.mp-spinner-grow-lg { width: var(--space-6); height: var(--space-6); }

/* A spinner conveys "still working", so reduced-motion slows it rather than
   freezing it — a stopped spinner reads as a broken one. */
@media (prefers-reduced-motion: reduce) {
  .mp-spinner,
  .mp-spinner-grow { animation-duration: 1.5s; }
}

/* ==========================================================================
   Placeholder / skeleton — greyed shapes standing in for content while it
   loads. Purely presentational; the consumer swaps them for real content.
   Set width inline (style="width:60%") or with your own layout.
   ========================================================================== */

.mp-placeholder {
  display: inline-block;
  min-height: 1em;
  vertical-align: middle;
  background-color: var(--bg-placeholder);
  border-radius: var(--radius-sm);
  opacity: 0.5;
  cursor: wait;
  user-select: none;
}

/* Whole paragraphs/lines: give each .mp-placeholder its own row. */
.mp-placeholder-block .mp-placeholder {
  display: block;
  margin-bottom: var(--space-2);
}

/* Glow — the group pulses opacity in unison. */
@keyframes mp-placeholder-glow {
  50% { opacity: 0.2; }
}

.mp-placeholder-glow .mp-placeholder {
  animation: mp-placeholder-glow 2s ease-in-out infinite;
}

/* Wave — a highlight sweeps across, via an animated mask. */
@keyframes mp-placeholder-wave {
  100% { mask-position: -200% 0; }
}

.mp-placeholder-wave .mp-placeholder {
  mask-image: linear-gradient(105deg, rgb(0 0 0 / 100%) 40%, rgb(0 0 0 / 20%) 50%, rgb(0 0 0 / 100%) 60%);
  -webkit-mask-image: linear-gradient(105deg, rgb(0 0 0 / 100%) 40%, rgb(0 0 0 / 20%) 50%, rgb(0 0 0 / 100%) 60%);
  mask-size: 200% 100%;
  -webkit-mask-size: 200% 100%;
  animation: mp-placeholder-wave 1.8s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
  .mp-placeholder-glow .mp-placeholder,
  .mp-placeholder-wave .mp-placeholder { animation: none; }
}

/* ==========================================================================
   Dropdown menu — the SKIN of a menu popover. Built on native <details>/<summary>
   so the browser owns open/close with zero JS (same doctrine as the accordion).
   The <summary> is the trigger — style it as a .mp-btn. Note the native limit:
   <details> doesn't close on outside-click or Esc; a consumer that wants that
   adds ~5 lines. See COMPONENTS.md.
   ========================================================================== */

.mp-dropdown {
  position: relative;
  display: inline-block;
}

.mp-dropdown > summary {
  cursor: pointer;
  list-style: none;
}

.mp-dropdown > summary::-webkit-details-marker { display: none; }
.mp-dropdown > summary::marker { content: ""; }

.mp-dropdown-menu {
  position: absolute;
  top: calc(100% + var(--space-1));
  left: 0;
  z-index: var(--z-dropdown);
  min-width: 12rem;
  padding: var(--space-1);
  background-color: var(--bg-raised);
  border: 1px solid var(--border-card);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
}

/* Fade the menu in/out instead of snapping — same softening as .mp-dialog.
   Chromium collapses a closed <details> by setting content-visibility:hidden on
   the ::details-content pseudo, so THAT is the element to animate (a transition
   on .mp-dropdown-menu itself never takes — the child isn't what toggles).
   @starting-style supplies the opening frame; content-visibility in the
   transition with allow-discrete keeps the panel painted through the closing
   fade rather than vanishing. A touch quicker than the modal (0.15s) since a
   menu is small and opened often. Engines without ::details-content (Firefox,
   Safari today) don't match this and just show the menu — progressive.
   Note: only opacity, not the modal's translate — a transform on the pseudo
   would become the containing block for the absolutely-placed menu and shift it
   off its anchor, so the drop is deliberately left out. */
.mp-dropdown::details-content {
  opacity: 0;
  transition:
    opacity 0.15s ease,
    content-visibility 0.15s ease allow-discrete;
}

.mp-dropdown[open]::details-content {
  opacity: 1;
}

@starting-style {
  .mp-dropdown[open]::details-content {
    opacity: 0;
  }
}

/* Reduced motion: no fade, just appear. */
@media (prefers-reduced-motion: reduce) {
  .mp-dropdown::details-content {
    transition: none;
  }
}

/* Right-align the menu under the trigger. */
.mp-dropdown-menu-end {
  left: auto;
  right: 0;
}

.mp-dropdown-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-body);
  font-size: var(--fs-3);
  color: var(--text-body);
  text-align: left;
  text-decoration: none;
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.mp-dropdown-item:hover,
.mp-dropdown-item:focus-visible {
  background-color: var(--bg-alt);
  outline: none;
}

.mp-dropdown-item.mp-active {
  background-color: var(--bg-accent);
  color: var(--text-on-accent);
}

.mp-dropdown-item:disabled,
.mp-dropdown-item[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
}

.mp-dropdown-header {
  padding: var(--space-1) var(--space-3);
  font-family: var(--font-body);
  font-size: var(--fs-1);
  font-weight: var(--fw-600);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}

.mp-dropdown-divider {
  height: 1px;
  margin: var(--space-1) 0;
  border: none;
  background-color: var(--border-divider);
}

/* ==========================================================================
   Offcanvas — an edge-anchored drawer. Built on native <dialog>: open with
   el.showModal() and the browser supplies the backdrop, focus trap, and Esc —
   same doctrine as .mp-dialog, just pinned to a side and full-height. The
   directional class sets which edge it slides from. Zero JS beyond showModal().
   ========================================================================== */

.mp-offcanvas {
  position: fixed;
  padding: 0;
  margin: 0;
  max-width: 100%;
  max-height: 100dvh;
  border: none;
  background-color: var(--bg-raised);
  color: var(--text-body);
  font-family: var(--font-body);
  box-shadow: var(--shadow-xl);
  flex-direction: column;
  transition:
    transform 0.3s ease,
    overlay 0.3s ease allow-discrete,
    display 0.3s ease allow-discrete;
}

/* Only laid out (flex column) while open; closed, the UA's display:none wins. */
.mp-offcanvas[open] {
  display: flex;
  transform: none;
}

.mp-offcanvas::backdrop {
  background: rgb(0 0 0 / 40%);
}

/* Edge + off-screen resting transform. --mp-oc-w sizes the side drawers. */
.mp-offcanvas-start,
.mp-offcanvas-end { width: var(--mp-oc-w, 22rem); height: 100dvh; }

.mp-offcanvas-start { inset: 0 auto 0 0; transform: translateX(-100%); }
.mp-offcanvas-end { inset: 0 0 0 auto; transform: translateX(100%); }
.mp-offcanvas-top { inset: 0 0 auto 0; width: 100%; transform: translateY(-100%); }
.mp-offcanvas-bottom { inset: auto 0 0 0; width: 100%; transform: translateY(100%); }

/* @starting-style gives the opening frame a state to slide FROM; without it the
   drawer would snap in. Engines lacking it just appear — progressive. */
@starting-style {
  .mp-offcanvas-start[open] { transform: translateX(-100%); }
  .mp-offcanvas-end[open] { transform: translateX(100%); }
  .mp-offcanvas-top[open] { transform: translateY(-100%); }
  .mp-offcanvas-bottom[open] { transform: translateY(100%); }
}

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

.mp-offcanvas-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4);
  border-bottom: 1px solid var(--border-divider);
}

.mp-offcanvas-title {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--fs-6);
  font-weight: var(--fw-700);
  color: var(--text-heading);
}

.mp-offcanvas-body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: var(--space-4);
}

.mp-offcanvas-footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  padding: var(--space-4);
  border-top: 1px solid var(--border-divider);
}

/* ==========================================================================
   Scrollspy nav — the SKIN of an in-page section nav. Like .mp-reveal, the
   class is inert until the consumer toggles .mp-active on the current link
   (the ~12-line IntersectionObserver is in example.html). Vertical by default;
   add .mp-scrollspy-horizontal for an underline tab-bar.
   ========================================================================== */

.mp-scrollspy {
  position: sticky;
  top: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  list-style: none;
  margin: 0;
  padding: 0;
}

.mp-scrollspy-link {
  display: block;
  padding: var(--space-1) var(--space-3);
  border-left: 2px solid var(--border-divider);
  font-family: var(--font-body);
  font-size: var(--fs-2);
  color: var(--text-muted);
  text-decoration: none;
  transition: color 0.15s ease, border-color 0.15s ease;
}

.mp-scrollspy-link:hover {
  color: var(--text-body);
}

.mp-scrollspy-link.mp-active {
  color: var(--ink-primary);
  border-left-color: var(--ink-primary);
  font-weight: var(--fw-600);
}

/* Horizontal: an underline tab-bar instead of a left rail. */
.mp-scrollspy-horizontal {
  position: static;
  flex-direction: row;
  gap: var(--space-2);
  border-bottom: 1px solid var(--border-divider);
}

.mp-scrollspy-horizontal .mp-scrollspy-link {
  border-left: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}

.mp-scrollspy-horizontal .mp-scrollspy-link.mp-active {
  border-left: none;
  border-bottom-color: var(--ink-primary);
}

@media (prefers-reduced-motion: reduce) {
  .mp-scrollspy-link { transition: none; }
}

/* ==========================================================================
   Icons — we don't ship an icon font. Icons are a downstream dependency;
   Font Awesome is the house choice. A bare <i class="fa-solid fa-…"> already
   inherits color and sizes to the surrounding font-size, so it drops into any
   component (buttons have gap:0.5em for exactly this). These classes are the
   optional extras: an inline sizing hook and a circular/rounded icon container.
   See COMPONENTS.md § Icons.
   ========================================================================== */

/* Nudge an inline icon to sit on the text baseline and scale relative to it. */
.mp-icon {
  display: inline-block;
  vertical-align: -0.075em;
  line-height: 1;
}

.mp-icon-lg { font-size: 1.25em; }
.mp-icon-xl { font-size: 1.5em; }

/* A tinted container to sit an icon in — feature lists, stat cards, list rows.
   Defaults to the accent tint + primary ink; pair with any role tint/text pair
   (e.g. .mp-tag-success sets both) or override the two vars inline. */
.mp-icon-box {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  background-color: var(--bg-accent);
  color: var(--text-on-accent);
}

.mp-icon-box-sm { width: 1.75rem; height: 1.75rem; font-size: var(--fs-2); }
.mp-icon-box-lg { width: 3.25rem; height: 3.25rem; font-size: var(--fs-6); }

/* Rounded-square instead of a circle. */
.mp-icon-box-square { border-radius: var(--radius-md); }

/* ==========================================================================
   Divider
   ========================================================================== */

.mp-divider {
  border: none;
  border-top: 1px solid var(--border-divider);
  margin: var(--space-4) 0;
}

/* ==========================================================================
   Prose — base typography for long-form/authored content.
   Scoped to a class so it never fights a consumer's own reset.
   ========================================================================== */

.mp-prose {
  font-family: var(--font-body);
  color: var(--text-body);
  line-height: var(--lh-normal);
}

.mp-prose h1,
.mp-prose h2,
.mp-prose h3,
.mp-prose h4,
.mp-prose h5,
.mp-prose h6 {
  font-family: var(--font-heading);
  color: var(--text-heading);
  font-weight: var(--fw-700);
  line-height: var(--lh-tight);
  margin: 0 0 var(--space-3);
}

.mp-prose h1 {
  font-size: var(--fs-10);
}

.mp-prose h2 {
  font-size: var(--fs-8);
  line-height: var(--lh-snug);
}

.mp-prose h3 {
  font-size: var(--fs-6);
  line-height: var(--lh-snug);
}

.mp-prose h4 {
  font-size: var(--fs-4);
}

.mp-prose h5 {
  font-size: var(--fs-2);
  text-transform: uppercase;
}

.mp-prose h6 {
  font-size: var(--fs-1);
}

.mp-prose p {
  margin: 0 0 var(--space-3);
}

.mp-prose a {
  color: var(--text-link);
  text-decoration: underline;
}

.mp-prose ul,
.mp-prose ol {
  margin: 0 0 var(--space-3);
  padding-left: var(--space-4);
}

.mp-prose li {
  margin-bottom: var(--space-1);
}

.mp-prose code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background-color: var(--bg-alt);
  border-radius: var(--radius-sm);
  padding: 0.15em 0.4em;
}

.mp-prose blockquote {
  margin: 0 0 var(--space-3);
  padding-left: var(--space-3);
  border-left: 4px solid var(--c-cta);
  color: var(--text-muted);
}

@media (max-width: 767px) {
  .mp-prose h1 {
    font-size: var(--fs-8);
  }

  .mp-prose h2 {
    font-size: var(--fs-6);
  }

  .mp-prose h3 {
    font-size: var(--fs-5);
  }
}

/* ==========================================================================
   Utilities — deliberately just ONE family: color & elevation, the parts that
   carry a brand decision. No spacing/flex/display/sizing layer — that's generic
   layout every consumer's framework already ships, and duplicating it invites
   drift. See COMPONENTS.md § Utilities. Per-role .mp-text-<role>, .mp-bg-<role>,
   .mp-bg-<role>-subtle, and .mp-bg-gradient-<role> are generated; the neutral
   inks, surfaces, and shadows are here.
   ========================================================================== */

/* --- Elevation ------------------------------------------------------------ */
.mp-shadow-sm { box-shadow: var(--shadow-sm); }
.mp-shadow-md { box-shadow: var(--shadow-md); }
.mp-shadow-lg { box-shadow: var(--shadow-lg); }
.mp-shadow-xl { box-shadow: var(--shadow-xl); }
.mp-shadow-none { box-shadow: none; }

/* --- Text ink (the non-role inks; roles are generated) -------------------- */
.mp-text-heading { color: var(--text-heading); }
.mp-text-body { color: var(--text-body); }
.mp-text-muted { color: var(--text-muted); }
.mp-text-link { color: var(--text-link); }
.mp-text-on-dark { color: var(--text-on-dark); }
.mp-text-on-dark-muted { color: var(--text-on-dark-muted); }

/* --- Surfaces — background + the ink that's legible on it. The brand-coupled
   payoff: drop one class and the text color is already correct and accessible,
   the "ink is computed" idea applied to sections. On the dark surfaces the muted
   helper re-maps to the on-dark muted tone so .mp-text-muted stays readable. */
.mp-surface { background-color: var(--bg-body); color: var(--text-body); }
.mp-surface-alt { background-color: var(--bg-alt); color: var(--text-body); }
.mp-surface-accent { background-color: var(--bg-accent); color: var(--text-body); }
.mp-surface-dark { background-color: var(--bg-dark); color: var(--text-on-dark); }
.mp-surface-dark-alt { background-color: var(--bg-dark-alt); color: var(--text-on-dark); }
.mp-surface-footer { background-color: var(--bg-footer); color: var(--text-on-dark); }

.mp-surface-dark :is(h1, h2, h3, h4, h5, h6),
.mp-surface-dark-alt :is(h1, h2, h3, h4, h5, h6),
.mp-surface-footer :is(h1, h2, h3, h4, h5, h6) {
  color: var(--text-on-dark);
}

.mp-surface-dark .mp-text-muted,
.mp-surface-dark-alt .mp-text-muted,
.mp-surface-footer .mp-text-muted {
  color: var(--text-on-dark-muted);
}

/* ==========================================================================
   Scroll-reveal utilities — entrance animations as elements enter the viewport.
   Ported from the Overlook marketing site.

   These are pure CSS: each class sets a hidden resting state and transitions to
   its visible state when `mp-in-view` is added to the element. The class is
   INERT until then, so it honours rule 2 — this file still ships zero JS. What
   adds `mp-in-view` is the consumer's choice; the recommended ~12-line
   IntersectionObserver is in the style guide (example.html) and below:

     const io = new IntersectionObserver((entries, obs) => {
       for (const e of entries) if (e.isIntersecting) {
         e.target.classList.add("mp-in-view");
         obs.unobserve(e.target);            // animate once
       }
     }, { threshold: 0.15, rootMargin: "0px 0px -100px 0px" });
     document.querySelectorAll("[class*='mp-reveal'],.mp-stagger")
       .forEach((el) => io.observe(el));

   Every effect collapses to a no-op under prefers-reduced-motion (bottom of block).
   ========================================================================== */

/* Fade + rise — the default reveal. Add .mp-delay-* to stage several in. */
.mp-reveal {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.6s ease-out, transform 0.6s ease-out;
  transition-delay: var(--mp-reveal-delay, 0ms);
}

.mp-reveal.mp-in-view {
  opacity: 1;
  transform: translateY(0);
}

/* Fade only — no movement. */
.mp-reveal-fade {
  opacity: 0;
  transition: opacity 0.6s ease-out;
  transition-delay: var(--mp-reveal-delay, 0ms);
}

.mp-reveal-fade.mp-in-view {
  opacity: 1;
}

/* Slide in from the left. */
.mp-reveal-left {
  opacity: 0;
  transform: translateX(-30px);
  transition: opacity 0.6s ease-out, transform 0.6s ease-out;
  transition-delay: var(--mp-reveal-delay, 0ms);
}

.mp-reveal-left.mp-in-view {
  opacity: 1;
  transform: translateX(0);
}

/* Slide in from the right. */
.mp-reveal-right {
  opacity: 0;
  transform: translateX(30px);
  transition: opacity 0.6s ease-out, transform 0.6s ease-out;
  transition-delay: var(--mp-reveal-delay, 0ms);
}

.mp-reveal-right.mp-in-view {
  opacity: 1;
  transform: translateX(0);
}

/* Individual entrance-delay presets — pair with any .mp-reveal* class. */
.mp-delay-100 { --mp-reveal-delay: 100ms; }
.mp-delay-200 { --mp-reveal-delay: 200ms; }
.mp-delay-300 { --mp-reveal-delay: 300ms; }
.mp-delay-400 { --mp-reveal-delay: 400ms; }
.mp-delay-500 { --mp-reveal-delay: 500ms; }
.mp-delay-600 { --mp-reveal-delay: 600ms; }

/* Staggered children — fade + rise each direct child in sequence. Put
   .mp-in-view on the PARENT; override --mp-stagger for the interval (default
   80ms) or use a .mp-stagger-* preset. Covers up to 12 children. */
.mp-stagger {
  --mp-stagger: 80ms;
}

.mp-stagger > * {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.5s ease-out, transform 0.5s ease-out;
}

.mp-stagger.mp-in-view > * {
  opacity: 1;
  transform: translateY(0);
}

.mp-stagger.mp-in-view > *:nth-child(1)  { transition-delay: calc(0 * var(--mp-stagger)); }
.mp-stagger.mp-in-view > *:nth-child(2)  { transition-delay: calc(1 * var(--mp-stagger)); }
.mp-stagger.mp-in-view > *:nth-child(3)  { transition-delay: calc(2 * var(--mp-stagger)); }
.mp-stagger.mp-in-view > *:nth-child(4)  { transition-delay: calc(3 * var(--mp-stagger)); }
.mp-stagger.mp-in-view > *:nth-child(5)  { transition-delay: calc(4 * var(--mp-stagger)); }
.mp-stagger.mp-in-view > *:nth-child(6)  { transition-delay: calc(5 * var(--mp-stagger)); }
.mp-stagger.mp-in-view > *:nth-child(7)  { transition-delay: calc(6 * var(--mp-stagger)); }
.mp-stagger.mp-in-view > *:nth-child(8)  { transition-delay: calc(7 * var(--mp-stagger)); }
.mp-stagger.mp-in-view > *:nth-child(9)  { transition-delay: calc(8 * var(--mp-stagger)); }
.mp-stagger.mp-in-view > *:nth-child(10) { transition-delay: calc(9 * var(--mp-stagger)); }
.mp-stagger.mp-in-view > *:nth-child(11) { transition-delay: calc(10 * var(--mp-stagger)); }
.mp-stagger.mp-in-view > *:nth-child(12) { transition-delay: calc(11 * var(--mp-stagger)); }

/* Stagger-interval presets — pair with .mp-stagger. */
.mp-stagger-100 { --mp-stagger: 100ms; }
.mp-stagger-150 { --mp-stagger: 150ms; }
.mp-stagger-200 { --mp-stagger: 200ms; }
.mp-stagger-300 { --mp-stagger: 300ms; }

/* Respect reduced-motion: reveal everything with no transition or offset. */
@media (prefers-reduced-motion: reduce) {
  .mp-reveal,
  .mp-reveal-fade,
  .mp-reveal-left,
  .mp-reveal-right,
  .mp-stagger > * {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ==========================================================================
   Color variants — GENERATED per interactive role from core/tokens.json.
   Ink is chosen by WCAG contrast, not assumed to be white, and lives in a
   per-mode token so these rules are the same in light and dark.
   ========================================================================== */

/* --- primary ------------------------------------------------------- */

.mp-btn-primary {
  background-color: var(--c-primary);
  border-color: var(--c-primary);
  color: var(--ink-primary-fill);
}

.mp-btn-primary:hover {
  background-color: var(--fill-primary-hover);
  border-color: var(--fill-primary-hover);
}

.mp-btn-primary:active {
  background-color: var(--fill-primary-active);
  border-color: var(--fill-primary-active);
}

.mp-btn-outline-primary {
  background-color: transparent;
  border-color: var(--c-primary);
  color: var(--ink-primary-page);
}

.mp-btn-outline-primary:hover,
.mp-btn-outline-primary:active {
  background-color: var(--c-primary);
  color: var(--ink-primary-fill);
}

.mp-btn-ghost-primary {
  background-color: var(--surface-primary-tint);
  border-color: transparent;
  color: var(--ink-primary-tint);
}

.mp-btn-ghost-primary:hover,
.mp-btn-ghost-primary:active {
  background-color: var(--surface-primary-tint-hover);
}

.mp-badge-primary {
  background-color: var(--c-primary);
  color: var(--ink-primary-fill);
}

.mp-badge-outline-primary {
  background-color: transparent;
  border-color: var(--c-primary);
  color: var(--ink-primary-page);
}

.mp-badge-light-primary {
  background-color: var(--surface-primary-tint);
  color: var(--ink-primary-tint);
}

.mp-tag-primary {
  background-color: var(--surface-primary-tint);
  color: var(--ink-primary-tint);
}

.mp-tag-primary:hover {
  background-color: var(--surface-primary-tint-hover);
}

.mp-status-primary {
  background-color: var(--c-primary);
}

.mp-alert-primary {
  background-color: var(--surface-primary-tint);
  border-color: var(--border-primary-tint);
  color: var(--ink-primary-tint);
}

.mp-alert-subtle-primary {
  background-color: transparent;
  border-color: var(--c-primary);
  border-left-width: 4px;
  color: var(--ink-primary-page);
}

.mp-callout-primary {
  background-color: var(--surface-primary-tint);
  border-color: var(--border-primary-tint);
  border-left-color: var(--c-primary);
}

.mp-callout-primary .mp-callout-title,
.mp-callout-primary .mp-callout-text {
  color: var(--ink-primary-tint);
}

.mp-alert-solid-primary {
  background-color: var(--c-primary);
  border-color: var(--c-primary);
  color: var(--ink-primary-fill);
}

.mp-progress-bar-primary {
  background-color: var(--c-primary);
  color: var(--ink-primary-fill);
}

/* Color utilities — the one utility family that is pure brand decision.
   -bg fills and carries its computed ink; -bg-subtle is the tint pair.
   .mp-text-* is the role as ink and its contrast stays the caller's problem in
   either mode, exactly as before; what changed is that it shifts to the role's
   300 on a dark ground instead of staying at the unreadable 500. */
.mp-text-primary { color: var(--ink-primary); }

.mp-bg-primary {
  background-color: var(--c-primary);
  color: var(--ink-primary-fill);
}

.mp-bg-primary-subtle {
  background-color: var(--surface-primary-tint);
  color: var(--ink-primary-tint);
}

.mp-bg-gradient-primary {
  background: linear-gradient(135deg, var(--c-primary), var(--c-primary-dark));
  color: var(--ink-primary-fill);
}

/* --- secondary ----------------------------------------------------- */

.mp-btn-secondary {
  background-color: var(--c-secondary);
  border-color: var(--c-secondary);
  color: var(--ink-secondary-fill);
}

.mp-btn-secondary:hover {
  background-color: var(--fill-secondary-hover);
  border-color: var(--fill-secondary-hover);
}

.mp-btn-secondary:active {
  background-color: var(--fill-secondary-active);
  border-color: var(--fill-secondary-active);
}

.mp-btn-outline-secondary {
  background-color: transparent;
  border-color: var(--c-secondary);
  color: var(--ink-secondary-page);
}

.mp-btn-outline-secondary:hover,
.mp-btn-outline-secondary:active {
  background-color: var(--c-secondary);
  color: var(--ink-secondary-fill);
}

.mp-btn-ghost-secondary {
  background-color: var(--surface-secondary-tint);
  border-color: transparent;
  color: var(--ink-secondary-tint);
}

.mp-btn-ghost-secondary:hover,
.mp-btn-ghost-secondary:active {
  background-color: var(--surface-secondary-tint-hover);
}

.mp-badge-secondary {
  background-color: var(--c-secondary);
  color: var(--ink-secondary-fill);
}

.mp-badge-outline-secondary {
  background-color: transparent;
  border-color: var(--c-secondary);
  color: var(--ink-secondary-page);
}

.mp-badge-light-secondary {
  background-color: var(--surface-secondary-tint);
  color: var(--ink-secondary-tint);
}

.mp-tag-secondary {
  background-color: var(--surface-secondary-tint);
  color: var(--ink-secondary-tint);
}

.mp-tag-secondary:hover {
  background-color: var(--surface-secondary-tint-hover);
}

.mp-status-secondary {
  background-color: var(--c-secondary);
}

.mp-alert-secondary {
  background-color: var(--surface-secondary-tint);
  border-color: var(--border-secondary-tint);
  color: var(--ink-secondary-tint);
}

.mp-alert-subtle-secondary {
  background-color: transparent;
  border-color: var(--c-secondary);
  border-left-width: 4px;
  color: var(--ink-secondary-page);
}

.mp-callout-secondary {
  background-color: var(--surface-secondary-tint);
  border-color: var(--border-secondary-tint);
  border-left-color: var(--c-secondary);
}

.mp-callout-secondary .mp-callout-title,
.mp-callout-secondary .mp-callout-text {
  color: var(--ink-secondary-tint);
}

.mp-alert-solid-secondary {
  background-color: var(--c-secondary);
  border-color: var(--c-secondary);
  color: var(--ink-secondary-fill);
}

.mp-progress-bar-secondary {
  background-color: var(--c-secondary);
  color: var(--ink-secondary-fill);
}

/* Color utilities — the one utility family that is pure brand decision.
   -bg fills and carries its computed ink; -bg-subtle is the tint pair.
   .mp-text-* is the role as ink and its contrast stays the caller's problem in
   either mode, exactly as before; what changed is that it shifts to the role's
   300 on a dark ground instead of staying at the unreadable 500. */
.mp-text-secondary { color: var(--ink-secondary); }

.mp-bg-secondary {
  background-color: var(--c-secondary);
  color: var(--ink-secondary-fill);
}

.mp-bg-secondary-subtle {
  background-color: var(--surface-secondary-tint);
  color: var(--ink-secondary-tint);
}

.mp-bg-gradient-secondary {
  background: linear-gradient(135deg, var(--c-secondary), var(--c-secondary-dark));
  color: var(--ink-secondary-fill);
}

/* --- tertiary ------------------------------------------------------ */

.mp-btn-tertiary {
  background-color: var(--c-tertiary);
  border-color: var(--c-tertiary);
  color: var(--ink-tertiary-fill);
}

.mp-btn-tertiary:hover {
  background-color: var(--fill-tertiary-hover);
  border-color: var(--fill-tertiary-hover);
}

.mp-btn-tertiary:active {
  background-color: var(--fill-tertiary-active);
  border-color: var(--fill-tertiary-active);
}

.mp-btn-outline-tertiary {
  background-color: transparent;
  border-color: var(--c-tertiary);
  color: var(--ink-tertiary-page);
}

.mp-btn-outline-tertiary:hover,
.mp-btn-outline-tertiary:active {
  background-color: var(--c-tertiary);
  color: var(--ink-tertiary-fill);
}

.mp-btn-ghost-tertiary {
  background-color: var(--surface-tertiary-tint);
  border-color: transparent;
  color: var(--ink-tertiary-tint);
}

.mp-btn-ghost-tertiary:hover,
.mp-btn-ghost-tertiary:active {
  background-color: var(--surface-tertiary-tint-hover);
}

.mp-badge-tertiary {
  background-color: var(--c-tertiary);
  color: var(--ink-tertiary-fill);
}

.mp-badge-outline-tertiary {
  background-color: transparent;
  border-color: var(--c-tertiary);
  color: var(--ink-tertiary-page);
}

.mp-badge-light-tertiary {
  background-color: var(--surface-tertiary-tint);
  color: var(--ink-tertiary-tint);
}

.mp-tag-tertiary {
  background-color: var(--surface-tertiary-tint);
  color: var(--ink-tertiary-tint);
}

.mp-tag-tertiary:hover {
  background-color: var(--surface-tertiary-tint-hover);
}

.mp-status-tertiary {
  background-color: var(--c-tertiary);
}

.mp-alert-tertiary {
  background-color: var(--surface-tertiary-tint);
  border-color: var(--border-tertiary-tint);
  color: var(--ink-tertiary-tint);
}

.mp-alert-subtle-tertiary {
  background-color: transparent;
  border-color: var(--c-tertiary);
  border-left-width: 4px;
  color: var(--ink-tertiary-page);
}

.mp-callout-tertiary {
  background-color: var(--surface-tertiary-tint);
  border-color: var(--border-tertiary-tint);
  border-left-color: var(--c-tertiary);
}

.mp-callout-tertiary .mp-callout-title,
.mp-callout-tertiary .mp-callout-text {
  color: var(--ink-tertiary-tint);
}

.mp-alert-solid-tertiary {
  background-color: var(--c-tertiary);
  border-color: var(--c-tertiary);
  color: var(--ink-tertiary-fill);
}

.mp-progress-bar-tertiary {
  background-color: var(--c-tertiary);
  color: var(--ink-tertiary-fill);
}

/* Color utilities — the one utility family that is pure brand decision.
   -bg fills and carries its computed ink; -bg-subtle is the tint pair.
   .mp-text-* is the role as ink and its contrast stays the caller's problem in
   either mode, exactly as before; what changed is that it shifts to the role's
   300 on a dark ground instead of staying at the unreadable 500. */
.mp-text-tertiary { color: var(--ink-tertiary); }

.mp-bg-tertiary {
  background-color: var(--c-tertiary);
  color: var(--ink-tertiary-fill);
}

.mp-bg-tertiary-subtle {
  background-color: var(--surface-tertiary-tint);
  color: var(--ink-tertiary-tint);
}

.mp-bg-gradient-tertiary {
  background: linear-gradient(135deg, var(--c-tertiary), var(--c-tertiary-dark));
  color: var(--ink-tertiary-fill);
}

/* --- cta ----------------------------------------------------------- */

.mp-btn-cta {
  background-color: var(--c-cta);
  border-color: var(--c-cta);
  color: var(--ink-cta-fill);
}

.mp-btn-cta:hover {
  background-color: var(--fill-cta-hover);
  border-color: var(--fill-cta-hover);
}

.mp-btn-cta:active {
  background-color: var(--fill-cta-active);
  border-color: var(--fill-cta-active);
}

.mp-btn-outline-cta {
  background-color: transparent;
  border-color: var(--c-cta);
  color: var(--ink-cta-page);
}

.mp-btn-outline-cta:hover,
.mp-btn-outline-cta:active {
  background-color: var(--c-cta);
  color: var(--ink-cta-fill);
}

.mp-btn-ghost-cta {
  background-color: var(--surface-cta-tint);
  border-color: transparent;
  color: var(--ink-cta-tint);
}

.mp-btn-ghost-cta:hover,
.mp-btn-ghost-cta:active {
  background-color: var(--surface-cta-tint-hover);
}

.mp-badge-cta {
  background-color: var(--c-cta);
  color: var(--ink-cta-fill);
}

.mp-badge-outline-cta {
  background-color: transparent;
  border-color: var(--c-cta);
  color: var(--ink-cta-page);
}

.mp-badge-light-cta {
  background-color: var(--surface-cta-tint);
  color: var(--ink-cta-tint);
}

.mp-tag-cta {
  background-color: var(--surface-cta-tint);
  color: var(--ink-cta-tint);
}

.mp-tag-cta:hover {
  background-color: var(--surface-cta-tint-hover);
}

.mp-status-cta {
  background-color: var(--c-cta);
}

.mp-alert-cta {
  background-color: var(--surface-cta-tint);
  border-color: var(--border-cta-tint);
  color: var(--ink-cta-tint);
}

.mp-alert-subtle-cta {
  background-color: transparent;
  border-color: var(--c-cta);
  border-left-width: 4px;
  color: var(--ink-cta-page);
}

.mp-callout-cta {
  background-color: var(--surface-cta-tint);
  border-color: var(--border-cta-tint);
  border-left-color: var(--c-cta);
}

.mp-callout-cta .mp-callout-title,
.mp-callout-cta .mp-callout-text {
  color: var(--ink-cta-tint);
}

.mp-alert-solid-cta {
  background-color: var(--c-cta);
  border-color: var(--c-cta);
  color: var(--ink-cta-fill);
}

.mp-progress-bar-cta {
  background-color: var(--c-cta);
  color: var(--ink-cta-fill);
}

/* Color utilities — the one utility family that is pure brand decision.
   -bg fills and carries its computed ink; -bg-subtle is the tint pair.
   .mp-text-* is the role as ink and its contrast stays the caller's problem in
   either mode, exactly as before; what changed is that it shifts to the role's
   300 on a dark ground instead of staying at the unreadable 500. */
.mp-text-cta { color: var(--ink-cta); }

.mp-bg-cta {
  background-color: var(--c-cta);
  color: var(--ink-cta-fill);
}

.mp-bg-cta-subtle {
  background-color: var(--surface-cta-tint);
  color: var(--ink-cta-tint);
}

.mp-bg-gradient-cta {
  background: linear-gradient(135deg, var(--c-cta), var(--c-cta-dark));
  color: var(--ink-cta-fill);
}

/* --- success ------------------------------------------------------- */

.mp-btn-success {
  background-color: var(--c-success);
  border-color: var(--c-success);
  color: var(--ink-success-fill);
}

.mp-btn-success:hover {
  background-color: var(--fill-success-hover);
  border-color: var(--fill-success-hover);
}

.mp-btn-success:active {
  background-color: var(--fill-success-active);
  border-color: var(--fill-success-active);
}

.mp-btn-outline-success {
  background-color: transparent;
  border-color: var(--c-success);
  color: var(--ink-success-page);
}

.mp-btn-outline-success:hover,
.mp-btn-outline-success:active {
  background-color: var(--c-success);
  color: var(--ink-success-fill);
}

.mp-btn-ghost-success {
  background-color: var(--surface-success-tint);
  border-color: transparent;
  color: var(--ink-success-tint);
}

.mp-btn-ghost-success:hover,
.mp-btn-ghost-success:active {
  background-color: var(--surface-success-tint-hover);
}

.mp-badge-success {
  background-color: var(--c-success);
  color: var(--ink-success-fill);
}

.mp-badge-outline-success {
  background-color: transparent;
  border-color: var(--c-success);
  color: var(--ink-success-page);
}

.mp-badge-light-success {
  background-color: var(--surface-success-tint);
  color: var(--ink-success-tint);
}

.mp-tag-success {
  background-color: var(--surface-success-tint);
  color: var(--ink-success-tint);
}

.mp-tag-success:hover {
  background-color: var(--surface-success-tint-hover);
}

.mp-status-success {
  background-color: var(--c-success);
}

.mp-alert-success {
  background-color: var(--surface-success-tint);
  border-color: var(--border-success-tint);
  color: var(--ink-success-tint);
}

.mp-alert-subtle-success {
  background-color: transparent;
  border-color: var(--c-success);
  border-left-width: 4px;
  color: var(--ink-success-page);
}

.mp-callout-success {
  background-color: var(--surface-success-tint);
  border-color: var(--border-success-tint);
  border-left-color: var(--c-success);
}

.mp-callout-success .mp-callout-title,
.mp-callout-success .mp-callout-text {
  color: var(--ink-success-tint);
}

.mp-alert-solid-success {
  background-color: var(--c-success);
  border-color: var(--c-success);
  color: var(--ink-success-fill);
}

.mp-progress-bar-success {
  background-color: var(--c-success);
  color: var(--ink-success-fill);
}

/* Color utilities — the one utility family that is pure brand decision.
   -bg fills and carries its computed ink; -bg-subtle is the tint pair.
   .mp-text-* is the role as ink and its contrast stays the caller's problem in
   either mode, exactly as before; what changed is that it shifts to the role's
   300 on a dark ground instead of staying at the unreadable 500. */
.mp-text-success { color: var(--ink-success); }

.mp-bg-success {
  background-color: var(--c-success);
  color: var(--ink-success-fill);
}

.mp-bg-success-subtle {
  background-color: var(--surface-success-tint);
  color: var(--ink-success-tint);
}

.mp-bg-gradient-success {
  background: linear-gradient(135deg, var(--c-success), var(--c-success-dark));
  color: var(--ink-success-fill);
}

/* --- danger -------------------------------------------------------- */

.mp-btn-danger {
  background-color: var(--c-danger);
  border-color: var(--c-danger);
  color: var(--ink-danger-fill);
}

.mp-btn-danger:hover {
  background-color: var(--fill-danger-hover);
  border-color: var(--fill-danger-hover);
}

.mp-btn-danger:active {
  background-color: var(--fill-danger-active);
  border-color: var(--fill-danger-active);
}

.mp-btn-outline-danger {
  background-color: transparent;
  border-color: var(--c-danger);
  color: var(--ink-danger-page);
}

.mp-btn-outline-danger:hover,
.mp-btn-outline-danger:active {
  background-color: var(--c-danger);
  color: var(--ink-danger-fill);
}

.mp-btn-ghost-danger {
  background-color: var(--surface-danger-tint);
  border-color: transparent;
  color: var(--ink-danger-tint);
}

.mp-btn-ghost-danger:hover,
.mp-btn-ghost-danger:active {
  background-color: var(--surface-danger-tint-hover);
}

.mp-badge-danger {
  background-color: var(--c-danger);
  color: var(--ink-danger-fill);
}

.mp-badge-outline-danger {
  background-color: transparent;
  border-color: var(--c-danger);
  color: var(--ink-danger-page);
}

.mp-badge-light-danger {
  background-color: var(--surface-danger-tint);
  color: var(--ink-danger-tint);
}

.mp-tag-danger {
  background-color: var(--surface-danger-tint);
  color: var(--ink-danger-tint);
}

.mp-tag-danger:hover {
  background-color: var(--surface-danger-tint-hover);
}

.mp-status-danger {
  background-color: var(--c-danger);
}

.mp-alert-danger {
  background-color: var(--surface-danger-tint);
  border-color: var(--border-danger-tint);
  color: var(--ink-danger-tint);
}

.mp-alert-subtle-danger {
  background-color: transparent;
  border-color: var(--c-danger);
  border-left-width: 4px;
  color: var(--ink-danger-page);
}

.mp-callout-danger {
  background-color: var(--surface-danger-tint);
  border-color: var(--border-danger-tint);
  border-left-color: var(--c-danger);
}

.mp-callout-danger .mp-callout-title,
.mp-callout-danger .mp-callout-text {
  color: var(--ink-danger-tint);
}

.mp-alert-solid-danger {
  background-color: var(--c-danger);
  border-color: var(--c-danger);
  color: var(--ink-danger-fill);
}

.mp-progress-bar-danger {
  background-color: var(--c-danger);
  color: var(--ink-danger-fill);
}

/* Color utilities — the one utility family that is pure brand decision.
   -bg fills and carries its computed ink; -bg-subtle is the tint pair.
   .mp-text-* is the role as ink and its contrast stays the caller's problem in
   either mode, exactly as before; what changed is that it shifts to the role's
   300 on a dark ground instead of staying at the unreadable 500. */
.mp-text-danger { color: var(--ink-danger); }

.mp-bg-danger {
  background-color: var(--c-danger);
  color: var(--ink-danger-fill);
}

.mp-bg-danger-subtle {
  background-color: var(--surface-danger-tint);
  color: var(--ink-danger-tint);
}

.mp-bg-gradient-danger {
  background: linear-gradient(135deg, var(--c-danger), var(--c-danger-dark));
  color: var(--ink-danger-fill);
}

/* --- warning ------------------------------------------------------- */

.mp-btn-warning {
  background-color: var(--c-warning);
  border-color: var(--c-warning);
  color: var(--ink-warning-fill);
}

.mp-btn-warning:hover {
  background-color: var(--fill-warning-hover);
  border-color: var(--fill-warning-hover);
}

.mp-btn-warning:active {
  background-color: var(--fill-warning-active);
  border-color: var(--fill-warning-active);
}

.mp-btn-outline-warning {
  background-color: transparent;
  border-color: var(--c-warning);
  color: var(--ink-warning-page);
}

.mp-btn-outline-warning:hover,
.mp-btn-outline-warning:active {
  background-color: var(--c-warning);
  color: var(--ink-warning-fill);
}

.mp-btn-ghost-warning {
  background-color: var(--surface-warning-tint);
  border-color: transparent;
  color: var(--ink-warning-tint);
}

.mp-btn-ghost-warning:hover,
.mp-btn-ghost-warning:active {
  background-color: var(--surface-warning-tint-hover);
}

.mp-badge-warning {
  background-color: var(--c-warning);
  color: var(--ink-warning-fill);
}

.mp-badge-outline-warning {
  background-color: transparent;
  border-color: var(--c-warning);
  color: var(--ink-warning-page);
}

.mp-badge-light-warning {
  background-color: var(--surface-warning-tint);
  color: var(--ink-warning-tint);
}

.mp-tag-warning {
  background-color: var(--surface-warning-tint);
  color: var(--ink-warning-tint);
}

.mp-tag-warning:hover {
  background-color: var(--surface-warning-tint-hover);
}

.mp-status-warning {
  background-color: var(--c-warning);
}

.mp-alert-warning {
  background-color: var(--surface-warning-tint);
  border-color: var(--border-warning-tint);
  color: var(--ink-warning-tint);
}

.mp-alert-subtle-warning {
  background-color: transparent;
  border-color: var(--c-warning);
  border-left-width: 4px;
  color: var(--ink-warning-page);
}

.mp-callout-warning {
  background-color: var(--surface-warning-tint);
  border-color: var(--border-warning-tint);
  border-left-color: var(--c-warning);
}

.mp-callout-warning .mp-callout-title,
.mp-callout-warning .mp-callout-text {
  color: var(--ink-warning-tint);
}

.mp-alert-solid-warning {
  background-color: var(--c-warning);
  border-color: var(--c-warning);
  color: var(--ink-warning-fill);
}

.mp-progress-bar-warning {
  background-color: var(--c-warning);
  color: var(--ink-warning-fill);
}

/* Color utilities — the one utility family that is pure brand decision.
   -bg fills and carries its computed ink; -bg-subtle is the tint pair.
   .mp-text-* is the role as ink and its contrast stays the caller's problem in
   either mode, exactly as before; what changed is that it shifts to the role's
   300 on a dark ground instead of staying at the unreadable 500. */
.mp-text-warning { color: var(--ink-warning); }

.mp-bg-warning {
  background-color: var(--c-warning);
  color: var(--ink-warning-fill);
}

.mp-bg-warning-subtle {
  background-color: var(--surface-warning-tint);
  color: var(--ink-warning-tint);
}

.mp-bg-gradient-warning {
  background: linear-gradient(135deg, var(--c-warning), var(--c-warning-dark));
  color: var(--ink-warning-fill);
}

/* --- info ---------------------------------------------------------- */

.mp-btn-info {
  background-color: var(--c-info);
  border-color: var(--c-info);
  color: var(--ink-info-fill);
}

.mp-btn-info:hover {
  background-color: var(--fill-info-hover);
  border-color: var(--fill-info-hover);
}

.mp-btn-info:active {
  background-color: var(--fill-info-active);
  border-color: var(--fill-info-active);
}

.mp-btn-outline-info {
  background-color: transparent;
  border-color: var(--c-info);
  color: var(--ink-info-page);
}

.mp-btn-outline-info:hover,
.mp-btn-outline-info:active {
  background-color: var(--c-info);
  color: var(--ink-info-fill);
}

.mp-btn-ghost-info {
  background-color: var(--surface-info-tint);
  border-color: transparent;
  color: var(--ink-info-tint);
}

.mp-btn-ghost-info:hover,
.mp-btn-ghost-info:active {
  background-color: var(--surface-info-tint-hover);
}

.mp-badge-info {
  background-color: var(--c-info);
  color: var(--ink-info-fill);
}

.mp-badge-outline-info {
  background-color: transparent;
  border-color: var(--c-info);
  color: var(--ink-info-page);
}

.mp-badge-light-info {
  background-color: var(--surface-info-tint);
  color: var(--ink-info-tint);
}

.mp-tag-info {
  background-color: var(--surface-info-tint);
  color: var(--ink-info-tint);
}

.mp-tag-info:hover {
  background-color: var(--surface-info-tint-hover);
}

.mp-status-info {
  background-color: var(--c-info);
}

.mp-alert-info {
  background-color: var(--surface-info-tint);
  border-color: var(--border-info-tint);
  color: var(--ink-info-tint);
}

.mp-alert-subtle-info {
  background-color: transparent;
  border-color: var(--c-info);
  border-left-width: 4px;
  color: var(--ink-info-page);
}

.mp-callout-info {
  background-color: var(--surface-info-tint);
  border-color: var(--border-info-tint);
  border-left-color: var(--c-info);
}

.mp-callout-info .mp-callout-title,
.mp-callout-info .mp-callout-text {
  color: var(--ink-info-tint);
}

.mp-alert-solid-info {
  background-color: var(--c-info);
  border-color: var(--c-info);
  color: var(--ink-info-fill);
}

.mp-progress-bar-info {
  background-color: var(--c-info);
  color: var(--ink-info-fill);
}

/* Color utilities — the one utility family that is pure brand decision.
   -bg fills and carries its computed ink; -bg-subtle is the tint pair.
   .mp-text-* is the role as ink and its contrast stays the caller's problem in
   either mode, exactly as before; what changed is that it shifts to the role's
   300 on a dark ground instead of staying at the unreadable 500. */
.mp-text-info { color: var(--ink-info); }

.mp-bg-info {
  background-color: var(--c-info);
  color: var(--ink-info-fill);
}

.mp-bg-info-subtle {
  background-color: var(--surface-info-tint);
  color: var(--ink-info-tint);
}

.mp-bg-gradient-info {
  background: linear-gradient(135deg, var(--c-info), var(--c-info-dark));
  color: var(--ink-info-fill);
}
