/*!
 * Marrow Dashboard Theme Layer
 * ------------------------------------------------------------------
 * One stylesheet that gives every dashboard shell (coach, athlete, gym)
 * the marrowfitness.com look: a black surface with red accents by default,
 * a light bone day theme on request, and vibrant color coded metrics.
 * Pair it with /assets/js/theme-toggle.js which stamps
 * data-mz-theme="dark" or "light" on the html element and mounts the
 * user facing day and night switch.
 *
 * Include lines for any dashboard page (after the surface stylesheet):
 *   <link rel="stylesheet" href="/assets/css/dashboard-theme.css">
 *   <script src="/assets/js/theme-toggle.js"></script>
 *
 * Rules honored:
 *   - Brand tokens come from /css/styles.css. The dark theme REMAPS their
 *     values under :root[data-mz-theme="dark"] so the whole existing
 *     dashboard CSS flips without rewrites. No new brand identity tokens.
 *   - The metric colors below are FUNCTIONAL data viz tokens, not brand
 *     colors, following the --marrow-ember-text precedent in styles.css.
 *     Each has a light value and a dark value tuned for WCAG AA on its
 *     surface. Meaning is fixed: training reads green, mind reads cyan,
 *     spirit reads violet, money reads gold, roster reads blue.
 *   - prefers-reduced-motion stills every transition this file adds.
 *   - No em or en dashes anywhere in this file.
 */

/* =====================================================================
   1. FUNCTIONAL METRIC TOKENS (light theme defaults, AA on bone)
   ===================================================================== */
:root {
  --mzv-train:  #0F7B37;  /* training and sessions, green */
  --mzv-mind:   #0E7490;  /* mind and recovery, cyan */
  --mzv-spirit: #6D28D9;  /* spirit and streaks, violet */
  --mzv-money:  #995F0B;  /* payments and revenue, gold */
  --mzv-roster: #1D4ED8;  /* roster and people, blue */
  --mzv-onfill: #FBF8F2;  /* constant light text for red or dark fills */
  /* Surface the ember token for theme use even if styles.css is older. */
  --marrow-ember-text: #E08894;
  /* Vitality kit fallbacks so this layer stands alone on pages that do
     not load /assets/css/vitality.css. Same values, no conflict. */
  --mz-accent: var(--brand-fill, var(--marrow-red, #6B0F1A));
  --mz-accent-text: var(--brand-accent, var(--marrow-red, #6B0F1A));
  --mz-surface: var(--bone-white, #FBF8F2);
  --mz-line: var(--line, rgba(10, 9, 8, 0.08));
}

/* =====================================================================
   2. DARK THEME TOKEN REMAP
   The black background, red accent look Edwin locked for the dashboards.
   :root[data-mz-theme="dark"] outranks the :root block in styles.css, so
   every token driven rule in the existing dashboard CSS flips with it.
   ===================================================================== */
:root[data-mz-theme="dark"] {
  color-scheme: dark;
  --bone-cream: #0A0908;                   /* page background, true Marrow black */
  --bone-white: #171411;                   /* cards and raised surfaces */
  --bone-black: #F2EDE3;                   /* primary text, bone on black */
  --steel: #A8B4C4;                        /* secondary text, 8.7:1 on card */
  --steel-mid: #8393A6;
  --steel-light: #C3CEDC;
  /* 2026-08-04. --ash is the softer body ink on roughly 78 rules across the
     themed surfaces: program card descriptions, review text, exercise cues,
     the range adherence philosophy note, importer copy, retention copy and
     more. The token never flipped, so that ink measured 1.28:1 on the dark
     card, unreadable, which is the "too gray, too dark, brighten them up"
     defect Edwin flagged. Remapped to #E8DFCE, an existing repo value
     (styles.css, --r2-stamp-color dark), 13.87:1 on the dark card and
     15.04:1 on the dark page. Ash FILLS were audited before this flip: the
     retention anniversary rails and the two dark button hover fills keyed
     to ash now read correctly light on dark, and the one dark fallback in
     this file that named ash names the card token instead (section 18.5
     fallback). The print block below restores the light value. */
  --ash: #E8DFCE;
  --line: rgba(242, 237, 227, 0.14);
  /* Metric colors go neon in the dark, all 7:1 or better on the card. */
  --mzv-train:  #3DDC84;
  --mzv-mind:   #33CFEE;
  --mzv-spirit: #B79CFF;
  --mzv-money:  #F5B83D;
  --mzv-roster: #5EA8FF;
  /* Vitality kit accent text flips to the AA ember red on dark. */
  --mz-accent-text: var(--marrow-ember-text);
}

/* =====================================================================
   3. DARK THEME COMPONENT OVERRIDES
   Everything the token flip cannot reach: hardcoded rgba surfaces, red
   text that needs the brighter ember value on black, and fills whose
   text must stay light in both themes.
   ===================================================================== */

/* Immersive ambient orb backdrop across every dark dashboard surface, matching
 * the Marrow app opening and the sign in page. Six low opacity marrow red orbs
 * spread to the corners and mid edges so depth reads everywhere, never a central
 * cluster. Pinned behind all content at z-index -1 (above the true black page
 * background, below cards and nav). Dark theme only, so the day theme stays bone.
 * The same no new color gradient language as the login backdrop. */
[data-mz-theme="dark"] body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(closest-side, rgba(139, 24, 40, 0.30), transparent) left -9vmax top -9vmax / 50vmax 50vmax no-repeat,
    radial-gradient(closest-side, rgba(139, 24, 40, 0.30), transparent) right -9vmax top -9vmax / 50vmax 50vmax no-repeat,
    radial-gradient(closest-side, rgba(139, 24, 40, 0.30), transparent) left -9vmax bottom -9vmax / 50vmax 50vmax no-repeat,
    radial-gradient(closest-side, rgba(139, 24, 40, 0.30), transparent) right -9vmax bottom -9vmax / 50vmax 50vmax no-repeat,
    radial-gradient(closest-side, rgba(139, 24, 40, 0.20), transparent) left 50% top -12vmax / 46vmax 46vmax no-repeat,
    radial-gradient(closest-side, rgba(139, 24, 40, 0.20), transparent) left 50% bottom -12vmax / 46vmax 46vmax no-repeat;
  filter: blur(54px);
}
@media (prefers-reduced-motion: no-preference) {
  [data-mz-theme="dark"] body::before {
    animation: dash-orb-drift 40s ease-in-out infinite alternate;
  }
}
@keyframes dash-orb-drift {
  from { transform: translate3d(-1.2%, -1%, 0) scale(1.02); }
  to   { transform: translate3d(1.2%, 1.1%, 0) scale(1.05); }
}

/* Nav and mobile bars: black glass instead of bone glass. */
[data-mz-theme="dark"] .dash-nav { background: rgba(10, 9, 8, 0.88); }
[data-mz-theme="dark"] .dash-bottom-nav { background: rgba(13, 11, 10, 0.94); }

/* The Marrow orb in the nav carries hardcoded bone black strokes. */
[data-mz-theme="dark"] .logo-svg circle,
[data-mz-theme="dark"] .logo-svg g { stroke: #EFE9DC; }

/* Solid marrow red TEXT fails AA on black. Remap known red text to the
   ember accessibility token. Fills, borders, dots, and rails stay solid red. */
[data-mz-theme="dark"] .card-eyebrow,
[data-mz-theme="dark"] .vs-time-period,
[data-mz-theme="dark"] .bnav-btn[aria-current="page"],
[data-mz-theme="dark"] .lib-tab[aria-selected="true"],
[data-mz-theme="dark"] .set-tab[aria-selected="true"],
[data-mz-theme="dark"] .ex-tag.shared,
[data-mz-theme="dark"] .logo-upload-status.is-error,
/* .status-pill.onboarding was removed from this group on 2026-07-31. The
   group's premise is that every selector in it is already brand red in LIGHT
   and only needs the ember remap to clear AA on black. That premise never held
   for onboarding: coach/athletes/roster.css painted it navy in light, so the
   mismatch was invisible. With the roster override repointed to
   --mz-status-info, onboarding reads correctly in light as in flight, and the
   ember remap here would have made the same chip read as risk in dark. An
   athlete part way through onboarding is in flight, not at risk. Removed so
   the chip inherits the info treatment in both themes. .silent and
   .uncollectible stay: those are genuinely risk states. */
[data-mz-theme="dark"] .status-pill.silent,
[data-mz-theme="dark"] .status-pill.uncollectible,
[data-mz-theme="dark"] .recovery-score-num.red,
[data-mz-theme="dark"] .week-row[data-today="true"] .week-day,
[data-mz-theme="dark"] .booking-date-mon,
[data-mz-theme="dark"] .coach-attribution strong,
[data-mz-theme="dark"] .next-up .d,
[data-mz-theme="dark"] .error-block,
[data-mz-theme="dark"] .preview-badge,
[data-mz-theme="dark"] .card-eyebrow.mz-brand-eyebrow {
  color: var(--marrow-ember-text);
}
[data-mz-theme="dark"] .bnav-btn[aria-current="page"] svg { stroke: var(--marrow-ember-text); }

/* Red tinted chips read against black with a slightly stronger tint.
   .onboarding left this group on 2026-07-31 for the reason recorded above: it
   is not a risk state, so it must not carry a red tinted fill either. */
[data-mz-theme="dark"] .status-pill.silent,
[data-mz-theme="dark"] .status-pill.uncollectible {
  background: rgba(139, 24, 40, 0.3);
}

/* Status pills, theme scoped, repointed at the SOURCE 2026-07-31.
   These rules used to paint literal green (#57D9A3) and amber (#F0B429 dark,
   #8A6118 light). An attribute selector plus two classes outranks a plain
   two class rule, so they beat the neutral --mz-status-* palette on every
   coach sub-surface that renders .status-pill, not only the one surface that
   was patched. The palette is set here now, once, in both themes, so roster,
   invoices, forms, scheduling, classes, packages, store, credentials, form
   progression and the gym surfaces all read the same.

   Steady states read neutral. A state that is simply true does not earn a
   colour, and that restraint is what keeps the risk colour meaning
   something. Amber does not exist in this palette, so .paused, .open and
   .departing resolve to neutral rather than to a warning hue. .paid is the
   one exception: an invoice being paid is a genuinely good outcome, not a
   resting state, so it keeps the good reading. */
[data-mz-theme="dark"] .status-pill.active,
[data-mz-theme="light"] .status-pill.active,
[data-mz-theme="dark"] .status-pill.paused,
[data-mz-theme="light"] .status-pill.paused,
[data-mz-theme="dark"] .status-pill.open,
[data-mz-theme="light"] .status-pill.open,
[data-mz-theme="dark"] .status-pill.departing,
[data-mz-theme="light"] .status-pill.departing {
  color: var(--mz-status-neutral);
  background: var(--mz-status-neutral-soft);
}
[data-mz-theme="dark"] .status-pill.paid,
[data-mz-theme="light"] .status-pill.paid {
  color: var(--mz-status-good);
  background: var(--mz-status-good-soft);
}

/* The recovery numeral carries hue only, never a chip fill. Green keeps the
   good reading. The class still named amber resolves to neutral, because the
   value it marks is a steady one and this palette has no amber. */
[data-mz-theme="dark"] .recovery-score-num.green,
[data-mz-theme="light"] .recovery-score-num.green { color: var(--mz-status-good); }
[data-mz-theme="dark"] .recovery-score-num.amber,
[data-mz-theme="light"] .recovery-score-num.amber { color: var(--mz-status-neutral); }

/* Red and dark fills keep constant light text in both themes. Under the
   dark remap --bone-white becomes the card charcoal, which would put dark
   text on a red button. These stay bone. */
[data-mz-theme="dark"] .badge-unread,
[data-mz-theme="dark"] .review-action.primary,
[data-mz-theme="dark"] .vs-link.primary,
[data-mz-theme="dark"] .msg-thread-unread,
[data-mz-theme="dark"] .composer-send,
[data-mz-theme="dark"] .logo-upload-btn:hover,
/* .plan-badge is a RED fill, so constant bone text is right. Its .plan-badge-custom
   variant is not: that one fills with var(--bone-black), and --bone-black remaps
   to #F2EDE3 in this theme, so the chip became bone text on a bone fill, 1.02:1,
   the unreadable CUSTOM chip. The variant is excluded here and keeps its own
   color: var(--bone-white), which remaps to the card charcoal #171411 for
   15.72:1. Token names are ROLES in this theme, not colors. */
[data-mz-theme="dark"] .plan-badge:not(.plan-badge-custom),
[data-mz-theme="dark"] .btn-primary-dash,
[data-mz-theme="dark"] .retry-banner,
[data-mz-theme="dark"] .retry-btn,
[data-mz-theme="dark"] .week-tab[data-active="true"][data-deload="true"],
[data-mz-theme="dark"] .att-action.primary,
[data-mz-theme="dark"] .tier-pill.founder_cohort,
[data-mz-theme="dark"] .role-pill.owner {
  color: var(--mzv-onfill);
}

/* Focus ring and selection need the bright red on black. */
[data-mz-theme="dark"] a:focus-visible,
[data-mz-theme="dark"] button:focus-visible,
[data-mz-theme="dark"] input:focus-visible,
[data-mz-theme="dark"] [tabindex]:focus-visible {
  outline-color: var(--marrow-ember-text);
}
[data-mz-theme="dark"] ::selection { background: var(--marrow-red-glow); color: #FBF8F2; }

/* Overlays and shadows deepen on black. */
[data-mz-theme="dark"] .more-sheet { background: rgba(0, 0, 0, 0.62); }
[data-mz-theme="dark"] .dash-settings-menu,
[data-mz-theme="dark"] .card,
[data-mz-theme="dark"] .mz-statcard { box-shadow: none; }
[data-mz-theme="dark"] .dash-settings-menu { box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55); }
[data-mz-theme="dark"] .skeleton {
  background: linear-gradient(90deg, #1E1A16 0%, rgba(242, 237, 227, 0.08) 50%, #1E1A16 100%);
  background-size: 200% 100%;
}

/* Cards on black get a hairline top light and a faint red breath, the
   marrowfitness.com dark section feel. */
[data-mz-theme="dark"] .card {
  background:
    radial-gradient(120% 90% at 100% 0%, rgba(139, 24, 40, 0.10), transparent 55%),
    var(--bone-white);
  border-color: var(--line);
}

/* Print always renders the light palette, ink on paper. */
@media print {
  :root[data-mz-theme="dark"] {
    --bone-cream: #EFE9DC;
    --bone-white: #FBF8F2;
    --bone-black: #0A0908;
    --steel: #475569;
    --ash: #2A2A28;
    --line: rgba(10, 9, 8, 0.08);
  }
}

/* =====================================================================
   4. VIBRANT COLOR CODED METRICS (both themes)
   Stat tiles opt in with data-viz="training|mind|spirit|money|roster".
   The number takes the meaning color, the tile gets a soft wash of the
   same hue, and in the dark theme a quiet neon glow.
   ===================================================================== */
.mz-statcard[data-viz]         { --viz: var(--mz-accent); }
.mz-statcard[data-viz="training"] { --viz: var(--mzv-train); }
.mz-statcard[data-viz="mind"]     { --viz: var(--mzv-mind); }
.mz-statcard[data-viz="spirit"]   { --viz: var(--mzv-spirit); }
.mz-statcard[data-viz="money"]    { --viz: var(--mzv-money); }
.mz-statcard[data-viz="roster"]   { --viz: var(--mzv-roster); }

.mz-statcard[data-viz] {
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--viz) 9%, var(--mz-surface)), var(--mz-surface));
  border-color: color-mix(in srgb, var(--viz) 22%, var(--mz-line));
}
.mz-statcard[data-viz] .v { color: var(--viz); }
.mz-statcard[data-viz] .d.up { color: var(--viz); }
.mz-statcard[data-viz]::after {
  content: "";
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 0;
  height: 3px;
  border-radius: 3px 3px 0 0;
  background: linear-gradient(90deg, var(--viz), color-mix(in srgb, var(--viz) 30%, transparent));
}
[data-mz-theme="dark"] .mz-statcard[data-viz] {
  box-shadow: 0 0 34px -18px color-mix(in srgb, var(--viz) 80%, transparent);
}
@supports not (background: color-mix(in srgb, red, blue)) {
  .mz-statcard[data-viz] { background: var(--mz-surface); }
}

/* Momentum sparkline takes the training green. */
.wk-momentum .mz-spark i { background: color-mix(in srgb, var(--mzv-train) 45%, var(--mz-surface)); }
.wk-momentum .mz-spark i:last-child { background: var(--mzv-train); }

/* =====================================================================
   5. SPACING POLISH (both themes)
   Fixes the cramped Today and By the numbers headers and the clipped
   MOMENTUM label Edwin flagged on 2026-07-02.

   THESE FOUR RULES ARE THE SINGLE OWNER OF THIS SPACING (noted 2026-07-31)
   ---------------------------------------------------------------------
   coach/dashboard/dashboard.css used to restate the same four properties
   on the same four classes with its own competing values. That was
   invisible only because the coach dashboard and the gym console loaded
   their surface stylesheet BEFORE this file, inverting the load order
   documented in assets/css/mz-primitives.css, so these declarations won
   on source position alone. Both pages were corrected on 2026-07-31 to
   load the surface stylesheet LAST, and the competing declarations were
   deleted from the surface rather than compensated for, so this block is
   now the only place the values live and the cascade cannot flip them
   back. Nothing here was raised in specificity on purpose: 86 other pages
   load this file without a surface sheet that contests these classes, and
   the athlete dashboard already follows the contract and deliberately
   carries its own tighter spacing, which a specificity raise here would
   silently overwrite.
   ===================================================================== */
.section-head { margin-bottom: 30px; row-gap: 12px; }
.section-sub { margin-top: 8px; }
.card-head { margin-bottom: 22px; row-gap: 6px; }
.card-title { margin-top: 7px; }
.kpi-grid { gap: 16px 18px; }
.card.mz-rail { padding-left: 30px; }
.wk-momentum {
  padding: 4px 2px 0;
  gap: 16px;
  flex-wrap: wrap;
}
.wk-momentum .card-eyebrow { white-space: nowrap; overflow: visible; }
@media (min-width: 720px) {
  .card.mz-rail { padding-left: 34px; }
}

/* =====================================================================
   6. THEME TOGGLE BUTTON (mounted by theme-toggle.js)
   ===================================================================== */
.mz-theme-btn {
  width: 38px;
  height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 50%;
  color: var(--bone-black);
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease, transform 0.15s ease;
  margin-right: 8px;
  flex-shrink: 0;
}
.mz-theme-btn:hover { border-color: var(--bone-black); background: var(--bone-white); transform: rotate(12deg); }
.mz-theme-btn svg { width: 17px; height: 17px; }
.mz-theme-btn-floating {
  position: fixed;
  right: 16px;
  bottom: calc(76px + env(safe-area-inset-bottom));
  z-index: 120;
  background: var(--bone-white);
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.28);
  margin-right: 0;
}
@media (min-width: 900px) {
  .mz-theme-btn-floating { bottom: 20px; }
}

/* =====================================================================
   7. CALENDAR (coach dashboard schedule card)
   Month and week views, sessions from the live scheduling data path.
   ===================================================================== */
.mz-cal-controls {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.mz-cal-label {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--steel);
  min-width: 110px;
  text-align: center;
}
.mz-cal-nav-btn,
.mz-cal-view-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--line);
  color: var(--bone-black);
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.mz-cal-nav-btn { width: 30px; height: 30px; border-radius: 50%; }
.mz-cal-nav-btn:hover { border-color: var(--bone-black); }
.mz-cal-nav-btn svg { width: 14px; height: 14px; }
.mz-cal-viewtoggle { display: inline-flex; border-radius: 999px; overflow: hidden; border: 1px solid var(--line); }
.mz-cal-view-btn {
  border: none;
  padding: 6px 14px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--steel);
}
.mz-cal-view-btn[aria-pressed="true"] {
  background: var(--bone-black);
  color: var(--bone-cream);
}
.mz-cal-weekdays,
.mz-cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
}
/* Type floor, applied 2026-07-31: the tracked uppercase mono micro label sits
   at 10px, sentence text at 12px, and nothing on a dashboard renders in
   single digit pixels. These three calendar labels were the last 9px rules
   in this file. */
