/* ==========================================================================
   AMS Labs — theme
   Violet Pulse. Five brand roles, derived states, light and dark.

   Source of truth: ams-labs-brand-styles.md
   Requires two faces. Load before this file:
   <link rel="preconnect" href="https://fonts.googleapis.com">
   <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
   <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@600;700&family=Montserrat:wght@400;500;600&display=swap">
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Brand roles — the five. Nothing else is a brand colour.
   -------------------------------------------------------------------------- */
:root {
  --ams-primary:          #321555;
  --ams-accent:           #FF3A62;
  --ams-secondary-light:  #F3EEF9;
  --ams-neutral-dark:     #1A1730;
  --ams-neutral-light:    #FFFFFF;

  /* Aliases matching the names printed in ams-labs-brand-styles.md, so
     snippets copied straight out of the guide keep resolving. */
  --color-primary:         var(--ams-primary);
  --color-accent:          var(--ams-accent);
  --color-secondary-light: var(--ams-secondary-light);
  --color-neutral-dark:    var(--ams-neutral-dark);
  --color-neutral-light:   var(--ams-neutral-light);
}

/* --------------------------------------------------------------------------
   2. Derived scales
   Tints mix the role toward Neutral light; shades mix it toward Neutral dark,
   never toward pure black — that keeps the violet cast through the whole ramp.
   These are states and surfaces, not new brand colours.
   -------------------------------------------------------------------------- */
:root {
  /* Every step is mixed from the role at run time, so changing a role above
     changes its whole ramp and no value here can silently fall out of date.
     The comment on each line is the resolved sRGB value at the roles above. */
  --ams-primary-050: color-mix(in srgb, var(--ams-primary)  4.5%, var(--ams-neutral-light)); /* #F6F4F7 */
  --ams-primary-100: color-mix(in srgb, var(--ams-primary) 10.5%, var(--ams-neutral-light)); /* #E9E6ED */
  --ams-primary-200: color-mix(in srgb, var(--ams-primary)   22%, var(--ams-neutral-light)); /* #D2CCDA */
  --ams-primary-300: color-mix(in srgb, var(--ams-primary)   40%, var(--ams-neutral-light)); /* #ADA1BB */
  --ams-primary-400: color-mix(in srgb, var(--ams-primary)   62%, var(--ams-neutral-light)); /* #806E96 */
  --ams-primary-500: color-mix(in srgb, var(--ams-primary)   84%, var(--ams-neutral-light)); /* #533A70 */
  --ams-primary-600: var(--ams-primary);                                                     /* #321555 role */
  --ams-primary-700: color-mix(in srgb, var(--ams-primary)   70%, var(--ams-neutral-dark));  /* #2B164A */
  --ams-primary-800: color-mix(in srgb, var(--ams-primary)   42%, var(--ams-neutral-dark));  /* #241640 */
  --ams-primary-900: color-mix(in srgb, var(--ams-primary)   18%, var(--ams-neutral-dark));  /* #1E1737 */

  --ams-accent-050: color-mix(in srgb, var(--ams-accent)  4.5%, var(--ams-neutral-light)); /* #FFF6F8 */
  --ams-accent-100: color-mix(in srgb, var(--ams-accent) 10.5%, var(--ams-neutral-light)); /* #FFEAEF */
  --ams-accent-200: color-mix(in srgb, var(--ams-accent)   22%, var(--ams-neutral-light)); /* #FFD4DC */
  --ams-accent-300: color-mix(in srgb, var(--ams-accent)   40%, var(--ams-neutral-light)); /* #FFB0C0 */
  --ams-accent-400: color-mix(in srgb, var(--ams-accent)   62%, var(--ams-neutral-light)); /* #FF859E */
  --ams-accent-500: color-mix(in srgb, var(--ams-accent)   84%, var(--ams-neutral-light)); /* #FF5A7B */
  --ams-accent-600: var(--ams-accent);                                                     /* #FF3A62 role */
  /* The Accent fill that carries small white text. Held at 4.86:1 rather than
     at the 4.5 line, so a later nudge to the Accent hex cannot silently drop
     every button and badge below AA. */
  --ams-accent-650: color-mix(in srgb, var(--ams-accent)   80%, var(--ams-neutral-dark));  /* #D13358 */
  --ams-accent-700: color-mix(in srgb, var(--ams-accent)   70%, var(--ams-neutral-dark));  /* #BA3053 */
  --ams-accent-800: color-mix(in srgb, var(--ams-accent)   42%, var(--ams-neutral-dark));  /* #7A2645 */
  --ams-accent-900: color-mix(in srgb, var(--ams-accent)   18%, var(--ams-neutral-dark));  /* #431D39 */

  /* Neutral ramp: Neutral dark lightened toward Neutral light. Not grey, and
     not derived from Primary either: it is the ink role at reduced strength. */
  --ams-neutral-050: color-mix(in srgb, var(--ams-neutral-dark)  3%, var(--ams-neutral-light)); /* #F8F8F9 */
  --ams-neutral-100: color-mix(in srgb, var(--ams-neutral-dark)  7%, var(--ams-neutral-light)); /* #EFEFF1 */
  --ams-neutral-200: color-mix(in srgb, var(--ams-neutral-dark) 15%, var(--ams-neutral-light)); /* #DDDCE0 */
  --ams-neutral-300: color-mix(in srgb, var(--ams-neutral-dark) 30%, var(--ams-neutral-light)); /* #BAB9C1 */
  --ams-neutral-400: color-mix(in srgb, var(--ams-neutral-dark) 48%, var(--ams-neutral-light)); /* #91909C */
  --ams-neutral-500: color-mix(in srgb, var(--ams-neutral-dark) 62%, var(--ams-neutral-light)); /* #716F7F */
  --ams-neutral-600: color-mix(in srgb, var(--ams-neutral-dark) 74%, var(--ams-neutral-light)); /* #565366 */
  --ams-neutral-700: color-mix(in srgb, var(--ams-neutral-dark) 84%, var(--ams-neutral-light)); /* #3F3C51 */
  --ams-neutral-800: color-mix(in srgb, var(--ams-neutral-dark) 92%, var(--ams-neutral-light)); /* #2C2A41 */
  --ams-neutral-900: var(--ams-neutral-dark);                                                   /* #1A1730 role */
}

