/* Opt-in section components. Load after legacy tokens.css, before the fork's
 * optional brand.css. Customer values and data-tone/data-wave choices are not
 * release files. Existing pages without these classes remain unchanged.
 *
 * Each tone accepts --mv-{tone}-{bg,text,muted,link,action,action-text,
 * action-hover,border,card,card-text,focus} and the card group
 * --mv-{tone}-card-{link,muted,focus,action,action-text,action-hover,border}
 * (DFW-11). Override complete pairs and verify both themes.
 * Waves occupy reserved inset bands, never cover neighboring content. Set
 * --mv-wave-top-backdrop / --mv-wave-bottom-backdrop to the actual adjacent
 * colors for seamless color-to-color transitions; default transparent reveals
 * the parent surface. Wave-bearing tones use solid backgrounds.
 * No clipping: portrait overlaps, shadows and focus rings stay visible.
 */
.mv-section {
  --_mv-wave-size: clamp(0px, var(--mv-wave-height, 24px), 48px);
  --_mv-bg: var(--mv-default-bg, var(--bg, #fbfbfc));
  --_mv-text: var(--mv-default-text, var(--text, #14202b));
  --_mv-muted: var(--mv-default-muted, var(--text-2, #4a5c68));
  --_mv-link: var(--mv-default-link, var(--accent-text, #0c6e6d));
  --_mv-action: var(--mv-default-action, var(--accent, #0c6e6d));
  --_mv-action-text: var(--mv-default-action-text, var(--on-accent, #fff));
  --_mv-border: var(--mv-default-border, var(--line-strong, #7e8f9a));
  --_mv-card: var(--mv-default-card, var(--surface, #fff));
  --_mv-card-text: var(--mv-default-card-text, var(--text, #14202b));
  --_mv-focus: var(--mv-default-focus, var(--accent-text, #0c6e6d));
  /* Hover colour of an action (DFW-11). Without a fork value it equals the
   * resting action colour, so nothing changes until a fork sets
   * --mv-{tone}-action-hover. Pick a value whose contrast to the action text is
   * equal or higher than at rest. Card border: bounds an outlined card. */
  --_mv-action-hover: var(--mv-default-action-hover, var(--_mv-action));
  --_mv-card-border: var(--mv-default-card-border, var(--mv-card-border, var(--line-strong, #7e8f9a)));
  /* Motion tokens (DFW-10). Values from the animation standards: press
   * feedback 100-160ms, state changes 150-250ms (UI stays under 300ms), strong
   * ease-out for entering and feedback, strong ease-in-out for movement on
   * screen, 8px start offset, 0.97 press scale. They only take effect where a
   * variant or component reads them, so a page without such a variant is
   * unchanged. A fork retunes them in brand.css via --mv-motion-*; the
   * reduced-motion block at the end of this file zeroes movement for everyone. */
  --_mv-motion-fast: var(--mv-motion-fast, 160ms);
  --_mv-motion-base: var(--mv-motion-base, 250ms);
  --_mv-ease-out: var(--mv-motion-ease-out, cubic-bezier(0.23, 1, 0.32, 1));
  --_mv-ease-in-out: var(--mv-motion-ease-in-out, cubic-bezier(0.77, 0, 0.175, 1));
  --_mv-motion-distance: var(--mv-motion-distance, 8px);
  --_mv-motion-press: var(--mv-motion-press, 0.97);
  position: relative;
  isolation: isolate;
  padding-block: var(--mv-section-space, clamp(3rem, 7vw, 6rem));
  background: var(--_mv-bg);
  color: var(--_mv-text);
  font-family: var(--mv-body-font, var(--sans, sans-serif));
}

.mv-section[data-tone="soft"] {
  --_mv-bg: var(--mv-soft-bg, var(--bg-2, #f2f5f6));
  --_mv-text: var(--mv-soft-text, var(--text, #14202b));
  --_mv-muted: var(--mv-soft-muted, var(--text-2, #4a5c68));
  --_mv-link: var(--mv-soft-link, var(--accent-text, #0c6e6d));
  --_mv-action: var(--mv-soft-action, var(--accent, #0c6e6d));
  --_mv-action-text: var(--mv-soft-action-text, var(--on-accent, #fff));
  --_mv-border: var(--mv-soft-border, var(--line-strong, #7e8f9a));
  --_mv-card: var(--mv-soft-card, var(--surface, #fff));
  --_mv-card-text: var(--mv-soft-card-text, var(--text, #14202b));
  --_mv-focus: var(--mv-soft-focus, var(--accent-text, #0c6e6d));
  --_mv-action-hover: var(--mv-soft-action-hover, var(--_mv-action));
  --_mv-card-border: var(--mv-soft-card-border, var(--mv-card-border, var(--line-strong, #7e8f9a)));
}

.mv-section[data-tone="accent"] {
  --_mv-bg: var(--mv-accent-bg, #0c6e6d);
  --_mv-text: var(--mv-accent-text, #fff);
  --_mv-muted: var(--mv-accent-muted, #fff);
  --_mv-link: var(--mv-accent-link, #fff);
  --_mv-action: var(--mv-accent-action, #fff);
  --_mv-action-text: var(--mv-accent-action-text, #08403f);
  --_mv-border: var(--mv-accent-border, #fff);
  --_mv-card: var(--mv-accent-card, #fff);
  --_mv-card-text: var(--mv-accent-card-text, #14202b);
  --_mv-focus: var(--mv-accent-focus, #fff);
  --_mv-action-hover: var(--mv-accent-action-hover, var(--_mv-action));
  --_mv-card-border: var(--mv-accent-card-border, var(--mv-card-border, #6b7c87));
}

.mv-section[data-tone="inverse"] {
  --_mv-bg: var(--mv-inverse-bg, #14202b);
  --_mv-text: var(--mv-inverse-text, #fff);
  --_mv-muted: var(--mv-inverse-muted, #fff);
  --_mv-link: var(--mv-inverse-link, #fff);
  --_mv-action: var(--mv-inverse-action, #fff);
  --_mv-action-text: var(--mv-inverse-action-text, #14202b);
  --_mv-border: var(--mv-inverse-border, #fff);
  --_mv-card: var(--mv-inverse-card, #fff);
  --_mv-card-text: var(--mv-inverse-card-text, #14202b);
  --_mv-focus: var(--mv-inverse-focus, #fff);
  --_mv-action-hover: var(--mv-inverse-action-hover, var(--_mv-action));
  --_mv-card-border: var(--mv-inverse-card-border, var(--mv-card-border, #6b7c87));
}

.mv-section__inner {
  position: relative;
  z-index: 2;
  width: min(var(--mv-container, 72rem), calc(100% - 2 * var(--mv-gutter, clamp(1rem, 4vw, 2rem))));
  margin-inline: auto;
}
.mv-section :where(h1, h2, h3, h4) {
  color: inherit;
  font-family: var(--mv-heading-font, inherit);
}
.mv-section :where(a:not(.mv-button):not(.btn)) { color: var(--_mv-link); }
.mv-section .mv-muted { color: var(--_mv-muted); }
.mv-section :where(a, button, input, textarea, select):focus-visible {
  outline: 3px solid var(--_mv-focus);
  outline-offset: 4px;
}
.mv-section .mv-card {
  padding: var(--mv-card-space, clamp(1.25rem, 3vw, 2rem));
  border-radius: var(--mv-card-radius, var(--radius, 1rem));
  background: var(--_mv-card);
  color: var(--_mv-card-text);
  /* A card is a separate surface, so inverse-section links must not inherit
   * white-on-white. Its complete semantic pair may be customized locally:
   * per tone first (--mv-{tone}-card-*), then for all tones (--mv-card-*),
   * then the tone's own fallback. The rules below pick the tone.
   * On default and soft the card surface follows the theme (--surface), so
   * the fallback ends in the theme tokens (--accent-text, --text-2, --accent,
   * --on-accent), same chain as .mv-tabs__list: the fixed light-card teal
   * measured 2.70:1 and the fixed muted grey 2.36:1 on the dark card (EPS-04).
   * On accent and inverse the card is white in both themes, the fixed pair
   * stays. */
  --_mv-link: var(--mv-default-card-link, var(--mv-card-link, var(--accent-text, #0c6e6d)));
  --_mv-muted: var(--mv-default-card-muted, var(--mv-card-muted, var(--text-2, #4a5c68)));
  --_mv-focus: var(--mv-default-card-focus, var(--mv-card-focus, var(--accent-text, #0c6e6d)));
  --_mv-action: var(--mv-default-card-action, var(--mv-card-action, var(--accent, #0c6e6d)));
  --_mv-action-text: var(--mv-default-card-action-text, var(--mv-card-action-text, var(--on-accent, #fff)));
  --_mv-action-hover: var(--mv-default-card-action-hover, var(--mv-card-action-hover, var(--_mv-action)));
}
.mv-section[data-tone="soft"] .mv-card {
  --_mv-link: var(--mv-soft-card-link, var(--mv-card-link, var(--accent-text, #0c6e6d)));
  --_mv-muted: var(--mv-soft-card-muted, var(--mv-card-muted, var(--text-2, #4a5c68)));
  --_mv-focus: var(--mv-soft-card-focus, var(--mv-card-focus, var(--accent-text, #0c6e6d)));
  --_mv-action: var(--mv-soft-card-action, var(--mv-card-action, var(--accent, #0c6e6d)));
  --_mv-action-text: var(--mv-soft-card-action-text, var(--mv-card-action-text, var(--on-accent, #fff)));
  --_mv-action-hover: var(--mv-soft-card-action-hover, var(--mv-card-action-hover, var(--_mv-action)));
}
.mv-section[data-tone="accent"] .mv-card {
  --_mv-link: var(--mv-accent-card-link, var(--mv-card-link, #0c6e6d));
  --_mv-muted: var(--mv-accent-card-muted, var(--mv-card-muted, #4a5c68));
  --_mv-focus: var(--mv-accent-card-focus, var(--mv-card-focus, #0c6e6d));
  --_mv-action: var(--mv-accent-card-action, var(--mv-card-action, #0c6e6d));
  --_mv-action-text: var(--mv-accent-card-action-text, var(--mv-card-action-text, #fff));
  --_mv-action-hover: var(--mv-accent-card-action-hover, var(--mv-card-action-hover, var(--_mv-action)));
}
.mv-section[data-tone="inverse"] .mv-card {
  --_mv-link: var(--mv-inverse-card-link, var(--mv-card-link, #0c6e6d));
  --_mv-muted: var(--mv-inverse-card-muted, var(--mv-card-muted, #4a5c68));
  --_mv-focus: var(--mv-inverse-card-focus, var(--mv-card-focus, #0c6e6d));
  --_mv-action: var(--mv-inverse-card-action, var(--mv-card-action, #0c6e6d));
  --_mv-action-text: var(--mv-inverse-card-action-text, var(--mv-card-action-text, #fff));
  --_mv-action-hover: var(--mv-inverse-card-action-hover, var(--mv-card-action-hover, var(--_mv-action)));
}
/* Card variants (DFW-11): data-card on .mv-card, no attribute = flat (today).
 * outlined: border in the tone's card border colour (UI boundary, 3:1 against
 * the card). raised: soft border plus shadow. */
.mv-section .mv-card[data-card="outlined"] {
  border: 1px solid var(--_mv-card-border, var(--line-strong, #7e8f9a));
}
.mv-section .mv-card[data-card="raised"] {
  border: 1px solid var(--mv-card-raised-border, var(--line-soft, #e6ecef));
  box-shadow: var(--mv-card-shadow, var(--shadow-2, 0 4px 12px rgba(10, 37, 64, .1)));
}
.mv-section .mv-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.75rem;
  box-sizing: border-box;
  padding: .75rem 1.25rem;
  border: 2px solid transparent;
  border-radius: var(--mv-button-radius, .5rem);
  background: var(--_mv-action);
  color: var(--_mv-action-text);
  font: inherit;
  font-weight: 600;
  line-height: 1.35;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}
.mv-section .mv-button:disabled { opacity: .55; cursor: not-allowed; }

/* Empty pseudo-elements are purely decorative and absent from the accessible
 * name. No animation, event target, foreign resource or overflow clipping. */
@supports (mask-image: linear-gradient(#000, #000)) or (-webkit-mask-image: linear-gradient(#000, #000)) {
  .mv-section[data-wave="top"],
  .mv-section[data-wave="bottom"],
  .mv-section[data-wave="both"] {
    --_mv-top: 0px;
    --_mv-bottom: 0px;
    background: linear-gradient(var(--mv-wave-top-backdrop, transparent), var(--mv-wave-top-backdrop, transparent)) top / 100% var(--_mv-top) no-repeat,
      linear-gradient(var(--mv-wave-bottom-backdrop, transparent), var(--mv-wave-bottom-backdrop, transparent)) bottom / 100% var(--_mv-bottom) no-repeat,
      linear-gradient(var(--_mv-bg), var(--_mv-bg)) left top var(--_mv-top) / 100% calc(100% - var(--_mv-top) - var(--_mv-bottom)) no-repeat;
    padding-block-start: calc(var(--mv-section-space, clamp(3rem, 7vw, 6rem)) + var(--_mv-top));
    padding-block-end: calc(var(--mv-section-space, clamp(3rem, 7vw, 6rem)) + var(--_mv-bottom));
  }
  .mv-section[data-wave="top"],
  .mv-section[data-wave="both"] { --_mv-top: var(--_mv-wave-size); }
  .mv-section[data-wave="bottom"],
  .mv-section[data-wave="both"] { --_mv-bottom: var(--_mv-wave-size); }
  .mv-section[data-wave="top"]::before,
  .mv-section[data-wave="both"]::before,
  .mv-section[data-wave="bottom"]::after,
  .mv-section[data-wave="both"]::after {
    content: "";
    position: absolute;
    z-index: 1;
    inset-inline: 0;
    height: var(--_mv-wave-size);
    background: var(--_mv-bg);
    pointer-events: none;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 64' preserveAspectRatio='none'%3E%3Cpath d='M0 40C240 0 480 0 720 32S1200 64 1440 24V64H0Z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 64' preserveAspectRatio='none'%3E%3Cpath d='M0 40C240 0 480 0 720 32S1200 64 1440 24V64H0Z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
  }
  .mv-section[data-wave="top"]::before,
  .mv-section[data-wave="both"]::before { top: 0; }
  .mv-section[data-wave="bottom"]::after,
  .mv-section[data-wave="both"]::after { bottom: 0; transform: rotate(180deg); }
}
@media (max-width: 40rem) {
  .mv-section { --_mv-wave-size: clamp(0px, var(--mv-wave-height, 24px), 24px); }
}
@media (forced-colors: active) {
  .mv-section[data-wave]::before,
  .mv-section[data-wave]::after { display: none; }
  .mv-section .mv-button { border-color: ButtonText; }
}

/* Motion levels (DFW-11). data-motion on .mv-section, no attribute = none
 * (today). "subtle": press feedback and hover colour on buttons, tab indicator
 * glide and panel change (components.css), spinner turn. "reveal": subtle plus
 * the scroll entrance below. Only transform and opacity move; the hover colour
 * fades with ease. Hover is gated to a hover capable fine pointer. A busy
 * button (aria-busy, below) gets no press or hover feedback. Everything sits
 * under .mv-section, so the reduced-motion net at the end of this file zeroes
 * it. */
.mv-section:is([data-motion="subtle"], [data-motion="reveal"]) .mv-button {
  transition: transform var(--_mv-motion-fast, 160ms) var(--_mv-ease-out, ease-out),
    background-color var(--_mv-motion-fast, 160ms) ease;
}
.mv-section:is([data-motion="subtle"], [data-motion="reveal"]) .mv-button:active:not(:disabled):not([aria-busy="true"]) {
  transform: scale(var(--_mv-motion-press, 0.97));
}
@media (hover: hover) and (pointer: fine) {
  .mv-section:is([data-motion="subtle"], [data-motion="reveal"]) .mv-button:hover:not(:disabled):not([aria-busy="true"]) {
    background-color: var(--_mv-action-hover, var(--_mv-action));
  }
}

/* Loading state (DFW-11 PR B). aria-busy="true" instead of disabled, so focus
 * stays on the button; mv-tabs.js swallows clicks while busy. The label stays
 * in the DOM (same width, same accessible name) and is only made transparent,
 * so the button needs its label in <span class="mv-button__label">. The spinner
 * is decoration drawn in the label colour; it turns (linear, constant motion)
 * only under data-motion, otherwise it stands as an arc. Reduced motion
 * leaves the arc standing (net below). */
.mv-section .mv-button[aria-busy="true"] {
  position: relative;
  cursor: progress;
}
.mv-section .mv-button[aria-busy="true"] > .mv-button__label { opacity: 0; }
.mv-section .mv-button[aria-busy="true"]::after {
  content: "";
  position: absolute;
  inset: 0;
  width: 1.1em;
  height: 1.1em;
  margin: auto;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  pointer-events: none;
}
.mv-section:is([data-motion="subtle"], [data-motion="reveal"]) .mv-button[aria-busy="true"]::after {
  animation: mv-spin 700ms linear infinite;
}
@keyframes mv-spin { to { transform: rotate(360deg); } }
/* Entrance keyframes move the individual `translate` property, never `transform`,
 * and have only a `from` step with fill-mode `backwards`: during the entrance a
 * block's own transform (a fork's rotate, a hover lift, a button press) keeps
 * working, and once the entrance is over the animation stops applying, so the
 * block's own opacity and transform are back. `both`/`forwards` would pin
 * opacity 1 and transform none for good (measured: it killed .mv-button press,
 * a disabled button's .55 opacity and a fork's rotate(3deg)). */
@keyframes mv-panel-in {
  from { opacity: 0; translate: 0 var(--_mv-motion-distance, 8px); }
}
@keyframes mv-reveal {
  from { opacity: 0; translate: 0 var(--_mv-motion-distance, 8px); }
}

/* Level "reveal": a scroll-driven entrance for the blocks directly inside
 * .mv-section__inner, .mv-grid and .mv-story-list (never the hero). It is a
 * CSS animation on a view timeline, not a timer and not an observer: the state
 * is a function of scroll position, so nothing can stay hidden after a jump
 * (anchor, page end, resize). A browser without animation-timeline matches no
 * rule here and simply shows the content. Screen only, so print never starts
 * at opacity 0, and only without a reduced-motion preference. The entry range
 * of a block taller than the viewport is bounded by the viewport height, so a
 * very tall block is fully visible after at most 40% of a screen of scrolling
 * (measured: 4000px block, full opacity after 220px). Grid items stagger
 * through offset ranges, not delays. If an ancestor of the section has an
 * overflow other than visible (for example overflow-x: hidden on main), the
 * view timeline binds to that non-scrolling ancestor, no animation runs and the
 * content simply stays visible. Avoid position: fixed descendants inside these
 * blocks (a running transform animation makes the block their containing
 * block). */
@media screen and (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .mv-section[data-motion="reveal"] :is(.mv-section__inner, .mv-grid, .mv-story-list) > :not(.mv-hero) {
      animation: mv-reveal linear backwards;
      animation-timing-function: var(--_mv-ease-out, ease-out);
      animation-timeline: view();
      animation-range: entry 0% entry 40%;
    }
    .mv-section[data-motion="reveal"] .mv-grid > :nth-child(2) { animation-range: entry 6% entry 46%; }
    .mv-section[data-motion="reveal"] .mv-grid > :nth-child(3) { animation-range: entry 12% entry 52%; }
  }
}

/* Reduced motion, global for everything inside a section. Movement goes to
 * zero and state changes become instant; colour and opacity states stay as
 * plain states. This mirrors the net in tokens.css, but tokens.css is core:once
 * and an older fork may not carry it, so sections.css brings its own. It sits
 * last so the zeroed tokens win over the base declarations above. */
@media (prefers-reduced-motion: reduce) {
  .mv-section {
    --_mv-motion-distance: 0px;
    --_mv-motion-press: 1;
  }
  .mv-section *,
  .mv-section *::before,
  .mv-section *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}