.mz-cal-weekdays {
  margin-bottom: 6px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--steel);
  text-align: center;
}
.mz-cal-day {
  position: relative;
  min-height: 56px;
  padding: 6px 4px 4px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: transparent;
  color: var(--bone-black);
  font-family: var(--mono);
  font-size: 12px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.mz-cal-day:hover { border-color: color-mix(in srgb, var(--mz-accent) 40%, var(--line)); }
.mz-cal-day.is-out { opacity: 0.34; }
.mz-cal-day.is-today {
  border-color: var(--marrow-red);
  box-shadow: inset 0 0 0 1px var(--marrow-red);
}
.mz-cal-day[aria-pressed="true"] {
  background: color-mix(in srgb, var(--mz-accent) 12%, var(--mz-surface));
  border-color: var(--marrow-red);
}
.mz-cal-day .n { line-height: 1; }
.mz-cal-dots { display: flex; gap: 3px; flex-wrap: wrap; justify-content: center; }
.mz-cal-dots i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--mzv-train);
  display: block;
}
.mz-cal-dots i.virtual { background: var(--mzv-mind); }
.mz-cal-count {
  font-size: 10px;
  color: var(--steel);
  letter-spacing: 0.08em;
}
.mz-cal-agenda { margin-top: 16px; border-top: 1px solid var(--line); padding-top: 14px; }
.mz-cal-agenda-title {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--steel);
  margin: 0 0 10px;
}
.mz-cal-week { display: grid; gap: 8px; }
@media (min-width: 900px) { .mz-cal-week { grid-template-columns: repeat(7, 1fr); } }
.mz-cal-weekcol {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 10px;
  min-height: 84px;
}
.mz-cal-weekcol.is-today { border-color: var(--marrow-red); }
.mz-cal-weekcol h4 {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--steel);
  margin: 0 0 8px;
  font-weight: 500;
}
.mz-cal-event {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 6px 8px;
  border-radius: 8px;
  margin-bottom: 4px;
  background: color-mix(in srgb, var(--mzv-train) 10%, var(--mz-surface));
  border-left: 3px solid var(--mzv-train);
  font-size: 12.5px;
  line-height: 1.35;
  color: var(--bone-black);
}
.mz-cal-event.virtual {
  background: color-mix(in srgb, var(--mzv-mind) 10%, var(--mz-surface));
  border-left-color: var(--mzv-mind);
}
.mz-cal-event .t {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--steel);
  flex-shrink: 0;
}
.mz-cal-empty-note {
  margin: 12px 0 0;
  font-size: 13px;
  color: var(--steel);
}
.mz-cal-empty-note a { color: var(--mz-accent-text); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }

/* =====================================================================
   8. MARROW BRANDMARK (Programming section and anywhere a section
   needs to carry the official app mark)
   ===================================================================== */
.mz-brand-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.mz-brand-eyebrow .mz-brand-mark { width: 18px; height: 18px; flex-shrink: 0; }
/* The official mark keeps its ink stroke: bone black in the light theme,
   bone text in the dark theme. The center hex stays marrow red. */
.mz-brand-mark circle,
.mz-brand-mark g { stroke: var(--bone-black); }

/* =====================================================================
   9. ACHIEVEMENT ENGINE, dark theme depth
   The card itself flips with the token remap. This adds the black
   theater dim and a soft accent glow so the moment lands at night.
   ===================================================================== */
[data-mz-theme="dark"] .marrow-achv-wrap { background: rgba(0, 0, 0, 0.62); }
[data-mz-theme="dark"] .marrow-achv-card {
  box-shadow:
    0 0 0 1px rgba(242, 237, 227, 0.07),
    0 30px 80px rgba(0, 0, 0, 0.65),
    0 0 70px -24px color-mix(in srgb, var(--achv-accent, var(--marrow-red)) 55%, transparent);
}
[data-mz-theme="dark"] .marrow-achv-eyebrow { color: var(--marrow-ember-text); }

/* Mind body spirit panel: keep its red wash breathing on black. */
[data-mz-theme="dark"] .mbs {
  background:
    radial-gradient(130% 120% at 100% 0%, rgba(139, 24, 40, 0.14), transparent 55%),
    var(--bone-white);
  box-shadow: none;
}

/* =====================================================================
   10. REDUCED MOTION
   ===================================================================== */