/* --------------------------------------------------------------------------
   3. Semantic tokens — light
   Build against these, not against the ramps. Swapping the theme swaps these.
   -------------------------------------------------------------------------- */
:root {
  color-scheme: light;

  --ams-surface-page:    var(--ams-secondary-light);
  --ams-surface-raised:  var(--ams-neutral-light);
  --ams-surface-sunken:  var(--ams-primary-050);
  --ams-surface-inset:   var(--ams-primary-100);
  --ams-surface-brand:   var(--ams-primary);
  --ams-surface-overlay: rgba(26, 23, 48, 0.44);

  --ams-ink:          var(--ams-neutral-dark);   /* 15.2:1 on page */
  --ams-ink-muted:    var(--ams-neutral-600);    /*  6.5:1 on page */
  --ams-ink-subtle:   color-mix(in srgb, var(--ams-neutral-dark) 64%, var(--ams-neutral-light)); /* 4.6:1 on page */
  --ams-ink-on-brand: var(--ams-neutral-light);  /* 15.3:1 on Primary */
  --ams-ink-on-brand-muted: var(--ams-primary-200);
  --ams-ink-on-accent: var(--ams-neutral-light); /* large text and icons only */

  --ams-border-subtle: var(--ams-neutral-200);
  --ams-border:        var(--ams-neutral-300);
  --ams-border-strong: var(--ams-neutral-500);
  --ams-border-brand:  var(--ams-primary);
  --ams-border-on-brand: rgba(255, 255, 255, 0.18);

  /* Accent at full strength is a mark, never body-size text: it reads 3.5:1
     on white and 3.1:1 on the page ground. Body-size links take a derived
     shade that clears 4.5:1 on both. */
  --ams-link:          color-mix(in srgb, var(--ams-accent) 72%, var(--ams-neutral-dark)); /* #BF3054, 4.9:1 on page */
  --ams-link-hover:    color-mix(in srgb, var(--ams-accent) 56%, var(--ams-neutral-dark)); /* #9A2B4C, 6.5:1 on page */
  --ams-link-large:    var(--ams-accent);
  --ams-mark:          var(--ams-accent);

  --ams-focus-ring:    var(--ams-accent);
  --ams-focus-ring-on-brand: var(--ams-accent-300);

  /* Primary is dark, so its hover lifts toward Neutral light rather than
     sinking: there is no room below it. */
  --ams-btn-primary-bg:        var(--ams-primary);
  --ams-btn-primary-bg-hover:  color-mix(in srgb, var(--ams-primary) 91%, var(--ams-neutral-light)); /* #442A64 */
  --ams-btn-primary-bg-active: var(--ams-primary-800);
  /* #FF3A62 behind a 15px label reads 3.5:1, which the guide's own rule shuts
     out. The button fills with the derived Accent that clears 4.5:1, and
     full-strength Accent stays where it is legal: marks, icons and large type. */
  --ams-btn-accent-bg:         var(--ams-accent-650);
  --ams-btn-accent-bg-hover:   color-mix(in srgb, var(--ams-accent) 68%, var(--ams-neutral-dark)); /* #B62F52 */
  --ams-btn-accent-bg-active:  var(--ams-accent-700);
  --ams-disabled-bg:    var(--ams-neutral-200);
  --ams-disabled-ink:   var(--ams-neutral-600);

  /* Status. The palette has two hues and the rule is to keep it that way, so
     status is carried by icon and label first and tint second: alert and
     error sit in the Accent family, confirmation and information in Primary.
     Colour alone is never the signal here. */
  --ams-status-info-ink:     var(--ams-primary-700);
  --ams-status-info-bg:      var(--ams-primary-100);
  --ams-status-info-border:  var(--ams-primary-300);
  --ams-status-ok-ink:       var(--ams-primary-800);
  --ams-status-ok-bg:        var(--ams-primary-050);
  --ams-status-ok-border:    var(--ams-primary-400);
  --ams-status-warn-ink:     var(--ams-accent-800);
  --ams-status-warn-bg:      var(--ams-accent-100);
  --ams-status-warn-border:  var(--ams-accent-400);
  --ams-status-error-ink:    var(--ams-accent-800);
  --ams-status-error-bg:     var(--ams-accent-200);
  --ams-status-error-border: var(--ams-accent-700);
}