@media (prefers-reduced-motion: reduce) {
  .mz-theme-btn,
  .mz-cal-day,
  .mz-cal-nav-btn,
  .mz-cal-view-btn { transition: none; }
  .mz-theme-btn:hover { transform: none; }
}

/* ------------------------------------------------------------------
 * QA walkthrough 2026-07-03: dark-scope repairs for surfaces that
 * hardcode the cream sticky nav or invert fills through raw tokens.
 * Scoped to dark so the light theme keeps the original look untouched.
 * ------------------------------------------------------------------ */
:root[data-mz-theme="dark"] .programs-nav,
:root[data-mz-theme="dark"] .rev-nav {
  background: rgba(10, 9, 8, 0.92);
  border-bottom-color: var(--mz-line);
}
/* Adversarial review 2026-07-03: the onboarding wizards hardcode the same
 * cream sticky bar. This commit put the dark default on those pages, which
 * left bone text (#F2EDE3 after the token flip) on the cream glass. Same
 * repair as programs-nav above. */
:root[data-mz-theme="dark"] .wiz-nav,
:root[data-mz-theme="dark"] .wiz-header {
  background: rgba(10, 9, 8, 0.92);
  border-bottom-color: var(--mz-line);
}
/* Inverted stat tile (light fill in the light theme). Under dark the
 * remapped tokens flipped it cream on black; pin it to the card surface
 * with an accent edge so it still reads as the highlighted tile. */
:root[data-mz-theme="dark"] .metric-tile.accent {
  background: var(--bone-white);
  color: var(--bone-black);
  border-color: var(--mz-accent);
}
:root[data-mz-theme="dark"] .metric-tile.accent .k {
  color: var(--steel);
  opacity: 1;
}
/* The accent tile's value and meta pin to the inverted fill colors, which
 * both resolve dark-on-dark once the tile sits on a card surface. Pin them
 * back to readable ink and secondary text. */
:root[data-mz-theme="dark"] .metric-tile.accent .v { color: var(--bone-black); }
:root[data-mz-theme="dark"] .metric-tile.accent .meta { color: var(--steel); opacity: 1; }

/* =====================================================================
   11. CONTRAST PAIRING LAYER  (V3 item 13)
   ---------------------------------------------------------------------
   A semantic text-on-background system. Every text ROLE maps to a
   foreground token that is guaranteed to clear WCAG contrast against the
   background it is meant to sit on: 4.5:1 for normal text, 3:1 for large
   text. Nothing here restyles an existing selector. It only defines
   custom properties and opt-in utility classes, so with no class adopted
   and no theme selected the rendered look is byte for byte the current
   Marrow default. Surfaces adopt the roles page by page in a later wave.

   Every value maps to an EXISTING token from styles.css or from the
   sections above. No new brand color values are introduced here.

   Verified pairings (sRGB relative luminance, WCAG 2.x):
     LIGHT (page --bone-cream #EFE9DC, card --bone-white, marrow-red fill)
       heading / body   --bone-black #0A0908 on bone-cream ....... 16.45:1
       muted            --steel #475569 on bone-cream ............. 6.26:1
       link             --marrow-red #6B0F1A on bone-cream ....... 10.16:1
       on-accent        --mzv-onfill #FBF8F2 on marrow-red ....... 11.60:1
       placeholder      --steel #475569 on bone-cream ............. 6.26:1
       badge            --bone-black on --steel-light chip ....... 11.36:1
     DARK (page #0A0908, card #171411, marrow-red fill)
       heading / body   #F2EDE3 on page ......................... 17.05:1
       heading / body   #F2EDE3 on card ......................... 15.72:1
       muted            #A8B4C4 on card .......................... 8.73:1
       link             --marrow-ember-text #E08894 on page ...... 7.69:1
       link             --marrow-ember-text #E08894 on card ...... 7.09:1
       on-accent        --mzv-onfill #FBF8F2 on marrow-red ....... 11.60:1
       placeholder      #A8B4C4 on card .......................... 8.73:1
   The role tokens ride the existing token flips, so --mz-fg-heading and
   its siblings auto-correct in the dark theme. Only the link role needs
   an explicit
   dark value, because solid marrow red text scores 1.62:1 on black.

   Design note (item 51 research fold). A premium dashboard earns its calm
   from restraint, not decoration. The disciplines applied here:
     - One ink for text, one accent for meaning. Color carries data
       (the metric tokens above), never mood. Text stays near-monochrome.
     - Contrast is a floor, not a target. Body copy sits far above 4.5:1
       so the eye never strains, while muted and placeholder text stay a
       clear step down without dropping under the line.
     - A muted role is a deliberate tier, not faded body text. It reads as
       hierarchy, so secondary information recedes without becoming noise.
     - The type scale climbs in gentle steps (roughly a 1.2 ratio) and the
       spacing rhythm holds to an 8px lattice (section 5 above), so the
       page feels engineered rather than assembled.
     - Links declare themselves with the brand red, underlined on adoption,
       never by color alone, so meaning survives a grayscale or colorblind
       read.
   ===================================================================== */
:root {
  /* Text role foregrounds (light theme values, all existing tokens). */
  --mz-fg-heading:     var(--bone-black);
  --mz-fg-body:        var(--bone-black);
  --mz-fg-muted:       var(--steel);
  --mz-fg-on-card:     var(--bone-black);
  --mz-fg-on-accent:   var(--mzv-onfill);   /* text on a marrow-red or brand-primary fill */
  --mz-fg-badge:       var(--bone-black);    /* text on a neutral chip surface */
  --mz-fg-placeholder: var(--steel);         /* WCAG pass, not the sub-3:1 hint gray */
  --mz-fg-link:        var(--marrow-red);

  /* Background reference aliases, so a surface can name the pairing it is
     adopting without guessing which token the role was tuned against. */
  --mz-bg-page:    var(--bone-cream);
  /* 2026-07-30 (Lane 1) pinned this to the literal #FBF8F2 because
     var(--bone-white) resolved to #EFE9DC in styles.css, identical to
     --mz-bg-page, so light mode cards had zero surface separation.
     2026-07-31: the root token is now the documented canon #FBF8F2, so the
     workaround is retired and the card names the token again. One source of
     truth. Section 18.5 still states the dark card explicitly. */
  --mz-bg-card:    var(--bone-white);
  --mz-bg-accent:  var(--marrow-red);
  --mz-bg-badge:   var(--steel-light);
}

/* Only the link role cannot ride the token flip: solid marrow red text
   fails on the dark page. Remap it to the accessibility ember, matching
   the red-text handling already used across section 3. */
:root[data-mz-theme="dark"] {
  --mz-fg-link: var(--marrow-ember-text);
}

/* Opt-in utility classes. A surface adds the class to adopt the role.
   Absent the class, nothing changes. */
.mz-fg-heading { color: var(--mz-fg-heading); }
.mz-fg-body    { color: var(--mz-fg-body); }
.mz-fg-muted   { color: var(--mz-fg-muted); }
.mz-fg-on-card { color: var(--mz-fg-on-card); }
.mz-fg-badge   { color: var(--mz-fg-badge); }
.mz-on-accent  { color: var(--mz-fg-on-accent); }
.mz-fg-link    { color: var(--mz-fg-link); }
.mz-fg-link:hover { color: var(--marrow-red-glow); }
.mz-fg-placeholder::placeholder { color: var(--mz-fg-placeholder); opacity: 1; }

/* =====================================================================
   12. PER-COACH THEMING ENGINE HOOKS  (V3 items 18 to 21, engine only)
   ---------------------------------------------------------------------
   A coach brand layer that sits OVER the locked Marrow tokens, never
   replacing them. The three properties below default to the locked
   brand values, so a surface that reads var(--mz-brand-primary) renders
   exactly the Marrow red until a coach theme is stored. No existing
   selector reads these yet, so defining them changes nothing today.

   /assets/js/theme-engine.js fills these at runtime only when a coach
   theme exists, and recomputes --mz-brand-on-primary and the on-accent
   pairing from the chosen color's luminance so text on the brand fill
   always clears 4.5:1. When nothing is stored the engine writes nothing
   and these defaults hold, keeping the default look unchanged.
   ===================================================================== */
:root {
  --mz-brand-primary:     var(--marrow-red);        /* coach primary, falls back to locked red */
  --mz-brand-offset:      var(--marrow-red-glow);   /* coach offset / hover, falls back to glow */
  --mz-brand-on-primary:  var(--mzv-onfill);        /* readable text on the primary fill */
}

/* Opt-in brand fill utilities. Text color is the engine-computed readable
   pairing, so it stays legible whatever primary the coach chose. */
.mz-brand-fill {
  background: var(--mz-brand-primary);
  color: var(--mz-brand-on-primary);
}
.mz-brand-fill--offset { background: var(--mz-brand-offset); color: var(--mz-brand-on-primary); }
.mz-brand-edge { border-color: var(--mz-brand-primary); }

/* =====================================================================
   13. DASHBOARD BUTTON AFFORDANCE  (V3.1 item 9, appended 2026-07-07)
   ---------------------------------------------------------------------
   This theme layer enriches the per-surface .btn-primary-dash base
   (defined in coach/athlete/gym dashboard.css) without editing it. Adds
   depth, a clear pressed state, and a focus-visible ring so the dashboard
   primary button reads as obviously clickable. Hover background stays
   owned by the surface rule (a different property), so nothing is
   overwritten. The reworked .btn-secondary base in styles.css keys off
   --bone-black, which the dark remap in section 2 flips, so the secondary
   button self-corrects to light ink on the dark dashboard theme with no
   extra rule here.

   THE TRANSITION HAS ONE OWNER, THIS BLOCK (noted 2026-07-31)
   ---------------------------------------------------------------------
   The original header said this file loads after every surface stylesheet.
   That was true of the coach dashboard and the gym console only because
   both inverted the load order documented in mz-primitives.css. Both were
   corrected on 2026-07-31 so the surface stylesheet loads LAST, which
   would have let coach/dashboard/dashboard.css win with its own bare
   transition: background 0.15s ease and strip transform and box-shadow
   from the list on 10 buttons, so the hover lift would snap instead of
   ease. That competing declaration was deleted from the surface, leaving
   this block as the only owner. The athlete dashboard keeps its own
   0.15s transition on purpose, which is why nothing here was raised in
   specificity.
   ===================================================================== */
.btn-primary-dash {
  box-shadow: 0 1px 2px rgba(10, 9, 8, 0.18);
  transition: background 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease;
}
.btn-primary-dash:hover { transform: translateY(-1px); box-shadow: 0 8px 20px rgba(107, 15, 26, 0.30); }
.btn-primary-dash:focus-visible { outline: 2px solid var(--marrow-red); outline-offset: 3px; }
.btn-primary-dash:active { transform: translateY(0); box-shadow: 0 1px 2px rgba(10, 9, 8, 0.24); }
:root[data-mz-theme="dark"] .btn-primary-dash:focus-visible { outline-color: var(--marrow-ember-text); }
:root[data-mz-theme="dark"] .btn-primary-dash:hover { box-shadow: 0 8px 22px rgba(139, 24, 40, 0.5); }
@media (prefers-reduced-motion: reduce) {
  .btn-primary-dash { transition: background 0.15s ease; }
  .btn-primary-dash:hover, .btn-primary-dash:active { transform: none; }
}

/* =====================================================================
   14. COLOR PICKER POPOVER  (V3.1 item 1, appended 2026-07-07)
   ---------------------------------------------------------------------
   Styles only. The open/close, swatch selection, and native input wiring
   are built separately in JS against these class names. Premium, compact,
   floats above content, keyboard focusable, dark-mode aware through the
   token flip. Used where a coach or gym picks their brand primary color.
   ===================================================================== */
.mz-colorpick { position: relative; display: inline-flex; }

.mz-colorpick-trigger {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px 8px 10px;
  background: var(--bone-white);
  color: var(--bone-black);
  border: 1px solid var(--line);
  border-radius: 10px;
  font: 600 13px var(--sans);
  cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}