/* --------------------------------------------------------------------------
   4. Semantic tokens — dark
   Neutral dark is the ground, exactly as the guide specifies. Primary cannot
   be the dark ground: it is the brand field, and a field that is also the
   page has nothing left to stand on.
   -------------------------------------------------------------------------- */
:root[data-theme="dark"] { color-scheme: dark; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --ams-surface-page:    var(--ams-neutral-dark);
    --ams-surface-raised:  #25233A;
    --ams-surface-sunken:  #15132A;
    --ams-surface-inset:   #2F2C43;
    /* Primary sits 1.14:1 from the dark page and would disappear on it, so
       the brand field lifts one step. The role itself is unchanged. */
    --ams-surface-brand:   var(--ams-primary-500);
    --ams-surface-overlay: rgba(10, 8, 22, 0.66);

    --ams-ink:          var(--ams-secondary-light);
    --ams-ink-muted:    var(--ams-neutral-300);
    --ams-ink-subtle:   var(--ams-neutral-400);
    --ams-ink-on-brand: var(--ams-neutral-light);
    --ams-ink-on-brand-muted: var(--ams-primary-200);

    --ams-border-subtle: rgba(243, 238, 249, 0.10);
    --ams-border:        rgba(243, 238, 249, 0.20);
    --ams-border-strong: rgba(243, 238, 249, 0.42);
    --ams-border-brand:  var(--ams-primary-400);

    --ams-link:          var(--ams-accent-400);
    --ams-link-hover:    var(--ams-accent-300);
    --ams-link-large:    var(--ams-accent);
    --ams-mark:          var(--ams-accent-400);

    --ams-focus-ring:    var(--ams-accent-300);

    --ams-btn-primary-bg:        var(--ams-primary-500);
    --ams-btn-primary-bg-hover:  var(--ams-primary-400);
    --ams-btn-primary-bg-active: var(--ams-primary);
    --ams-disabled-bg:    rgba(243, 238, 249, 0.10);
    --ams-disabled-ink:   var(--ams-neutral-300);

    --ams-status-info-ink:     var(--ams-primary-200);
    --ams-status-info-bg:      rgb(50 21 85 / 0.55);
    --ams-status-info-border:  var(--ams-primary-500);
    --ams-status-ok-ink:       var(--ams-primary-200);
    --ams-status-ok-bg:        rgb(50 21 85 / 0.40);
    --ams-status-ok-border:    var(--ams-primary-400);
    --ams-status-warn-ink:     var(--ams-accent-300);
    --ams-status-warn-bg:      rgb(255 58 98 / 0.18);
    --ams-status-warn-border:  var(--ams-accent-600);
    --ams-status-error-ink:    var(--ams-accent-300);
    --ams-status-error-bg:     rgb(255 58 98 / 0.28);
    --ams-status-error-border: var(--ams-accent-500);

    --ams-shadow-1: 0 1px 2px rgba(0, 0, 0, 0.34);
    --ams-shadow-2: 0 2px 4px rgba(0, 0, 0, 0.30), 0 8px 20px -6px rgba(0, 0, 0, 0.46);
    --ams-shadow-3: 0 4px 8px rgba(0, 0, 0, 0.32), 0 16px 32px -14px rgba(0, 0, 0, 0.58);
  }
}

:root[data-theme="dark"] {
  --ams-surface-page:    var(--ams-neutral-dark);
  --ams-surface-raised:  #25233A;
  --ams-surface-sunken:  #15132A;
  --ams-surface-inset:   #2F2C43;
  /* Primary sits 1.14:1 from the dark page and would disappear on it, so the
     brand field lifts one step. The role itself is unchanged. */
  --ams-surface-brand:   var(--ams-primary-500);
  --ams-surface-overlay: rgba(10, 8, 22, 0.66);

  --ams-ink:          var(--ams-secondary-light);
  --ams-ink-muted:    var(--ams-neutral-300);
  --ams-ink-subtle:   var(--ams-neutral-400);
  --ams-ink-on-brand: var(--ams-neutral-light);
  --ams-ink-on-brand-muted: var(--ams-primary-200);

  --ams-border-subtle: rgba(243, 238, 249, 0.10);
  --ams-border:        rgba(243, 238, 249, 0.20);
  --ams-border-strong: rgba(243, 238, 249, 0.42);
  --ams-border-brand:  var(--ams-primary-400);

  --ams-link:          var(--ams-accent-400);
  --ams-link-hover:    var(--ams-accent-300);
  --ams-link-large:    var(--ams-accent);
  --ams-mark:          var(--ams-accent-400);

  --ams-focus-ring:    var(--ams-accent-300);

  --ams-btn-primary-bg:        var(--ams-primary-500);
  --ams-btn-primary-bg-hover:  var(--ams-primary-400);
  --ams-btn-primary-bg-active: var(--ams-primary);
  --ams-disabled-bg:    rgba(243, 238, 249, 0.10);
  --ams-disabled-ink:   var(--ams-neutral-300);

  --ams-status-info-ink:     var(--ams-primary-200);
  --ams-status-info-bg:      rgb(50 21 85 / 0.55);
  --ams-status-info-border:  var(--ams-primary-500);
  --ams-status-ok-ink:       var(--ams-primary-200);
  --ams-status-ok-bg:        rgb(50 21 85 / 0.40);
  --ams-status-ok-border:    var(--ams-primary-400);
  --ams-status-warn-ink:     var(--ams-accent-300);
  --ams-status-warn-bg:      rgb(255 58 98 / 0.18);
  --ams-status-warn-border:  var(--ams-accent-600);
  --ams-status-error-ink:    var(--ams-accent-300);
  --ams-status-error-bg:     rgb(255 58 98 / 0.28);
  --ams-status-error-border: var(--ams-accent-500);

  --ams-shadow-1: 0 1px 2px rgba(0, 0, 0, 0.34);
  --ams-shadow-2: 0 2px 4px rgba(0, 0, 0, 0.30), 0 8px 20px -6px rgba(0, 0, 0, 0.46);
  --ams-shadow-3: 0 4px 8px rgba(0, 0, 0, 0.32), 0 16px 32px -14px rgba(0, 0, 0, 0.58);
}

/* --------------------------------------------------------------------------
   5. Typography, space, shape, depth, motion
   -------------------------------------------------------------------------- */
:root {
  --ams-font-display: "Hanken Grotesk", "Segoe UI", system-ui, sans-serif;
  --ams-font-body:    "Montserrat", "Segoe UI", system-ui, sans-serif;

  /* Hanken Grotesk 600 for the lockup, 700 standalone. Never 400 at logo scale. */
  --ams-weight-lockup:   600;
  --ams-weight-wordmark: 700;
  --ams-weight-body:     400;
  --ams-weight-emphasis: 500;

  --ams-text-2xs: 0.6875rem; /* 11 */
  --ams-text-xs:  0.75rem;   /* 12 */
  --ams-text-sm:  0.8125rem; /* 13 */
  --ams-text-md:  0.9375rem; /* 15 — body default */
  --ams-text-lg:  1.0625rem; /* 17 */
  --ams-text-xl:  1.375rem;  /* 22 */
  --ams-text-2xl: 1.75rem;   /* 28 */
  --ams-text-3xl: 2.25rem;   /* 36 */
  --ams-text-4xl: 2.75rem;   /* 44 */
  --ams-text-5xl: 3.75rem;   /* 60 */

  --ams-leading-tight: 1.08;
  --ams-leading-snug:  1.3;
  --ams-leading-body:  1.65;

  /* Montserrat is wide; display sizes need pulling in, body does not. */
  --ams-track-display: -0.022em;
  --ams-track-body:    0em;
  --ams-track-code:    0.04em;
  --ams-track-caps:    0.09em;

  --ams-measure: 68ch;

  --ams-space-1: 0.25rem;
  --ams-space-2: 0.5rem;
  --ams-space-3: 0.75rem;
  --ams-space-4: 1rem;
  --ams-space-5: 1.5rem;
  --ams-space-6: 2rem;
  --ams-space-7: 3rem;
  --ams-space-8: 4rem;
  --ams-space-9: 6rem;

  /* Fields and rails are square. Controls take the small radius. */
  --ams-radius-field:   0px;
  --ams-radius-control: 4px;
  --ams-radius-panel:   8px;
  --ams-radius-pill:    999px;
  --ams-radius-mark:    22%;

  --ams-shadow-1: 0 1px 2px rgba(26, 23, 48, 0.06), 0 1px 3px rgba(26, 23, 48, 0.10);
  --ams-shadow-2: 0 2px 4px rgba(26, 23, 48, 0.05), 0 6px 16px -4px rgba(26, 23, 48, 0.14);
  --ams-shadow-3: 0 4px 8px rgba(26, 23, 48, 0.06), 0 14px 30px -12px rgba(26, 23, 48, 0.24);

  --ams-duration-1: 120ms;
  --ams-duration-2: 200ms;
  --ams-duration-3: 320ms;
  --ams-ease: cubic-bezier(0.16, 1, 0.3, 1);

  --ams-rail-width: 264px;

  /* The mark. Primary is its ground and Accent is its glyph, which is why the
     two roles are these two values and not the other way round. */
  --ams-mark-glyph:  var(--ams-accent);
  --ams-mark-ground: var(--ams-primary);
  --ams-mark-ratio:  1.3956; /* the mark's own width / height */
}