.mz-colorpick-trigger:hover { border-color: var(--bone-black); box-shadow: 0 6px 16px rgba(10, 9, 8, 0.10); }
.mz-colorpick-trigger:focus-visible { outline: 2px solid var(--marrow-red); outline-offset: 2px; }
.mz-colorpick-trigger .mz-colorpick-chip {
  width: 20px;
  height: 20px;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: var(--mz-brand-primary);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.25);
  flex: none;
}
.mz-colorpick-trigger .mz-colorpick-caret {
  width: 10px;
  height: 10px;
  color: var(--steel);
  flex: none;
  transition: transform 0.15s ease;
}
.mz-colorpick.is-open .mz-colorpick-trigger .mz-colorpick-caret,
.mz-colorpick-trigger[aria-expanded="true"] .mz-colorpick-caret { transform: rotate(180deg); }

.mz-colorpick-panel {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 140;
  min-width: 232px;
  padding: 14px;
  background: var(--bone-white);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: 0 18px 44px rgba(10, 9, 8, 0.18);
  display: none;
}
.mz-colorpick-panel[data-mz-open="true"],
.mz-colorpick.is-open .mz-colorpick-panel {
  display: block;
  animation: mz-colorpick-in 0.16s ease both;
}
.mz-colorpick-panel--right { left: auto; right: 0; }
[data-mz-theme="dark"] .mz-colorpick-panel { box-shadow: 0 18px 44px rgba(0, 0, 0, 0.55); }
@keyframes mz-colorpick-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.mz-colorpick-swatches {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 8px;
}
.mz-colorpick-swatch {
  width: 100%;
  aspect-ratio: 1;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 8px;
  cursor: pointer;
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.mz-colorpick-swatch:hover { transform: scale(1.08); }
.mz-colorpick-swatch:focus-visible { outline: 2px solid var(--marrow-red); outline-offset: 2px; }
.mz-colorpick-swatch[aria-pressed="true"],
.mz-colorpick-swatch.is-selected {
  box-shadow: 0 0 0 2px var(--bone-white), 0 0 0 4px var(--bone-black);
}
[data-mz-theme="dark"] .mz-colorpick-swatch:focus-visible { outline-color: var(--marrow-ember-text); }

.mz-colorpick-native {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
  font: 500 12px var(--sans);
  color: var(--steel);
}
.mz-colorpick-native label { color: var(--steel); }
.mz-colorpick-native input[type="color"] {
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: transparent;
  cursor: pointer;
  flex: none;
}
.mz-colorpick-native input[type="color"]:focus-visible { outline: 2px solid var(--marrow-red); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
  .mz-colorpick-trigger,
  .mz-colorpick-trigger .mz-colorpick-caret,
  .mz-colorpick-swatch { transition: none; }
  .mz-colorpick-panel[data-mz-open="true"],
  .mz-colorpick.is-open .mz-colorpick-panel { animation: none; }
  .mz-colorpick-swatch:hover { transform: none; }
}

/* =====================================================================
   15. COMMUNITY + EVENTS TABS AND CARDS  (V3.1 item 12, 2026-07-07)
   ---------------------------------------------------------------------
   Two new dashboard tabs, Community and Events. The tabs and panels reuse
   the existing .dash-section-btn and .dash-section look verbatim, so they
   are visually identical to Today and Training. The two additions below
   are only the per-section accent hooks and the premium surface cards the
   Events and Community feeds render into.

   Every text-on-background pair uses the readable-ink pairing tokens
   (--mz-fg-*, section 11) or the engine-computed --mz-brand-on-primary, so
   copy stays legible on the light theme, the dark theme, and any per-coach
   primary color. No hardcoded near-white ink on light.
   ===================================================================== */

/* Tab accent parity for the two new sections (matches the existing
   underline treatment in the surface dashboard.css). */
.dash-section-btn[data-section="community"][aria-selected="true"]::after,
.dash-section-btn[data-section="events"][aria-selected="true"]::after {
  background: var(--marrow-red);
}
[data-mz-theme="dark"] .dash-section-btn[data-section="community"][aria-selected="true"]::after,
[data-mz-theme="dark"] .dash-section-btn[data-section="events"][aria-selected="true"]::after {
  background: var(--marrow-ember-text);
}

/* ----- Events surface, built to beat Eventbrite ----- */
.ev-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 20px;
}
.ev-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--mz-bg-card, var(--bone-white));
  border: 1px solid var(--line);
  border-radius: 16px;
  overflow: hidden;
  transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
.ev-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 20px 44px rgba(10, 9, 8, 0.10);
  border-color: color-mix(in srgb, var(--mz-brand-primary) 40%, var(--line));
}
[data-mz-theme="dark"] .ev-card:hover { box-shadow: 0 20px 44px rgba(0, 0, 0, 0.5); }

.ev-card-media {
  position: relative;
  aspect-ratio: 16 / 9;
  background:
    linear-gradient(135deg,
      color-mix(in srgb, var(--mz-brand-primary) 24%, var(--bone-white)),
      color-mix(in srgb, var(--mz-brand-primary) 6%, var(--bone-white)));
  display: flex;
  align-items: flex-end;
  padding: 12px;
  overflow: hidden;
}
.ev-card-media img,
.ev-card-media video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.ev-card-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 18px 20px 20px;
}
.ev-card-date {
  font: 600 11px var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mz-fg-muted, var(--steel));
}
.ev-card-title {
  font-family: var(--display);
  font-weight: 800;
  font-size: 19px;
  line-height: 1.18;
  letter-spacing: -0.01em;
  color: var(--mz-fg-heading, var(--bone-black));
}
.ev-card-meta {
  font: 400 13.5px var(--sans);
  line-height: 1.5;
  color: var(--mz-fg-muted, var(--steel));
}
.ev-card-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 4px;
}

/* Badge sits on the brand fill, ink is the engine-computed readable pairing. */
.ev-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--mz-brand-primary);
  color: var(--mz-brand-on-primary);
  font: 600 10.5px var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
}
.ev-badge--soft {
  background: color-mix(in srgb, var(--mz-brand-primary) 14%, var(--bone-white));
  color: var(--mz-fg-heading, var(--bone-black));
}
.ev-badge--free {
  background: color-mix(in srgb, var(--mzv-train) 16%, var(--bone-white));
  color: var(--mzv-train);
}

/* RSVP action. Compact filled button on the brand color, full microstates. */
.ev-rsvp {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  border: none;
  border-radius: 10px;
  background: var(--mz-brand-primary);
  color: var(--mz-brand-on-primary);
  font: 600 12.5px var(--sans);
  letter-spacing: 0.02em;
  cursor: pointer;
  box-shadow: 0 1px 2px rgba(10, 9, 8, 0.18);
  transition: background 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease;
}
.ev-rsvp:hover { background: var(--mz-brand-offset); transform: translateY(-1px); box-shadow: 0 8px 18px rgba(107, 15, 26, 0.28); }
.ev-rsvp:focus-visible { outline: 2px solid var(--marrow-red); outline-offset: 2px; }
.ev-rsvp:active { transform: translateY(0); box-shadow: 0 1px 2px rgba(10, 9, 8, 0.24); }
.ev-rsvp[aria-pressed="true"] {
  background: color-mix(in srgb, var(--mz-brand-primary) 14%, var(--bone-white));
  color: var(--mz-fg-heading, var(--bone-black));
  box-shadow: none;
}
.ev-rsvp[disabled] { background: var(--steel); color: var(--mzv-onfill); cursor: not-allowed; box-shadow: none; }
/* --steel FLIPS to the light #A8B4C4 under the dark stamp while --mzv-onfill
   is constant light, so the disabled label read 1.92 to 1 there. Same pairing
   and same repair as section 19.2 below: name the page black for the dark
   table. Found by PART 12 of tests/theme-ink-ground-guard.test.mjs. */
:root[data-mz-theme="dark"] .ev-rsvp[disabled] { color: var(--bone-cream); }
[data-mz-theme="dark"] .ev-rsvp:focus-visible { outline-color: var(--marrow-ember-text); }

/* Co-host stack. Small overlapping avatars plus a label. */
.ev-cohost { display: inline-flex; align-items: center; gap: 8px; }
.ev-cohost-avatars { display: inline-flex; }
.ev-cohost-avatars > * {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 2px solid var(--bone-white);
  margin-left: -8px;
  object-fit: cover;
  background: color-mix(in srgb, var(--mz-brand-primary) 20%, var(--bone-white));
}
.ev-cohost-avatars > *:first-child { margin-left: 0; }
.ev-cohost-label {
  font: 500 12px var(--sans);
  color: var(--mz-fg-muted, var(--steel));
}

/* ----- Community feed ----- */
.cm-feed { display: flex; flex-direction: column; gap: 16px; }
.cm-post {
  background: var(--mz-bg-card, var(--bone-white));
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 18px 20px;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.cm-post:hover { border-color: color-mix(in srgb, var(--mz-brand-primary) 30%, var(--line)); box-shadow: 0 12px 30px rgba(10, 9, 8, 0.07); }
[data-mz-theme="dark"] .cm-post:hover { box-shadow: 0 12px 30px rgba(0, 0, 0, 0.45); }
.cm-post-head { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.cm-post-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
  background: color-mix(in srgb, var(--mz-brand-primary) 20%, var(--bone-white));
  flex: none;
}
.cm-post-author {
  font-family: var(--sans);
  font-weight: 600;
  font-size: 14px;
  color: var(--mz-fg-heading, var(--bone-black));
  line-height: 1.2;
}
.cm-post-time {
  font: 500 11.5px var(--mono);
  letter-spacing: 0.06em;
  color: var(--mz-fg-muted, var(--steel));
}
.cm-post-body {
  font: 400 14.5px var(--sans);
  line-height: 1.6;
  color: var(--mz-fg-body, var(--bone-black));
}
.cm-post-actions { display: flex; gap: 18px; margin-top: 14px; }
.cm-post-action {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0;
  background: transparent;
  border: none;
  cursor: pointer;
  font: 500 12.5px var(--sans);
  color: var(--mz-fg-muted, var(--steel));
  transition: color 0.15s ease;
}
.cm-post-action:hover { color: var(--mz-fg-link, var(--marrow-red)); }
.cm-post-action:focus-visible { outline: 2px solid var(--marrow-red); outline-offset: 3px; border-radius: 3px; }
.cm-post-action[aria-pressed="true"] { color: var(--mz-fg-link, var(--marrow-red)); font-weight: 600; }
[data-mz-theme="dark"] .cm-post-action:focus-visible { outline-color: var(--marrow-ember-text); }

/* Community area tiles (topics, spaces, groups a member can enter). */
.cm-area-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 14px;
}
.cm-area-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 18px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--mz-brand-primary) 7%, var(--bone-white)), var(--bone-white));
  cursor: pointer;
  text-align: left;
  transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}
.cm-area-card:hover {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--mz-brand-primary) 45%, var(--line));
  box-shadow: 0 14px 32px rgba(10, 9, 8, 0.08);
}
.cm-area-card:focus-visible { outline: 2px solid var(--marrow-red); outline-offset: 2px; }
[data-mz-theme="dark"] .cm-area-card:focus-visible { outline-color: var(--marrow-ember-text); }
.cm-area-title {
  font-family: var(--display);
  font-weight: 800;
  font-size: 16px;
  letter-spacing: -0.01em;
  color: var(--mz-fg-heading, var(--bone-black));
}
.cm-area-count {
  font: 500 12px var(--mono);
  letter-spacing: 0.08em;
  color: var(--mz-fg-muted, var(--steel));
}

@supports not (background: color-mix(in srgb, red, blue)) {
  .ev-card-media { background: var(--bone-cream); }
  .cm-area-card { background: var(--bone-white); }
}
@media (prefers-reduced-motion: reduce) {
  .ev-card, .ev-rsvp, .cm-post, .cm-post-action, .cm-area-card { transition: none; }
  .ev-card:hover, .ev-rsvp:hover, .cm-area-card:hover { transform: none; }
}

/* =====================================================================
   16. CHECK-IN SECTION  (V3.1 item 10, appended 2026-07-07)
   ---------------------------------------------------------------------
   A shared check-in block reused by both the Training and Nutrition
   surfaces: the section shell, a cadence row, and the delivery-method
   pills (text, virtual, phone, email). Readable-ink tokens throughout so
   it holds on light, dark, and any per-coach primary.
   ===================================================================== */