/* --------------------------------------------------------------------------
   6. Base and browser surfaces
   The parts nobody draws still carry the brand: selection, caret, scrollbar,
   focus ring, list markers, numerals.
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--ams-surface-page);
  color: var(--ams-ink);
  font-family: var(--ams-font-body);
  font-size: var(--ams-text-md);
  font-weight: var(--ams-weight-body);
  line-height: var(--ams-leading-body);
  letter-spacing: var(--ams-track-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  caret-color: var(--ams-accent);
}

::selection { background: var(--ams-accent-300); color: var(--ams-neutral-dark); }
:root[data-theme="dark"] ::selection { background: var(--ams-accent-800); color: var(--ams-secondary-light); }

* { scrollbar-color: var(--ams-primary-400) transparent; scrollbar-width: thin; }
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--ams-primary-400);
  border: 3px solid transparent;
  background-clip: content-box;
  border-radius: var(--ams-radius-pill);
}
::-webkit-scrollbar-thumb:hover { background: var(--ams-primary); background-clip: content-box; }

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--ams-focus-ring);
  outline-offset: 2px;
  border-radius: var(--ams-radius-control);
}

h1, h2, h3, h4 {
  font-family: var(--ams-font-display);
  font-weight: var(--ams-weight-wordmark);
  line-height: var(--ams-leading-tight);
  letter-spacing: var(--ams-track-display);
  text-wrap: balance;
  margin: 0;
}
h1 { font-size: var(--ams-text-4xl); }
h2 { font-size: var(--ams-text-2xl); }
h3 { font-size: var(--ams-text-xl); font-weight: var(--ams-weight-lockup); }
h4 { font-size: var(--ams-text-lg); font-weight: var(--ams-weight-lockup); letter-spacing: -0.012em; }

p { margin: 0 0 var(--ams-space-4); max-width: var(--ams-measure); text-wrap: pretty; }
strong, b { font-weight: var(--ams-weight-emphasis); }

a { color: var(--ams-link); text-decoration-color: var(--ams-accent-400); text-underline-offset: 0.18em; text-decoration-thickness: 1px; }
a:hover { color: var(--ams-link-hover); text-decoration-color: currentColor; }

ul, ol { padding-left: 1.15em; max-width: var(--ams-measure); }
li { margin-bottom: var(--ams-space-1); }
li::marker { color: var(--ams-mark); }

hr { border: 0; border-top: 1px solid var(--ams-border-subtle); margin: var(--ams-space-6) 0; }

/* Any figure a reader might compare against another figure is tabular. */
.ams-num, table, .ams-code, code, kbd {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

.ams-code {
  font-family: var(--ams-font-body);
  font-weight: var(--ams-weight-emphasis);
  font-size: 0.9em;
  letter-spacing: var(--ams-track-code);
}

.ams-caps {
  font-size: var(--ams-text-xs);
  font-weight: var(--ams-weight-emphasis);
  letter-spacing: var(--ams-track-caps);
  text-transform: uppercase;
  color: var(--ams-ink-muted);
}

.ams-visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --------------------------------------------------------------------------
   7. Wordmark and lockup
   -------------------------------------------------------------------------- */
.ams-lockup { display: inline-flex; align-items: center; gap: 0.6em; }
.ams-lockup__mark { display: block; width: 2.4em; height: 2.4em; border-radius: var(--ams-radius-mark); flex: none; }
.ams-lockup__word {
  font-family: var(--ams-font-display);
  font-weight: var(--ams-weight-lockup);
  font-size: 1.05rem;
  letter-spacing: -0.014em;
  line-height: 1;
}
.ams-wordmark {
  font-family: var(--ams-font-display);
  font-weight: var(--ams-weight-wordmark);
  letter-spacing: -0.024em;
  line-height: 1;
}

/* --------------------------------------------------------------------------
   8. Buttons
   -------------------------------------------------------------------------- */
.ams-btn {
  --_bg: transparent;
  --_ink: var(--ams-ink);
  --_border: transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  padding: 0.6875rem 1.125rem;
  min-height: 2.75rem;
  border: 1px solid var(--_border);
  border-radius: var(--ams-radius-control);
  background: var(--_bg);
  color: var(--_ink);
  font-family: var(--ams-font-body);
  font-size: var(--ams-text-md);
  font-weight: var(--ams-weight-emphasis);
  line-height: 1.1;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color var(--ams-duration-1) var(--ams-ease),
              border-color var(--ams-duration-1) var(--ams-ease),
              color var(--ams-duration-1) var(--ams-ease);
}
.ams-btn svg { width: 1.125em; height: 1.125em; flex: none; }
/* Anchor buttons: a:hover and .ams-nav a both out-specify .ams-btn's own
   colour, so restate it at a weight that wins. */
.ams-btn:hover, .ams-btn:focus, .ams-btn:active, .ams-nav a.ams-btn { color: var(--_ink); }

.ams-btn--primary { --_bg: var(--ams-btn-primary-bg); --_ink: var(--ams-ink-on-brand); }
.ams-btn--primary:hover { --_bg: var(--ams-btn-primary-bg-hover); }
.ams-btn--primary:active { --_bg: var(--ams-btn-primary-bg-active); }

/* Filled with --ams-accent-650 rather than the role itself, so the white label
   clears 4.5:1 at every button size. */
.ams-btn--accent { --_bg: var(--ams-btn-accent-bg); --_ink: var(--ams-neutral-light); font-weight: 600; }
.ams-btn--accent:hover { --_bg: var(--ams-btn-accent-bg-hover); }
.ams-btn--accent:active { --_bg: var(--ams-btn-accent-bg-active); }

.ams-btn--outline { --_ink: var(--ams-primary); --_border: var(--ams-primary); }
:root[data-theme="dark"] .ams-btn--outline { --_ink: var(--ams-primary-200); --_border: var(--ams-primary-400); }
.ams-btn--outline:hover { --_bg: var(--ams-primary-100); }
:root[data-theme="dark"] .ams-btn--outline:hover { --_bg: rgb(50 21 85 / 0.60); }

.ams-btn--quiet { --_ink: var(--ams-ink-muted); }
.ams-btn--quiet:hover { --_bg: var(--ams-surface-inset); --_ink: var(--ams-ink); }

.ams-btn--sm { min-height: 2.125rem; padding: 0.4rem 0.75rem; font-size: var(--ams-text-sm); }
.ams-btn--lg { min-height: 3.25rem; padding: 0.9rem 1.5rem; font-size: var(--ams-text-lg); }

.ams-btn:disabled, .ams-btn[aria-disabled="true"] {
  --_bg: var(--ams-disabled-bg); --_ink: var(--ams-disabled-ink); --_border: transparent;
  cursor: not-allowed;
}
.ams-btn[data-loading="true"] { cursor: progress; }
.ams-btn[data-loading="true"] .ams-spinner { display: block; }

.ams-spinner {
  display: none; width: 1.05em; height: 1.05em; flex: none;
  border: 2px solid currentColor; border-right-color: transparent;
  border-radius: 50%;
  animation: ams-spin 620ms linear infinite;
}
@keyframes ams-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .ams-spinner { animation-duration: 1800ms; } }

/* --------------------------------------------------------------------------
   9. Panels, form controls, tables
   -------------------------------------------------------------------------- */
.ams-panel {
  background: var(--ams-surface-raised);
  border: 1px solid var(--ams-border-subtle);
  border-radius: var(--ams-radius-panel);
  padding: var(--ams-space-5);
  box-shadow: var(--ams-shadow-1);
}
.ams-panel--flat { box-shadow: none; }
/* A surface that floats does not also need an outline. Each step up in
   elevation trades the border away rather than stacking both. */
.ams-panel--raised { box-shadow: var(--ams-shadow-2); border-color: transparent; }
.ams-panel--floating { box-shadow: var(--ams-shadow-3); border-color: transparent; }
.ams-panel--brand {
  background: var(--ams-surface-brand);
  color: var(--ams-ink-on-brand);
  border-color: transparent;
}
.ams-panel--brand h2, .ams-panel--brand h3 { color: var(--ams-ink-on-brand); }
.ams-panel--brand p { color: var(--ams-ink-on-brand-muted); }
.ams-panel--brand a:not(.ams-btn) { color: var(--ams-accent-300); text-decoration-color: currentColor; }
.ams-panel--brand a:not(.ams-btn):hover { color: var(--ams-neutral-light); }
.ams-panel--brand :focus-visible { outline-color: var(--ams-focus-ring-on-brand); }