.checkin-section {
  background: var(--mz-bg-card, var(--bone-white));
  border: 1px solid var(--line);
  border-radius: 14px;
  /* 2026-08-04: widened from 20px 22px to the shared box inset so the copy
     never crowds the card edge. Falls back to the same numbers when the
     foundation tokens are not loaded. */
  padding: var(--mz-pad-y, 24px) var(--mz-pad-x, 28px);
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.checkin-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.checkin-section-title {
  font-family: var(--display);
  font-weight: 800;
  /* 2026-08-04: 17px to 18px so the check-in block titles carry the card
     the way Edwin asked the check-ins area to pop. */
  font-size: 18px;
  letter-spacing: -0.01em;
  color: var(--mz-fg-heading, var(--bone-black));
}
.checkin-section-note {
  font: 400 13px var(--sans);
  color: var(--mz-fg-muted, var(--steel));
}

.checkin-cadence {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.checkin-cadence-option {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 16px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: color-mix(in srgb, var(--bone-black) 3%, var(--bone-white));
  color: var(--mz-fg-body, var(--bone-black));
  font: 600 12.5px var(--sans);
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease, transform 0.15s ease;
}
.checkin-cadence-option:hover { border-color: var(--bone-black); transform: translateY(-1px); }
.checkin-cadence-option:focus-visible { outline: 2px solid var(--marrow-red); outline-offset: 2px; }
.checkin-cadence-option[aria-pressed="true"],
.checkin-cadence-option.is-selected {
  background: var(--mz-brand-primary);
  border-color: var(--mz-brand-primary);
  color: var(--mz-brand-on-primary);
}
[data-mz-theme="dark"] .checkin-cadence-option:focus-visible { outline-color: var(--marrow-ember-text); }

/* Delivery-method pills. Neutral by default, brand fill when selected, each
   method keeps a small color cue drawn from the functional metric tokens
   so the four read apart at a glance. */
.checkin-methods {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.checkin-method {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bone-white);
  color: var(--mz-fg-body, var(--bone-black));
  font: 600 12.5px var(--sans);
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease, transform 0.15s ease;
}
.checkin-method::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--steel);
  flex: none;
}
.checkin-method--text::before    { background: var(--mzv-train); }
.checkin-method--virtual::before { background: var(--mzv-mind); }
.checkin-method--phone::before   { background: var(--mzv-money); }
.checkin-method--email::before   { background: var(--mzv-roster); }
.checkin-method:hover { border-color: var(--bone-black); transform: translateY(-1px); }
.checkin-method:focus-visible { outline: 2px solid var(--marrow-red); outline-offset: 2px; }
.checkin-method[aria-pressed="true"],
.checkin-method.is-selected {
  background: var(--mz-brand-primary);
  border-color: var(--mz-brand-primary);
  color: var(--mz-brand-on-primary);
}
.checkin-method[aria-pressed="true"]::before,
.checkin-method.is-selected::before { background: var(--mz-brand-on-primary); }
[data-mz-theme="dark"] .checkin-method:focus-visible { outline-color: var(--marrow-ember-text); }

@supports not (background: color-mix(in srgb, red, blue)) {
  .checkin-cadence-option { background: var(--bone-white); }
}
@media (prefers-reduced-motion: reduce) {
  .checkin-cadence-option, .checkin-method { transition: border-color 0.15s ease, background 0.15s ease; }
  .checkin-cadence-option:hover, .checkin-method:hover { transform: none; }
}

/* =====================================================================
   17. COACH SURFACE DARK REPAIRS (2026-07-24)
   The marketing footer rule in styles.css keys its background off
   --bone-black, which the dark remap flips to bone. Re-pin dashboard
   footers to the page surface. Same class of repair as the QA nav
   fixes above. No new color values, tokens only.
   ===================================================================== */
:root[data-mz-theme="dark"] footer {
  background: var(--bone-cream);
  color: var(--steel);
}
/* RE-PINNING A GROUND WITHOUT ITS INK IS HALF A REPAIR.
   The rule directly above moved the footer ground to --bone-cream, which is
   #0A0908 under this stamp. .footer-wordmark in css/styles.css keeps
   color: var(--bone-white), and --bone-white is the CARD charcoal #171411 in
   dark, so the brand block rendered its own brand at 1.08 to 1: a footer with
   no wordmark in it on every dark stamped page. --bone-black is the dark
   stamp's primary ink token, #F2EDE3, and measures 17.06 to 1 on this ground.
   Scoped to the dark stamp only, so the light footer keeps bone white on
   #0A0908 at 18.77 to 1 and is not touched. Both directions are measured in
   tests/lamella-connect-steps.test.mjs Part 10, which resolves the cascade
   across every stylesheet a page loads and then holds the CLASS: for the four
   dark stamped Lamella pages, every ink that lands on a ground this file
   re-pins has to still clear its floor there. That guard is scoped to the
   pages it can walk, so it is a floor under this family and not a proof about
   the other dark surfaces. */
:root[data-mz-theme="dark"] footer .footer-wordmark {
  color: var(--bone-black);
}

/* The program builder save bar hardcodes the cream glass the nav repairs
   above already handle. Same black glass value. */
:root[data-mz-theme="dark"] .builder-savebar {
  background: rgba(10, 9, 8, 0.92);
  border-top-color: var(--line);
}

/* Solid marrow red text fails 1.62:1 on black. Ember convention,
   extending the section 3 list to the newer surface classes. */
[data-mz-theme="dark"] .growth-card-label,
[data-mz-theme="dark"] .mg-moves li,
[data-mz-theme="dark"] .mg-card-mode.is-self,
[data-mz-theme="dark"] .mr-comm-eye,
[data-mz-theme="dark"] .mr-chal-err {
  color: var(--marrow-ember-text);
}

/* Red fills keep constant light text in both themes. */
[data-mz-theme="dark"] .mr-comm-btn {
  color: var(--mzv-onfill);
}
[data-mz-theme="dark"] .mr-comm-btn.ghost { color: var(--bone-black); }

/* Steel-light borders flip to a glowing #C3CEDC line on black. Pin the
   migrate surface chrome to the standard dark hairline. */
[data-mz-theme="dark"] .mg-moves li,
[data-mz-theme="dark"] .mg-card,
[data-mz-theme="dark"] .mg-panel,
[data-mz-theme="dark"] .mg-drop,
[data-mz-theme="dark"] .mg-recent-item,
[data-mz-theme="dark"] .mg-all-result {
  border-color: var(--line);
}

/* ---------------------------------------------------------------------
   Grep sweep, checklist step 10. Every remaining red TEXT class that
   renders on a themed coach surface and was not already covered by the
   section 3 list. Each one was checked to sit on a transparent, bone, or
   low alpha red background, never on a solid red fill, so the ember
   convention is the correct repair. Fills, borders, dots, and rails keep
   the solid red. Reused classes live here, one edit for every page.
   --------------------------------------------------------------------- */
[data-mz-theme="dark"] .dash-identity-eyebrow,
[data-mz-theme="dark"] .dash-navmenu-kicker,
[data-mz-theme="dark"] .review-kind,
[data-mz-theme="dark"] .program-card-type,
[data-mz-theme="dark"] .program-card.cta:hover,
[data-mz-theme="dark"] .ex-thumb,
[data-mz-theme="dark"] .tr-flag,
[data-mz-theme="dark"] .qc-method-tag,
[data-mz-theme="dark"] .ach-seeall,
[data-mz-theme="dark"] .mz-tour-eyebrow,
[data-mz-theme="dark"] .week-deload,
[data-mz-theme="dark"] .day-name,
[data-mz-theme="dark"] .drawer-delete,
[data-mz-theme="dark"] .ghost-link,
[data-mz-theme="dark"] .sc-remove:hover:not(:disabled),
[data-mz-theme="dark"] .programs-related-link,
[data-mz-theme="dark"] .btn-danger,
[data-mz-theme="dark"] .split-pane .pane-eyebrow,
[data-mz-theme="dark"] .field .err,
[data-mz-theme="dark"] .hub-card .hub-eyebrow,
[data-mz-theme="dark"] .mg-error,
[data-mz-theme="dark"] .agenda-day-add,
/* Second pass. These live in single line rule bodies, which the first
   grep shape missed and the rendered browser check caught. */
[data-mz-theme="dark"] .tag-chip button:hover,
[data-mz-theme="dark"] details[open] .builder-desc-hint,
[data-mz-theme="dark"] .phase-remove:hover,
[data-mz-theme="dark"] .week-item[aria-current="true"] .week-label,
[data-mz-theme="dark"] .ex-card-icon:hover,
[data-mz-theme="dark"] .icon-btn:hover,
[data-mz-theme="dark"] .canvas-exercise .remove-x:hover,
[data-mz-theme="dark"] .canvas-day-add:hover,
[data-mz-theme="dark"] .canvas-week-add:hover,
[data-mz-theme="dark"] .status-pill[data-state="rejected"],
[data-mz-theme="dark"] .mg-file-status.is-ok,
[data-mz-theme="dark"] .mg-file-remove:focus-visible,
[data-mz-theme="dark"] .mg-help a,
[data-mz-theme="dark"] .dash-checkins-grid .nut-checkin-icon,
[data-mz-theme="dark"] .dash-checkins-grid .nut-checkin-status[data-tone="warn"],
[data-mz-theme="dark"] .dash-checkins-grid .nut-checkin-status[data-tone="error"],
[data-mz-theme="dark"] .sched-banner.attention,
[data-mz-theme="dark"] .agenda-item[data-kind="booking"] .agenda-kind-pill,
[data-mz-theme="dark"] .agenda-item[data-kind="one_on_one_session"] .agenda-kind-pill {
  color: var(--marrow-ember-text);
}

/* One member of that list needs its own rule (added 2026-07-31).
   coach/dashboard/dashboard.css carries .program-card-type.template with a
   two class selector, which ties with [data-mz-theme="dark"]
   .program-card-type above. Until 2026-07-31 the coach dashboard and the
   gym console loaded that surface stylesheet BEFORE this file, so the dark
   remap above won on source order alone. Both pages now load the surface
   stylesheet LAST, per the contract in assets/css/mz-primitives.css, which
   would have handed the template chip back to the flat steel value in
   dark. Restated here at four class-level components so the deliberate
   dark remap holds on specificity instead of on load order. Same value,
   dark only, light theme untouched. */
:root[data-mz-theme="dark"] .program-card-type.template {
  color: var(--marrow-ember-text);
}

/* Grep sweep, checklist step 11. Text sitting on a SOLID marrow red fill.
   Marrow red does not flip with the theme, so bone-white ink flips to the
   card charcoal and lands near black on red. Pin these to the constant
   light ink. Fills keyed to --bone-black are skipped on purpose: that
   token flips, so those buttons self correct. */
[data-mz-theme="dark"] .btn-primary,
[data-mz-theme="dark"] .btn-danger:hover,
[data-mz-theme="dark"] .sc-ordinal,
[data-mz-theme="dark"] .program-status[data-state="published"],
[data-mz-theme="dark"] .status-pill[data-state="live"],
[data-mz-theme="dark"] .mr-comm-tab[aria-selected="true"],
[data-mz-theme="dark"] .mr-comm-chip[aria-pressed="true"] {
  color: var(--mzv-onfill);
}

/* The paid pill hardcodes a deep green that scores 3.64:1 on the dark card.
   Repointed 2026-07-31 onto the shared good token, so the quick check pill
   and the invoice pill resolve to one value instead of two greens. */
[data-mz-theme="dark"] .qc-status-pill[data-state="paid"] { color: var(--mz-status-good); }

/* ---------------------------------------------------------------------
   Form control baseline. Fills the UA-default gap (grey fills in dark)
   on every themed dashboard. Element level, so any surface rule wins.
   --------------------------------------------------------------------- */
/* :where() holds this at specificity zero. The spec's stated rule is that
   the baseline "loses every specificity contest, so already styled controls
   keep their look" and only replaces UA defaults. Written bare, the seven
   :not() clauses score [0,14,1] and do the opposite: they outrank surface
   rules like .mg-field input[type="text"] [0,2,1] and flatten their
   max-width, padding, and fill in BOTH themes. :where() is the literal
   expression of the intent. */