.ams-field { display: grid; gap: 0.4rem; max-width: 26rem; }
.ams-label { font-size: var(--ams-text-sm); font-weight: var(--ams-weight-emphasis); color: var(--ams-ink); }
.ams-input, .ams-select, .ams-textarea {
  width: 100%;
  padding: 0.625rem 0.75rem;
  min-height: 2.75rem;
  font-family: var(--ams-font-body);
  font-size: var(--ams-text-md);
  color: var(--ams-ink);
  background: var(--ams-surface-raised);
  border: 1px solid var(--ams-border);
  border-radius: var(--ams-radius-control);
  transition: border-color var(--ams-duration-1) var(--ams-ease),
              box-shadow var(--ams-duration-1) var(--ams-ease);
}
.ams-textarea { min-height: 6rem; line-height: 1.55; resize: vertical; }
.ams-input::placeholder, .ams-textarea::placeholder { color: var(--ams-ink-subtle); }
.ams-input:hover, .ams-select:hover, .ams-textarea:hover { border-color: var(--ams-border-strong); }
.ams-input:focus, .ams-select:focus, .ams-textarea:focus {
  outline: none;
  border-color: var(--ams-primary);
  box-shadow: 0 0 0 3px var(--ams-accent-200);
}
:root[data-theme="dark"] .ams-input:focus,
:root[data-theme="dark"] .ams-select:focus,
:root[data-theme="dark"] .ams-textarea:focus {
  border-color: var(--ams-primary-400);
  box-shadow: 0 0 0 3px rgb(255 58 98 / 0.34);
}
.ams-input[aria-invalid="true"] { border-color: var(--ams-status-error-border); }
.ams-input[aria-invalid="true"]:focus { box-shadow: 0 0 0 3px var(--ams-status-error-bg); }
.ams-input:disabled, .ams-select:disabled, .ams-textarea:disabled {
  background: var(--ams-disabled-bg); color: var(--ams-disabled-ink); cursor: not-allowed;
}
.ams-select {
  appearance: none;
  padding-right: 2.25rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23321555' stroke-width='1.6' stroke-linecap='square'%3E%3Cpath d='M5.5 8 10 12.5 14.5 8'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.625rem center;
  background-size: 1.15rem;
}
:root[data-theme="dark"] .ams-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23ADA1BB' stroke-width='1.6' stroke-linecap='square'%3E%3Cpath d='M5.5 8 10 12.5 14.5 8'/%3E%3C/svg%3E");
}
.ams-help { font-size: var(--ams-text-sm); color: var(--ams-ink-muted); }
.ams-error {
  display: flex; align-items: flex-start; gap: 0.4rem;
  font-size: var(--ams-text-sm); font-weight: var(--ams-weight-emphasis);
  color: var(--ams-status-error-ink);
}
.ams-error svg { width: 1rem; height: 1rem; flex: none; margin-top: 0.18em; }

.ams-check { display: flex; align-items: flex-start; gap: 0.6rem; cursor: pointer; font-size: var(--ams-text-md); }
.ams-check input {
  appearance: none; width: 1.15rem; height: 1.15rem; margin: 0.2rem 0 0; flex: none;
  border: 1px solid var(--ams-border-strong);
  border-radius: var(--ams-radius-control);
  background: var(--ams-surface-raised);
  transition: background-color var(--ams-duration-1) var(--ams-ease), border-color var(--ams-duration-1) var(--ams-ease);
}
.ams-check input[type="radio"] { border-radius: 50%; }
.ams-check input[type="checkbox"]:checked {
  background: var(--ams-primary) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='2.2' stroke-linecap='square'%3E%3Cpath d='m3.5 8.4 3 3 6-6.4'/%3E%3C/svg%3E") center / 0.9rem no-repeat;
  border-color: var(--ams-primary);
}
.ams-check input[type="radio"]:checked {
  border-color: var(--ams-primary);
  box-shadow: inset 0 0 0 4px var(--ams-primary);
}
:root[data-theme="dark"] .ams-check input[type="checkbox"]:checked { background-color: var(--ams-primary-500); border-color: var(--ams-primary-400); }
:root[data-theme="dark"] .ams-check input[type="radio"]:checked { border-color: var(--ams-primary-400); box-shadow: inset 0 0 0 4px var(--ams-primary-500); }

.ams-switch { display: inline-flex; align-items: center; gap: 0.6rem; cursor: pointer; }
.ams-switch input {
  appearance: none; width: 2.5rem; height: 1.4rem; flex: none; margin: 0;
  border-radius: var(--ams-radius-pill);
  background: var(--ams-neutral-300);
  position: relative;
  transition: background-color var(--ams-duration-2) var(--ams-ease);
}
.ams-switch input::after {
  content: ""; position: absolute; top: 3px; bottom: 3px; left: 3px;
  width: 1rem; border-radius: 50%; background: var(--ams-neutral-light);
  transition: transform var(--ams-duration-2) var(--ams-ease);
}
.ams-switch input:checked { background: var(--ams-accent); }
.ams-switch input:checked::after { transform: translateX(1.1rem); }
@media (prefers-reduced-motion: reduce) { .ams-switch input::after { transition: none; } }