:where(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]):not([type="submit"]):not([type="button"])),
:where(select),
:where(textarea) {
  font: inherit;
  font-size: 14px;
  color: var(--bone-black);
  background: var(--bone-cream);
  border: 1px solid var(--steel-light);
  border-radius: 8px;
  padding: 10px 12px;
  max-width: 100%;
}
input::placeholder,
textarea::placeholder {
  color: var(--mz-fg-placeholder);
  opacity: 1;
}
input:not([type="checkbox"]):not([type="radio"]):focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--marrow-red);
  outline-offset: 1px;
}
:root[data-mz-theme="dark"] input:focus-visible,
:root[data-mz-theme="dark"] select:focus-visible,
:root[data-mz-theme="dark"] textarea:focus-visible {
  outline-color: var(--marrow-ember-text);
}
:root[data-mz-theme="dark"] input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]):not([type="submit"]):not([type="button"]),
:root[data-mz-theme="dark"] select,
:root[data-mz-theme="dark"] textarea {
  border-color: var(--line);
}


/* ---------------------------------------------------------------------
   Wave 2, review finding C-1. Inverted fill text still live on the high
   traffic surfaces. Marrow red does not flip with the theme, so ink keyed
   to --bone-white lands as the card charcoal on a red fill, measured
   1.49:1. Same repair as the step 11 block above: pin the ink to the
   constant onfill token. Fills, borders, dots, and rails keep solid red.
   --------------------------------------------------------------------- */
[data-mz-theme="dark"] .inbox-unread-total,
[data-mz-theme="dark"] .inbox-row-avatar,
[data-mz-theme="dark"] .inbox-thread-avatar,
[data-mz-theme="dark"] .inbox-row-unread,
[data-mz-theme="dark"] .inbox-bubble-coach,
[data-mz-theme="dark"] .inbox-send-btn,
[data-mz-theme="dark"] .hb-seg input:checked + span,
[data-mz-theme="dark"] .hb-tag-opt input:checked + .hb-tag-body,
[data-mz-theme="dark"] .hb-tag-opt input:checked + .hb-tag-mind,
[data-mz-theme="dark"] .hb-tag-opt input:checked + .hb-tag-spirit,
[data-mz-theme="dark"] .hb-avatar,
[data-mz-theme="dark"] .hb-tab.is-active,
[data-mz-theme="dark"] .cl-filter-tab.is-active,
[data-mz-theme="dark"] .cl-preset-use:hover,
[data-mz-theme="dark"] .cl-avatar,
[data-mz-theme="dark"] .mc-viewtoggle button[aria-pressed="true"],
[data-mz-theme="dark"] .mc-cell.is-today .mc-daynum,
[data-mz-theme="dark"] .mc-copy,
[data-mz-theme="dark"] .roster-cta-primary,
[data-mz-theme="dark"] .ath-avatar,
[data-mz-theme="dark"] .add-ath-submit,
[data-mz-theme="dark"] .invite-cta-primary,
[data-mz-theme="dark"] .mv-pr-flag,
[data-mz-theme="dark"] .mv-iconbtn-play:hover:not(:disabled),
[data-mz-theme="dark"] .mv-voice-btn[data-recording="true"],
[data-mz-theme="dark"] .drawer-stage-btn[aria-checked="true"],
[data-mz-theme="dark"] .cx-btn-primary,
[data-mz-theme="dark"] .mb-btn-primary,
[data-mz-theme="dark"] .mops-pill--needs_attention,
[data-mz-theme="dark"] .wiz-step-dot[data-state="done"],
[data-mz-theme="dark"] .wiz-readiness-pill.is-selected,
[data-mz-theme="dark"] .fp-card[data-latest="true"] .band-pill,
[data-mz-theme="dark"] .severity-pill[data-severity="critical"],
[data-mz-theme="dark"] .imp-stepper-item[data-state="active"] .imp-stepper-dot,
[data-mz-theme="dark"] .imp-warning-list-num,
[data-mz-theme="dark"] .imp-map-required-flag,
[data-mz-theme="dark"] .imp-halt-mark,
[data-mz-theme="dark"] .imp-halt-cta {
  color: var(--mzv-onfill);
}

/* ---------------------------------------------------------------------
   Wave 2, review finding M-2. The section switcher renders as a <button>
   on checkins, crm, analytics, nutrition and gym dashboard, and as an <a>
   on athletes, but no base rule exists for the button form anywhere. Under
   color-scheme: dark the browser paints its own grey button face with
   white ink, which is the grey fill complaint and a templated tell. Reset
   it to the anchor form. Tokens only, both themes, no new values. The
   aria-selected decorations in dashboard.css keep their own specificity.
   --------------------------------------------------------------------- */
button.dash-section-btn {
  appearance: none;
  background: transparent;
  border: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
}

/* ---------------------------------------------------------------------
   Wave 2, review finding M-1. Third sweep pass. The wave 1 grep shape
   keyed on single property lines and on the seven verified pages, so
   compound selectors, multi line rule bodies, and the themed surfaces
   outside those seven never entered the net. This list is the machine
   checked remainder: every rule across the themed coach surfaces whose
   foreground color resolves to the solid marrow red family, minus every
   selector already remapped anywhere in this file. Solid red scores
   1.62:1 on the dark page. Text and glyph foregrounds move to the ember
   token; fills, borders, dots, and rails are untouched and stay solid red.
   --------------------------------------------------------------------- */
[data-mz-theme="dark"] .mnote-readall,
[data-mz-theme="dark"] .mnote-action,
[data-mz-theme="dark"] .mnote-empty-mark,
[data-mz-theme="dark"] .mnote-toast-action,
[data-mz-theme="dark"] .marrow-welcome-eyebrow,
[data-mz-theme="dark"] .marrow-welcome-steps li a,
[data-mz-theme="dark"] .adash-card-tag[data-state="warn"],
[data-mz-theme="dark"] .adash-card-tag[data-state="down"],
[data-mz-theme="dark"] .adash-denied a,
[data-mz-theme="dark"] .mops-denied a,
[data-mz-theme="dark"] .mops-action-msg--ok,
[data-mz-theme="dark"] .mops-action-msg--err,
[data-mz-theme="dark"] .amod-denied a,
[data-mz-theme="dark"] .amod-eyebrow,
[data-mz-theme="dark"] .astf-denied a,
[data-mz-theme="dark"] .astf-eyebrow,
[data-mz-theme="dark"] .astf-btn.danger,
[data-mz-theme="dark"] .asup-denied a,
[data-mz-theme="dark"] .asup-eyebrow,
[data-mz-theme="dark"] .an-kpi-risk .kpi-value,
[data-mz-theme="dark"] .an-inline-link,
[data-mz-theme="dark"] .an-eyebrow-risk,
[data-mz-theme="dark"] .an-risk-meta,
[data-mz-theme="dark"] .status-pill.at-risk,
[data-mz-theme="dark"] .an-cell-risk,
[data-mz-theme="dark"] .detail-avatar,
[data-mz-theme="dark"] .detail-status-badge[data-status="onboarding"],
[data-mz-theme="dark"] .overview-prs li strong,
[data-mz-theme="dark"] .sess-status[data-status="missed"],
[data-mz-theme="dark"] .review-flag strong,
[data-mz-theme="dark"] .session-exercises .ex-actual.is-pr,
[data-mz-theme="dark"] .session-side .unreviewed,
[data-mz-theme="dark"] .program-block[data-block-status="current"],
[data-mz-theme="dark"] .program-week .status[data-status="missed"],
[data-mz-theme="dark"] .msg-bubble.kind-form_video .form-attach,
[data-mz-theme="dark"] .form-card-pr,
[data-mz-theme="dark"] .nutrition-plan-caution,
[data-mz-theme="dark"] .checkin-chip[data-mood="drained"],
[data-mz-theme="dark"] .attendance-badge[data-tone="missed"],
[data-mz-theme="dark"] .achievement-icon,
[data-mz-theme="dark"] .detail-risk-chip-label,
[data-mz-theme="dark"] .sg-swap,
[data-mz-theme="dark"] .mv-iconbtn-danger:hover,
[data-mz-theme="dark"] .mv-fallback .mono,
[data-mz-theme="dark"] .mv-item-stamp,
[data-mz-theme="dark"] .mv-item-del:hover,
[data-mz-theme="dark"] .mv-warning,
[data-mz-theme="dark"] .status-pill.churned,
[data-mz-theme="dark"] .add-ath-error,
[data-mz-theme="dark"] .af-note-band > svg,
[data-mz-theme="dark"] .af-held-flag svg,
[data-mz-theme="dark"] .af-held-pill,
[data-mz-theme="dark"] .af-icon-btn:hover,
[data-mz-theme="dark"] .af-outcome-pill[data-outcome="queued_held"],
[data-mz-theme="dark"] .af-outcome-pill[data-outcome="test"],
[data-mz-theme="dark"] .ck-status-chip[data-status="submitted"],
[data-mz-theme="dark"] .ck-reply-status,
[data-mz-theme="dark"] .kb-col-title,
[data-mz-theme="dark"] .drawer-section-h,
[data-mz-theme="dark"] .drawer-files li .file-kind,
[data-mz-theme="dark"] .bc-count[data-warn="true"],
[data-mz-theme="dark"] .bc-recent-kind.email,
[data-mz-theme="dark"] .bc-recent-status[data-status="scheduled"],
[data-mz-theme="dark"] .pg-row-url:hover,
[data-mz-theme="dark"] .pg-template-best,
[data-mz-theme="dark"] .tk-meta[data-overdue="true"],
[data-mz-theme="dark"] .tk-delete:hover,
[data-mz-theme="dark"] .rt-group[data-tier="lapsing"] .rt-group-title,
[data-mz-theme="dark"] .rt-client-days[data-tier="lapsing"],
[data-mz-theme="dark"] .cx-nav-help:hover,
[data-mz-theme="dark"] .cx-btn-text:hover,
[data-mz-theme="dark"] .imp-tier-price,
[data-mz-theme="dark"] .imp-tier-status-hold,
[data-mz-theme="dark"] .imp-warning-eyebrow,
[data-mz-theme="dark"] .imp-file-mark[data-kind="clients"],
[data-mz-theme="dark"] .imp-file-mark[data-kind="unknown"],
[data-mz-theme="dark"] .imp-file-sub[data-flag="warn"],
[data-mz-theme="dark"] .imp-file-remove:hover,
[data-mz-theme="dark"] .imp-file-remove:focus-visible,
[data-mz-theme="dark"] .imp-conf-pill[data-conf="low"],
[data-mz-theme="dark"] .imp-row-issue,
[data-mz-theme="dark"] .imp-error-list strong,
[data-mz-theme="dark"] .imp-summary-stat-num,
[data-mz-theme="dark"] .imp-rebill-msg,
[data-mz-theme="dark"] .imp-draft-status[data-state="saving"],
[data-mz-theme="dark"] .ghost-link:hover,
[data-mz-theme="dark"] .ghost-link:focus-visible,
[data-mz-theme="dark"] .mig-card-status[data-status="ready"],
[data-mz-theme="dark"] .mig-help-eyebrow,
[data-mz-theme="dark"] .imp-file-mark[data-kind="csv"],
[data-mz-theme="dark"] .field-hint[data-state="error"],
[data-mz-theme="dark"] .form-banner,
[data-mz-theme="dark"] .save-status[data-state="saving"],
[data-mz-theme="dark"] .save-status[data-state="error"],
[data-mz-theme="dark"] .profile-preview-link a,
[data-mz-theme="dark"] .profile-preview-link a:hover,
[data-mz-theme="dark"] .fp-card[data-latest="true"]::before,
[data-mz-theme="dark"] .severity-flag,
[data-mz-theme="dark"] .fp-compare-label,
[data-mz-theme="dark"] .fp-card-athlete,
[data-mz-theme="dark"] .cf-legal-note > svg,
[data-mz-theme="dark"] .cf-review-pill[data-state="needs"],
[data-mz-theme="dark"] .marrow-founder-badge__eyebrow,
[data-mz-theme="dark"] .gr-chip[data-tone="red"],
[data-mz-theme="dark"] .gr-form-status,
[data-mz-theme="dark"] .gr-remove-btn:hover,
[data-mz-theme="dark"] .gr-remove-btn:focus-visible,
[data-mz-theme="dark"] .gr-session-when,
[data-mz-theme="dark"] .gr-board-row[data-top="true"] .gr-board-rank,
[data-mz-theme="dark"] .hb-preview-chip,
[data-mz-theme="dark"] .hb-icon-btn:hover,
[data-mz-theme="dark"] .cl-preset-use,
[data-mz-theme="dark"] .iv-hold-note > svg,
[data-mz-theme="dark"] .iv-line-remove:hover:not([disabled]),
[data-mz-theme="dark"] .iv-row-open:hover,
[data-mz-theme="dark"] .mb-eyebrow,
[data-mz-theme="dark"] .mb-signin a,
[data-mz-theme="dark"] .mb-help a,
[data-mz-theme="dark"] .mb-error,
[data-mz-theme="dark"] .mb-card-price,
[data-mz-theme="dark"] .mg-file-remove:hover,
[data-mz-theme="dark"] .mig-job-eyebrow,
[data-mz-theme="dark"] .mig-item-kind,
[data-mz-theme="dark"] .adh-data > summary,
[data-mz-theme="dark"] .plan-card-new:hover,
[data-mz-theme="dark"] .review-card-stat-num[data-tone="low"],
[data-mz-theme="dark"] .nut-checksum[data-tone="warn"] .nut-checksum-body,
[data-mz-theme="dark"] .nut-generator > summary::before,
[data-mz-theme="dark"] .nut-checkin-ref-link:hover,
[data-mz-theme="dark"] .nut-checkin-status[data-tone="error"],
[data-mz-theme="dark"] .mp-targets-eyebrow,
[data-mz-theme="dark"] .mp-targets-warn-link,
[data-mz-theme="dark"] .pe-eyebrow,
[data-mz-theme="dark"] .pe-status.err,
[data-mz-theme="dark"] .wiz-eyebrow,
[data-mz-theme="dark"] .wiz-secondary-card.is-selected,
[data-mz-theme="dark"] .wiz-program-tag,
[data-mz-theme="dark"] .wiz-form-error,
[data-mz-theme="dark"] .wiz-cohort-action,
[data-mz-theme="dark"] .wiz-roadmap h2,
[data-mz-theme="dark"] .od-badge[data-tone="attention"],
[data-mz-theme="dark"] .od-quality-mark[data-state="fail"],
[data-mz-theme="dark"] .od-banner.attention,
[data-mz-theme="dark"] .od-panel .panel-eyebrow,
[data-mz-theme="dark"] .cp-chip-paid,
[data-mz-theme="dark"] .cp-cancel-btn:hover,
[data-mz-theme="dark"] .cp-service-remove:hover:not([disabled]),
[data-mz-theme="dark"] .perm-eyebrow,
[data-mz-theme="dark"] .perm-status.is-ok,
[data-mz-theme="dark"] .perm-status.is-err,
[data-mz-theme="dark"] .perm-toggle-default.is-overridden,
[data-mz-theme="dark"] .cp-frame-tag,
[data-mz-theme="dark"] .mx-table-toggle,
[data-mz-theme="dark"] .ret-pill[data-tone="red"],
[data-mz-theme="dark"] .ret-onb-first.missing,
[data-mz-theme="dark"] .ret-ttfv[data-hit="false"],
[data-mz-theme="dark"] .ret-onb-status[data-status="stalled"],
[data-mz-theme="dark"] .ret2-kpi-foot.down,
[data-mz-theme="dark"] .ret2-kpi-link:hover,
[data-mz-theme="dark"] .ret2-reason-rank,
[data-mz-theme="dark"] .ret2-atrisk-signal,
[data-mz-theme="dark"] .mc-more,
[data-mz-theme="dark"] .st-status-row a,
[data-mz-theme="dark"] .st-pill-attention,
[data-mz-theme="dark"] .st-empty a,
[data-mz-theme="dark"] .st-preview-chip,
[data-mz-theme="dark"] .st-hex-err,
[data-mz-theme="dark"] .st-pct-sign,
[data-mz-theme="dark"] .st-plan-custom .st-plan-num,
[data-mz-theme="dark"] .tl-status a,
[data-mz-theme="dark"] .tl-card-style,
[data-mz-theme="dark"] .tl-block-name,
[data-mz-theme="dark"] .tr-kicker,
[data-mz-theme="dark"] .tr-summary-num,
[data-mz-theme="dark"] .type-badge[data-type="follow_along"],
[data-mz-theme="dark"] .cw-preview-chip,
[data-mz-theme="dark"] .cw-pill.ok {
  color: var(--marrow-ember-text);
}

/* Same C-1 class, two hits the review inventory listed but did not carry
   into its fix list. Both sit on a fill that does not flip with the theme:
   the staff primary button on solid marrow red, and the video duration
   badge on a fixed dark overlay. */
[data-mz-theme="dark"] .astf-btn.primary,
[data-mz-theme="dark"] .vid-thumb-duration,
/* Browser pass additions. The ink on these comes from a base rule keyed to a
   bone token, while a later rule swaps the fill to a value that does not flip.
   The importer howto marker lands near black on solid red at 1.49:1.
   .plan-card-action.primary:hover left this list on 2026-08-04: its hover
   fill is var(--ash), which the dark remap now turns light, so the base
   rule's flipped dark ink is the correct pairing and the onfill pin here
   would have put light ink on a light fill. */
[data-mz-theme="dark"] .imp-howto-card-meta .imp-howto-num {
  color: var(--mzv-onfill);
}

/* ---------------------------------------------------------------------
   Wave 3, sign-off findings F-1, F-3, F-4 and F-6. The last defects live
   in chrome the themed coach pages pull from css/styles.css and
   community/community.css, two files no earlier sweep entered because
   both sweeps scoped their net to the coach/ directory. A sweep's net is
   defined by what the PAGES load, never by directory.

   Every rule below is dark scoped, so the public marketing pages that
   share css/styles.css and never carry data-mz-theme stay exactly as
   they are. No new color values: tokens and the established dark
   conventions only.
   --------------------------------------------------------------------- */

/* F-1. The marketing nav band is a literal cream glass that does not flip
   with the theme, so its ink lands light on light at 1.44:1 on the first
   page a new coach sees. Same black glass family as the .dash-nav and
   builder save bar repairs above. */
:root[data-mz-theme="dark"] .nav {
  background: rgba(10, 9, 8, 0.85);
}

/* F-1. Solid marrow red does not flip, so ink keyed to a bone token lands
   as the card charcoal on the red fill. Constant light ink instead. */
[data-mz-theme="dark"] .nav-cta {
  color: var(--mzv-onfill);
}

/* F-1. The orb hero is a fixed dark band. Its ink is keyed to bone tokens
   that flip, which takes the headline to 1.08:1 and the lede to 1.00:1,
   both effectively invisible. Constant light ink on a fixed dark fill,
   the same rule the rest of this section applies. */
[data-mz-theme="dark"] .onb-orb-hero .onb-eyebrow,
[data-mz-theme="dark"] .onb-orb-hero .onb-title,
[data-mz-theme="dark"] .onb-orb-hero .onb-lede,
[data-mz-theme="dark"] .onb-orb-hero .onb-lede strong {
  color: var(--mzv-onfill);
}

/* F-1 and F-3. Solid marrow red as text on a dark card, 1.49:1 on the
   onboarding form and 1.62:1 on the progress hero. Ember convention,
   extending the section 3 list to the shared marketing classes. */
[data-mz-theme="dark"] .apply-form-eyebrow,
[data-mz-theme="dark"] .consent-label a,
[data-mz-theme="dark"] .page-hero-eyebrow {
  color: var(--marrow-ember-text);
}

/* F-4. The community nav band is a second literal cream glass, this one
   on the themed event pages, measured 1.07:1. Same repair as the
   marketing band above. */
:root[data-mz-theme="dark"] .com-nav {
  background: rgba(10, 9, 8, 0.92);
  border-bottom-color: var(--line);
}
[data-mz-theme="dark"] .com-nav-brand-text small {
  color: var(--marrow-ember-text);
}

/* F-4. Both button states swap to a solid red fill that does not flip,
   while the ink stays keyed to a bone token. */
[data-mz-theme="dark"] .com-btn.primary:hover,
[data-mz-theme="dark"] .com-btn.red {
  color: var(--mzv-onfill);
}

/* F-6. Brand preview eyebrow: the brand primary rendered as TEXT on the
   dark settings card, 1.49:1. The token itself stays untouched because it
   drives fills, the color-mix tint recipes above, achievement accents and
   two JS readers, and the theme engine deepens saved picks so they read
   on LIGHT surfaces. Mixing toward the constant light ink keeps whatever
   hue a coach saved and always clears AA on the dark card. color-mix on
   the brand token is this file's established idiom, see section 13. */
[data-mz-theme="dark"] .st-preview-eyebrow {
  color: color-mix(in srgb, var(--mz-brand-primary) 40%, var(--mzv-onfill));
}

/* ---------------------------------------------------------------------
   Wave 4, sign-off finding. The post payment welcome hero on
   /coach/onboarded/ is the last rule on a coach surface that keys its
   own FILL off --bone-black, exactly the defect family the marketing
   footer repair at the head of this section fixed. The dark remap turns
   --bone-black into bone, so the hero card flips to cream while every
   ink inside it stays keyed to dark theme values: the ember eyebrow and
   welcome name land at 2.22:1 and the two subtitle lines at 1.37:1.

   Repin the card to the dark card surface token so it stays a raised
   dark block, and give it the constant light ink every fixed dark fill
   in this file already uses. The two strong rules inside the card key
   off --bone-white, which the remap turns into that same card charcoal,
   so they move to the constant light ink with it. Dark scoped, tokens
   only, no new values, light theme untouched.
   --------------------------------------------------------------------- */
[data-mz-theme="dark"] .ob-status-card {
  background: var(--bone-white);
  color: var(--mzv-onfill);
}
[data-mz-theme="dark"] .ob-subtitle strong,
[data-mz-theme="dark"] .ob-pending-banner strong {
  color: var(--mzv-onfill);
}

/* =====================================================================
   18. DASHBOARD FOUNDATION APPENDIX  (Lane 1, appended 2026-07-30)
   ---------------------------------------------------------------------
   Four token families the dashboards were missing: a productive type
   scale, an accent independent status layer, spacing and radius half
   steps, and dashboard scoped motion. Plus the dark raised surface
   ladder and the dark side of the light --mz-bg-card fix above.

   Nothing here renames, reorders, or redefines an existing --mz-* token
   except the single documented --mz-bg-card light value in section 11.
   No new brand color or font token is introduced. Every hex below
   already exists in this repo, cited per line. Consumed by
   /assets/css/mz-primitives.css, which loads after this file.
   ===================================================================== */

/* ---------------------------------------------------------------------
   18.1  TYPE SCALE
   Productive scale, tight steps in the 12px to 20px working band, wider
   above. Switzer (--display) sets the page title and large metrics,
   Inter (--sans) is the UI font and never renders above 24px here,
   JetBrains Mono (--mono) sets labels, eyebrows and timestamps.
   Nothing renders below 12px. Sizes only, no color identity.
   --------------------------------------------------------------------- */
:root {
  --fs-page:      1.75rem;  /* 28px, page title, Switzer 700, lh 1.15, tracking -0.02em */
  --fs-section:   1.25rem;  /* 20px, section header, Inter 600, lh 1.30, tracking -0.01em */
  --fs-card:      1rem;     /* 16px, card title, Inter 600, lh 1.375, tracking 0 */
  --fs-metric-xl: 2.5rem;   /* 40px, hero metric, Switzer 600, lh 1.05, tracking -0.025em */
  --fs-metric:    2rem;     /* 32px, card metric, Switzer 600, lh 1.10, tracking -0.02em */
  --fs-metric-sm: 1.25rem;  /* 20px, inline or table metric, Inter 600, lh 1.20, tracking -0.01em */
  --fs-body:      0.875rem; /* 14px, body and prose in panels, Inter 400, lh 1.50 */
  --fs-td:        0.875rem; /* 14px, table cell, Inter 400, lh 1.43 */
  --fs-th:        0.75rem;  /* 12px, table header, Inter 600, uppercase, tracking 0.04em */
  --fs-label:     0.75rem;  /* 12px, metric label and eyebrow, mono 500, uppercase, tracking 0.08em */
  --fs-help:      0.75rem;  /* 12px, helper and caption, Inter 400, sentence case */
}