.ams-table { width: 100%; border-collapse: collapse; font-size: var(--ams-text-sm); }
.ams-table th {
  text-align: left;
  font-weight: var(--ams-weight-emphasis);
  font-size: var(--ams-text-xs);
  letter-spacing: var(--ams-track-caps);
  text-transform: uppercase;
  color: var(--ams-ink-muted);
  padding: 0 0.75rem 0.55rem;
  border-bottom: 1px solid var(--ams-border);
}
.ams-table td { padding: 0.6rem 0.75rem; border-bottom: 1px solid var(--ams-border-subtle); vertical-align: middle; }
.ams-table tbody tr:hover td { background: var(--ams-surface-sunken); }
.ams-table th:first-child, .ams-table td:first-child { padding-left: 0; }
.ams-table th:last-child, .ams-table td:last-child { padding-right: 0; }

/* --------------------------------------------------------------------------
   10. Badges, notices, nav, skeleton
   -------------------------------------------------------------------------- */
.ams-badge {
  display: inline-flex; align-items: center; gap: 0.35em;
  padding: 0.2rem 0.55rem;
  border-radius: var(--ams-radius-pill);
  background: var(--ams-accent-650);
  color: var(--ams-neutral-light);
  font-size: var(--ams-text-xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1.45;
}
.ams-badge--quiet { background: var(--ams-primary-100); color: var(--ams-primary-700); }
:root[data-theme="dark"] .ams-badge--quiet { background: rgb(50 21 85 / 0.70); color: var(--ams-primary-200); }
.ams-badge--outline { background: transparent; color: var(--ams-link); box-shadow: inset 0 0 0 1px currentColor; }
/* Terminal states get the least ink in the room, never the warmest. */
.ams-badge--muted { background: transparent; color: var(--ams-ink-muted); box-shadow: inset 0 0 0 1px var(--ams-border); }

.ams-notice {
  display: grid; grid-template-columns: auto 1fr; gap: 0.75rem;
  padding: var(--ams-space-4);
  border-radius: var(--ams-radius-control);
  border: 1px solid var(--ams-status-info-border);
  background: var(--ams-status-info-bg);
  color: var(--ams-status-info-ink);
  font-size: var(--ams-text-sm);
}
.ams-notice svg { width: 1.25rem; height: 1.25rem; margin-top: 0.1rem; }
.ams-notice p { margin: 0; color: inherit; max-width: none; }
.ams-notice strong { display: block; font-weight: 600; margin-bottom: 0.15rem; }
.ams-notice--ok { border-color: var(--ams-status-ok-border); background: var(--ams-status-ok-bg); color: var(--ams-status-ok-ink); }
.ams-notice--warn { border-color: var(--ams-status-warn-border); background: var(--ams-status-warn-bg); color: var(--ams-status-warn-ink); }
.ams-notice--error { border-color: var(--ams-status-error-border); background: var(--ams-status-error-bg); color: var(--ams-status-error-ink); }

.ams-nav {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 0.5rem var(--ams-space-5);
  padding: 0.75rem var(--ams-space-5);
  background: var(--ams-surface-brand);
  color: var(--ams-ink-on-brand);
}
.ams-nav a:not(.ams-btn) {
  color: var(--ams-ink-on-brand-muted);
  text-decoration: none;
  font-size: var(--ams-text-sm);
  font-weight: var(--ams-weight-emphasis);
  padding: 0.3rem 0;
  border-bottom: 2px solid transparent;
  transition: color var(--ams-duration-1) var(--ams-ease), border-color var(--ams-duration-1) var(--ams-ease);
}
.ams-nav a:not(.ams-btn):hover { color: var(--ams-neutral-light); }
.ams-nav a[aria-current="page"] { color: var(--ams-neutral-light); border-bottom-color: var(--ams-accent); }
.ams-nav :focus-visible { outline-color: var(--ams-focus-ring-on-brand); }
@media (max-width: 640px) {
  .ams-nav { gap: 0.5rem var(--ams-space-4); padding: 0.75rem var(--ams-space-4); }
  .ams-nav > :last-child { margin-left: 0; }
}

.ams-skeleton {
  background: linear-gradient(90deg, var(--ams-surface-inset) 0%, var(--ams-primary-050) 50%, var(--ams-surface-inset) 100%);
  background-size: 220% 100%;
  border-radius: var(--ams-radius-control);
  animation: ams-shimmer 1.4s var(--ams-ease) infinite;
}
:root[data-theme="dark"] .ams-skeleton {
  background: linear-gradient(90deg, #2F2C43 0%, #3A374D 50%, #2F2C43 100%);
  background-size: 220% 100%;
}
@keyframes ams-shimmer { to { background-position: -220% 0; } }
@media (prefers-reduced-motion: reduce) { .ams-skeleton { animation: none; } }