/* ---------------------------------------------------------------------
   18.2  SEMANTIC STATUS LAYER, ACCENT INDEPENDENT
   Two non overlapping color jobs. Identity and interaction belong to the
   brand layer alone (--mz-accent, --mz-brand-*). State belongs here and
   NEVER references the brand layer, so a gym whose theme-engine brand is
   green cannot make brand read as success. theme-engine.js never writes
   these names.

   Functional tokens, not new brand colors, the same precedent as
   --marrow-ember-text in styles.css. Every hex is reused:
     #0C632C  = --r2-cat-nutrition light   (styles.css:4990)
     #9E2B18  = --r2-cat-training light    (styles.css:4988)
     #6D28D9  = --mzv-spirit light         (this file, section 1)
     #4E4942  = --r2-muted-color light     (styles.css:4970)
     #3ECF74  = --r2-cat-nutrition dark    (styles.css:5009)
     #E08894  = --marrow-ember-text        (styles.css:12)
     #B79CFF  = --mzv-spirit dark          (this file, section 2)
     #C9C2B4  = --r2-muted-color dark      (styles.css:5003)
   Info moved off #475569 / #B8C5D6 on 2026-07-31. Those were --steel and
   --steel-light, which are also --mz-fg-muted, so info and muted were the
   same ink. See the note on the token itself.

   Rules: there is no warning amber, a caution renders neutral plus glyph
   plus words. Never color alone, every status ships color plus glyph plus
   word. --marrow-red is never a status color and never text on dark.
   Trend direction is not a status.
   --------------------------------------------------------------------- */
:root {
  --mz-status-good:         #0C632C;
  --mz-status-good-soft:    rgba(12, 99, 44, 0.10);
  --mz-status-risk:         #9E2B18;
  --mz-status-risk-soft:    rgba(158, 43, 24, 0.10);
  /* 2026-07-31. Was #475569, byte identical to --steel and therefore to
     --mz-fg-muted, so an info chip and a muted label were the same hue in
     light and only their words told them apart. Now --mzv-spirit
     (dashboard-theme.css:34), an existing value, no new hue family.
     #6D28D9 on the light card 6.70:1, on the light page 5.87:1, both AA.
     CIEDE2000 from muted #475569 is 18.38, from good 50.78, risk 42.10,
     neutral 36.63. */
  --mz-status-info:         #6D28D9;
  --mz-status-info-soft:    rgba(109, 40, 217, 0.10);
  --mz-status-neutral:      #4E4942;
  --mz-status-neutral-soft: rgba(78, 73, 66, 0.10);
}
:root[data-mz-theme="dark"] {
  --mz-status-good:         #3ECF74;
  --mz-status-good-soft:    rgba(62, 207, 116, 0.15);
  --mz-status-risk:         #E08894;
  --mz-status-risk-soft:    rgba(224, 136, 148, 0.15);
  /* Dark follows light onto the spirit pair, --mzv-spirit dark
     (dashboard-theme.css:66). The old #B8C5D6 scored CIEDE2000 4.47 against
     dark muted #A8B4C4, a just noticeable difference, so dark carried a
     quieter version of the same collision. #B79CFF is 8.05:1 on the dark
     card, 8.73:1 on the dark page, and 12.92 from dark muted. */
  --mz-status-info:         #B79CFF;
  --mz-status-info-soft:    rgba(183, 156, 255, 0.15);
  --mz-status-neutral:      #C9C2B4;
  --mz-status-neutral-soft: rgba(201, 194, 180, 0.15);
}

/* ---------------------------------------------------------------------
   18.3  SPACING AND RADIUS
   --space-1 through --space-8 in styles.css are untouched. Two half
   steps are added for optical corrections only. Everything vertical
   resolves to a multiple of 4, the only 2px values are optical.
   Exactly two radius values exist on these surfaces. Avatars and the
   brand mark are the only circles.
   --------------------------------------------------------------------- */
:root {
  --space-025: 2px;
  --space-05:  4px;
  --radius-sm: 4px;   /* inputs, pills, chips, chart elements */
  --radius-md: 10px;  /* cards, panels, modals */
}

/* ---------------------------------------------------------------------
   18.4  MOTION, DASHBOARD SCOPED
   The THEME-CONTRACT motion tokens live in css/marrow-theme.css, which no
   dashboard loads. These are the dashboard scoped equivalents, taking the
   exact values that contract documents so web and app stay one language.
   Only the fast three durations and three easings exist. The slow pair
   and the spring are deliberately NOT defined here so they cannot be
   misused. Nothing above 240ms, no overshoot.

   Reduced motion is already handled site wide in this file, in the
   surface CSS, and in styles.css. The block below collapses these new
   tokens in step with those, it does not duplicate them.
   --------------------------------------------------------------------- */
:root {
  --mz-dur-instant: 80ms;
  --mz-dur-fast:    160ms;
  --mz-dur-base:    240ms;
  --mz-ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
  --mz-ease-out:      cubic-bezier(0.16, 1, 0.3, 1);
  --mz-ease-in:       cubic-bezier(0.7, 0, 0.84, 0);
}
@media (prefers-reduced-motion: reduce) {
  :root {
    --mz-dur-instant: 0.01ms;
    --mz-dur-fast:    0.01ms;
    --mz-dur-base:    0.01ms;
  }
}

/* ---------------------------------------------------------------------
   18.5  SURFACE LADDER
   Light mode resting card is --mz-bg-card with a 1px --line border and no
   shadow, so every raised level resolves to the same card surface. Dark
   mode bans shadows outright, depth comes from this ladder plus the
   hairline. Both dark levels are computed with color-mix from the two
   canonical bone values already in this file, so no new hex is created.

   Dark --mz-bg-card is restored here to the card charcoal it has always
   had. Section 11 above now pins the LIGHT value to a literal, which
   would otherwise have leaked the light card into the dark theme.
   --------------------------------------------------------------------- */
:root {
  --mz-bg-raised:  var(--mz-bg-card);
  --mz-bg-overlay: var(--mz-bg-card);
  --mz-bg-modal:   var(--mz-bg-card);
}
:root[data-mz-theme="dark"] {
  --mz-bg-card:    var(--bone-white);                          /* #171411 under the dark remap */
  --mz-bg-raised:  color-mix(in srgb, #EFE9DC 7%,  #0A0908);   /* hover, sticky header */
  --mz-bg-overlay: color-mix(in srgb, #EFE9DC 10%, #0A0908);   /* dropdown, popover */
  --mz-bg-modal:   color-mix(in srgb, #EFE9DC 14%, #0A0908);   /* modal, drawer */
}
@supports not (background: color-mix(in srgb, red, blue)) {
  :root[data-mz-theme="dark"] {
    --mz-bg-raised:  var(--bone-white);
    --mz-bg-overlay: var(--bone-white);
    /* Was var(--ash). The 2026-08-04 dark remap turns ash into a light ink,
       so a modal keyed to it would flash light in dark on the no color-mix
       browsers. The card token is the correct dark surface here. */
    --mz-bg-modal:   var(--bone-white);
  }
}

/* =====================================================================
   19. PREMIUM POLISH WAVE (2026-08-04)
   ---------------------------------------------------------------------
   Edwin's voice note remediation, fixed at the source so every surface
   corrects at once. Four repairs:
     19.1 corner tags get a chip inset so small mono type never sits
          flush in a card corner
     19.2 the disabled dashboard primary button (the Save cadence
          "white and blue" complaint) becomes a full opacity, AA passing
          state in both themes
     19.3 the nutrition legal footer's hardcoded 60 percent black ink,
          invisible on the dark card, moves to the muted role token
     19.4 nothing else: the "too gray" body ink family is fixed by the
          --ash dark remap in section 2, not here
   Tokens only, no new color values.
   ===================================================================== */

/* 19.1 CORNER TAGS. .card-meta inside a .card-head is the small
   uppercase count and quiet state tag ("None today", "Quiet week",
   "Empty"). Two class specificity beats the surface's one class rule
   regardless of load order, so this corrects every dashboard at once.
   --line as a soft chip fill flips with the theme. Contrast held: the
   tag ink is --steel, 5.9:1 or better on the tinted chip in light,
   8.4:1 or better in dark. */
.card-head .card-meta {
  padding: 5px 12px;
  background: var(--line);
  border-radius: 999px;
  line-height: 1.4;
  white-space: nowrap;
}

/* 19.2 DISABLED PRIMARY BUTTON. The base rule paints a disabled
   .btn-primary-dash steel blue with bone ink, and the nutrition surface
   fades the whole button to 0.55 opacity, which lands the Save cadence
   label at 2.55:1 in light and 1.69:1 in dark. Element plus class plus
   pseudo class outranks the surface's .nut-checkin-save:disabled, so the
   fade is retired everywhere. After: 7.14:1 in light (bone ink on
   steel), 9.47:1 in dark (page ink on the flipped light steel). */
button.btn-primary-dash[disabled],
button.btn-primary-dash:disabled,
.btn-primary-dash[disabled] {
  background: var(--steel);
  color: var(--mzv-onfill);
  opacity: 1;
  box-shadow: none;
  cursor: not-allowed;
}
:root[data-mz-theme="dark"] button.btn-primary-dash[disabled],
:root[data-mz-theme="dark"] button.btn-primary-dash:disabled {
  /* Dark flips --steel to #A8B4C4, a light fill, so the constant light
     ink would vanish. --bone-cream is the page black under the remap. */
  color: var(--bone-cream);
}

/* 19.3 LEGAL FOOTER INK. rgba(10, 9, 8, 0.6) is a literal that cannot
   flip, measured 1.02:1 on the dark card. The muted role token reads
   8.73:1 on the dark card per the section 11 table. Dark scoped, the
   light theme keeps its current look. */
[data-mz-theme="dark"] .nut-legal-footer {
  color: var(--mz-fg-muted);
  border-top-color: var(--line);
}

/* =====================================================================
   MZ SURFACE HEADER + PREMIUM CARD SCALE, DARK THEME (2026-08-05)
   Companion to the two blocks of the same names at the tail of
   /css/styles.css. The header itself needs no dark rules: every ink it
   uses is a remapped token (bone-black, steel, steel-light, bone-white,
   line) and the orb strokes already flip via the .logo-svg rules in
   section 3 of this file. What does need remapping are the premium
   card's elevation, sheen, and glow layers, which ride custom
   properties precisely so this block can restyle them without touching
   the !important declarations in styles.css. Values are low-alpha
   overlays of existing token values only, per the rgba convention used
   throughout this file.
   ===================================================================== */
:root[data-mz-theme="dark"] {
  /* Dark elevation: an inset top hairline of bone light catches the
     card edge like a machined bevel, and the ambient goes deeper. */
  --mz-card-shadow: inset 0 1px 0 rgba(242, 237, 227, 0.05), 0 18px 44px rgba(0, 0, 0, 0.55);
  /* Faint top-down bone sheen so the card reads as a lit surface, not
     a flat cutout, on the black page. 4 percent at the top edge. */
  --mz-card-sheen: linear-gradient(180deg, rgba(242, 237, 227, 0.04), rgba(242, 237, 227, 0) 55%);
  /* Brand glow wash goes to the glow-red value at higher alpha, since
     dark surfaces swallow low-alpha red. */
  --mz-card-glow-fill: radial-gradient(120% 60% at 50% 0%, rgba(139, 24, 40, 0.16), transparent 60%);
}
/* Accent micro label follows the ember convention: solid marrow red
   text fails on the dark card, ember clears 7.09:1 there. !important
   matches the base declaration in styles.css; this selector's higher
   specificity settles the cascade between the two importants. */
[data-mz-theme="dark"] .mz-card-micro-accent { color: var(--marrow-ember-text) !important; }


/* =========================================================================
   RED AS TYPE, ON A DARK GROUND.

   .section-eyebrow in css/styles.css is coloured with solid --marrow-red.
   That is 10.16:1 on bone cream and correct on every light marketing page.
   On the dark ground it is 1.62:1, which is the contrast defect that has
   already bitten this build three times in other forms.

   --marrow-red is NOT remapped by the theme, and must not be: it is a fill,
   a rule, a dot and a glow, and all of those are correct on both grounds.
   Only its use AS TYPE is wrong on dark, so only that is overridden here,
   and only under the dark stamp. Light pages are untouched.

   --marrow-ember-text is the shipped accessibility token for exactly this,
   css/styles.css line 19. Measured 7.69:1 on #0A0908 and 7.09:1 on #171411.

   Found by browser QA, not by a stylesheet sweep. The sweep only searched
   the Lamella stylesheets and this class lives in the shared one.
   ========================================================================= */
:root[data-mz-theme="dark"] .section-eyebrow {
  color: var(--marrow-ember-text);
}
