/* Sassu Coach — coach.sassu.fit (Track C slice 1).
   Variable names mirror the app's app.css so the two surfaces theme alike;
   coach.sassu.fit is a separate origin so the stylesheet is self-contained. */

:root {
  --bg:        #F1F5F9;
  --surface:   #FFFFFF;
  --ink:       #0F172A;
  --ink-2:     #475569;
  --muted:     #64748B;
  --line:      #CBD5E1;
  --line-2:    #E2E8F0;
  --accent:    #006E7D;
  --accent-2:  #00A8B5;
  --on-accent: #F0F9FF;
  --ok:        oklch(60% .14 145);
  --danger:    oklch(55% .14 25);
  --warn:      oklch(70% .14 85);
  /* GYM-DE-BEWEGINGSANALYSE-HOUDT-ELKE-MEETDATUM (L227) — de tweede
     signaalkleur van het overzicht: links-rechts-onbalans. Violet, bewust GEEN
     rood en GEEN groen: een verschil tussen twee kanten is geen fout en geen
     winst, en amber is al bezet door het gat passief-actief. */
  --ba-side:   oklch(58% .12 295);
  --ink-strong: #0F172A;
  /* Act-as banner. Deliberately OUTSIDE the calm palette and identical in both
     themes: it is safety UI, so it must never blend into a surface. */
  --actas-bg:  oklch(70% .14 85);
  --actas-ink: oklch(25% .05 85);
  /* One source for the macro colours: the distribution bar AND the layered
     control chart read these, so protein is one colour throughout the panel
     instead of two. They must stay distinguishable from each other, from
     --ink (which the chart uses for calories) and from --danger.
     Chroma is capped around .14 and every hue sits ≥45° from the accent and
     from its siblings, so protein no longer reads as "this is clickable".
     Identical in both themes on purpose: a macro must not change identity
     when the coach flips Day/Night mid-analysis. */
  --macro-p:   oklch(62% .14 270);
  --macro-c:   oklch(65% .14 110);
  --macro-f:   oklch(62% .14 55);

  --font-sans: -apple-system, BlinkMacSystemFont, "Inter", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --radius:  4px;
  /* previously referenced-but-undefined; fallbacks 8px/999px applied silently (.spkgrid__cell, .tabvis__chip, .tabvis__bulk) */
  --radius-sm: 4px;
  --radius-pill: 999px;
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  /* ════ DOSSIER-VLOEIENDE-RUIMTE (L183 herontwerp 3/6, 2026-10-13) ════
     ÉÉN RUIMTESCHAAL, en ze is vloeiend. Drie tokens, drie niveaus, en meer
     niveaus bestaan niet:

       --gutter       de paginamarge  (venster  -> .cmain)
       --card-pad     de ENE kaart    (.cmain   -> .dossier__panel/.csheet__panel)
       --section-gap  het ritme TUSSEN secties binnen die kaart

     "NOOIT OPGETELD" is de hele regel (§3.2 van
     docs/COACH_RESPONSIVE_AUDIT_L183_2026-10-12.md): van de rand van het
     venster tot aan een letter mag alleen --gutter + --card-pad staan. Het
     derde, vierde en vijfde niveau zijn in de vorige fase weggehaald
     (DOSSIER-EEN-KAART-DIEP, onderaan dit bestand); deze fase zet de twee die
     blijven op één schaal en laat ze meegroeien in plaats van springen.
     --section-gap is er met opzet GEEN horizontale maat — ruimte tussen
     secties hoort verticaal te zijn, want horizontaal zou het een vierde
     niveau zijn.

     WAAROM clamp() EN GEEN @media. De paginamarge sprong op 16 / 24 / 32 bij
     600 en 900px, dus 375px en 430px kregen exact dezelfde marge terwijl het
     scherm 15% groter is (bevinding #17), en een iPhone 16 Pro Max zat op de
     maat van een iPhone SE. Een clamp() heeft geen sprong: elke pixel scherm
     geeft een beetje meer lucht, en de twee uiteinden staan vast.

     DE GETALLEN ZIJN GEKOZEN, NIET GEVONDEN:
       --gutter    3.2vw + 4px geeft op 375px exact 16px — precies de waarde van
                   vandaag, dus de smalste telefoon verandert niet — en loopt
                   vloeiend door naar het plafond van 32px rond 875px, óók de
                   waarde van vandaag op een laptop. Alleen het stuk ERTUSSEN
                   wordt anders, en dat is exact wat bevinding #17 vraagt.
       --card-pad  2.5vw + 4px: 13,4px op 375 (was 16) tot 20px vanaf 640px.
                   Smal scherm levert padding in voor tekstbreedte, breed
                   scherm krijgt meer lucht dan het ooit had.
       --section-gap 2vw + 4px: blijft op elke telefoon op de vloer van 12px
                   (het ritme van vandaag) en groeit op tablet/laptop naar 20px.
     Vloeren en plafonds zijn er zodat 320px niet verstikt en een 27"-monitor
     niet uit elkaar valt; de vloer van 12px is --space-3, het plafond van 32px
     is --space-6. De schaal verlaat de bestaande staprij dus niet, hij vult
     hem op.

     DE LES VAN GELD-RUIMTE-EN-MARGES BLIJFT STAAN, en is hier zelfs harder
     nodig: de paginamarge MOET een token zijn en geen los getal, want op een
     iPad staat .cmain op `max-width: none` — zonder dit zou een 834px-scherm op
     12px blijven hangen. Dat was de reden dat --gutter bestond; dat hij nu
     vloeiend is in plaats van sprongsgewijs verandert niets aan die reden. */
  --gutter:      clamp(12px, 3.2vw + 4px, 32px);
  --card-pad:    clamp(12px, 2.5vw + 4px, 20px);
  --section-gap: clamp(12px, 2vw + 4px, 20px);
}

/* GELD-DONKER-HOORT-BIJ-HET-MERK — het donkere accent was neon-cyaan #2AF0EA,
   een vijfde kleursysteem naast merk, ok, danger en warn. Naast zoveel signaal
   viel rood niet meer op. Het accent is nu merk-ijsblauw en de donkere vlakken
   komen één stap uit het zwart, zodat een kaart van zijn achtergrond te
   onderscheiden is. Gemeten contrast (WCAG 2.1, alle vier ruim boven 4,5:1):
     --ink #F0F2F5 op --surface #0F1624 ......... 16,1:1
     --accent #6FE8FF op --bg #03040A .......... 14,3:1
     --accent #6FE8FF op --surface #0F1624 ..... 12,6:1
     --on-accent #080C14 op --accent ........... 13,7:1
   --line gaat mee naar #2A3346: --line-2 neemt zijn oude waarde over, en twee
   identieke lijnkleuren zijn geen twee lijnkleuren.

   WAAROM NIET HET KALE MERK-IJSBLAUW #A8D8EA — dat is een pastel (OKLCH
   C≈0.056) en scripts/apca-lint.mjs houdt elk accent onder C 0.10 tegen, plus
   on-accent haalde er maar Lc 78,7 van de vereiste 80. Exact hetzelfde pad liep
   de klant-app al (app.css :root, COLOR_SYSTEM_RESEARCH §3): ijsblauw als vlak
   leest als waas op bijna-zwart. Dus hetzelfde antwoord hier — de ijsblauwe
   hoek blijven, met echte verzadiging: H 211,8 (merk-ijs is 222,9, het oude
   neon 191,5), C 0.113, Lc on-accent 82,9. Verlaag de vloer niet; wie dit
   verder naar het merk wil duwen heeft een nieuwe merkkleur nodig, geen
   lintregel. */
:root[data-theme="dark"] {
  --bg:        #03040A;
  --surface:   #0F1624;
  --ink:       #F0F2F5;
  --ink-2:     #ACB3C1;
  --muted:     #6B7280;
  --line:      #2A3346;
  --line-2:    #1E2533;
  --accent:    #6FE8FF;
  --accent-2:  #B6F1FF;
  --on-accent: #080C14;
  --ok:        oklch(60% .14 145);
  --danger:    oklch(55% .14 25);
  --warn:      oklch(70% .14 85);
  --ba-side:   oklch(72% .11 295);
  --ink-strong: #F0F2F5;
  --actas-bg:  oklch(70% .14 85);
  --actas-ink: oklch(25% .05 85);
  --macro-p:   oklch(62% .14 270);
  --macro-c:   oklch(65% .14 110);
  --macro-f:   oklch(62% .14 55);
}

* { box-sizing: border-box; }

/* HTML5 [hidden] hard-override. The UA stylesheet defines [hidden]{display:none},
   but any author rule that sets `display:` (e.g. `.client-card { display:flex }`,
   `.claim-row { display:flex }`, etc.) wins on specificity and silently neuters
   `element.hidden = true`. The v0.9.352 client search bar drove this exact bug:
   typing in the search box set `card.hidden = true` on every non-matching card +
   sibling row, but `display:flex` kept them visible, so the filter looked dead.
   Keep this rule above any class that sets `display:`. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
}

/* ───────── boot + gate ───────── */
.boot, .gate {
  min-height: 100vh;
  min-height: 100dvh; /* dvh wins on modern engines, 100vh above stays fallback */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  padding: var(--space-5);
  text-align: center;
}
.boot__mark, .gate__mark {
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: lowercase;
  color: var(--muted);
}
.gate__title { margin: 0; font-size: 1.4rem; }
.gate__msg   { margin: 0; max-width: 28rem; color: var(--ink-2); line-height: 1.5; }

.btn {
  display: inline-block;
  padding: var(--space-3) var(--space-5);
  background: var(--accent);
  color: var(--on-accent);
  text-decoration: none;
  border: 0;
  border-radius: var(--radius);
  font-weight: 600;
  font-size: 1rem;
  cursor: pointer;
}
.btn:active { background: var(--accent-2); }

/* ───────── top bar ───────── */
.topbar {
  position: sticky;
  top: 0;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  z-index: 10;
}
.topbar__back  { color: var(--accent); text-decoration: none; font-size: 0.9rem; font-weight: 600; }
.topbar__title { font-weight: 700; flex: 1; text-align: center; }
.topbar__who   { color: var(--muted); font-size: 0.8rem; max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ───────── page ───────── */
/* Bottom inset reserves room for the fixed coach-nav (≈64px tab + 8px breath
   + safe-area-inset on notched devices). Without this the last list item /
   form button sits under the nav. */
.page {
  max-width: 40rem;
  margin: 0 auto;
  padding: var(--space-4) var(--space-4) calc(72px + var(--safe-bottom));
}

/* Plan tab uses a wider canvas — desktop multi-column grid lives here. */
.page--wide {
  max-width: 80rem;
}
.page__empty, .page__note {
  color: var(--muted);
  font-size: 0.85rem;
  text-align: center;
  padding: var(--space-4) 0;
}

/* Section divider — same language as the app's group headers. */
.section-divider {
  display: flex;
  align-items: center;
  margin: var(--space-5) 0 var(--space-3);
}
.section-divider::before,
.section-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}
.section-divider__label {
  padding: 0 var(--space-3);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ───────── client search (v0.9.352 micro-fix G) ─────────
   Top-of-page filter for the client list. Pure client-side; hidden when
   clients.length < 2 or in duo-picker mode. SVG glass icon left, native
   <input type="search"> middle, SVG clear-X right (visible only while the
   input has content). Tokens are space-separated case-insensitive substring
   matches against display_name + email (see applyClientFilter in coach.js). */
.client-search {
  position: relative;
  display: flex;
  align-items: center;
  margin: 0 0 var(--space-3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0 var(--space-3);
}
.client-search:focus-within { border-color: var(--accent); }
.client-search__icon {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  margin-right: var(--space-2);
  color: var(--muted);
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
}
.client-search__input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: none;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 1rem;
  padding: 10px 0;
  -webkit-appearance: none;
  appearance: none;
}
.client-search__input::placeholder { color: var(--muted); }
.client-search__input::-webkit-search-cancel-button { display: none; }
.client-search__clear {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 50%;
  background: var(--line);
  cursor: pointer;
  padding: 0;
}
.client-search__clear .fz-icon {
  width: 12px;
  height: 12px;
  color: var(--ink);
}
.client-search__nohit {
  margin: var(--space-3) 0 0;
  color: var(--muted);
  font-size: 0.9rem;
  text-align: center;
}

/* ───────── client cards (clients-as-groups) ───────── */
.client-list { display: flex; flex-direction: column; gap: var(--space-2); }
.client-card {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: transform 0.12s ease, border-color 0.12s ease;
}
.client-card:active { border-color: var(--accent); }
.client-card--poke  { transform: scale(0.98); border-color: var(--accent); }

.client-card__dot {
  flex: 0 0 auto;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--muted);
}
.client-card__dot--active { background: var(--ok); }
.client-card__dot--idle   { background: var(--muted); }

.client-card__main { flex: 1; min-width: 0; }
.client-card__name { font-weight: 600; }
.client-card__meta { color: var(--muted); font-size: 0.8rem; margin-top: 2px; }
.client-card__chev { color: var(--muted); font-size: 1.4rem; line-height: 1; }

/* ───────── Track D — duo picker ───────── */
.duo-toggle {
  margin-left: auto;
  padding: 6px 14px;
  border: 1px solid var(--accent);
  border-radius: 999px;
  background: transparent;
  color: var(--accent);
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
}
.duo-toggle--on { background: var(--accent); color: var(--on-accent); }
.duo-toggle:active { background: var(--accent-2); color: var(--on-accent); border-color: var(--accent-2); }

.client-card--sel { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent), 0 0 12px -2px var(--accent-2); }

.client-card__pick {
  flex: 0 0 auto;
  width: 22px; height: 22px;
  border-radius: 50%;
  border: 2px solid var(--line);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 0.8rem; font-weight: 700; color: transparent;
}
.client-card__pick--on { border-color: var(--accent); background: var(--accent); color: var(--on-accent); }

/* ───────── add client (coach-direct onboarding, v0.9.155) ───────── */
/* Pill in the section divider, same language as .duo-toggle. */
.add-toggle {
  margin-left: auto;
  padding: 6px 14px;
  border: 1px solid var(--accent);
  border-radius: 999px;
  background: transparent;
  color: var(--accent);
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
}
.add-toggle--on { background: var(--accent); color: var(--on-accent); }
.add-toggle:active { background: var(--accent-2); color: var(--on-accent); border-color: var(--accent-2); }
/* When both pills show, keep them grouped on the right (override the auto). */
.add-toggle + .duo-toggle { margin-left: var(--space-2); }

/* Inline new-client form. */
.add-client {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4);
  margin-bottom: var(--space-3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.add-client__label {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}
.add-client__input {
  padding: var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--ink);
  font: inherit;
  font-size: 1rem;
}
.add-client__input:focus { outline: none; border-color: var(--accent); }
.add-client__err {
  margin: 0;
  color: var(--danger);
  font-size: 0.85rem;
}
.add-client__actions {
  display: flex;
  gap: var(--space-2);
  margin-top: var(--space-2);
}
.add-client__cancel {
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--ink-2);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.add-client__submit {
  margin-left: auto;
  padding: var(--space-3) var(--space-5);
  border: 0;
  border-radius: 999px;
  background: var(--accent);
  color: var(--on-accent);
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}
.add-client__submit:disabled { background: var(--muted); opacity: 0.6; cursor: default; }
.add-client__submit:not(:disabled):active { background: var(--accent-2); }

/* ───────── managed-client claim link (v0.9.157) ───────── */
.claim-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: -2px 0 var(--space-2);
  padding: 0 var(--space-2);
}
.claim-row__get {
  background: none;
  border: 0;
  padding: 4px 2px;
  color: var(--accent);
  font: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
  text-align: left;
}
.claim-row__get:disabled { color: var(--muted); cursor: default; }
.claim-row__url {
  flex: 1;
  min-width: 0;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--ink-2);
  font: inherit;
  font-size: 0.8rem;
}
.claim-row__copy {
  flex-shrink: 0;
  padding: var(--space-2) var(--space-3);
  border: 0;
  border-radius: var(--radius);
  background: var(--accent);
  color: var(--on-accent);
  font: inherit;
  font-weight: 600;
  font-size: 0.82rem;
  cursor: pointer;
}

/* The per-client Strength-view pills that used to live here (v0.9.340,
   today | sheet) were removed with COACH-KAN-GYM-WEERGAVE-WEER-OMZETTEN: the
   client-card sibling row had no producer left in coach.js. The live control is
   gymViewSection() in the Manage card — see .gymview__* further down. */

/* ───────── cardio-row (v0.9.382 — CARDIO-TRAINER-ASSIGN-AND-VIEW)
   Sibling row under each client card with two link affordances:
   Assign → cardio-assign.html; Dashboard → cardio-client-view.html. */
.cardio-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin: -2px 0 var(--space-3);
  padding: 0 var(--space-2);
}
.cardio-row__lbl {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--muted);
  letter-spacing: 0.01em;
}
.cardio-row__group {
  display: inline-flex;
  gap: 6px;
}
.cardio-row__link {
  display: inline-block;
  padding: 4px 12px;
  font-size: 0.78rem;
  font-weight: 600;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink-2);
  text-decoration: none;
  line-height: 1.6;
}
.cardio-row__link--primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}

/* ───────── remove-client affordance (v0.9.341) ─────────
   Sibling row under each managed-client card. Idle state is intentionally
   quiet (muted text-button) so the destructive action doesn't dominate the
   list. Two-tap confirm: the armed state goes red + reads "Tap again to
   remove <name>" to make the consequence explicit before the second tap. */
.delete-row {
  display: flex;
  align-items: center;
  margin: -2px 0 var(--space-3);
  padding: 0 var(--space-2);
}
.delete-row__btn {
  background: none;
  border: 0;
  padding: 4px 2px;
  color: var(--muted);
  font: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  text-align: left;
}
.delete-row__btn--armed {
  color: var(--danger);
}
.delete-row__btn:disabled { color: var(--muted); cursor: default; }

/* ───────── direct sign-in (v0.9.156) ───────── */
.auth-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  width: 100%;
  max-width: 20rem;
}
.auth-form .btn { width: 100%; text-align: center; }
.auth-form .btn:disabled { background: var(--muted); opacity: 0.6; cursor: default; }
.auth-err {
  margin: 0;
  width: 100%;
  max-width: 20rem;
  color: var(--danger);
  font-size: 0.9rem;
  text-align: left;
}
.auth-google {
  width: 100%;
  max-width: 20rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
}
.auth-divider {
  display: flex;
  align-items: center;
  width: 100%;
  color: var(--muted);
  font-size: 0.85rem;
  text-transform: lowercase;
}
.auth-divider::before,
.auth-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
  margin: 0 var(--space-3);
}
.auth-google__btn { color-scheme: light; }
.auth-foot { margin: 0; }
.auth-link {
  color: var(--accent);
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 600;
}

/* Empty-state primary CTA + just-created highlight. */
.page__empty-wrap { display: flex; flex-direction: column; align-items: center; gap: var(--space-3); }
.add-first {
  padding: var(--space-3) var(--space-5);
  border: 0;
  border-radius: 999px;
  background: var(--accent);
  color: var(--on-accent);
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}
.add-first:active { background: var(--accent-2); }

.client-card--new {
  border-color: var(--ok);
  box-shadow: inset 0 0 0 1px var(--ok);
  animation: client-card-new-fade 2.2s ease;
}
@keyframes client-card-new-fade {
  0%   { background: rgba(0, 200, 83, 0.14); }
  100% { background: var(--surface); }
}

/* ───────── intake questionnaire (COACH-INTAKE-QUESTIONNAIRE) ───────── */
/* Pill in the section divider next to the + Add client pill. Same shape, */
/* filled by default so the takeover affordance reads as primary action. */
.intake-toggle {
  margin-left: var(--space-2);
  padding: 6px 14px;
  border: 1px solid var(--accent);
  border-radius: 999px;
  background: var(--accent);
  color: var(--on-accent);
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
}
.intake-toggle:active { background: var(--accent-2); border-color: var(--accent-2); }

/* The page itself is a single-column phone-shaped flow. */
/* DOSSIER-VLOEIENDE-RUIMTE (bevinding #10) — `width: 100%` is hier geen
   sierregel maar de fix. In een flex-kolom (`.dsec__sheetbody`) zet
   `margin-inline: auto` de `align-self: stretch` UIT, en dan krimpt dit blok
   naar zijn eigen inhoud (fit-content). Gemeten 2026-10-13 in het intakevel op
   375/390/402/430px: bij een klant ZONDER bijgehouden maten en met een korte
   naam werd het 273px breed in een vel van 358px — 42px dode ruimte per kant,
   bovenop de padding van het vel. Bij een klant MET meetkaarten en een lange
   naam liep datzelfde blok juist tot de volle 358px. De breedte van het
   formulier hing dus af van hoeveel de klant had ingevuld, en dat is erger dan
   te smal: het is elke keer anders. `width: 100%` maakt hem altijd zo breed als
   zijn vel; `max-width: 520px` blijft en begrenst hem nog steeds op een laptop. */
.intake {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  width: 100%;
  max-width: 520px;
  margin: 0 auto;
}
.intake__headline {
  margin: var(--space-4) 0 0;
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--ink);
  letter-spacing: -0.01em;
}
.intake__sub {
  margin: 0;
  color: var(--muted);
  font-size: 0.95rem;
}
.intake__progress {
  height: 6px;
  border-radius: 999px;
  background: var(--line);
  overflow: hidden;
}
.intake__progress-fill {
  height: 100%;
  background: var(--accent);
  transition: width 180ms ease-out;
}
.intake__step-meta {
  margin: 0;
  color: var(--muted);
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.intake__card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.intake__step-title {
  margin: 0 0 var(--space-2);
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--ink);
}
.intake__field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.intake__lbl {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}
.intake__optional {
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  color: var(--muted);
}
.intake__hint {
  margin: 0 0 var(--space-1);
  font-size: 0.8rem;
  color: var(--muted);
}
.intake__input,
.intake__textarea {
  padding: var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--ink);
  font: inherit;
  font-size: 1rem;
  width: 100%;
  box-sizing: border-box;
}
.intake__textarea { resize: vertical; min-height: 96px; }
.intake__input:focus,
.intake__textarea:focus { outline: none; border-color: var(--accent); }
.intake__radio-group {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.intake__pill {
  padding: 8px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}
.intake__pill--on {
  background: var(--accent);
  color: var(--on-accent);
  border-color: var(--accent);
}
.intake__pill:active { background: var(--accent-2); color: var(--on-accent); border-color: var(--accent-2); }
.intake__err {
  margin: 0;
  padding: var(--space-3);
  background: rgba(211, 47, 47, 0.08);
  border: 1px solid color-mix(in oklab, var(--danger) 40%, transparent);
  border-radius: var(--radius);
  color: var(--danger);
  font-size: 0.9rem;
}
.intake__nav {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding-bottom: calc(var(--space-4) + env(safe-area-inset-bottom, 0px));
}
.intake__back,
.intake__cancel {
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--ink-2);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.intake__next {
  margin-left: auto;
  padding: var(--space-3) var(--space-5);
  border: 0;
  border-radius: 999px;
  background: var(--accent);
  color: var(--on-accent);
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}
.intake__next:disabled { background: var(--muted); opacity: 0.6; cursor: default; }
.intake__next:not(:disabled):active { background: var(--accent-2); }

/* Review screen — two-column key/value pairs. */
.intake__review {
  display: grid;
  grid-template-columns: minmax(120px, max-content) 1fr;
  gap: var(--space-2) var(--space-3);
  margin: 0;
}
.intake__review-key {
  margin: 0;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  align-self: center;
}
.intake__review-val {
  margin: 0;
  font-size: 0.95rem;
  color: var(--ink);
  word-break: break-word;
}
.intake__review-foot {
  margin: var(--space-3) 0 0;
  color: var(--muted);
  font-size: 0.85rem;
}

/* ───────── bottom navigation (COACH-BOTTOM-NAV-SHELL v0.9.607) ─────────
   Four-tab launcher mirroring the main app's pattern. Fixed at the screen
   bottom with safe-area-inset padding so it clears the iPhone home-indicator.
   Active tab uses --accent + --on-accent per UI invariant (no hardcoded
   white on accent — kaizen feedback_accent_buttons_on_accent_token). */
.coachnav {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: stretch;
  background: var(--surface);
  border-top: 1px solid var(--line);
  padding-bottom: var(--safe-bottom);
  z-index: 20;
}
/* GYM-HET-DOSSIER-HOUDT-DE-COACHBALK-ALLEEN-DE-SPELER-IS-VOLSCHERM (L225) —
   syncCoachBar() zet het hidden-attribuut; `display: flex` hierboven verslaat
   de UA-regel voor [hidden], dus die moet hier expliciet terug. */
.coachnav[hidden] { display: none; }
.coachnav__tab {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 8px 4px;
  background: transparent;
  border: 0;
  color: var(--muted);
  font: inherit;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
}
.coachnav__tab:active { background: var(--line-2); }
.coachnav__icon {
  width: 24px;
  height: 24px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.coachnav__label {
  line-height: 1.1;
}
/* NOTIFICATIONS-BELL-LIVE-UPDATE — work-list count on the Review tab. The tab is
   a flex COLUMN, so the badge is positioned rather than appended in flow. */
.coachnav__tab--review { position: relative; }
.coachnav__badge {
  position: absolute;
  top: 4px;
  left: 50%;
  margin-left: 4px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--danger, #d33);
  color: #fff;
  font-size: 0.62rem;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
  pointer-events: none;
}
.coachnav__tab--on {
  color: var(--accent);
}
.coachnav__tab--on .coachnav__icon { stroke: currentColor; }

/* Larger viewports — give each tab cell more room for the label. */
@media (min-width: 1024px) {
  .coachnav__tab { font-size: 0.78rem; padding: 10px 4px; }
  .coachnav__icon { width: 26px; height: 26px; }
}

/* ───────── tab page chrome ─────────
   Shared header for the Plan / Work / Settings tabs (Clients keeps its own
   layout from the original landing). Compact but readable so the four-tab
   surface still feels like four real screens, not just one with chrome. */
.tab-page__title {
  margin: var(--space-2) 0 var(--space-1);
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--ink);
  letter-spacing: -0.01em;
}
.tab-page__sub {
  margin: 0 0 var(--space-3);
  color: var(--ink-2);
  font-size: 0.9rem;
  line-height: 1.4;
}

/* ───────── Plan tab — wide client grid ─────────
   Auto-fill grid scales from one column on phone to many on desktop without
   a JS resize listener. plan-card is a flex row that mirrors client-card
   visually so the grid still feels like the Sassu client surface. */
.plan-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: var(--space-3);
}
.plan-card {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: transform 0.12s ease, border-color 0.12s ease;
}
.plan-card:active { border-color: var(--accent); }
.plan-card__open {
  flex: 0 0 auto;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 0.78rem;
  font-weight: 700;
}

/* ───────── Work tab — duo launcher ─────────
   A single prominent button that flips the Clients tab into duoMode and
   routes there, reusing the existing two-pick → /duo.html flow instead of
   duplicating it on the Work tab. Solo training is the list below — same
   client-card pattern as the Clients tab. */
.work-duo-launcher {
  display: block;
  width: 100%;
  padding: var(--space-4);
  margin: 0 0 var(--space-2);
  background: var(--accent);
  color: var(--on-accent);
  border: 0;
  border-radius: var(--radius);
  font: inherit;
  font-size: 1rem;
  font-weight: 700;
  text-align: center;
  cursor: pointer;
}
.work-duo-launcher:active { background: var(--accent-2); }

/* ───────── Settings tab ─────────
   Sectioned form. Each section gets its own card-ish container so the
   visual rhythm reads as "list of preferences" rather than one long form. */
.settings-section {
  margin: var(--space-4) 0 var(--space-5);
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.settings-section__title {
  margin: 0 0 var(--space-3);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.settings-row {
  display: flex;
  gap: var(--space-2);
  align-items: center;
}
.settings-row__hint {
  display: block;
  margin-top: var(--space-2);
  color: var(--muted);
  font-size: 0.78rem;
}
.settings-section--placeholder { opacity: 0.85; }
.settings-placeholder {
  margin: 0;
  color: var(--ink-2);
  font-size: 0.9rem;
  line-height: 1.45;
}

.theme-group {
  display: inline-flex;
  border: 1px solid var(--line);
  border-radius: 999px;
  overflow: hidden;
  background: var(--bg);
}
.theme-pill {
  border: 0;
  background: transparent;
  padding: 8px 18px;
  font: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--ink-2);
  cursor: pointer;
}
.theme-pill + .theme-pill { border-left: 1px solid var(--line); }
.theme-pill--on {
  background: var(--accent);
  color: var(--on-accent);
}
.theme-pill:active { background: var(--accent-2); color: var(--on-accent); }

/* COACH-ICON-WIRE-FROM-WAVE-1-ASSETS (v0.9.708) — port of the app-side .fz-icon
   primitive. The brand line-art webp is rendered as a CSS mask filled with
   currentColor, so the icon inherits the parent text colour (--muted in the
   search bar, --ink on a clear button, --accent on the active nav tab) and
   recolours automatically with the theme finish — no per-surface tint overrides.
   The bottom-nav glyphs bump to 28px to match the app-side ICON-NAV-BIGGER ship. */
.fz-icon {
  display: inline-block;
  width: 24px;
  height: 24px;
  background: currentColor;
  -webkit-mask: var(--icon-url) center / contain no-repeat;
          mask: var(--icon-url) center / contain no-repeat;
  vertical-align: middle;
  flex: 0 0 auto;
}
.coachnav__tab .fz-icon { width: 28px; height: 28px; }

/* ════════════════════════════════════════════════════════════════════════
   COACH-PLATFORM-SPRINT-1-FOUNDATION-SHELL (coach-0.9.200)
   Foundation shell: sticky searchbar + hamburger drawer + responsive
   3-panel dossier. Layout only — panel content lands in later sprints.
   ════════════════════════════════════════════════════════════════════════ */

/* ── sticky shell header (hamburger + searchbar) ── */
.cshell {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: calc(env(safe-area-inset-top, 0px) + var(--space-2)) var(--space-3) var(--space-2);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
/* ── searchbar ── */
.csearch { position: relative; flex: 1 1 auto; min-width: 0; }
.csearch__bar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  height: 40px;
  padding: 0 var(--space-2) 0 var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
}
.csearch--open .csearch__bar { border-color: var(--accent); }
.csearch__glass { flex: 0 0 auto; display: flex; color: var(--muted); }
.csearch__input {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  background: transparent;
  font: inherit;
  font-size: 15px;
  color: var(--ink);
  outline: none;
}
.csearch__input::placeholder { color: var(--muted); }
.csearch__lib {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink-2);
  cursor: pointer;
}
.csearch__lib:active { background: var(--line-2); }

.csearch__panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 60;
  max-height: 60vh;
  overflow-y: auto;
  padding: var(--space-2);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.csearch__heading {
  padding: var(--space-1) var(--space-2);
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.csearch__empty { padding: var(--space-3) var(--space-2); color: var(--muted); font-size: 14px; }
.csearch__row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-2);
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  font: inherit;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
}
.csearch__row:hover { background: var(--line-2); }
.csearch__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); flex: 0 0 auto; }
.csearch__dot--active { background: var(--ok); }
.csearch__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* COACH-IA-5-EEN-NAVIGATIEMODEL — the hamburger drawer and its burger
   button are removed: the six-tab bar is the one navigation model. */

/* ── page scaffold ── */
.cmain { padding: var(--space-4) var(--gutter) calc(var(--space-6) + var(--safe-bottom)); }
/* COACH-IA-5-EEN-NAVIGATIEMODEL — standalone coach.sassu.fit draws its own
   six-tab bar (in the app embed the host draws it, and this class is absent).
   The fixed bar would otherwise cover the last card on every page. */
/* COACH-GYM-TOETSENBORD-DUWT-NIETS-WEG — --coach-navh is de ECHT gemeten
   balkhoogte (measureCoachNav in coach.js), niet de 64 die op een iPad te laag
   is. Eén bron van waarheid voor alle drie de plekken die deze balk aftrekken. */
body.has-coachnav .cmain { padding-bottom: calc(var(--space-6) + var(--safe-bottom) + var(--coach-navh, 64px)); }
.cpage-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); row-gap: var(--space-2); margin-bottom: var(--space-4); }
.cpage-head__title { margin: 0; min-width: 0; font-size: 22px; font-weight: 700; color: var(--ink); }
/* COACH-KLANTEN-HEAD-RESPONSIVE-WRAP — Klanten-kop: titel op eigen regel, drie knoppen eronder. */
@media (max-width: 560px) {
  .cpage-head--stack .cpage-head__title { flex-basis: 100%; }
  .cpage-head--stack .cpage-head__action { flex: 1 1 auto; margin-left: 0; }
  /* COACH-CLEANUP-1 — the kebab keeps its square footprint; only the primary
     action grows to fill the row. */
  .cpage-head--stack .cpage-head__action--icon { flex: 0 0 auto; }
}
/* EEN-DOSSIERKOP-DIE-ZEGT-MET-WIE-JE-BEZIG-BENT — Jayy vroeg het kebabmenu
   RECHTSBOVEN. Als ghost droeg het margin-left:0, dus het plakte tegen de naam
   aan; op de dossierkop duwt het zichzelf naar de rand. */
.cpage-head--dossier .cpage-head__action--ghost { margin-left: auto; }

/* DOSSIER-KOP-ZEGT-HOE-HET-GAAT — de toestandsregel onder de naam. Stripe's
   klantdetail opent met naam + status + twee kerngetallen; hier is dat doel ·
   week · laatst actief, zodat de coach weet hoe het staat VOORDAT hij een tab
   kiest. Een eigen regel (flex-basis 100% in de al wrappende kop), niet naast
   de naam: naast een titel wordt zo'n zin een prop die op 375px de naam
   wegdrukt. Rustige tint, 13px — het is context, geen actie.

   De scheidingspunt staat in CSS en niet in de tekst, want de drie delen
   landen op verschillende momenten (laatst actief meteen, doel en week na hun
   antwoord): een punt die bij de TEKST hoort zou bij een ontbrekend deel als
   los teken blijven staan. `~` en niet `+`, want tussen twee zichtbare delen
   kan een verborgen deel staan. */
.cpage-head--dossier { row-gap: var(--space-1); }
.dhead-state {
  flex: 0 0 100%;
  min-width: 0;
  margin: 0;
  display: flex;
  /* ÉÉN regel, altijd — en niet omdat het mooier staat. De twee dossierkoppen
     (fitness en zaken) moeten even hoog blijven, anders springt alles eronder
     als de coach tussen de twee wisselt; dat is de belofte die
     coach-dossierkop-acties-achter-menu.spec.js bewaakt. Een regel die bij een
     lang doel naar twee regels wrapt, breekt die pariteit op precies de dagen
     dat een klant een uitgebreid doel heeft opgeschreven. Dus: geen wrap, en
     wat niet past krijgt een ellips. */
  flex-wrap: nowrap;
  align-items: baseline;
  gap: 0 var(--space-2);
  overflow: hidden;
  white-space: nowrap;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.35;
}
.dhead-state[hidden] { display: none; }
.dhead-state__part {
  min-width: 0;
  flex: 0 0 auto;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dhead-state__part:not([hidden]) ~ .dhead-state__part:not([hidden])::before {
  content: '·';
  margin-right: var(--space-2);
  color: var(--line);
}
/* Het doel is het ENE ding dat deze klant wil; dat mag donkerder staan dan de
   twee feiten erachter. Geen accentkleur — één accent per scherm (§3.5 van de
   audit), en dat is de actieve tab. */
/* Het doel is het ENE ding dat de coach als eerste leest en het enige deel dat
   zo lang kan worden dat het de andere twee opeet. Daarom is dit het enige deel
   dat mag krimpen, en nooit verder dan de helft van de regel. */
.dhead-state__part--goal { flex: 0 1 auto; max-width: 50%; color: var(--ink-2); }
.dhead-state__part--week { font-variant-numeric: tabular-nums; }
/* LEAD-STUUR-BETAALLINK-VANUIT-HET-DOSSIER — de knop naast het lead-etiket.
   Een chip met een rand en geen accentvlak: één accent per scherm, en dat is de
   actieve tab (§3.5 van de audit). flex:0 0 auto plus order op de standaard, dus
   hij krimpt niet mee en wat er ACHTER staat ("laatst actief") wordt als eerste
   afgekapt — precies de bedoelde voorrang.

   align-self:center omdat de regel op `baseline` staat: een knop met een icoon
   erin zou dan op zijn tekstbasislijn hangen en één pixel hoger dan het etiket
   ernaast gaan staan. Geen extra regelhoogte: 20px past binnen de 13px/1.35 van
   de regel plus zijn rand, zodat de twee dossierkoppen even hoog blijven. */
.dhead-paylink {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 4px;
  align-self: center;
  min-height: 20px;
  padding: 1px 8px;
  border: 1px solid var(--line-2); border-radius: 999px;
  background: transparent; color: var(--ink-2);
  font: inherit; font-size: 11px; font-weight: 600;
  white-space: nowrap; cursor: pointer;
}
.dhead-paylink svg { flex: 0 0 auto; }
.dhead-paylink:active { background: var(--surface-2); }
/* Spelerstand: de kop gaat op `flex-wrap: nowrap` (zie .gym-player-open
   hieronder), en een regel met `flex-basis: 100%` knijpt de naam daar tot nul.
   Hij hoort er sowieso niet: met het schema open is het scherm van de set die
   je logt, dezelfde reden waarom de notitiekaart daar al verdwijnt. */
.gym-player-open .cpage-head--dossier .dhead-state { display: none; }
.cpage-head__back {
  width: 36px; height: 36px; flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); cursor: pointer;
}

/* COACH-HET-HELE-DAGRITME-VAN-JE-KLANT-OP-EEN-PAGINA — de kop boven het iframe.
   Hij staat in een kolom (terug · naam · ondertitel) in plaats van de rij die
   .cpage-head normaal is: de terugweg noemt hier een BESTEMMING en niet alleen
   een richting, en zo'n regel naast een titel maakt van twee zinnen één prop. */
.cpage-head--dcp { flex-direction: column; align-items: stretch; gap: var(--space-2); margin-bottom: var(--space-3); }
.cdcp__back {
  align-self: flex-start;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 10px 6px 6px;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--muted);
  font: inherit; font-size: 13px; cursor: pointer;
}
.cdcp__titles { min-width: 0; }
.cdcp__idrow { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
.cdcp__avatar {
  flex: 0 0 auto;
  width: 32px; height: 32px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--line-2); color: var(--ink);
  font-size: 14px; font-weight: 700;
}
.cdcp__sub { margin: 4px 0 0; font-size: 13px; line-height: 1.4; color: var(--muted); }

/* De volle-hoogte-keten, op ELKE breedte (dit is geen kaart die meescrolt — het
   is de editor, en die heeft de hoogte nodig die er is). Zelfde stelsel als de
   gym-speler hieronder: geen tweede hoogte-berekening, dezelfde --coach-vh die
   measureCoachNav op één plek meet. :has(.cdcp) houdt hem op deze pagina, en
   ruimt zichzelf op zodra het scherm wisselt — geen klasse om te vergeten.
   min-height:0 op ELKE schakel, anders kan het iframe niet krimpen en duwt het
   zijn onderrand uit het venster. */
html:has(.cdcp),
html:has(.cdcp) body { height: 100%; overflow: hidden; overscroll-behavior: none; }
html:has(.cdcp) #coach {
  display: flex; flex-direction: column; min-height: 0;
  height: 100vh;                 /* fallback, moet BOVEN de dvh-regel blijven */
  height: var(--coach-vh, 100dvh);
}
html:has(.cdcp) body.has-coachnav #coach { padding-bottom: calc(var(--coach-navh, 64px) + var(--safe-bottom)); }
html:has(.cdcp) .cshell { flex: 0 0 auto; }
html:has(.cdcp) .cmain,
html:has(.cdcp) body.has-coachnav .cmain {
  flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column;
  /* Nul, niet 'klein': #coach reserveert de balk hierboven al één keer. */
  padding-bottom: 0;
}
html:has(.cdcp) .cmain > *:not(.cdcp) { flex: 0 0 auto; }
.cdcp { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
/* Het iframe scrolt ZELF van binnen: één scrollgebied, nooit twee over elkaar. */
.cdcp__frame { flex: 1 1 auto; width: 100%; min-height: 0; border: 0; display: block; }

/* ── placeholder card ── */
.cplaceholder {
  padding: var(--space-6) var(--space-4);
  background: var(--bg);
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  text-align: center;
}
.cplaceholder__title { margin: 0 0 var(--space-2); font-size: 18px; color: var(--ink); }
.cplaceholder__copy { margin: 0; color: var(--muted); font-size: 14px; }

/* ── EEN-VERSE-COLLEGA-ZIET-EEN-BEGIN — first-run card for a coach with zero
      clients. Solid, not dashed: this is a real starting point, not a stub. ── */
.cstart {
  padding: var(--space-5) var(--space-4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.cstart__title { margin: 0 0 var(--space-2); font-size: 18px; color: var(--ink); }
.cstart__copy { margin: 0 0 var(--space-4); color: var(--muted); font-size: 14px; line-height: 1.5; }
.cstart__actions { display: flex; flex-direction: column; gap: var(--space-2); }
.cstart__btn {
  padding: var(--space-3);
  border: 1px solid var(--accent); border-radius: var(--radius);
  background: var(--accent); color: var(--on-accent);
  font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
}
.cstart__btn--ghost {
  border-color: var(--line); background: var(--bg); color: var(--ink); font-weight: 500;
}

/* ── SAMENWERKING-EEN-VOORSTEL-STAAT-OP-DE-KLANTEN-TAB ──────────────────────
   Het voorstel van een collega bovenaan de Klanten-tab. Zelfde doos als .cstart
   maar met een accentrand: het is het enige op dit scherm dat op een akkoord
   van hem wacht. Nul voorstellen = een lege gastheer zonder eigen marge. */
.cpart-invites {
  display: flex; flex-direction: column; gap: var(--space-2);
  margin: var(--space-3) 0;
}
/* NA de basisregel, nooit ervoor: bij gelijke specificiteit wint de LAATSTE,
   en een display:none die eerst staat verliest van zijn eigen display:flex. */
.cpart-invites:empty { display: none; }
.cpart-invite {
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
}
.cpart-invite__head { display: flex; align-items: center; gap: var(--space-2); }
.cpart-invite__head svg { color: var(--accent); flex: 0 0 auto; }
.cpart-invite__title { margin: 0; font-size: 17px; color: var(--ink); }
.cpart-invite__copy {
  margin: var(--space-2) 0 0; color: var(--muted); font-size: 14px; line-height: 1.5;
}
.cpart-invite__label { margin: var(--space-1) 0 0; color: var(--ink); font-size: 14px; font-weight: 600; }
.cpart-invite__actions { display: flex; gap: var(--space-2); margin-top: var(--space-3); }
.cpart-invite__btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  flex: 1 1 0; padding: var(--space-3);
  border: 1px solid var(--accent); border-radius: var(--radius);
  background: var(--accent); color: var(--on-accent);
  font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
}
.cpart-invite__btn[disabled] { opacity: .6; cursor: default; }
.cpart-invite__btn--ghost {
  border-color: var(--line); background: var(--bg); color: var(--ink); font-weight: 500;
}
.cpart-invite__more {
  margin-top: var(--space-2); padding: 0;
  border: 0; background: none; font: inherit; font-size: 14px;
  color: var(--accent); cursor: pointer; text-decoration: underline; text-underline-offset: 3px;
}

/* KLANTEN-LAATST-GEZIEN-EN-SORTEREN — de sorteerknop onder de segmentbalk. Geen
   volvlak-accent: hij staat NAAST de navigatie en is geen hoofdactie, dus hij
   volgt het chip-recept uit .ctoday__seg-btn.is-on — een 16%-tint tegen
   --surface. display:flex + width:fit-content en NIET inline-flex: .cmain is een
   blok en de segmentbalk erboven is inline-flex, dus een inline-flex knop zou
   naast de segmentbalk op dezelfde regel plakken in plaats van eronder. */
.clib-sort {
  display: flex; width: fit-content; align-items: center; gap: 6px;
  margin-top: var(--space-2);
  padding: 6px var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink-2);
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.clib-sort[aria-pressed="true"] {
  background: color-mix(in srgb, var(--accent) 16%, var(--surface));
  color: var(--accent); border-color: var(--accent);
}

/* CONNECTOR-TOESTEMMING-EEN-BRON-EN-VRAAG-HET-AL-JE-KLANTEN — de strook boven de
   klantenlijst: één knop plus de teller eronder. Zelfde chip-recept als
   .clib-sort hierboven, en met opzet GEEN volvlak-accentknop: hij staat boven de
   lijst en concurreert daar met '+ Klant toevoegen' en de sorteerknop, en drie
   hoofdacties naast elkaar heeft geen hoofdactie meer. display:flex met
   width:fit-content om dezelfde reden als .clib-sort: .cmain is een blok, dus
   inline-flex zou de knop naast het element erboven plakken. */
.clib-consent { margin-top: var(--space-3); }
/* Zolang de teller nog niet binnen is — en als het antwoord geen stand bevat —
   is de strook leeg. Leeg is niet maatloos: zijn margin-top houdt dan een gat
   van 12px open boven de lijst dat niets verklaart, en dat gat verspringt zodra
   de knop alsnog landt. display:none nuleert ook de marge. */
.clib-consent:empty { display: none; }
.clib-consent__ask {
  display: flex; width: fit-content; align-items: center; gap: 6px;
  padding: 6px var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink-2);
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.clib-consent__ask[hidden] { display: none; }
.clib-consent__counts {
  margin-top: 6px;
  font-size: 12px; color: var(--muted);
}

/* ── client library list ── */
.clib { display: flex; flex-direction: column; gap: var(--space-2); }
.clib__row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  font: inherit;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
}
.clib__row:active { background: var(--line-2); }
.clib__avatar {
  position: relative;
  width: 40px; height: 40px; flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--accent); color: var(--on-accent);
  font-weight: 700;
}
.clib__mid { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; }
.clib__name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.clib__meta { font-size: 13px; color: var(--muted); }
/* COACH-MODE-KLANTEN-AGGREGAAT-SUMMARY — one compact line of three numbers,
   wrapped onto its own full-width row line (inside .clib__mid it competes with
   the status pill and the Duo button and ellipsises away at 390px). The wrap is
   opt-in per row so the other .clib__row users keep their single-line layout. */
.clib__row--sum { flex-wrap: wrap; row-gap: var(--space-1); }
.clib__metrics {
  flex: 1 0 100%;
  font-size: 12px; color: var(--muted); cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.clib__metrics--warn { color: var(--warn); font-weight: 600; }
/* COACH-NIETS-LOOPT-NOG-BUITEN-ZIJN-VAK (L183 #14) — op een telefoon van 375px
   kapte de klantnaam af tot "T…". Oorzaak: .clib__mid was het ENIGE kind van de
   rij dat kon krimpen (min-width: 0), terwijl de status-pil op `flex: 0 0 auto`
   stond en met een lang label ("nog geen trainingen") zijn volle breedte opeiste.
   De pil geeft nu mee: hij mag krimpen en kort zijn eigen label af. Gemeten op
   375px met drie lange namen en het label "nog geen trainingen": de naam ging
   van 17px ("…") naar 75-86px en de rij werd 32px LAGER (124 → 92), want de pil
   wikkelde eerst over drie regels. Dat de pil nu zelf afkapt is de bedoelde
   ruil — hij herhaalt wat de metaregel eronder al zegt, de naam is waar de coach
   op navigeert.
   Bewust GEEN min-width-ondergrens op .clib__mid en GEEN tweede regel: een
   ondergrens duwde de pil terug naar 17px en liet de Duo-knop op de
   samenvattingsrij (die wrapt) naar een volgende regel vallen, en een tweede
   regel maakt elke klantrij 32px hoger. Allebei herindeling, en die hoort in de
   herontwerpfase KLANTENRIJ-NAAM-EERST-OP-DE-TELEFOON (audit L183 §5.6), niet
   in deze reparatie. */
.clib__pill {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  padding: 2px var(--space-2);
  border-radius: 999px;
  font-size: 12px;
  background: var(--line-2);
  color: var(--ink-2);
}
.clib__pill--active { background: color-mix(in srgb, var(--ok) 18%, transparent); color: var(--ok); }
/* NOTES-UNREAD-WATERMARK-AND-BADGES — unread client-note count badge. */
.clib__unread {
  flex: 0 0 auto;
  min-width: 20px;
  margin-left: var(--space-2);
  padding: 2px var(--space-2);
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  text-align: center;
  background: var(--accent);
  color: var(--on-accent);
}
/* COACH-DUO-PHONE-TABLET-PARITY — per-card duo launcher, shown on ALL shells
   (desktop, iPad, phone — coach/duo.html is mobile-first). 32px hit target is
   touch-friendly. Accent-filled active state uses --on-accent for contrast,
   never hardcoded white. */
.clib__duo {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--space-1);
  min-width: 32px; height: 32px;
  padding: 0 var(--space-2);
  margin-left: var(--space-2);
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink-2);
  cursor: pointer;
}
.clib__duo:hover { border-color: var(--accent); color: var(--accent); }
.clib__duo:active { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.clib__duo:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.clib__duo-lbl { font-size: 12px; font-weight: 600; line-height: 1; color: inherit; }
/* DUO-KOPPEL-IN-KLANTEN-EN-DOSSIER — the linked variant carries a NAME, which at
   390px would push the client's own name out of .clib__mid. Cap it and ellipsise
   rather than let the row reflow. */
.clib__duo--linked .clib__duo-lbl {
  max-width: 20ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* COACH-DOSSIER-MINDER-DEUREN-EN-ONTHOUDT-JE-KEUZE — the act-as pill on the
   client row (.clib__row--act / .clib__actline / .clib__act) is gone: that door
   now lives only in the dossier header. Its styles left with it. */
.duo-pick__row { justify-content: space-between; }
/* DUO-KOPPEL-IN-KLANTEN-EN-DOSSIER — the linked partner's row carries two extras
   between the name and the chevron. The name takes the slack so the marker and
   the unlink action stay pinned to the right edge. */
.duo-pick__row .duo-pick__linked,
.duo-pick__row .duo-pick__unlink { flex: 0 0 auto; }
.duo-pick__row:has(.duo-pick__linked) .ccal-chooser__cname { flex: 1 1 auto; text-align: left; }
.duo-pick__linked {
  display: inline-flex; align-items: center; height: 22px;
  padding: 0 var(--space-2); margin-left: var(--space-2);
  border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid var(--line);
  font-size: 11px; font-weight: 700; line-height: 1; color: var(--ink-2);
}
.duo-pick__unlink {
  display: inline-flex; align-items: center; height: 22px;
  padding: 0 var(--space-2); margin-left: var(--space-2);
  border-radius: 999px; border: 1px solid var(--line);
  background: var(--surface);
  font-size: 11px; font-weight: 600; line-height: 1; color: var(--ink-2);
  cursor: pointer;
}
.duo-pick__unlink:hover { border-color: var(--danger); color: var(--danger); }
.duo-pick__unlink:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ── responsive 3-panel dossier ── */
/* minmax(0, 1fr) everywhere, never a bare 1fr: a bare `1fr` is minmax(AUTO, 1fr),
   so a column whose content has a wide min-content floor (the Client panel's
   intake grid + photo groups) refuses to shrink to its share and grows past the
   other panels. That is the unequal-column-width bug. */
/* DOSSIER-VLOEIENDE-RUIMTE — de ruimte tussen panelen is hetzelfde ritme als de
   ruimte tussen secties binnen een paneel: één token, geen twee bijna-gelijke
   getallen die los van elkaar kunnen gaan drijven. */
.dossier { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--section-gap); position: relative; }
/* DOSSIER-VLOEIENDE-RUIMTE — dit is HET ene kaartniveau van het dossier (de
   vorige fase haalde alles eronder weg), dus het is ook de enige plek waar
   --card-pad hoort te staan. Zet hem nergens anders binnen dit paneel neer:
   dan is hij per definitie opgeteld. */
.dossier__panel {
  min-height: 240px;
  padding: var(--card-pad);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
/* DOSSIER-BLOKKEN-KIJKEN-NAAR-HUN-EIGEN-BREEDTE — de twee vakken waarin
   dossierinhoud woont, en dus de twee breedtes waar die inhoud naar hoort te
   kijken. Het paneel zelf is op een telefoon ~324px breed, op een tablet
   (2 panelen) en op een laptop (3 panelen) ~316-350px — op ALLE DRIE smaller
   dan de helft van de viewport. Elke `@media`-regel voor iets BINNEN dit vak
   meet dus het verkeerde ding; dat was de hele klasse van bevindingen #1-#4
   uit docs/COACH_RESPONSIVE_AUDIT_L183_2026-10-12.md.
   `container-name` is er met opzet: `.nutmeas` is sinds de vorige fase zelf een
   container, en een naamloze `@container` zou daar binnen op de KAART uitkomen
   in plaats van op het vak. Met een naam vraagt een blok altijd het vak dat het
   draagt. Secties die via dossierRow() geparkeerd staan, openen in een vel
   (`.dsec__sheetbody`) — dat is hetzelfde soort vak en draagt daarom dezelfde
   naam, zodat één regel voor beide standen klopt.
   Geen `container-type: size`: dat zou ook de HOOGTE vastzetten, en deze
   panelen groeien met hun inhoud. */
.dossier__panel,
.dsec__sheetbody { container-type: inline-size; container-name: dbox; }
.dossier__panel-title { margin: 0 0 var(--space-2); font-size: 16px; color: var(--ink); }
.dossier__panel-copy { margin: 0; color: var(--muted); font-size: 14px; }

/* CONNECTOR-KLANTNUMMER-BIJNAAM-EN-GEEN-IDENTITEIT — client number + nickname,
   one quiet line under the dossier header. Muted throughout: it is reference
   information, not an action. */
.dossier-ident {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
  color: var(--muted);
  font-size: 13px;
}
.dossier-ident__num { font-variant-numeric: tabular-nums; letter-spacing: 0.04em; }
.dossier-ident__label { color: var(--muted); }
.dossier-ident__value { color: var(--ink); }
.dossier-ident__why { font-style: italic; }
.dossier-ident__input {
  flex: 0 1 220px;
  min-width: 120px;
  padding: 6px var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm, 8px);
  background: var(--surface);
  color: var(--ink);
  font-size: 13px;
}
/* CONNECTOR-KLANT-VINDEN-OP-BIJNAAM — "deze bijnaam verraadt wie het is".
   Hoort ONDER het veld en niet ernaast: hij gaat over wat je net typte, en
   naast het veld leest hij als een tweede label. flex-basis 100% in de al
   wrappende rij doet dat zonder een extra omhulsel. Waarschuwingskleur via
   --warn, dezelfde token als .clib__metrics--warn — een eigen hex zou langs
   het thema heen gaan (en langs css-hex-lint). */
.dossier-ident__warn {
  flex: 0 0 100%;
  color: var(--warn);
}

/* CONNECTOR-COACH-VRAAGT-TOESTEMMING — de stand van de AI-koppeling plus de
   vraagknop, op een EIGEN volle regel onder de bijnaam. Niet ernaast: het gaat
   niet over de bijnaam, en op 320px zou de knop de bijnaam-invoer wegdrukken.
   Geen waarschuwingskleur en geen accent — "uit" is geen fout, het is de
   normale stand tot de klant zelf iets zegt. De knop leent de rustige
   contourvorm die elders in dit dossier staat; tokens, nooit een eigen hex
   (css-hex-lint). */
.dossier-ident__ai {
  flex: 0 0 100%;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  font-style: normal;
}
.dossier-ident__asked { color: var(--muted); }
.dossier-ident__ask {
  padding: 4px var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm, 8px);
  background: var(--surface);
  color: var(--ink);
  font-size: 13px;
  cursor: pointer;
}
.dossier-ident__ask:disabled { opacity: 0.6; cursor: default; }

/* HET-AFGESLOTEN-DOSSIER-LEEST-TERUG-MAAR-SCHRIJFT-NIET — de strook onder de
   identiteitsregel. Bewust GEEN waarschuwingskleur: er is niets mis, er is
   alleen iets afgelopen. Dezelfde rustige toon als de oud-klantengroep in de
   lijst, met een linkerrand zodat hij zich van de cijfers eronder losmaakt
   zonder een kaart te worden. Wrapt op 390px: op smal valt de knop onder de
   zin in plaats van de datum af te knippen. */
.dossier-ended {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  margin-bottom: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-left: 3px solid var(--line);
  border-radius: var(--radius-sm, 8px);
  background: var(--surface-2, var(--surface));
}
.dossier-ended__line {
  display: flex; align-items: center; gap: var(--space-2);
  min-width: 0; flex: 1 1 auto;
  color: var(--muted); font-size: 13px;
}
.dossier-ended__text { color: var(--ink-2, var(--ink)); font-weight: 600; }
.dossier-ended__resume {
  flex: 0 0 auto;
  padding: 7px var(--space-3);
  border: 0;
  border-radius: var(--radius-sm, 8px);
  background: var(--accent);
  color: var(--on-accent);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.dossier-ended__resume:active { background: var(--accent-2); }
.dossier-ended__resume[disabled] { opacity: .6; cursor: default; }

/* LEAD-BETAALD-ZONDER-INTAKE-MELDT-DE-COACH-METEEN — zelfde strook-vorm als
   hierboven (dus geen tweede lay-out om te onderhouden), met een accent-rand
   links in plaats van een grijze: dit is wél iets wat van de coach gevraagd
   wordt. Twee knoppen, dus wrapt hij op 390px netjes onder de zin. */
.dossier-intake { border-left-color: var(--accent); }
.dossier-intake__why { color: var(--muted); }
.dossier-intake__plan {
  flex: 0 0 auto;
  padding: 7px var(--space-3);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm, 8px);
  background: transparent;
  color: var(--ink);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.dossier-intake__plan:active { background: var(--surface-2, var(--surface)); }

/* DOSSIER-INTAKE-AL-GEDAAN-MET-EEN-TIK — de derde knop. Zijn EIGEN regel en
   niet meegehangen aan de selector hierboven: twee buurpoorten pinnen
   `.dossier-intake__plan` op precies één element in de strook, en die mogen niet
   omvallen op een knop die er alleen maar hetzelfde uitziet. Vorm is wel
   identiek — dit is een afsluiting, geen hoofdhandeling. Hij draagt een icoon,
   dus flex voor de uitlijning van vinkje + woord. */
.dossier-intake__done {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px var(--space-3);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm, 8px);
  background: transparent;
  color: var(--ink);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.dossier-intake__done:active { background: var(--surface-2, var(--surface)); }
.dossier-intake__done[disabled] { opacity: .6; cursor: default; }
/* Het blad erachter: Annuleren naast Bevestigen, en de accentknop krijgt de
   ruimte. Op 360px blijven ze naast elkaar — twee woorden passen. */
.dossier-intake__acts {
  display: flex;
  gap: var(--space-2);
  margin-top: var(--space-3);
}
.dossier-intake__acts .acform__submit { flex: 1 1 auto; }

/* LEAD-ANDER-EMAILADRES-KOPPELEN-MET-EEN-TIK — dezelfde strook-vorm en dezelfde
   accent-rand als de intake-strook (er wordt iets van de coach gevraagd), maar
   met DRIE keuzes. Die drie gaan in hun eigen rij: wrappen ze mee in de
   buitenste flex, dan staat op 390px één knop naast de zin en vallen de andere
   twee eronder — drie keuzes die verschillend lijken te wegen terwijl ze dat
   niet doen. De keuzelijst van "Andere lead" klapt eronder open op volle
   breedte, zodat een lange naam niet wordt afgeknipt. */
.dossier-leadmatch { border-left-color: var(--accent); }
.dossier-leadmatch__row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  flex: 1 1 100%;
}
.dossier-leadmatch__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  flex: 1 1 100%;
}
.dossier-leadmatch__pick {
  width: 100%;
  text-align: left;
  padding: 9px var(--space-3);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm, 8px);
  background: var(--surface);
  color: var(--ink);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.dossier-leadmatch__pick:active { background: var(--surface-2, var(--surface)); }
.dossier-leadmatch__pick[disabled] { opacity: .6; cursor: default; }

/* tablet pair-toggle + mobile segmented control — visibility per breakpoint */
.dossier-pair, .dossier-seg { display: none; }
.dossier-pair { gap: var(--space-2); margin-bottom: var(--space-3); }
.dossier-pair__btn, .dossier-seg__btn {
  flex: 1 1 0;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line);
  background: var(--surface);
  font: inherit;
  font-size: 14px;
  color: var(--ink-2);
  cursor: pointer;
}
.dossier-pair__btn { border-radius: var(--radius); }
.dossier-pair__btn--on, .dossier-seg__btn--on {
  background: var(--accent);
  color: var(--on-accent);
  border-color: var(--accent);
}

/* mobile ≤639 → single panel via data-active + bottom segmented control */
@media (max-width: 639px) {
  /* DOSSIER-KOP-ZEGT-HOE-HET-GAAT — één omlijsting om de hele balk en een
     INGESPRONGEN actieve knop, in plaats van drie vakjes met scheidslijnen die
     onder de notitiekaart als een derde horizontale lijn lazen (audit #13). De
     baan houdt zijn rand, de knoppen verliezen de hunne: wat je ziet is één
     ding met een markering erin (Apple's segmented control). De 3px padding is
     de inspringing; de knop neemt de rest. */
  .dossier-seg {
    display: flex;
    gap: 2px;
    position: sticky;
    /* sits flush under the sticky .cshell searchbar (safe-area + 40px bar + 2× pad + border) */
    top: calc(env(safe-area-inset-top, 0px) + 40px + var(--space-2) * 2 + 1px);
    z-index: 5;
    margin-bottom: var(--space-3);
    padding: 3px;
    background: var(--surface);
    border-radius: var(--radius);
    border: 1px solid var(--line);
  }
  .dossier-seg__btn {
    border: 0;
    border-radius: var(--radius);
    background: transparent;
    padding: var(--space-2) var(--space-2);
  }
  /* De `--on`-regel staat BOVEN dit mediablok en heeft dezelfde soortelijkheid,
     dus de transparante achtergrond hierboven won ervan: de actieve knop raakte
     zijn accent kwijt en hield zijn witte letters — onzichtbaar op wit. Hier
     terugzetten, in hetzelfde blok, zodat de twee regels niet meer om de
     volgorde van het bestand kunnen vechten. */
  .dossier-seg__btn--on { background: var(--accent); color: var(--on-accent); }
  .dossier[data-active="client"]    .dossier__panel:not([data-panel="client"]),
  .dossier[data-active="gym"]       .dossier__panel:not([data-panel="gym"]),
  .dossier[data-active="nutrition"] .dossier__panel:not([data-panel="nutrition"]) {
    display: none;
  }
}

/* tablet 640-1023 → 2 panels via data-pair + pair-toggle */
@media (min-width: 640px) and (max-width: 1023px) {
  .dossier-pair { display: flex; }
  /* --dossier-split is the seam position as a percentage of the grid width; the
     first column stops half a gap short of it so the seam lands in the gap's
     centre. Second column takes the remainder — never a second percentage, or a
     rounding drift would leave a sliver. minmax(0,…) for the same min-content
     reason as the base rule. */
  .dossier { grid-template-columns: minmax(0, calc(var(--dossier-split, 50%) - var(--section-gap) / 2)) minmax(0, 1fr); }
  .dossier[data-pair="client-gym"]       .dossier__panel[data-panel="nutrition"] { display: none; }
  .dossier[data-pair="client-nutrition"] .dossier__panel[data-panel="gym"]       { display: none; }
}

/* COACH-GYM-PANEL-SPLIT-GRIP — the dossier's own resizable seam. (Its former
   sibling, the duo split divider, is gone since DUO-DECK-STRIP-FOUNDATION moved
   duo to deck/strip.) Absolutely positioned so it takes no grid track; it rides the
   seam variable its column rule reads. The 1-column mobile stand has no seam, so
   every grip is off there; the tablet stand has one, the wide stand two. */
.dossier__grip {
  display: none;
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--dossier-split, 50%);
  transform: translateX(-50%);
  width: 3px;
  /* above BOTH panels and above the embedded strength iframe, so the hit-test
     for a tap on the seam always resolves to the grip. */
  z-index: 20;
  align-items: center;
  justify-content: center;
  background: var(--accent);
  border: 0;
  padding: 0;
  cursor: col-resize;
  touch-action: none;
}
/* The INVISIBLE widening: the visible seam stays 3px, this overlay makes the
   finger target 45px wide (21 left + 3 + 21 right) per Apple's 44px HIG minimum.
   It carries the pointer events — the thin bar alone is unacquirable on a
   touchscreen. The duo divider solved its overlap with the buttons beside it by
   CLIPPING the overlay (-9px downward, because pane B's zoom/flip buttons sat
   right under it). Here the arithmetic lets us clear it instead, which is
   sturdier than a magic offset — but count the WHOLE chain or it is off by a
   hair: from the seam centre outward it is 1.5px (half the grip) + 21px (reach)
   = 22.5px, minus the 6px half-gap and the panel's 1px border = 15.5px into the
   panel's padding box. The player control row below is inset --space-4 (16px),
   so its buttons start half a pixel past where the overlay stops. 21px rather
   than a rounder 22px is deliberate: 22 per side overlapped the Back button by
   0.5px — the forgotten half-grip — and 45px still clears the HIG minimum. */
.dossier__grip::before {
  content: '';
  position: absolute;
  left: -21px;
  right: -21px;
  top: 0;
  bottom: 0;
}
.dossier__grip-pill {
  width: 5px;
  height: 44px;
  border-radius: 999px;
  background: var(--accent);
  box-shadow: 0 0 0 2px var(--surface);
  pointer-events: none;
}
.dossier__grip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Each grip rides the variable of the seam it moves. Same one-class specificity
   as the base rule above, so these must stay BELOW it. */
/* --split-a/--split-b are inherited from .dossier, so a grip always sits on the
   very same computed seam its columns were laid out against — including the
   gap correction baked into the unset default. */
.dossier__grip--a { left: var(--split-a, 33.3333%); }
.dossier__grip--b { left: var(--split-b, 66.6667%); }
/* Must live AFTER the display:none base rule, not inside the earlier tablet
   media query: equal specificity, so source order decides and an override
   written higher up loses silently. Scoped per modifier, or the tablet stand
   would light up the wide stand's two grips as well. */
@media (min-width: 640px) and (max-width: 1023px) {
  .dossier__grip--pair { display: flex; }
}
@media (min-width: 1024px) {
  .dossier__grip--a, .dossier__grip--b { display: flex; }
}
.dossier--dragging { cursor: col-resize; -webkit-user-select: none; user-select: none; }
.dossier--dragging iframe { pointer-events: none; }

/* desktop ≥1024 → 3 panels side-by-side (pair + active ignored) */
@media (min-width: 1024px) {
  .cmain { max-width: 1200px; margin: 0 auto; }
  /* COACH-DOSSIER-SPLIT-GRIP-WIDE-STAND — two seams, two variables, same idiom
     as the tablet rule above: --dossier-split-a and -b are seam positions as a
     percentage of the grid width, each column stops half a gap short of its
     seam, and the LAST column takes the remainder via 1fr. Never three
     percentages side by side — rounding drift would leave a visible sliver.
     Column two spans seam to seam, so it loses a WHOLE gap, not a half.

     The defaults carry a ∓gap/6 correction and that is not decoration: the two
     gaps have to come out of the three columns, and a seam parked at a flat
     33.3333% would hand the outer columns half a gap each while the middle one
     paid a whole one — a 6px-narrower centre panel at rest, where the rule this
     replaces gave three exactly equal tracks. Equal columns are 100%/3 − 2·gap/3
     wide, which puts the seam centres at 100%/3 − gap/6 and 200%/3 + gap/6.
     Percentages alone cannot express that (the gap is in px), so equal thirds is
     the UNSET state: the JS removes the variable rather than writing a number
     when a seam is reset.

     DOSSIER-VLOEIENDE-RUIMTE — "de gap" hieronder is `var(--section-gap)` en
     dat MOET letterlijk hetzelfde token zijn als de `gap` van `.dossier`
     (coach.css:1544). Deze vier calc()'s zijn geen opmaak maar de omgekeerde
     rekensom van die gap; staat er een ander getal, dan kloppen de kolommen
     niet meer. Toen de gap van `--space-3` naar `--section-gap` ging en deze
     regels nog op `--space-3` stonden, werd het derde paneel op 1440px 16px
     smaller dan de andere twee — groen bij elke lint, rood bij
     tests/visual/desktop/coach-dossier-column-widths.spec.js. Wie de gap
     verzet, verzet hem hier mee; of beter: laat beide hetzelfde token lezen,
     zoals nu. */
  .dossier {
    --split-a: var(--dossier-split-a, calc(100% / 3 - var(--section-gap) / 6));
    --split-b: var(--dossier-split-b, calc(200% / 3 + var(--section-gap) / 6));
    grid-template-columns:
      minmax(0, calc(var(--split-a) - var(--section-gap) / 2))
      minmax(0, calc(var(--split-b) - var(--split-a) - var(--section-gap)))
      minmax(0, 1fr);
  }
}

/* COACH-PLAYER-IPHONE-IPAD-BASIS — an iPad Pro in landscape is 1366px and fell
   into the wide stand above; after list + detail the gym column had ~380px left,
   narrower than an iPhone, while the trainer picked up the iPad precisely for
   the bigger screen. data-ipad is already stamped (coach.js stampTablet) and was
   read by nothing until now. A real desktop keeps its three panels. Placed after
   the ≥1024 block on purpose — see the note at the tablet grip rules about
   exactly this trap. */
@media (min-width: 1024px) {
  html[data-ipad] .cmain { max-width: none; }
  html[data-ipad] .dossier-pair { display: flex; }
  html[data-ipad] .dossier {
    grid-template-columns: minmax(0, calc(var(--dossier-split, 50%) - var(--section-gap) / 2)) minmax(0, 1fr);
  }
  html[data-ipad] .dossier[data-pair="client-gym"]       .dossier__panel[data-panel="nutrition"] { display: none; }
  html[data-ipad] .dossier[data-pair="client-nutrition"] .dossier__panel[data-panel="gym"]       { display: none; }
  html[data-ipad] .dossier__grip--pair { display: flex; }
  html[data-ipad] .dossier__grip--a,
  html[data-ipad] .dossier__grip--b   { display: none; }
}

/* COACH-DOSSIER-IPAD-VULT-HET-SCHERM-EN-GEEN-PANEELKOP ───────────────────── */

/* Visueel weg, maar NIET uit de toegankelijkheidsboom. De drie dossierpanelen
   zijn identieke <section>s die hun naam aan hun kop ontlenen; display:none of
   visibility:hidden zou een schermlezer dat onderscheid ook afnemen. Enige
   hulpklasse in dit bestand — maak er geen bibliotheek van. */
.u-sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* De paneelkop draagt u-sr-only ALTIJD (coach.js), want in twee van de drie
   standen benoemt iets anders het paneel al: de segmented control ≤639px en de
   pair-toggle op tablet/iPad-liggend. Alleen in de brede driekoloms-stand is er
   géén schakelbalk en is de kop de enige naam van de kolom — daar komt hij
   terug. Terugzetten in plaats van per stand opnieuw verbergen: de veilige
   waarde is de verborgen waarde. */
@media (min-width: 1024px) {
  html:not([data-ipad]) .dossier__panel-title.u-sr-only {
    position: static;
    width: auto; height: auto;
    margin: 0 0 var(--space-2); padding: 0;
    overflow: visible;
    clip-path: none;
    white-space: normal;
  }
}

/* De volle-hoogte-keten uit .gym-player-open, doorgetrokken naar de GEWONE
   dossierstand overal waar de pair-toggle zichtbaar is. Geen tweede
   hoogte-berekening: dezelfde --coach-vh / --coach-navh die coach.js op één
   plek meet (measureCoachNav). html:has(.dossier) houdt hem op het
   dossierscherm; elk ander coach-scherm blijft gewone documentstroom.
   :not(.gym-player-open) laat het spelersblok verderop ongemoeid — twee
   stelsels die allebei de vensterhoogte uitrekenen is precies hoe dit stukgaat.
   DE TABBALK KOMT ER ÉÉN KEER AF: padding-bottom op #coach, en op .cmain gaat
   hij juist naar nul. Twee keer aftrekken IS de witte strook van ~64px.
   min-height:0 op ELKE schakel (#coach → .cmain → .dossier → paneel), anders
   kan de 240px-bodem op .dossier__panel niet krimpen en duwt hij de onderrand
   er juist verder uit. */
@media (min-width: 640px) and (max-width: 1023px) {
  html:not(.gym-player-open):has(.dossier),
  html:not(.gym-player-open):has(.dossier) body { height: 100%; overflow: hidden; overscroll-behavior: none; }
  html:not(.gym-player-open):has(.dossier) #coach {
    display: flex; flex-direction: column; min-height: 0;
    height: 100vh;                 /* fallback, moet BOVEN de dvh-regel blijven */
    height: var(--coach-vh, 100dvh);
  }
  html:not(.gym-player-open):has(.dossier) body.has-coachnav #coach { padding-bottom: calc(var(--coach-navh, 64px) + var(--safe-bottom)); }
  html:not(.gym-player-open):has(.dossier) .cshell { flex: 0 0 auto; }
  html:not(.gym-player-open):has(.dossier) .cmain,
  html:not(.gym-player-open):has(.dossier) body.has-coachnav .cmain {
    flex: 1 1 auto; min-height: 0;
    display: flex; flex-direction: column;
    padding-bottom: 0;
  }
  html:not(.gym-player-open):has(.dossier) .cmain > *:not(.dossier) { flex: 0 0 auto; }
  html:not(.gym-player-open):has(.dossier) .dossier { flex: 1 1 auto; min-height: 0; }
  /* Beide kolommen delen dus dezelfde onderrand: ze zijn even hoog als het
     grid en scrollen ieder van binnen. Een kolom die op zijn eigen inhoud
     eindigt is de kartelrand. */
  html:not(.gym-player-open):has(.dossier) .dossier__panel {
    min-height: 0; height: 100%;
    overflow-y: auto; overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }
}
/* Zelfde blok, andere stand: een iPad in landschap is ≥1024px breed maar toont
   dezelfde pair-toggle (zie COACH-PLAYER-IPHONE-IPAD-BASIS hierboven). De
   declaraties staan bewust twee keer uitgeschreven in plaats van achter een
   gedeelde klasse: de twee standen worden los gemeten en los gepind. */
@media (min-width: 1024px) {
  html[data-ipad]:not(.gym-player-open):has(.dossier),
  html[data-ipad]:not(.gym-player-open):has(.dossier) body { height: 100%; overflow: hidden; overscroll-behavior: none; }
  html[data-ipad]:not(.gym-player-open):has(.dossier) #coach {
    display: flex; flex-direction: column; min-height: 0;
    height: 100vh;                 /* fallback, moet BOVEN de dvh-regel blijven */
    height: var(--coach-vh, 100dvh);
  }
  html[data-ipad]:not(.gym-player-open):has(.dossier) body.has-coachnav #coach { padding-bottom: calc(var(--coach-navh, 64px) + var(--safe-bottom)); }
  html[data-ipad]:not(.gym-player-open):has(.dossier) .cshell { flex: 0 0 auto; }
  html[data-ipad]:not(.gym-player-open):has(.dossier) .cmain,
  html[data-ipad]:not(.gym-player-open):has(.dossier) body.has-coachnav .cmain {
    flex: 1 1 auto; min-height: 0;
    display: flex; flex-direction: column;
    padding-bottom: 0;
  }
  html[data-ipad]:not(.gym-player-open):has(.dossier) .cmain > *:not(.dossier) { flex: 0 0 auto; }
  html[data-ipad]:not(.gym-player-open):has(.dossier) .dossier { flex: 1 1 auto; min-height: 0; }
  html[data-ipad]:not(.gym-player-open):has(.dossier) .dossier__panel {
    min-height: 0; height: 100%;
    overflow-y: auto; overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }
}

/* ── central notes (COACH-PLATFORM-SPRINT-2-CENTRAL-NOTES-SYSTEM) ── */
.cpage-head__action {
  margin-left: auto; flex: 0 0 auto;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--accent); border-radius: var(--radius);
  background: var(--accent); color: var(--on-accent);
  font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
}
.cpage-head__action:active { background: var(--accent-2); }
/* COACH-ADD-CLIENT-LINEAR-FLOW — secondary toolbar routes (Import / Intake link). */
.cpage-head__action--ghost {
  margin-left: 0;
  border-color: var(--line); background: transparent; color: var(--ink-2);
}
.cpage-head__action--ghost:active { background: var(--surface); }
/* COACH-CLEANUP-1 — icon-only overflow kebab next to the primary action. */
.cpage-head__action--icon {
  width: 38px; height: 38px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
}

/* note composer (panel block + correspondence) */
.notecompose { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-3); }
.notecompose__field { position: relative; }
.notecompose__input {
  width: 100%; resize: vertical; min-height: 44px;
  padding: var(--space-2) var(--space-3);
  padding-right: 72px;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); font: inherit; font-size: 14px;
}
/* To-do insert — sits left of the pencil-submit inside the same field. */
.notecompose__todo {
  position: absolute; right: 34px; top: 50%; transform: translateY(-50%);
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 0; cursor: pointer;
  padding: var(--space-1); color: var(--muted); line-height: 0;
  border-radius: 8px;
}
.notecompose__todo:hover { color: var(--accent); }
/* Inline variant for the note edit-actions row (static flow, not overlaid). */
.notecompose__todo--inline { position: static; transform: none; margin-left: auto; }
.notecompose__submit {
  position: absolute; right: var(--space-2); top: 50%; transform: translateY(-50%);
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 0; cursor: pointer;
  padding: var(--space-1); color: var(--accent); line-height: 0;
}
.notecompose__submit:hover { opacity: 0.8; }
.notecompose__submit:disabled { opacity: 0.4; cursor: default; }

/* DOSSIER-DE-NOTITIEKAART-SCROLLT-EN-HEEFT-EEN-KEBAB — the dossier card's row
   shape. Field and send button side by side, nothing overlaid on the typing: the
   old field carried a pin toggle, a to-do glyph and a pencil inside its own
   padding, which is what cut the placeholder off halfway through a word. The
   panel blocks and the inline note editor keep the field above, untouched. */
.notecompose--row .notecompose__field {
  display: flex; align-items: flex-end; gap: var(--space-2);
}
.notecompose--row .notecompose__input {
  flex: 1 1 auto; min-width: 0;
  /* 16px is not a taste: iOS zooms into any field below it and does not zoom
     back out on leaving. "Smaller" therefore means ONE ROW HIGH, never a
     smaller letter. The field grows with the typing up to five rows
     (field-sizing where it is supported, a JS fallback where it is not) and
     scrolls inside itself after that. */
  padding: 10px var(--space-3);
  min-height: 44px; max-height: 132px;
  font-size: 16px; line-height: 1.4;
  resize: none; overflow-y: auto;
  field-sizing: content;
}
/* A real send button: round, accent, arrow up — a pencil means "edit". It never
   slides in and out (a control that appears with the first character goes
   missing for a screen reader mid-sentence); it dims while the field is empty. */
.notecompose__submit--send {
  position: static; transform: none; flex: 0 0 auto;
  width: 44px; height: 44px; padding: 0;
  border-radius: 50%;
  background: var(--accent); color: var(--on-accent);
}
.notecompose__submit--send:disabled { opacity: 0.45; cursor: default; }

/* panel notes-block */
.pnotes { margin-top: var(--space-3); }
.pnotes__list { display: flex; flex-direction: column; gap: var(--space-2); }
.pnotes__empty { margin: 0; color: var(--muted); font-size: 13px; }
.pnotes__all {
  align-self: flex-start; padding: var(--space-1) 0;
  border: 0; background: transparent; color: var(--accent);
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}

/* note card */
.note {
  position: relative;
  padding: var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface);
}

/* COACH-CLIENT-LOG-TAB-NOTES-CHAT-SPLIT — one Log tab mixes every source, so the
   source must be readable at a glance: a 4px left band on the card + a tinted
   source chip. Colours derive from existing tokens, no raw hex. */
.note[data-src] { border-left: 4px solid var(--line); }
.note[data-src="coach_panel_client"]    { border-left-color: var(--accent); }
.note[data-src="coach_panel_gym"]       { border-left-color: color-mix(in srgb, var(--accent) 45%, var(--danger)); }
.note[data-src="coach_panel_nutrition"] { border-left-color: var(--ok); }
.note[data-src="client_inbox"]          { border-left-color: color-mix(in srgb, var(--ok) 40%, var(--danger)); }
.note__source--coach_panel_client {
  color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, transparent);
}
.note__source--coach_panel_gym {
  color: color-mix(in srgb, var(--accent) 45%, var(--danger));
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}
.note__source--coach_panel_nutrition {
  color: var(--ok); background: color-mix(in srgb, var(--ok) 14%, transparent);
}
.note__source--client_inbox {
  color: color-mix(in srgb, var(--ok) 40%, var(--danger));
  background: color-mix(in srgb, var(--ok) 10%, transparent);
}

/* DOSSIER-WAT-JE-MOET-WETEN-STAAT-BOVENAAN — the Log tab (.dlog*) went with the
   row that mounted it: the correspondence card at the top of the dossier carries
   its content and both of its doors. Nothing renders those classes any more, so
   the rules left with the markup instead of rotting here. */

/* ⋯ overflow on compact dossier-panel previews only. */
.note__ov { position: absolute; top: var(--space-2); right: var(--space-2); }
.note__ov-btn {
  display: flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; padding: 0;
  border: 0; border-radius: var(--radius); background: transparent;
  color: var(--muted); cursor: pointer;
}
.note__ov-btn:hover { color: var(--ink); background: var(--line-2); }
.note__ov-list {
  display: none; position: absolute; top: calc(100% + 4px); right: 0; z-index: 5;
  min-width: 140px; flex-direction: column;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); overflow: hidden;
}
.note__ov-list.is-open { display: flex; }
.note__ov-item {
  display: flex; align-items: center; padding: var(--space-2) var(--space-3);
  border: 0; background: transparent; color: var(--ink);
  font: inherit; font-size: 0.88rem; text-align: left; cursor: pointer;
}
.note__ov-item:hover { background: var(--line-2); }
.note__ov-item--danger { color: var(--danger); }
.note--hasov .note__meta { padding-right: 26px; }
.note--archived { opacity: 0.6; }
/* CLIENT-TIMELINE-NUTRITION-EOD-SUMMARY — machine-written timeline events sit
   in the same chronological thread as real correspondence, so they read quieter:
   flatter surface, no source-colour band, muted body. Tokens only. */
.note--event {
  padding: var(--space-2) var(--space-3);
  background: transparent;
  border-style: dashed;
  border-left-color: var(--line) !important;
}
.note--event .note__body { color: var(--ink-2); font-size: 13px; }
.note--event .note__source { color: var(--muted); background: var(--line-2); }
.note--event .note__author { font-weight: 400; color: var(--muted); }

/* DOSSIER-EEN-NOTITIE-DIE-BLIJFT-STAAN — the timeline copy of a pinned note.
   Deliberately ABOVE the priority rules: priority is "today", pinning is
   "always", and when a note is both the urgent colour wins the edge while the
   chip in the meta row still says it stands. */
.note--pinned { border-left: 3px solid var(--warn); }
.note__pinmark {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px var(--space-2); border-radius: 999px;
  background: color-mix(in srgb, var(--warn) 16%, transparent);
  color: color-mix(in srgb, var(--warn) 80%, var(--ink));
  font-weight: 600;
}
.note__pinmark svg { flex: 0 0 auto; }

.note--p1 { border-left: 3px solid var(--ok); }
.note--p2 { border-left: 3px solid var(--accent); }
.note--p3 { border-left: 3px solid var(--danger); }
.note__meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2); font-size: 12px; color: var(--muted); }
.note__source {
  padding: 1px var(--space-2); border-radius: 999px;
  background: var(--line-2); color: var(--ink-2); font-weight: 600;
}
.note__author { font-weight: 600; color: var(--ink-2); }
.note__lock { padding: 1px var(--space-2); border-radius: 999px; background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger); }
.note__body { margin: 0; color: var(--ink); font-size: 14px; white-space: pre-wrap; word-break: break-word; }
.note__bodywrap { display: flex; flex-direction: column; }
.note__todo { display: flex; gap: var(--space-2); align-items: flex-start; padding: 2px 0; font-size: 14px; color: var(--ink); }
.note__todo input[type=checkbox] { accent-color: var(--accent); margin-top: 3px; flex: none; }
.note__todo--done span { text-decoration: line-through; color: var(--muted); }
.note__tags { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-top: var(--space-2); }
.note__tag { padding: 1px var(--space-2); border-radius: 999px; background: var(--line-2); color: var(--ink-2); font-size: 12px; }
.note__acts { display: flex; gap: var(--space-3); margin-top: var(--space-2); }
.note__act {
  padding: var(--space-1) 0; border: 0; background: transparent;
  color: var(--ink-2); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.note__act--danger { color: var(--danger); }
.note__act--primary { color: var(--accent); }
.note__act:disabled { opacity: 0.5; cursor: default; }
.note__editor { display: flex; flex-direction: column; gap: var(--space-2); }
.note__editor-input {
  width: 100%; resize: vertical;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); font: inherit; font-size: 14px;
}
.note__editor-acts { display: flex; gap: var(--space-3); }

/* correspondence filter-bar */
.cfilter {
  position: sticky; top: calc(env(safe-area-inset-top, 0px) + 40px + var(--space-2) * 2 + 1px);
  z-index: 5;
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-3) 0; margin-bottom: var(--space-3);
  background: var(--bg);
}
.cfilter__search {
  width: 100%; padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); font: inherit; font-size: 14px;
}
.cfilter__chip {
  padding: var(--space-1) var(--space-3); border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface);
  color: var(--ink-2); font: inherit; font-size: 13px; cursor: pointer;
}
.cfilter__chip--on { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.cfilter__toggles { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.cfilter__select {
  padding: var(--space-1) var(--space-2); border-radius: var(--radius); min-width: 0;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink); font: inherit; font-size: 13px;
}

/* source dropdown — compact trigger + floating single-select list */
.cfilter__src { position: relative; }
.cfilter__srcbtn {
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding: var(--space-1) var(--space-2); border-radius: var(--radius);
  border: 1px solid var(--line); background: var(--surface); color: var(--ink);
  font: inherit; font-size: 13px; cursor: pointer; max-width: 100%;
}
.cfilter__srclbl { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cfilter__srcbtn svg { flex: 0 0 auto; }
.cfilter__srcmenu {
  position: absolute; top: calc(100% + var(--space-1)); left: 0; z-index: 20;
  display: flex; flex-direction: column; min-width: 160px; max-height: 60vh; overflow: auto;
  padding: var(--space-1); border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface);
}
.cfilter__srcopt {
  padding: var(--space-2) var(--space-3); border: 0; border-radius: var(--radius);
  background: none; color: var(--ink); font: inherit; font-size: 13px; text-align: left; cursor: pointer;
}
.cfilter__srcopt:hover { background: var(--bg); }
.cfilter__srcopt--on { background: var(--accent); color: var(--on-accent); }

/* timeline */
.ctimeline { display: flex; flex-direction: column; gap: var(--space-2); }
.ctimeline__empty, .ctimeline__loading { margin: var(--space-4) 0; text-align: center; color: var(--muted); font-size: 14px; }

/* ── COACH-PLATFORM-SPRINT-3-PANEL-1-CLIENT-DOSSIER (coach-0.9.220) ──
   Client-panel intake: basisgegevens card, Smart-goal trend tiles with
   dependency-free sparklines, the "Meer klantinfo" sheet, and the dedicated
   /intake/edit form. Tokens only; accent buttons use --on-accent. */
.intake { display: flex; flex-direction: column; gap: var(--space-4); }
.intake__loading, .intake__empty { margin: var(--space-3) 0; color: var(--muted); font-size: 14px; }

.intake-card__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); }
.intake-card__name { margin: 0; font-size: 20px; font-weight: 700; color: var(--ink); }
.intake-card__edit {
  display: inline-flex; align-items: center; gap: var(--space-1); flex: 0 0 auto;
  padding: var(--space-1) var(--space-3); border-radius: var(--radius);
  border: 1px solid var(--line); background: var(--surface); color: var(--ink);
  font: inherit; font-size: 13px; cursor: pointer;
}
.intake-card__edit svg { flex: 0 0 auto; }
.intake-card__viewonly { flex: 0 0 auto; font-size: 13px; color: var(--muted); }
.intake-card__grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3);
}
/* INTAKE-CONSENT-1-GEDEELDE-LAAG — "nothing shared yet" is a state with a
   reason, so it gets a heading-weight line plus the why underneath; the
   shared-copy note under a FILLED grid stays a quiet footnote. */
.intake-card__notshared { margin: 0; font-size: 15px; font-weight: 600; color: var(--ink); }
.intake-card__notshared-why { margin: 0; font-size: 13px; line-height: 1.45; color: var(--muted); }
.intake-card__sharednote { margin: 0; font-size: 12px; line-height: 1.45; color: var(--muted); }
.intake-field { display: flex; flex-direction: column; gap: 2px; }
.intake-field__label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.03em; }
.intake-field__value { font-size: 15px; color: var(--ink); font-weight: 600; }

/* COACH-INTAKE-FORMATTED-RENDER — grouped, scannable intake Q&A (label above,
   answer below with line-breaks preserved) replaces the old single-line blob. */
.intake-card--answers { gap: var(--space-4); }
.intake-qgroup { display: flex; flex-direction: column; gap: var(--space-3); }
.intake-qgroup__title {
  margin: 0; font-size: 12px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--muted);
}
.intake-qa { display: flex; flex-direction: column; gap: 2px; }
.intake-qa__q { font-size: 12px; color: var(--muted); }
.intake-qa__a { margin: 0; font-size: 15px; color: var(--ink); white-space: pre-line; overflow-wrap: anywhere; }

.smartgoal { display: flex; flex-direction: column; gap: var(--space-3); }
.smartgoal__empty { margin: 0; color: var(--muted); font-size: 14px; }

.mtile {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-3); border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface);
}
.mtile--tappable { cursor: pointer; }
.mtile--tappable:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.mtile--open { border-color: var(--accent); }
.mtile__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); }
.mtile__name { font-size: 14px; font-weight: 600; color: var(--ink); }
.mtile__cur { display: inline-flex; align-items: baseline; gap: 4px; }
.mtile__val { font-size: 18px; font-weight: 700; color: var(--ink); }
.mtile__unit { font-size: 12px; color: var(--muted); }
.mtile__target { font-size: 12px; color: var(--ink-2); }
.mtile__when { font-size: 12px; color: var(--ink-2); }
.mtile__trends { display: flex; gap: var(--space-2); }
.mtrend {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px var(--space-2); border-radius: 999px;
  background: var(--bg); font-size: 12px; color: var(--ink-2);
}
.mtrend--up { color: var(--ok); }
.mtrend--down { color: var(--danger); }
.mtrend--flat, .mtrend--none { color: var(--muted); }
.mtrend__win { font-weight: 600; }
.mtrend svg { flex: 0 0 auto; }
.spark { display: block; width: 100%; max-width: 100%; }
.spark__line { fill: none; stroke: var(--accent); stroke-width: 1.5; stroke-linejoin: round; stroke-linecap: round; }
.spark__dot { fill: var(--accent); }
.mtile__chart { display: flex; flex-direction: column; gap: var(--space-1); padding-top: var(--space-2); border-top: 1px solid var(--line-2); }
.mtile__chart-empty { margin: 0; color: var(--muted); font-size: 13px; }
.mtile__range { display: flex; justify-content: space-between; font-size: 11px; color: var(--muted); }

/* GEWICHT-KRIJGT-ZIJN-EIGEN-REGELKAART — one verdict glyph beside the value, a
   caption line under the trend chips, and the weekly I-chart in the fold.
   Deliberately no --danger anywhere: a body on a scale is not a defect, and red
   is the nudge toward tampering the chart exists to stop. */
.mtile__verdict { display: inline-flex; align-items: center; margin-left: 4px; }
.mtile__verdict--ok { color: var(--ok); }
.mtile__verdict--warn { color: var(--warn); }
.mtile__verdict--muted { color: var(--muted); }
.mtile__ctl { font-size: 12px; color: var(--ink-2); }
.wchart__limit { stroke: var(--muted); stroke-width: 1; stroke-dasharray: 3 3; }
.wchart__mean { stroke: var(--muted); stroke-width: 1; }
.wchart__dot--out { fill: var(--warn); }

/* COACH-MEASUREMENT-QUICK-LOG — per-tile pencil + quick-log sheet */
.mtile__log {
  flex: 0 0 auto; align-self: center;
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink-2); cursor: pointer;
}
.mtile__log:hover { color: var(--accent); border-color: var(--accent); }
.mtile__log:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.mlog__last { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); margin-bottom: var(--space-2); }
.mlog__last-label { font-size: 13px; color: var(--muted); }
.mlog__delta { font-size: 13px; font-weight: 700; color: var(--muted); }
.mlog__delta--up { color: var(--ok); }
.mlog__delta--down { color: var(--danger); }
.mlog__delta--flat { color: var(--muted); }

/* COACH-DOSSIER-INFO-REARRANGE — .intake-links (the "More client info" + second
   "View all notes" pair) is gone: the account fields live in the Manage card and
   the notes block already carries its own "View all →". */

/* bottom sheet */
.csheet {
  position: fixed; inset: 0; z-index: 50; display: flex; align-items: flex-end; justify-content: center;
  background: rgba(0, 0, 0, 0.4);
}
/* DOSSIER-VLOEIENDE-RUIMTE — een vel IS de kaart (zie .dsec__sheetbody, dat
   zelf 0 horizontale padding draagt), dus het draagt --card-pad en niet een
   eigen getal. Verticaal blijft het ritme --space-4: boven zit de kop en
   onder de veilige zone van de telefoon, en die twee horen niet mee te
   krimpen met de breedte. */
.csheet__panel {
  width: 100%; max-width: 520px; max-height: 80vh; overflow: auto;
  display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-4) var(--card-pad) calc(var(--space-4) + var(--safe-bottom));
  border-radius: var(--radius) var(--radius) 0 0; background: var(--surface);
}
.csheet__top { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.csheet__title { font-size: 16px; font-weight: 700; color: var(--ink); }
.csheet__close { border: 0; background: none; color: var(--ink-2); cursor: pointer; padding: var(--space-1); }
.csheet__rows { display: flex; flex-direction: column; gap: var(--space-2); }
.csheet__row { display: flex; justify-content: space-between; gap: var(--space-3); }
.csheet__label { color: var(--muted); font-size: 13px; }
.csheet__value { color: var(--ink); font-size: 14px; font-weight: 600; word-break: break-word; text-align: right; }
.csheet__note { margin: 0; color: var(--muted); font-size: 12px; font-style: italic; }

/* COACH-CONFIRMS-WERKEN-OVERAL — the themed confirm sheet that replaced every
   native confirm box in coach.js. Sits above the ordinary bottom sheets on
   purpose: it is nearly always asked from inside one of them. */
.cconf { z-index: 95; }
.cconf__panel { gap: var(--space-2); }
.cconf__msg { margin: 0 0 var(--space-2); color: var(--muted); font-size: 13px; line-height: 1.5; }
.cconf__btn {
  width: 100%; padding: 14px; border: 0; border-radius: var(--radius);
  font: inherit; font-size: 14px; font-weight: 700; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.cconf__btn--go { background: var(--accent); color: var(--on-accent); }
.cconf__btn--danger { background: var(--danger); color: var(--on-accent); }
.cconf__btn--cancel { background: transparent; color: var(--muted); font-weight: 600; }

/* DOSSIER-VASTZETTEN-MET-LANG-INDRUKKEN — the menu behind a long press. A sheet
   on the body, NOT a popover in the row: the notes card clips itself (it owns a
   height budget), so a menu anchored to the last row would be cut off at the
   card's edge, and the coach would find out by missing the item he wanted. Rows
   are 48px, well past the 44pt Apple asks and the 24px of WCAG 2.5.8. */
.cact { z-index: 96; }
.cact__panel { gap: var(--space-2); }
.cact__msg { margin: 0 0 var(--space-2); color: var(--muted); font-size: 13px; line-height: 1.5; }
.cact__list { display: flex; flex-direction: column; }
.cact__item {
  display: block; width: 100%; min-height: 48px; padding: 13px var(--space-3);
  border: 0; border-radius: var(--radius); background: transparent;
  color: var(--ink); font: inherit; font-size: 15px; font-weight: 600;
  text-align: left; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cact__item:hover { background: var(--line-2); }
.cact__item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.cact__item--danger { color: var(--danger); }
.cact__item--cancel { color: var(--muted); font-weight: 600; text-align: center; }

/* COACH-VERWIJDERT-EEN-DOSSIER-VOORGOED — the password step reuses the confirm
   panel rather than inventing a second sheet: the coach is one step further in
   the same act, and a differently-shaped screen would read as a new one. */
.cconf__input {
  width: 100%; padding: 12px 14px; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface); color: var(--ink);
  font: inherit; font-size: 15px;
}
.cconf__input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.cconf__err { margin: 0; color: var(--danger); font-size: 13px; line-height: 1.4; }
/* The five-minute line under the password field. Quiet by design: it is a fact
   about the confirmation, not a warning — hence muted, never danger. */
.cconf__hint { margin: 0; color: var(--muted); font-size: 12px; line-height: 1.4; }

/* The delete row sits in its own section with a rule above it. The gap is the
   point: the one irreversible action in the menu must not share an edge with
   the rows a thumb scrolls past. */
.csettings-sec--danger { margin-top: var(--space-4); }
.csettings-row--danger .csettings-row__title { color: var(--danger); }
.csettings-row--danger svg { color: var(--danger); }

/* ── Add-client sheet (COACH-SIDE-CLIENT-ONBOARDING) ── */
/* COACH-ADD-CLIENT-LINEAR-FLOW — swap link between the new-client form and the
   existing-account search; replaces the old 4-button segmented control. */
.acswap {
  align-self: flex-start; border: 0; background: none; padding: 0;
  font: inherit; font-size: 13px; color: var(--muted);
  text-decoration: underline; cursor: pointer;
}
.acswap:active { color: var(--ink); }
.acseg {
  display: flex; gap: 0; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden;
}
.acseg__btn {
  flex: 1; border: 0; background: var(--surface); color: var(--ink-2);
  padding: var(--space-3) var(--space-2); font-size: 14px; font-weight: 600; cursor: pointer;
}
.acseg__btn + .acseg__btn { border-left: 1px solid var(--line); }
.acseg__btn--on { background: var(--accent); color: var(--on-accent); }
.acbody { display: flex; flex-direction: column; }
.acpane { display: flex; flex-direction: column; gap: var(--space-3); }
.acinput {
  width: 100%; box-sizing: border-box; padding: var(--space-3); font-size: 15px;
  color: var(--ink); background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius);
}
.acinput:focus { outline: none; border-color: var(--accent); }
.acresults { display: flex; flex-direction: column; gap: var(--space-2); }
.acresults__hint { margin: 0; color: var(--muted); font-size: 13px; }
.acrow {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-2); border: 1px solid var(--line); border-radius: var(--radius);
}
.acrow__avatar {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: var(--on-accent); font-weight: 700; font-size: 14px;
}
.acrow__mid { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.acrow__name { color: var(--ink); font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acrow__email { color: var(--muted); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acrow__flag { flex: 0 0 auto; color: var(--muted); font-size: 12px; font-style: italic; }
.acrow__send {
  flex: 0 0 auto; border: 0; background: var(--accent); color: var(--on-accent);
  padding: var(--space-2) var(--space-3); border-radius: var(--radius); font-weight: 600; cursor: pointer;
}
.acrow__send:disabled { opacity: 0.6; cursor: default; }
.acform { gap: var(--space-3); }
.acfield { display: flex; flex-direction: column; gap: var(--space-1); }
.acfield__label { color: var(--muted); font-size: 13px; font-weight: 600; }
.acradio { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.acradio__btn {
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-2);
  padding: var(--space-2) var(--space-3); border-radius: var(--radius); font-size: 13px; cursor: pointer;
}
.acradio__btn--on { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.acform__err { margin: 0; color: var(--danger); font-size: 13px; min-height: 0; }
.acform__err:empty { display: none; }
.acform__hint { margin: -4px 0 var(--space-2); color: var(--muted); font-size: 12px; }
.acform__hint--warn { color: var(--danger); font-weight: 700; }

/* LEAD-STUUR-BETAALLINK-VANUIT-HET-DOSSIER — het pakketblad. Alles mag krimpen
   en niets mag een eigen breedte opleggen: op 390 px is het blad smaller dan de
   langste pakketnaam en een enkele vaste maat hier zet het hele scherm aan het
   zijwaarts schuiven. Vandaar min-width:0 op elke flexrij en een url-veld dat
   100% van zijn ouder is in plaats van zo breed als zijn inhoud. */
.lpay, .lpay__list, .lpay__out { min-width: 0; }
.lpay__list { display: flex; flex-direction: column; gap: var(--space-2); }
.lpay__empty { margin: 0; color: var(--muted); font-size: 13px; }
.lpay__row {
  display: flex; align-items: center; gap: var(--space-2);
  width: 100%; min-width: 0;
  padding: 10px 12px; text-align: left;
  border: 1px solid var(--line); border-radius: var(--radius-2, 12px);
  background: var(--surface); color: var(--ink); font: inherit; cursor: pointer;
}
.lpay__row:disabled { opacity: .55; cursor: default; }
.lpay__row svg { flex: 0 0 auto; color: var(--muted); }
.lpay__row-txt { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-width: 0; }
.lpay__row-name {
  font-weight: 600; font-size: 14px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lpay__row-meta { color: var(--muted); font-size: 12px; }
.lpay__out { display: flex; flex-direction: column; gap: var(--space-2); }
.lpay__out-pkg { margin: 0; font-weight: 700; font-size: 14px; }
.lpay__fine { margin: 0; color: var(--muted); font-size: 12px; }
.lpay__url {
  width: 100%; min-width: 0; box-sizing: border-box;
  padding: 10px 12px;
  border: 1px solid var(--line); border-radius: var(--radius-2, 12px);
  background: var(--surface-2); color: var(--ink);
  font: inherit; font-size: 13px;
}
.lpay__acts { display: flex; gap: var(--space-2); min-width: 0; }
/* .btn/.cbtn erven width:100%; hier WIL je dat juist, twee gelijke helften —
   maar wel met min-width:0 erbij, anders duwt de inhoud ze breder dan de helft. */
.lpay__act { flex: 1 1 0; min-width: 0; display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
/* PAKKET-EEN-LOOPTIJD-HOORT-BIJ-HET-PAKKET — een getal met de eenheid ernaast
   ("24" + "weken"), zodat de looptijd één antwoord blijft in plaats van twee
   velden onder elkaar. De keuzelijst krijgt de vaste helft van de breedte. */
.acform__duo { display: flex; gap: var(--space-2); align-items: center; }
.acform__duo > * { min-width: 0; }
.acform__duo > :first-child { flex: 1 1 auto; }
.acform__duo > :last-child { flex: 0 0 44%; }
.acform__submit {
  border: 0; background: var(--accent); color: var(--on-accent);
  padding: var(--space-3); border-radius: var(--radius); font-size: 15px; font-weight: 700; cursor: pointer;
}
.acform__submit:disabled { opacity: 0.6; cursor: default; }

/* ── AGENDA-JE-WERKTIJDEN-STEL-JE-ZELF-IN ──────────────────────────────────
   Zeven dagen onder elkaar, elk met zijn eigen blokken. De dag is de kop en de
   blokken staan eronder ingesprongen, zodat de hiërarchie (dag → tijden) te
   zien is zonder dat er een kader om elke dag heen hoeft.

   Geen `display` op .cwh__add: die knop bestaat alleen op een dag die aanstaat
   en wordt in JS weggelaten in plaats van met [hidden] verborgen — een klasse
   met eigen display zou van dat attribuut winnen. */
.cwh__hint { margin: 0 0 var(--space-3); }
.cwh__week { display: flex; flex-direction: column; }
.cwh__day { padding: var(--space-2) 0; border-top: 1px solid var(--line); }
.cwh__day:first-child { border-top: 0; }
.cwh__dayhead { display: flex; align-items: center; gap: var(--space-2); }
.cwh__switch {
  display: flex; align-items: center; gap: var(--space-2);
  flex: 1 1 auto; min-width: 0; cursor: pointer;
}
.cwh__dayname { font-size: 15px; font-weight: 600; text-transform: capitalize; }
.cwh__add {
  flex: 0 0 auto; border: 1px solid var(--line); background: var(--surface);
  color: var(--ink-2); border-radius: var(--radius);
  padding: 4px var(--space-2); font-size: 12px; font-weight: 600; cursor: pointer;
  display: inline-flex; align-items: center; gap: 4px;
}
.cwh__off { margin: var(--space-1) 0 0 28px; color: var(--muted); font-size: 13px; }
.cwh__block {
  display: flex; align-items: center; gap: var(--space-2);
  margin: var(--space-2) 0 0 28px;
}
.cwh__time { flex: 1 1 0; min-width: 0; }
.cwh__dash { flex: 0 0 auto; color: var(--muted); }
.cwh__del {
  flex: 0 0 auto; border: 0; background: none; color: var(--muted);
  padding: var(--space-1); cursor: pointer; line-height: 0;
}
.cwh__err { margin: var(--space-3) 0 0; }

/* ── AGENDA-EEN-BRON-DE-OMZETLIJST-VOOR-JAYY ───────────────────────────────
   De lijst gaat over tientallen reeksen en honderden sessies, en Jayy loopt hem
   per regel na. Daarom is de klantnaam de kop en staan de reeksen eronder
   ingesprongen: hij leest "wie" één keer en daarna alleen nog "welke".

   Het vinkje staat links en vol formaat (18px): het is de enige handeling op
   dit blad en moet met een duim te raken zijn. De waarschuwing hangt ONDER de
   regel waar hij bij hoort en niet bovenaan het blad — hij is alleen iets waard
   op het moment dat het vinkje ernaast staat. */
.comz__head { margin: 0 0 var(--space-3); }
.comz__count { font-size: 16px; font-weight: 700; }
.comz__sub { margin: var(--space-1) 0 0; color: var(--muted); font-size: 13px; }
.comz__client { padding: var(--space-3) 0; border-top: 1px solid var(--line); }
.comz__client:first-of-type { border-top: 0; padding-top: 0; }
.comz__name { font-size: 15px; font-weight: 600; }
.comz__meta { color: var(--muted); font-size: 13px; }
.comz__row {
  display: flex; align-items: flex-start; gap: var(--space-2);
  margin: var(--space-2) 0 0; cursor: pointer;
}
.comz__cb { flex: 0 0 auto; width: 18px; height: 18px; margin: 2px 0 0; }
.comz__txt { flex: 1 1 auto; min-width: 0; }
.comz__when { font-size: 14px; font-weight: 600; text-transform: capitalize; }
.comz__warn {
  display: flex; align-items: center; gap: 6px;
  margin: var(--space-1) 0 0; color: var(--warn); font-size: 13px;
}
.comz__err { margin: var(--space-3) 0 0; }

/* ── AGENDA-PLEKKEN-TOEWIJZEN-IN-EEN-KEER ──────────────────────────────────
   Eén rij = naam + wanneer links, de keuzelijst rechts, en het grijze woordje
   waarom eronder over de volle breedte. Op een telefoon (iPhone 13, 390 px)
   past "Hannah Bakker · elke dinsdag 09:30 · 12 afspraken" naast een
   keuzelijst niet, dus de lijst krijgt een eigen regel zodra het krap wordt
   in plaats van de naam af te knijpen: wie je een plek geeft is de vraag, de
   plek is het antwoord. */
.cplek__row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-2);
  align-items: start;
  padding: var(--space-3) 0; border-top: 1px solid var(--line);
}
.cplek__row:first-of-type { border-top: 0; }
.cplek__row .acinput { max-width: 46vw; }
.cplek__why {
  grid-column: 1 / -1; color: var(--muted); font-size: 12px;
}
.cplek__why:empty { display: none; }
@media (max-width: 420px) {
  .cplek__row { grid-template-columns: minmax(0, 1fr); }
  .cplek__row .acinput { max-width: none; }
}

/* ── AGENDA-EEN-BRON-OMZETTEN-NAAR-SASSU ───────────────────────────────────
   Het verslag van de proefdraai hergebruikt de kop, de klantblokken en de
   waarschuwing van de lijst: het gaat over dezelfde klanten en dezelfde
   reeksen, dus mag het er niet als een ander scherm uitzien.

   Nieuw is alleen de reeks-regel — ingesprongen met een streep ervoor, zodat
   "wat er met deze ene reeks gebeurt" visueel ONDER de klant hangt en niet
   ernaast. En de weg terug: die is bewust een tekstknop en geen tweede volle
   knop, want het echte omzetten moet de enige zware knop op dit scherm zijn. */
.comz__ser {
  margin: var(--space-2) 0 0; padding-left: var(--space-3);
  border-left: 2px solid var(--line);
}
.comz__back {
  display: block; width: 100%; margin: var(--space-2) 0 0;
  border: 0; background: none; color: var(--muted);
  padding: var(--space-2); font-size: 14px; cursor: pointer;
}

/* ── COACH-EVENT-FORM-NORMAN-RESTYLE — grouped sections for the group-event sheet ── */
.glsec {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-3); margin-bottom: var(--space-2);
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--bg);
}
.glsec__head {
  color: var(--muted); font-size: 11px; font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase;
  margin-bottom: var(--space-1);
}
/* Fields that only apply under the open-enrollment toggle: indent + rule so the
   mapping (setting sits where it takes effect) is visible. */
.glsub {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding-left: var(--space-3); margin-top: var(--space-1);
  border-left: 2px solid var(--line);
}
/* Toggle-style checkbox row: bordered so it reads as a discrete control. */
.glsw {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3); margin: var(--space-2) 0 0;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
}
.glsw .cpay-cash__input { width: 18px; height: 18px; accent-color: var(--accent); }
/* Primary save action sticks to the bottom of the scrolling sheet. */
.acform__submit--sticky {
  position: sticky; bottom: 0; z-index: 2;
  margin-top: var(--space-2);
  box-shadow: 0 -1px 0 var(--line);
}

/* NUTRITION-HISTORY-IMPORT-UI-SETTINGS-AND-COACH — coach import pointer sheet. */
.nut-importrow { display: flex; justify-content: flex-end; padding-bottom: var(--space-2); }
.csheet__body { display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-3) 0; }
.csheet__lead { margin: 0; color: var(--ink); font-size: 15px; }
.csheet__hint { margin: 0; color: var(--muted); font-size: 13px; }

/* ── bulk import pane ── */
.acbulk__hint { margin: 0; color: var(--muted); font-size: 13px; }
.acbulk__ta { min-height: 120px; resize: vertical; font-family: inherit; line-height: 1.5; }
.acbulk__preview { display: flex; flex-direction: column; gap: var(--space-2); }
.acbulk__row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  border: 1px solid var(--line); border-radius: var(--radius); padding: var(--space-2) var(--space-3);
}
.acbulk__row--ok { border-color: var(--accent); }
.acbulk__row--bad { border-color: var(--danger); }
.acbulk__mid { display: flex; flex-direction: column; min-width: 0; }
.acbulk__name { font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; }
.acbulk__email { color: var(--muted); font-size: 12px; }
.acbulk__flag { color: var(--muted); font-size: 12px; white-space: nowrap; }
.acbulk__row--bad .acbulk__flag { color: var(--danger); }
.acbulk__claim { padding: 0 var(--space-2) var(--space-1); }
.acbulk__copy {
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-2);
  padding: var(--space-1) var(--space-2); border-radius: var(--radius); font-size: 12px; cursor: pointer;
}

/* ── intake wizard ── */
.csheet__panel--wizard { max-width: 640px; }
.acwiz { gap: var(--space-4); min-height: 320px; }
.acwiz__prog { display: flex; flex-direction: column; gap: var(--space-2); }
.acwiz__count { color: var(--muted); font-size: 12px; font-weight: 600; }
.acwiz__bar { height: 4px; border-radius: 999px; background: var(--line); overflow: hidden; }
.acwiz__fill { height: 100%; background: var(--accent); transition: width 0.2s ease; }
.acwiz__q { margin: 0; color: var(--ink); font-size: 18px; font-weight: 700; line-height: 1.35; }
.acwiz__field { display: flex; flex-direction: column; gap: var(--space-2); }
.acwiz__hint { margin: 0; color: var(--muted); font-size: 13px; }
.acwiz__nav { display: flex; gap: var(--space-3); align-items: center; margin-top: auto; }
.acwiz__back {
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-2);
  padding: var(--space-3) var(--space-4); border-radius: var(--radius); font-size: 15px; font-weight: 600; cursor: pointer;
}
.acwiz__back:disabled { opacity: 0.4; cursor: default; }
.acwiz__next { flex: 1; }
/* INTAKE-ONTHOUDT-ELKE-STAP — the reassurance line under the wizard. Quiet on
   purpose: it exists so the coach dares to close the sheet, not to be noticed. */
.acwiz__saved { margin: var(--space-2) 0 0; color: var(--muted); font-size: 12px; text-align: center; }
.acwiz__saved--warn { color: var(--warn, var(--ink-2)); }
.acwiz__done { display: flex; flex-direction: column; align-items: center; gap: var(--space-3); text-align: center; padding: var(--space-4) 0; }
.acwiz__done-ic { color: var(--accent); }
.acwiz__done-title { margin: 0; color: var(--ink); font-size: 20px; font-weight: 700; }
.acwiz__done-sub { margin: 0; color: var(--muted); font-size: 14px; }

/* ── coach toast ── */
.ctoast {
  position: fixed; left: 50%; bottom: calc(var(--space-5) + var(--safe-bottom));
  transform: translate(-50%, 16px); z-index: 60;
  max-width: 90vw; padding: var(--space-3) var(--space-4);
  background: var(--ink); color: var(--surface); border-radius: var(--radius);
  font-size: 14px; font-weight: 600; box-shadow: 0 0 0 1px var(--line);
  opacity: 0; pointer-events: none; transition: opacity 0.2s ease, transform 0.2s ease;
}
.ctoast--show { opacity: 1; transform: translate(-50%, 0); }
.ctoast--err { background: var(--danger); color: var(--on-accent); }
/* REVIEW-KLEINE-DINGEN-DIE-IN-EEN-UUR-WEG-ZIJN — a toast that carries an action.
   The box keeps pointer-events:none (it must never swallow a tap on the list
   behind it); only the button takes taps, and only while the toast is SHOWN —
   a hidden toast still occupies its corner and would otherwise stay clickable.
   Ink is currentColor on purpose: the same button rides the --err background. */
.ctoast--action { display: flex; align-items: center; gap: var(--space-3); }
.ctoast__undo {
  flex: none; padding: 4px 10px; border: 1px solid currentColor;
  border-radius: var(--radius-sm); background: none; color: inherit;
  font: inherit; font-weight: 700; cursor: pointer; pointer-events: none;
}
.ctoast--show .ctoast__undo { pointer-events: auto; }
/* RONDE-ROOD-DUWT-ORANJE-WACHT-GRIJS-ZWIJGT — the toast carries at most TWO
   actions (Undo, Why?). The text takes the slack so both buttons keep their
   full label; nothing else about the toast changes. */
.ctoast__text { flex: 1 1 auto; min-width: 0; }

/* ── RONDE-ROOD-DUWT-ORANJE-WACHT-GRIJS-ZWIJGT: the interrupting band ──
   Sits between the sticky header and the routed view, on EVERY coach route.
   Deliberately not sticky itself: .cshell's height depends on the safe-area
   inset, so a second sticky layer would need a magic top offset that is wrong
   on exactly the phones the inset exists for.
   --danger + --on-accent is the pairing .ctoast--err already ships, so the
   contrast is the one already measured — and the warning triangle carries the
   same meaning as the colour, for a coach who cannot see the difference. */
.credband { background: var(--danger); color: var(--on-accent); }
.credband__go {
  display: flex; align-items: center; gap: var(--space-3);
  width: 100%; min-height: 56px;
  padding: var(--space-2) var(--space-4);
  border: 0; background: none; color: inherit; font: inherit;
  text-align: left; cursor: pointer;
}
.credband__txt { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; }
.credband__name { font-size: 14px; font-weight: 700; }
.credband__line {
  font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.credband__more {
  flex: 0 0 auto; font-size: 12px; font-weight: 700;
  border: 1px solid currentColor; border-radius: var(--radius-sm); padding: 2px 6px;
}

/* ── GELD-EEN-COACH-DIE-NIET-BETAALT-HOUDT-ZIJN-WERK-IN-HET-RESPIJT ──
   Dezelfde plek als .credband, met opzet een andere stem. Rood is hier fout:
   deze coach werkt door, zijn klanten merken niets, en het enige dat mis is,
   is een incasso. Daarom de rustige oppervlakkleur met een accentrand aan de
   zijkant — zichtbaar genoeg om niet te missen, stil genoeg om geen paniek te
   zijn. Ook niet sticky, om dezelfde reden als de rode band. */
.cgraceband {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface); color: var(--ink);
  border-bottom: 1px solid var(--line);
  border-left: 3px solid var(--accent);
}
.cgraceband__txt { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-width: 0; }
.cgraceband__lead { font-size: 14px; font-weight: 700; }
.cgraceband__calm { font-size: 13px; color: var(--ink-2); }
.cgraceband__pay {
  flex: 0 0 auto; min-height: 44px; padding: 0 var(--space-4);
  border: 0; border-radius: var(--radius);
  background: var(--accent); color: var(--on-accent);
  font: inherit; font-size: 14px; font-weight: 700; cursor: pointer;
}
.cgraceband__pay:disabled { opacity: 0.6; cursor: progress; }

/* ── GELD-HET-STOPSCHERM-ZEGT-WAT-ER-MET-JE-KLANTEN-GEBEURT ──
   Dezelfde strook, ander onderwerp. Bewust dezelfde vorm als de respijt-strook
   hierboven: voor de coach is dit hetzelfde soort bericht — er verandert
   vandaag niets, er komt een datum aan, er is één knop — en twee verschillende
   vormen zouden suggereren dat het twee verschillende soorten nieuws zijn.
   Eigen klassen en geen gedeelde selector, zodat het hernoemen van een label in
   de ene strook de ijkplaten van de andere niet meesleept. Alle kleur komt uit
   tokens, dus licht en donker rollen mee zonder een tweede regel. */
.cstopband {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface); color: var(--ink);
  border-bottom: 1px solid var(--line);
  border-left: 3px solid var(--accent);
}
.cstopband__txt { flex: 1 1 auto; min-width: 0; font-size: 14px; font-weight: 700; }
.cstopband__undo {
  flex: 0 0 auto; min-height: 44px; padding: 0 var(--space-4);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: transparent; color: var(--ink);
  font: inherit; font-size: 14px; font-weight: 700; cursor: pointer;
}
.cstopband__undo:disabled { opacity: 0.6; cursor: progress; }

/* ── COACH-DE-STILSTAANDE-COACHOMGEVING-ZEGT-HOE-JE-VERDERGAAT ──
   De derde strook in deze rij, en met opzet dezelfde vorm als de twee erboven.
   Dit is het ZWAARSTE bericht van de drie — zijn werk slaat niet meer op — en
   juist daarom niet rood en niet groter: een coach wiens abonnement afliep heeft
   geen fout gemaakt, en een deurwaarderskleur maakt de kassa geen millimeter
   dichterbij (doc §7). De accentrand doet het werk, de knop draagt het accent,
   en alle kleur komt uit tokens zodat licht en donker meerollen.
   Eigen klassen en geen gedeelde selector met .cgraceband / .cstopband: een
   hernoemd label in de ene strook mag de ijkplaten van de andere niet
   meeslepen. */
.cpauseband {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface); color: var(--ink);
  border-bottom: 1px solid var(--line);
  border-left: 3px solid var(--accent);
}
.cpauseband__txt { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-width: 0; }
.cpauseband__lead { font-size: 14px; font-weight: 700; }
.cpauseband__calm { font-size: 13px; color: var(--ink-2); }
.cpauseband__pay {
  flex: 0 0 auto; min-height: 44px; padding: 0 var(--space-4);
  border: 0; border-radius: var(--radius);
  background: var(--accent); color: var(--on-accent);
  font: inherit; font-size: 14px; font-weight: 700; cursor: pointer;
}
.cpauseband__pay:disabled { opacity: 0.6; cursor: progress; }

/* Het blad achter een geweigerde schrijfactie. Dezelfde stem als de strook — de
   kop IS de eerste regel van de strook — en één knop, want hier valt niets
   anders te doen dan kijken of betalen. */
.cpausesheet__calm { margin: 0; color: var(--ink-2); font-size: 14px; }
.cpausesheet__pay {
  min-height: 44px; padding: 0 var(--space-4);
  border: 0; border-radius: var(--radius);
  background: var(--accent); color: var(--on-accent);
  font: inherit; font-size: 15px; font-weight: 700; cursor: pointer;
}
.cpausesheet__pay:disabled { opacity: 0.6; cursor: progress; }

/* De deur eruit staat onderaan /abonnement, stil en zonder omlijsting: hij
   hoort gevonden te worden door wie hem zoekt, niet aangeboden aan wie hem
   niet zoekt. */
.cseat-stop { display: flex; flex-direction: column; margin-top: var(--space-4); }
.cseat-stop__btn {
  min-height: 44px; padding: 0 var(--space-4);
  border: 0; border-radius: var(--radius);
  background: transparent; color: var(--ink-2);
  font: inherit; font-size: 14px; cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
}

/* Het blad erachter: vier feiten, twee knoppen. 'Ik blijf' draagt het accent —
   de rustige uitgang hoort de makkelijkste te zijn — en de stopknop draagt geen
   gevarenkleur, want een coach die stopt maakt geen fout. */
.cstopsheet { display: flex; flex-direction: column; gap: var(--space-3); }
.cstopsheet__facts {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: var(--space-3);
}
.cstopsheet__fact {
  display: flex; align-items: flex-start; gap: var(--space-3);
  font-size: 15px; line-height: 1.45; color: var(--ink);
}
.cstopsheet__fact svg { flex: 0 0 auto; margin-top: 2px; color: var(--accent); }
.cstopsheet__factTxt { flex: 1 1 auto; min-width: 0; }
.cstopsheet__fact--quiet { color: var(--ink-2); font-size: 14px; }
.cstopsheet__stay, .cstopsheet__stop {
  width: 100%; min-height: 48px; padding: 0 var(--space-4);
  border-radius: var(--radius); font: inherit; font-size: 15px;
  font-weight: 700; cursor: pointer;
}
.cstopsheet__stay { border: 0; background: var(--accent); color: var(--on-accent); }
.cstopsheet__stop { border: 1px solid var(--line); background: transparent; color: var(--ink); }
.cstopsheet__stop:disabled { opacity: 0.6; cursor: progress; }

/* ── the four reasons behind "Why?" ── */
.creason__list { display: flex; flex-direction: column; gap: var(--space-2); }
.creason__opt {
  min-height: 48px; padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink);
  font: inherit; font-size: 15px; font-weight: 600; text-align: left; cursor: pointer;
}
.creason__opt:hover { border-color: var(--accent); }

/* intake edit form */
.iedit { display: flex; flex-direction: column; gap: var(--space-3); }
.iedit__loading, .iedit__empty { margin: var(--space-3) 0; color: var(--muted); font-size: 14px; }
.iedit__form { display: flex; flex-direction: column; gap: var(--space-3); }
.iedit__row { display: flex; flex-direction: column; gap: var(--space-1); }
.iedit__label { font-size: 13px; color: var(--ink-2); font-weight: 600; }
.iedit__input {
  padding: var(--space-2) var(--space-3); border-radius: var(--radius);
  border: 1px solid var(--line); background: var(--surface); color: var(--ink); font: inherit; font-size: 14px;
}
.iedit__derived { font-size: 13px; color: var(--muted); }
.iedit__input:disabled { opacity: 0.6; cursor: not-allowed; }
.iedit__subtitle { margin: var(--space-2) 0 0; font-size: 15px; font-weight: 700; color: var(--ink); }
.iedit__hint { margin: 0; color: var(--muted); font-size: 13px; }
/* TAILLE-EN-HEUP-ZET-JE-IN-EEN-TIK-AAN — the pair shortcut above the list.
   Three states via [data-state]: off, half (exactly one of the two ticked) and
   on. Half is quieter, never red — it reads as "not complete yet". */
.imetric-pair { display: flex; flex-direction: column; gap: var(--space-1); }
.imetric-pair__btn {
  display: flex; align-items: center; gap: var(--space-3); width: 100%; text-align: left;
  padding: var(--space-2) var(--space-3); border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface); color: var(--ink);
  font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
}
.imetric-pair__mark {
  flex: 0 0 auto; position: relative; width: 18px; height: 18px; border-radius: 4px;
  border: 1px solid var(--line); background: var(--surface);
}
.imetric-pair[data-state="half"] .imetric-pair__btn,
.imetric-pair[data-state="on"] .imetric-pair__btn { border-color: var(--accent); }
.imetric-pair[data-state="half"] .imetric-pair__mark { border-color: var(--accent); }
.imetric-pair[data-state="half"] .imetric-pair__mark::after {
  content: ''; position: absolute; left: 3px; right: 3px; top: 7px;
  height: 2px; border-radius: 1px; background: var(--accent);
}
.imetric-pair[data-state="on"] .imetric-pair__mark { border-color: var(--accent); background: var(--accent); }
.imetric-pair[data-state="on"] .imetric-pair__mark::after {
  content: ''; position: absolute; left: 5px; top: 1px; width: 5px; height: 10px;
  border: solid var(--on-accent); border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.imetric-pair__hint { margin: 0; color: var(--muted); font-size: 13px; }
.iedit__metrics { display: flex; flex-direction: column; gap: var(--space-2); }
.imetric {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-2) var(--space-3); border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface);
}
.imetric--on { border-color: var(--accent); }
.imetric__label { display: inline-flex; align-items: center; gap: var(--space-2); flex: 1 1 auto; cursor: pointer; }
.imetric__cb { width: 18px; height: 18px; flex: 0 0 auto; }
.imetric__name { font-size: 14px; color: var(--ink); }
.imetric__target {
  flex: 0 0 auto; width: 120px; padding: var(--space-1) var(--space-2); border-radius: var(--radius);
  border: 1px solid var(--line); background: var(--surface); color: var(--ink); font: inherit; font-size: 13px;
}
.imetric__target:disabled { opacity: 0.5; }
.iedit__err { margin: 0; color: var(--danger); font-size: 13px; }
.iedit__acts { display: flex; gap: var(--space-2); }
.iedit__save { flex: 1 1 auto; background: var(--accent); color: var(--on-accent); border: 0; }
.iedit__cancel {
  flex: 0 0 auto; padding: var(--space-2) var(--space-4); border-radius: var(--radius);
  border: 1px solid var(--line); background: var(--surface); color: var(--ink); font: inherit; cursor: pointer;
}

@media (min-width: 640px) {
  /* Het VEL zelf mag het scherm lezen: waar een vel staat (onderaan geplakt of
     gecentreerd) is een schermvraag. Zijn INHOUD leest zijn eigen vak — zie
     .intake-card__grid hieronder. */
  .csheet { align-items: center; }
  .csheet__panel { border-radius: var(--radius); }
}
/* DOSSIER-BLOKKEN-KIJKEN-NAAR-HUN-EIGEN-BREEDTE — de intakekaart staat in het
   intakevel van het dossier, dat op een laptop 520px breed is en nooit het
   scherm. Op `@media (min-width: 640px)` kreeg hij daar drie kolommen in een
   vak van ~488px: drie labels van "LICHAAMSGEWICHT"-lengte naast elkaar.
   Drempel 440px: twee kolommen vragen 2×150 + gap, drie vragen 3×140 + 2 gaps. */
@container dbox (min-width: 440px) {
  .intake-card__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ───────── Panel 2 gym (COACH-PLATFORM-SPRINT-4-PANEL-2-GYM-DOSSIER) ───────── */
.gym { display: flex; flex-direction: column; gap: var(--space-3); margin-top: var(--space-3); }

/* SCHEMA-SCHRIJVEN-KAN-OP-JE-TELEFOON-STAP-EEN — de Plan-deur stond op
   display:none en ging pas open vanaf 1024px, dus voor een klaarstaand concept
   bekijken en publiceren moest de coach een laptop openklappen. De knop blijft
   staan waar COACH-DOSSIER-MINDER-DEUREN-EN-ONTHOUDT-JE-KEUZE hem zette (in het
   uitklapblok Details); alleen de breedte-grendel gaat eraf. De rechtsuitlijning
   is het enige dat desktop-eigen was en blijft achter het breekpunt. */
.gym__planrow { display: flex; }
.gym__plan {
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding: var(--space-2) var(--space-3); border-radius: var(--radius);
  border: 1px solid var(--line); background: var(--surface); color: var(--accent);
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.gym__plan:active { background: var(--line-2); }
.gym__plan svg { flex: 0 0 auto; }

.gymcard__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); flex-wrap: wrap; }
.gymcard__span { display: inline-flex; border: 1px solid var(--line); border-radius: 999px; overflow: hidden; }
.gymcard__span-btn {
  padding: 4px var(--space-3); border: 0; background: var(--surface);
  color: var(--ink-2); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
}
.gymcard__span-btn + .gymcard__span-btn { border-left: 1px solid var(--line); }
.gymcard__span-btn--on { background: var(--accent); color: var(--on-accent); }
.gymcard__loading, .gymcard__empty { margin: 0; color: var(--muted); font-size: 13px; }
.gymcard__grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2); }
.gymstat {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--space-2) var(--space-3); border: 1px solid var(--line-2);
  border-radius: var(--radius); background: var(--bg);
}
.gymstat__label { font-size: 12px; color: var(--muted); }
.gymstat__val { display: inline-flex; align-items: baseline; gap: 4px; }
.gymstat__num { font-size: 18px; font-weight: 700; color: var(--ink); }
.gymstat__unit { font-size: 11px; color: var(--muted); }
.gymtrend { display: inline-flex; align-items: center; gap: 3px; font-size: 11px; color: var(--ink-2); }
.gymtrend--up { color: var(--ok); }
.gymtrend--down { color: var(--danger); }
.gymtrend--flat, .gymtrend--none { color: var(--muted); }
.gymtrend svg { flex: 0 0 auto; }

/* DOSSIER-NIEUWE-PRS-ALS-GOED-NIEUWS — de PR-regels onder de overzichtscijfers.
   Bewust GEEN accent- of ok-kleur: het is goed nieuws, maar het is nog steeds
   een meting, en een gekleurde lijst zou naast de neutrale cijfers erboven als
   een waarschuwing lezen. De oefeningsnaam krijgt de rek en ellipsiseert; het
   gewicht en de dag zijn kort en mogen nooit inleveren. */
.gymprs { display: flex; flex-direction: column; gap: var(--space-1); }
.gymprs__head {
  display: flex; align-items: center; gap: var(--space-1);
  font-size: 12px; font-weight: 600; color: var(--muted);
}
.gymprs__head svg { flex: 0 0 auto; }
.gymprs__row {
  display: flex; align-items: baseline; gap: var(--space-2);
  font-size: 13px; color: var(--ink);
}
.gymprs__ex { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gymprs__kg { flex: 0 0 auto; font-weight: 700; }
.gymprs__day { flex: 0 0 auto; font-size: 12px; color: var(--muted); }
.gymprs__note { margin: 0; font-size: 11px; color: var(--muted); }

/* COACH-SEND-BODY-SCAN-TWO-PATHS — one card, two paths. A passwordless client
 * (is_dummy) gets a shareable /claim link; a client who already has a login
 * gets an in-app reminder in the coach thread and NO link at all. */
.scansend {
  padding: var(--space-3); border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface);
}
.scansend__head { display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2); }
.scansend__head svg { flex: 0 0 auto; color: var(--ink-2); }
.scansend__hint { margin: 0 0 var(--space-3); color: var(--muted); font-size: 13px; line-height: 1.45; }
.scansend__btn {
  width: 100%; display: flex; align-items: center; justify-content: center; gap: var(--space-2);
  border: 1px solid var(--accent); background: var(--accent); color: var(--on-accent);
  padding: var(--space-3); border-radius: var(--radius);
  font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
}
.scansend__btn:disabled { opacity: 0.55; cursor: default; }
.scansend__out { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-3); }
.scansend__label { color: var(--muted); font-size: 12px; font-weight: 600; }
.scansend__url {
  width: 100%; box-sizing: border-box; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--bg); color: var(--ink-2);
  padding: var(--space-2); font-size: 12px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.scansend__acts { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.scansend__act {
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-2);
  padding: var(--space-1) var(--space-2); border-radius: var(--radius);
  font: inherit; font-size: 12px; cursor: pointer;
}
.scansend__done {
  display: flex; align-items: center; gap: var(--space-2);
  margin: var(--space-3) 0 0; color: var(--accent); font-size: 13px; font-weight: 600;
}
.scansend__done svg { flex: 0 0 auto; }
.scansend__err { margin: var(--space-2) 0 0; color: var(--danger); font-size: 13px; }

/* VANUIT-HET-DOSSIER-GEEF-JE-TOEGANG — the dossier's app-access door. */
.appacc {
  padding: var(--space-3); border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface);
}
.appacc__head { display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2); }
.appacc__head svg { flex: 0 0 auto; color: var(--ink-2); }
.appacc__body { display: flex; flex-direction: column; gap: var(--space-2); }
.appacc__hint { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.45; }
.appacc__btn {
  width: 100%; display: flex; align-items: center; justify-content: center; gap: var(--space-2);
  border: 1px solid var(--accent); background: var(--accent); color: var(--on-accent);
  padding: var(--space-3); border-radius: var(--radius);
  font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
}
.appacc__btn:disabled { opacity: 0.55; cursor: default; }
.appacc__done {
  display: flex; align-items: center; gap: var(--space-2);
  margin: 0; color: var(--accent); font-size: 13px; font-weight: 600;
}
.appacc__done svg { flex: 0 0 auto; }
.appacc__out { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-1); }
.appacc__label { color: var(--muted); font-size: 12px; font-weight: 600; }
.appacc__url {
  width: 100%; box-sizing: border-box; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--bg); color: var(--ink-2);
  padding: var(--space-2); font-size: 12px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.appacc__acts { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.appacc__act {
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-2);
  padding: var(--space-1) var(--space-2); border-radius: var(--radius);
  font: inherit; font-size: 12px; cursor: pointer;
}
.appacc__act--go { border-color: var(--accent); background: var(--accent); color: var(--on-accent); font-weight: 600; }
.appacc__ask {
  display: flex; flex-direction: column; gap: var(--space-2); align-items: flex-start;
  margin-top: var(--space-1); padding-top: var(--space-3); border-top: 1px solid var(--line);
}
.appacc__err { margin: 0; color: var(--danger); font-size: 13px; }

/* COACH-PROGRESS-PHOTO-REVIEW-GALLERY — read-only progress-photo gallery card. */
.photocard {
  padding: var(--space-3); border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface);
}
.photocard__head { display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2); }
.photocard__head svg { flex: 0 0 auto; color: var(--ink-2); }
.photocard__loading, .photocard__empty { margin: 0; color: var(--muted); font-size: 13px; }
.photogrp + .photogrp { margin-top: var(--space-3); }
.photogrp__date { font-size: 12px; font-weight: 600; color: var(--muted); margin-bottom: var(--space-1); }
.photogrp__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-2); }
.photothumb {
  width: 100%; aspect-ratio: 3 / 4; object-fit: cover;
  border: 1px solid var(--line-2); border-radius: var(--radius);
  background: var(--bg); display: block;
}

/* BODYSCAN-COMPARE-COACH — the Compare toggle + its temporary selection row.
   The bar sits INSIDE the card (not position:fixed), so it can never end up
   over another surface's controls. */
.photocard__cmp {
  margin-left: auto; display: inline-flex; align-items: center; gap: var(--space-1);
  padding: 5px 10px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface-2, var(--surface)); color: var(--ink); font: inherit;
  font-size: 12px; font-weight: 600; cursor: pointer;
}
/* .photocard__head svg is forced to --ink-2; the toggle's glyph must follow the
   button's own state colour instead. */
.photocard__head .photocard__cmp svg { color: inherit; }
.photocard__cmp[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); }
.photocard__cmpbar {
  display: flex; flex-direction: column; gap: var(--space-2);
  margin-top: var(--space-3); padding-top: var(--space-2); border-top: 1px solid var(--line);
}
.photocard__cmphint { font-size: 12px; color: var(--muted); }
.photocard__cmprow { display: flex; justify-content: flex-end; gap: var(--space-2); }
.photocard__cmpcancel, .photocard__cmpcta {
  padding: 8px 14px; border-radius: var(--radius); font: inherit; font-weight: 600; cursor: pointer;
}
.photocard__cmpcancel { border: 1px solid var(--line); background: transparent; color: var(--ink); }
.photocard__cmpcta { border: none; background: var(--accent); color: var(--on-accent); }
.photocard__cmpcta:disabled { opacity: .5; cursor: default; }
.photopick {
  position: relative; padding: 0; border: none; background: none;
  display: block; cursor: pointer; border-radius: var(--radius);
}
.photopick--full { opacity: .45; }
.photopick--on .photothumb { outline: 3px solid var(--accent); outline-offset: -3px; }
.photopick__tick {
  position: absolute; top: 6px; right: 6px; width: 24px; height: 24px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, .42); color: #fff; border: 1.5px solid rgba(255, 255, 255, .7);
}
.photopick--on .photopick__tick {
  background: var(--accent); color: var(--on-accent); border-color: var(--accent);
}

/* GYM-CENTRALE-SHEET-OPRUIMING-DRIE-DEUREN-DICHT — the paginated session list
   and its row styles are gone; the central sheet reads those days side by side.
   What is left is one door, shaped like the other secondary panel actions. */
.gymsheet-open {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
}
.gymsheet-open:active { background: var(--bg); }
.gymsheet-open svg { flex: 0 0 auto; }

/* DOSSIER-WAT-JE-MOET-WETEN-STAAT-BOVENAAN — the correspondence card that took
   the week ruler's place at the top of the dossier. Unlike the ruler this IS a
   card: it carries writing, so it needs an edge to sit inside. It stands above
   the tab controls on every width, which makes its height a budget rather than a
   preference — the Klant/Gym/Voeding buttons must stay above the fold on a 390px
   phone, so the note text clamps at two lines and the card caps at 45vh.

   DOSSIER-DE-SCHEIDSLIJN-ONDER-DE-NOTITIES-SCHUIFT-MEE — that cap is now the
   coach's to move. --dcorr-h is a UNITLESS number of percent, multiplied here by
   the one height the coach shell already measures (--coach-vh, written by
   measureCoachNav in coach.js; 100dvh when the token is absent). Deliberately
   still a max-height and not a height: an empty or one-note card must stay the
   size of its content, or every new client would open on a tall empty box. The
   45 default IS the 45vh it replaces, so a coach who never touches the grip sees
   no change at all. The bottom margin moved to the grip below — the grip is now
   what stands between this card and the tab doors. */
.dcorr {
  display: flex; flex-direction: column;
  max-height: calc(var(--dcorr-h, 45) * var(--coach-vh, 100dvh) / 100);
  overflow: hidden;
  margin: 0;
  padding: var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface);
}
/* DOSSIER-KOP-ZEGT-HOE-HET-GAAT — de kaart opent SAMENGEVOUWEN: kop, eventuele
   vastgezette regels en één regel van de laatste notitie. Op een 390px-telefoon
   begon de eerste tabinhoud pas rond 700px hoogte (audit #12), en het grootste
   deel daarvan was deze kaart in volle hoogte terwijl de coach hem nog niet
   nodig had. Wat weg is, is niet weg: één tik op de chevron geeft de lijst, de
   tip en het invoerveld terug, en die keuze wordt per coach onthouden.

   Samengevouwen vervalt de hoogtebegroting (er is niets meer om te begrenzen)
   en vervalt de sleepgreep: een kaart die zijn lijst niet toont heeft geen
   hoogte om te slepen. De greep stond ook voor de ruimte tot de tabdeuren, dus
   die marge komt hier terug. */
.dcorr--collapsed { max-height: none; margin-bottom: var(--space-4); }
.dcorr--collapsed .dcorr__last,
.dcorr--collapsed .dcorr__hint,
.dcorr--collapsed .notecompose { display: none; }
.dcorr--collapsed + .dcorr-grip { display: none; }
.dcorr:not(.dcorr--collapsed) .dcorr__peek { display: none; }
/* De samenvatting: precies één regel, met een ellips als de notitie langer is.
   Geen twee regels — dan is het een voorproefje dat alweer een alinea wordt. */
.dcorr__peek {
  flex: 0 0 auto;
  margin: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--ink-2); font-size: 13px; line-height: 1.4;
}
.dcorr__peek--empty { color: var(--muted); font-style: italic; }
/* Dezelfde maat en hetzelfde onzichtbare 44×44-bereik als de ⋮ ernaast: twee
   knoppen naast elkaar in één kop moeten even groot aanvoelen. */
.dcorr__toggle {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; padding: 0;
  border: 0; border-radius: var(--radius); background: transparent;
  color: var(--muted); cursor: pointer;
}
.dcorr__toggle::before {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
}
.dcorr__toggle:hover { color: var(--ink); background: var(--line-2); }
.dcorr__toggle > svg { transition: transform 120ms ease; }
.dcorr__toggle[aria-expanded="true"] > svg { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  .dcorr__toggle > svg { transition: none; }
}
/* De kop draagt nu twee knoppen; ze horen bij elkaar aan de rechterkant. */
.dcorr__headbtns { flex: 0 0 auto; display: flex; align-items: center; gap: var(--space-1); }
/* The seam itself: a hairline with an iOS-sized grabber pill on it. The visible
   line stays 1px — Apple's split-view guidance is an unobtrusive divider — and an
   invisible ::before carries the finger.

   The reach is arithmetic, not a round number, exactly like .dossier__grip's 21px
   per side: ABOVE the line there is this grip's own 8px top margin plus the card's
   12px bottom padding, so 20px of dead space; BELOW it there are 16px of margin
   before the tab doors start, so the overlay stops at 15px and overlaps nothing
   tappable. 20 + 1 + 15 = 36px, past the 24×24 floor of WCAG 2.5.8. It is NOT the
   44px Apple asks for, and reaching 44 would mean covering either the composer
   above or the first row of doors below — a target that steals a tap is worse than
   a slightly small one, and the tap/Home/End/arrow routes all reach the same
   detents without the seam at all. */
.dcorr-grip {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  height: 1px; margin: var(--space-2) 0 var(--space-4);
  background: var(--line);
  cursor: row-resize;
  /* ONLY on the grip. On the card or the list this would kill one-finger
     scrolling through the notes — see .dcorr__last. */
  touch-action: none;
}
.dcorr-grip::before {
  content: ''; position: absolute; left: 0; right: 0; top: -20px; bottom: -15px;
}
.dcorr-grip__pill {
  width: 36px; height: 5px; border-radius: 999px;
  background: var(--muted);
  pointer-events: none;
}
.dcorr-grip:focus-visible { outline: 2px solid var(--accent); outline-offset: 6px; }
/* Same contract as .dossier--dragging, minus its col-resize cursor: a horizontal
   seam resizes rows, and the embedded schema iframe must go deaf for the duration
   or it swallows pointermove the moment the pointer crosses it. */
.dcorr--dragging { cursor: row-resize; -webkit-user-select: none; user-select: none; }
.dcorr--dragging iframe { pointer-events: none; }
/* DOSSIER-DE-NOTITIEKAART-SCROLLT-EN-HEEFT-EEN-KEBAB — head, pinned block and
   composer hold their place; ONLY the list scrolls. A card that scrolled as a
   whole would carry the input he was aiming for out from under his finger. */
.dcorr__head {
  flex: 0 0 auto;
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  margin: 0 0 var(--space-2);
}
.dcorr__title {
  margin: 0; min-width: 0;
  font-size: 11px; line-height: 1; font-weight: 700; letter-spacing: 0.06em;
  color: var(--muted); text-transform: uppercase;
}
.dcorr__ov { position: relative; flex: 0 0 auto; }
.dcorr__ov-btn {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; padding: 0;
  border: 0; border-radius: var(--radius); background: transparent;
  color: var(--muted); cursor: pointer;
}
/* The glyph stays 18px so the head stays a head, and an invisible pad carries
   the finger to 44×44 (Apple) — well past the 24×24 WCAG 2.5.8 floor. */
.dcorr__ov-btn::before {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
}
.dcorr__ov-btn:hover { color: var(--ink); background: var(--line-2); }
/* The unread-chat signal used to be text on the Chat door. Behind a menu it has
   to be visible on the CLOSED button, or a client's message goes unseen. */
.dcorr__ov-dot {
  position: absolute; top: 1px; right: 1px;
  width: 8px; height: 8px; border-radius: 50%; background: var(--accent);
}
/* `[hidden]` is only a UA rule on `display`, and ANY author rule that sets
   display beats it silently. This one does not set display — so the pin is here
   to keep it that way rather than to fix something. */
.dcorr__ov-dot[hidden] { display: none; }
.dcorr__ov-list {
  display: none; position: absolute; top: calc(100% + 4px); right: 0; z-index: 5;
  min-width: 170px; flex-direction: column;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); overflow: hidden;
}
.dcorr__ov-list.is-open { display: flex; }
.dcorr__ov-item {
  display: flex; align-items: center; min-height: 44px;
  padding: var(--space-2) var(--space-3);
  border: 0; background: transparent; color: var(--ink);
  font: inherit; font-size: 0.88rem; text-align: left; cursor: pointer;
}
.dcorr__ov-item:hover { background: var(--line-2); }
/* One finger through every note, inside the card. `overscroll-behavior: contain`
   keeps the page underneath still at the end of the list and keeps
   pull-to-refresh out of it; `touch-action: pan-y` leaves the scroll to the
   browser, which is exactly what a preventDefault on touchstart would kill. */
.dcorr__last {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; overscroll-behavior: contain; touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
}
/* DOSSIER-VASTZETTEN-MET-LANG-INDRUKKEN — a row is a press-and-hold target, so
   the text may not be selectable: a hold on selectable text starts iOS' own
   selection with the magnifier and the menu never arrives. Copy comes back as
   a menu item, exactly the trade WhatsApp makes. `touch-action` stays off this
   element — the list owns `pan-y` and the hold must never cost the scroll. */
.dcorr__row {
  position: relative;
  padding: var(--space-2) 36px var(--space-2) 0;
  border-bottom: 1px solid var(--line);
  border-radius: var(--radius);
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
  transition: background-color 120ms ease, transform 120ms ease;
}
.dcorr__row:last-child { border-bottom: 0; }
/* The press state after 150 ms. It is the ONLY feedback we can promise: there
   is no vibration API on iOS, so the coach has to SEE that the hold started. */
.dcorr__row.is-pressing { background: var(--line-2); transform: scale(0.98); }
@media (prefers-reduced-motion: reduce) {
  .dcorr__row { transition: none; }
  .dcorr__row.is-pressing { transform: none; }
}
/* The route that needs no gesture (WCAG 2.5.7): with a mouse the ⋯ appears on
   the row and opens the same menu, and because it is a real button the keyboard
   and a screen reader get there too. On a touch screen there is no hover to
   reveal it, and an invisible-but-tappable button over the text would eat the
   tap — so it is absent there and the hold is the route. */
.dcorr__rowov {
  position: absolute; top: var(--space-1); right: 0;
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0;
  border: 0; border-radius: 8px; background: transparent;
  color: var(--muted); line-height: 0; cursor: pointer;
  opacity: 0; transition: opacity 120ms ease;
}
.dcorr__row:hover .dcorr__rowov,
.dcorr__rowov:focus-visible { opacity: 1; }
.dcorr__rowov:hover { color: var(--ink); background: var(--line-2); }
@media (hover: none) {
  .dcorr__rowov { display: none; }
}
/* The one-time tip. A gesture nobody is told about is a feature nobody has
   (NN/g), so this line says what the hold does — once, per coach, with an ×. */
.dcorr__hint {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: var(--space-2);
  margin: 0 0 var(--space-2); padding: var(--space-2);
  border-radius: var(--radius); background: var(--line-2);
  color: var(--muted);
}
.dcorr__hint[hidden] { display: none; }
.dcorr__hint > svg { flex: 0 0 auto; }
.dcorr__hint-text { flex: 1 1 auto; margin: 0; font-size: 12px; line-height: 1.4; }
.dcorr__hint-x {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; padding: 0;
  border: 0; border-radius: 8px; background: transparent;
  color: var(--muted); line-height: 0; cursor: pointer;
}
.dcorr__hint-x:hover { color: var(--ink); background: var(--line); }
/* The spinner-row at the end of the list: reaching it asks the server for the
   next page, so it is a sentinel first and a skeleton second. */
.dcorr__more { padding: var(--space-2) 0; }
/* DOSSIER-EEN-NOTITIE-DIE-BLIJFT-STAAN — standing knowledge above the last line.
   The card's height is a budget (the tab buttons must stay above the fold on a
   390px phone), so three pins may never push the doors off the screen: the block
   scrolls inside its own cap and each line clamps to two rows, exactly like the
   "Last" line does. */
.dcorr__pins {
  flex: 0 0 auto;
  margin: 0 0 var(--space-2); max-height: 26vh;
  overflow-y: auto; overscroll-behavior: contain;
}
/* The hairline says the block above is a different KIND of line, not merely an
   older one: what stands, versus what was last said. `:not(:empty)` keeps it
   off the screen entirely when nothing is pinned — a rule over nothing would
   read as a card that failed to load. */
.dcorr__pins:not(:empty) { padding-bottom: var(--space-2); border-bottom: 1px solid var(--line); }
.dcorr__kicker--pin {
  display: flex; align-items: center; gap: var(--space-1);
  color: color-mix(in srgb, var(--warn) 70%, var(--ink));
}
.dcorr__kicker--pin svg { flex: 0 0 auto; }
.dcorr__pin {
  position: relative;
  margin-top: var(--space-1);
  padding: var(--space-2) 32px var(--space-2) var(--space-3);
  border-left: 4px solid var(--warn); border-radius: var(--radius);
  background: color-mix(in srgb, var(--warn) 16%, transparent);
}
.dcorr__pin-text {
  margin: 0; font-size: 14px; line-height: 1.4; color: var(--ink);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden; word-break: break-word;
}
.dcorr__pin-who { margin: var(--space-1) 0 0; font-size: 12px; line-height: 1.35; color: var(--muted); }
.dcorr__pin-off {
  position: absolute; top: var(--space-1); right: var(--space-1);
  display: inline-flex; align-items: center; justify-content: center;
  padding: var(--space-1); border: 0; border-radius: 8px;
  background: transparent; color: color-mix(in srgb, var(--warn) 75%, var(--ink));
  line-height: 0; cursor: pointer;
}
.dcorr__pin-off:hover { color: var(--danger); }
.dcorr__pin-off:disabled { opacity: 0.4; cursor: default; }
.dcorr__kicker {
  margin: 0 0 var(--space-1);
  font-size: 11px; line-height: 1; font-weight: 700; letter-spacing: 0.06em;
  color: var(--muted); text-transform: uppercase;
}
.dcorr__line { display: flex; align-items: flex-start; gap: var(--space-2); min-width: 0; }
/* note vs chat — one quiet chip, told apart by fill and not by colour alone:
   a note is an outline, a message from the client is filled. */
.dcorr__chip {
  flex: 0 0 auto; margin-top: 2px; padding: 1px var(--space-2);
  border: 1px solid var(--line); border-radius: 999px;
  font-size: 11px; line-height: 1.5; font-weight: 600;
  color: var(--muted); text-transform: lowercase;
}
.dcorr__chip--chat {
  border-color: transparent;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent);
}
/* Three lines and no more: the list is for reading, but this card still sits ON
   TOP of the panel buttons, so one long note may never push them off a phone
   screen. The ⋮ carries the door to the note in full. */
.dcorr__text {
  flex: 1 1 auto; min-width: 0; margin: 0;
  font-size: 14px; line-height: 1.4; color: var(--ink);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3;
  overflow: hidden; word-break: break-word;
}
.dcorr__dot {
  flex: 0 0 auto; width: 8px; height: 8px; margin-top: 6px;
  border-radius: 50%; background: var(--accent);
}
.dcorr__who { margin: var(--space-1) 0 0; font-size: 12px; line-height: 1.35; color: var(--muted); }
.dcorr__none { margin: 0; font-size: 13px; line-height: 1.4; color: var(--muted); }
.dcorr .notecompose { flex: 0 0 auto; margin-top: var(--space-2); }
/* The unread count, now inside the Chat row of the ⋮ menu. */
.dcorr__new { color: var(--accent); font-weight: 700; }
/* The chat window lives here between visits — see dossierCorrespondenceCard(). */
.dcorr__holder { display: none; }

/* COACH-CLIENT-WEEK-STRIP-ABOVE-ALL-TABS — the dossier-wide week ruler. It sits
   above the tab controls, so it is deliberately a STRIP and not a card: no
   heading, no border box, no fill — only a hairline separating it from the tabs.
   Shape language is lifted from the member app's diary dot row
   (.nut-consist__dot in app.css): same 50% rounding, hairline ring, accent fill. */
.cweek {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-4);
  padding: var(--space-3) var(--space-4) var(--space-4);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--space-4);
}
.cweek__days {
  flex: 1 1 auto; display: flex; align-items: flex-end;
  justify-content: space-between; gap: var(--space-1);
}
.cweek__day {
  flex: 1 1 0; display: flex; flex-direction: column; align-items: center;
  gap: 6px; min-width: 0;
}
.cweek__lbl {
  font-size: 11px; line-height: 1; font-weight: 600; letter-spacing: 0.04em;
  color: var(--muted); text-transform: uppercase;
}
.cweek__ring {
  width: 20px; height: 20px; border-radius: 50%; box-sizing: border-box;
  border: 2px solid var(--line); background: transparent;
  display: flex; align-items: center; justify-content: center;
}
.cweek__core { width: 0; height: 0; border-radius: 50%; background: var(--accent); }
/* KERN = trained */
.cweek__day.is-trained .cweek__core { width: 10px; height: 10px; }
/* RING = nutrition logged */
.cweek__day.is-logged .cweek__ring { border-color: var(--accent); }
/* both → the core fills the ring: one solid circle, never two dots */
.cweek__day.is-trained.is-logged .cweek__core { width: 100%; height: 100%; }
/* NO ANSWER — a query that failed. Dashed, never filled: the day must not read
   as a deliberate empty day. No new colour, only the existing line token. */
.cweek__day.is-unknown .cweek__ring { border-style: dashed; border-color: var(--muted); }

/* TODAY — weight + position, never colour, so it cannot be confused with the
   accent ring that means "logged". The base rule reserves the same 2px on every
   column so the circles stay on one baseline. */
.cweek__day.is-today .cweek__lbl { color: var(--ink); font-weight: 800; }
.cweek__day::after { content: ""; display: block; width: 18px; height: 2px; border-radius: 2px; }
.cweek__day.is-today::after { background: var(--ink-2); }

/* DOSSIER-WEEKSTRIP-DAG-DEUREN — a day cell is a BUTTON now: strip the UA chrome
   so the dot row looks exactly as before, and let the selected day carry a soft
   accent plate (never a second colour on the dot itself, which still means
   trained/logged). */
.cweek__day {
  appearance: none; -webkit-appearance: none; border: 0; background: none;
  padding: 4px 2px; border-radius: 10px; font: inherit; cursor: pointer;
}
.cweek__day.is-sel { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.cweek__detail {
  /* GYM-SCHEMAWISSEL-ZICHTBAAR-VOOR-COACH — wrap so the swap line can take a
     row of its own. The two original children never wrap: the day text
     ellipsises before it runs out of room, so a day without a swap renders
     byte-for-byte as it did. */
  flex: 1 1 100%; order: 3; display: flex; align-items: baseline; flex-wrap: wrap;
  gap: var(--space-2); font-size: 12px; line-height: 1.35; color: var(--ink-2);
  min-width: 0;
}
/* `flex: 1 1 0` (not the auto basis) is what keeps "Openen & bewerken" on the
   FIRST row now that the container wraps: with an auto basis a long day text
   would push the button onto a line of its own instead of ellipsising. */
.cweek__detail-txt { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cweek__detail-none { color: var(--muted); }
/* GYM-SCHEMAWISSEL-ZICHTBAAR-VOOR-COACH — the swap line takes a row of its own
   (order 4, full basis) instead of squeezing between the day text and Open &
   edit. It is information, not an alarm, so it stays in the muted voice: no
   colour, no badge, no icon. */
.cweek__detail-swap { flex: 1 1 100%; order: 4; color: var(--muted); }
.cweek__open {
  flex: 0 0 auto; margin-left: auto; padding: 0; border: 0; background: none;
  font: inherit; color: var(--accent); text-decoration: underline; cursor: pointer;
}

.cweek__sum {
  flex: 0 0 auto; order: 2; margin: 0; font-size: 12px; line-height: 1.35;
  color: var(--ink-2); text-align: right;
}
.cweek__sum b { color: var(--ink); font-weight: 700; }
.cweek--zero .cweek__sum { color: var(--muted); }
.cweek__warn { color: var(--muted); }
.cweek__warn + .cweek__warn::before { content: " · "; }
.cweek__retry {
  margin-left: var(--space-2); padding: 0; border: 0; background: none;
  font: inherit; color: var(--accent); text-decoration: underline; cursor: pointer;
}

/* DOSSIER-BLOKKEN-KIJKEN-NAAR-HUN-EIGEN-BREEDTE — de weekstrook woont in het
   Naleving-vel van het dossier, niet op een vrij scherm. De twee regels
   hieronder stonden op `@media (max-width: 639px)` en `@media (min-width: 1024px)`
   en lazen dus de viewport: op een laptop van 1280px kreeg de strook de
   LAPTOP-stand (dikkere ringen, dagen op 560px, samenvatting ernaast) in een vel
   van ~488px, en op een tablet van 768px de brede stand in datzelfde vel.
   Drempels in VAKbreedte: zeven dagkolommen vragen ~190px en de samenvatting
   ~230px, dus naast elkaar pas vanaf ~440px; de ruimere ringen plus een
   dagenstrook van 560px vragen een vak van ~680px (alleen het brede perio-vel
   haalt dat). */
@container dbox (max-width: 439.98px) {
  .cweek { flex-direction: column; align-items: stretch; gap: var(--space-2); }
  .cweek__sum { text-align: left; }
  /* Phone: the detail line belongs DIRECTLY under the day it describes; the
     week summary drops below it. On wider screens the summary keeps its place
     beside the dots and the detail line sits under both. */
  .cweek__detail { order: 1; }
  .cweek__sum { order: 2; }
}
@container dbox (min-width: 680px) {
  .cweek__ring { width: 22px; height: 22px; }
  .cweek__day.is-trained .cweek__core { width: 11px; height: 11px; }
  .cweek__day.is-trained.is-logged .cweek__core { width: 100%; height: 100%; }
  /* The hairline spans the full width; the circles do not. Seven dots smeared
     across a 2560px monitor reads as the fragmentation this strip replaces. */
  .cweek__days { flex: 0 1 560px; }
  .cweek__sum { margin-left: var(--space-5); text-align: left; }
}
/* DOSSIER-WAT-JE-MOET-WETEN-STAAT-BOVENAAN — the same ruler, now living at the
   top of the Naleving row. It loses the dossier gutter it was padded for, but it
   keeps its hairline: that line is exactly the separator the design draws
   between the week and the adherence numbers underneath it. */
.cadh > .cweek { padding-left: 0; padding-right: 0; }

/* Open-programs CTA → full-screen program-card view. */
.gym__progrow { display: flex; }
.gym__prog {
  flex: 1 1 auto; display: inline-flex; align-items: center; justify-content: center; gap: var(--space-1);
  padding: var(--space-2) var(--space-3); border-radius: var(--radius);
  border: 0; background: var(--accent); color: var(--on-accent);
  font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
}
.gym__prog:active { opacity: 0.85; }
.gym__prog svg { flex: 0 0 auto; }

/* Inline program + concept lists inside the gym panel. */
.gym__progs { display: flex; flex-direction: column; gap: var(--space-2); }
.gym__progs-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.gym__progs-title { margin: 0; font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }

/* COACH-GYM-VANDAAG-BOVENAAN-ALS-DAGKAART — the training door, and the FIRST
   interactive element of the gym panel. Jayy: "als ik op de gym-tab druk wil ik
   meteen iets in beeld krijgen in plaats van naar beneden scrollen en zoeken."
   Full width and two lines so it reads as a day, not as one more button in a
   row of buttons — there is no row any more, this is the only primary here.
   Selector is .gym-today.cbtn and not .gym-today: .cbtn is declared ~2300 lines
   further down and centres its content, which would pull the lines to the middle. */
.gym-today.cbtn {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  width: 100%; min-height: 56px; text-align: left;
  padding: var(--space-3); margin-bottom: var(--space-3);
}
.gym-today__lines { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.gym-today__day { font-size: 15px; font-weight: 600; }
/* Inherits the button's --on-accent ink; dim it rather than recolouring, so the
   contrast protocol keeps holding on both themes. */
.gym-today__state { font-size: 12px; font-weight: 500; opacity: 0.8; }
.gym-today > svg { flex: 0 0 auto; }

/* PLANNER-PERIODISERING-STAAT-BOVENAAN-GYM-EN-DE-RUIS-IS-WEG — the plan sits
   ABOVE the day card: it is the answer to "where is this client heading", which
   is what a coach opens the Gym tab for. Deliberately NOT a .cbtn: the day card
   below is the only filled button on this panel, so this one is a bordered card
   that reads as a surface you can tap, like .gym__prog-row does. */
.gym__perio {
  display: flex; align-items: center; gap: var(--space-3);
  width: 100%; min-height: 56px; text-align: left;
  padding: var(--space-3); margin-bottom: var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); cursor: pointer;
}
.gym__perio > svg { flex: 0 0 auto; color: var(--accent); }
.gym__perio > svg:last-child { color: var(--muted); margin-left: auto; }
.gym__perio-lines { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.gym__perio-title { font-size: 15px; font-weight: 600; }
/* One reserved line: the sentence arrives after its own fetch, and a card that
   grows while the coach is reading the list under it is worse than a blank. */
.gym__perio-sub { font-size: 13px; line-height: 1.3; min-height: 1.3em; color: var(--ink-2); }
/* The week strip. Boxes, not a progress bar: weeks are countable things the
   coach plans one at a time, and a bar would claim a completion we do not know. */
.gym__perio-strip { display: flex; flex-wrap: wrap; gap: 3px; margin-top: 2px; }
.gym__perio-wk {
  width: 14px; height: 6px; border-radius: 2px;
  background: var(--line);
}
.gym__perio-wk.is-now { background: var(--accent); }
.gym__proglist { display: flex; flex-direction: column; gap: var(--space-2); }
.gym__progs-note { margin: 0; font-size: 13px; color: var(--muted); }
.gym__prog-row {
  display: flex; align-items: center; gap: var(--space-3); width: 100%; min-height: 48px;
  padding: var(--space-2) var(--space-3); border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); font: inherit; font-size: 14px;
  text-align: left; cursor: pointer;
}
.gym__prog-row:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.gym__prog-row > svg { flex: 0 0 auto; margin-left: auto; color: var(--muted); }
.gym__prog-name { flex: 1 1 auto; min-width: 0; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* PROGRAM-VISIBILITY-FOUNDATION-COACH-KEBAB — the row plus its ONE settings
   kebab. The kebab sits OUTSIDE the row button: a button inside a button is
   invalid HTML and would swallow the row's own open-player click. */
.gym__prog-item { display: flex; align-items: center; gap: var(--space-1); position: relative; }
.gym__prog-item > .gym__prog-row { flex: 1 1 auto; min-width: 0; width: auto; }
/* The chevron's margin-left:auto would eat the free space before .gym__prog-name
   can grow, stranding the flag mid-row; let the name push instead. */
.gym__prog-item .gym__prog-row > svg { margin-left: 0; }
/* COACH-BOUW-AFRONDING-EIGEN-LIJST — the row the coach just built lands marked,
   with its next step on its own line underneath (hence the wrap; the base item
   stays a single flex line). */
.gym__prog-item--justbuilt { flex-wrap: wrap; }
.gym__prog-item--justbuilt > .gym__prog-row {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}
.gym__prog-next { flex: 1 0 100%; justify-content: center; min-height: 40px; }
/* Bare text on purpose — status without inventing a badge component. */
.gym__prog-flag { flex: 0 0 auto; font-size: 12px; color: var(--muted); }
.gym__prog-more { flex: 0 0 auto; position: relative; }
.gym__prog-kebab {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 40px; padding: 0; border: 0; border-radius: var(--radius);
  background: transparent; color: var(--muted); cursor: pointer;
}
.gym__prog-kebab:hover { background: var(--line-2); color: var(--ink); }
.gym__prog-kebab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.gym__prog-menu {
  position: absolute; right: 0; top: calc(100% + 4px); z-index: 20;
  min-width: 210px; padding: var(--space-1);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
}
.gym__prog-menuitem {
  display: flex; align-items: center; gap: var(--space-2);
  width: 100%; box-sizing: border-box; text-align: left;
  border: 0; background: transparent; color: var(--ink); cursor: pointer;
  padding: var(--space-2) var(--space-3); font-size: 0.85rem; font-weight: 600;
  border-radius: calc(var(--radius) - 2px);
}
.gym__prog-menuitem > svg { flex: 0 0 auto; color: var(--muted); }
.gym__prog-menuitem:hover { background: var(--line-2); }
/* GYM-PROGRAM-KEBAB-ACTIONS — Delete is the one irreversible item, so it is
   last, red, and separated by a rule: the eye has to cross a line to reach it. */
.gym__prog-menuitem--danger {
  color: var(--danger);
  margin-top: var(--space-1);
  border-top: 1px solid var(--line);
  border-radius: 0 0 calc(var(--radius) - 2px) calc(var(--radius) - 2px);
}
.gym__prog-menuitem--danger > svg { color: inherit; }
.gym__prog-menuitem--danger:hover { background: color-mix(in srgb, var(--danger) 12%, transparent); }
/* The collapsed archive line under the program list. */
.gym__archive { margin-top: var(--space-2); }
.gym__archive-sum {
  cursor: pointer; list-style: none; padding: var(--space-2) 0;
  font-size: 0.8rem; font-weight: 600; color: var(--muted);
}
.gym__archive-sum::-webkit-details-marker { display: none; }
.gym__archive-sum::before { content: '▸ '; }
.gym__archive[open] > .gym__archive-sum::before { content: '▾ '; }
.gym__archlist { display: flex; flex-direction: column; gap: var(--space-1); }
.gym__arch-row {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  color: var(--muted);
}
/* DE-COACH-ZET-EEN-SCHEMA-OOK-WEER-TERUG — name over date, so the row answers
   "which one, and when did I put it away" before the coach opens anything. Its
   own class, not the neighbouring row's: .gym__arch-row is a flex ROW and the
   pair inside it stacks. */
.gym__arch-names { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.gym__arch-when { font-size: 0.75rem; color: var(--muted); }
.gym__arch-restore {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px;
  border: 0; background: transparent; color: var(--accent); cursor: pointer;
  font-size: 0.8rem; font-weight: 600; padding: 4px 6px; border-radius: var(--radius);
}
.gym__arch-restore:hover { background: var(--line-2); }
.gym__arch-restore[disabled] { opacity: 0.5; cursor: default; }
/* DE-TRAINING-VAN-BASILIOS-KOMT-TERUG — the removed-TRAININGS drawer. Same
   shape as the archive above it so the two read as one family, but its own
   classes throughout: two drawers wearing one class would make every later
   querySelector depend on which mounted first. */
.gym__binlist { display: flex; flex-direction: column; gap: var(--space-1); }
.gym__bin-row {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  color: var(--muted);
}
.gym__bin-names { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.gym__bin-when { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gym__bin-meta { font-size: 0.75rem; color: var(--muted); }
.gym__bin-restore {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px;
  border: 0; background: transparent; color: var(--accent); cursor: pointer;
  font-size: 0.8rem; font-weight: 600; padding: 4px 6px; border-radius: var(--radius);
}
.gym__bin-restore:hover { background: var(--line-2); }
.gym__bin-restore[disabled] { opacity: 0.5; cursor: default; }
/* Duplicate's "Who for?" options — one tap target per destination. */
.gym__duplist { display: flex; flex-direction: column; gap: var(--space-1); margin-top: var(--space-2); }
.gym__dup-opt {
  display: flex; align-items: center; gap: var(--space-2);
  width: 100%; box-sizing: border-box; text-align: left; min-height: 44px;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: transparent; color: var(--ink); cursor: pointer; font-weight: 600;
}
.gym__dup-opt > svg { flex: 0 0 auto; color: var(--muted); }
.gym__dup-opt:hover { background: var(--line-2); }
.gym__dup-opt[disabled] { opacity: 0.5; cursor: default; }
/* Delete's own buttons. The permanent path is a plain red link, never a filled
   button — the filled primary in that dialog belongs to Archive. */
.gym__prog-danger-btn { background: var(--danger); color: #fff; }
.gym__prog-danger-link {
  display: block; width: 100%; margin-top: var(--space-2);
  border: 0; background: transparent; color: var(--danger);
  font-size: 0.85rem; font-weight: 600; cursor: pointer; padding: var(--space-2);
}
.gym__prog-danger-link:hover { text-decoration: underline; }
.gym__prog-menunote { margin: 0; padding: var(--space-2) var(--space-3); font-size: 0.85rem; color: var(--muted); }
/* COACH-GYM-VANDAAG-BOVENAAN-ALS-DAGKAART — New schema now sits in the Programs
   header, so it is a compact inline control, no longer a full-width row. */
.gym__new-schema {
  display: inline-flex; align-items: center; gap: var(--space-1);
  flex: 0 0 auto; min-height: 34px; padding: var(--space-1) var(--space-2);
}
.gym__new-schema > svg { flex: 0 0 auto; }
/* COACH-GYM-PANEL-PLAYER-EMBED — the panel body becomes a flex column so the
   embedded strength iframe fills whatever height the dossier panel offers. */
.gym__player { display: flex; flex-direction: column; gap: var(--space-3); min-height: 0; height: 100%; }
/* COACH-SNELLE-NOTITIE-EN-MACRO-BLIK — the coach bar: back · injury · goal ·
   dots · note · sheet, on ONE line always. flex-wrap is gone on purpose — the
   goal line shrinks to nothing before the bar is allowed to take a second row,
   because a wrapping bar pushed the player down mid-set. */
.gym__player-bar { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
.gym__player-back,
.gym__player-sheet,
.gym__player-abort,
.gym__player-col,
.gym__player-fs,
.gym__player-mob,
.gym__ctx-open,
.gym__ctx-injury,
.gym__ctx-note,
.gym__ctx-dots,
.gym__ctx-goal { min-height: 48px; gap: var(--space-2); flex: 0 0 auto; }
.gym__player-back:focus-visible,
.gym__player-sheet:focus-visible,
.gym__player-abort:focus-visible,
.gym__player-col:focus-visible,
.gym__player-fs:focus-visible,
.gym__player-mob:focus-visible,
.gym__ctx-open:focus-visible,
.gym__ctx-injury:focus-visible,
.gym__ctx-note:focus-visible,
.gym__ctx-dots:focus-visible,
.gym__ctx-goal:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.gym__ctx-slot { display: contents; }
/* COACH-GYM-PLAYER-SCHERMVULLEND-EN-TERUG — de icoonhouder van de maatschakelaar
   wisselt van pijlrichting; display:flex houdt het icoon gecentreerd in de 34px
   knop zoals de knoppen die hun svg direct dragen. */
.gym__player-fs-icon { display: flex; align-items: center; justify-content: center; }
.gym__ctx-injury { color: var(--danger); }
/* COACH-GYM-BALK-BEGROTING-VIJF — an injury on file tints the ONE context
   button; a warning that only exists behind a tap is a warning nobody reads. */
.gym__ctx-open.is-alert { color: var(--danger); }
/* Stop is the only non-reversible way out of this bar. It gets the danger tint
   AND the far end of the row, so it never sits shoulder to shoulder with Back
   at the same 48px weight in the same thumb arc. */
/* COACH-DOSSIER-DUIDELIJKE-KNOPPEN-EN-UITGANG — a tint alone still reads as one
   of the grey icons at arm's length; the wash + danger border make it a
   different KIND of button. No hardcoded colour: both derive from --danger.
   GEMETEN: het oude `.gym__player-abort{color:var(--danger)}` had NOOIT effect —
   `.cbtn--secondary` staat verderop in dit bestand met dezelfde soortelijkheid en
   zet color/background/border terug. Vandaar de balk-scope ervoor. */
.gym__player-bar .gym__player-abort {
  color: var(--danger); margin-left: auto;
  border-color: color-mix(in oklab, var(--danger) 45%, transparent);
  background: color-mix(in oklab, var(--danger) 10%, transparent);
}
/* The four readers, stacked in the one context sheet. */
.gym__ctxs-sec { padding: var(--space-3) 0; border-top: 1px solid var(--line); }
.gym__ctxs-sec:first-child { border-top: 0; padding-top: 0; }
.gym__ctxs-h { margin: 0 0 var(--space-2); font-size: 14px; color: var(--ink); }
/* GYM-DE-COACH-ZIET-DE-BEWEGINGSANALYSE-IN-DE-SPELER — de lege staat in het blad
   over de speler: nooit gemeten is geen storing, dus geen dangerkleur. Het icoon
   draagt de accentkleur, de regel eronder zegt het, en de knop ernaast is
   secundair — de coach staat midden in een training. */
.gym__mobempty {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: var(--space-2); padding: var(--space-4) 0 var(--space-3);
}
.gym__mobempty > svg { color: var(--accent); }
.gym__mobempty-h { margin: 0; font-weight: 700; color: var(--ink); }
.gym__mobempty-btn { min-height: 48px; }
/* GYM-HET-SPELERBLAD-TOONT-DE-HELE-ANALYSE — het blad draagt de HELE
   overzichtstabel, uit dezelfde tekenaar als het scherm. Lettergroottes en het
   raster van .ba-ov__* worden hier NIET aangeraakt: "precies hetzelfde" is de
   opdracht, dus het omhulsel regelt alleen zijn eigen lucht. .csheet__body is een
   flex-kolom met gap, en zonder dit omhulsel zou elk gewrichtsblok die gap erbij
   krijgen. De aanleidingsregel heeft in het blad geen kop boven zich, dus zij
   krijgt haar eigen marge in plaats van de --space-4 van het scherm. */
.ba-peek__ov { padding-bottom: var(--space-2); }
.ba-peek__ov .ba-ov__lead { margin-top: var(--space-2); }
.gym__mobfull { width: 100%; min-height: 48px; justify-content: space-between; font-size: 14px; }
/* Een lange analyse (acht gewrichten) scrollt in het blad. Zonder dit draagt iOS
   die scroll aan het eind door naar het dossier en de speler erachter — cosmetisch,
   maar het ZIET eruit alsof de training beweegt. */
.csheet--coachbar .csheet__panel { overscroll-behavior: contain; }
/* The one element allowed to give up width, down to zero. */
.gym__ctx-goal { flex: 1 1 auto; min-width: 0; justify-content: flex-start; padding: 0 var(--space-2); }
.gym__ctx-goal-txt {
  display: block; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  font-size: 13px; color: var(--ink-2);
}
.gym__ctx-dots { display: flex; align-items: center; gap: 4px; margin-left: auto; padding: 0 var(--space-2); }
.gym__ctx-dots .cadh__dot { margin-top: 0; }
/* No data is a RING, never a filled grey dot: a filled dot reads as "measured
   and fine" for something we have not measured at all. */
.gym__ctx-dots .cadh__dot--none { background: transparent; box-shadow: inset 0 0 0 2px var(--muted); }
.gym__ctx-nodata { font-size: 12px; color: var(--muted); }
/* The bar's sheets must clear the sheet-escape fullscreen shell (z-index 50). */
.csheet--coachbar { z-index: 70; }
/* Height is written inline from the viewport in showPlayer(); this is the floor. */
/* COACH-PLAYER-IPHONE-IPAD-BASIS — 240px, not 420: a 420px floor guarantees a
   stage taller than an iPhone in landscape (~390px visible), so the page below
   scrolled instead of the schema. */
.gym__player-stage { display: flex; flex: 1 1 auto; min-height: 240px; position: relative; }
.gym__player-frame { flex: 1 1 auto; width: 100%; border: 0; }
/* PLANNER-EEN-FASE-BEWERK-JE-IN-DE-GEWONE-SCHEMABOUWER — de publiceerbalk boven
   het frame als de bouwer een werkkopie open heeft. flex-shrink:0 is dragend: de
   stage eronder is `flex:1 1 auto`, dus zonder dit krimpt de balk op een korte
   telefoon weg tot een streep. De warn-tint zegt "dit staat nog niet bij de
   klant" zonder het woord te hoeven herhalen; de knop is een gewone
   .cbtn--primary en haalt zijn tekstkleur dus uit --on-accent. */
.gym__draftbar {
  flex: 0 0 auto;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--space-2); padding: var(--space-2) var(--space-3);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--warn) 14%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--warn) 45%, var(--line));
}
.gym__draftbar-txt { font-size: 0.9rem; font-weight: 600; color: var(--ink); min-width: 0; }
.gym__draftbar-pub { min-height: 44px; }
/* PLANNER-DE-BEWEGINGSANALYSE-KRIJGT-EEN-EIGEN-BAAN — "ook in de mobiliteitsbaan".
   Een eigen REGEL in de balk (flex-basis 100% in een wrappende balk) en niet naast
   de knop: hij staat standaard aan, dus de coach moet hem kunnen lezen voordat hij
   publiceert, en naast de knop zou hij op 390px wegvallen. 44px hoog, want het is
   een aantikbaar ding. */
.gym__draftbar-mob {
  flex: 1 1 100%; display: flex; align-items: center; gap: var(--space-2);
  min-height: 44px; font-size: 0.85rem; font-weight: 600; color: var(--ink);
  cursor: pointer;
}
.gym__draftbar-mob input { width: 20px; height: 20px; flex: none; accent-color: var(--accent); }
/* DOSSIER-BLOKKEN-KIJKEN-NAAR-HUN-EIGEN-BREEDTE — de conceptbalk staat in de
   speler in het Gym-paneel. Op `@media (max-width: 759px)` las hij de viewport:
   op een laptop van 1280px (paneel ~350px) kreeg de knop zijn SMALLE-scherm-
   uitzondering NIET en werd hij de sliver waar deze regel juist tegen is.
   Drempel 480px vakbreedte: daaronder past er niets naast de knop. */
@container dbox (max-width: 479.98px) {
  .gym__draftbar-pub { width: 100%; }
}
/* Top-anchored strip, never a blanket: the frame underneath keeps loading and
   must stay visible + interactive, so only the button takes pointer events. */
.gym__player-wait {
  position: absolute; top: 0; left: 0; right: 0; z-index: 2;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: var(--space-2); padding: var(--space-2);
  background: var(--surface); color: var(--ink);
  border-bottom: 1px solid var(--line);
  pointer-events: none;
}
.gym__player-wait-text { font-size: 0.9rem; }
/* pointer-events:auto is load-bearing: the wrapper above is pointer-events:none
   so the still-loading frame stays usable underneath. */
.gym__player-reload,
.gym__player-cancel { min-height: 48px; pointer-events: auto; }
.gym__player-reload:focus-visible,
.gym__player-cancel:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* COACH-GYM-SHEET-FULLSCREEN-ESCAPE — the sheet-escape promotes the SAME gym
   container to a fullscreen shell (same fixed/inset/z-index idiom as .csheet at
   line ~1844). #fz-sheet-page inside the iframe is position:fixed, so it hooks
   onto the iframe viewport and fills whatever size we hand the frame — the
   player is never forked. Placed AFTER the .gym__player base rules so these
   declarations win the cascade at equal specificity. */
/* COACH-PLAYER-EEN-SCROLLGEBIED — bottom:auto + the dvh ladder instead of
   inset:0: standalone on coach.sassu.fit this IS the top document, and on iOS
   bottom:0 resolves to the LARGE viewport, so the bottom of the sheet sat under
   the collapsing URL bar. --coach-vh: see the seam with
   COACH-PLAYER-IPHONE-IPAD-BASIS. */
.dossier--sheet-fullscreen { position: fixed; top: 0; left: 0; right: 0; bottom: auto;
  height: 100vh; height: var(--coach-vh, 100dvh); z-index: 50; background: var(--bg);
  /* COACH-PLAYER-IPHONE-IPAD-BASIS — this shell covers the whole screen edge,
     Dynamic Island and home indicator included, and reserved nothing. Standalone
     env() yields the real insets; inside the shell it is 0, which is exactly
     right there because app.css already reserves outside the iframe. One block,
     self-regulating, no fork. box-sizing:border-box is global (coach.css:72). */
  padding-top: env(safe-area-inset-top, 0px);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  padding-left: env(safe-area-inset-left, 0px);
  padding-right: env(safe-area-inset-right, 0px); }
/* GYM-HET-DOSSIER-HOUDT-DE-COACHBALK-ALLEEN-DE-SPELER-IS-VOLSCHERM (L225) —
   vergroten is nu ECHT volscherm: met de balk weg (html.coach-bar-off) mag deze
   aftrek niet meer gelden, anders bleef er een strook over waar niets staat.
   --coach-navh is dan toch 0; de guard houdt de regel eerlijk in plaats van
   afhankelijk van de meetvolgorde. Basisregel hierboven valt terug op --coach-vh. */
html:not(.coach-bar-off) body.has-coachnav .dossier--sheet-fullscreen { height: calc(var(--coach-vh, 100dvh) - var(--coach-navh, 64px) - var(--safe-bottom)); }
.dossier--sheet-fullscreen .gym__player { height: 100%; gap: 0; }
/* !important beats the inline viewport height showPlayer() writes on the stage —
   the stage flexes to the space left under the control bar and the frame
   stretches with it. NOT 100vh on the frame: the bar sits above it inside the
   inset-0 shell, so a viewport-height frame overflowed the screen by the bar
   height and pushed the sheet's own bottom-anchored UI (edit action bar,
   add-exercise sheet) below the fold (iPad, 2026-08-04). */
.dossier--sheet-fullscreen .gym__player-stage { min-height: 0; height: auto !important; }
.dossier--sheet-fullscreen .gym__player-frame { width: 100%; height: 100%; min-height: 0; border: 0; }
body.gym-fullscreen { overflow: hidden; }

/* COACH-TIMERS-ECHT-SCHERMVULLEND — on top of the sheet-fullscreen shell, a
   running timer also drops the coach's own control row, so the frame is the
   entire promoted surface and the timer overlay inside it finally reaches every
   edge. Placed after the .dossier--sheet-fullscreen block so it wins at equal
   specificity. The !important beats the inline viewport height fitStage()
   writes on the stage — same reason as the rule above. */
.dossier--timer-fullscreen .gym__player-bar { display: none; }
.dossier--timer-fullscreen .gym__player-stage { min-height: 0; height: auto !important; }

/* COACH-PLAYER-EEN-SCROLLGEBIED — zolang de player leeft is de coach-pagina
   een schil met vaste hoogte: html/body scrollen niet, #coach is één
   viewporthoogte, en de dossierkolommen zijn de flexibele rest. Er blijft
   precies één scroller over per kolom, en in de Gym-kolom zit die scroller
   binnen het iframe (.fz-pp-scroll). Nested scrollers repareer je niet door de
   binnenste exact uit te rekenen (dat is wat fitStage doet en het breekt bij de
   eerste chrome-hoogte die verandert) maar door de buitenste te laten ophouden
   een scroller te zijn. --coach-vh: zie de seam met
   COACH-PLAYER-IPHONE-IPAD-BASIS — die fase bezit het GETAL in de token, deze
   fase de layout eromheen. */
.gym-player-open,
.gym-player-open body { height: 100%; overflow: hidden; overscroll-behavior: none; }
.gym-player-open #coach {
  display: flex; flex-direction: column;
  height: 100vh;                 /* fallback, moet BOVEN de dvh-regel blijven */
  height: var(--coach-vh, 100dvh);
  min-height: 0;
}
.gym-player-open .cshell { flex: 0 0 auto; }
.gym-player-open body.has-coachnav #coach { padding-bottom: calc(var(--coach-navh, 64px) + var(--safe-bottom)); }
/* COACH-GYM-TOETSENBORD-GEEN-LEGE-STROOK-STANDALONE — body.kb-open werd door
   coach.js:1509 wél gezet maar door GEEN ENKELE regel in dit bestand gelezen:
   dode bedrading die werkend uitzag (app.css:1447 heeft hem al jaren, de
   coach-app erfde die gewoonte niet). Gevolg: de vaste balk bleef bestaan
   onder het toetsenbord, en de reservering hierboven bleef zijn hoogte
   vasthouden BINNEN een #coach waar fitStage het toetsenbord via --coach-vh al
   vanaf had gehaald — weggegooide hoogte, dus de kolomkop werd afgeknipt. */
.gym-player-open body.kb-open .coachnav { display: none; }
.gym-player-open body.has-coachnav.kb-open #coach { padding-bottom: 0; }
/* COACH-GYM-TOETSENBORD-DUWT-NIETS-WEG — deze regel MOET de has-coachnav-regel
   op .cmain hierboven verslaan, vandaar body.has-coachnav in de selector: die
   woog zwaarder (0,2,1 tegen 0,2,0) en reserveerde de balk een TWEEDE keer,
   bovenop de padding die #coach hierboven al neemt. Gemeten op 2026-08-18: ~97px
   lege ruimte onder het dossier waar je niet eens heen kon scrollen, precies de
   witte strook uit de foto. Die ruimte vloeit nu naar het schema. */
/* DOSSIER-KOP-ZEGT-HOE-HET-GAAT — `width: 100%` is hier geen opmaak maar een
   reparatie, en wel van hetzelfde soort als bevinding #10 van de L183-audit:
   `.cmain` draagt `margin: 0 auto`, en een flex-item met automarges op de
   DWARSAS van een kolom rekt niet mee maar krimpt tot zijn inhoud. In
   spelerstand is #coach zo'n kolom, dus stond het schema op een breed scherm in
   een kolom zo breed als de langste tekst erboven toevallig was — gemeten op
   1180px: 334px kolom, 77px schemavak. Dat viel niemand op zolang er een lange
   regel boven stond die hem toevallig breed hield; zodra die regel verhuisde,
   zakte het vak naar 0 en was de speler onzichtbaar. De iPad-tak hieronder
   (html[data-ipad]) deed dit al met de hand; dit is diezelfde regel voor elk
   ander breed scherm. */
.gym-player-open .cmain,
.gym-player-open body.has-coachnav .cmain {
  flex: 1 1 auto; min-height: 0;
  width: 100%;
  display: flex; flex-direction: column;
  /* Nul, niet 'klein': #coach reserveert de balk hierboven al één keer. Elke
     pixel die hier nog bij komt is opnieuw weggegooide ruimte onder het schema. */
  padding-bottom: 0;
}
.gym-player-open .dossier-seg { position: static; flex: 0 0 auto; }
.gym-player-open .dossier { flex: 1 1 auto; min-height: 0; }
.gym-player-open .dossier__panel {
  min-height: 0; height: 100%;
  overflow-y: auto; overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
/* De Gym-kolom scrolt ZELF niet: hij is een flexkolom waarvan de stage de
   rest opvult. Zou hij wel scrollen, dan hadden we de bug terug. */
.gym-player-open .dossier__panel--player { overflow: hidden; display: flex; flex-direction: column; }
.gym-player-open .dossier__panel--player .gym,
.gym-player-open .gym__player { flex: 1 1 auto; min-height: 0; }
.gym-player-open .gym__player-bar { flex: 0 0 auto; }
/* height:auto !important verslaat de inline hoogte die fitStage op de stage
   schrijft — zelfde truc, zelfde reden als .dossier--sheet-fullscreen hierboven. */
.gym-player-open .gym__player-stage { flex: 1 1 auto; min-height: 0; height: auto !important; }
.gym-player-open .gym__player-frame { height: 100%; min-height: 0; }
/* Panelvolgorde is client | gym | nutrition (coach.js DOSSIER_PANELS), dus
   grip--a en grip--pair hebben het schema RECHTS, grip--b heeft het LINKS. De
   onzichtbare 45px greep draagt touch-action:none; schuif hem wég van het
   schema zodat een duim vlak naast de naad het schema scrolt. Totale 45px
   blijft, dus het HIG-minimum blijft gehaald. */
.gym-player-open .dossier__grip--pair::before,
.gym-player-open .dossier__grip--a::before { left: -42px; right: 0; }
.gym-player-open .dossier__grip--b::before { left: 0; right: -42px; }

/* COACH-GYM-IPAD-VERLIEST-DE-TELEFOONBEGROTING — de dossierkop + weekstrip
   verdwijnen zolang het schema openstaat, op ELKE breedte. Dit stond in een
   max-width:639px-query terwijl de redenering nergens aan de telefoon hing:
   chrome die tijdens het loggen niets te zoeken heeft. Gemeten op iPad liggend
   (1024x768) kostte die uitzondering 142px van 282px werkvlak. De schakelbalk
   (de uitgang), de knoppenrij en de coach-tabbalk blijven.

   EEN-DOSSIERKOP-DIE-ZEGT-MET-WIE-JE-BEZIG-BENT — die redenering blijft gelden
   voor de terugknop en de weekstrip, maar NIET voor "met wie ben ik bezig": met
   het schema open verdween ook de naam, en dan zit je te loggen zonder te zien
   in wiens dossier je staat. De naam en de kebab blijven daarom staan, in
   afgeslankte vorm — één regel, kleinere letter, afgekapt bij lange namen. Dat
   kost minder dan de .cfile-seg-rij die deze fase heeft weggehaald, dus netto
   staat er MINDER chrome dan hiervoor. De terugknop is niet weg maar verhuisd
   naar datzelfde kebabmenu, zodat er geen uitgang verdwijnt. */
.gym-player-open .cweek { display: none; }
/* DOSSIER-WAT-JE-MOET-WETEN-STAAT-BOVENAAN — same budget, same reason: with the
   player open the screen belongs to the set you are logging, and the
   correspondence card now stands where the week ruler used to. */
.gym-player-open .dcorr { display: none; }
/* And its seam with it: a grabber for a card that is not on the screen is a
   control over nothing, and its invisible 36px reach would sit right on top of
   the player's own first row. */
.gym-player-open .dcorr-grip { display: none; }
.gym-player-open .cpage-head:not(.cpage-head--dossier) { display: none; }
.gym-player-open .cpage-head--dossier {
  flex-wrap: nowrap; margin-bottom: var(--space-2);
}
.gym-player-open .cpage-head--dossier .cpage-head__back { display: none; }
.gym-player-open .cpage-head--dossier .cpage-head__title {
  flex: 1 1 auto;
  font-size: 15px; line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.gym-player-open .cpage-head--dossier .cpage-head__action--icon {
  width: 28px; height: 28px;
}

/* COACH-GYM-PANEL-EDGE-TO-EDGE — in player mode the panel drops its own padding
   so the schema iframe fills the box border-to-border (Jayy: the schema looked
   squeezed shut). Only the .gym wrap goes flush; the panel's other children (the
   "Gym" heading, the North Star block) keep the inset they had, and the player's
   own control row keeps one so the buttons don't touch the border. That inset is
   --space-4, NOT --space-3: it is load-bearing against the split grip's 16px
   invisible overlay reach — see .dossier__grip::before for the arithmetic. */
.dossier__panel--player { padding: 0; }
.dossier__panel--player > *:not(.gym) { padding-left: var(--space-4); padding-right: var(--space-4); }
/* COACH-SNELLE-NOTITIE-EN-MACRO-BLIK — the full goal editor ate roughly a third
   of a phone screen while the coach was logging sets. It stays MOUNTED (its
   fetch and half-typed edits survive) and simply leaves the screen for the
   duration of the player; the goal is one line in the coach bar meanwhile.
   showList() drops the class and the editor is back, unchanged. */
/* COACH-GYM-BALK-BEGROTING-VIJF — in player mode the bar already says where you
   are, so the "Gym" heading is a second state label for the same state. Hidden
   for the same reason and in the same way as the North Star block below. */
.dossier__panel--player > .dossier__panel-title { display: none; }
.dossier__panel--player > .northstar--gym { display: none; }
/* COACH-GYM-VANDAAG-BOVENAAN-ALS-DAGKAART — the day card leaves for the same
   reason: while the player is open the coach is already IN today, so a door
   into it is noise. Its own rule, because a source-pin greps the line above. */
.dossier__panel--player > .gym-today { display: none; }
/* DOSSIER-GYM-BEWEGINGSANALYSE-KAART — same reasoning for the card under it:
   while the player fills the panel, a second door is noise. */
.dossier__panel--player > .gym-ba { display: none; }
/* PLANNER-PERIODISERING-STAAT-BOVENAAN-GYM-EN-DE-RUIS-IS-WEG — and for the
   periodisation card above them both. */
.dossier__panel--player > .gym__perio { display: none; }
/* COACH-DOSSIER-IPAD-VULT-HET-SCHERM-EN-GEEN-PANEELKOP — nagerekend: het eerste
   kind IS de kop, en die staat in de spelerstand al op display:none, dus deze
   padding landde daar toen al op een onzichtbaar element. De kop draagt sinds
   deze fase óók u-sr-only (positie absoluut), wat aan die uitkomst niets
   verandert: :first-child blijft de kop, de regel blijft inert. Bewust NIET
   verlegd — hem naar het eerstvolgende kind schuiven zou de spelerstand een
   bovenmarge geven die hij vandaag niet heeft. */
.dossier__panel--player > *:first-child { padding-top: var(--space-4); }
/* COACH-GYM-BALK-BEGROTING-VIJF — the bar's own top inset plus .gym__player's
   12px column gap was 24px of nothing between the controls and the schema. The
   inset shrinks and the gap goes to zero; that height goes back to the log. */
.dossier__panel--player .gym__player-bar { padding: var(--space-2) var(--space-4) 0; }
.dossier__panel--player .gym__player { gap: 0; }

/* COACH-GYM-IPAD-VERLIEST-DE-TELEFOONBEGROTING — vanaf 1024px staat de
   coachbalk RECHTOP naast het speelvlak in plaats van erboven. De verticale
   kosten van de balk worden nul; de horizontale kosten zijn 48px die de iPad
   ruim heeft. Onder 1024px blijft hij liggen zoals hij lag — daar is 48px
   breedte duurder dan 48px hoogte. */
@media (min-width: 1024px) {
  .gym-player-open .dossier__panel--player .gym__player { flex-direction: row; }
  .gym-player-open .dossier__panel--player .gym__player-bar {
    flex-direction: column; align-items: stretch;
    width: 48px; flex: 0 0 48px;
    padding: var(--space-2) 0 var(--space-2) var(--space-2);
    gap: var(--space-1);
  }
  /* De twee LEZERS in de balk (doellijn, adherentie-stippen) passen niet in
     48px en horen daar ook niet: ze staan alle vier al onder de contextknop.
     Alleen de vijf tikbare dingen blijven op de rail. */
  .gym-player-open .dossier__panel--player .gym__ctx-goal,
  .gym-player-open .dossier__panel--player .gym__ctx-dots { display: none; }
  /* Stop houdt de verste hoek van de rij — die rij loopt nu omlaag. */
  .gym-player-open .dossier__panel--player .gym__player-abort {
    margin-left: 0; margin-top: auto;
  }

  /* PLANNER-EEN-FASE-BEWERK-JE-IN-DE-GEWONE-SCHEMABOUWER — de publiceerbalk hoort
     BOVEN het speelvlak, en hierboven is de speler vanaf 1024px een RIJ geworden.
     Een derde kind landt daar dus NAAST de rail en het speelvlak: gemeten op 1280
     werd de balk een volle-hoogte kolom die het frame tot een sliver kneep en de
     bouwer onbereikbaar maakte (UAT flow 2, stap 8, alleen desktop rood).
     Daarom hier een raster zodra er een balk IS: de rail houdt links beide rijen,
     de balk pakt de bovenrij rechts, het speelvlak de rest. Zonder balk verandert
     er niets — `:has` doet elders in dit bestand al hetzelfde werk. */
  .gym-player-open .dossier__panel--player .gym__player:has(> .gym__draftbar) {
    display: grid;
    grid-template-columns: 48px minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
    column-gap: 0; row-gap: var(--space-2);
  }
  .gym-player-open .dossier__panel--player .gym__player:has(> .gym__draftbar) > .gym__player-bar {
    grid-column: 1; grid-row: 1 / -1;
  }
  .gym-player-open .dossier__panel--player .gym__player > .gym__draftbar {
    grid-column: 2; grid-row: 1;
  }
  .gym-player-open .dossier__panel--player .gym__player:has(> .gym__draftbar) > .gym__player-stage {
    grid-column: 2; grid-row: 2;
  }

  /* .cmain draagt vanaf 640px `margin: 0 auto`, en een auto-marge op de dwarsas
     van een flexkolom zet stretch UIT: de kolom wordt fit-content. Met twee
     panelen viel dat niet op; met de ene 1fr-kolom hieronder klapt hij in tot
     de breedte van de knoppenrail — 255px in plaats van 1024, gemeten in de
     mock. Dus eerst de marge weg, dan pas de grid. */
  html[data-ipad].gym-player-open .cmain { width: 100%; max-width: none; margin: 0; }
  /* De gym-kolom pakt in playerstand de hele .cmain. De klantkolom komt terug
     via de rail-knop hieronder, die data-playercol zet. */
  html[data-ipad].gym-player-open .dossier { grid-template-columns: minmax(0, 1fr); }
  html[data-ipad].gym-player-open .dossier:not([data-playercol="1"]) .dossier__panel[data-panel="client"],
  html[data-ipad].gym-player-open .dossier:not([data-playercol="1"]) .dossier__panel[data-panel="nutrition"],
  html[data-ipad].gym-player-open .dossier:not([data-playercol="1"]) .dossier__grip--pair { display: none; }
  html[data-ipad].gym-player-open .dossier[data-playercol="1"] {
    grid-template-columns: minmax(0, calc(var(--dossier-split, 50%) - var(--section-gap) / 2)) minmax(0, 1fr);
  }
  /* De segmentbalk verdwijnt in playerstand: zijn functie zit in de rail. Dit
     mag ALLEEN hier, waar die rail bestaat — op de telefoon is de segmentbalk
     de enige uitgang uit het schema. */
  html[data-ipad].gym-player-open .dossier-pair,
  html[data-ipad].gym-player-open .dossier-seg { display: none; }
}
/* De rail-knop bestaat alleen waar de rail bestaat. */
.gym__player-col { display: none; }
/* GYM-DE-COACH-ZIET-DE-BEWEGINGSANALYSE-IN-DE-SPELER — GEMETEN: de regel hierboven
   had in de balk NOOIT effect. `.cbtn { display: inline-flex }` staat verderop in
   dit bestand met dezelfde soortelijkheid, en de LATERE wint — dezelfde val die
   `.gym__player-bar .gym__player-abort` hierboven al documenteert. Dus stond de
   rail-knop óók op de telefoon, als zesde zichtbare bediening die daar niets
   doet. De regel hierboven blijft staan: de poort van die fase leest hem.
   De iPad-regel hieronder heeft hogere soortelijkheid en toont hem vanaf 1024px. */
.gym__player-bar .gym__player-col { display: none; }
@media (min-width: 1024px) {
  html[data-ipad].gym-player-open .dossier__panel--player .gym__player-col { display: inline-flex; }
}

/* SCHEMA-IMPORT-PLAK-JE-SCHEMA-OF-UPLOAD-DE-PDF — the draft row is a BUTTON now
   (it opens its own review screen), so it must reset the UA button styling:
   without width/background/text-align/font it renders as a shrink-wrapped grey
   control instead of the full-width dashed row it has always been. */
.gym__draft-row {
  display: flex; align-items: center; gap: var(--space-3); min-height: 48px; width: 100%;
  padding: var(--space-2) var(--space-3); border: 1px dashed var(--line); border-radius: var(--radius);
  color: var(--muted); font-size: 14px;
  background: none; font-family: inherit; text-align: left; cursor: pointer;
}
.gym__draft-row:hover { border-color: var(--accent); color: var(--ink); }
.gym__draft-row .gym__prog-name { font-weight: 500; }
.gym__draft-when { flex: 0 0 auto; margin-left: auto; font-size: 12px; color: var(--muted); }
/* SAMENWERKING-SUBCOACH-MAG-COACHEN — author line on a shared schedule. Quiet
   by design: it answers "whose is this" without competing with the title. */
.gym__draft-author { flex: 0 0 auto; font-size: 12px; color: var(--muted); }
.cide-picker__item .gym__draft-author { display: block; width: 100%; margin-top: 2px; }
.cpayd--locked .cpayd__line { color: var(--muted); }

/* COACH-GYM-EEN-SPELER-NOOIT-TWEE — the second, full-screen player surface
   (/clients/:cid/session/:sid) is gone; the dossier Gym panel is the one player.
   Only .tmode__actas and .tmode__safety* survive; both are reused elsewhere. */

/* COACH-VOCAB-LOCK-SESSION-CLASS-CLIENT-MEMBER — X-04 acting-as mode strip.
   Persistent accent band pinned above the client iframe so the coach can
   never forget they are operating in another user's context (DOET ch.5).
   COACH-ACT-AS-PERSISTENT-BANNER — full-width band (it sits inside the coach
   shell above the iframe, not fixed over the client app), keeping the exact
   placement and 12px/600 prominence it has always had.
   COACHSTYLE-2 — protected safety UI: it keeps its OWN colour pair
   (--actas-bg / --actas-ink, warn-amber, identical in both themes) instead of
   any calm surface token. The old near-black translucent band had become
   near-invisible against the new dark background; amber is louder, not calmer,
   and never tracks the theme. Do not fold these into the surface palette. */
.tmode__actas {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: center; gap: 6px;
  width: 100%; border: 0;
  padding: var(--space-1) var(--space-3);
  background: var(--actas-bg); color: var(--actas-ink);
  font: inherit; font-size: 12px; font-weight: 600; letter-spacing: .01em;
  cursor: pointer; text-align: center;
}
.tmode__actas-dot {
  width: 5px; height: 5px; border-radius: 50%; background: var(--actas-ink); flex: 0 0 auto;
}
.tmode__actas-lbl { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tmode__actas-exit {
  flex: 0 0 auto; background: color-mix(in oklab, var(--actas-ink) 16%, transparent); color: var(--actas-ink);
  font-size: 11px; font-weight: 600; padding: 3px 8px; border-radius: 999px;
}

/* COACH-INTAKE-SAFETY-BLOCK-AND-LESSON-FLAGS — pinned safety banner */
.tmode__safety { flex: 0 0 auto; border-bottom: 1px solid var(--line); }
.tmode__safety-bar {
  display: flex; align-items: center; gap: var(--space-2); width: 100%;
  padding: var(--space-2) var(--space-3); border: 0; cursor: pointer;
  background: color-mix(in srgb, var(--danger) 14%, var(--surface));
  color: var(--danger); font: inherit; font-size: 13px; font-weight: 700; text-align: left;
}
.tmode__safety-bar svg { flex: 0 0 auto; }
.tmode__safety-lbl { flex: 1 1 auto; min-width: 0; }
.tmode__safety-caret { transition: transform .15s ease; }
.tmode__safety--open .tmode__safety-caret { transform: rotate(180deg); }
.tmode__safety-detail {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-2) var(--space-3) var(--space-3);
  background: color-mix(in srgb, var(--danger) 6%, var(--surface));
}
.tmode__safety-group {
  margin: var(--space-1) 0 0; font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em; color: var(--muted);
}
.tmode__safety-item { display: flex; flex-direction: column; gap: 1px; }
.tmode__safety-txt { font-size: 14px; font-weight: 600; color: var(--ink); }
.tmode__safety-note { font-size: 12px; color: var(--muted); }

/* COACH-INTAKE-SAFETY-BLOCK-AND-LESSON-FLAGS — intake list editor */
.sflags-edit { display: flex; flex-direction: column; gap: var(--space-2); }
.sflags-edit__row { display: flex; align-items: center; gap: var(--space-2); }
.sflags-edit__text, .sflags-edit__note {
  min-width: 0; padding: var(--space-2); border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface); color: var(--ink);
  font: inherit; font-size: 14px;
}
.sflags-edit__text { flex: 1 1 55%; }
.sflags-edit__note { flex: 1 1 45%; }
.sflags-edit__rm {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--muted); cursor: pointer;
}
.sflags-edit__add {
  display: inline-flex; align-items: center; gap: var(--space-1); align-self: flex-start;
  margin-top: var(--space-1); padding: var(--space-1) var(--space-2);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--accent); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.sflags-edit__add svg { flex: 0 0 auto; }

@media (min-width: 1024px) {
  .gym__planrow { justify-content: flex-end; }
}

/* ───────── Panel 3 nutrition (COACH-PLATFORM-SPRINT-5-PANEL-3-NUTRITION-DOSSIER) ───────── */
.nut { display: flex; flex-direction: column; gap: var(--space-3); }
.nutcard__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); flex-wrap: wrap; }
.nutcard__sub { margin: 0; font-size: 13px; font-weight: 600; color: var(--ink-2); }
.nutcard__span { display: inline-flex; border: 1px solid var(--line); border-radius: 999px; overflow: hidden; }
.nutcard__span-btn {
  padding: 4px var(--space-3); border: 0; background: var(--surface);
  color: var(--ink-2); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
}
.nutcard__span-btn + .nutcard__span-btn { border-left: 1px solid var(--line); }
.nutcard__span-btn--on { background: var(--accent); color: var(--on-accent); }
.nutcard__loading, .nutcard__empty { margin: 0; color: var(--muted); font-size: 13px; }
.nutcard__grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2); }
.nutstat {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--space-2) var(--space-3); border: 1px solid var(--line-2);
  border-radius: var(--radius); background: var(--bg);
}
.nutstat__label { font-size: 12px; color: var(--muted); }
.nutstat__val { display: inline-flex; align-items: baseline; gap: 4px; }
.nutstat__num { font-size: 18px; font-weight: 700; color: var(--ink); }
.nutstat__unit { font-size: 11px; color: var(--muted); }

/* macro-distribution stacked bar */
.nutmacro { display: flex; flex-direction: column; gap: var(--space-2); }
.nutmacro__empty { margin: 0; color: var(--muted); font-size: 13px; }
.nutmacro__bar { display: flex; height: 14px; border-radius: 999px; overflow: hidden; background: var(--bg); }
.nutmacro__seg { display: block; height: 100%; }
.nutmacro__seg--p, .nutmacro__dot--p { background: var(--macro-p); }
.nutmacro__seg--c, .nutmacro__dot--c { background: var(--macro-c); }
.nutmacro__seg--f, .nutmacro__dot--f { background: var(--macro-f); }
.nutmacro__legend { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.nutmacro__leg { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: var(--ink-2); }
.nutmacro__dot { width: 10px; height: 10px; border-radius: 3px; flex: 0 0 auto; }
.nutmacro__leg-val { font-weight: 700; color: var(--ink); }

/* control chart */
.nutctrl { position: relative; width: 100%; }
/* pan-y keeps vertical page scroll native while horizontal drags reach the
   scrub handler instead of being swallowed by the browser's own panning. */
.nutctrl__canvas { display: block; width: 100%; touch-action: pan-y; cursor: crosshair; }
.nutctrl__empty { margin: 0; color: var(--muted); font-size: 13px; }
.nutctrl__tip {
  position: absolute; top: 0; transform: translateX(-50%);
  padding: 4px 8px; border-radius: var(--radius); font-size: 11px; font-weight: 600;
  background: var(--ink); color: var(--surface); white-space: nowrap; pointer-events: none;
}
.nutctrl__tip--warn { background: var(--danger); color: var(--on-accent); }
/* Multi-line read-out (intake / BMR / active / net). Left-aligned so the
   numbers stack into a scannable column instead of centring ragged. */
.nutctrl__tip-row { text-align: left; }
.nutctrl__tip-src {
  display: flex; align-items: center; gap: 4px;
  margin-top: 2px; opacity: 0.75; font-weight: 500;
}
.nutctrl__tip-src svg { width: 11px; height: 11px; flex: none; }
/* Which regime drew the control limits — goal-derived or statistical. */
/* The legend now carries two messages (systematic deviation + how firm the band
   is), so let it wrap instead of widening the chart on a phone. */
.nutctrl__legend { margin-top: 4px; color: var(--muted); font-size: 11px; line-height: 1.3; overflow-wrap: anywhere; }
/* Series switch above the control chart.
   DOSSIER-NOORDSTER-ALS-OVERZICHT (L183 4/6, bevinding #8) — dit WAS één
   `.nutcard__span`-pil (999px, `overflow:hidden`) met `flex-wrap: wrap` naast
   de kaartkop. Vier labels ("Calorieën/Eiwit/Koolhydraten/Vet") passen daar in
   een dossierpaneel van ~290-350px nooit naast, dus viel "Vet" op een tweede
   regel BINNEN de afgeronde pil: de helft van de onderrand liep dwars door de
   knoppen en de hele kiezer oogde kapot. Hij staat nu op een eigen regel, rand
   tot rand, en SCHUIFT horizontaal in plaats van te breken — precies wat
   `.cfin-chips` op de Geld-tab al doet (bevinding #15 noemt dat het patroon).
   De knoppen houden hun `.nutcard__span-btn`-klassen: de aan/uit-stand en vier
   zustertoetsen hangen eraan; alleen de vorm verandert, van segment in een pil
   naar losse chip. */
.nutctrl__switch {
  display: flex; width: 100%; margin: 0;
  flex-wrap: nowrap; gap: 6px;
  border: 0; border-radius: 0;
  overflow-x: auto; overflow-y: hidden;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.nutctrl__switch::-webkit-scrollbar { display: none; }
.nutctrl__switch .nutcard__span-btn {
  flex: 0 0 auto; white-space: nowrap;
  padding: 5px var(--space-3);
  border: 1px solid var(--line); border-radius: 999px;
}
/* De scheidslijn hoorde bij de segmentpil; losse chips hebben hun eigen rand. */
.nutctrl__switch .nutcard__span-btn + .nutcard__span-btn { border-left: 1px solid var(--line); }
.nutctrl__switch .nutcard__span-btn--on {
  background: var(--accent); color: var(--on-accent); border-color: var(--accent);
}
/* Colour dot in the series button. In the layered view the colour is the only
   thing tying a line to a series, so the tie belongs in the button and not only
   in a legend that falls off a phone screen. */
.nutctrl__switch-btn { display: inline-flex; align-items: center; gap: 5px; }
/* The ring is load-bearing, not decoration: --accent is the coach's own brand
   colour, so a swatch can land on a button filled with almost exactly itself
   (protein blue on a blue brand) and disappear. currentColor is the button's
   own text colour, which is already contrast-checked in both states. */
.nutctrl__switch-dot {
  width: 8px; height: 8px; border-radius: 2px; flex: 0 0 auto;
  box-shadow: 0 0 0 1px currentColor;
}
/* An OFF button keeps its dot but dims it, so the colour code stays readable
   while the on/off state is readable too. */
.nutctrl__switch-btn:not(.nutcard__span-btn--on) .nutctrl__switch-dot { opacity: 0.35; }
/* Multi-line tooltip in the layered view. */
.nutctrl__tip-row--layer { display: flex; align-items: center; gap: 5px; }
.nutctrl__tip-dot { width: 7px; height: 7px; border-radius: 2px; flex: 0 0 auto; }
/* DE-COACH-VERKLAART-DE-FASEWISSEL — a plain text button, deliberately not a
   primary one. Declaring a phase is a rare, considered act; a filled button
   beside the series switch would compete with the chart it annotates. */
/* DOSSIER-NOORDSTER-ALS-OVERZICHT — "Nieuwe fase" rechts in de kop, óók als de
   kop afbreekt. `.nutcard__head` staat op `justify-content: space-between`, en
   dat doet niets voor het ENIGE item op een tweede, afgebroken regel: op 402px
   is de titel "Regelkaart — afwijking van doel" te lang en viel de knop daar
   links onder. `margin-left: auto` laat hem op beide regels rechts staan. */
.nutctrl__phasebtn {
  margin-left: auto;
  background: none; border: 0; padding: 2px 0; cursor: pointer;
  color: var(--accent); font: inherit; font-size: 12px; text-decoration: underline;
}
.nutctrl__phasebtn:hover { opacity: 0.8; }
.nutphase__list { margin-top: var(--space-3); }
.nutphase__row {
  display: flex; align-items: center; gap: var(--space-2);
  padding: 6px 0; border-top: 1px solid var(--line); font-size: 13px;
}
.nutphase__when { color: var(--muted); flex: 0 0 auto; }
.nutphase__label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nutphase__del { flex: 0 0 auto; }
/* De `@container dbox (max-width: 419.98px)`-regel die de kiezer onder de kop
   duwde staat hier NIET meer. DOSSIER-BLOKKEN-KIJKEN-NAAR-HUN-EIGEN-BREEDTE
   verving daarmee een `@media (max-width: 420px)`, zodat de kiezer in élk smal
   vak zijn eigen regel kreeg; DOSSIER-NOORDSTER-ALS-OVERZICHT maakt die regel
   ONVOORWAARDELIJK — de kiezer is nu altijd een eigen, horizontaal schuivende
   strook, dus er valt niets meer om te schakelen. Zie `.nutctrl__switch`. */
/* Measured-vs-estimated disclaimer under a burn/net card. Inherits --muted so
   it reads the same in the Dag and Nacht coach themes. */
.cccard__srcnote {
  display: flex; align-items: center; gap: 5px;
  margin-top: 4px; color: var(--muted); font-size: 11px; line-height: 1.3; text-align: left;
}
.cccard__srcnote svg { width: 12px; height: 12px; flex: none; }

/* daily sheet */
.nutsheet { display: flex; flex-direction: column; gap: var(--space-2); }
.nutsheet__list { display: flex; flex-direction: column; gap: 6px; }
.nutsheet__empty { margin: 0; color: var(--muted); font-size: 13px; }
.nutsheet__more {
  align-self: flex-start; padding: 6px var(--space-3); border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface); color: var(--ink-2);
  font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
}
.nutrow { border: 1px solid var(--line-2); border-radius: var(--radius); overflow: hidden; }
.nutrow__head {
  display: flex; align-items: center; gap: var(--space-2); width: 100%;
  padding: var(--space-2) var(--space-3); border: 0; background: var(--surface);
  font: inherit; text-align: left; cursor: pointer;
}
.nutrow__head:active { background: var(--bg); }
.nutrow__head--miss { cursor: default; }
/* Fixed width so the date column stays aligned across rows: 'wo'/'Wed' are
   wider than 'vr'/'Fri' and would otherwise push each date to its own indent. */
.nutrow__dow { font-size: 11px; color: var(--muted); flex: 0 0 auto; min-width: 26px; text-align: right; margin-right: calc(-1 * var(--space-2) + 4px); }
.nutrow__date { font-size: 12px; font-weight: 600; color: var(--ink); flex: 0 0 auto; min-width: 88px; }
.nutrow__macros { display: flex; flex-wrap: wrap; gap: 8px; flex: 1 1 auto; min-width: 0; }
.nutrow__kcal { font-size: 13px; font-weight: 700; color: var(--ink); }
.nutrow__m { font-size: 12px; color: var(--ink-2); white-space: nowrap; }
.nutrow__miss-lbl { font-size: 12px; color: var(--muted); }
.nutrow__flag { display: inline-flex; flex: 0 0 auto; }
.nutrow__flag--ok { color: var(--ok); }
.nutrow__flag--no { color: var(--muted); }
.nutrow__head--on { background: var(--bg); }
.nutrow__detail { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-2) var(--space-3); border-top: 1px solid var(--line-2); }
.nutrow__loading, .nutrow__empty { margin: 0; color: var(--muted); font-size: 12px; }
.nutmeal { display: flex; flex-direction: column; gap: 3px; }
.nutmeal__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); }
.nutmeal__name { font-size: 13px; font-weight: 600; color: var(--ink); }
.nutmeal__kcal { font-size: 12px; color: var(--muted); }
.nutmeal__item { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); padding-left: var(--space-2); }
.nutmeal__item-name { font-size: 12px; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nutmeal__item-kcal { font-size: 12px; color: var(--muted); flex: 0 0 auto; }

/* GYM-DE-TRAININGSHISTORIE-LEEST-ALS-HET-VOEDINGSLOGBOEK — the training log rides
   on the nutrition row/meal shapes above (.nutrow / .nutmeal), so the two tabs
   keep reading as one app. Only what is genuinely gym-specific gets a class here,
   and it copies the sizing and tokens of the nutrition form — no new colours, no
   new spacing scale, so light and dark follow along by themselves. */
.gymlog { margin-top: var(--space-3); }
.gymrow__prog { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 12ch; }
.gymrow__mark { display: inline-flex; flex: 0 0 auto; color: var(--muted); }
/* The set number is the row's left anchor; a fixed column keeps 1..10 aligned. */
.gymex__num { flex: 0 0 auto; min-width: 18px; font-variant-numeric: tabular-nums; }
.gymex__out { font-variant-numeric: tabular-nums; text-align: right; }
/* GYM-HET-COACHLOGBOEK-LEEST-DEZELFDE-SETREGEL (L223) — twee stille markeringen,
   dezelfde twee die de speler-Historie draagt (.hs-tag en .hs-chip in
   public/strength.html). De DROP-pil zegt dat die 40 kg een START was en geen
   zware set; de uni/bi-pil zegt met één of met beide kanten. Alleen bestaande
   tokens, dus licht en donker volgen van zichzelf. */
.gymex__tag {
  flex: 0 0 auto; margin-left: 4px; padding: 1px 4px; border-radius: 5px;
  font-size: 9px; font-weight: 800; font-style: normal; letter-spacing: .3px;
  background: var(--surface-2, var(--surface)); color: var(--ink-2);
}
.gymex__sides {
  margin-left: 6px; padding: 1px 5px; border-radius: var(--radius-pill);
  font-size: 11px; font-weight: 700; letter-spacing: .3px;
  background: var(--surface-2, var(--surface)); color: var(--muted);
}

/* GYM-HISTORIE-EN-COACHLOGBOEK-TONEN-DE-SCHEIDINGSLIJN (L226 fase 4) — de
   scheidingslijn tussen twee blokken van dezelfde dag, en de chip die hetzelfde
   op de logboekrij zegt. De lijn is de coach-tegenhanger van .pl-blockline in de
   speler (public/strength.html): twee haarlijnen met de tekst ertussen.

   Alles in bestaande tokens, dus licht en donker hebben hier geen eigen regel
   nodig: --line is de haarlijn in elk thema en --muted de stille tekst. De chip
   leent het accent via color-mix in plaats van een nieuwe kleur, want een zacht
   accent-vlak bestaat in coach.css alleen binnen .cpz-panel. GEEN knop, dus
   --on-accent is hier niet van toepassing. */
.gymex__blockline {
  display: flex; align-items: center; gap: 10px;
  margin: var(--space-3) 0 var(--space-2);
}
.gymex__blockline-ln {
  flex: 1 1 auto; height: 1px; min-width: 8px; background: var(--line);
}
.gymex__blockline-tx {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px; font-weight: 600; color: var(--muted); white-space: nowrap;
}
.gymex__blk {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 9px; border-radius: 20px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent); font-size: 12px; font-weight: 600; white-space: nowrap;
}

/* ════ Today / Overview — COACH-PLATFORM-SPRINT-6-TODAY-OVERVIEW-PAGE ════ */
.ctoday__bulk-btn {
  margin-left: auto; display: inline-flex; align-items: center; gap: 6px;
  padding: 6px var(--space-3); border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); font-size: 13px; font-weight: 600; cursor: pointer;
}
.ctoday__bulk-btn:hover { border-color: var(--accent); color: var(--accent); }
/* COACH-CLEANUP-1 — icon-only kebab: square, no text gap. */
.ctoday__bulk-btn--kebab { width: 34px; height: 34px; padding: 0; justify-content: center; gap: 0; }

/* AGENDA-KOP-IN-EEN-RIJ — one 44px bar replaces title row + view row + nav row.
   No wrapping: the bar must never grow back into a second line. */
.ctoday__bar {
  display: flex; align-items: center; gap: 4px;
  min-height: 44px; margin-bottom: var(--space-2); flex-wrap: nowrap;
}
/* Only the spacer may give way. Everything else keeps its natural width — a
   shrinking date label reads as "24–" and answers nothing. */
.ctoday__bar-gap { flex: 1 1 auto; min-width: 0; }
.ctoday__bar > .ctoday__nav-btn { flex: 0 0 auto; width: 32px; height: 32px; }
.ctoday__bar .ctoday__nav-today { flex: 0 0 auto; padding: 6px 10px; }
/* AGENDA-OPENT-OP-NU-EN-DE-KOP-PAST — the "back to today" exit is an icon in
   this row, so it costs the same 32px as its neighbours instead of a 75px pill. */
.ctoday__bar > .ctoday__nav-today-btn { flex: 0 0 auto; width: 32px; height: 32px; }
.ctoday__period {
  flex: 0 1 auto; min-width: 0;
  display: inline-flex; align-items: center; gap: 2px;
  padding: 6px var(--space-2); border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); font-size: 14px; font-weight: 700;
  cursor: pointer; white-space: nowrap;
}
/* The date may shrink; the caret that says "this opens something" may not. */
.ctoday__period-lbl { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ctoday__period > svg { flex: 0 0 auto; }
@media (min-width: 768px) {
  .ctoday__bar { gap: var(--space-2); }
  .ctoday__bar > .ctoday__nav-btn { width: 34px; height: 34px; }
  .ctoday__period { font-size: 15px; padding: 6px var(--space-3); }
}
.ctoday__period:hover { border-color: var(--accent); }
.ctoday__viewmenu { position: relative; }
.ctoday__view-btn {
  display: inline-flex; align-items: center; gap: 2px; height: 32px;
  padding: 0 8px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink-2); font-size: 13px; font-weight: 600; cursor: pointer;
}
.ctoday__view-btn:hover { border-color: var(--accent); color: var(--accent); }
/* AGENDA-OPENT-OP-NU-EN-DE-KOP-PAST — the view switcher keeps its LABEL at every
   width. Dropping it ('Dag' → a bare chevron after one arrow tap) saved 36px and
   cost the answer to "which view am I looking at", which is the ONE question that
   control exists to answer. The 43px the icon-button exit gives back pays for it;
   below that, the date label ellipsises (.ctoday__period-lbl) and the row still
   fits. Measured: scrollWidth === clientWidth at 390px in both states. */
.ctoday__view-btn { flex: 0 0 auto; }
.ctoday__view-lbl { white-space: nowrap; }
.ctoday__view-list {
  position: absolute; top: calc(100% + 4px); right: 0; z-index: 40;
  display: flex; flex-direction: column; min-width: 128px;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
  box-shadow: 0 8px 24px rgba(0,0,0,.18); overflow: hidden;
}
.ctoday__view-list[hidden] { display: none; }
.ctoday__view-item {
  padding: 8px var(--space-3); border: 0; background: transparent; color: var(--ink);
  font-size: 13px; font-weight: 600; text-align: left; cursor: pointer;
}
.ctoday__view-item:hover { border-color: var(--accent); color: var(--accent); }
.ctoday__view-item.is-on { color: var(--accent); }
.ctoday__seg, .ctoday__ts {
  display: inline-flex; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden;
}
.ctoday__seg-btn, .ctoday__ts-btn {
  padding: 6px var(--space-4); border: 0; background: var(--surface);
  color: var(--ink-2); font-size: 13px; font-weight: 600; cursor: pointer;
}
.ctoday__ts-btn { padding: 5px var(--space-3); font-size: 12px; }
.ctoday__seg-btn + .ctoday__seg-btn, .ctoday__ts-btn + .ctoday__ts-btn { border-left: 1px solid var(--line); }
/* GELD-DONKER-HOORT-BIJ-HET-MERK — ÉÉN recept voor elke aan-staat van een chip
   of segment, in beide thema's: een 16%-tint in plaats van een volvlak. Een
   volvlak-accent op elke aan-staat trok de aandacht naar de navigatie in plaats
   van naar de inhoud. De tweede term is --surface en NIET transparent: op --bg
   (#F1F5F9 licht) haalt accenttekst op zo'n tint 4,31:1 en zakt door de eis;
   tegen --surface is het 4,70:1 (licht) en 8,15:1 (donker). Gevulde knoppen die
   wél een hoofdactie zijn houden var(--accent) + var(--on-accent). */
.ctoday__seg-btn.is-on, .ctoday__ts-btn.is-on {
  background: color-mix(in srgb, var(--accent) 16%, var(--surface));
  color: var(--accent); border-color: var(--accent);
}

.ctoday__nav { display: inline-flex; align-items: center; gap: var(--space-2); }
.ctoday__nav-btn {
  width: 34px; height: 34px; display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); color: var(--ink); cursor: pointer;
}
.ctoday__nav-btn:hover { border-color: var(--accent); color: var(--accent); }
.ctoday__nav-today {
  padding: 6px var(--space-3); border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink-2); font-size: 13px; font-weight: 600; cursor: pointer;
}
/* COACH-ALLEEN-VERTICAAL-SCROLLEN — the jump sheet's copy sits under the date
   field, full width; on narrow phones it is the only way back to today. */
.csettings-sec > .add-client__input + .ctoday__nav-today { display: block; width: 100%; margin-top: var(--space-2); }

.ctoday__sec { margin-bottom: var(--space-5); }
.ctoday__sec-title { margin: 0 0 var(--space-3); font-size: 14px; font-weight: 700; color: var(--ink); text-transform: uppercase; letter-spacing: 0.04em; }
.ctoday__dash-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-3); }
.ctoday__dash-head .ctoday__sec-title { margin: 0; }
.ctoday__loading, .ctoday__empty { color: var(--muted); font-size: 13px; margin: 0; padding: var(--space-3) 0; }

/* Section 1 — scheduled */
.ctoday__sched { display: flex; flex-direction: column; gap: var(--space-2); }
.ctoday__sched-row {
  display: flex; align-items: center; gap: var(--space-3); width: 100%;
  padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); cursor: pointer; text-align: left;
}
.ctoday__sched-row:hover { border-color: var(--accent); }
.ctoday__sched-when { flex: 0 0 auto; font-size: 13px; font-weight: 700; color: var(--accent); min-width: 64px; }
.ctoday__sched-mid { flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0; }
.ctoday__sched-name { font-size: 14px; font-weight: 600; }
.ctoday__sched-prog { font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ctoday__sched-row > svg { flex: 0 0 auto; color: var(--muted); }
.ctoday__sched-item { display: flex; align-items: stretch; gap: var(--space-2); }
.ctoday__sched-item .ctoday__sched-row { flex: 1 1 auto; }
/* REVIEW-GELD-EN-AFSPRAKEN-LANDEN-OP-HUN-BLAD (L212) — de rij die de knop op
   een boekingskaart aanwees. De streep hangt aan de RIJ zelf, niet aan een
   doos eromheen: een extra omhulsel zou dubbele padding geven (L183). */
.ctoday__sched-item--focus .ctoday__sched-row {
  box-shadow: inset 3px 0 0 0 var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}
.ctoday__sched-cancel {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 40px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--muted); cursor: pointer;
}
.ctoday__sched-cancel:hover { border-color: var(--danger); color: var(--danger); }
.ctoday__sched-add {
  display: inline-flex; align-items: center; gap: var(--space-2); margin-top: var(--space-2);
  padding: var(--space-2) var(--space-3); border: 1px solid var(--accent); border-radius: var(--radius);
  background: var(--accent); color: var(--on-accent); font-weight: 600; cursor: pointer;
}
.ctoday__sched-add > svg { flex: 0 0 auto; }

/* ════ Calendar grid — COACH-CALENDAR-TRAININ-GRID-READONLY ════
   Trainin's time-grid idiom in Sassu tokens only: no new colour variables and no
   hex literals. Card colours are computed per gym label in JS (deterministic
   hue), so this sheet only styles structure. */
.cal { --cal-cols: 7; }
.cal__viewbar { display: inline-flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.cal__filter-btn.is-on {
  background: color-mix(in srgb, var(--accent) 16%, var(--surface));
  color: var(--accent); border-color: var(--accent);
}

.cal__filters {
  display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap;
  padding: var(--space-3); margin-bottom: var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
}
.cal__filters-locs { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
/* AGENDA-WAT-JE-VERBERGT-BLIJFT-VERBORGEN — was een <label> met een vinkje en
   is nu één tikbare chip: verbergen is één tik en zichtbaar is de standaard, dus
   er is niets aan te vinken. Vlak en zonder eigen vorm — de rij is een kijkglas
   boven de agenda, geen tweede knoppenbalk. */
.cal__filters-loc {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; color: var(--ink-2); cursor: pointer;
  background: none; border: 0; padding: var(--space-1) 0; min-height: 32px;
  -webkit-tap-highlight-color: transparent;
}
/* Verborgen: doorgestreept EN gedimd. Alleen dimmen leest als "uitgegrijsd/niet
   beschikbaar"; de streep zegt dat JIJ hem hebt weggehaald en dat één tik hem
   terugbrengt. */
.cal__filters-loc.is-off { color: var(--ink-2); opacity: 0.45; }
.cal__filters-loc.is-off .cal__filters-loc-lbl { text-decoration: line-through; }
.cal__filters-dot { width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto; }

/* The axis column is fixed at 48px; the day columns always share the rest, so a
   full week fits any viewport without sideways scrolling. */
.cal__board {
  /* The dial the whole grid is drawn from: one hour of height. Resizing the
     agenda means changing it, not re-rendering the grid. */
  --cal-hour: 60px;
  --cal-rows: 16;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); overflow-x: auto;
  overscroll-behavior-x: contain; -webkit-overflow-scrolling: touch;
  /* AGENDA-DE-WEEK-VOLGT-JE-VINGER — the containing block for the two
     neighbouring weeks that lie beside the visible one during a swipe. */
  position: relative;
}

/* AGENDA-DE-WEEK-VOLGT-JE-VINGER — the week left and right of the one on
   screen, translated in from outside the board. Its own class on purpose: at
   rest these panes do not exist, and while they do they must not answer to the
   selectors the real grid is measured by (.cal__head / .cal__body).
   z-index 1 keeps them UNDER the left-sticky clock column (z-index 2), which is
   what lets the hour axis stand still while its own grid slides past it. */
.cal__ghost {
  position: absolute; top: 0; z-index: 1;
  background: var(--surface); pointer-events: none;
  will-change: transform;
}
.cal__ghost-head, .cal__ghost-body {
  display: grid; grid-template-columns: repeat(var(--cal-cols), minmax(0, 1fr));
}
.cal__ghost-head { border-bottom: 1px solid var(--line); box-sizing: border-box; }
.cal__ghost-ad { border-bottom: 1px solid var(--line); box-sizing: border-box; }
.cal__head, .cal__allday, .cal__body {
  display: grid; grid-template-columns: 48px repeat(var(--cal-cols), minmax(0, 1fr));
  min-width: 100%;
}
.cal__head { border-bottom: 1px solid var(--line); }
/* Scrolling sideways to Sunday must never take the clock off screen. */
.cal__head-week, .cal__allday-label, .cal__axis {
  position: sticky; left: 0; z-index: 2; background: var(--surface);
}
.cal__head-week {
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; color: var(--muted); letter-spacing: 0.04em;
}
.cal__head-cell {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: var(--space-2) 4px; border-left: 1px solid var(--line-2);
}
.cal__head-dow { font-size: 11px; text-transform: uppercase; color: var(--muted); letter-spacing: 0.04em; }
.cal__head-num { font-size: 15px; font-weight: 700; color: var(--ink); }
/* Today's column head takes the accent + its luminance-derived ink (never a literal). */
.cal__head-cell.is-today { background: var(--accent); }
.cal__head-cell.is-today .cal__head-dow,
.cal__head-cell.is-today .cal__head-num { color: var(--on-accent); }

.cal__allday { border-bottom: 1px solid var(--line); min-height: 26px; }
.cal__allday-label {
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; text-transform: uppercase; color: var(--muted);
}
.cal__allday-cell { border-left: 1px solid var(--line-2); padding: 3px; display: flex; flex-direction: column; gap: 2px; }

.cal__axis { height: calc(var(--cal-hour) * var(--cal-rows)); }
.cal__axis-cell {
  display: flex; justify-content: center; padding-top: 2px;
  height: var(--cal-hour); box-sizing: border-box;
  font-size: 11px; color: var(--muted);
  border-top: 1px solid var(--line-2);
}
.cal__col {
  position: relative; border-left: 1px solid var(--line-2);
  height: calc(var(--cal-hour) * var(--cal-rows));
}
/* Hour line solid, half-hour dotted — Trainin §2.2. */
.cal__slot {
  border-top: 1px solid var(--line-2); position: relative;
  height: var(--cal-hour); box-sizing: border-box;
}
.cal__slot::after {
  content: ''; position: absolute; left: 0; right: 0; top: 50%;
  border-top: 1px dotted var(--line-2);
}

/* AGENDA-STREEP-VAN-NU — where the clock stands, in today's column only. Above
   the cards like Google Agenda, which is only safe because pointer-events: none
   keeps every click on the hour slot underneath ("schedule a session"). */
.cal__nowline {
  position: absolute; left: 0; right: 0; height: 0;
  border-top: 2px solid var(--accent);
  z-index: 1; pointer-events: none;
}
.cal__nowline::before {
  content: ''; position: absolute; left: -1px; top: -4px;
  width: 6px; height: 6px; border-radius: 50%; background: var(--accent);
}

.cal__card {
  position: absolute; left: 2px; right: 2px; overflow: hidden;
  display: flex; flex-direction: column; gap: 1px;
  padding: 3px 5px; border-radius: var(--radius);
  border-left: 3px solid var(--cal-card-bar, var(--line));
  color: var(--ink); font-size: 11px; line-height: 1.25; cursor: pointer;
}
.cal__card-time { display: flex; align-items: center; gap: 3px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.cal__card-time > svg { flex: 0 0 auto; }
/* Zoomed far out the name is the only thing worth the room: hide the time line
   instead of truncating both lines. */
.cal__board--tight .cal__card-time { display: none; }
.cal__card-who { font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal__card-what { color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* AGENDA-AFZEGGEN-MET-EEN-REDEN — de stille regel. --muted en niet --danger of
   --warn: dit is context waarmee je de sessie ingaat, geen alarm dat om een
   handeling vraagt. Dezelfde afkap-regel als zijn buren, want een kaart in het
   weekraster is smal en een reden mag nooit de naam wegdrukken. Staat volledig
   op tokens, dus in Nacht is hij meteen goed. */
.cal__card-prevcancel {
  color: var(--muted); font-size: 11px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Needs the coach: unmatched import, or the client is out of credits. */
.cal__card--attention { border-left-color: var(--danger); }
.cal__card--mini { position: static; left: auto; right: auto; height: auto; }

.cal__month {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); overflow: hidden;
}
.cal__month-dow {
  padding: var(--space-2) 4px; text-align: center;
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--muted); border-bottom: 1px solid var(--line);
}
.cal__month-cell {
  min-height: 84px; padding: 3px; display: flex; flex-direction: column; gap: 2px;
  border-top: 1px solid var(--line-2); border-left: 1px solid var(--line-2);
}
.cal__month-cell.is-out { opacity: 0.45; }
.cal__month-num { font-size: 11px; font-weight: 700; color: var(--ink-2); }
.cal__month-cell.is-today .cal__month-num {
  align-self: flex-start; padding: 0 5px; border-radius: 999px;
  background: var(--accent); color: var(--on-accent);
}

/* COACH-TODAY-ROW-TYPE-MARKER (F-04) — left-edge kind bar + glyph. The colour is
   set by the .ctoday__row--{kind} modifier; the bar + glyph inherit currentColor. */
.ctoday__row-marker {
  flex: 0 0 auto; align-self: stretch; display: inline-flex; align-items: center;
  gap: 6px; padding-left: 6px;
}
.ctoday__row-marker::before {
  content: ''; flex: 0 0 auto; width: 1.5px; align-self: stretch; min-height: 20px;
  border-radius: 1px; background: currentColor;
}
.ctoday__row-marker > svg { flex: 0 0 auto; }
.ctoday__row--training { color: var(--ink-strong); }
.ctoday__row--booking  { color: var(--accent); }
.ctoday__row--class    { color: var(--accent-2); }
.ctoday__row--note     { color: var(--warn); }
/* Note rows already carry a priority left-border, so the marker there is glyph-only. */
.ctoday__note-meta .ctoday__row-marker { align-self: center; padding-left: 0; }
.ctoday__note-meta .ctoday__row-marker::before { display: none; }

.gym__sched {
  display: inline-flex; align-items: center; gap: var(--space-2); width: 100%;
  justify-content: center; margin-top: var(--space-2);
  padding: var(--space-3); border: 1px solid var(--accent); border-radius: var(--radius);
  background: var(--accent); color: var(--on-accent); font-weight: 600; cursor: pointer;
}
.gym__sched > svg { flex: 0 0 auto; }

/* COACH-HISTORY-IMPORT-WIZARD-COMMIT — entry button + committed-import undo list */
.gym__import {
  display: inline-flex; align-items: center; gap: var(--space-2); width: 100%;
  justify-content: center; margin-top: var(--space-2); padding: var(--space-3);
}
.gym__import > svg { flex: 0 0 auto; }
.gym__imports { margin-top: var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); }
.gym__imports-title { margin: 0; font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.gym__import-row {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
}
.gym__import-meta { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.gym__import-name { font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gym__import-sub { font-size: 12px; color: var(--muted); }
.gym__import-undo { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; padding: 6px var(--space-3); }

/* history-import wizard sheet (himp) */
.himp { display: flex; flex-direction: column; gap: var(--space-3); }
.himp__lead { margin: 0; font-size: 14px; color: var(--ink); line-height: 1.4; }
.himp__hint { margin: 0; font-size: 13px; color: var(--muted); }
.himp__status { margin: 0; font-size: 13px; color: var(--muted); min-height: 18px; }
.himp__pick { display: inline-flex; align-items: center; gap: var(--space-2); justify-content: center; }
/* SCHEMA-IMPORT-EEN-FOTO-VAN-PAPIER-MAG-OOK — file + camera side by side, and they
   stack on a narrow phone rather than squeezing either label. */
.himp__picks { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.himp__picks > .cbtn { flex: 1 1 140px; }
.himp__shoot { display: inline-flex; align-items: center; gap: var(--space-2); justify-content: center; }
/* SCHEMA-IMPORT-PLAK-JE-SCHEMA-OF-UPLOAD-DE-PDF — the paste box on the import sheet. */
.himp__paste { width: 100%; min-height: 140px; resize: vertical; font: inherit; font-size: 14px; line-height: 1.4; }
.himp__wk { display: flex; flex-direction: column; gap: var(--space-3); max-height: 52vh; overflow-y: auto; }
.himp__card { border: 1px solid var(--line); border-radius: var(--radius); padding: var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); }
.himp__cardhd { display: flex; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; }
.himp__date { font-weight: 700; color: var(--ink); }
.himp__wname { font-size: 13px; color: var(--muted); }
.himp__ex { border-top: 1px solid var(--line-2); padding-top: var(--space-2); display: flex; flex-direction: column; gap: 4px; }
.himp__ex:first-child { border-top: 0; padding-top: 0; }
.himp__ex--skip { opacity: 0.5; }
.himp__exhd { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.himp__raw { font-weight: 600; color: var(--ink); }
.himp__chip { font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 999px; text-transform: uppercase; letter-spacing: 0.03em; }
.himp__chip--matched { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); }
.himp__chip--suggested { background: var(--line-2); color: var(--ink-2); }
.himp__chip--unmatched { background: color-mix(in srgb, var(--danger) 16%, transparent); color: var(--danger); }
.himp__sets { font-size: 12px; color: var(--muted); }
.himp__match { font-size: 13px; color: var(--accent); font-weight: 600; }
.himp__resolve { display: flex; flex-direction: column; gap: var(--space-2); margin-top: 4px; }
.himp__sugs { display: flex; flex-wrap: wrap; gap: 6px; }
.himp__sug {
  font-size: 12px; font-weight: 600; padding: 4px 10px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink); cursor: pointer;
}
.himp__sug:hover { border-color: var(--accent); color: var(--accent); }
.himp__name { width: 100%; }
.himp__skip { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: var(--muted); cursor: pointer; }
.himp__schema { display: flex; align-items: flex-start; gap: 8px; font-size: 14px; color: var(--ink); cursor: pointer; }
.himp__schema input { margin-top: 3px; flex: 0 0 auto; }
.himp__btns { display: flex; gap: var(--space-2); }
.himp__btns > * { flex: 1 1 0; }

/* COACH-AGENDA-GCAL-ICS-IMPORT — imported ICS lesson rows */
.ctoday__sched-item--feed .ctoday__sched-row { border-style: dashed; }
.ctoday__sched-item--feed .ctoday__sched-row:not(.ctoday__sched-row--unknown) { border-style: solid; }
.ctoday__sched-row--unknown { border-color: var(--line); background: var(--line-2); }
.ctoday__sched-row--unknown:hover { border-color: var(--accent); }
.ctoday__sched-name--muted { color: var(--muted); font-weight: 600; }
.ctoday__sched-unrec { font-size: 12px; color: var(--accent); font-weight: 600; }
.ctoday__sched-gym {
  font-size: 11px; color: var(--muted); text-transform: uppercase;
  letter-spacing: 0.04em; margin-top: 1px;
}

/* AGENDA-EEN-GESPIEGELDE-AFSPRAAK-ZET-JE-VAST-IN-SASSU — de drie dingen die een
   gespiegelde rij wint door hem vast te zetten. Elke regel één vinkje, en het
   vinkje krijgt `flex: 0 0 auto` in plaats van een percentage: een inline svg
   zonder vaste maat in een flexrij krimpt mee met de tekst ernaast
   (GROCERIES-SORT-BTN-ICON-SIZE-FIX). */
.cpromote__why {
  list-style: none; margin: 0 0 var(--space-3); padding: 0;
  display: flex; flex-direction: column; gap: 6px;
}
.cpromote__why li {
  display: flex; align-items: center; gap: var(--space-2);
  font-size: 13px; color: var(--ink-2);
}
.cpromote__why li svg { flex: 0 0 auto; color: var(--accent); }

/* Client chooser + feed-settings sheets */
.ccal-chooser__ev { font-size: 13px; color: var(--muted); }
.ccal-chooser__hint { font-size: 13px; color: var(--ink); font-weight: 600; }
.ccal-chooser__list { display: flex; flex-direction: column; gap: var(--space-2); }
.ccal-chooser__client {
  display: flex; align-items: center; gap: var(--space-3);
  width: 100%; text-align: left; padding: var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); font-weight: 600; cursor: pointer;
}
.ccal-chooser__client:hover { border-color: var(--accent); color: var(--accent); }
.ccal-chooser__check {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 6px;
  border: 2px solid var(--line); display: flex; align-items: center; justify-content: center;
  color: var(--on-accent);
}
.ccal-chooser__check svg { opacity: 0; }
.ccal-chooser__client.is-selected { border-color: var(--accent); color: var(--accent); }
.ccal-chooser__client.is-selected .ccal-chooser__check { background: var(--accent); border-color: var(--accent); }
.ccal-chooser__client.is-selected .ccal-chooser__check svg { opacity: 1; }
.ccal-chooser__cname { flex: 1 1 auto; min-width: 0; }
.ccal-chooser__confirm { margin-top: var(--space-3); }

.ccal-feeds__help { font-size: 13px; color: var(--muted); }
.ccal-feeds__list { display: flex; flex-direction: column; gap: var(--space-2); }
.ccal-feeds__row {
  display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap;
  padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface);
}
/* GCAL-MULTI-CALENDAR-PAIRING — the "Writes to" picker takes its own line under
   the row it belongs to: on a phone a select next to the on/off + remove
   buttons leaves no readable width for the calendar name. */
.ccal-feeds__pair { flex: 1 1 100%; display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
.ccal-feeds__pair select { flex: 1 1 auto; min-width: 0; }
.ccal-feeds__text { flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0; }
.ccal-feeds__name { font-size: 14px; font-weight: 600; }
/* DE-UITLEG-BIJ-DE-AGENDAKOPPELING-VALT-NIET-MEER-VAN-HET-SCHERM — this class
   did two incompatible things at once: "small grey line" AND "cut off after one
   line". Four explanatory sentences under the Google-calendar connection ended
   in an ellipsis because of it. Reading is the default now; cutting off is an
   opt-in, and only for a feed or calendar NAME that can be any length and sits
   in a row next to buttons. */
.ccal-feeds__meta { font-size: 12px; color: var(--muted); white-space: normal; }
.ccal-feeds__meta--oneline { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ccal-feeds__actions { flex: 0 0 auto; display: flex; gap: var(--space-2); }
.ccal-feeds__add { display: flex; flex-direction: column; gap: var(--space-2); }

/* AGENDA-DE-KLEUR-VAN-EEN-SASSU-AFSPRAAK-KIES-JE-ZELF — Google's eleven calendar
   colours as eleven round swatches. The fill is Google's own hex (set inline, it
   is data and not a theme token); everything around it is ours.
   The chosen one is marked TWICE on purpose: a ring in the text colour AND a
   step up in size. Colour alone would make the answer unreadable for anyone who
   separates colours poorly — which is precisely the audience of this setting. */
.gcal-swatches { display: flex; flex-wrap: wrap; gap: var(--space-2); padding: 2px 0; }
.gcal-swatch {
  width: 28px; height: 28px; padding: 0; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--line); box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12);
  transition: transform .12s ease, box-shadow .12s ease;
}
.gcal-swatch:disabled { cursor: default; opacity: .6; }
.gcal-swatch[aria-checked="true"] {
  transform: scale(1.18);
  box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--ink);
}
.gcal-swatch:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

/* AGENDA-GEEN-KLEUR-VOLGT-DE-GOOGLE-AGENDA — het eerste rondje is leeg met een
   schuine streep erdoor: de bekende "niets"-vorm, getekend in CSS en niet in een
   emoji. De streep staat in de tekstkleur zodat hij in beide thema's leesbaar
   blijft, en de achtergrond blijft de ondergrond van het blad — een kleurvlak
   zou precies het tegenovergestelde beweren van wat de knop doet. */
.gcal-swatch--none {
  position: relative;
  background: var(--surface);
  border-color: var(--ink);
}
.gcal-swatch--none::after {
  content: '';
  position: absolute;
  top: 50%; left: 2px; right: 2px;
  height: 1px;
  background: var(--ink);
  transform: rotate(-45deg);
}

/* AGENDA-ELKE-PLEK-ZIJN-EIGEN-KLEUR — de kleurrij op een plek-rij.
   Hij neemt een eigen regel ONDER de naam (dat doet .ccal-feeds__pair al met
   flex-basis 100%), en de rondjes mogen wrappen: dertien van 28px passen niet
   op één telefoonregel en afkappen zou de laatste kleuren onbereikbaar maken.
   align-items: flex-start zodat het woord "Kleur" bij de EERSTE regel rondjes
   staat en niet in het midden van twee regels zweeft. */
.cplace-col { align-items: flex-start; }
.cplace-col > .ccal-feeds__meta { padding-top: 6px; }
.cplace-col__row { flex: 1 1 auto; min-width: 0; }

/* 'Zoals algemeen' — leeg, met een onderbroken rand. De streepjes zeggen
   "van iets anders overgenomen"; een kleurvlak zou een eigen kleur beweren en
   de schuine streep van .gcal-swatch--none betekent al iets ANDERS, namelijk
   "met opzet geen kleur". Twee keuzes, twee vormen, geen emoji. */
.gcal-swatch--general {
  background: var(--surface);
  border: 1px dashed var(--ink);
  box-shadow: none;
}

/* AGENDA-IN-GOOGLE-STAAT-ALLEEN-DE-VOORNAAM — four title shapes, each written
   out with a real client name. One per row and left-aligned, because what the
   coach compares here is TEXT: side by side the four would wrap differently and
   he would be reading a layout instead of a title. */
.gcal-titles { display: flex; flex-direction: column; gap: var(--space-1); padding: 2px 0; }
.gcal-title {
  text-align: left; padding: 8px 10px; cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); font-size: 14px;
}
.gcal-title:disabled { cursor: default; opacity: .6; }
.gcal-title[aria-checked="true"] { border-color: var(--ink); font-weight: 700; box-shadow: inset 0 0 0 1px var(--ink); }
.gcal-title:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.set-mini {
  padding: 6px 10px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); font-size: 13px; font-weight: 600; cursor: pointer;
}
.set-mini:hover { border-color: var(--accent); color: var(--accent); }
.set-mini--on { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.set-mini--on:hover { color: var(--on-accent); }
.set-mini--danger { color: var(--danger); border-color: var(--line); }
.set-mini--danger:hover { border-color: var(--danger); color: var(--danger); }

/* Section 2 — priority notes */
.ctoday__notes { display: flex; flex-direction: column; gap: var(--space-2); }
.ctoday__note {
  display: block; width: 100%; text-align: left; padding: var(--space-3);
  border: 1px solid var(--line); border-left: 3px solid var(--muted); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); cursor: pointer;
}
.ctoday__note:hover { border-color: var(--accent); }
.ctoday__note--p1 { border-left-color: var(--accent); }
.ctoday__note--p2 { border-left-color: var(--warn); }
.ctoday__note--p3 { border-left-color: var(--danger); }
.ctoday__note-meta { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin-bottom: 4px; }
.ctoday__note-name { font-size: 13px; font-weight: 700; }
.ctoday__note-time { font-size: 11px; color: var(--muted); }
.ctoday__note-body { margin: 0; font-size: 13px; color: var(--ink-2); }

/* Section 3 — check-in review queue */
.ctoday__queue { display: flex; flex-direction: column; gap: var(--space-2); }
/* COACH-REVIEW-QUICK-ACTIONS — the row is a CONTAINER, never a control: the
   quick-message <form> lives inside it and a form may not nest in a button.
   So no cursor/appearance here; the name button and send button are the
   targets, which also makes "what happens if I tap" unambiguous. */
/* REVIEW-HET-SNELBERICHT-KLAPT-IN-TOT-EEN-KNOP — no row gap and 8px of vertical
   padding: with the quick-message field folded away the card is its top line and
   nothing else, and the gap would otherwise still separate a zero-height fold.
   Horizontal padding stays 12px. Measured: 114px → 58px per card (390px). */
.ctoday__qrow {
  display: flex; flex-direction: column; gap: 0; width: 100%; text-align: left;
  padding: var(--space-2) var(--space-3); border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink);
}
.ctoday__qtop { display: flex; align-items: center; gap: var(--space-2); width: 100%; }
.ctoday__qrow:hover { border-color: var(--accent); }
.ctoday__qmid {
  flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 4px;
  border: 0; background: transparent; color: inherit; padding: 0; cursor: pointer; font: inherit;
  align-items: flex-start; text-align: left;
}
.ctoday__qname { font-size: 14px; font-weight: 700; }
/* COACH-REVIEW-QUEUE-V2 — one action sentence per row replaces the chip row and
   the separate unread badge: saying the same thing twice is surface. */
.ctoday__qreason { font-size: 12px; color: var(--ink-2); text-align: left; }
/* REVIEW-DE-LIJST-WEET-WIE-JE-OP-LOCATIE-ZIET — de staart hoort BIJ de reden en
   staat een tint zachter: hij verklaart de rij, hij is niet het nieuws. */
.ctoday__qmode { color: var(--muted); }
/* RONDE-DE-RONDE-HEEFT-EEN-BODEM — de datum voor wie vandaag niet aan de beurt
   is. Een eigen regel onder de reden, een tint zachter: het is een belofte, geen
   melding, en het bouwt geen schuld op. */
.ctoday__qnext { font-size: 12px; color: var(--muted); text-align: left; }
/* Het expliciete einde. Een zin, geen confetti, geen badge, geen percentage. */
.ctoday__rounddone {
  padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink);
}
.ctoday__rounddone-title { font-size: 15px; font-weight: 700; margin: 0; }
.ctoday__rounddone-week { font-size: 12px; color: var(--ink-2); margin: 4px 0 0; }
.ctoday__rounddone-sub {
  font-size: 12px; font-weight: 600; color: var(--muted);
  margin: var(--space-3) 0 4px;
}
.ctoday__rounddone-list {
  margin: 0; padding-left: 1.1em; font-size: 12px; color: var(--ink-2);
  display: flex; flex-direction: column; gap: 2px;
}
/* Rank as a left edge — the top three ranks are the ones that need the eye. */
.ctoday__qrank--1 { border-left: 3px solid var(--danger); }
.ctoday__qrank--2 { border-left: 3px solid var(--warn); }
.ctoday__qrank--3 { border-left: 3px solid var(--line); }
/* Rank 7 = the weekly touchpoint reminder. No accent edge, muted name: it is a
   nudge, not a deviation, and must not compete with a real red row. */
.ctoday__qrow--soft .ctoday__qname { color: var(--muted); font-weight: 600; }
.ctoday__qdone {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; padding: 0; border: 0; border-radius: 999px;
  background: transparent; color: var(--muted); cursor: pointer; font-size: 12px;
}
.ctoday__qdone:hover { color: var(--accent); }
/* REVIEW-HET-SNELBERICHT-KLAPT-IN-TOT-EEN-KNOP — the folded field is a 40px
   icon on the top line, same box as the tick so the two read as one pair. */
.ctoday__qtoggle {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; padding: 0; border: 0; border-radius: 999px;
  background: transparent; color: var(--muted); cursor: pointer;
}
.ctoday__qtoggle:hover, .ctoday__qtoggle[aria-expanded="true"] { color: var(--accent); }
/* RONDE-DE-ACTIE-ZIT-IN-DE-REGEL — the handling as a word. Same 40px box as the
   two icons it stands between, only wider, so the row height is untouched: the
   fold this row already measured at <=72px must not re-inflate through a button.
   .ctoday__qgo is the one that LEAVES for the editor (no fold, no aria-expanded);
   .ctoday__qact is the shared worded shape both wear. */
.ctoday__qgo {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; padding: 0; border: 0; border-radius: 999px;
  background: transparent; color: var(--muted); cursor: pointer;
}
.ctoday__qgo:hover { color: var(--accent); }
.ctoday__qact {
  width: auto; gap: 6px; padding: 0 var(--space-3);
  color: var(--accent); font: inherit; font-size: 13px; font-weight: 600;
}
.ctoday__qactlbl { white-space: nowrap; }
/* The word costs the name block about 70px of width. Rather than let the reason
   wrap to a second line and push the card past the 72px it was halved to, the
   reason clips — and the part that falls off the end is the tracking tally, the
   same tail the row's own aria-label already leaves out on purpose. */
.ctoday__qtop--act .ctoday__qmid { overflow: hidden; }
.ctoday__qtop--act .ctoday__qname,
.ctoday__qtop--act .ctoday__qreason {
  max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* KLANTENRIJ-NAAM-EERST-OP-DE-TELEFOON — dezelfde regel als op Klanten en Geld:
   onder 480px levert de NAAM niet in. GEMETEN met 'Mariette van der
   Waterlanden' en de knop 'Voeding aanpassen': de naam was 165px op 375px en
   had er 204 nodig (39 te kort), 179 op 390 (25 te kort), 191 op 402 (13 te
   kort) en paste pas op 430. Het WOORD kost de naamkolom ~70px — ruim meer dan
   de 39 die het krapste geval tekortkwam, dus alle vier de breedtes komen in
   één keer vrij (gemeten na: 204px op elke breedte, en 204 is wat de naam
   nodig heeft).

   Waarom hier het woord wijkt en niet de naam: de regel eronder
   (.ctoday__qreason) zegt de handeling AL in woorden — 'Aanpassen: eiwit' —
   dus de knoptekst herhaalt op een telefoon wat er een regel lager staat,
   terwijl de naam nergens anders staat. Het icoon blijft, met zijn aria-label
   en title; dit is dus geen kale glyph zoals COACH-DUO-ICON-LABEL repareerde,
   maar een icoon naast zijn eigen zin. De 40px-doos van .ctoday__qgo blijft
   ongemoeid, dus de rijhoogte die REVIEW-HET-SNELBERICHT op 58px zette
   verandert niet — en vanaf 480px staat het woord er onveranderd.

   Geschreven als `.ctoday__qtop--act .ctoday__qact` en niet kaal: de
   bronscanner van ronde-de-actie-zit-in-de-regel pint `.ctoday__qact {` op
   positie én op `width: auto`, en een tweede kale regel met dezelfde naam
   maakt die pin dubbelzinnig. */
@media (max-width: 479px) {
  .ctoday__qtop--act .ctoday__qactlbl { display: none; }
  .ctoday__qtop--act .ctoday__qact { width: 40px; padding: 0; gap: 0; }
}
/* visibility, not just the 0fr track: a clipped input is still focusable and
   still hands a 40px box to anything that measures it. The visibility switch is
   a 0s step — instant on the way OPEN (the field is focused in the same tick,
   and you cannot focus something still computed hidden) and held back 220ms on
   the way closed so the fold is finished before the field disappears. */
.ctoday__qcollapse {
  display: grid; grid-template-rows: 0fr; visibility: hidden;
  transition: grid-template-rows 220ms ease, visibility 0s linear 220ms;
}
.ctoday__qcollapse.is-open {
  grid-template-rows: 1fr; visibility: visible;
  transition: grid-template-rows 220ms ease, visibility 0s linear 0s;
}
.ctoday__qinner { overflow: hidden; min-height: 0; }
@media (prefers-reduced-motion: reduce) { .ctoday__qcollapse { transition: none; } }
/* One line, send, next — full width under the name so the 390px row keeps
   every target at 40px without wrapping onto the name button. The top padding
   lives INSIDE the fold, so it costs nothing while the card is closed. */
.ctoday__qsend { display: flex; align-items: center; gap: 6px; width: 100%; padding-top: var(--space-2); }
.ctoday__qsend input {
  flex: 1 1 auto; min-width: 0; height: 40px; padding: 0 var(--space-2);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface-2); color: var(--ink); font: inherit; font-size: 13px;
}
.ctoday__qsend input:focus { outline: none; border-color: var(--accent); }
.ctoday__qsendbtn {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; padding: 0; border: 0; border-radius: 999px;
  background: transparent; color: var(--muted); cursor: pointer;
}
.ctoday__qsendbtn:hover { color: var(--accent); }
.ctoday__qsendbtn[disabled], .ctoday__qsend input[disabled] { opacity: 0.5; cursor: default; }
.ctoday__qprogress { margin: 0 0 var(--space-2); font-size: 12px; color: var(--ink-2); }
.ctoday__qdone-wrap { margin-top: var(--space-3); font-size: 13px; color: var(--ink-2); }
.ctoday__qdone-wrap summary { cursor: pointer; padding: var(--space-2) 0; }
.ctoday__qdone-wrap .ctoday__qdone { width: auto; padding: 0 var(--space-2); }

/* Section 4 — dashboard */
.ctoday__dash { display: flex; flex-direction: column; gap: var(--space-2); }
.cdash { border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); overflow: hidden; }
.cdash__head {
  display: flex; align-items: center; gap: var(--space-3); width: 100%;
  padding: var(--space-3); border: 0; background: transparent; color: var(--ink); cursor: pointer; text-align: left;
}
.cdash__head:hover { background: var(--line-2); }
.cdash__avatar {
  width: 32px; height: 32px; flex: 0 0 auto; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: var(--on-accent); font-size: 13px; font-weight: 700;
}
.cdash__name { font-size: 14px; font-weight: 600; flex: 0 0 auto; max-width: 28%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cdash__pills { flex: 1 1 auto; display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.cdash__pill {
  display: inline-flex; align-items: center; gap: 4px; padding: 3px 8px;
  border-radius: 999px; font-size: 11px; font-weight: 600;
  background: var(--line-2); color: var(--muted);
}
.cdash__pill-k { opacity: 0.75; }
.cdash__pill--within   { background: color-mix(in srgb, var(--ok) 18%, transparent); color: var(--ok); }
.cdash__pill--critical { background: color-mix(in srgb, var(--danger) 18%, transparent); color: var(--danger); }
.cdash__pill--no_data  { background: var(--line-2); color: var(--muted); }
.cdash__head > svg { flex: 0 0 auto; color: var(--muted); transition: transform 0.15s ease; }
.cdash__head.is-open > svg { transform: rotate(180deg); }
.cdash__body { padding: 0 var(--space-3) var(--space-3); display: grid; gap: var(--space-2); }

.cdash-metric { padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--radius); border-left: 3px solid var(--muted); }
.cdash-metric--within   { border-left-color: var(--ok); }
.cdash-metric--critical { border-left-color: var(--danger); }
.cdash-metric__top { display: flex; align-items: center; gap: var(--space-2); }
.cdash-metric__label { font-size: 13px; font-weight: 600; color: var(--ink); }
.cdash-metric__val { font-size: 13px; font-weight: 700; color: var(--ink-2); margin-left: auto; }
.cdash-metric__edit {
  width: 28px; height: 28px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); color: var(--muted); cursor: pointer;
}
.cdash-metric__edit:hover { border-color: var(--accent); color: var(--accent); }
.cdash-metric__chart { margin-top: var(--space-2); display: flex; align-items: center; gap: var(--space-3); }
.cdash-metric__thr { font-size: 11px; color: var(--muted); }
.cdash-metric__nodata { margin: var(--space-2) 0 0; font-size: 12px; color: var(--muted); }

/* threshold edit + bulk forms */
.csheet__panel--wide { max-width: 480px; }
.thr-form { display: flex; gap: var(--space-2); margin: var(--space-3) 0; }
.thr-form__sel, .thr-form__input {
  padding: 8px var(--space-3); border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); font-size: 14px;
}
.thr-form__sel { flex: 1 1 auto; }
.thr-form__input { width: 90px; }
.thr-form__err { color: var(--danger); font-size: 13px; margin: 0 0 var(--space-2); }
.bulk { margin-top: var(--space-3); }
.bulk__row { display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2); }
.bulk__label { flex: 1 1 auto; font-size: 14px; color: var(--ink); }
.bulk__row .thr-form__sel { flex: 0 0 64px; }

/* ════ Per-rule report card (ELKE-REGEL-KRIJGT-ZIJN-EIGEN-RAPPORTCIJFER) ════ */
/* A table of a handful of lines. Deliberately no bar, no ring and no coloured
   badge: a rule that needs attention gets a SENTENCE, because a colour invites
   a glance and this asks for a decision. */
.rulerep { margin-top: var(--space-4); border-top: 1px solid var(--line); padding-top: var(--space-3); }
.rulerep__h { font-size: 14px; font-weight: 600; color: var(--ink); margin-bottom: var(--space-1); }
.rulerep__empty { font-size: 13px; color: var(--ink-2); margin: var(--space-2) 0 0; }
.rulerep__rule { margin-top: var(--space-3); }
.rulerep__name { font-size: 14px; color: var(--ink); }
.rulerep__nums { font-size: 13px; color: var(--ink-2); }
.rulerep__why { font-size: 12px; color: var(--ink-2); margin-top: 2px; }
.rulerep__warn { font-size: 13px; color: var(--ink); margin: var(--space-1) 0 0; }

/* ════ Control charts (COACH-CONTROL-CHARTS-OVERVIEW-PAGE-AND-PER-CLIENT-PANEL-1) ════ */
/* Panel-1 per-client control chart (above the intake card) */
.cctrl__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); flex-wrap: wrap; }
.cctrl__span { display: inline-flex; border: 1px solid var(--line); border-radius: 999px; overflow: hidden; }
.cctrl__span-btn {
  padding: 4px var(--space-3); border: 0; background: var(--surface);
  color: var(--ink-2); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
}
.cctrl__span-btn + .cctrl__span-btn { border-left: 1px solid var(--line); }
.cctrl__span-btn--on { background: var(--accent); color: var(--on-accent); }
.cctrl__loading, .cctrl__empty { margin: 0; color: var(--muted); font-size: 13px; }

/* /control-charts overview page */
.ccpage__bar {
  position: sticky; top: 0; z-index: 4;
  display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap;
  padding: var(--space-2) 0; margin-bottom: var(--space-4);
  background: var(--bg);
}
.ccpage__ts, .ccpage__metric {
  display: inline-flex; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden;
}
.ccpage__ts-btn, .ccpage__metric-btn {
  padding: 5px var(--space-3); border: 0; background: var(--surface);
  color: var(--ink-2); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
}
.ccpage__ts-btn + .ccpage__ts-btn, .ccpage__metric-btn + .ccpage__metric-btn { border-left: 1px solid var(--line); }
.ccpage__ts-btn.is-on, .ccpage__metric-btn.is-on {
  background: color-mix(in srgb, var(--accent) 16%, var(--surface));
  color: var(--accent); border-color: var(--accent);
}

.ccgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: var(--space-3); }
.ccgrid__loading, .ccgrid__empty { margin: 0; color: var(--muted); font-size: 13px; grid-column: 1 / -1; }
.cccard {
  display: flex; flex-direction: column; gap: var(--space-2); text-align: left;
  padding: var(--space-3); border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface); cursor: pointer; font: inherit;
}
.cccard:hover { border-color: var(--accent); }
.cccard:active { transform: scale(0.99); }
.cccard__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.cccard__name { font-size: 14px; font-weight: 700; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cccard__pill {
  flex: 0 0 auto; padding: 3px 8px; border-radius: 999px;
  font-size: 11px; font-weight: 700; white-space: nowrap;
}
.cccard__pill--in { background: color-mix(in srgb, var(--accent) 16%, var(--surface)); color: var(--accent); }
.cccard__pill--out { background: var(--danger); color: var(--on-accent); }
.cccard__chart { width: 100%; }
/* F-12: informative empty state — a div (not a button), so it doesn't invite a
   tap; the nudge inside is the only affordance. */
div.cccard { cursor: default; }
div.cccard:hover { border-color: var(--line); }
.cccard__empty { margin: var(--space-1) 0 var(--space-2); color: var(--muted); font-size: 13px; line-height: 1.4; }
.cccard__nudge {
  display: inline-flex; align-items: center; gap: 5px; align-self: flex-start;
  padding: 6px 12px; border: 1px solid var(--accent); border-radius: 999px;
  background: transparent; color: var(--accent); font: inherit; font-size: 13px; font-weight: 700; cursor: pointer;
}
.cccard__nudge:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.cccard__nudge:active { transform: scale(0.98); }
.cccard__nudge svg { flex: 0 0 auto; }

/* ── Charts page sub-tabs + nutrition cue + sparkline grid (COACH-CHARTS-REFACTOR) ── */
.chtabs {
  position: sticky; top: 0; z-index: 4;
  display: inline-flex; gap: 0; margin-bottom: var(--space-4);
  border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; background: var(--bg);
}
.chtabs__btn {
  padding: 7px var(--space-4); border: 0; background: var(--surface);
  color: var(--ink-2); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.chtabs__btn + .chtabs__btn { border-left: 1px solid var(--line); }
.chtabs__btn.is-on {
  background: color-mix(in srgb, var(--accent) 16%, var(--surface));
  color: var(--accent); border-color: var(--accent);
}
.chtabs__body { display: block; }

.cccard__namewrap { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.cccard__namewrap > svg { flex: 0 0 auto; color: var(--accent); }
.cccard__nutri {
  flex: 0 0 auto; padding: 2px 7px; border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 14%, var(--surface)); color: var(--accent);
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
}

/* ── Adherence glance + triage board (COACH-ADHERENCE-GLANCE-REDESIGN) ── */
/* Panel-1 per-client status block: a status dot + one plain-language line per
   metric, replacing the old 2×2 sparkline grid. Red only when action needed. */
.cadh__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); flex-wrap: wrap; }
.cadh__span { display: inline-flex; border: 1px solid var(--line); border-radius: 999px; overflow: hidden; }
.cadh__span-btn {
  padding: 4px var(--space-3); border: 0; background: var(--surface);
  color: var(--ink-2); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
}
.cadh__span-btn + .cadh__span-btn { border-left: 1px solid var(--line); }
.cadh__span-btn--on { background: var(--accent); color: var(--on-accent); }
.cadh__loading, .cadh__empty { margin: 0; color: var(--muted); font-size: 13px; }
.cadh__rows { display: flex; flex-direction: column; gap: var(--space-2); }
.cadh__row { display: flex; align-items: flex-start; gap: var(--space-2); }
.cadh__text { font-size: 13px; line-height: 1.4; color: var(--ink); }

/* DE-VIER-GEDRAGSCIJFERS-KRIJGEN-HUN-LIJN — the series beside the sentence.
   margin-left:auto pins it to the right edge without touching .cadh__text, which
   does not grow. Fixed 64px so every row's line is read on the same width. */
.cadh__spark { flex: 0 0 64px; margin-left: auto; }
/* Inside a pill the base .spark rule (width:100%) would stretch it over the
   number, so the 36px is held here instead. */
.cdash__pill .spark { flex: 0 0 36px; width: 36px; }
/* The mean line stays neutral and dashed: the dot (and the pill's own tint)
   already carries the state, and a second colour carrier on one row is one
   signal too many. Never --danger — a reference line is not an alarm. */
.spark__mean { fill: none; stroke: var(--muted); stroke-width: 1; stroke-dasharray: 2 2; }

/* Shared status dots — green=on track, orange=watch, red=action, grey=no data. */
.cadh__dot, .triage__dot {
  flex: 0 0 auto; width: 10px; height: 10px; border-radius: 50%; background: var(--muted);
}
.cadh__dot { margin-top: 4px; }
.cadh__dot--ok,   .triage__dot--ok   { background: var(--ok); }
.cadh__dot--warn, .triage__dot--warn { background: var(--warn); }
.cadh__dot--act,  .triage__dot--act  { background: var(--danger); }
.cadh__dot--none, .triage__dot--none { background: var(--muted); }

/* DOSSIER-DE-COACH-ZIET-OF-HET-DAGRITME-GEDAAN-WORDT +
   DAGRITME-DE-COACH-GEEFT-EEN-GEWOONTE-MEE — the day-rhythm block borrows the
   adherence rows wholesale; the phase headings, the sub-line and the cross are
   its own. No bar, no percentage, and since this phase no verdict dot either:
   the card shows the two numbers the verdict was made of and lets the coach
   read them himself. */
.cdcy__phase {
  margin: var(--space-3) 0 var(--space-1); font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted);
}
.cdcy__phase:first-child { margin-top: 0; }
.cdcy__texts { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.cdcy__name { min-width: 0; }
/* 'tot 22 nov · van jou' — één grijze regel onder de naam. */
.cdcy__sub { font-size: 11px; line-height: 1.3; color: var(--muted); }
.cdcy__days {
  flex: 0 0 auto; font-size: 12px; line-height: 1.4; color: var(--muted);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* Het kruisje. Alleen op een stap die DEZE coach zelf meegaf — geen kleur, want
   iets terugnemen wat je zelf voorstelde is geen gevaar, het is een correctie. */
.cdcy__x {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; margin: -4px -4px -4px 0; padding: 0;
  border: 0; border-radius: 50%; background: transparent; color: var(--muted); cursor: pointer;
}
.cdcy__x:hover { background: var(--line-2); color: var(--ink); }
.cdcy__x[disabled] { opacity: 0.5; cursor: default; }
/* Slaap is één regel: afspraak naast meting. Nooit een score. */
.cdcy__sleep {
  margin: var(--space-3) 0 0; font-size: 12px; line-height: 1.4; color: var(--muted);
}
/* Twee deuren onder elkaar op een telefoon: beide een echt duimvlak van 44px,
   anders staan ze zo dicht op elkaar dat je de verkeerde raakt. */
.cdcy__add { margin-top: var(--space-3); width: 100%; min-height: 44px; }
/* COACH-HET-HELE-DAGRITME-VAN-JE-KLANT-OP-EEN-PAGINA — de tweede deur staat ONDER
   'een stap erbij' en is secundair: één stap toevoegen is de handeling die hier
   het vaakst nodig is, de hele pagina is de uitzondering die je soms wilt. */
.cdcy__all { margin-top: var(--space-2); width: 100%; min-height: 44px; }

/* DAGRITME-DE-COACH-GEEFT-EEN-GEWOONTE-MEE — de drie vragen. Eén vraag per
   scherm (CHECKIN-ONE-FIELD-PER-QUESTION): een coach die drie velden tegelijk
   ziet vult het bovenste in en raadt de rest. */
.cdcy-add__q { margin: 0 0 var(--space-3); font-size: 16px; font-weight: 700; color: var(--ink); }
.cdcy-add__field { display: flex; flex-direction: column; gap: var(--space-2); }
.cdcy-add__chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.cdcy-add__chip {
  padding: 8px var(--space-3); min-height: 36px;
  border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); color: var(--ink); font: inherit; font-size: 13px; cursor: pointer;
}
.cdcy-add__chip:hover { background: var(--line-2); }
.cdcy-add__chip[aria-pressed="true"] {
  background: var(--accent); border-color: var(--accent); color: var(--on-accent); font-weight: 700;
}
/* Avond / Ochtend: twee even grote deuren, want er is geen voorkeur. */
.cdcy-add__two { display: flex; gap: var(--space-2); }
.cdcy-add__big {
  flex: 1 1 0; min-height: 52px;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); font: inherit; font-size: 15px; font-weight: 600;
  cursor: pointer;
}
.cdcy-add__big[aria-pressed="true"] {
  background: var(--accent); border-color: var(--accent); color: var(--on-accent);
}
/* Een waarschuwing, nooit een blokkade — dus de kleur van 'let op', niet van 'fout'. */
.cdcy-add__warn { margin: var(--space-3) 0 0; font-size: 12px; line-height: 1.4; color: var(--warn); }
.cdcy-add__next { margin-top: var(--space-4); width: 100%; }

/* DAGRITME-JE-CIJFERS-IN-TRENDS-EN-BIJ-JE-COACH — de soort-kiezer: vier tegels
   op twee rijen, zelfde raster als de tegels in de editor van de klant, zodat
   coach en klant naar hetzelfde vlakje kunnen wijzen. Icoon boven het woord: op
   390px is een tegel met het woord ernaast een tegel met een afgekapt woord. */
.cdcy-add__tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2); }
.cdcy-add__tile {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; min-height: 76px; padding: var(--space-2);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); font: inherit; cursor: pointer;
}
.cdcy-add__tile:hover { background: var(--line-2); }
.cdcy-add__tile-word { font-size: 13px; font-weight: 600; line-height: 1.2; text-align: center; }
.cdcy-add__tile[aria-checked="true"] {
  background: var(--accent); border-color: var(--accent); color: var(--on-accent);
}

/* DAGRITME-JE-CIJFERS-IN-TRENDS-EN-BIJ-JE-COACH — de cijfers die de klant zélf
   gaf, onder de rijen die hij afvinkt. Eén kleur voor beide lijnen: het is
   tweemaal dezelfde vraag op één dag, dus de STREEP is het verschil, niet de
   tint. Nooit een percentage en nooit een kleurband: dit is gespreksstof. */
.cdsc { margin-top: var(--space-4); }
.cdsc:empty { margin-top: 0; }
.cdsc__h { margin: 0 0 var(--space-1); font-size: 13px; font-weight: 700; color: var(--ink); }
.cdsc__legend {
  display: flex; gap: var(--space-3); align-items: center; margin-bottom: var(--space-2);
  font-size: 10px; font-weight: 600; color: var(--muted);
}
.cdsc__legend-item { display: inline-flex; align-items: center; gap: 5px; }
.cdsc__legend-line {
  display: inline-block; width: 14px; height: 0; border-top: 1.6px solid var(--accent);
}
.cdsc__legend-line--evening { border-top-style: dashed; }
.cdsc__topic + .cdsc__topic { margin-top: var(--space-3); }
.cdsc__hd { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); }
.cdsc__name { font-size: 13px; font-weight: 600; color: var(--ink); min-width: 0; }
.cdsc__avg {
  flex: 0 0 auto; font-size: 11px; color: var(--muted);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* De 0-10 ladder staat er ALTIJD bij: een lijn zonder as is een vorm zonder maat,
   en dan leest 6-7-6 als een berglandschap. */
.cdsc__chart { display: flex; gap: 6px; align-items: stretch; }
.cdsc__ygutter {
  flex: 0 0 auto; display: flex; flex-direction: column; justify-content: space-between;
  font-size: 9px; color: var(--muted); font-variant-numeric: tabular-nums;
}
.cdsc__svg { flex: 1 1 auto; width: 100%; height: 56px; overflow: visible; }
/* non-scaling-stroke want de svg wordt met preserveAspectRatio="none" uitgerekt:
   zonder dit wordt een 1,6px lijn een ovale veeg (en de streepjes van de avond
   onleesbaar lang). Zelfde truc als .spark-line in de app zelf. */
.cdsc__line {
  fill: none; stroke: var(--accent); stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke;
}
.cdsc__line--evening { stroke-dasharray: 5 3; }
.cdsc__dot { fill: var(--accent); stroke: none; }
.cdsc__foot { margin-top: 2px; font-size: 10px; color: var(--muted); }

/* DOSSIER-WATER-STAAT-ERBIJ-ALS-WATER-DE-METING-IS — seven day columns, height
   is the share of the busiest day. One neutral ink for every column: no red, no
   green, no goal line. A colour here would score the client, and the strip
   exists to start a conversation, not to hand out a verdict. */
.cwtr__strip {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: var(--space-1); align-items: end; margin-bottom: var(--space-2);
}
.cwtr__col { display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0; }
.cwtr__val {
  font-size: 10px; line-height: 1.2; color: var(--muted);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.cwtr__track {
  width: 100%; height: 56px; border-radius: 4px;
  background: var(--line-2); display: flex; align-items: flex-end; overflow: hidden;
}
.cwtr__fill { width: 100%; min-height: 2px; border-radius: 4px; background: var(--ink-2); }
.cwtr__dow { font-size: 10px; line-height: 1.2; color: var(--muted); white-space: nowrap; }
.cwtr__sum { margin: 0; font-size: 13px; font-weight: 700; color: var(--ink); }

/* Charts → Adherence overview: exception-based triage board. */
.triage { display: flex; flex-direction: column; gap: var(--space-2); }
.triage__loading, .triage__empty { margin: 0; color: var(--muted); font-size: 13px; }
.triage__title {
  margin: 0 0 var(--space-1); font-size: 13px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.03em;
}
.triage__row {
  display: flex; align-items: center; gap: var(--space-2); text-align: left; width: 100%;
  padding: var(--space-3); border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface); cursor: pointer; font: inherit;
}
.triage__row:hover { border-color: var(--accent); }
.triage__row:active { transform: scale(0.99); }
.triage__rowbody { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.triage__name { font-size: 14px; font-weight: 700; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.triage__reason { font-size: 12px; color: var(--muted); }
.triage__row > svg { flex: 0 0 auto; color: var(--muted); }
.triage__calm, .triage__clear {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3); color: var(--muted); font-size: 13px;
}
.triage__clear { padding: var(--space-3); }

/* ── COACH-CHARTS-UNIFIED-TRIAGE-LIST ── */
.chpage__cards { margin-top: var(--space-4); }
.chpage__sectitle {
  margin: 0 0 var(--space-2); font-size: 13px; font-weight: 700;
  color: var(--muted); text-transform: uppercase; letter-spacing: .04em;
}
.triage__row--static { cursor: default; }
.triage__row--static:hover { border-color: var(--line); }
.triage__row--static .cccard__nudge { flex: 0 0 auto; }
.triage__calm--tap {
  width: 100%; background: none; border: 0; text-align: left; cursor: pointer;
  font: inherit;
}
.triage__calm--tap > svg { margin-left: auto; color: var(--muted); transition: transform .15s; }
.triage__calm--tap.is-open > svg { transform: rotate(90deg); }
.triage__oklist { display: flex; flex-direction: column; gap: var(--space-2); }

.nutcard__titlewrap { display: inline-flex; align-items: center; gap: 6px; }
.nutcard__titlewrap > svg { flex: 0 0 auto; color: var(--accent); }

/* ── COACH-PER-CLIENT-TAB-VISIBILITY-TOGGLES — Panel-1 chip row ── */
.tabvis {
  margin: var(--space-3) 0; padding: var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
}
.tabvis__chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.tabvis__hint { margin: var(--space-2) 0 0; font-size: 12px; line-height: 1.4; color: var(--muted); }
/* DE-KLANTENLIJST-VERTELT-WAAROM — de bron-regel leest voor, hij schakelt niet.
   Daarom geen chipvorm en geen aanraakdoel: gewoon een regel tekst boven de
   schakelaars, met ruimte voor de volle einddatum. */
.tabvis__source {
  margin: 0 0 var(--space-3); font-size: 13px; line-height: 1.4; font-weight: 600;
}
.tabvis__standing { margin-top: var(--space-3); display: inline-flex; align-items: center; gap: 6px; }
.tabvis__chip {
  appearance: none; cursor: pointer; font: inherit; font-size: 13px; font-weight: 600;
  padding: 6px 14px; border-radius: var(--radius-pill, 999px);
  border: 1px solid var(--line-2); background: transparent; color: var(--muted);
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.tabvis__chip:active { transform: scale(0.97); }
.tabvis__chip--on { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.tabvis__bulk {
  appearance: none; cursor: pointer; font: inherit; font-size: 12px; font-weight: 600;
  margin-top: var(--space-3); padding: 6px 12px; border-radius: var(--radius-sm, 8px);
  border: 1px solid var(--line-2); background: transparent; color: var(--ink);
}
.tabvis__bulk:active { transform: scale(0.98); }
/* COACH-TABS-ADMIN-ONLY-TRISTATE-CONTROL — per-tab three-state segmented control */
.tabvis__row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); margin-bottom: var(--space-2); }
.tabvis__row-label { font-size: 13px; font-weight: 600; color: var(--ink); }
.tabvis__seg { display: inline-flex; border: 1px solid var(--line-2); border-radius: var(--radius-pill, 999px); overflow: hidden; }
.tabvis__seg-btn {
  appearance: none; cursor: pointer; font: inherit; font-size: 12px; font-weight: 600;
  padding: 5px 12px; border: 0; background: transparent; color: var(--muted);
  transition: background 0.15s ease, color 0.15s ease;
}
.tabvis__seg-btn + .tabvis__seg-btn { border-left: 1px solid var(--line-2); }
.tabvis__seg-btn:active { transform: scale(0.97); }
.tabvis__seg-btn--on { background: var(--accent); color: var(--on-accent); }
/* VOEDING-MEETVORM-IN-HET-KLANTDOSSIER — keuze links, bewijs rechts. Alles hier
   hergebruikt de tabvis-knoppen; dit is enkel de tweekoloms-wikkel plus de
   bewijsregels. BEWUST geen balk, geen percentage en geen rood/groen: kleur
   maakt van een telling een oordeel, en dat is precies wat hier niet mag. */
/* COACH-NIETS-LOOPT-NOG-BUITEN-ZIJN-VAK (L183 #4) — de tweekoloms-omschakeling
   hieronder stond op `@media (min-width: 640px)`, dus op een laptop van 1280px
   schakelde hij om terwijl de kaart in een dossierpaneel van ~350px staat: de
   bewijskolom (`min-width: 220px`) stak 53-69px buiten zijn kaart. De kaart is
   nu zelf een query-container en de omschakeling kijkt naar HAAR breedte. */
.nutmeas { container-type: inline-size; }
.nutmeas__cols { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-3); }
/* Zes standen passen niet op één regel van 390px. Ze wikkelen daarom als losse
   pillen in plaats van als één aaneengesloten segment: een segmentbalk die
   afbreekt houdt zijn buitenrand niet en leest als een kapotte rand. */
.nutmeas__seg {
  display: flex; flex-wrap: wrap; gap: 6px;
  border: 0; border-radius: 0; overflow: visible;
}
.nutmeas__seg .tabvis__seg-btn {
  border: 1px solid var(--line-2); border-radius: var(--radius-pill, 999px); padding: 6px 14px;
}
.nutmeas__seg .tabvis__seg-btn + .tabvis__seg-btn { border-left: 1px solid var(--line-2); }
.nutmeas__seg .tabvis__seg-btn--on { border-color: var(--accent); }
.nutmeas__origin { margin: var(--space-2) 0 0; font-size: 11px; color: var(--muted); }
/* VOEDING-ZACHTE-START-VEERTIEN-DAGEN — het voorstel na veertien dagen. */
.nutmeas__prop { margin-top: var(--space-3); padding-top: var(--space-3); border-top: 1px solid var(--line-2); }
.nutmeas__propdays { margin: 0; font-size: 13px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.nutmeas__propmsg { margin: 4px 0 0; font-size: 12px; color: var(--muted); }
.nutmeas__propanchor { margin: 4px 0 0; font-size: 12px; font-style: italic; color: var(--ink); }
.nutmeas__propbtn { margin-top: var(--space-2); border-radius: var(--radius-sm); border: 1px solid var(--line-2); }
.tabvis__seg-btn--suggested { outline: 2px dashed var(--accent); outline-offset: -2px; }
.nutmeas__evhead { display: block; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); margin-bottom: var(--space-2); }
.nutmeas__evrow { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); padding: 4px 0; }
.nutmeas__evlabel { font-size: 12px; color: var(--muted); }
.nutmeas__evval { font-size: 13px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
/* 520px = 220px bewijs + 24px gap + ~276px voor de pillenkolom. Een container
   query, geen media query: zie de notitie bij .nutmeas. */
@container (min-width: 520px) {
  .nutmeas__cols { grid-template-columns: minmax(0, 1fr) auto; align-items: start; }
  .nutmeas__evidence { min-width: 220px; }
}
/* VOEDING-BEREKENDE-VERBRANDING-TELT-VOOR-DRIEKWART-MEE — dezelfde pilvorm als
   de meetladder erboven, want het is dezelfde soort keuze, maar met een EIGEN
   prefix: .nutmeas .tabvis__hint wordt in een visuele test binnen die kaart
   geteld, en een hint met dezelfde klasse in de buurkaart is daar een
   strict-mode-fout. Vijf standen, kort genoeg voor één regel, maar de wrap
   staat er toch in voor een langere vertaling van 'Standaard'. */
.burnret__seg {
  display: flex; flex-wrap: wrap; gap: 6px;
  border: 0; border-radius: 0; overflow: visible;
}
.burnret__seg .tabvis__seg-btn {
  border: 1px solid var(--line-2); border-radius: var(--radius-pill, 999px); padding: 6px 14px;
}
.burnret__seg .tabvis__seg-btn + .tabvis__seg-btn { border-left: 1px solid var(--line-2); }
.burnret__seg .tabvis__seg-btn--on { border-color: var(--accent); }
.burnret__hint { margin: var(--space-2) 0 0; font-size: 12px; color: var(--muted); }
.burnret__standard { margin: 4px 0 0; font-size: 12px; color: var(--muted); }
.burnret__origin { margin: var(--space-2) 0 0; font-size: 11px; color: var(--muted); }
/* DELOAD-DE-TRAINER-KIEST — dezelfde pil-vorm als de meetladder, want het is
   dezelfde soort keuze: één coachbesluit over één klant. Drie standen passen op
   390px wél op één regel, maar de wrap staat er toch in — een vertaling die
   langer is dan het Nederlands mag de rand niet breken. */
.dlform__seg {
  display: flex; flex-wrap: wrap; gap: 6px;
  border: 0; border-radius: 0; overflow: visible;
}
.dlform__seg .tabvis__seg-btn {
  border: 1px solid var(--line-2); border-radius: var(--radius-pill, 999px); padding: 6px 14px;
}
.dlform__seg .tabvis__seg-btn + .tabvis__seg-btn { border-left: 1px solid var(--line-2); }
.dlform__seg .tabvis__seg-btn--on { border-color: var(--accent); }
/* Eigen klasse, bewust niet .tabvis__hint van de buurregel: die staat op ditzelfde
   scherm al onder een andere kaart en een gedeelde klasse maakt van elke poort
   een strict-mode-botsing. */
.dlform__effect {
  margin: var(--space-2) 0 0; font-size: 12px; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
/* ADHERENCE-TALK-PER-CLIENT-DOSSIER-SETTING — a row whose governing switch is
   Off: dimmed and inert, but still on screen (hiding it would read as "the
   setting is gone"). --stack carries the seven-option day/hour rows: label
   above, segmented control below and scrollable, because seven segments plus a
   label overflow a phone row. */
.tabvis__row--off { opacity: 0.45; }
.tabvis__row--off .tabvis__seg-btn { cursor: default; }
.tabvis__row--stack { flex-direction: column; align-items: flex-start; gap: 6px; }
.tabvis__row--stack .tabvis__seg { max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.tabvis__row--stack .tabvis__seg-btn { flex: 0 0 auto; }

/* COACH-KAN-GYM-WEERGAVE-WEER-OMZETTEN — the per-client Gym-view switch reuses
   the .tabvis primitives; only the label + question-mark affordance are its own,
   so the explanation stays one line behind a tap instead of a paragraph. */
.gymview__lblwrap { display: inline-flex; align-items: center; gap: 6px; }
.gymview__help {
  appearance: none; cursor: pointer; font: inherit; font-size: 11px; font-weight: 700;
  width: 18px; height: 18px; line-height: 1; padding: 0; border-radius: 999px;
  border: 1px solid var(--line-2); background: transparent; color: var(--muted);
}
.gymview__hint { margin: 0 0 var(--space-2); font-size: 12px; line-height: 1.4; color: var(--muted); }
.gymview__hint[hidden] { display: none; }

/* ════ COACH-DOSSIER-INFO-REARRANGE ════
   Section order per dossier tab: Noordster → Signaal → Notities → Detail. The
   Detail tier is one collapsible container; the collapse idiom is the shipped
   DIARY-ADHERENCE-RING-COLLAPSE-CARDS one (grid-template-rows 0fr→1fr). */
.ddetail {
  margin: var(--space-3) 0; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface); overflow: hidden;
}
.ddetail__toggle {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  width: 100%; padding: var(--space-3) var(--space-4);
  border: 0; background: transparent; color: var(--ink);
  font: inherit; font-size: 14px; font-weight: 600; text-align: left; cursor: pointer;
}
.ddetail__lbl { min-width: 0; }
.ddetail__chev { flex: 0 0 auto; color: var(--muted); transition: transform 200ms ease; }
.ddetail__toggle[aria-expanded="true"] .ddetail__chev { transform: rotate(180deg); }
.ddetail__collapse { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 220ms ease; }
.ddetail__collapse.is-open { grid-template-rows: 1fr; }
.ddetail__inner { overflow: hidden; min-height: 0; }
.ddetail__body { padding: 0 var(--space-4) var(--space-4); }
@media (prefers-reduced-motion: reduce) {
  .ddetail__chev, .ddetail__collapse { transition: none; }
}

/* ════ COACH-CLIENT-SCREEN-GROUP-METRICS-UNDER-A-DISCLOSURE ════
   `.gdisc` is the reusable "one line instead of a wide field" primitive: a quiet
   label row + optional count, and everything else folded away underneath. It is
   deliberately chromeless (no card, no border) so it can sit INSIDE an existing
   card — unlike `.ddetail`, which is itself a section container. */
.gdisc { display: flex; flex-direction: column; }
.gdisc__toggle {
  display: flex; align-items: center; gap: var(--space-2);
  width: 100%; padding: var(--space-1) 0;
  border: 0; background: transparent; color: var(--ink);
  font: inherit; font-size: 12px; font-weight: 600; text-align: left; cursor: pointer;
}
.gdisc__lbl { color: var(--muted); min-width: 0; }
.gdisc__count {
  flex: 0 0 auto; padding: 1px 8px; border-radius: var(--radius-pill);
  border: 1px solid var(--line); background: var(--bg); color: var(--muted);
  font-size: 11px; font-weight: 600;
}
.gdisc__chev { flex: 0 0 auto; margin-left: auto; color: var(--muted); transition: transform 200ms ease; }
.gdisc__toggle[aria-expanded="true"] .gdisc__chev { transform: rotate(180deg); }
.gdisc__toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-sm); }
.gdisc__collapse { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 220ms ease; }
.gdisc__collapse.is-open { grid-template-rows: 1fr; }
.gdisc__inner { overflow: hidden; min-height: 0; }
.gdisc__body { padding-top: var(--space-2); }
@media (prefers-reduced-motion: reduce) {
  .gdisc__chev, .gdisc__collapse { transition: none; }
}

/* Empty-state rule (F-15): a blank field renders as one inviting line with a
   plus signifier, never as a dash or a hollow card. */
.dempty {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 1px dashed var(--line); border-radius: var(--radius);
  background: transparent; color: var(--muted);
  font: inherit; font-size: 14px; text-align: left; cursor: pointer;
}
.dempty svg { flex: 0 0 auto; }
.dempty:active { border-color: var(--accent); color: var(--accent); }
.intake-field .dempty { padding: 2px 8px; font-size: 13px; }

/* Manage card (tier 5, Client tab): account facts inherited from the retired
   "More client info" sheet, then the two access blocks rendered flush. */
.dacct {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3); margin-bottom: var(--space-3);
}
.dacct__val { font-size: 13px; overflow-wrap: anywhere; }
.tabvis--flush { margin: 0 0 var(--space-3); padding: 0; border: 0; background: transparent; }
.tabvis--flush:last-child { margin-bottom: 0; }

/* Access chips carry their state, not just their tappability (F-16). */
.tabvis__chip { display: inline-flex; align-items: center; gap: 6px; }
.tabvis__mark { display: inline-flex; flex: 0 0 auto; }
.tabvis__chip-tx { min-width: 0; }
.tabvis__chip[aria-checked="false"] { border-style: dashed; }
.tabvis__state {
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.04em; opacity: 0.85;
}

/* ════ Templates library + bulk-assign (COACH-TEMPLATE-BULK-ASSIGN-MULTI-CLIENT) ════ */
.clib__row--static { cursor: default; }
.clib__row--static:active { background: var(--surface); }
.bulkassign__list {
  display: flex; flex-direction: column; gap: var(--space-2);
  margin: var(--space-3) 0; max-height: 46vh; overflow-y: auto;
}
.bulkassign__row {
  display: flex; align-items: center; gap: var(--space-3);
  width: 100%; padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); font: inherit; text-align: left; cursor: pointer;
}
.bulkassign__row:active { background: var(--line-2); }
.bulkassign__check {
  width: 22px; height: 22px; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line-2); border-radius: 6px; color: transparent;
}
.bulkassign__row--on { border-color: var(--accent); }
.bulkassign__row--on .bulkassign__check { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.bulkassign__name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bulkassign__confirm {
  appearance: none; cursor: pointer; font: inherit; font-size: 14px; font-weight: 600;
  width: 100%; padding: 10px var(--space-3); border-radius: var(--radius);
  border: 1px solid var(--accent); background: var(--accent); color: var(--on-accent);
}
.bulkassign__confirm:disabled { opacity: 0.5; cursor: not-allowed; }
.bulkassign__confirm:active { background: var(--accent-2); }

/* ───────── COACH-INTAKE-QUESTION-EDITOR-PENCIL ───────── */
.acintake__bar { display: flex; justify-content: flex-end; margin-bottom: var(--space-3); }
.acintake__edit {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: 6px var(--space-3); border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-2);
  font: inherit; font-size: 0.85rem; font-weight: 600; cursor: pointer;
}
.acintake__edit:active { border-color: var(--accent); color: var(--accent); }

/* ── COACH-SELF-SERVICE-INTAKE-LINK — Intake-tab chooser + link pane ── */
.acintake-choose__lead, .acintake-link__lead {
  margin: 0 0 var(--space-2); color: var(--muted); font-size: 14px;
}
.acintake-choose__card {
  display: flex; align-items: center; gap: var(--space-3); width: 100%;
  padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--bg); color: var(--ink); text-align: left; cursor: pointer;
}
.acintake-choose__card:active { border-color: var(--accent); }
.acintake-choose__card > svg:first-child { color: var(--accent); flex: 0 0 auto; }
.acintake-choose__mid { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.acintake-choose__title { font-size: 15px; font-weight: 700; }
.acintake-choose__sub { font-size: 12px; color: var(--muted); }
.acintake-link__back {
  display: inline-flex; align-items: center; gap: 4px; align-self: flex-start;
  padding: 4px 0; border: 0; background: transparent; color: var(--muted);
  font: inherit; font-size: 13px; cursor: pointer;
}
.acintake-link__field { display: flex; gap: var(--space-2); }
.acintake-link__field .acinput { flex: 1; min-width: 0; }
.acintake-link__copy {
  border: 0; background: var(--accent); color: var(--on-accent);
  padding: 0 var(--space-4); border-radius: var(--radius);
  font-size: 14px; font-weight: 700; cursor: pointer; white-space: nowrap;
}
.acintake-link__hint { margin: var(--space-2) 0 0; color: var(--muted); font-size: 12px; }

.iqe { display: flex; flex-direction: column; gap: var(--space-5); }

.iqe__locked {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--bg); padding: var(--space-3); opacity: 0.9;
}
.iqe__locked-head { display: flex; align-items: center; gap: var(--space-2); color: var(--muted); }
.iqe__locked-title { font-weight: 700; font-size: 0.9rem; }
.iqe__locked-note { color: var(--muted); font-size: 0.8rem; margin: var(--space-1) 0 var(--space-3); }
.iqe__locked-rows { display: flex; flex-direction: column; gap: var(--space-1); }
.iqe__locked-row {
  display: flex; align-items: center; gap: var(--space-2);
  color: var(--muted); font-size: 0.85rem;
}

.iqe__custom-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-3); }
.iqe__custom-title { font-size: 1rem; font-weight: 700; color: var(--ink); margin: 0; }
.iqe__add {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: 6px var(--space-3); border-radius: 999px;
  border: 1px solid var(--accent); background: var(--accent); color: var(--on-accent);
  font: inherit; font-size: 0.85rem; font-weight: 600; cursor: pointer;
}
.iqe__add:disabled { opacity: 0.5; cursor: not-allowed; }
.iqe__add:active { background: var(--accent-2); }

.iqe__list { display: flex; flex-direction: column; gap: var(--space-2); }
.iqe__empty { color: var(--muted); font-size: 0.9rem; padding: var(--space-3) 0; }

.iqe__card {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); padding: var(--space-3);
}
.iqe__card--edit { flex-direction: column; }
.iqe__card-main { min-width: 0; flex: 1; }
.iqe__card-label { color: var(--ink); font-size: 0.92rem; font-weight: 600; }
.iqe__card-meta { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-top: var(--space-2); }
.iqe__badge {
  font-size: 0.72rem; font-weight: 600; color: var(--ink-2);
  background: var(--line-2); border-radius: 999px; padding: 2px 8px;
}
.iqe__badge--req { color: var(--accent); background: transparent; border: 1px solid var(--accent); }
/* INTAKE-VRAGEN-IN-JE-EIGEN-TAAL — Sassu copy travels with the client's language, the
   coach's own words never do. Filled vs outlined so the two are told apart at a glance
   without relying on reading the word. */
.iqe__badge--seed { color: var(--bg); background: var(--ink-2); }
.iqe__badge--own  { color: var(--ink-2); background: transparent; border: 1px dashed var(--line-2); }
.iqe__lbl-note {
  font-size: 0.78rem; line-height: 1.4; color: var(--muted); margin-top: 4px;
}

.iqe__card-acts { display: flex; align-items: center; gap: var(--space-1); flex-shrink: 0; }
.iqe__ic {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: var(--radius);
  border: 1px solid transparent; background: transparent; color: var(--ink-2); cursor: pointer;
}
.iqe__ic:active { color: var(--accent); border-color: var(--line); }
.iqe__ic:disabled { opacity: 0.3; cursor: not-allowed; }

.iqe__form { display: flex; flex-direction: column; gap: var(--space-3); width: 100%; }
.iqe__lbl { display: flex; flex-direction: column; gap: var(--space-1); }
.iqe__lbl-cap { font-size: 0.78rem; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: 0.02em; }
.iqe__input {
  width: 100%; box-sizing: border-box; padding: 8px var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); font: inherit; font-size: 0.9rem;
}
.iqe__input:focus { outline: none; border-color: var(--accent); }

.iqe__opts { display: flex; flex-direction: column; gap: var(--space-2); }
.iqe__opt-row { display: flex; align-items: center; gap: var(--space-2); }
.iqe__opt-row .iqe__input { flex: 1; }
.iqe__opt-add {
  align-self: flex-start; padding: 4px var(--space-3); border-radius: 999px;
  border: 1px dashed var(--line); background: transparent; color: var(--ink-2);
  font: inherit; font-size: 0.82rem; font-weight: 600; cursor: pointer;
}

.iqe__flags { display: flex; flex-direction: column; gap: var(--space-2); }
.iqe__check { display: flex; align-items: center; gap: var(--space-2); font-size: 0.88rem; color: var(--ink-2); cursor: pointer; }

.iqe__err { color: var(--danger); font-size: 0.82rem; min-height: 1em; margin: 0; }

.iqe__form-nav { display: flex; justify-content: flex-end; gap: var(--space-2); }
.iqe__btn {
  padding: 8px var(--space-4); border-radius: var(--radius);
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-2);
  font: inherit; font-size: 0.88rem; font-weight: 600; cursor: pointer;
}
.iqe__btn--primary { border-color: var(--accent); background: var(--accent); color: var(--on-accent); }
.iqe__btn--primary:disabled { opacity: 0.5; cursor: not-allowed; }
.iqe__btn--primary:active { background: var(--accent-2); }

/* ═════════ COACH-IDE-P1 — desktop authoring workspace (.cide) ═════════
   Full-bleed 5-region IDE shell: a menubar over a 4-panel grid. On >=1024px
   all panels are simultaneously visible; <768px degrades to a tab strip that
   shows one panel at a time (blueprint A5). */
.cide {
  position: fixed; inset: 0; z-index: 40;
  display: flex; flex-direction: column;
  background: var(--bg); color: var(--ink);
}

/* menubar */
.cide__bar {
  flex: 0 0 auto; display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--line); background: var(--surface);
}
/* COACH-IDE-DRAFT-FIRST-NO-AUTO-PUBLISH — standing "the client can't see this
   yet" strip; visible only while the open schema is still a draft. */
.cide__banner {
  flex: 0 0 auto;
  padding: var(--space-2) var(--space-3);
  border-left: 4px solid var(--warn);
  background: color-mix(in srgb, var(--warn) 16%, transparent);
  color: var(--ink); font-size: 0.85rem; font-weight: 600;
}
.cide__banner[hidden] { display: none; }
/* COACH-PROGRAM-LOCK-OPT-IN-NOT-DEFAULT — deliberate lock switch, one strip
   under the menubar. Reuses the .ctprof-toggle switch idiom. */
.cide__lock {
  flex: 0 0 auto; display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--line); background: var(--surface);
}
.cide__lock-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cide__lock-title { font-weight: 600; color: var(--ink); }
.cide__lock-hint { font-size: 0.8rem; color: var(--muted); }
.cide__lock .ctprof-toggle { margin-left: auto; }
/* PLANNER-PERIODISERING-STAAT-BOVENAAN-GYM-EN-DE-RUIS-IS-WEG — .cide__lock--off
   maakte de schakelaar half doorzichtig zolang er geen gepubliceerd programma
   open stond. Een halfdoorzichtige schakelaar legt niet uit waarom hij niet werkt;
   de strook is nu gewoon weg tot er iets te vastzetten is (syncLock). */
.cide__back {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--accent); cursor: pointer;
}
.cide__menu { position: relative; flex: 0 0 auto; }
.cide__menu-btn {
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding: var(--space-1) var(--space-2); border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface); color: var(--ink);
  font: inherit; font-size: 0.88rem; font-weight: 600; cursor: pointer;
}
.cide__menu-list {
  display: none; position: absolute; top: calc(100% + 4px); left: 0; z-index: 5;
  min-width: 180px; flex-direction: column;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); overflow: hidden;
}
.cide__menu-list--open { display: flex; }
.cide__menu-item {
  display: flex; align-items: center; padding: var(--space-2) var(--space-3);
  border: 0; background: transparent; color: var(--ink);
  font: inherit; font-size: 0.88rem; text-align: left; cursor: pointer;
}
.cide__menu-item:hover { background: var(--line-2); }
.cide__title {
  flex: 0 1 260px; min-width: 120px;
  padding: var(--space-1) var(--space-2); border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--bg); color: var(--ink);
  font: inherit; font-size: 0.9rem; font-weight: 600;
}
.cide__title:focus { outline: none; border-color: var(--accent); }
.cide__spacer { flex: 1 1 auto; }
/* PLANNER-PERIODISERING-STAAT-BOVENAAN-GYM-EN-DE-RUIS-IS-WEG — .cide__new was de
   tweede "Nieuw concept"-knop in de balk, naast dezelfde eerste regel in
   Bestand ▾. Twee deuren naar één kamer; de knop en zijn regels zijn weg. */
/* client-switcher — custom dropdown w/ per-client attention (COACH-IDE-P4) */
.cidesw { position: relative; flex: 0 0 auto; }
.cidesw__btn {
  display: inline-flex; align-items: center; gap: var(--space-1);
  max-width: 220px; padding: var(--space-1) var(--space-2);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink);
  font: inherit; font-size: 0.85rem; font-weight: 600; cursor: pointer;
}
.cidesw__btn-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cidesw__menu {
  display: none; position: absolute; top: calc(100% + 4px); right: 0; z-index: 6;
  min-width: 240px; max-height: 60vh; overflow-y: auto; flex-direction: column;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface);
}
.cidesw__menu--open { display: flex; }
.cidesw__row {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3); border: 0; background: transparent;
  color: var(--ink); font: inherit; text-align: left; cursor: pointer;
}
.cidesw__row:hover { background: var(--line-2); }
.cidesw__row--on { background: var(--line-2); }
.cidesw__col { display: flex; flex-direction: column; min-width: 0; }
.cidesw__name { font-size: 0.88rem; font-weight: 600; }
.cidesw__status { font-size: 0.74rem; color: var(--muted); }
.cidesw__dot {
  flex: 0 0 auto; width: 9px; height: 9px; border-radius: 50%;
  background: transparent; border: 1px solid transparent;
}
.cidesw__dot--none { border-color: var(--line); }
.cidesw__dot--warn { background: var(--warn); }
.cidesw__dot--attn { background: var(--danger); }

/* dirty-dot — unsaved-changes indicator (COACH-IDE-P2) */
.cide__dot {
  flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%;
  background: transparent; transition: background 0.15s ease;
}
.cide__dot--on { background: var(--accent); }

/* File → Open picker (COACH-IDE-P2) */
.cide-picker__back {
  position: fixed; inset: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  padding: var(--space-4); background: rgba(0, 0, 0, 0.45);
}
.cide-picker {
  width: 100%; max-width: 420px; max-height: 70vh; display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden;
}
.cide-picker__title {
  flex: 0 0 auto; margin: 0; padding: var(--space-3);
  border-bottom: 1px solid var(--line);
  font-size: 0.95rem; font-weight: 700; color: var(--ink);
}
.cide-picker__list { flex: 1 1 auto; min-height: 0; overflow: auto; }
.cide-picker__item {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  width: 100%; padding: var(--space-3); border: 0; border-bottom: 1px solid var(--line);
  background: var(--surface); color: var(--ink); font: inherit; text-align: left; cursor: pointer;
}
.cide-picker__item:hover { background: var(--line-2); }
.cide-picker__name { font-size: 0.9rem; font-weight: 600; }
.cide-picker__meta {
  flex: 0 0 auto; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--muted);
}

/* panel grid */
.cide__grid {
  flex: 1 1 auto; min-height: 0; display: grid; gap: 1px;
  background: var(--line);
  grid-template-columns: 1fr; grid-auto-rows: minmax(160px, auto);
}
.cide__panel {
  display: flex; flex-direction: column; min-height: 0; min-width: 0;
  background: var(--surface);
}
.cide__panel-head {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-2); padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--line); background: var(--surface);
}
.cide__panel-title {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--muted);
}
.cide__panel-body { flex: 1 1 auto; min-height: 0; overflow: auto; }
.cide__panel--schema .cide__panel-body { overflow: hidden; }
.cide__frame { width: 100%; height: 100%; border: 0; display: block; }
.cide__krow {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3); padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--line-2);
}
.cide__k { color: var(--muted); font-size: 0.85rem; }
.cide__v { color: var(--ink); font-size: 0.9rem; font-weight: 600; }
.cide__loading, .cide__empty { padding: var(--space-3); color: var(--muted); font-size: 0.88rem; }
.cide__stub {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--space-2); height: 100%; padding: var(--space-4); color: var(--muted); text-align: center;
}
.cide__stub-copy { padding: var(--space-3); color: var(--muted); font-size: 0.88rem; }

/* BEWEGINGSANALYSE-IN-CHAT-EN-SCHEMA — kijkvenster-paneel. Read-only: geen
   invoer, geen duiding, alleen het verschil en de genoteerde pijn. */
.cide__mob-head {
  padding: var(--space-2) var(--space-3);
  color: var(--muted); font-size: 0.82rem;
}
.cide__mob-joint {
  padding: var(--space-3) var(--space-3) var(--space-1);
  color: var(--ink); font-size: 0.74rem; font-weight: 700;
  letter-spacing: 0.04em; text-transform: uppercase;
}
.cide__mob-link {
  display: block; width: calc(100% - var(--space-3) * 2);
  margin: var(--space-3); padding: var(--space-2);
  border: 1px solid var(--line-2); border-radius: var(--radius);
  background: transparent; color: var(--ink);
  font: inherit; font-size: 0.85rem; cursor: pointer;
}
.cide__mob-link:hover { background: var(--surface-2); }

/* COACH-IDE-AI-COAUTHOR-CHAT-V1 — AI co-author chat, in the IDE's light panel
   language (same tokens/type scale as the surrounding panels). */
.cchat { display: flex; flex-direction: column; height: 100%; min-height: 0; }
.cchat__log {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-3);
}
.cchat__intro { margin: auto 0; padding: 0 var(--space-3); color: var(--muted); font-size: 0.85rem; text-align: center; line-height: 1.5; }
.cchat__msg {
  max-width: 88%; padding: var(--space-2) var(--space-3);
  border-radius: var(--radius); font-size: 0.86rem; line-height: 1.45;
  white-space: pre-wrap; word-break: break-word;
}
.cchat__msg--user {
  align-self: flex-end; background: var(--accent); color: var(--on-accent);
}
.cchat__msg--assistant {
  align-self: flex-start; background: var(--line-2); color: var(--ink);
}
.cchat__msg--typing { color: var(--muted); }
.cchat__msg--error { background: transparent; color: var(--muted); border: 1px solid var(--line); }
.cchat__action {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 6px;
  padding: 2px var(--space-2); color: var(--accent); font-size: 0.78rem; font-weight: 600;
}
.cchat__action svg { flex: 0 0 auto; }
.cchat__form {
  display: flex; align-items: flex-end; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-top: 1px solid var(--line);
}
.cchat__input {
  flex: 1 1 auto; resize: none; min-height: 34px; max-height: 120px;
  padding: 7px var(--space-3);
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--radius);
  font: inherit; font-size: 0.86rem; line-height: 1.4;
}
.cchat__input:focus { outline: none; border-color: var(--accent); }
.cchat__input::placeholder { color: var(--muted); }
.cchat__send {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0;
  background: var(--accent); color: var(--on-accent);
  border: none; border-radius: var(--radius); cursor: pointer;
}
.cchat__send:hover { background: var(--accent-2); }
.cchat__send:disabled { opacity: 0.5; cursor: default; }

/* >=1024px — all four panels visible simultaneously */
@media (min-width: 1024px) {
  .cide__grid {
    grid-template-columns: minmax(240px, 1fr) minmax(360px, 2fr) minmax(240px, 1fr);
    grid-template-rows: minmax(0, 1fr) minmax(160px, 0.5fr);
    grid-template-areas:
      "intake schema per"
      "chat   schema per";
  }
  .cide__panel--intake { grid-area: intake; }
  .cide__panel--schema { grid-area: schema; }
  .cide__panel--per    { grid-area: per; }
  .cide__panel--chat   { grid-area: chat; }
}

/* COACH-IDE-TELEFOON-EEN-PANEEL-MET-WISSELAAR — wisselaar en samengevoegd menu
   staan altijd in de DOM; welk menu-idioom zichtbaar is loopt puur via de
   breekpunten hieronder, zodat draaien live goed gaat en desktop ongemoeid blijft. */
.cide__chips { display: none; }
.cide__menu--phone { display: none; }

/* <768px — telefoon: één paneel tegelijk, met een wisselaar onder de menubalk */
@media (max-width: 767px) {
  .cide__grid { grid-auto-rows: minmax(0, 1fr); overflow: hidden; }
  .cide__title { flex: 1 1 auto; min-width: 0; text-overflow: ellipsis; }
  .cide__new span { display: none; }
  .cide__spacer { display: none; }
  /* File ▾ en View ▾ vouwen samen tot één menu-knop */
  .cide__menu--file, .cide__menu--view { display: none; }
  .cide__menu--phone { display: block; }
  .cide__menu--phone .cide__menu-btn { min-width: 40px; min-height: 40px; justify-content: center; }
  .cide__menu--phone .cide__menu-item { min-height: 40px; }
  /* de wisselaar */
  .cide__chips {
    flex: 0 0 auto; display: flex; gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    border-bottom: 1px solid var(--line); background: var(--surface);
  }
  .cide__chip {
    flex: 0 0 auto; min-height: 40px; padding: 0 var(--space-3);
    border: 1px solid var(--line); border-radius: 999px;
    background: var(--surface-2); color: var(--muted);
    font-size: 0.85rem; font-weight: 600; white-space: nowrap; cursor: pointer;
  }
  .cide__chip--on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
  /* alleen het actieve paneel staat er; slotten bestaan hier niet */
  .cide__grid > .cide__panel { display: none; }
  .cide__grid > .cide__panel--phoneon { display: flex; grid-area: auto !important; }
  .cide__grid > .cide__panel--hidden { display: none; }
  .cide__gutter { display: none !important; }
  /* de altijd-aan tip vreet ruimte die het enige zichtbare paneel nodig heeft.
     DOSSIER-BLOKKEN-KIJKEN-NAAR-HUN-EIGEN-BREEDTE — deze regel stond hier
     ONGESCOPED als `.cpz-hint`, geschreven voor de telefoonstand van de
     schemawerkplek maar lekkend naar de ANDERE plek waar de planner woont: het
     periodiseringsvel van het dossier. Daar is de schermbreedte niet de
     vakbreedte, dus staat de dossierstand nu in zijn eigen regel hieronder (met
     dezelfde uitkomst op elke telefoon — gemeten: vel 343px op 375px, dus
     verborgen voor én na). Deze poort vond hem, niet ik. */
  .cide__grid .cpz-hint { display: none; }
}
/* De tip in het periodiseringsvel kijkt naar het vel. Drempel 440px: daaronder
   is er geen ruimte naast de inhoud, net als in de werkplek hierboven. */
@container dbox (max-width: 439.98px) {
  .cpz-hint { display: none; }
}

/* 768–1023px — tablet-portret houdt de bestaande gestapelde kolom */
@media (min-width: 768px) and (max-width: 1023px) {
  .cide__grid { grid-auto-rows: minmax(220px, auto); overflow: auto; }
  .cide__title { flex-basis: 120px; }
  .cide__new span { display: none; }
}

/* ═════════ COACH-IDE-WM-P1 — panel toggles, collapse, layout persistence ═════════
   Hide / collapse are pure CSS classes — nodes (and the schema-sheet iframe)
   stay in the DOM so nothing reloads. applyLayout() writes the inline grid
   tracks/areas ≥1024px on top of the static media-query fallback below. */
.cide__panel--hidden { display: none; }
.cide__panel--collapsed .cide__panel-body { display: none; }
.cide__panel-btn {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; padding: 0;
  border: 0; border-radius: 3px; background: transparent;
  color: var(--muted); cursor: pointer;
}
.cide__panel-btn:hover { background: var(--line-2); }
.cide__panel-btn svg { transition: transform 0.15s ease; }
.cide__panel-btn--collapsed svg { transform: rotate(180deg); }
/* View-menu checkbox rows — reserve the check-icon width so labels don't shift */
.cide__check-ic { flex: 0 0 auto; visibility: hidden; }
.cide__menu-check--on .cide__check-ic { visibility: visible; }

/* ═════════ COACH-IDE-WM-P2 — gutter resize + panel maximise ═════════
   Gutters are 6px grid tracks carrying a centred 1px hairline (the ≥1024px
   engine sets gap:0 inline, so gutters replace the 1px gap for their edges).
   Drag/keyboard resize mutates the inline grid tracks only — no node moves, so
   the schema-sheet iframe never reloads. The drag-shield rule below is
   MANDATORY: while resizing, the sheet iframe must not swallow pointermove. */
.cide__panel-btns { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 2px; }
.cide__panel-btn--max { color: var(--ink); }
.cide__gutter { display: none; }
@media (min-width: 1024px) {
  .cide__gutter--col1, .cide__gutter--col2 {
    cursor: col-resize;
    background: linear-gradient(to right, transparent 2.5px, var(--line) 2.5px, var(--line) 3.5px, transparent 3.5px);
  }
  .cide__gutter--lrow {
    cursor: row-resize;
    background: linear-gradient(to bottom, transparent 2.5px, var(--line) 2.5px, var(--line) 3.5px, transparent 3.5px);
  }
  .cide__gutter:hover, .cide__gutter:focus-visible { background: var(--line); outline: none; }
  .cide--resizing .cide__gutter { background: var(--line); }
}
.cide--resizing { user-select: none; cursor: col-resize; }
.cide--resizing-row { cursor: row-resize; }
.cide--resizing .cide__frame { pointer-events: none; }
/* maximise — one panel fills the grid; others + gutters hide (nodes stay). */
.cide__grid--max { grid-template: 1fr / 1fr !important; gap: 0 !important; }
.cide__grid--max .cide__gutter { display: none !important; }
.cide__grid--max .cide__panel { display: none !important; }
.cide__grid--max .cide__panel--max { display: flex !important; grid-area: 1 / 1 !important; }
.cide__grid--max .cide__panel--max .cide__panel-body { display: block !important; }

/* ═════════ COACH-IDE-WM-P3 — header-drag slot rearrange ═════════
   Dragging a panel header swaps two slots (a pure grid-area restyle — nodes
   never move, so the schema-sheet iframe never reloads). The pointer shield
   below is MANDATORY so document.elementFromPoint hit-tests past the iframe. */
.cide--slotdrag { user-select: none; cursor: grabbing; }
.cide--slotdrag .cide__frame { pointer-events: none; }
@media (min-width: 1024px) {
  .cide__panel-head { cursor: grab; }
  .cide__panel-btns { cursor: default; }
}
.cide__drag-ghost {
  position: fixed; top: 0; left: 0; z-index: 60; pointer-events: none;
  margin: 10px 0 0 14px;
  padding: 4px 10px; max-width: 220px;
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--muted); background: var(--surface);
  border: 1px solid var(--line); border-radius: 3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cide__panel--droptarget { outline: 2px solid var(--accent); outline-offset: -2px; }
/* View-menu 'Move to…' flat inline expansion */
.cide__menu-move-btn { justify-content: space-between; }
.cide__menu-move-btn svg { transition: transform 0.15s ease; }
.cide__menu-move--open .cide__menu-move-btn svg { transform: rotate(180deg); }
.cide__menu-slots { display: none; }
.cide__menu-move--open .cide__menu-slots { display: block; }
.cide__menu-slot { padding-left: var(--space-5); }
.cide__menu-slot--on { color: var(--ink); font-weight: 600; }

/* ───── PLANNER-PERIODISERING-STAAT-BOVENAAN-GYM-EN-DE-RUIS-IS-WEG ─────
   Het periodiseringsvel: het raster hangt niet meer in een werkplek met vijf
   sleepbare panelen, maar in één blad over het dossier.

   LET OP de val in de basis: .csheet__panel--wide is max-width:480px — SMALLER
   dan de 520px van .csheet__panel. Die modifier maakt een vel dus niet breder.
   De maat komt hier daarom uit twee klassen (specificiteit 0,2,0), niet uit een
   modifier, zodat niemand later per ongeluk op --wide vertrouwt.

   Op de telefoon vult het blad het scherm; een weekraster heeft elke pixel
   nodig. Vanaf 640px staat het gecentreerd op max. 1200px: met 16px padding aan
   weerszijden blijft ~1168px over, en 132 + 8×96 + 92 = 992px past daarin — acht
   weken zonder horizontale scroll (eis van deze fase op 1280). */
.csheet--perio { align-items: stretch; }
.csheet--perio .csheet__panel {
  width: 100%; max-width: none; height: 100%; max-height: none;
  overflow: hidden; border-radius: 0;
  padding: var(--space-4) var(--space-4) calc(var(--space-3) + var(--safe-bottom));
}
/* De body is de scrollbak — niet het paneel. Alleen zó kan de naamkolom
   (.cpz-stick) links blijven plakken terwijl de weken eronder doorschuiven.
   Geen eigen achtergrond: die komt van .csheet__panel → var(--surface). */
.cpzsheet__body { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 0; }
.cpzsheet__tools { display: flex; align-items: center; gap: var(--space-2); margin-left: auto; }

@media (min-width: 640px) {
  .csheet--perio { align-items: center; }
  .csheet--perio .csheet__panel {
    max-width: 1200px; height: auto; max-height: 92vh; border-radius: var(--radius);
  }
}

/* Het ⋮-menu van het vel: startdatum en "na het blok". Drie aantikbare dingen
   in de kop is het plafond, dus deze twee instellingen zitten achter één knop. */
.cpzset { position: relative; display: flex; }
.cpzset__btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px; padding: 0;
  border: 0; border-radius: var(--radius); background: none;
  color: var(--ink-2); cursor: pointer;
}
.cpzset__btn:active { background: var(--line); }
.cpzset__menu {
  position: absolute; top: calc(100% + var(--space-1)); right: 0; z-index: 3;
  min-width: 236px; display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); box-shadow: 0 8px 24px -8px rgba(0, 0, 0, 0.35);
}
.cpzset__field { display: flex; flex-direction: column; gap: var(--space-1); }
.cpzset__lbl {
  font-size: 11px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
}
.cpzset__lbl--sep { margin-top: var(--space-1); }
.cpzset__date,
.cpzset__name {
  min-height: 44px; padding: 0 var(--space-2); font: inherit; font-size: 14px;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--bg); color: var(--ink);
}
.cpzset__modes { display: flex; gap: var(--space-2); }
.cpzset__mode {
  flex: 1 1 0; min-height: 44px; padding: 0 var(--space-2);
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink-2);
}
.cpzset__mode.is-on {
  background: var(--accent); border-color: var(--accent); color: var(--on-accent);
}
/* PLANNER-PROGRESSIE-EN-DELOAD-STEL-JE-PER-FASE-IN — de deloadvorm van de klant
   is hier te gast. Hij komt als hele kaart uit het Details-paneel, waar hij
   ruimte had; in dit menu is hij één instelling tussen drie andere. Dus geen
   kader om een kader (het menu is al een vel), geen eigen kopje (het label
   erboven zegt het al), en de uitleg van drie regels blijft daar staan — hier
   past één regel, en die staat als .cpzset__hint onder de kaart. */
.cpzset__dlform {
  margin: 0; padding: 0; border: 0; border-radius: 0; background: none;
}
.cpzset__dlform .dsec-title,
.cpzset__dlform .tabvis__hint { display: none; }
.cpzset__dlform .dlform__effect { margin-top: var(--space-1); font-size: 11.5px; }
.cpzset__hint {
  margin: 0; font-size: 11.5px; line-height: 1.4; color: var(--muted);
}

/* ───────── COACH-PERIO-P6B periodisation panel — precision grid ─────────
   Ported verbatim from the approved mock v4 (design-mocks/coach-periodisation-
   panel-mock-v4-2026-07-05.html). Colour vars are scoped to .cpz-panel so the
   light precision-grid look is exact and independent of the coach theme. */
.cpz-panel {
  --cpz-white:#fff; --cpz-ink:#111826;
  --cpz-line:#e4e8ec; --cpz-line-strong:#c9cfd6;
  --cpz-grey-soft:#fafbfc; --cpz-grey-lane:#f3f5f8;
  --cpz-muted:#7a828c; --cpz-faint:#c3c9d0;
  --cpz-accent:#006E7D; --cpz-accent-tint:rgba(0,110,125,.07); --cpz-on-accent:#fff;
  --cpz-repmax:#e8923a; --cpz-volume:#1d3557;
  background:var(--cpz-white); color:var(--cpz-ink);
  font-variant-numeric:tabular-nums;
}
.cpz-panel *{ box-sizing:border-box; }

/* PLANNER-PERIODISERING-STAAT-BOVENAAN-GYM-EN-DE-RUIS-IS-WEG — het raster kwam
   als lichte mock binnen en hield zijn eigen palet. In een blad over een donker
   dossier is dat een wit vlak in een donkere app. In het donkere thema komen
   dezelfde variabelen daarom uit de tokens van coach.css; de LICHTE waarden
   hierboven blijven letterlijk de goedgekeurde mock, dus het lichte thema
   verandert geen pixel. Let op dat --line in het donker LICHTER is dan --line-2:
   de zichtbare hoofdlijn is daar --line, de zachte onderlijn --line-2. */
:root[data-theme="dark"] .cpz-panel {
  --cpz-white:var(--surface); --cpz-ink:var(--ink);
  --cpz-line:var(--line-2); --cpz-line-strong:var(--line);
  --cpz-grey-soft:var(--bg); --cpz-grey-lane:var(--bg);
  --cpz-muted:var(--ink-2); --cpz-faint:var(--muted);
  --cpz-accent:var(--accent); --cpz-accent-tint:rgba(111,232,255,.10);
  --cpz-on-accent:var(--on-accent);
}

/* De naamkolom plakt links. Zonder dit valt de oefeningsnaam op een telefoon uit
   beeld zodra je naar week 3 schuift (bijvangst B3 uit de UAT): je ziet getallen
   zonder te weten waar ze bij horen. Elke cel in kolom 1 krijgt `cpz-stick` van
   rowStart() in coach.js; ze hebben allemaal een dekkende achtergrond, dus de
   weken schuiven eronder door. De kolomkop moet nog een laag hoger, want die
   plakt óók naar boven in de scrollbak. */
.cpz-stick{ position:sticky; left:0; z-index:1; }
.cpz-colhead.cpz-stick{ z-index:2; }

/* ───── het raster : één tabel, gedeelde haarlijnen ─────
   Het aantal kolommen wordt in JS gezet. PLANNER-EEN-CYCLUS-BESTAAT-UIT-FASES-VAN-
   EEN-AANTAL-WEKEN — er is niet één raster meer over de hele cyclus, maar één per
   fase binnen haar eigen kaart, over de weken van díe fase. Daarmee verdwenen de
   banen die er bij hoorden: de schemastrook (.cpz-sched/.cpz-tag), het
   "+ Verlengen"-vakje (.cpz-extend), de sporen onder een oefening (.cpz-sp*,
   .cpz-bar*), de inline-editor (.cpz-editing/.cpz-step) en de ingeklapte
   samenvatting (.cpz-sum/.cpz-more/.cpz-count). Een fase heeft geen uitklapstand
   meer — alle vier de velden van een week staan in één blad. */
.cpz-grid{ display:grid; }
.cpz-c{ display:flex; align-items:center; min-height:38px; padding:0 14px;
  border-bottom:1px solid var(--cpz-line); border-right:1px solid var(--cpz-line);
  background:var(--cpz-white); min-width:0; }
.cpz-num{ justify-content:flex-end; font-size:13px; font-weight:600; text-align:right; }

.cpz-colhead{ min-height:34px; font-size:10px; font-weight:700; letter-spacing:.09em;
  text-transform:uppercase; color:var(--cpz-muted); background:var(--cpz-grey-soft);
  border-bottom:1px solid var(--cpz-line-strong); }
.cpz-rowhead{ font-size:10.5px; font-weight:700; letter-spacing:.05em;
  text-transform:uppercase; color:var(--cpz-muted); background:var(--cpz-grey-soft); }

/* ───── de kop ─────
   Drie regels en één knop: de naam van de cyclus, zijn lengte met begin- en
   einddatum, en waar de klant nu staat. De naam, de startdatum en "na afloop"
   worden in het ⋮-menu van het blad erboven geschreven, zodat het hier bij één
   aantikbaar ding blijft. Hier stonden eerder een eigen <h1>, een datumveld, een
   Stop/Herhaal-schakelaar en een tweede opslaanknop (.cpz-title/-hdr-right/
   -field/-seg/-save/-kbd/-on); die gingen met de vorige fase weg, en de
   opslaanknop van het blad (.cpzsheet__save) met deze: een cyclus heeft geen
   conceptlaag, elke wijziging staat na 600ms bij de klant. */
.cpz-hdr{ display:flex; justify-content:space-between; align-items:center; gap:16px;
  flex-wrap:wrap; padding:16px 20px; border-bottom:1px solid var(--cpz-line-strong); }
.cpz-hdr__lines{ display:flex; flex-direction:column; gap:2px; min-width:0; flex:1 1 auto; }
.cpz-cyclename{ font-size:15px; font-weight:800; letter-spacing:-.01em;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cpz-hdr__span{ font-size:12px; font-weight:600; }
.cpz-sub{ font-size:11.5px; color:var(--cpz-muted); margin:3px 0 0; }
.cpz-addphase{ flex:none; white-space:nowrap; }

/* ───── de zes fasekleuren ─────
   Dezelfde zes namen als CPZ_PALETTE in coach.js en als de enum van de PUT, in
   dezelfde orde — een fase zonder eigen kleur krijgt de kleur van haar plek, dus
   die drie lijsten moeten één lijst zijn. De vulling komt uit de kleur zelf
   (color-mix), zodat het donkere thema alleen het mengpercentage bijstelt. */
.cpz-panel{ --cpz-ph-mix:11%; }
.cpz-band.is-teal,   .cpz-strip__wk.is-teal,   .cpz-card.is-teal{   --cpz-ph:#0f766e; }
.cpz-band.is-amber,  .cpz-strip__wk.is-amber,  .cpz-card.is-amber{  --cpz-ph:#b45309; }
.cpz-band.is-violet, .cpz-strip__wk.is-violet, .cpz-card.is-violet{ --cpz-ph:#6d28d9; }
.cpz-band.is-rose,   .cpz-strip__wk.is-rose,   .cpz-card.is-rose{   --cpz-ph:#be123c; }
.cpz-band.is-sky,    .cpz-strip__wk.is-sky,    .cpz-card.is-sky{    --cpz-ph:#0369a1; }
.cpz-band.is-slate,  .cpz-strip__wk.is-slate,  .cpz-card.is-slate{  --cpz-ph:#475569; }
/* Op een donkere ondergrond zijn diezelfde zes te donker om nog een naam in te
   kunnen lezen; de lichte varianten zijn dezelfde tinten, een paar stappen op. */
:root[data-theme="dark"] .cpz-panel{ --cpz-ph-mix:22%; }
:root[data-theme="dark"] .cpz-band.is-teal,   :root[data-theme="dark"] .cpz-strip__wk.is-teal,   :root[data-theme="dark"] .cpz-card.is-teal{   --cpz-ph:#5eead4; }
:root[data-theme="dark"] .cpz-band.is-amber,  :root[data-theme="dark"] .cpz-strip__wk.is-amber,  :root[data-theme="dark"] .cpz-card.is-amber{  --cpz-ph:#fcd34d; }
:root[data-theme="dark"] .cpz-band.is-violet, :root[data-theme="dark"] .cpz-strip__wk.is-violet, :root[data-theme="dark"] .cpz-card.is-violet{ --cpz-ph:#c4b5fd; }
:root[data-theme="dark"] .cpz-band.is-rose,   :root[data-theme="dark"] .cpz-strip__wk.is-rose,   :root[data-theme="dark"] .cpz-card.is-rose{   --cpz-ph:#fda4af; }
:root[data-theme="dark"] .cpz-band.is-sky,    :root[data-theme="dark"] .cpz-strip__wk.is-sky,    :root[data-theme="dark"] .cpz-card.is-sky{    --cpz-ph:#7dd3fc; }
:root[data-theme="dark"] .cpz-band.is-slate,  :root[data-theme="dark"] .cpz-strip__wk.is-slate,  :root[data-theme="dark"] .cpz-card.is-slate{  --cpz-ph:#cbd5e1; }

/* ───── de tijdlijn ─────
   Twee verschijningsvormen van hetzelfde: op een breed scherm de weken als
   kolommen met gekleurde fasebanden eroverheen, op een telefoon een strook
   blokjes van één week. JS tekent ze BEIDE en CSS kiest welke te zien is — deed
   JS die keus, dan keek een coach die zijn venster versmalt op een lege plek tot
   er iets hertekende. */
.cpz-tl{ display:flex; flex-direction:column; gap:6px;
  padding:14px 20px; border-bottom:1px solid var(--cpz-line-strong); }
.cpz-tl__weeks{ display:none; gap:3px; }
.cpz-tl__wk{ display:flex; align-items:center; justify-content:center; min-width:0;
  font-size:9.5px; font-weight:700; letter-spacing:.06em; color:var(--cpz-faint); }
.cpz-tl__wk.is-now{ color:var(--cpz-accent); }
.cpz-tl__bands{ display:none; gap:3px; }
.cpz-band{ display:flex; flex-direction:column; justify-content:center; gap:1px;
  min-width:0; min-height:54px; padding:7px 10px; text-align:left; cursor:pointer;
  font-family:inherit; border:1px solid var(--cpz-ph); border-left-width:3px;
  border-radius:3px; color:var(--cpz-ink);
  background:color-mix(in srgb, var(--cpz-ph) var(--cpz-ph-mix), transparent); }
.cpz-band__nm, .cpz-band__sub{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cpz-band__nm{ font-size:12px; font-weight:800; color:var(--cpz-ph); }
.cpz-band__sub{ font-size:10.5px; color:var(--cpz-muted); }
.cpz-band__wks{ font-size:9.5px; font-weight:700; letter-spacing:.08em;
  text-transform:uppercase; color:var(--cpz-faint); }
.cpz-band.is-sel{ box-shadow:0 0 0 1.5px var(--cpz-ph); }
.cpz-band:focus-visible{ outline:2px solid var(--cpz-accent); outline-offset:1px; }

/* De telefoonstrook. De kleur zegt welke fase, de rand welke week nu loopt: twee
   dingen in hetzelfde blokje, want ze kunnen samenvallen. */
.cpz-strip{ display:flex; flex-wrap:wrap; gap:4px; }
.cpz-strip__wk{ flex:0 0 auto; width:36px; min-height:36px; padding:0;
  display:flex; align-items:center; justify-content:center; cursor:pointer;
  font-family:inherit; font-size:11px; font-weight:700; color:var(--cpz-ph);
  border:1px solid var(--cpz-ph); border-radius:3px;
  background:color-mix(in srgb, var(--cpz-ph) var(--cpz-ph-mix), transparent); }
.cpz-strip__wk.is-sel{ border-width:2px; }
.cpz-strip__wk.is-now{ box-shadow:0 0 0 2px var(--cpz-accent); }
.cpz-strip__wk:focus-visible{ outline:2px solid var(--cpz-accent); outline-offset:1px; }

/* ───── PLANNER-DE-BEWEGINGSANALYSE-KRIJGT-EEN-EIGEN-BAAN — de tweede baan ─────
   Dezelfde kolommen als de fasebanden, maar bewust GEEN fasekleur: een
   mobiliteitsblok is geen fase, en zou het zijn kleur uit CPZ_PALETTE lenen dan
   leest de coach het als een vijfde fase die zijn cyclus niet langer maakt. Eén
   eigen, rustige kleur voor de hele baan. */
.cpz-panel{ --cpz-mob:#0e7490; }
:root[data-theme="dark"] .cpz-panel{ --cpz-mob:#67e8f9; }
.cpz-tl__mob{ display:none; gap:3px; row-gap:4px; }
.cpz-mband{ display:flex; flex-direction:column; justify-content:center; gap:1px;
  min-width:0; min-height:34px; padding:5px 9px; text-align:left; cursor:pointer;
  font-family:inherit; border:1px solid var(--cpz-mob); border-left-width:3px;
  border-radius:3px; color:var(--cpz-ink);
  background:color-mix(in srgb, var(--cpz-mob) var(--cpz-ph-mix), transparent); }
.cpz-mband__nm{ display:flex; align-items:center; gap:4px; min-width:0;
  overflow:hidden; font-size:11.5px; font-weight:800; color:var(--cpz-mob); }
.cpz-mband__nm > span{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cpz-mband__sub{ font-size:9.5px; font-weight:700; letter-spacing:.06em;
  text-transform:uppercase; color:var(--cpz-muted);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cpz-mband:focus-visible{ outline:2px solid var(--cpz-accent); outline-offset:1px; }
/* De volgende trede is nog niet gepubliceerd: gestippeld, en niet aan te tikken,
   want er is nog niets om te openen tot de hertest gedaan is. */
.cpz-mband--next{ border-style:dashed; border-left-width:1px; cursor:default;
  background:transparent; }
/* Is de ladder op, dan blijft alleen de hertest over: een streepje op zijn week. */
.cpz-mtick{ display:flex; align-items:center; justify-content:center; min-width:0;
  border-left:2px solid var(--cpz-mob); }
.cpz-mtick__lbl{ font-size:9px; font-weight:700; letter-spacing:.06em;
  text-transform:uppercase; color:var(--cpz-mob);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cpz-tl__mobnote{ margin:0; font-size:10.5px; color:var(--cpz-muted); }

/* De baan op de telefoon: een dunne balk per blok, één vakje per week van de
   cyclus. Geen cijfers — die staan één regel hoger in .cpz-strip. */
.cpz-mstrip{ display:flex; flex-direction:column; gap:6px; }
.cpz-mstrip__row{ display:flex; flex-direction:column; gap:3px; width:100%;
  padding:0; border:0; background:none; font-family:inherit; text-align:left;
  cursor:pointer; }
.cpz-mstrip__bar{ display:flex; gap:2px; }
.cpz-mstrip__c{ flex:1 1 0; min-width:0; height:6px; border-radius:2px;
  background:var(--cpz-grey-soft); }
.cpz-mstrip__c.is-on{ background:var(--cpz-mob); }
.cpz-mstrip__c.is-retest{ box-shadow:inset 0 0 0 1px var(--cpz-mob);
  background:color-mix(in srgb, var(--cpz-mob) 35%, transparent); }
.cpz-mstrip__lbl{ display:flex; align-items:center; gap:4px; min-width:0;
  font-size:10.5px; font-weight:700; color:var(--cpz-mob); }
.cpz-mstrip__lbl > span{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cpz-mstrip__row:focus-visible{ outline:2px solid var(--cpz-accent); outline-offset:2px; }

/* DOSSIER-BLOKKEN-KIJKEN-NAAR-HUN-EIGEN-BREEDTE — de tijdbalk wisselt van
   veegstrook naar raster. Dat stond op `@media (min-width: 760px)` en las de
   viewport, terwijl de balk in de body van het periodiseringsvel staat: op een
   tablet van 768px is die body ~720px, dus het raster klapte open in een vak dat
   er 40px te smal voor is. Nu vraagt hij zijn eigen vak, en de drempel betekent
   wat hij zegt: 760px RUIMTE voor het raster. */
@container dbox (min-width: 760px) {
  .cpz-tl__weeks, .cpz-tl__bands, .cpz-tl__mob{ display:grid; }
  .cpz-strip, .cpz-mstrip{ display:none; }
}

/* ───── de fasekaart ───── */
.cpz-cards{ display:flex; flex-direction:column; }
.cpz-card{ border-bottom:1px solid var(--cpz-line-strong); scroll-margin-top:8px; }
.cpz-card.is-sel{ box-shadow:inset 3px 0 0 0 var(--cpz-ph); }
.cpz-card__head{ display:flex; align-items:flex-start; gap:10px; padding:12px 20px; }
.cpz-card__dot{ width:10px; height:10px; border-radius:50%; flex:none; margin-top:5px;
  background:var(--cpz-ph); }
.cpz-card__lines{ display:flex; flex-direction:column; gap:3px; min-width:0; flex:1 1 auto; }
.cpz-card__nmrow{ display:flex; align-items:center; gap:8px; min-width:0; }
.cpz-card__nm{ font-size:13.5px; font-weight:800; min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cpz-card__meta{ display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  font-size:11.5px; color:var(--cpz-muted); }
/* De schematitel is de deur naar de bouwer. Hij ziet eruit als een verwijzing en
   niet als een knop: de primaire knop van dit paneel is "Fase toevoegen". */
.cpz-card__schema{ max-width:100%; padding:0; border:0; background:none;
  font:inherit; font-size:11.5px; font-weight:700; color:var(--cpz-accent);
  text-align:left; cursor:pointer; text-decoration:underline; text-underline-offset:2px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cpz-card__schema:disabled{ color:var(--cpz-muted); text-decoration:none; cursor:default; }
/* De trainingsdagen van het schema ("Ma · Do"). Ze staan naast de schematitel
   omdat ze bij het SCHEMA horen en niet bij de fase. */
.cpz-card__days{ white-space:nowrap; }
/* De echte deur naar de bouwer. Kleur en tekstkleur komen van .cbtn--primary,
   dus hij leest hetzelfde als elke andere accentknop in de coach-schil; hier
   staat alleen dat hij niet mag krimpen en niet mag afbreken. */
.cpz-card__edit{ flex:none; align-self:flex-start; white-space:nowrap; }
/* PLANNER-PROGRESSIE-EN-DELOAD-STEL-JE-PER-FASE-IN — de regel in één zin
   ("Elke week +2,5 kg op Back squat · week 4 is deload"). Hij staat ONDER de
   schemanaam en niet in de metarij, want hij hoort bij de FASE en niet bij het
   schema, en hij mag afbreken: een regel met drie oefeningen erin is lang en
   afkappen zou juist het deel weglaten waar het om gaat. De accentkleur zegt
   "dit rekent iets uit" — dezelfde kleur als een door de regel gevuld weekvakje. */
.cpz-card__rule{ font-size:11.5px; font-weight:600; line-height:1.4;
  color:var(--cpz-accent); }
/* Twee deuren naast elkaar in de kop: het schema bouwen (primair) en de regel
   van de fase (secundair). Secundair, want negen van de tien fases hebben geen
   regel en dan is dit de knop die je níet nodig hebt.
   Met deze tweede knop past de kop op de telefoon niet meer op één regel (350px
   werkruimte, twee knoppen plus kebab willen er 364), dus hij mag afbreken: de
   naam van de fase houdt de eerste regel voor zich en de knoppen zakken eronder.
   Zonder dit zou de fasenaam tot drie letters krimpen — flex:1 1 auto met
   min-width:0 geeft alles weg wat de knoppen vragen. */
.cpz-card__prog{ flex:none; align-self:flex-start; white-space:nowrap; }
.cpz-card__head{ flex-wrap:wrap; row-gap:8px; }
/* Zelfde omzetting als de tijdbalk hierboven: de fasekaart staat in het vel, dus
   hij leest het vel. Op `@media (max-width: 759px)` kreeg hij op een tablet van
   768px de BREDE kop in een vel van ~720px. */
@container dbox (max-width: 759.98px) {
  /* De kebab gaat met `order` mee naar boven zodat hij naast de fasenaam blijft
     staan waar hij altijd stond; de naam reserveert zijn 44px plus de tussenruimte
     zodat flexbox hem niet alsnog een regel verderop zet. De twee knoppen vullen
     daaronder samen de breedte. */
  .cpz-card__lines{ flex:1 1 calc(100% - 56px); }
  .cpz-card__head .cpz-kebab{ order:1; }
  .cpz-card__edit{ order:2; flex:1 1 calc(50% - 6px); }
  .cpz-card__prog{ order:3; flex:1 1 calc(50% - 6px); white-space:normal; }
}

.cpz-pill{ display:inline-flex; align-items:center; flex:none; line-height:1;
  border:1px solid var(--cpz-line-strong); border-radius:2px; padding:3px 6px;
  font-size:9.5px; font-weight:700; letter-spacing:.08em; text-transform:uppercase;
  white-space:nowrap; }
.cpz-pill--deload{ border-color:var(--cpz-accent); background:var(--cpz-accent-tint);
  color:var(--cpz-accent); }
/* "Concept — nog niet zichtbaar": een waarschuwing, geen accent. Daarom de
   repmax-oranje van dit paneel en niet de accentkleur, die hier al "deload" zegt.
   De pil mag wél afbreken: hij draagt een naam en die kan lang zijn. */
.cpz-pill--draft{ border-color:var(--cpz-repmax); color:var(--cpz-repmax);
  background:color-mix(in srgb, var(--cpz-repmax) 10%, transparent);
  white-space:normal; }

/* ───── PLANNER-DE-BEWEGINGSANALYSE-KRIJGT-EEN-EIGEN-BAAN — kaart en blad ─────
   De kaart leent de indeling van de fasekaart (kop, naamregel, metarij) zodat de
   coach niet twee soorten kaarten hoeft te leren lezen, maar draagt nergens de
   fasekleur --cpz-ph: geen stip, geen gekleurde zijkant, geen is-sel. Hij is NIET
   aantikbaar als geheel en heeft geen kebab — wat je met dit blok kunt doen staat
   in het blad, achter "Details".
   --cpz-mob komt van .cpz-panel, waar de tijdlijn hem ook vandaan haalt. */
.cpz-card--mob .cpz-card__head{ align-items:center; }
.cpz-card__mobicon{ display:inline-flex; align-items:center; justify-content:center;
  width:22px; height:22px; flex:none; border-radius:3px; color:var(--cpz-mob);
  background:color-mix(in srgb, var(--cpz-mob) var(--cpz-ph-mix), transparent); }
.cpz-pill--mob{ border-color:var(--cpz-mob); color:var(--cpz-mob);
  background:color-mix(in srgb, var(--cpz-mob) 10%, transparent); }
/* De hertestregel staat onder de metarij en niet erin: hij gaat over de TOEKOMST
   van dit blok en niet over waar het nu loopt, en hij draagt soms een pil. */
.cpz-card__meta--mob{ color:var(--cpz-mob); font-weight:700; }
/* Dezelfde verwijzings-stijl als .cpz-card__schema en niet .cbtn--primary: de
   primaire knop van dit paneel blijft "Fase toevoegen". */
.cpz-card__mobopen{ flex:none; align-self:center; padding:0; border:0;
  background:none; font:inherit; font-size:11.5px; font-weight:700;
  color:var(--cpz-mob); white-space:nowrap; cursor:pointer;
  text-decoration:underline; text-underline-offset:2px; }
.cpz-card__mobopen:focus-visible{ outline:2px solid var(--cpz-accent); outline-offset:2px; }

/* Het blad. Het hangt onder document.body en dus BUITEN .cpz-panel, dus de
   baankleur wordt hier opnieuw gezet — zonder dit valt hij terug op niets. */
.cpz-mob{ --cpz-mob:#0e7490;
  display:flex; flex-direction:column; gap:12px; }
:root[data-theme="dark"] .cpz-mob{ --cpz-mob:#67e8f9; }
.cpz-mob__sub{ margin:0; font-size:12px; line-height:1.5; color:var(--muted); }
.cpz-mob__sub:first-child{ font-weight:700; color:var(--ink); }
/* De bevindingen komen uit baFindingNodes en dragen daarom cide__-klassen. Die
   zijn vlak (niet genest onder .cide), dus ze werken hier zonder één extra regel;
   dit kadert ze alleen in zodat ze als één blok lezen. */
.cpz-mob__finds{ display:flex; flex-direction:column;
  border:1px solid var(--line); border-radius:var(--radius); padding:10px 12px; }
.cpz-mob__retest{ margin:0; font-size:12.5px; font-weight:700; color:var(--cpz-mob); }
.cpz-mob__vals{ display:flex; flex-direction:column; gap:8px; }
.cpz-mob__acts{ display:flex; flex-direction:column; gap:8px; }
/* Uit de cyclus halen is de enige handeling die iets weghaalt, dus hij staat
   onderaan, los van de rest, en in waarschuwingskleur. Er is geen globale
   .cbtn--danger, dus de rand- en tekstkleur staan hier. */
.cpz-mob__rm{ margin-top:4px; border:1px solid var(--danger); color:var(--danger);
  background:var(--surface); }
.cpz-mob__rm:active{ background:color-mix(in srgb, var(--danger) 10%, transparent); }

/* Alles wat je met een FASE kunt doen zit achter deze ene knop, zodat de kaart
   zelf bij twee aantikbare dingen blijft naast haar weekvakjes. */
.cpz-kebab{ display:inline-flex; align-items:center; justify-content:center; flex:none;
  width:44px; height:44px; margin:-6px -10px -6px 0; padding:0;
  border:0; border-radius:var(--radius); background:none;
  color:var(--cpz-muted); cursor:pointer; }
.cpz-kebab:hover{ background:var(--cpz-grey-soft); color:var(--cpz-ink); }
.cpz-kebab:focus-visible{ outline:2px solid var(--cpz-accent); outline-offset:-2px; }

/* ───── de oefenregel ─────
   Naam, soort, en de SCHEMAwaarde als chip. De chip is de deur naar "voor alle
   weken wijzigen"; een weekvakje verzet nooit het schema zelf. */
.cpz-ex{ min-height:48px; gap:8px; justify-content:space-between;
  font-size:13px; font-weight:700; }
.cpz-ex .cpz-cat{ display:block; font-size:9px; font-weight:700; letter-spacing:.1em;
  text-transform:uppercase; color:var(--cpz-muted); margin-bottom:1px; }
.cpz-ex__lines{ display:flex; flex-direction:column; align-items:flex-start; gap:2px;
  min-width:0; flex:1 1 auto; }
/* L238 besluit 8 — de rijkop kapt ook niet af: "Superw…" en "Bulgaria…" waren
   precies de namen waarop de coach moet kiezen. Breken op WOORDgrens, met
   hyphens als vangnet — nooit `overflow-wrap:anywhere`, want dat maakte in de
   mock "Superwoma / n" van een naam die gewoon op één regel past. */
.cpz-ex__nm{ max-width:100%; white-space:normal; overflow-wrap:break-word; hyphens:auto; }
.cpz-schemaval{ max-width:100%; padding:1px 6px; cursor:pointer;
  border:1px solid var(--cpz-line-strong); border-radius:2px; background:transparent;
  font:inherit; font-size:11px; font-weight:600; color:var(--cpz-muted);
  white-space:normal; text-align:left; }
.cpz-schemaval:hover, .cpz-schemaval:focus-visible{ border-color:var(--cpz-accent);
  color:var(--cpz-accent); outline:none; }
/* De rust achter de schemawaarde. Zelfde grijs als de soort erboven: het is
   context bij de oefening, niet een waarde die je hier kunt veranderen. */
.cpz-ex__rest{ font-size:11px; font-weight:600; color:var(--cpz-muted);
  white-space:nowrap; }
.cpz-notedot{ display:inline-block; width:6px; height:6px; border-radius:50%; flex:none;
  background:var(--cpz-accent, var(--accent)); vertical-align:1px; }

/* ───── het weekvakje ─────
   De waarde die de KLANT die week ziet. Een vulling zegt "deze week wijkt af van
   het schema", een volle linkerrand "dit is de week die nu loopt" — twee dingen
   die in hetzelfde vakje kunnen samenvallen, dus twee verschillende middelen. */
/* PERIODISERING-NA-AANPASSEN-IS-DE-SELECTIE-WEG-EN-TOONT-ELKE-CEL-ZIJN-HELE-WAARDE
   (L238, Jayy 21-10) — het vakje is een kleine STAPEL en kapt niets meer af.
   Gemeten vóór deze fase op 390: kolom minmax(84px,1fr) − 2×14px padding = 56px
   inhoud, en daarin stonden op ÉÉN regel een icoon van 12px, "3×30 s" (~44px) en
   een stip van 6px met twee gaps van 6 — samen ~74px. `text-overflow:ellipsis`
   maakte daar "3…" van, en dan is precies de waarde weg die de cel moet zeggen.
   Nu: meetwijze / dosis / rest op drie regels rechts uitgelijnd, de stip
   absoluut in de hoek (kost geen breedte), en NERGENS nog een ellipsis op tekst
   van een .cpz-wk*. De rij wordt hoger; dat is goed. */
.cpz-wk{ flex-direction:column; align-items:flex-end; justify-content:center;
  gap:1px; position:relative; line-height:1.25; cursor:pointer; }
/* Hover alleen waar er een MUIS is: op iOS blijft :hover na een tik hangen, en
   een grijs vakje tussen witte buren leest dan als "nog gekozen". */
@media (hover:hover) {
  .cpz-wk:hover{ background:var(--cpz-grey-soft); }
}
.cpz-wk:focus-visible{ outline:none; box-shadow:inset 0 0 0 1.5px var(--cpz-accent); }
/* De DOSE. Nowrap, want "3×1:30" mag nooit middenin breken — maar zonder
   overflow:hidden en zonder ellipsis: wat er staat, staat er heel. */
.cpz-wk__v{ max-width:100%; white-space:nowrap; }
/* Regel 1: de meetwijze van DEZE week, als die afwijkt van haar rij. Zelfde
   stijl als .cpz-cat op het rijlabel — het is context, geen tweede waarde. */
.cpz-wk__tag{ display:flex; align-items:center; justify-content:flex-end; gap:3px;
  max-width:100%; font-size:9px; font-weight:700; letter-spacing:.1em;
  text-transform:uppercase; color:var(--cpz-muted); text-align:right;
  white-space:normal; overflow-wrap:break-word; }
/* Regel 3: de rest. Mag op de · afbreken — twee korte regels zijn leesbaar, een
   afgekapte is dat niet. */
.cpz-wk__x{ max-width:100%; font-size:10.5px; font-weight:600;
  color:var(--cpz-muted); white-space:normal; text-align:right; }
.cpz-wk .cpz-notedot{ position:absolute; bottom:4px; right:4px; vertical-align:0; }
/* PERIODISERING-EEN-WEEK-MAG-EEN-ANDERE-MEETWIJZE-HEBBEN — het metriek-icoon van
   een week die op een ANDERE meetwijze loopt dan haar schemarij. Vóór de waarde,
   in hetzelfde grijs als de soort op het rijlabel: het is CONTEXT bij het getal
   en geen tweede getal. Nooit kleur als enige signaal — het icoon zelf is het
   verschil, en zijn aria-label noemt de methode met naam. */
.cpz-wk__mk{ display:inline-flex; align-items:center; flex:none; color:var(--cpz-muted); }
.cpz-wk__mk svg{ display:block; }
.cpz-has-ov{ background:var(--cpz-accent-tint); color:var(--cpz-accent); }
.cpz-is-now{ box-shadow:inset 3px 0 0 0 var(--cpz-accent); }
.cpz-colhead.cpz-is-now{ color:var(--cpz-accent); }
/* PLANNER-PROGRESSIE-EN-DELOAD-STEL-JE-PER-FASE-IN — drie herkomsten in één
   vakje, en ze moeten naast elkaar leesbaar blijven:
   · .cpz-has-ov  — de coach TIKTE dit getal in (volle vulling, bestond al)
   · .cpz-by-rule — de REGEL rekende het uit (alleen de letterkleur: het is geen
     afwijking van het schema, het is de fase die doet wat je hem opgaf)
   · .cpz-is-deload — deze WEEK is de lichtere (arcering over de hele kolom)
   De arcering ligt op de achtergrond en laat de vulling van een override dus
   staan; wie een deloadweek handmatig overschreef ziet beide. Zij is bewust
   grijs en niet accent: een deload is geen gebeurtenis om aandacht naar toe te
   trekken, hij is de rust tussen de weken die er wel om vragen. En hij staat er
   niet alleen: de kolomkop zet het woord "deload" erbij, want een streepjes-
   patroon betekent niets voor wie het voor het eerst ziet. */
.cpz-by-rule{ color:var(--cpz-accent); }
.cpz-is-deload{
  background-image:repeating-linear-gradient(135deg,
    transparent 0, transparent 5px,
    var(--cpz-line) 5px, var(--cpz-line) 10px);
}
.cpz-colhead.cpz-is-deload{ color:var(--cpz-ink); }

/* ───── PERIODISERING-EEN-GEDANE-WEEK-TOONT-WAT-ER-GEDAAN-IS ─────
   Een week die al getraind is toont het GEDANE vooraan en het plan klein
   eronder. Drie keuzes, en elk ervan is een bestaand signaal dat niet dubbel
   mag gaan betekenen:
   · De vulling is GRIJS en geen accent. Accent-vulling zegt al "de coach tikte
     deze week" (.cpz-has-ov) en staat hierboven; een tweede betekenis op
     hetzelfde middel maakt beide onleesbaar. Daarom staat deze regel ACHTER
     .cpz-has-ov: een gedane week die de coach ook aanraakte houdt haar stip,
     maar leest als gedaan.
   · Onder plan is amber MET een pijltje. Geen rood (dat is .cpz-mob__rm, en een
     training die iets minder was is geen fout) en geen groen voor boven plan —
     de app velt hier geen oordeel.
   · De amber is in het LICHTE thema een donkerder mengsel. Gemeten (20-10):
     --warn zelf is #c69612 en haalt op wit 2,70:1 — onder de 3:1 die 13px vet
     nodig heeft; het mengsel met --cpz-ink is #907018 en haalt 4,65:1. In het
     donker is --warn zelf juist het goede getal (6,59:1 op het donkere vlak),
     dus de token kantelt mee met het thema in plaats van per regel. */
.cpz-panel{ --cpz-warn:color-mix(in srgb, var(--warn) 70%, var(--cpz-ink)); }
:root[data-theme="dark"] .cpz-panel{ --cpz-warn:var(--warn); }
.cpz-wk--done{ background:color-mix(in srgb, var(--cpz-ink) 7%, var(--cpz-white));
  flex-direction:column; align-items:flex-end; justify-content:center; gap:2px;
  padding-block:6px; position:relative; }
.cpz-wk--done .cpz-wk__v{ font-weight:750; color:var(--cpz-ink); }
.cpz-wk__n{ display:inline-flex; align-items:center; gap:1px;
  font-size:11px; font-weight:700; color:var(--cpz-muted); }
.cpz-wk__n svg{ display:block; }
/* L238 — het plan onder een gedane cel mag óók breken; afkappen zou hier het
   tweede getal van de dosis opeten. */
.cpz-wk__plan{ font-size:10.5px; font-weight:600; color:var(--cpz-faint); white-space:normal; }
.cpz-wk--below .cpz-wk__v, .cpz-wk--below .cpz-wk__n{ color:var(--cpz-warn); }
/* Voorbij en niets gelogd: het plan vaal, met een open rondje ervoor. Geen
   woord — de lopende week krijgt dit niet, want daar kan nog getraind worden. */
.cpz-wk--miss{ flex-direction:column; align-items:flex-end; justify-content:center;
  color:var(--cpz-faint); }
.cpz-wk__multi{ position:absolute; top:4px; left:7px; display:flex; gap:2px; align-items:center;
  font-size:10px; font-weight:700; color:var(--cpz-muted); }
.cpz-wk__multi svg{ display:block; }
/* Het vinkje voor "Week n" in de kolomkop van een week waarin getraind is. */
.cpz-colhead__done{ display:inline-flex; align-items:center; margin-right:3px;
  color:var(--cpz-accent); vertical-align:-1px; }
.cpz-colhead__done svg{ display:block; }
/* "Gedaan, niet gepland": één dunne scheidingsrij met een plus, daaronder de
   rijen die niet uit het schema komen. Ze dragen geen chip en geen videoknop,
   dus hun naamcel is lager dan een schemarij. */
.cpz-xtra-div{ min-height:18px; justify-content:flex-start; padding-block:2px;
  border-top:1px dashed var(--cpz-line-strong); color:var(--cpz-faint); }
.cpz-ex--xtra{ min-height:34px; font-weight:600; color:var(--cpz-muted); }
.cpz-wk--xtra{ cursor:default; }
/* Dezelfde muis-poort als .cpz-wk:hover hierboven: deze twee zijn de tegenhanger
   daarvan en horen in dezelfde stand te leven. */
@media (hover:hover) {
  .cpz-wk--xtra:hover{ background:none; }
  .cpz-wk--xtra.cpz-wk--done:hover{ background:color-mix(in srgb, var(--cpz-ink) 7%, var(--cpz-white)); }
}
/* De weektag als deur naar de bouwer. Op de telefoon is hij 44px hoog — de hele
   kolomkop is dan het doel, want de vakjes eronder doen iets ánders (een week-
   afwijking) en die twee mogen niet door één misser verwisseld worden. */
.cpz-colhead--door{ cursor:pointer; text-decoration:underline;
  text-decoration-style:dotted; text-underline-offset:3px; }
/* L238 besluit 4 — hover alleen waar er een muis is (zie .cpz-wk:hover). */
@media (hover:hover) {
  .cpz-colhead--door:hover{ background:var(--cpz-grey-lane); color:var(--cpz-accent); }
}
.cpz-colhead--door:focus-visible{ outline:none;
  box-shadow:inset 0 0 0 1.5px var(--cpz-accent); }
/* Idem: een aantikbare kolomkop in een smal vel moet 44px halen, en of het vel
   smal is zegt het vel — niet het scherm. */
@container dbox (max-width: 759.98px) {
  .cpz-colhead--door{ min-height:44px; }
  /* PERIODISERING-EEN-GEDANE-WEEK-TOONT-WAT-ER-GEDAAN-IS — op een telefoon mag
     een setregel over twee regels lopen. Afkappen zou "12 × 9 / 9 kg" tot
     "12 × 9 /…" maken, en dan is het tweede gewicht precies het ding kwijt dat
     deze fase laat zien. */
  .cpz-wk--done .cpz-wk__v{ white-space:normal; text-align:right; }
  /* L238 — in een smal vel is elke pixel inhoud er één: 14px padding liet 56px
     over voor een waarde van ~44px plus icoon en stip. 8px laat 68px over, en
     de rijkop krijgt 10px links / 4px rechts zodat "Superwoman" en "Bulgarian"
     op één regel passen naast de afspeelknop. */
  .cpz-c.cpz-wk{ padding:0 8px; }
  .cpz-c.cpz-ex{ padding:7px 4px 7px 10px; }
  .cpz-ex__nm{ font-size:12.5px; }
}

/* ───── Voeding per week ─────
   De kcal/eiwit/koolhydraat-rijen van het oude raster, nu onder de fasekaart
   waar ze bij horen en ingeklapt omdat niet elke coach ze gebruikt. Vet staat
   erbij: fat_g bestond al in de API maar had nergens een invoerveld. */
.cpz-nut{ border-top:1px solid var(--cpz-line); }
.cpz-nut__head{ display:flex; align-items:center; justify-content:space-between; gap:8px;
  width:100%; min-height:40px; padding:0 20px; cursor:pointer; text-align:left;
  border:0; background:var(--cpz-grey-soft); color:var(--cpz-muted); font-family:inherit; }
.cpz-nut__ttl{ font-size:10px; font-weight:700; letter-spacing:.09em; text-transform:uppercase; }
.cpz-nut__head > svg{ flex:none; transform:rotate(-90deg); transition:transform .12s ease; }
.cpz-nut__head.is-open{ color:var(--cpz-ink); }
.cpz-nut__head.is-open > svg{ transform:none; color:var(--cpz-accent); }
.cpz-nut__grid .cpz-c{ background:var(--cpz-grey-soft); }
.cpz-nutcell{ padding:0; }
input.cpz-v{ width:100%; min-width:0; min-height:36px; padding:0 14px;
  border:0; border-radius:2px; background:transparent; text-align:right;
  font:inherit; font-size:13px; font-weight:600; color:inherit; }
input.cpz-v:focus{ outline:none; color:var(--cpz-accent);
  box-shadow:inset 0 0 0 1.5px var(--cpz-accent); }

/* ───── de waardenkaart ─────
   Eén blad voor twee opdrachten op een andere laag: de schemawaarde (alle weken)
   of de weekwaarde (alleen die week). Dit blad hangt BUITEN .cpz-panel, dus het
   leest de gewone tokens van coach.css en niet de --cpz-*-variabelen. */
.cpz-valsheet{ display:flex; flex-direction:column; gap:12px; }
.cpz-valsheet__sub{ margin:0; font-size:12.5px; line-height:1.45; color:var(--ink-2); }
/* PERIODISERING-EEN-WEEK-MAG-EEN-ANDERE-MEETWIJZE-HEBBEN — "Deze week: Op tijd".
   Eén rustige regel onder de titel; hij LEGT UIT waarom dit blad secondenvelden
   toont op een oefening die herhalingen telt, en is daarom accent en geen grijs. */
.cpz-valsheet__mk{ margin:2px 0 0; font-size:12.5px; font-weight:700; line-height:1.4;
  color:var(--cpz-accent, var(--accent)); }
/* PERIODISERING-HET-WEEKBLAD-TOONT-ELKE-GEDANE-SET — wat er die week werkelijk
   gedaan is, bovenaan het blad: per training een datumkop en elke set heel
   eronder. Eén rustig omkaderd blok, zodat het zichtbaar iets ANDERS is dan de
   weekvelden eronder — die schrijf je, dit lees je. `--cpz-warn` bestaat hier
   niet: dit blad hangt buiten .cpz-panel, dus de pijl leest het gewone
   --warn-token. */
.cpz-valsheet__done{ display:flex; flex-direction:column; gap:10px; margin:4px 0 14px;
  padding:10px 12px; border:1px solid var(--line); border-radius:var(--radius);
  background:color-mix(in srgb, var(--ink) 5%, var(--surface)); }
.cpz-valsheet__day{ display:flex; align-items:center; gap:6px; font-size:12px; font-weight:700; color:var(--ink-2); }
.cpz-valsheet__below{ display:inline-flex; align-items:center; color:var(--warn); }
.cpz-valsheet__sides{ font-weight:600; color:var(--muted); }
.cpz-valsheet__set{ font-size:13.5px; font-variant-numeric:tabular-nums; }
.cpz-valsheet__set--best{ font-weight:700; }
.cpz-valsheet__rows{ display:flex; flex-direction:column; gap:8px; }
.cpz-valrow{ display:flex; align-items:center; gap:8px; }
.cpz-valrow__lbl{ flex:1 1 auto; min-width:0; font-size:13px; font-weight:700; }
/* PERIODISERING-WEEK-TWEE-BEGINT-WAAR-WEEK-EEN-STOPTE — "Uit week 2" onder het
   label: het getal ernaast komt uit een eerdere week en is geen schemawaarde. */
.cpz-valrow__from{ display:block; font-size:11.5px; font-weight:500; color:var(--ink-2); }
.cpz-valrow__step{ width:44px; height:44px; flex:none; padding:0; cursor:pointer;
  border:1px solid var(--line); border-radius:var(--radius);
  background:var(--surface); color:var(--ink);
  font:inherit; font-size:18px; font-weight:700; line-height:1; }
.cpz-valrow__step:active{ background:var(--line); }
.cpz-valrow__v{ width:84px; flex:none; min-height:44px; padding:0 10px; text-align:center;
  border:1px solid var(--line); border-radius:var(--radius);
  background:var(--bg); color:var(--ink); font:inherit; font-size:15px; font-weight:700; }
.cpz-valsheet__back{ align-self:flex-start; min-height:44px; padding:0 14px; cursor:pointer;
  border:1px solid var(--line); border-radius:var(--radius);
  background:var(--surface); color:var(--ink-2); font:inherit; font-size:13px; font-weight:700; }
.cpz-valsheet__back:hover{ border-color:var(--accent); color:var(--accent); }
.cpz-valsheet__foot{ margin:0; font-size:11.5px; line-height:1.45; color:var(--muted); }

/* ───── PERIODISERING-MEERDERE-CELLEN-IN-EEN-KEER-AANPASSEN ─────
   De selectiestand (binnen .cpz-panel, dus met de --cpz-*-variabelen) en het
   aanpasblad (buiten het paneel, dus met de gewone tokens).

   Een gekozen cel draagt TWEE signalen: een accentrand én een vinkje. Nooit
   kleur alleen — een coach met een telefoon in de zon of met kleurblindheid moet
   kunnen zien wat hij heeft aangetikt, en de rand valt daar als eerste weg. */
.cpz-is-sel{ position:relative; box-shadow:inset 0 0 0 2px var(--cpz-accent); }
/* De cel die NU loopt draagt al een inset-rand van 3px links; samen in één
   box-shadow, anders overschrijft de laatste regel de eerste en verdwijnt het
   "deze week"-streepje precies in de stand waarin je weken vergelijkt. */
.cpz-wk.cpz-is-now.cpz-is-sel{
  box-shadow:inset 3px 0 0 0 var(--cpz-accent), inset 0 0 0 2px var(--cpz-accent);
}
.cpz-selmark{
  position:absolute; top:2px; right:2px; display:inline-flex; flex:none;
  align-items:center; justify-content:center; width:14px; height:14px;
  border-radius:50%; background:var(--cpz-accent); color:var(--cpz-on-accent);
}
.cpz-selmark svg{ display:block; }
/* De weekkop en de rijnaam zijn in deze stand doelen; ze lenen de stippellijn
   van de bouwer-deur niet, want ze gaan nergens heen — ze kiezen. */
.cpz-colhead--pick{ cursor:pointer; }
.cpz-colhead--pick:focus-visible, .cpz-ex__nm--pick:focus-visible{
  outline:none; box-shadow:inset 0 0 0 1.5px var(--cpz-accent); }
.cpz-ex__nm--pick{ cursor:pointer; }
/* L238 besluit 4 — hover alleen waar er een muis is (zie .cpz-wk:hover). */
@media (hover:hover) {
  .cpz-colhead--pick:hover{ background:var(--cpz-grey-lane); color:var(--cpz-accent); }
  .cpz-ex__nm--pick:hover{ color:var(--cpz-accent); }
}
@container dbox (max-width: 759.98px) {
  .cpz-colhead--pick{ min-height:44px; }
}

/* De onderbalk. Hij is het LAATSTE kind van .cpz-panel en plakt met
   `position:sticky; bottom:0` aan de onderkant van de scrollbak van het vel: op
   de telefoon staat hij daarmee boven de veilige rand, op de iPad binnen het
   paneel. Omdat hij een ECHT laatste kind is en geen vast-gepositioneerde laag,
   neemt hij onderaan ruimte in en verbergt hij de laatste rasterrij niet — wie
   doorscrollt ziet hem op zijn eigen plek onder de tabel. Een dekkende
   achtergrond is daarbij geen sausje maar de voorwaarde: zonder die laag
   schuiven de weekgetallen er zichtbaar achter door. */
.cpz-selbar{
  position:sticky; bottom:0; z-index:4;
  display:flex; align-items:center; gap:10px;
  min-height:56px; padding:8px 12px calc(8px + var(--safe-bottom));
  border-top:1px solid var(--cpz-line-strong); background:var(--cpz-white);
}
.cpz-selbar__x{
  width:40px; height:40px; flex:none; padding:0; cursor:pointer;
  display:inline-flex; align-items:center; justify-content:center;
  border:1px solid var(--cpz-line-strong); border-radius:var(--radius);
  background:transparent; color:var(--cpz-ink);
}
/* L238 besluit 3 — "KIEZEN" boven de teller: de balk is een STAND en geen
   melding over wat er net gebeurde. Een kolom, zodat het woord geen breedte van
   de teller afneemt en de knoppen rechts op hun plek blijven staan. */
.cpz-selbar__lab{
  flex:1 1 auto; min-width:0; display:flex; flex-direction:column;
  align-items:flex-start; gap:1px; line-height:1.2;
}
.cpz-selbar__mode{
  font-size:10px; font-weight:700; letter-spacing:.09em; text-transform:uppercase;
  color:var(--cpz-muted);
}
.cpz-selbar__n{
  max-width:100%; font-size:13px; font-weight:700; color:var(--cpz-ink);
  white-space:nowrap;
}
.cpz-selbar__clear{
  flex:none; min-height:40px; padding:0 10px; cursor:pointer;
  border:0; background:transparent; color:var(--cpz-muted);
  font:inherit; font-size:13px; font-weight:700;
}
.cpz-selbar__clear:hover{ color:var(--cpz-accent); }
/* De ene accentknop van deze stand. Tekst in --on-accent, want dat is de enige
   kleur die op --accent in beide thema's leesbaar blijft. */
.cpz-selbar__go{
  flex:none; min-height:40px; padding:0 16px; cursor:pointer;
  border:0; border-radius:var(--radius);
  background:var(--accent); color:var(--on-accent);
  font:inherit; font-size:13px; font-weight:700;
}
.cpz-selbar__go:disabled{ opacity:.45; cursor:default; }
/* L238 besluit 3 — de regel boven de eerste fasekaart, alleen in de stand. Hij
   zegt wat een tik NU doet; zonder hem kon een trage duimtik de stand stil
   aanzetten en leek een vinkje op een cel een gelukte handeling. */
.cpz-selhint{
  display:flex; align-items:center; gap:7px; margin:0 0 8px; padding:0 4px;
  font-size:12px; font-weight:600; color:var(--cpz-muted);
}
.cpz-selhint__ic{
  display:inline-flex; align-items:center; justify-content:center; flex:none;
  width:16px; height:16px; border-radius:50%;
  background:var(--cpz-accent); color:var(--cpz-on-accent);
}
.cpz-selhint__ic svg{ display:block; }

/* ───── PERIODISERING-GEKOZEN-CELLEN-KOPIEER-JE-EN-PLAK-JE-ERGENS-ANDERS ─────
   (L237) Twee nieuwe celstanden en één tweede vorm van de onderbalk.

   DE BRON (het klembord) is STIL: een gestippelde grijze rand, geen accent en
   geen vulling. Hij zegt alleen "dit staat op je klembord"; de aandacht van de
   coach hoort bij de DOELcellen te liggen, waar het nieuwe getal al staat.

   HET DOEL draagt drie signalen, en dat is geen overdaad: een gestippelde
   accentrand, de NIEUWE waarde in de cel, en de oude waarde doorgestreept
   eronder. Kleur is nooit het enige verschil — wie de rand niet ziet leest nog
   twee getallen boven elkaar, en dat is het hele voorbeeld. */
/* Outline en NIET box-shadow: de lopende week draagt al een inset-box-shadow
   (.cpz-is-now) en een gekozen cel ook, en een tweede box-shadow-regel zou die
   stil overschrijven — precies de val die .cpz-wk.cpz-is-now.cpz-is-sel
   hierboven met een samengestelde waarde moest repareren. Een outline leeft op
   een eigen eigenschap en kan dus nooit een randsignaal wegduwen. */
.cpz-is-clip{ outline:1.5px dashed var(--cpz-line-strong); outline-offset:-2px; }
.cpz-is-paste{ outline:2px dashed var(--cpz-accent); outline-offset:-2px; }
/* De oude waarde, doorgestreept. Mag breken en kapt NIET af: afkappen zou hier
   precies het tweede getal van de dosis opeten dat de coach vergelijkt. */
.cpz-wk__old{ max-width:100%; font-size:10px; font-weight:600;
  color:var(--cpz-faint); text-decoration:line-through; white-space:normal;
  text-align:right; }
/* Het merk op de STARTCEL — hetzelfde rondje als .cpz-selmark, want het is
   hetzelfde soort bevestiging ("hier heb ik op getikt"), alleen op een andere
   hoek zodat hij niet met een keuzevinkje verwart. */
.cpz-pastemark{
  position:absolute; top:2px; left:2px; display:inline-flex; flex:none;
  align-items:center; justify-content:center; width:14px; height:14px;
  border-radius:50%; background:var(--cpz-accent); color:var(--cpz-on-accent);
}
.cpz-pastemark svg{ display:block; }

/* De gekopieerde stand van de onderbalk: een rustige regel bovenaan (alleen als
   hij iets te zeggen heeft) en daaronder dezelfde drie bedieningen op een rij.
   Daarom KOLOM hier en rij in .cpz-selbar__row — de sticky-bodem, de rand en de
   dekkende achtergrond van .cpz-selbar blijven precies zoals ze waren. */
.cpz-selbar--paste{ flex-direction:column; align-items:stretch; gap:6px; }
.cpz-selbar__row{ display:flex; align-items:center; gap:8px; }
/* `[hidden]` is alleen een UA-regel op display, en elke klasse met een eigen
   display verslaat hem stil — dus de haak staat er expliciet bij. */
.cpz-selbar__note{ display:flex; flex-direction:column; gap:2px; }
.cpz-selbar__note[hidden]{ display:none; }
/* Geen waarschuwingskleur: afsnijden is een uitkomst van wat de coach aanwees,
   geen fout — en "hier verandert niets" is een feit, geen alarm. */
.cpz-selbar__note p{ margin:0; font-size:11.5px; font-weight:600; line-height:1.35;
  color:var(--cpz-muted); }
.cpz-selbar__where{ max-width:100%; font-size:11.5px; font-weight:600;
  color:var(--cpz-muted); }
/* Kopiëren is SECUNDAIR — omlijnd met de inktkleur. De ene accentknop van een
   stand blijft de handeling die schrijft; twee accentknoppen naast elkaar zouden
   op 390 bovendien niet meer naast de teller passen. */
.cpz-selbar__copy{
  flex:none; display:inline-flex; align-items:center; gap:6px;
  min-height:40px; padding:0 12px; cursor:pointer;
  border:1px solid var(--cpz-line-strong); border-radius:var(--radius);
  background:transparent; color:var(--cpz-ink);
  font:inherit; font-size:13px; font-weight:700; white-space:nowrap;
}
.cpz-selbar__copy svg{ display:block; }
.cpz-selbar__copy:disabled{ opacity:.45; cursor:default; }

/* Het aanpasblad. Buiten .cpz-panel, dus gewone tokens — net als de waardenkaart
   waarvan het de stepperrij (.cpz-valrow) leent. */
.cpz-bulk__in{ display:flex; flex-direction:column; gap:14px; }
.cpz-bulk__chips{ display:flex; flex-wrap:wrap; gap:6px; }
.cpz-bulk__chip{
  min-height:36px; padding:0 12px; cursor:pointer;
  border:1px solid var(--line); border-radius:999px;
  background:var(--surface); color:var(--ink-2);
  font:inherit; font-size:12.5px; font-weight:700;
}
.cpz-bulk__chip.is-on{
  border-color:var(--accent); background:var(--accent); color:var(--on-accent);
}
.cpz-bulk__prev{
  display:flex; flex-direction:column; gap:6px;
  padding:10px 12px; border:1px solid var(--line); border-radius:var(--radius);
  background:var(--bg);
}
.cpz-bulk__hd{ margin:0; font-size:13.5px; font-weight:700; color:var(--ink); }
/* De wisselregel. --text-2 en GEEN waarschuwingskleur: van meetwijze wisselen is
   precies waar de coach om vroeg (Jayy, 20-10 — "geen overslaan"), dus hij wordt
   benoemd en niet als fout gekleurd. */
.cpz-bulk__sw{
  display:flex; align-items:center; gap:6px;
  margin:0; font-size:12px; font-weight:600; color:var(--ink-2);
}
.cpz-bulk__sw svg{ flex:none; }
.cpz-bulk__list{
  margin:0; padding:0; list-style:none;
  display:flex; flex-direction:column; gap:2px;
  font-size:12px; font-weight:600; color:var(--ink-2);
}
/* Welke cel, en wat ermee gebeurt — twee stukken met lucht ertussen, zodat
   "Week 2" en "3×8" op een telefoon niet als één getal lezen. */
.cpz-bulk__list li{ display:flex; flex-wrap:wrap; gap:2px 10px; }
.cpz-bulk__who{ color:var(--ink); }
.cpz-bulk__more, .cpz-bulk__follow{ font-size:11.5px; font-weight:600; color:var(--muted); }
.cpz-bulk__follow{ margin:0; }
.cpz-bulk__go{
  align-self:stretch; min-height:48px; padding:0 18px; cursor:pointer;
  border:0; border-radius:var(--radius);
  background:var(--accent); color:var(--on-accent);
  font:inherit; font-size:15px; font-weight:700;
}
.cpz-bulk__go:disabled{ opacity:.45; cursor:default; }

/* ───── PLANNER-PROGRESSIE-EN-DELOAD-STEL-JE-PER-FASE-IN: "Progressie en deload"
   Hetzelfde blad als de waardenkaart, dus ook hier de gewone tokens en niet de
   --cpz-*-variabelen: dit hangt BUITEN .cpz-panel. Het blad leent de stepperrij
   (.cpz-valrow) van de waardenkaart, want een stepper is een stepper, en de
   segment- en chip-klassen van .tabvis, want de coach kent die al uit Details. */
.cpz-prog{ display:flex; flex-direction:column; gap:12px; }
.cpz-prog__sub{ margin:0; font-size:12.5px; line-height:1.45; color:var(--ink-2); }
.cpz-prog__form{ display:flex; flex-direction:column; gap:12px; }
/* Het label boven een segment of boven de chips. Geen <label>: de groep is een
   radiogroup met aria-label, dus dit is de ZICHTBARE kant van diezelfde naam. */
.cpz-prog__lbl{
  font-size:11px; font-weight:700; letter-spacing:.06em;
  text-transform:uppercase; color:var(--muted);
}
.cpz-prog__seg-wrap{ display:flex; flex-direction:column; gap:6px; }
/* Vier soorten progressie passen op de telefoon niet naast elkaar in één pil,
   dus het segment mag afbreken in plaats van te krimpen tot onleesbaar. */
.cpz-prog__seg{ flex-wrap:wrap; border:0; border-radius:0; overflow:visible; gap:6px; }
.cpz-prog__seg .tabvis__seg-btn{
  border:1px solid var(--line-2); border-radius:var(--radius-pill, 999px); padding:6px 14px;
}
.cpz-prog__seg .tabvis__seg-btn + .tabvis__seg-btn{ border-left:1px solid var(--line-2); }
.cpz-prog__seg .tabvis__seg-btn--on{ border-color:var(--accent); }
/* De deloadschakelaar is een chip over de volle breedte: hij hoort niet bij de
   "geldt voor"-chips erboven maar is een eigen ja/nee, en volle breedte is het
   verschil tussen een keuze uit een rij en een schakelaar. */
.cpz-prog__dl{ width:100%; justify-content:space-between; min-height:44px; }
.cpz-prog__effect{
  margin:0; font-size:12px; line-height:1.45; color:var(--muted);
  font-variant-numeric:tabular-nums;
}
/* De stepperwaarde in dit blad is een <span> en geen invoerveld: de getallen zijn
   gebonden aan stapjes van 0,25 of 0,5 en wie 7,3 typt zou een 400 krijgen. */
.cpz-valrow__v--ro{
  display:inline-flex; align-items:center; justify-content:center;
  font-variant-numeric:tabular-nums;
}

/* "Zo ziet <klant> het" — het antwoord van ?dry_run=1, week voor week. Dit is
   geen voorbeeld maar het resultaat, dus het staat als een lijstje en niet als
   een hint: de coach mag erop vertrouwen. */
.cpz-prog__preview:empty{ display:none; }
.cpz-prog__preview{
  display:flex; flex-direction:column; gap:6px;
  padding:12px; border:1px solid var(--line); border-radius:var(--radius);
  background:var(--bg);
}
.cpz-prog__exnm{ margin:0; font-size:13px; font-weight:700; }
.cpz-prog__weeks{ display:flex; flex-direction:column; gap:2px; }
.cpz-prog__wk{
  display:flex; align-items:baseline; gap:8px; min-height:26px;
  font-size:13px; font-variant-numeric:tabular-nums;
}
.cpz-prog__wknm{ flex:none; width:68px; color:var(--muted); font-size:11.5px; font-weight:600; }
.cpz-prog__wkv{ flex:1 1 auto; min-width:0; font-weight:700; }
/* Dezelfde keuze als in de tabel: de lichtere week is grijs en draagt het woord,
   niet een kleur die om aandacht vraagt. */
.cpz-prog__wk.is-deload .cpz-prog__wkv{ color:var(--ink-2); }
.cpz-prog__wkdl{
  flex:none; font-size:9.5px; font-weight:700; letter-spacing:.08em;
  text-transform:uppercase; color:var(--muted);
  border:1px solid var(--line-2); border-radius:2px; padding:1px 5px;
}
.cpz-prog__done{ align-self:flex-start; }

/* footer lines */
.cpz-foot{ padding:12px 20px 16px; border-top:1px solid var(--cpz-line-strong); }
.cpz-hint{ display:flex; gap:8px; align-items:flex-start; font-size:11.5px;
  color:var(--cpz-muted); line-height:1.45; }
.cpz-hint svg{ margin-top:1px; flex:none; }

.cpz-loading, .cpz-emptystate{ padding:20px; color:var(--cpz-muted); font-size:12.5px; }

/* ── lege staat (PLANNER-PERIODISERING-STAAT-BOVENAAN-GYM-EN-DE-RUIS-IS-WEG) ──
   Wat hier stond: een zin, één knop, een inline lijst met TWEE knoppen per regel
   (.cpz-schemalist/.cpz-schemarow*) en — als er niets planbaar was — grijze
   kopbesturing (.cpz-hdr-right input:disabled e.d.) met een opdracht om elders
   iets te publiceren. UAT-flow 1 liep hier op beide breedtes vast.
   Wat er nu staat: één zin, een decorstrook die de VORM van een cyclus laat zien,
   en de uitgangen als gelijkvormige rijen. Niets uitgegrijsd: een ingang die niet
   kan, wordt niet getekend. */
.cpz-emptystate-wrap{ padding:20px; display:flex; flex-direction:column;
  align-items:stretch; gap:14px; max-width:520px; }
.cpz-emptystate-wrap .cpz-emptystate{ padding:0; line-height:1.5; }

.cpz-example{ display:flex; gap:4px; }
.cpz-example__cell{ flex:1 1 0; min-width:0; display:flex; align-items:center;
  justify-content:center; min-height:34px; padding:0 6px;
  border:1px solid var(--cpz-line); border-radius:3px; background:var(--cpz-grey-soft); }
.cpz-example__cell--deload{ flex:0 0 auto; background:var(--cpz-accent-tint);
  border-color:var(--cpz-accent); }
.cpz-example__name{ font-size:9.5px; font-weight:700; letter-spacing:.09em;
  text-transform:uppercase; color:var(--cpz-muted);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cpz-example__cell--deload .cpz-example__name{ color:var(--cpz-accent); }

.cpz-startlist{ display:flex; flex-direction:column; gap:6px; }
.cpz-start{ display:flex; align-items:center; gap:12px; width:100%;
  min-height:48px; padding:8px 12px; text-align:left; cursor:pointer;
  border:1px solid var(--cpz-line-strong); border-radius:3px;
  background:var(--cpz-white); color:var(--cpz-ink); font-family:inherit; }
.cpz-start:hover{ border-color:var(--cpz-accent); }
.cpz-start__lines{ display:flex; flex-direction:column; gap:2px; min-width:0; flex:1 1 auto; }
.cpz-start__label{ font-size:13px; font-weight:700; }
.cpz-start__meta{ font-size:11.5px; color:var(--cpz-muted);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cpz-start > svg{ flex:none; color:var(--cpz-faint); }
/* Eén primaire deur per paneel: accentvlak met de tekst in de bijbehorende
   contrastkleur (--on-accent), nooit een eigen wit. */
.cpz-start--primary{ background:var(--accent); border-color:var(--accent);
  color:var(--on-accent); }
.cpz-start--primary:hover{ border-color:var(--accent); }
.cpz-start--primary .cpz-start__meta,
.cpz-start--primary > svg{ color:var(--on-accent); opacity:.82; }

.cide-picker__item--disabled{ opacity:.5; cursor:default; }
.cide-picker__item--disabled:hover{ background:var(--surface); }
.cide-picker__item--disabled .cide-picker__meta{ color:var(--accent); }
/* PLANNER-EEN-CYCLUS-BESTAAT-UIT-FASES-VAN-EEN-AANTAL-WEKEN — een regel die iets
   weghaalt draagt die lading zelf; de bevestiging erna zegt hoeveel weekwijzigingen
   meegaan. */
.cide-picker__item.is-danger{ color:var(--danger); }
.cide-picker__item.is-danger:hover{ background:color-mix(in srgb, var(--danger) 12%, transparent); }

/* ───────── Data & consent stewardship (COACH-IDE-P3-TRAINER-ISOLATION-STEWARDSHIP-GATE) ───────── */
.csteward__intro {
  color: var(--ink-2);
  font-size: 0.9rem;
  margin: 0 var(--space-4) var(--space-4);
  max-width: 640px;
}
.csteward {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: var(--space-4);
  padding: 0 var(--space-4) var(--space-6);
}
.csteward__loading,
.csteward__empty { color: var(--muted); font-size: 0.9rem; padding: var(--space-4); }

.csteward-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.csteward-card__head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--accent);
}
.csteward-card__name { color: var(--ink); font-weight: 700; font-size: 1rem; }

.csteward-sec { display: flex; flex-direction: column; gap: var(--space-2); }
.csteward-sec__title {
  margin: 0;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  font-weight: 700;
}

.csteward-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.csteward-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 3px 10px;
  font-size: 0.78rem;
  color: var(--ink-2);
}
.csteward-chip.is-on  { border-color: var(--accent); color: var(--ink); }
.csteward-chip.is-off { color: var(--muted); }
.csteward-chip__state { color: var(--muted); font-size: 0.7rem; }
.csteward-chip.is-on .csteward-chip__state { color: var(--accent); }

.csteward-rights { display: flex; flex-direction: column; gap: var(--space-1); }
.csteward-right {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  font-size: 0.85rem;
}
.csteward-right__area { color: var(--ink-2); }
.csteward-right__val {
  font-weight: 600;
  font-size: 0.78rem;
  padding: 2px 8px;
  border-radius: var(--radius);
}
.csteward-right__val--edit { background: var(--accent); color: var(--on-accent); }
.csteward-right__val--view { border: 1px solid var(--accent); color: var(--accent); }
.csteward-right__val--none { color: var(--muted); border: 1px solid var(--line); }

.csteward-hist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-1); }
.csteward-hist__empty { color: var(--muted); font-size: 0.82rem; margin: 0; }
.csteward-hist__row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 0.82rem;
}
.csteward-hist__badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-weight: 600;
  font-size: 0.72rem;
}
.csteward-hist__badge--ok { color: var(--ok); }
.csteward-hist__badge--no { color: var(--danger); }
.csteward-hist__when { color: var(--muted); }

/* ── COACH-DOSSIER-PANEL-SKELETON-LOADERS — shimmering placeholders ──
   Dossier-only. coach.css has no --surface-2/3 ladder, so the shimmer is built
   from --line-2 → --line, which exist in both themes. */
.skel {
  background: linear-gradient(90deg, var(--line-2) 25%, var(--line) 50%, var(--line-2) 75%);
  background-size: 200% 100%;
  animation: skelShimmer 1.2s ease-in-out infinite;
  border-radius: var(--radius-sm);
  color: transparent;
}
.skel--line { height: 14px; margin: 6px 0; }
.skel--block { height: 56px; margin: 8px 0; }
@keyframes skelShimmer {
  from { background-position: 200% 0; }
  to { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .skel { animation: none; }
}

/* ── COACH-DOSSIER-DESIGN-GRAMMAR — one section-title token ──
   Every dossier section heading (all 3 tabs) renders as .dsec-title via the
   dsecTitle() helper: quiet muted label, optional 16px icon left, optional
   action right. Supersedes the old per-card __title classes. */
.dsec-title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-2);
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.dsec-title__ic { flex: 0 0 16px; width: 16px; height: 16px; color: var(--muted); }
.dsec-title__tx { min-width: 0; }
.dsec-title__act { margin-left: auto; }

/* Noordster keeps its accent-card primacy: same token, but stronger ink, no
   bottom margin (title sits in a centered flex head), and an accent star. */
/* DOSSIER-NOORDSTER-ALS-OVERZICHT — `flex: 1 1 auto` is load-bearing sinds het
   potlood in de kop hangt: `.dsec-title__act` duwt zichzelf met `margin-left:
   auto` naar rechts, en dat doet niets zolang de kop zelf tot zijn tekst
   krimpt — dan plakt de knop tegen het woord "Noordster" aan. */
.northstar__head .dsec-title { flex: 1 1 auto; margin: 0; color: var(--ink-2); letter-spacing: 0.06em; }
.northstar__head .dsec-title__ic { color: var(--accent); }

/* ── COACH-DOSSIER-DESIGN-GRAMMAR — one card anatomy ──
   title → content → footer-actions, fixed padding/radius/gap from existing
   tokens. The standard stacked dossier cards share one box; no per-card
   exceptions (northstar/sesscred keep their deliberate accent-rule variant). */
.intake-card, .gymcard, .nutcard, .cctrl, .cadh, .dchat {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}
.cctrl, .cadh, .dchat { margin-bottom: var(--space-3); }

/* COACH-DOSSIER-MINI-CHAT-WINDOW — the last slice of the coach↔client channel,
   readable and answerable in place. Bubble/composer measurements mirror the
   .cchat vocabulary so the dossier gains no third chat look; only the scroll
   box and the "open full chat" link are new. */
.dchat__thread {
  display: flex; flex-direction: column; gap: var(--space-2);
  max-height: 260px; overflow-y: auto;
}
.dchat__empty { color: var(--muted); font-size: 0.86rem; margin: 0; }
.dchat__b {
  align-self: flex-start; max-width: 82%;
  padding: 6px var(--space-3);
  background: var(--bg); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--radius);
}
.dchat__b--me {
  align-self: flex-end;
  background: var(--accent); color: var(--on-accent); border-color: transparent;
}
.dchat__b-text { font-size: 0.86rem; line-height: 1.4; white-space: pre-wrap; overflow-wrap: anywhere; }
.dchat__b-ts { margin-top: 2px; font-size: 0.7rem; opacity: 0.7; display: flex; gap: 4px; }
/* CHAT-EEN-BERICHT-BEWERK-JE-OF-HAAL-JE-WEG — a message its sender took back.
   Italic and faded on BOTH sides of the window (the --me bubble keeps its accent
   fill, so the colour comes from the text, never from a second background). */
.dchat__b--gone .dchat__b-text { font-style: italic; opacity: 0.65; }
/* The quiet word before the clock. Never louder than the timestamp it sits by. */
.dchat__b-edited::after { content: "·"; margin-left: 4px; }
.dchat__composer { display: flex; align-items: flex-end; gap: var(--space-2); }
.dchat__input {
  flex: 1 1 auto; resize: none; min-height: 34px; max-height: 120px;
  padding: 7px var(--space-3);
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--radius);
  font: inherit; font-size: 0.86rem; line-height: 1.4;
}
.dchat__input:focus { outline: none; border-color: var(--accent); }
.dchat__input::placeholder { color: var(--muted); }
.dchat__send {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0;
  background: var(--accent); color: var(--on-accent);
  border: none; border-radius: var(--radius); cursor: pointer;
}
.dchat__send:hover { background: var(--accent-2); }
.dchat__send:disabled { opacity: 0.5; cursor: default; }
.dchat__full {
  align-self: flex-start; padding: 0;
  background: none; border: none; cursor: pointer;
  color: var(--accent); font: inherit; font-size: 0.78rem; font-weight: 600;
}

/* ── COACH-DOSSIER-AI-BRAINSTORM — the private sparring card ──
   Reuses the existing .cchat vocabulary (bubbles/composer) INSIDE the .dbrain
   card, so the dossier gains no second chat vocabulary; .dbrain only supplies
   the card box, the privacy line, the thread picker and the save-as-note action.
   The .cchat overrides below are scoped under .dbrain because .cchat is sized
   for the full-height IDE panel (height:100%) and would otherwise collapse. */
.dbrain {
  display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface);
  margin-bottom: var(--space-3);
}
.dbrain__priv {
  display: flex; align-items: flex-start; gap: 6px;
  margin: calc(var(--space-2) * -1) 0 0;
  color: var(--muted); font-size: 12px; line-height: 1.45;
}
.dbrain__priv svg { flex: 0 0 14px; margin-top: 1px; }
.dbrain__bar { display: flex; align-items: center; gap: var(--space-2); }
.dbrain__sel {
  flex: 1 1 auto; min-width: 0; height: 32px; padding: 0 var(--space-2);
  background: var(--bg); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--radius);
  font: inherit; font-size: 13px;
}
.dbrain .cchat { height: auto; gap: var(--space-2); }
.dbrain .cchat__log { max-height: 360px; padding: 0; gap: var(--space-2); }
.dbrain .cchat__intro { margin: 0; padding: var(--space-3) 0; text-align: left; }
.dbrain .cchat__form { padding: var(--space-2) 0 0; }
.dbrain__save {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 6px;
  margin-top: calc(var(--space-1) * -1); padding: 2px 8px;
  background: transparent; color: var(--muted);
  border: 1px dashed var(--line); border-radius: var(--radius);
  font: inherit; font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em; cursor: pointer;
}
.dbrain__save:hover { color: var(--accent); border-color: var(--accent); }
.dbrain__save svg { flex: 0 0 auto; }
.dbrain__saved {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 6px;
  padding: 2px 8px; color: var(--accent);
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
}

/* COACH-BRAINSTORM-HARD-CONTEXT-CAP-AND-METER — de lengtemeter in de sectiekop,
   plus het neutrale bericht bij het bereiken van de limiet. Uitsluitend
   bestaande tokens; niets hier draagt tekst op een accentvlak. */
.dbrain__act { display: inline-flex; align-items: center; gap: var(--space-2); flex: 0 0 auto; }
.dbrain__meter {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11px; color: var(--ink-2);
}
.dbrain__meter-label { text-transform: lowercase; letter-spacing: .02em; white-space: nowrap; }
/* In een smal VAK wint de sectietitel: het balkje draagt de boodschap ook
   zonder woord, en het percentage blijft in de title-tooltip staan.
   DOSSIER-BLOKKEN-KIJKEN-NAAR-HUN-EIGEN-BREEDTE — dit was `@media (max-width:
   560px)`; de brainstormsectie opent in een dossiervel van ~358-488px, dus op
   elke tablet en laptop bleef het woord staan in een kop die er geen ruimte
   voor had. Drempel 440px vakbreedte. */
@container dbox (max-width: 439.98px) {
  .dbrain__meter-label { display: none; }
}
.dbrain__meter-bar {
  display: block; width: 48px; height: 4px; border-radius: 2px;
  background: var(--line-2); overflow: hidden;
}
.dbrain__meter-fill {
  display: block; height: 100%; width: 0;
  background: var(--ink-2); transition: width .3s ease;
}
.dbrain__meter--high .dbrain__meter-fill { background: var(--accent); }
.cchat__msg--notice { background: transparent; color: var(--ink-2); border: 1px solid var(--line-2); }

/* COACH-BRAINSTORM-MARKDOWN-RENDER-SHARED-LIB — opmaak binnen de assistent-
   bubbel. Spiegelt .chat__msg-text in app.css; alleen binnen .dbrain gescoped
   zodat de IDE-co-auteur (.cchat buiten .dbrain) ongewijzigd blijft.
   .cchat__msg houdt bewust white-space: pre-wrap: de renderer levert output
   zonder newlines (regels worden met <br> aaneengeplakt), terwijl de
   gebruikersbubbel via textContent wél op echte newlines leunt. */
.dbrain .cchat__msg--assistant strong { font-weight: 700; }
.dbrain .cchat__msg--assistant em { font-style: italic; }
.dbrain .cchat__msg--assistant code {
  font-family: var(--mono, monospace);
  font-size: 0.92em;
  background: var(--surface);
  padding: 0.05em 0.3em;
  border-radius: var(--radius-sm);
}
.dbrain .cchat__msg--assistant ul { margin: .25rem 0; padding-left: 1em; white-space: normal; }
.dbrain .cchat__msg--assistant li { margin: .25rem 0; }
.dbrain .cchat__msg--assistant .chat__md-table {
  width: 100%; border-collapse: collapse; margin: 6px 0;
  font-size: .86em; display: block; overflow-x: auto;
}
.dbrain .cchat__msg--assistant .chat__md-table th,
.dbrain .cchat__msg--assistant .chat__md-table td {
  padding: 4px 8px; border: 1px solid var(--line); text-align: left; white-space: nowrap;
}
.dbrain .cchat__msg--assistant .chat__md-table th { font-weight: 700; background: var(--surface); }
/* Elementen waarvan de deelboom nog geen teken toont tijdens de onthulling. */
.md-reveal-hide { display: none !important; }

/* ── COACH-DETAIL-UNIFORM button system ── */
.cbtn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-1);
  padding: var(--space-2) var(--space-3); border-radius: var(--radius);
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; line-height: 1.2;
}
.cbtn--primary   { border: 1px solid var(--accent); background: var(--accent); color: var(--on-accent); }
.cbtn--primary:active { background: var(--accent-2); }
.cbtn--secondary { border: 1px solid var(--line); background: var(--surface); color: var(--ink); }
.cbtn--secondary:active { background: var(--line-2); }
.cbtn--ghost     { border: 0; background: transparent; color: var(--accent); padding: var(--space-1) 0; }
.cbtn--icon      { width: 34px; height: 34px; padding: 0; }

/* ───────── My profile — MARKETPLACE-TRAINER-PROFILE-FOUNDATION ───────── */
.ctprof { padding: var(--space-2, 12px) 0; }
.ctprof__intro { color: var(--ink-2); margin: 0 0 var(--space-3, 16px); }
.ctprof__loading, .ctprof__empty { color: var(--muted); }
.ctprof-form { display: flex; flex-direction: column; gap: var(--space-3, 16px); }
.ctprof-field { display: flex; flex-direction: column; gap: 6px; }
.ctprof-field__label { font-size: 0.85rem; font-weight: 600; color: var(--ink-2); }
.ctprof-input {
  width: 100%;
  box-sizing: border-box;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
}
.ctprof-input:focus { outline: none; border-color: var(--accent); }
.ctprof-input--area { resize: vertical; }
.ctprof-opt { display: flex; align-items: flex-start; gap: 12px; }
.ctprof-opt__text { display: flex; flex-direction: column; gap: 2px; }
.ctprof-opt__title { font-weight: 600; color: var(--ink); }
.ctprof-opt__sub { font-size: 0.8rem; color: var(--muted); }
/* MARKTPLAATS-ZICHTBAAR-JA-OF-NEE — the "visible to your own clients" row is a
   statement, not a switch, so it gets a locked-on marker the exact size of the
   toggle next to it: the two rows line up, but only one of them can be tapped. */
.ctprof-opt--fixed { opacity: 0.85; }
.ctprof-fixed {
  flex: 0 0 auto; width: 44px; height: 26px; border-radius: 999px;
  background: var(--accent); opacity: 0.45; position: relative;
}
.ctprof-fixed::after {
  content: ''; position: absolute; top: 3px; left: 21px;
  width: 20px; height: 20px; border-radius: 50%; background: var(--on-accent);
}
.ctprof-hint { font-size: 0.8rem; color: var(--muted); margin: 4px 0 0; }

/* MARKTPLAATS-VOL-IS-EEN-EERLIJKE-STAND — ONE choice, three stacked options.
   Stacked and not a segmented row because each option carries its own
   consequence line: the coach reads what happens before he taps. */
.ctprof-state { display: flex; flex-direction: column; gap: 8px; }
.ctprof-state__opt {
  display: flex; flex-direction: column; gap: 2px; text-align: left;
  padding: 10px 12px; border-radius: 12px; font: inherit; cursor: pointer;
  border: 1px solid var(--border); background: var(--surface); color: var(--ink);
}
.ctprof-state__opt.is-on { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.ctprof-state__label { font-weight: 600; }
.ctprof-state__sub { font-size: 0.8rem; color: var(--muted); }

/* TESTIMONIAL-1-SCHEMA-KLANTFLOW — client recommendations on the coach's
   lead-page settings. A withdrawn row keeps its place, dimmed and without a
   toggle, so its absence from the public page is explained rather than
   mysterious. Tokens only. */
.ctprof-testimonials { display: flex; flex-direction: column; gap: 8px; margin-top: 18px; }
.ctprof-testimonials__list { display: flex; flex-direction: column; gap: 10px; }
.ctprof-testimonial {
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.ctprof-testimonial.is-revoked { opacity: 0.55; }
.ctprof-testimonial__body { margin: 0; color: var(--ink); line-height: 1.5; white-space: pre-wrap; }
.ctprof-testimonial__name { font-size: 0.85rem; color: var(--muted); }

.ctprof-toggle {
  flex: 0 0 auto;
  width: 46px;
  height: 26px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--line-2);
  position: relative;
  cursor: pointer;
  padding: 0;
  transition: background 0.15s ease;
}
.ctprof-toggle__knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: 0 0 0 1px var(--line);
  transition: transform 0.15s ease;
}
.ctprof-toggle.is-on { background: var(--accent); border-color: var(--accent); }
.ctprof-toggle.is-on .ctprof-toggle__knob { transform: translateX(20px); }
.ctprof-actions { display: flex; }
/* MARKETPLACE-TRAINER-AVATAR-UPLOAD — profile photo block. */
.ctprof-avatar {
  display: flex;
  align-items: center;
  gap: var(--space-4, 16px);
  margin-bottom: var(--space-4, 16px);
}
.ctprof-avatar__preview {
  flex: 0 0 auto;
  width: 96px;
  height: 96px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--line-2);
  border: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: center;
}
.ctprof-avatar__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.ctprof-avatar__placeholder {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--line);
}
.ctprof-avatar__ctrls {
  display: flex;
  flex-direction: column;
  gap: var(--space-2, 8px);
}
.ctprof-avatar__label { font-size: 0.9rem; color: var(--ink-2); }
.ctprof-avatar__btns { display: flex; flex-wrap: wrap; gap: var(--space-2, 8px); }
.ctprof-avatar__btn {
  padding: 8px 14px;
  border: 0;
  border-radius: 10px;
  background: var(--accent);
  color: var(--on-accent);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.ctprof-avatar__btn:active { background: var(--accent-2); }
.ctprof-avatar__btn:disabled { opacity: 0.6; cursor: default; }
.ctprof-avatar__btn--ghost {
  background: transparent;
  color: var(--ink-2);
  border: 1px solid var(--line);
}
.ctprof-avatar__btn--ghost:active { background: var(--line-2); }

/* CHALLENGE-IMAGE-BANNER-UPLOAD-AND-DISPLAY — banner picker in the challenge sheet. */
.chimg { display: flex; flex-direction: column; gap: var(--space-2, 8px); }
.chimg__preview {
  width: 100%;
  aspect-ratio: 16 / 7;
  border-radius: 12px;
  overflow: hidden;
  background: var(--line-2);
  border: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: center;
}
.chimg__img { width: 100%; height: 100%; object-fit: cover; }
.chimg__placeholder { font-size: 0.85rem; color: var(--ink-2); }
.chimg__btns { display: flex; flex-wrap: wrap; gap: var(--space-2, 8px); }
.ctprof-save {
  padding: 10px 18px;
  border: 0;
  border-radius: 10px;
  background: var(--accent);
  color: var(--on-accent);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.ctprof-save:active { background: var(--accent-2); }
.ctprof-save:disabled { opacity: 0.6; cursor: default; }
.ctprof-pay {
  margin-top: var(--space-4, 20px);
  padding: var(--space-3, 16px);
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--line-2);
}
.ctprof-pay__title { margin: 0 0 8px; font-size: 1rem; }
.ctprof-pay__copy { margin: 0 0 8px; color: var(--ink-2); font-size: 0.9rem; }
.ctprof-pay__copy:last-child { margin-bottom: 0; }

/* MARKETPLACE-COACHLESS-TRAINER-DISCOVERY — lead source label (in-app vs public page). */
.caanv-card__source {
  display: inline-block;
  margin: 4px 0 0;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--line-2);
  color: var(--ink-2);
  font-size: 0.75rem;
}
.caanv-card__source--in_app {
  background: var(--accent);
  color: var(--on-accent);
}
/* LEAD-INTAKE-SPAM-V2 — onboarding-funnel rows share the spam folder with the
   coach's own leads, so the chip must read as a different origin at a glance.
   Outlined rather than filled: it is a provenance label, not a call to act. */
.caanv-card__source--onboarding {
  background: transparent;
  border: 1px solid var(--line);
  color: var(--muted);
}

/* COACH-AANVRAGEN-CARD-UX-DOPAMINE-PROFESSIONAL — request cards mirror the
   .cinbox-card visual language; a 'new' lead gets an accent left-rail, dot,
   'New' pill and a one-time highlight so it demands attention, professionally. */
.caanv { display: flex; flex-direction: column; gap: var(--space-3); }
.caanv__loading, .caanv__empty { color: var(--muted); font-size: 0.9rem; padding: var(--space-4) 0; }
.caanv-card {
  padding: var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface);
}
.caanv-card--new { border-left: 3px solid var(--accent); animation: caanv-new-in 1.1s ease-out 1; }
/* REVIEW-AANVRAGEN-EN-COACHZAKEN-HEBBEN-EEN-BESTEMMING (L212) — de kaart die de
   postvakmelding aanwees (?lead=<id>). Dezelfde taal als .cfin-row--focus: een
   gekleurde ondergrond en een streep aan de kop, geen vak om de kaart (L183).
   De animatie van --new wordt hier uitgezet: twee keer oplichten is één keer te
   veel, en de nieuwste lead is juist degene die wordt aangewezen. */
.caanv-card--focus {
  animation: none;
  border-left: 3px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, var(--surface));
}
.caanv-card__top { display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2); }
.caanv-card__dot { flex: 0 0 auto; width: 8px; height: 8px; border-radius: 999px; background: var(--accent); }
.caanv-card__name { font-weight: 600; color: var(--ink); }
.caanv-card__date { margin-left: auto; color: var(--muted); font-size: 0.78rem; }
.caanv-card__tags { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2); }
.caanv-card__new {
  display: inline-block; padding: 2px var(--space-2);
  border-radius: var(--radius-pill); font-size: 0.72rem; font-weight: 700;
  background: var(--accent); color: var(--on-accent);
}
.caanv-card__contact {
  display: flex; flex-wrap: wrap; gap: var(--space-2);
  margin: 0 0 var(--space-2);
}
.caanv-card__link {
  display: inline-flex; align-items: center;
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius-pill);
  background: var(--surface); color: var(--accent);
  font-size: 0.85rem; text-decoration: none;
}
.caanv-card__link:hover { border-color: var(--accent); }
.caanv-card__msg { margin: 0 0 var(--space-2); color: var(--ink-2); font-size: 0.9rem; white-space: pre-wrap; }
.caanv-chip {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink);
  font: inherit; font-size: 0.85rem; font-weight: 600; cursor: pointer;
}
.caanv-chip:hover { border-color: var(--accent); }
.caanv-chip:disabled { opacity: 0.55; cursor: default; }

/* LEAD-INTAKE-SPAM-SCORING-AND-SPAM-FOLDER — the spam folder is a quiet, muted
   sibling of the requests list: findable, but it must never compete with real
   leads for attention, so no accent rail, no dot, no highlight animation. */
.caanv-filter {
  display: flex; flex-wrap: wrap; gap: var(--space-2);
  margin: 0 0 var(--space-3);
}
.caanv-filter__btn {
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius-pill);
  background: var(--surface); color: var(--ink-2);
  font: inherit; font-size: 0.82rem; font-weight: 600; cursor: pointer;
}
.caanv-filter__btn:hover { border-color: var(--accent); }
.caanv-filter__btn--on {
  border-color: var(--accent);
  background: var(--accent); color: var(--on-accent);
}
.caanv-card__spamsig { margin: 0 0 var(--space-2); color: var(--muted); font-size: 0.78rem; }
.caanv-chip--spam { color: var(--ink-2); }

@keyframes caanv-new-in {
  0%   { background: color-mix(in srgb, var(--accent) 18%, var(--surface)); }
  100% { background: var(--surface); }
}
@media (prefers-reduced-motion: reduce) {
  .caanv-card--new { animation: none; }
}

/* SASSU-CRM-PAYMENTS-LEDGER — trainer payment ledger screen + sheets. */
.cpay__note { margin: 0 0 var(--space-4); color: var(--muted); font-size: 14px; line-height: 1.45; }
.cpay__newbtn {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: var(--space-3) var(--space-4); margin-bottom: var(--space-4);
  border: 1px solid var(--line); background: var(--surface); color: var(--ink);
  border-radius: var(--radius); cursor: pointer; font-size: 14px;
}
.cpay__loading, .cpay__empty { margin: var(--space-4) 0; color: var(--muted); font-size: 14px; }
.cpay-rosterhits { display: flex; flex-direction: column; gap: var(--space-2); margin-bottom: var(--space-3); }
.cpay-rosterhit {
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-2);
  padding: var(--space-3); border: 1px dashed var(--line);
  border-radius: var(--radius); background: var(--surface);
}
.cpay-rosterhit__head { display: flex; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; }
.cpay-rosterhit__name { font-weight: 700; color: var(--ink); font-size: 16px; }
.cpay-rosterhit__num { color: var(--muted); font-size: 12px; }
.cpay-rosterhit__none { margin: 0; color: var(--muted); font-size: 13px; }
.cpay-summary { display: flex; gap: var(--space-3); margin-bottom: var(--space-4); }
.cpay-summary__stat {
  flex: 1; display: flex; flex-direction: column; gap: 2px;
  padding: var(--space-3); border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface);
}
/* GELD-EEN-GETAL-WINT — de deur Klanten krijgt hetzelfde recept als Overzicht:
   Ontvangen groot, Openstaand en Terugbetaald klein eronder, in één kader. */
.cpay-summary--hero {
  flex-direction: column; gap: var(--space-3);
  padding: var(--space-3); border: 1px solid var(--line-2);
  border-radius: var(--radius); background: var(--surface);
}
.cpay-summary__pair { display: flex; gap: var(--space-4); }
.cpay-summary__pair .cstat { flex: 1; }
.cpay-summary__val { font-size: 20px; font-weight: 700; color: var(--ink); }
.cpay-summary__lbl { font-size: 12px; color: var(--muted); }
.cpay-summary__stat--danger .cpay-summary__val { color: var(--danger); }
/* COLLEGA-FACTUUR-DE-OMZET-KLOPT — de uitleg onder de samenvatting: wat een
   collega betaalde staat op geen enkele klantkaart, dus zonder deze regel las
   Ontvangen hier lager dan op deur Overzicht. Zelfde toon als .cfin-hero__scope:
   het is een voetnoot bij een getal, geen getal. */
.cpay-summary__colleagues {
  margin: var(--space-2) 0 var(--space-3); font-size: 14px; color: var(--ink-2);
}
/* GELD-DE-KLANTKAART-WORDT-WEER-EEN-KAART — vier regels binnen 140px: wie,
   hoeveel geld, welk betaalstelsel, en één actie. De kaart was een scherm van
   ruim 1.500px met zes knoppen; alles wat hier weg is leeft door op het
   klant-geldvel. `overflow` staat bewust op zichtbaar: het overloopmenu klapt
   onder zijn knop uit en werd door een verborgen overflow afgeknipt. */
.cpay-card {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); margin-bottom: var(--space-3); overflow: visible;
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--space-3) var(--space-4);
}
.cpay-card__head {
  /* Een lange Nederlandse naam mag wikkelen in plaats van het saldo van de
     rechterrand af te knippen. */
  display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
}
.cpay-card__name { font-weight: 700; color: var(--ink); font-size: 16px; }
/* GELD-PAKKETTEN-EN-DOSSIER-NETJES — de pakketkaart had naam en prijs in EEN
   flexregel met wikkeling, dus een lange pakketnaam duwde het bedrag naar een
   eigen regel of tegen de rand. Kolommen dus: naam links (afgekapt), prijs
   rechts. Eigen modifier, want .cpay-card__head draagt ook de klantkaart en die
   rij heeft een andere inhoud.
   GELD-EEN-PAKKET-KOPIEER-JE-EN-DE-KAART-WORDT-EEN-REGEL — een DERDE kolom voor
   de ⋯: die zweefde los onder de kaart en wees daar niets aan. In de kopregel
   hoort hij bij de naam waar hij over gaat. Het interval stond hier op regel 2
   en is opgegaan in .cpay-card__meta eronder. */
.cpay-card__head--pkg {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: baseline;
  column-gap: var(--space-2); row-gap: 2px;
}
.cpay-card__head--pkg .cpay-card__name {
  grid-column: 1; grid-row: 1;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cpay-card__price {
  grid-column: 2; grid-row: 1; justify-self: end;
  color: var(--ink); font-weight: 700; font-size: 14px;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* De ⋯ is 32px hoog tussen twee tekstregels: op de basislijn zou hij een halve
   knop onder de naam hangen, dus hij centreert in zijn eigen cel. De negatieve
   rechtermarge trekt zijn transparante klikvlak terug naar de kaartrand, zodat
   het icoon zelf op één lijn staat met de rechterrand van de tekst eronder. */
.cpay-card__head--pkg .cpay-ov {
  grid-column: 3; grid-row: 1; align-self: center;
  margin-left: 0; margin-right: -6px;
}
/* De meta-regel: ritme · credits · btw · klanten. Één gedempte regel in plaats
   van drie regels en drie chips — dit scherm is BEHEER, dus de feiten scan je
   en de handelingen wachten in het menu. */
.cpay-card__meta {
  margin: 2px 0 0; color: var(--muted); font-size: 13px; line-height: 1.35;
}
.cpay-card__tally {
  margin-left: auto; color: var(--ink); font-weight: 700; font-size: 14px;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* De geldregel: één zin, tabulair, zodat een kolom kaarten onder elkaar
   uitgelijnd leest. Rood alleen op het deel dat ECHT te laat is. */
.cpay-card__money {
  margin: 0; display: flex; align-items: baseline; flex-wrap: wrap;
  column-gap: var(--space-2); row-gap: 2px;
  font-size: 14px; color: var(--ink-2); font-variant-numeric: tabular-nums;
}
.cpay-card__money > span + span::before { content: '· '; color: var(--muted); }
.cpay-card__open--late { color: var(--danger); font-weight: 600; }
/* De stelsel-zin: waar het geld van deze klant vandaan komt. Gedempt, want het
   is een feit dat zelden verandert — niet iets dat om een handeling vraagt. */
.cpay-card__system {
  margin: 0; font-size: 13px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* De actierij: één zichtbare knop links, het overloopmenu rechts. */
.cpay-card__acts {
  display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-1);
}
.cpay-card__prim {
  border: 1px solid var(--line); border-radius: var(--radius-pill);
  padding: 5px var(--space-3); background: var(--surface); color: var(--accent);
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.cpay-card__prim:hover { border-color: var(--accent); }
.cpay-card__prim:disabled { opacity: 0.6; cursor: default; }
/* ⋯ op de klantkaart. Zelfde vorm en zelfde gedrag als het menu op een
   notitiekaart; alleen staat dit menu in de rij en niet in een hoek. */
.cpay-ov { position: relative; margin-left: auto; }
.cpay-ov__btn {
  display: flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0;
  border: 0; border-radius: var(--radius); background: transparent;
  color: var(--muted); cursor: pointer;
}
.cpay-ov__btn:hover { color: var(--ink); background: var(--line-2); }
.cpay-ov__list {
  display: none; position: absolute; top: calc(100% + 4px); right: 0; z-index: 5;
  min-width: 200px; flex-direction: column;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); overflow: hidden;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
}
.cpay-ov__list.is-open { display: flex; }
.cpay-ov__item {
  display: flex; align-items: center; padding: var(--space-2) var(--space-3);
  border: 0; background: transparent; color: var(--ink);
  font: inherit; font-size: 0.88rem; text-align: left; cursor: pointer;
  white-space: nowrap;
}
.cpay-ov__item:hover { background: var(--line-2); }
.cpay-ov__item--danger { color: var(--danger); }
/* CREDITS-ONGEKOPPELDE-KLANT-BLIJFT-ONZICHTBAAR — geen getal maar een stand, dus
   ook niet de vette cijferstijl van een saldo: gedempt en normaal van gewicht,
   zodat het oog hem niet als administratie leest. Kleur uit de tokens, dus licht
   en donker volgen vanzelf. */
.cpay-card__tally--unlinked {
  color: var(--muted); font-weight: 500; font-size: 13px;
}
.cpay-dot { width: 8px; height: 8px; border-radius: var(--radius-pill); flex: 0 0 auto; background: var(--muted); }
/* GELD-KLEUR-VERTELT-DE-WAARHEID — the dot has three meanings, not two. A
   planned instalment keeps the neutral base colour on purpose: a colour that
   lights up for every client every month is a colour the coach stops reading. */
/* GELD-DE-LIJST-LEEST-ALS-EEN-BANKAPP — rustige toestanden dragen geen kleur:
   "alles voldaan" en "termijn gepland" zijn de normale gang van zaken, en een
   kleur die bij elke klant aanstaat is een kleur die niemand meer leest. */
.cpay-dot--ok { background: var(--muted); }
.cpay-dot--planned { background: var(--muted); }
.cpay-dot--warn { background: var(--warn); }
.cpay-dot--danger { background: var(--danger); }
.cpay-agr {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2);
  padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--line-2);
}
.cpay-agr:last-child { border-bottom: 0; }
.cpay-agr--inactive { opacity: 0.55; }
.cpay-agr__main { display: flex; flex-direction: column; gap: 1px; margin-right: auto; }
.cpay-agr__label { font-weight: 600; color: var(--ink); }
.cpay-agr__meta { font-size: 13px; color: var(--muted); }
.cpay-agr__link { font-size: 13px; color: var(--accent); text-decoration: none; }
.cpay-cash {
  display: inline-flex; align-items: center; gap: var(--space-1);
  font-size: 13px; color: var(--ink-2); cursor: pointer;
}
.cpay-cash--sheet { margin: var(--space-2) 0; font-size: 14px; }
.cpay-cash__input { margin: 0; }
.cpay-agr__rec {
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding: var(--space-2) var(--space-3); border: 1px solid var(--line);
  background: var(--surface); color: var(--ink); border-radius: var(--radius);
  cursor: pointer; font-size: 13px;
}
.cpay-rec__agr { margin: 0 0 var(--space-3); color: var(--muted); font-size: 14px; }
.cpay-agr__edit {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0; border: 1px solid var(--line);
  background: var(--surface); color: var(--muted); border-radius: var(--radius);
  cursor: pointer; flex: 0 0 auto;
}
.cpay-agr__readonly { margin: 0; color: var(--muted); font-size: 14px; }
.acform__submit--danger {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-1);
  margin-top: var(--space-2); background: var(--surface);
  color: var(--danger); border: 1px solid var(--danger);
}

/* ── PAYMENTS-PACKAGES-AND-SUBSCRIPTIONS-ADMIN ──
   The recurring-package strip on a payment card, and the package cards on the
   Packages screen. Deliberately built from the same tokens and the same
   .cpay-credits__btn / .cpay-credits__actions controls as the credits strip
   directly below it, so the card reads as one surface instead of three. */
.cpay-sub {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--line-2);
  display: flex; flex-direction: column; gap: var(--space-2);
}
.cpay-sub__head {
  font-size: 12px; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--muted);
}
.cpay-sub__none { margin: 0; color: var(--muted); font-size: 14px; }
/* Wraps: at 390px the name, the amount and the status chip do not fit on one
   line, and a truncated status is exactly the word the coach needs to read. */
.cpay-sub__row { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); }
.cpay-sub__name { font-weight: 600; color: var(--ink); }
.cpay-sub__amt { color: var(--ink-2); font-size: 14px; }
/* Lucht boven, want deze regel volgt op de chiprij en plakte er zonder marge
   tegenaan. */
.cpay-sub__next { margin: var(--space-1) 0 0; color: var(--muted); font-size: 13px; }
/* GELD-ABO-VLOEIENDE-KOPPELFLOW — de volgende-stap-strook. Een eigen omlijnd
   vlak en niet los tussen de regels, omdat dit het enige stuk van de kaart is
   waar nog iets van een ANDER gevraagd wordt; tussen de status en het bedrag in
   zou het meelezen als gewoon nog een feit. */
.cpay-sub__invite {
  display: flex; flex-direction: column; align-items: flex-start;
  gap: var(--space-2); margin-top: var(--space-2);
  padding: var(--space-2); border: 1px solid var(--line-2); border-radius: var(--radius);
}
/* GELD-RUIMTE-EN-MARGES hing hier een inspring-reparatie op blokken die
   RECHTSTREEKS aan de kaart hingen. Die blokken wonen sinds
   GELD-DE-KLANTKAART-WORDT-WEER-EEN-KAART op het klant-geldvel, waar hun eigen
   wrapper de padding draagt — de reparatie had daar niets meer te repareren. */
/* COACH-COLLEGA-UITNODIGEN-IN-EEN-LINK — de link zelf plus zijn kopieerknop, en
   de enkele tekstactie op een uitnodigingskaart. Beide leven alleen in het
   uitnodigingsvel; ze lenen de maten van de kaarten eromheen. */
.acpane__linkbox { display: flex; flex-direction: column; gap: var(--space-2); }
/* EEN-QR-IN-DE-ZAAL-EN-JIJ-ZET-ZE-AAN — de QR-plaat blijft in BEIDE thema's
   wit. Een QR wordt gelezen als donker-op-licht; hem in Nacht omdraaien levert
   een code op die veel telefooncamera's weigeren, en juist deze moet in een
   zaal omhoog worden gehouden en in één keer scannen. */
.czaal__qr {
  background: #fff;
  border-radius: 14px;
  padding: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.czaal__qr svg { width: 100%; height: auto; display: block; max-width: 240px; }
/* ZAAL-QR-IN-TWEE-TIKKEN — op een eigen scherm mag de code zo groot als het
   scherm toelaat: hij wordt van een telefoon in een zaal gescand, en elke
   millimeter is leesafstand. De witte plaat erboven blijft ongemoeid. */
.czaal__qr--page { margin: 0 auto var(--space-3); max-width: 298px; }
.czaal__qr--page svg { max-width: 270px; }
/* WIE-BINNENKOMT-KRIJGT-EEN-ZAAL — de zaalkeuze staat BOVEN de code: je kiest
   de zaal voordat je de telefoon omhoog houdt, niet erna. */
.czaal__gym { margin: 0 auto var(--space-2); max-width: 298px; }
.czaal__gym select { width: 100%; }
.czaal__limits { margin: var(--space-2) 0 0; color: var(--muted); font-size: 0.85rem; }
.czaal__acts { display: flex; flex-direction: column; gap: var(--space-2); margin: var(--space-3) 0; }
/* COLLEGA-DE-ZAAL-QR-STAAT-OOK-BIJ-DE-UITNODIGING — de bediening voor een
   NIEUWE code: de geldigheidskeuze plus de knop die hem maakt. Een eigen blok
   naast .czaal__acts, want de drie keuzechips zijn geen acties op de code die
   er nu staat. De chips lenen .cfin-chips__btn van de Geld-tab in plaats van
   een vierde eigen chipvorm: die klasse staat al op tokens (--surface, --line,
   --accent), dus hij is in Nacht meteen goed en kan niet uiteen gaan lopen. */
.czaal__ctl { display: flex; flex-direction: column; gap: var(--space-2); margin: 0 0 var(--space-3); }
.czaal__ctl .acform__hint { margin: 0; }
.czaal__durrow { flex-wrap: wrap; }
/* De witte plaat blijft wit in BEIDE thema's (een QR wordt gelezen als
   donker-op-licht), dus de tekst erop staat net als .pkqr__name HARD op een
   donkere kleur: var(--ink) zou in Nacht wit op wit opleveren. */
.czaal__stopped { margin: 0; color: #555; font-size: 15px; font-weight: 700; text-align: center; }
/* De groepsdeur: knop plus de regel die hem uitlegt, als één paar. Op het
   Collega's-scherm staat hij in blokstroom en draagt hij dus zelf zijn marges;
   in het uitnodigingsvel is .acpane een flexkolom met een eigen gap, en een
   marge BOVENOP die gap zet de knop los van de regel die hem uitlegt. */
.czaal__groupdoor { margin-bottom: var(--space-2); }
.czaal__groupwhy { margin: 0 0 var(--space-4); }
.acpane .czaal__groupdoor { margin-bottom: 0; justify-content: center; }
.acpane .czaal__groupwhy { margin-bottom: 0; }
/* DE-QR-KAN-OOK-ALS-LINKJE-DE-DEUR-UIT — icon + label on one baseline. */
.czaal__share { display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
/* Schermvullend: zwart-op-wit over alles heen, zonder tabbalk, een tik terug.
   Geen Fullscreen API — de coach-app draait ook in een iframe, en een beamer
   spiegelt het scherm toch. */
.czaal-fs {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  padding: var(--space-4); background: #fff; cursor: pointer;
}
.czaal-fs__plate { width: 100%; max-width: min(92vw, 92vh); }
.czaal-fs__plate svg { width: 100%; height: auto; display: block; }
/* PAKKET-EEN-INTAKE-QR-OP-VOLLEDIG-SCHERM — dezelfde witte plaat, maar met drie
   regels tekst erbij: pakketnaam, het bedrag van vandaag en de kopieerknop. De
   kleuren staan HARD en niet op een token: de overlay is in BEIDE thema's wit
   (een QR wordt gelezen als donker-op-licht), dus var(--ink) zou in Nacht wit
   op wit opleveren. De overlay zelf krijgt daarom ook geen cursor:pointer meer
   — er staat een knop in, en 'alles is een sluiter' klopt hier niet. */
.czaal-fs--pkg { cursor: default; flex-direction: column; gap: var(--space-3); }
.czaal-fs--pkg .czaal-fs__plate {
  display: flex; flex-direction: column; align-items: center; gap: var(--space-2);
  max-width: min(92vw, 70vh);
}
.pkqr__name { margin: 0; font-size: 1.1rem; font-weight: 700; color: #111; text-align: center; }
.pkqr__today { margin: 0; font-size: 1.5rem; font-weight: 700; color: #111; text-align: center; }
.pkqr__qr { width: 100%; }
.pkqr__qr .cpay__loading { color: #555; margin: 0; }
.pkqr__copy { min-width: 180px; }
/* COLLEGA-ELKE-UITNODIGINGSLINK-KRIJGT-EEN-QR — de kleine code in de lade en
   diens volledige scherm. Dezelfde witte plaat als de zaal- en pakket-QR, en om
   dezelfde reden HARDE kleuren in plaats van tokens: de overlay is in BEIDE
   thema's wit, want een QR wordt gelezen als donker-op-licht en een omgekeerd
   vlak weigeren veel telefooncamera's. var(--ink) zou in Nacht wit op wit zijn. */
.czaal-fs--invite { flex-direction: column; gap: var(--space-3); }
.czaal-fs--invite .czaal-fs__plate {
  display: flex; flex-direction: column; align-items: center; gap: var(--space-2);
  max-width: min(92vw, 70vh);
}
.cinvqr__for { margin: 0; font-size: 1.1rem; font-weight: 700; color: #111; text-align: center; }
.cinvqr__plate { width: 100%; }
.cinvqr__plate .cpay__loading { color: #555; margin: 0; }
/* De code in de lade is een KNOP, dus hij moet zijn knop-standaarden kwijt —
   .czaal__qr geeft hem de witte plaat, de rest komt hier weg. ±200px code op een
   plaat van 228px: 200 + twee keer de 14px padding van .czaal__qr. */
.cinvqr__inline {
  border: 0; cursor: pointer; font: inherit;
  width: 100%; max-width: 228px; margin: 0;
}
.cinvqr__inline svg { max-width: 200px; }
.cinvqr__inline .cpay__loading { color: #555; margin: 0; }
.cinvqr__inline:disabled { cursor: default; }
/* Twee tekstacties naast elkaar op een uitnodigingsregel. .cpay-card__act draagt
   zelf de zijmarge van de kaart; in een rij neemt deze wrapper die over. */
.cinvqr__row {
  display: flex; align-items: center; gap: var(--space-3);
  margin: 0 var(--space-4) var(--space-3);
}
.cinvqr__row .cpay-card__act { margin: 0; }
.cpay-card__act {
  align-self: flex-start; margin: 0 var(--space-4) var(--space-3);
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; font-weight: 600; color: var(--accent);
}
.cpay-card__act:disabled { opacity: 0.6; cursor: default; }
.cpay-sub__chip {
  /* GELD-DE-KLEINE-FOUTEN-EERST — de trainersvergoeding-chip draagt een icoon
     naast zijn tekst; zonder gap plakte het er tegenaan. */
  display: inline-flex; align-items: center; gap: 4px; padding: 2px var(--space-2);
  border-radius: var(--radius-pill); font-size: 13px; font-weight: 600;
  background: var(--line-2); color: var(--ink-2);
}
/* GELD-DONKER-HOORT-BIJ-HET-MERK — statuschips volgen ÉÉN recept, dat van
   .cfin-status hieronder: 14% van de toonkleur als vlak, de tekst een 78%-menging
   van diezelfde toon naar --ink. Ze droegen hun tekst in --ink en waren daarmee
   drie chips die alleen in achtergrond verschilden; de kleur die je ziet is nu
   ook echt het verschil tussen twee toestanden. --off/--none blijft neutraal. */
.cpay-sub__chip--ok      { background: color-mix(in srgb, var(--ok) 14%, transparent); color: color-mix(in srgb, var(--ok) 78%, var(--ink)); }
.cpay-sub__chip--pending { background: color-mix(in srgb, var(--accent) 14%, transparent); color: color-mix(in srgb, var(--accent) 78%, var(--ink)); }
.cpay-sub__chip--bad     { background: color-mix(in srgb, var(--danger) 14%, transparent); color: color-mix(in srgb, var(--danger) 78%, var(--ink)); }
.cpay-sub__chip--off     { background: var(--line-2); color: var(--muted); }
/* PAKKETLINK-EEN-OPENBARE-KASSA-VERLOOPT-NIET — een aanmeldlink die binnen
   veertien dagen afloopt. Alleen DIT geval kleurt: een link zonder vervaldatum
   is de gewenste stand en blijft dus de kale chip. */
.cpay-sub__chip--warn    { background: color-mix(in srgb, var(--warn) 16%, transparent); color: color-mix(in srgb, var(--warn) 80%, var(--ink)); }
/* An archived package stays legible — it is history the coach may reactivate,
   not disabled UI. */
.cpay-card--off { opacity: 0.7; }
/* DE-BEL-BRENGT-JE-NAAR-DE-AANMELDING — the one person the bell sent you here
   for. An accent rail, nothing louder: the coach is standing in a room reading
   this at arm's length and the row is already at the top of the list. */
.cpay-card--marked { border-left: 3px solid var(--accent); }

/* ── PAYMENTS-PAUSE-AND-CHARGE-EDIT-UI ──
   The list of upcoming instalments under the subscription strip. The date is
   fixed-width so six rows read as a column of dates the eye can scan, and the
   amount pushes the status chip to the right edge. */
.cpay-chg { display: flex; flex-direction: column; gap: var(--space-1); }
/* Wraps sinds GELD-BETAALLINK-4: bij een betaallink draagt deze rij naast de
   status ook "staat N dagen open" en een herinneringsknop, en die vier dingen
   passen op 390px niet meer op één regel. Zonder wrap wordt het document breder
   dan het scherm — dezelfde faalwijze die .cpay-sub__row hierboven al opvangt. */
.cpay-chg__row {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2);
  font-size: 14px; color: var(--ink-2);
}
.cpay-chg__date { min-width: 7.5em; color: var(--ink); }
.cpay-chg__amt { margin-inline-end: auto; }
/* A settled instalment is context, not something to act on. */
.cpay-chg__row--past { color: var(--muted); }
.cpay-chg__btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; padding: 0;
  border: 1px solid var(--line-2); border-radius: var(--radius-sm);
  background: transparent; color: var(--ink-2); cursor: pointer;
}
.cpay-chg__btn:hover { background: var(--line-2); color: var(--ink); }

/* ── SASSU-CRM-CREDITS-BUNDLES-CORE ── */
.cpay-credits {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--line-2);
  display: flex; flex-direction: column; gap: var(--space-2);
}
.cpay-credits__row { display: flex; align-items: center; gap: var(--space-2); }
.cpay-credits__chip {
  display: inline-flex; align-items: center; padding: 2px var(--space-2);
  border-radius: var(--radius-pill); font-size: 13px; font-weight: 600;
  background: var(--line-2); color: var(--ink-2);
}
.cpay-credits__chip--ok   { background: color-mix(in srgb, var(--ok) 14%, transparent); color: color-mix(in srgb, var(--ok) 78%, var(--ink)); }
.cpay-credits__chip--low  { background: color-mix(in srgb, var(--accent) 14%, transparent); color: color-mix(in srgb, var(--accent) 78%, var(--ink)); }
.cpay-credits__chip--over { background: color-mix(in srgb, var(--danger) 14%, transparent); color: color-mix(in srgb, var(--danger) 78%, var(--ink)); }
.cpay-credits__chip--none { background: var(--line-2); color: var(--muted); }
/* CREDITS-TERUGWERKEND-BIJBOEKEN-VRAAGT-BEVESTIGING — de wachtregel. Accentkleur
   omdat hij om een antwoord vraagt, maar geen gevulde knop: er staat nog niets
   in de administratie, dus hij mag de tegoedchip erboven niet overstemmen.
   Volle breedte, want het aantal moet leesbaar blijven op 390px. */
.cpay-credits__backfill {
  display: flex; align-items: center; gap: var(--space-2); width: 100%;
  margin-top: var(--space-2); padding: var(--space-3);
  border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--line));
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  color: var(--ink); border-radius: var(--radius);
  cursor: pointer; font-size: 14px; font-weight: 600; text-align: left;
}
.cbfill__count { font-size: 30px; font-weight: 700; color: var(--ink); }
.cbfill__period { margin-top: 2px; font-size: 15px; color: var(--ink-2); }
.cbfill__decline {
  display: block; width: 100%; margin-top: var(--space-3);
  padding: var(--space-3) var(--space-4); border: 1px solid var(--line);
  background: var(--surface); color: var(--muted);
  border-radius: var(--radius); cursor: pointer; font-size: 15px;
}
.cbfill__decline:disabled { opacity: 0.5; cursor: default; }

/* CREDITS-RECHTZETTEN-VANAF-DE-REVIEWKAART — het blad achter 'Rechtzetten'.
   Eén rij per sessie: wanneer, waar hij vandaan komt, en drie knoppen waarvan er
   altijd precies één aan staat. De tokens doen het werk in beide thema's; de
   aangezette knop draagt --on-accent, nooit een eigen wit. */
.cfix__list { margin-top: var(--space-3); }
.cfix__row { padding: var(--space-3) 0; border-top: 1px solid var(--line); }
.cfix__row:first-child { border-top: 0; }
.cfix__when { font-size: 15px; font-weight: 700; color: var(--ink); }
.cfix__src { margin-top: 1px; font-size: 13px; color: var(--ink-2); }
.cfix__opts { display: flex; gap: var(--space-2); margin-top: var(--space-2); }
.cfix__opt {
  flex: 1 1 0; min-width: 0; padding: var(--space-3) var(--space-2);
  border: 1px solid var(--line); background: var(--surface-2, var(--surface));
  color: var(--ink); border-radius: var(--radius);
  cursor: pointer; font-size: 14px; font-family: inherit;
}
.cfix__opt--on {
  background: var(--accent); color: var(--on-accent);
  border-color: var(--accent); font-weight: 700;
}
.cfix__empty { padding: var(--space-4) 0; font-size: 15px; color: var(--ink-2); }
.cfix__warn {
  margin-top: var(--space-3); padding: var(--space-3);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--warn, var(--accent)) 16%, transparent);
  color: var(--ink); font-size: 14px; line-height: 1.45;
}
.cfix__bundle {
  display: block; margin-top: var(--space-2); padding: 0; border: 0;
  background: none; color: var(--accent); font-family: inherit;
  font-size: 14px; font-weight: 700; cursor: pointer;
}
.cfix__foot {
  display: flex; justify-content: space-between; gap: var(--space-3);
  margin-top: var(--space-3); padding-top: var(--space-3);
  border-top: 1px solid var(--line); font-size: 14px; color: var(--ink-2);
}
.cfix__foot strong { color: var(--ink); }
/* De voet van de Review-kaart draagt nu twee dingen: de deur naar het dossier
   en de handeling zelf. Alleen DEZE voet gaat uit elkaar staan — de andere
   geldkaarten houden hun rechts uitgelijnde enkele link. */
.cinbox-card__foot--fix { justify-content: space-between; align-items: center; }
.cinbox-card__fix {
  padding: var(--space-2) var(--space-4); border: 0; border-radius: var(--radius);
  background: var(--accent); color: var(--on-accent);
  font-family: inherit; font-size: 0.85rem; font-weight: 700; cursor: pointer;
}
/* CREDITS-EEN-OP-PAKKET-MAAKT-NOOIT-ZELF-EEN-REKENING — de pakket-op-kaart
   draagt twee knoppen naast de dossierdeur, dus ze krijgen hun eigen rij die op
   een telefoon mag omvallen in plaats van de deur weg te duwen. */
.cinbox-card__acts {
  display: flex; flex-wrap: wrap; justify-content: flex-end;
  gap: var(--space-2);
}
/* De tweede uitweg mag nooit even hard roepen als de eerste: omlijnd, en dan
   draagt de LETTER --accent — niet --on-accent, dat is de kleur ÓP een gevuld
   accentvlak en geeft hier wit op wit. */
.cinbox-card__fix--ghost {
  background: none; border: 1px solid var(--line); color: var(--accent);
}
.cinbox-card__fix:disabled { opacity: 0.5; cursor: default; }
/* REVIEW-EEN-CHALLENGE-INZENDING-BEOORDEEL-JE-MET-EEN-TIK (L212) — de ENE
   primaire knop die het register per soort uitdeelt. Links in de voet, naast
   de dossierdeur rechts, en 44 px hoog: hij staat op de DICHTE kaart en is op
   een telefoon het eerste wat de duim raakt. Geen vak in een vak — hij ligt in
   dezelfde voet die er al was en krijgt geen eigen omhulsel (L183). */
.cinbox-card__primary {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; min-width: 44px; padding: 0 var(--space-4);
  border: 0; border-radius: var(--radius);
  background: var(--accent); color: var(--on-accent);
  font-family: inherit; font-size: 0.85rem; font-weight: 700;
  line-height: 1.2; text-align: center; cursor: pointer;
}
.cinbox-card__primary:disabled { opacity: 0.5; cursor: default; }
/* REVIEW-AANVRAGEN-EN-COACHZAKEN-HEBBEN-EEN-BESTEMMING (L212) — het bevestigblad
   van een credit-verzoek. Drie regels label/waarde en twee knoppen; de regels
   staan LOS in het blad en zitten niet in een eigen kader met eigen padding
   (L183), want het blad is al het vak. */
.cwpur__rows { display: flex; flex-direction: column; gap: var(--space-2); margin: 0 0 var(--space-4); }
.cwpur__row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-3); padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--line);
}
.cwpur__row:last-child { border-bottom: 0; padding-bottom: 0; }
.cwpur__lbl { color: var(--muted); font-size: 0.85rem; }
.cwpur__val { color: var(--ink); font-size: 1rem; }
.cwpur__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
.cpay-credits__actions { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.cpay-credits__btn {
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding: var(--space-3) var(--space-4); border: 1px solid var(--line);
  background: var(--surface); color: var(--ink); border-radius: var(--radius);
  cursor: pointer; font-size: 14px;
}
.cpay-credits__btn:disabled { opacity: 0.5; cursor: default; }
.cpay-credits__btn--ghost { border-style: dashed; color: var(--muted); }
/* An irreversible action shares its wrapping row with Edit, so it may never
   share Edit's fill: quiet outline in the danger colour, pushed to the far end
   of the row so the thumb cannot reach it on the way to Edit. */
.cpay-credits__btn--danger {
  background: none; border-color: var(--danger); color: var(--danger);
  margin-left: auto;
}
.cpay-credits__uses { display: flex; flex-direction: column; gap: 1px; }
.cpay-credits__use {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-1) 0; font-size: 13px; color: var(--ink-2);
}
.cpay-credits__use-src { color: var(--muted); margin-right: auto; }
/* CREDITS-KWARTAAL-GELDIGHEID — purchased bundles head the list with their
   expiry date; a lapsed one dims instead of disappearing. */
.cpay-credits__bundle { border-bottom: 1px solid var(--line); }
.cpay-credits__bundle .cpay-credits__use-src { color: var(--ink-2); }
.cpay-credits__bundle-valid { display: block; font-size: 12px; color: var(--muted); }
.cpay-credits__bundle--gone { opacity: 0.55; }
.cpay-credits__undo {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border: 1px solid var(--line);
  background: var(--surface); color: var(--muted); border-radius: var(--radius); cursor: pointer;
}
.cpay-credits__loading, .cpay-credits__empty { color: var(--muted); font-size: 13px; margin: var(--space-1) 0; }
.ctoday__credits {
  display: inline-flex; align-items: center; padding: 1px var(--space-2);
  border-radius: var(--radius-pill); font-size: 12px; font-weight: 600;
  background: var(--surface); color: var(--muted); border: 1px solid var(--line);
}
.ctoday__credits[role="button"] { cursor: pointer; }
.ctoday__credits--low { background: color-mix(in srgb, var(--warn) 14%, transparent); color: color-mix(in srgb, var(--warn) 78%, var(--ink)); border-color: transparent; }
.ctoday__credits--over { background: color-mix(in srgb, var(--danger) 14%, transparent); color: color-mix(in srgb, var(--danger) 78%, var(--ink)); border-color: transparent; }

/* ── SASSU-CRM-GROUP-LESSONS-CORE ── */
.cgl-card {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); margin-bottom: var(--space-4);
  padding: var(--space-3) var(--space-4);
}
.cgl-card--inactive { opacity: 0.6; }
/* DE-CHALLENGE-BEHEER-JE-VANAF-DE-CHALLENGE — the card you arrived for, marked
   quietly so you recognise it after the page load. No animation, no toast. */
.cgl-card--focus { border-color: var(--accent); }
/* REVIEW-EEN-CHALLENGE-INZENDING-BEOORDEEL-JE-MET-EEN-TIK — de inzending waar
   de Review-kaart over ging is al beoordeeld. Eén rustige regel bovenin het
   blad, geen waarschuwkleur: er is niets misgegaan. */
.cgl-seen { margin: 0 0 var(--space-3); color: var(--muted); font-size: 0.85rem; }
/* F-07: persistent signifier for an event that is not visible to members. */
.cgl-card--hidden { border-left: 4px solid var(--warn); }
.cgl-card__chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px var(--space-2); border-radius: 999px;
  background: color-mix(in srgb, var(--warn) 16%, transparent);
  color: var(--warn); font-size: 0.7rem; font-weight: 700; white-space: nowrap;
}
.cgl-card__top { display: flex; align-items: center; gap: var(--space-2); }
.cgl-card__title { font-weight: 700; color: var(--ink); }
.cgl-card__edit {
  margin-left: auto; display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border: 1px solid var(--line);
  background: var(--surface); color: var(--ink); border-radius: var(--radius); cursor: pointer;
}
.cgl-card__meta { color: var(--muted); font-size: 0.8rem; margin-top: 2px; }
.cgl-card__desc { color: var(--muted); font-size: 0.85rem; margin: var(--space-2) 0 0; line-height: 1.4; }
.cgl-card__actions { display: flex; gap: var(--space-2); margin-top: var(--space-3); }
.cgl-card__btn {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3); border: 1px solid var(--line);
  background: var(--surface); color: var(--ink); border-radius: var(--radius);
  cursor: pointer; font-size: 0.82rem;
}
/* ── Bulk review bar (approve all shown pending entries) ── */
.cgl-bulk {
  display: flex; justify-content: flex-end;
  margin: 0 0 var(--space-3); padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--line);
}
.cgl-bulk__btn { background: var(--accent); color: var(--on-accent); border-color: var(--accent); font-weight: 700; }
.cgl-bulk__btn:disabled { opacity: 0.6; cursor: default; }

/* ── GYM-INSPO-CONTROLELIJST-VOOR-JAYY — owner review of the shared library ──
   Three lists on one page, all built from the cgl-card grammar above. The only
   thing that grammar lacked is a side-by-side compare: an old text next to its
   rewrite, or two candidate names next to each other. Below 640px the columns
   stack — two narrow columns of prose are unreadable on a phone. */
.cinsp-sec { margin-bottom: var(--space-5); }
.cinsp-sec__title { margin: 0 0 2px; font-size: 1rem; }
.cinsp-sec__sub { margin: 0 0 var(--space-3); color: var(--muted); font-size: 0.8rem; }
.cinsp-pair {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-3); margin-top: var(--space-3);
}
.cinsp-pair__col {
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-2);
  border: 1px solid var(--line); border-radius: var(--radius); padding: var(--space-3);
}
.cinsp-pair__lbl { color: var(--muted); font-size: 0.75rem; font-weight: 700; }
.cinsp-pair__txt {
  margin: 0; font-size: 0.85rem; line-height: 1.45;
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.cinsp-ex {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) 0; border-top: 1px solid var(--line);
}
.cinsp-ex__name { flex: 1; font-size: 0.85rem; overflow-wrap: anywhere; }
.cinsp-ex__kill {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--danger); cursor: pointer;
}
.cinsp-ex__kill:disabled { opacity: 0.6; cursor: default; }
@media (max-width: 640px) {
  .cinsp-pair { grid-template-columns: minmax(0, 1fr); }
}

/* ── OWNER-WALLET-PURCHASE-ADMIN-PANEL — platform-owner credit-request console ── */
.cwp { display: flex; flex-direction: column; gap: var(--space-2); }
.cwp-row {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4); border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface);
}
.cwp-row--paid { opacity: 0.7; }
.cwp-row__main { display: flex; flex-direction: column; gap: 2px; margin-right: auto; min-width: 0; }
.cwp-row__name { font-weight: 700; color: var(--ink); }
.cwp-row__meta { color: var(--muted); font-size: 0.8rem; }
.cwp-row__note { color: var(--ink-2); font-size: 0.8rem; }
.cwp-row__pay {
  display: inline-flex; align-items: center; gap: var(--space-1); flex: 0 0 auto;
  padding: var(--space-2) var(--space-3); border: 1px solid var(--accent);
  background: var(--accent); color: var(--on-accent); border-radius: var(--radius);
  cursor: pointer; font-size: 0.82rem; font-weight: 600;
}
.cwp-row__pay:disabled { opacity: 0.5; cursor: default; }
.cwp-paid { margin-top: var(--space-5); display: flex; flex-direction: column; gap: var(--space-2); }
.cwp-paid__title { font-size: 0.9rem; font-weight: 700; color: var(--ink); margin: 0; }

.cgl-sheet__sub { font-weight: 700; color: var(--ink); margin: 0 0 var(--space-2); }
.cgl-sheet__hint { color: var(--muted); font-size: 0.78rem; margin: var(--space-1) 0 0; line-height: 1.4; }
.cgl-occ {
  display: flex; align-items: center; gap: var(--space-3); width: 100%;
  padding: var(--space-3); margin-bottom: var(--space-2);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); cursor: pointer;
}
.cgl-occ__when { font-weight: 600; }
.cgl-occ__count { margin-left: auto; color: var(--muted); font-size: 0.85rem; }
.cgl-att {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-2) var(--space-3); margin-bottom: var(--space-2);
  border: 1px solid var(--line-2); border-radius: var(--radius); background: var(--surface);
}
.cgl-att--cancelled { opacity: 0.5; }
.cgl-att__info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cgl-att__name { font-weight: 600; color: var(--ink); }
.cgl-att__meta { color: var(--muted); font-size: 0.75rem; }
.cgl-att__acts { margin-left: auto; display: flex; gap: var(--space-1); flex: 0 0 auto; }
.cgl-att__btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border: 1px solid var(--line);
  background: var(--surface); color: var(--ink); border-radius: var(--radius); cursor: pointer;
}
.cgl-att__btn--on { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
/* F-09: distinct tones so Attended (ok) and No-show (warn) never read alike. */
.cgl-att__btn--ok { color: var(--ok); }
.cgl-att__btn--ok.cgl-att__btn--on { background: var(--ok); color: var(--on-accent); border-color: var(--ok); }
.cgl-att__btn--warn { color: var(--warn); }
.cgl-att__btn--warn.cgl-att__btn--on { background: transparent; color: var(--warn); border-color: var(--warn); box-shadow: inset 0 0 0 1px var(--warn); }
.cgl-att__btn--more { color: var(--muted); }
.cgl-att__more { position: relative; display: inline-flex; }
.cgl-att__menu {
  position: absolute; right: 0; top: calc(100% + 4px); z-index: 20;
  min-width: 210px; padding: var(--space-1);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
}
.cgl-att__menuitem {
  display: block; width: 100%; box-sizing: border-box; text-align: left;
  border: 0; background: transparent; color: var(--danger); cursor: pointer;
  padding: var(--space-2) var(--space-3); font-size: 0.85rem; font-weight: 600;
  border-radius: calc(var(--radius) - 2px);
}
.cgl-att__menuitem:active { background: color-mix(in srgb, var(--danger) 12%, transparent); }
.cgl-add {
  margin-top: var(--space-3); padding-top: var(--space-3);
  border-top: 1px solid var(--line-2); display: flex; flex-direction: column; gap: var(--space-2);
}
.cgl-add__title { font-weight: 700; color: var(--ink); }
.cgl-add__or { color: var(--muted); font-size: 0.78rem; margin-top: var(--space-2); }
.cgl-add__btn {
  align-self: flex-start; display: inline-flex; align-items: center;
  padding: var(--space-2) var(--space-4); border: 1px solid var(--line);
  background: var(--surface); color: var(--ink); border-radius: var(--radius);
  cursor: pointer; font-size: 0.85rem;
}

/* ── COACH-INBOX-CENTRAL-NOTIFICATIONS — centralized inbox screen ── */
.cinbox__controls {
  display: flex; align-items: center; gap: var(--space-2);
  margin-bottom: var(--space-4); flex-wrap: wrap;
}
.cinbox__filter {
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius-pill);
  background: var(--surface); color: var(--ink);
  font: inherit; font-size: 0.85rem; cursor: pointer;
}
.cinbox__filter--on { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.cinbox__markall {
  margin-left: auto;
  padding: var(--space-2) var(--space-3);
  border: 0; background: transparent; color: var(--accent);
  font: inherit; font-size: 0.85rem; font-weight: 600; cursor: pointer;
}
.cinbox { display: flex; flex-direction: column; gap: var(--space-3); }
.cinbox__loading, .cinbox__empty { color: var(--muted); font-size: 0.9rem; padding: var(--space-4) 0; }
.cinbox-card {
  padding: var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); cursor: pointer;
}
.cinbox-card:hover { border-color: var(--accent); }
.cinbox-card--unread { border-left: 3px solid var(--accent); }
.cinbox-card__top { display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2); }
.cinbox-card__dot { flex: 0 0 auto; width: 8px; height: 8px; border-radius: 999px; background: var(--accent); }
.cinbox-card__chip {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px var(--space-2); border-radius: var(--radius-pill);
  font-size: 0.72rem; font-weight: 700;
  background: var(--line-2); color: var(--ink-2);
}
.cinbox-card__chip svg { flex: 0 0 auto; }
/* F-20: distinct glyph + colour tone per inbox type. Message stays neutral
   (--ink-2); the actionable types carry a tinted pill in their tone. */
.cinbox-card__chip--booking_request { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); }
.cinbox-card__chip--lead            { background: color-mix(in srgb, var(--warn) 18%, transparent); color: var(--warn); }
.cinbox-card__chip--client_signup   { background: color-mix(in srgb, var(--ok) 18%, transparent); color: var(--ok); }
/* CREDITS-WEEGSCHAAL-EN-GELDSIGNALEN — geld draagt dezelfde kaart als de post. */
.cinbox-card__chip--money           { background: color-mix(in srgb, var(--warn) 18%, transparent); color: var(--warn); }
/* SESSIEFEEDBACK-DE-KLANT-GEEFT-EEN-CIJFER-NA-ZIJN-TRAINING — eigen tint, want
   deze kaart is geen vraag die wacht maar iets dat iemand je gaf. */
.cinbox-card__chip--session_feedback { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); }
.cinbox-card__date { margin-left: auto; color: var(--muted); font-size: 0.78rem; }
.cinbox-card__title { font-weight: 600; color: var(--ink); }
.cinbox-card__meta { color: var(--muted); font-size: 0.8rem; margin-top: 2px; }
.cinbox-card__detail { margin-top: var(--space-3); padding-top: var(--space-3); border-top: 1px solid var(--line-2); }
.cinbox-card__body { margin: 0 0 var(--space-2); color: var(--ink-2); font-size: 0.9rem; white-space: pre-wrap; }
.cinbox-card__reply { color: var(--accent); font-size: 0.85rem; font-weight: 600; text-decoration: none; }
/* NOTIF-REPLY-BY-CHAT-EVERYWHERE-REPLY-BY-EMAIL-IS — chat + e-mail naast elkaar. */
.cinbox-card__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4); min-height: 44px; }
button.cinbox-card__reply { appearance: none; -webkit-appearance: none; border: 0; padding: 0; background: none; font-family: inherit; cursor: pointer; }
/* REVIEW-ELKE-MELDING-BRENGT-JE-NAAR-HET-DOSSIER-VAN-DE-KLANT — de deur naar de
   klant staat op de DICHTE kaart, rechtsonder, altijd op dezelfde plek. */
/* gap, want sinds SESSIEFEEDBACK-DE-KLANT-GEEFT-EEN-CIJFER-NA-ZIJN-TRAINING kan
   er een tweede knop ('Gelezen') naast de dossierdeur staan. */
.cinbox-card__foot { display: flex; justify-content: flex-end; gap: var(--space-4); margin-top: var(--space-2); }
.cinbox-card__dossier { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; min-width: 44px; padding: 0 var(--space-2); }
button.cinbox-card__metaname { appearance: none; -webkit-appearance: none; border: 0; padding: 0; background: none; font: inherit; color: inherit; text-decoration: underline; cursor: pointer; }

/* ── SESSIEFEEDBACK-DE-KLANT-GEEFT-EEN-CIJFER-NA-ZIJN-TRAINING ──
   De bol met het cijfer, het citaat eronder, en de maandkop erboven. Drie
   tinten, en het zijn PRECIES de drie bakken waaruit het aanbevelingscijfer is
   opgebouwd (9-10 / 7-8 / 0-6) — geen eigen stoplicht erbovenop. */
.sfbpill {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 999px;
  font-size: 0.85rem; font-weight: 800; font-variant-numeric: tabular-nums;
  background: var(--line-2); color: var(--ink-2);
}
.sfbpill--fan  { background: color-mix(in srgb, var(--accent) 20%, transparent); color: var(--accent); }
.sfbpill--mid  { background: var(--line-2); color: var(--ink-2); }
.sfbpill--crit { background: color-mix(in srgb, var(--danger) 18%, transparent); color: var(--danger); }
/* Het citaat staat OP de kaart, niet in de uitklap: het is de melding zelf.
   pre-wrap, want de klant typt zijn eigen regelovergangen. */
.sfbquote {
  margin: var(--space-2) 0 0;
  color: var(--ink-2); font-size: 0.9rem; font-style: italic;
  white-space: pre-wrap; overflow-wrap: anywhere;
}
/* SESSIEFEEDBACK-HET-CIJFER-STAAT-IN-REVIEW-EN-DOSSIER — de maandkop is sinds
   deze fase een KNOP (tik = de lijst van die maand). Een <button> erft de
   breedte van zijn inhoud en niet van zijn ouder, dus zonder width:100% zou de
   kop ineens een smal blokje linksboven worden; en zonder appearance-reset zet
   de browser er zijn eigen rand en grijze vulling omheen. De spans stapelen via
   flex-column: in een knop zijn ze inline en zouden titel, cijfer en subregel
   op één regel achter elkaar komen. */
.sfbhead {
  appearance: none; -webkit-appearance: none;
  width: 100%;
  display: flex; flex-direction: column; align-items: center;
  margin-bottom: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--line-2); border-radius: var(--radius);
  background: var(--surface-2, var(--surface));
  font-family: inherit; text-align: center; cursor: pointer;
}
.sfbhead__title { font-size: 0.8rem; font-weight: 700; color: var(--muted); }
.sfbhead__score {
  margin-top: 2px;
  font-size: 2rem; font-weight: 800; line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
}
.sfbhead__sub { margin-top: 2px; font-size: 0.8rem; color: var(--muted); }
.sfbhead__note { margin: var(--space-2) 0 0; font-size: 0.75rem; color: var(--muted); }

/* De maandlijst achter de kop. Eén rij per antwoord: bol, naam, datum, citaat,
   en de dossierdeur die de rest van de Werklijst ook gebruikt. */
.sfbmonth { display: flex; flex-direction: column; gap: var(--space-3); }
.sfbmonth__row {
  padding: var(--space-3);
  border: 1px solid var(--line-2); border-radius: var(--radius);
  background: var(--surface);
}
.sfbmonth__top { display: flex; align-items: center; gap: var(--space-2); }
/* De naam duwt de datum naar rechts en knipt zelf af; een lange naam mag de
   datum niet van de rij af schuiven. */
.sfbmonth__name {
  flex: 1 1 auto; min-width: 0;
  font-weight: 700; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sfbmonth__date { flex: 0 0 auto; font-size: 0.8rem; color: var(--muted); }
/* De bol in de dossiertijdlijn staat tussen de metategels en moet dus kleiner
   dan de 28px van de Werklijst zijn, anders rekt hij die regel op. */
.note__meta .sfbpill { width: 22px; height: 22px; font-size: 0.75rem; }

/* ── Settings v1 (COACH-SETTINGS-V1-REPLACE-SPRINT8-STUB) ── */
.csettings { display: flex; flex-direction: column; gap: var(--space-4); }
.csettings-sec { display: flex; flex-direction: column; gap: var(--space-2); }
/* REVIEW-AANVRAGEN-EN-COACHZAKEN-HEBBEN-EEN-BESTEMMING (L212) — de sectie die
   een Review-melding aanwees. Een streep aan de kop, geen doos eromheen: de
   sectie ligt al in de pagina en krijgt dus geen tweede omhulsel of padding
   (L183). De streep hangt aan de kop, zodat de inhoud niet verschuift. */
.csettings-sec--focus > .csettings-sec__title {
  padding-left: var(--space-3);
  box-shadow: inset 3px 0 0 0 var(--accent);
}
.csettings-sec__title { margin: 0; font-size: 0.95rem; font-weight: 700; color: var(--ink); }
.csettings-lbl { font-size: 0.8rem; font-weight: 600; color: var(--muted); }
.csettings-seg { display: inline-flex; gap: 4px; padding: 4px; border: 1px solid var(--line); border-radius: 12px; background: var(--surface); align-self: flex-start; }
.csettings-seg__btn {
  border: none; background: transparent; color: var(--ink-2);
  font: inherit; font-weight: 600; padding: 8px 18px; border-radius: 9px; cursor: pointer;
}
.csettings-seg__btn.is-on {
  background: color-mix(in srgb, var(--accent) 16%, var(--surface));
  color: var(--accent); border-color: var(--accent);
}
/* SAMENWERKING-EIGEN-MOLLIE — Payouts panel. */
.csettings-mollie { display: flex; flex-direction: column; gap: var(--space-2); align-items: flex-start; }
.csettings-mollie__row { display: flex; align-items: center; gap: var(--space-2); color: var(--ink); }
.csettings-mollie__id { font-weight: 600; color: var(--ink); }
.csettings-mollie .ctprof-input { width: 100%; }
/* COACH-BEDRIJFSGEGEVENS — the coach's own company. Borrows the financial
   file's field dressing (.fzdet__*) so it is one design, not two. */
.csettings-biz { display: flex; flex-direction: column; gap: var(--space-2); align-items: stretch; }
.csettings-biz__mb { display: flex; align-items: center; gap: var(--space-2); color: var(--ink); }
.csettings-biz__copy { align-self: flex-start; }
/* CONTRACT-DE-COACH-ZET-ZIJN-EIGEN-VOORWAARDEN-KLAAR — the coach's own terms,
   under his company details. align-items: flex-start so the two buttons keep
   their own width instead of stretching the full panel like a form field: the
   point of the block is the one line of status, not the buttons. */
.csettings-biz__terms {
  display: flex; flex-direction: column; gap: var(--space-2); align-items: flex-start;
  padding-top: var(--space-3); border-top: 1px solid var(--line);
}
.csettings-biz__terms-row {
  display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; color: var(--ink);
}
.csettings-row {
  display: flex; align-items: center; gap: var(--space-3); width: 100%;
  padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px;
  background: var(--surface); color: var(--ink); cursor: pointer; text-align: left; font: inherit;
}
.csettings-row:active { background: var(--line-2); }
.csettings-row__txt { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-width: 0; }
.csettings-row__title { font-weight: 600; color: var(--ink); }
.csettings-row__sub { font-size: 0.8rem; color: var(--muted); }
/* EEN-DOSSIERKOP-DIE-ZEGT-MET-WIE-JE-BEZIG-BENT — de rij van het dossier waar je
   NU staat. Zelfde dressing als --danger: één modifier op de rij, kleur op titel
   en icoon, geen tweede component. Rand mee, want kleur alleen is op nachtmodus
   te zwak om "hier ben je" te dragen. */
.csettings-row--on { border-color: var(--accent); }
.csettings-row--on .csettings-row__title { color: var(--accent); }
.csettings-row--on svg { color: var(--accent); }
/* ZAAL-QR-IN-TWEE-TIKKEN — "hoeveel wachten er op mij", leesbaar zonder de rij
   te openen. Alleen aanwezig bij één of meer; een nul is iets om weg te tikken,
   niet om te lezen. */
.csettings-row__count {
  flex: 0 0 auto; min-width: 22px; padding: 2px 7px;
  border-radius: var(--radius-pill); background: var(--accent); color: var(--on-accent);
  font-size: 0.78rem; font-weight: 700; text-align: center;
}
.cpart-sec .csettings-row__count { display: inline-block; margin-left: var(--space-2); }

/* ── COACH-ONBOARDING-JE-AGENDA-KLAAR-VOOR-VERZETTEN ──
   De stap leent .csettings-row voor zijn rij-dressing en zet er twee dingen
   bij: een vinkje VOOR het icoon en het gemeten getal achter de tekst. Geen
   eigen rij-component — een tweede dressing voor dezelfde rij is precies hoe
   één pagina twee ontwerpen wordt. */
.csrr { display: flex; flex-direction: column; gap: var(--space-2); }
.csrr__rows { display: flex; flex-direction: column; gap: var(--space-2); }
/* Het vinkje is een RING die vol loopt, niet een icoon dat verschijnt: zo staat
   de rij op dezelfde hoogte of hij af is of niet, en kantelt de kaart niet bij
   elke tik. flex: 0 0 auto, want .btn-achtergrond erft width:100% in dit huis. */
.csrr__mark {
  flex: 0 0 auto; width: 20px; height: 20px; border-radius: 50%;
  border: 2px solid var(--line); display: inline-flex; align-items: center; justify-content: center;
}
.csrr__mark--on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.csrr__mark--on svg { color: var(--on-accent); }
/* Het getal. Grijs bij nul en accent zodra er iets staat — kleur is hier de
   tweede lezing van hetzelfde feit, niet een eigen boodschap. */
/* De twee svg's van de rij (onderwerp-icoon en pijl) mogen NIET meekrimpen. Een
   rij met een tekst van drie regels perst ze anders tot halve grootte, en dan
   staat één rij met een ander icoonformaat naast twee die het wel hebben —
   gemeten op 390px, niet aangenomen. */
.csrr__row > svg { flex: 0 0 auto; }
.csrr__num { flex: 0 0 auto; font-size: 0.85rem; font-weight: 700; color: var(--muted); }
.csrr__num--on { color: var(--accent); }
.csrr__row--done { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }
.csrr__why { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 4px; }
.csrr__why-item { font-size: 0.8rem; line-height: 1.5; color: var(--muted); }

/* ───────── DOSSIER-KLANT-PANEEL-RUST — the calm list card ─────────
   A slab title over ONE bordered card. Rows sit flush, separated by a single
   hairline rather than by gaps: the coach reads one list, not six stacked cards.
   Same dressing as .csettings-row (icon · label · chevron) plus a right-aligned
   meta, so a row can answer "how many" without being opened. */
.dsec { margin-bottom: var(--space-4); }
.dsec__title {
  margin: 0 0 var(--space-2); padding: 0 2px;
  font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--muted);
}
.dsec__list {
  display: flex; flex-direction: column;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); overflow: hidden;
}
.dsec__row {
  display: flex; align-items: center; gap: var(--space-3); width: 100%;
  padding: 14px; border: 0; border-top: 1px solid var(--line);
  background: none; color: var(--ink); cursor: pointer; text-align: left; font: inherit;
}
.dsec__row:first-child { border-top: 0; }
.dsec__row:active { background: var(--line-2); }
.dsec__row > svg:first-child { flex: 0 0 auto; color: var(--ink-2); }
/* DOSSIER-WAT-JE-MOET-WETEN-STAAT-BOVENAAN — a row's meta became a SENTENCE
   ("this week: trained 2 · logged 0"), and the old pair could not carry one: the
   label was the only shrinkable child (min-width:0, no overflow rule), so on a
   390px phone its box shrank to 40px while "Adherence" still painted 82px wide —
   straight over the meta. Now the label may not shrink past its longest word and
   the meta yields instead, wrapping to a second line rather than being cut. A
   short meta ('credits · payments') never reaches that point, so every row that
   fit before is laid out exactly as it was. */
.dsec__label { flex: 1 1 auto; min-width: min-content; font-weight: 600; }
.dsec__meta { flex: 0 1 auto; min-width: 0; font-size: 0.8rem; color: var(--muted); text-align: right; }
.dsec__row > svg:last-child { flex: 0 0 auto; color: var(--muted); }
/* The parked sections live here between openings — never visible in place. */
.dsec__holder { display: none; }
/* DOSSIER-VLOEIENDE-RUIMTE — verticaal het sectieritme, horizontaal NUL: de
   padding van dit vel staat al op .csheet__panel (--card-pad), en een tweede
   getal hier zou precies de optelsom zijn die deze fase afschaft. */
.dsec__sheetbody { display: flex; flex-direction: column; padding: var(--section-gap) 0; }
/* Sections were written as standalone cards; inside the sheet the SHEET is the
   card, so they drop their own frame instead of nesting a second border. */
.dsec__sheetbody > .dmanage,
.dsec__sheetbody > .gym__progs { border: 0; padding: 0; background: none; margin: 0; }

/* ───────── Begeleidingsvorm (REVIEW-DE-LIJST-WEET-WIE-JE-OP-LOCATIE-ZIET) ─────────
   Eén regel bovenaan het Klant-paneel: label, twee keuzeknoppen, en daarachter
   OF de gedempte hint "automatisch" OF de knop terug naar automatisch — nooit
   allebei, want ze beantwoorden dezelfde vraag. Wrap op 390px, geen eigen kaart:
   dit is een instelling, geen bericht. */
.cmode {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2);
  margin-bottom: var(--space-4);
}
.cmode__label { font-size: 0.8rem; font-weight: 600; color: var(--muted); }
.cmode__opts {
  display: flex; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); overflow: hidden;
}
.cmode__btn {
  padding: 7px 12px; border: 0; background: none; font: inherit; font-size: 0.85rem;
  color: var(--ink-2); cursor: pointer;
}
.cmode__btn + .cmode__btn { border-left: 1px solid var(--line); }
.cmode__btn--on { background: var(--accent); color: var(--on-accent); font-weight: 600; }
.cmode__hint { font-size: 0.75rem; color: var(--muted); }
.cmode__hint:empty { display: none; }
.cmode__reset {
  padding: 0; border: 0; background: none; font: inherit; font-size: 0.75rem;
  color: var(--muted); text-decoration: underline; cursor: pointer;
}

/* ───────── Wie zie je in persoon? (JE-ZEGT-EEN-KEER-WIE-JE-IN-PERSOON-ZIET) ─────────
   Het hele bestand in één lijst: naam links, dezelfde tweestandsschakelaar als
   in het dossier rechts. Geen kleurcodering en geen teller per rij — dit is een
   vraag die je één keer beantwoordt, geen score. De opslagbalk plakt onderaan
   zodat veertig rijen niet eerst teruggescrold hoeven te worden. */
.cbegel__intro { margin: 0 0 var(--space-4); font-size: 13px; color: var(--muted); }
.cbegel__list { display: flex; flex-direction: column; }
.cbegel__row {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2);
  padding: 10px 0; border-bottom: 1px solid var(--line);
}
.cbegel__row:last-child { border-bottom: 0; }
.cbegel__name { flex: 1 1 140px; min-width: 0; display: flex; flex-direction: column; }
.cbegel__who {
  font-size: 14px; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cbegel__auto { font-size: 0.75rem; color: var(--muted); }
.cbegel__auto[hidden] { display: none; }
.cbegel__row .cmode__reset[hidden] { display: none; }
.cbegel__bar {
  position: sticky; bottom: 0; z-index: 1;
  display: flex; justify-content: flex-end;
  padding: var(--space-3) 0;
  background: var(--bg);
  border-top: 1px solid var(--line);
}
.cbegel__bar[hidden] { display: none; }

/* De open vraag op Review: gedempt, aanklikbaar, nooit rood en nooit een balk. */
.ctoday__qmodehint { margin: 2px 0 0; }
.ctoday__qmodehint:empty { display: none; }
.ctoday__qmodelink {
  padding: 0; border: 0; background: none; font: inherit; font-size: 12px;
  color: var(--muted); text-align: left; text-decoration: underline; cursor: pointer;
}

/* ───────── Noordster / SMART goals (COACH-DOSSIER-NORTHSTAR-SMART-GOALS) ─────────
   The most important info per panel: a calm card pinned to the top, marked by a
   left accent bar + star. Not screaming — signals primacy, not urgency. */
.northstar {
  display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-4); margin-bottom: var(--space-4);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
  background: var(--surface);
}
.northstar__head { display: flex; align-items: center; gap: var(--space-2); }
.northstar__head svg { flex: 0 0 auto; color: var(--accent); }
.northstar__body { display: flex; flex-direction: column; gap: var(--space-3); }
.northstar__loading, .northstar__empty { margin: 0; color: var(--muted); font-size: 14px; }
/* DIARY-METRIEK-EIGEN-CUSTOM — one-line note under the metric picker grid. */
.northstar__pickhint { margin: 8px 0 0; color: var(--muted); font-size: 13px; line-height: 1.4; }

/* Gym panel — editable goal */
.northstar__goal { display: flex; flex-direction: column; gap: var(--space-2); }
.northstar__goaltext {
  width: 100%; text-align: left; margin: 0;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--bg); color: var(--ink);
  font-size: 15px; font-weight: 600; line-height: 1.4; cursor: pointer;
}
.northstar__goaltext:hover { border-color: var(--accent); }
.northstar__goaltext:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.northstar__add {
  display: inline-flex; align-items: center; gap: 6px;
  padding: var(--space-2) var(--space-3);
  border: 1px dashed var(--line); border-radius: var(--radius);
  background: transparent; color: var(--muted);
  font-size: 14px; cursor: pointer;
}
.northstar__add svg { flex: 0 0 auto; }
.northstar__add:hover { border-color: var(--accent); color: var(--ink-2); }
.northstar__input {
  width: 100%; box-sizing: border-box; resize: vertical;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--accent); border-radius: var(--radius);
  background: var(--surface); color: var(--ink);
  font: inherit; font-size: 15px; line-height: 1.4;
}
.northstar__acts { display: flex; gap: var(--space-2); }

/* COACH-GOAL-STRUCTURE-V2 — the one structured goal editor. Layout only; every
   control reuses the tokens above. */
.northstar__goal--editor { display: flex; flex-direction: column; gap: var(--space-3); }
/* COACH-GOAL-EDITOR-COLLAPSE-AFTER-SAVE — two mutually exclusive states in one
   block; the [hidden] rules must out-specify the display:flex above them. */
.northstar__goalform { display: flex; flex-direction: column; gap: var(--space-3); }
.northstar__goalsum { display: flex; flex-direction: column; gap: var(--space-2); }
.northstar__goalform[hidden], .northstar__goalsum[hidden] { display: none; }
.northstar__field { display: flex; flex-direction: column; gap: 6px; }
.northstar__flbl { color: var(--muted); font-size: 12px; font-weight: 600; letter-spacing: .02em; }
.northstar__hint { margin: 0; color: var(--muted); font-size: 12px; }
.northstar__err { margin: 0; color: var(--danger, #c0392b); font-size: 13px; }
.northstar__strip,
.northstar__ifrow,
.northstar__procrow { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.northstar__procs,
.northstar__ifs { display: flex; flex-direction: column; gap: var(--space-2); }
.northstar__sel,
.northstar__num,
.northstar__date {
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink);
  font: inherit; font-size: 14px;
}
/* Inside a strip the shared full-width input token becomes a flex cell, so the
   if/then pair sits on one line instead of stacking. */
.northstar__strip .northstar__input,
.northstar__ifrow .northstar__input { flex: 1 1 160px; width: auto; min-width: 0; }
.northstar__sel { flex: 1 1 140px; min-width: 0; }
.northstar__num { flex: 0 1 100px; min-width: 0; }
.northstar__date { flex: 0 1 150px; min-width: 0; }
.northstar__delproc,
.northstar__delif { flex: 0 0 auto; }
.northstar__addproc,
.northstar__addif { align-self: flex-start; }
.northstar__help { border: 1px solid var(--line); border-radius: var(--radius); padding: var(--space-2) var(--space-3); }
.northstar__helpsum { color: var(--muted); font-size: 13px; cursor: pointer; }
.northstar__helpq { margin: var(--space-2) 0 0; color: var(--ink-2); font-size: 13px; line-height: 1.4; }

/* Gym panel — metric multi-select */
.northstar__metrics { display: flex; flex-direction: column; gap: var(--space-2); }
.northstar__chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.northstar__chip {
  display: inline-flex; align-items: baseline; gap: 5px;
  padding: 5px var(--space-3); border-radius: var(--radius-pill);
  border: 1px solid var(--line); background: var(--bg);
  color: var(--ink-2); font-size: 13px; cursor: pointer;
}
.northstar__chip:hover { border-color: var(--accent); }
.northstar__chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.northstar__chip.is-on {
  background: var(--accent); border-color: var(--accent); color: var(--on-accent);
}
/* METRICS-DERIVED-HIP-WAIST-RATIO — a computed number, not a loggable metric:
   dashed edge + default cursor so it reads as read-out, not as a control. */
.northstar__chip--derived {
  background: transparent; color: var(--ink-2);
  border-style: dashed; border-color: var(--line);
  cursor: default;
}
.northstar__chip--derived:hover { border-color: var(--line); }
.northstar__chip-label { font-weight: 600; }
.northstar__chip-val { font-size: 12px; opacity: 0.9; }

/* COACH-NORTHSTAR-METRICS-COLLAPSED-PLUS-ENTRY — collapsed-by-default header,
   the small pencil chip that opens the picker, and the one-line entry strip. */
.northstar__mhead {
  display: flex; align-items: baseline; gap: var(--space-2);
  font-size: 13px; font-weight: 600; color: var(--muted);
}
.northstar__mcount { font-weight: 500; opacity: 0.85; }
.northstar__picker { display: flex; flex-direction: column; gap: var(--space-2); }
.northstar__chip--edit {
  padding: 5px 9px; color: var(--muted); background: transparent;
  border-style: dashed;
}
.northstar__chip--edit svg { display: block; }
.northstar__chip.is-open { outline: 2px solid var(--accent); outline-offset: 2px; }
.northstar__entry {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--accent); border-radius: var(--radius);
  background: var(--surface);
}
.northstar__entry-lbl { font-size: 13px; font-weight: 600; color: var(--ink-2); }
.northstar__entry-inp {
  width: 92px; box-sizing: border-box;
  padding: 5px var(--space-2);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--bg); color: var(--ink);
  font: inherit; font-size: 15px;
}
.northstar__entry-unit { font-size: 12px; color: var(--muted); }
.northstar__entry-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 34px; padding: 5px 8px;
}
.northstar__entry-err { font-size: 12px; color: var(--danger); }

/* Client panel — read-only */
.northstar__quote {
  margin: 0; padding: var(--space-3);
  border-radius: var(--radius); background: var(--bg);
  display: flex; flex-direction: column; gap: 4px;
}
.northstar__quote-cap {
  font-size: 11px; font-weight: 700; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--muted);
}
.northstar__quote-text { margin: 0; font-size: 15px; font-style: italic; color: var(--ink); line-height: 1.45; }
.northstar__care { display: flex; flex-direction: column; gap: var(--space-2); }
.northstar__carerow { display: flex; flex-direction: column; gap: 2px; }
.northstar__carelabel { font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); }
.northstar__carebody { font-size: 14px; color: var(--ink-2); line-height: 1.4; }
.northstar__goals { display: flex; flex-direction: column; gap: var(--space-2); }
.northstar__goalrow { display: flex; flex-direction: column; gap: 2px; }
.northstar__goallabel { font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--accent); }
.northstar__goalbody { font-size: 14px; font-weight: 600; color: var(--ink); line-height: 1.4; }
.northstar__trend { display: inline-flex; align-items: center; gap: 6px; color: var(--ink-2); font-size: 13px; }
.northstar__trend svg { flex: 0 0 auto; }

/* Nutrition panel — calorie/macro targets + TDEE (one-glance) */
/* COACH-NIETS-LOOPT-NOG-BUITEN-ZIJN-VAK (L183 #1-#3) — deze vier tegels stonden
   op `repeat(4, 1fr)` met een omschakeling naar twee kolommen in een
   @media (max-width: 400px). Die media-regel meet de VIEWPORT, en de Noordster
   staat in een dossierPANEEL dat op een telefoon ~290px breed is, op een tablet
   ~350px en op een laptop ~350px (drie panelen naast elkaar). Boven 400px
   viewport kregen vier tegels dus één rij in een vak dat er twee aankan: de
   vierde tegel ("98 g VET") stak 22px uit op 402px en tot 66px op 768/1280, en
   de pagina kreeg 17px horizontale scroll — exact de screenshot van Jayy.
   Het raster kijkt nu naar zijn EIGEN breedte: auto-fit legt zoveel kolommen van
   minimaal 136px als er passen, en `min(100%, 136px)` zorgt dat die ondergrens
   nooit breder is dan het vak zelf (anders loopt hij in een vak van 120px weer
   uit). Een kale `1fr` is minmax(AUTO, 1fr), dus de hoofdletterlabels dwongen de
   kolom ook nog breder dan haar deel; de expliciete ondergrens haalt die vloer
   weg. Geen viewport-breakpoint meer voor een component in een wisselend vak. */
/* DOSSIER-NOORDSTER-ALS-OVERZICHT (L183 4/6) — auto-fit kon hier nooit meer
   uitsteken, maar hij kon de vier doelen wél in 1, 2, 3 óf 4 kolommen leggen,
   afhankelijk van een paneelbreedte die per tabblad en per schermmaat verschilt.
   Vier getallen die van vorm veranderen terwijl je tussen klanten bladert zijn
   vier getallen die je elke keer opnieuw moet zoeken. Het zijn er ALTIJD vier,
   dus het raster is altijd 2×2 — dezelfde vorm op 375, 402, 768 en 1280, precies
   de mock (mock_dossier_390_na.png). `minmax(0, 1fr)` en niet een kale `1fr`:
   §3.4 van de audit, een kale 1fr is minmax(AUTO, 1fr) en laat een lang label
   de kolom breder duwen dan haar deel. */
.northstar__nutstats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2);
}
.northstar__stat {
  display: flex; flex-direction: column; gap: 2px;
  min-width: 0;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius); background: var(--bg);
}
.northstar__stat-num {
  font-size: 22px; font-weight: 700; color: var(--ink); line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.northstar__stat-unit { font-size: 12px; font-weight: 600; color: var(--muted); }
/* DOSSIER-NOORDSTER-ALS-OVERZICHT — zinshoofdletters, geen kapitalen. §4 van de
   audit: alleen SECTIEKOPPEN staan in klein kapitaal. "CALORIEDOEL" met
   letter-spacing is ~22% breder dan "Caloriedoel" en was mede de reden dat de
   tegel breder werd dan zijn kolom (bevinding #1). */
.northstar__stat-lbl {
  font-size: 12px; font-weight: 600; color: var(--muted);
  overflow-wrap: anywhere;
}
.northstar__tdee { display: flex; flex-direction: column; gap: var(--space-2); }
/* DOSSIER-NOORDSTER-ALS-OVERZICHT (bevinding #5) — eigenschapsregels, het
   Linear-patroon uit §4: label links, waarde rechts, een haarlijn tussen twee
   regels. TDEE was een VIJFDE tegel met een eigen rand én een eigen 3px
   accentstreep, binnen een Noordster die er al een had — twee accentstrepen in
   elkaar. Het is context bij de vier doelen, geen vijfde doel. */
.northstar__props { display: flex; flex-direction: column; }
.northstar__prop {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-3); padding: 7px 0;
}
.northstar__prop + .northstar__prop { border-top: 1px solid var(--line); }
.northstar__prop-lbl { min-width: 0; color: var(--muted); font-size: 13px; }
.northstar__prop-val {
  flex: 0 0 auto; color: var(--ink); font-size: 15px; font-weight: 700;
  font-variant-numeric: tabular-nums; text-align: right;
}
.northstar__tdee-missing { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.4; }
/* DOSSIER-NOORDSTER-ALS-OVERZICHT — de herkomstregel van de TDEE had GEEN eigen
   regel en erfde dus de volle tekstmaat van de pagina: hij stond in 15px zwarte
   letters onder een TDEE-regel van 13px, en was daarmee het luidste ding in het
   paneel terwijl hij een voetnoot is. */
.northstar__tdee-src { margin: 0; color: var(--muted); font-size: 12px; line-height: 1.4; }
/* DOSSIER-NOORDSTER-ALS-OVERZICHT — de ENE uitspraak, bovenaan het paneel.
   Geen doos en geen vulling: dat zou precies de kaart-in-kaart terugzetten die
   de vorige fase weghaalde. Hij is de kop van het paneel, dus hij is groter dan
   de rest en verder niets. */
.northstar__lead {
  margin: 0; color: var(--ink);
  font-size: 17px; font-weight: 700; line-height: 1.3;
  font-variant-numeric: tabular-nums; text-wrap: balance;
}

/* COACH-DOSSIER-NUTRITION-TARGETS-INLINE-EDIT — coach-editable targets */
.northstar__nutwrap { display: flex; flex-direction: column; gap: var(--space-2); }
/* DOSSIER-NOORDSTER-ALS-OVERZICHT — het potlood hangt rechts in de Noordster-
   kop. `display: flex` verslaat de UA-regel voor `[hidden]` stil, dus de
   verborgen stand (tijdens bewerken, en bij een leeg paneel) staat hier. */
.northstar__nuttools { display: flex; justify-content: flex-end; }
.northstar__nuttools[hidden] { display: none; }
.northstar__nutedit {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2);
}
.northstar__nutfield { display: flex; flex-direction: column; gap: 3px; }
.northstar__nutfield-lbl {
  font-size: 11px; font-weight: 600; letter-spacing: 0.03em;
  text-transform: uppercase; color: var(--muted);
}
.northstar__numinput {
  width: 100%; box-sizing: border-box;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--accent); border-radius: var(--radius);
  background: var(--surface); color: var(--ink);
  font: inherit; font-size: 16px; font-weight: 700;
}
.northstar__nuterr { margin: 0; color: var(--danger); font-size: 13px; line-height: 1.4; }
/* COACH-KCAL-TAP-FROM-MACROS-TO-ADOPT — the derived kcal number is the control.
   It was dimmed + dashed, which reads as inert/placeholder; it is a real button,
   so it gets a solid border, accent ink and a pointer. Sized to line up with
   .northstar__numinput beside it. The cell keeps its place when there is no
   honest total: the button falls back to a dimmed em dash and is disabled. */
.northstar__derived { display: flex; flex-direction: column; gap: 3px; }
.northstar__derived[hidden] { display: none; }
.northstar__derived-num {
  width: 100%; box-sizing: border-box; text-align: left;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--accent); border-radius: var(--radius);
  background: var(--surface); color: var(--accent);
  font: inherit; font-size: 16px; font-weight: 700;
  cursor: pointer;
}
.northstar__derived-num:hover { background: var(--bg); }
.northstar__derived-num:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
.northstar__derived-num:disabled {
  border-color: var(--line); color: var(--muted);
  background: var(--surface); cursor: default;
}

/* De oude `@media (max-width: 400px) { .northstar__nutstats }` staat hier NIET
   meer: hij is vervangen door de auto-fit-regel hierboven, die dezelfde twee
   kolommen geeft in een smal vak en vier in een breed vak — zonder de viewport
   te raadplegen. Zie de notitie bij .northstar__nutstats. */

/* COACH-DOSSIER-CREDITS-SUBCARD-AND-AUTOBUNDLE — quiet session-credits sub-block,
   same restrained idiom as .northstar (accent left-rule, muted labels). */
.sesscred {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-4); margin-bottom: var(--space-4);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
  background: var(--surface);
}
.sesscred__head { display: flex; align-items: center; gap: var(--space-2); }
.sesscred__head svg { flex: 0 0 auto; color: var(--accent); }
.sesscred__title {
  font-size: 12px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--ink-2);
}
.sesscred__body { display: flex; flex-direction: column; gap: var(--space-2); }
.sesscred__muted { color: var(--muted); font-size: 14px; }
.sesscred__empty { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.sesscred__pkg {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3);
  padding-bottom: var(--space-2); border-bottom: 1px solid var(--line);
}
.sesscred__pkgname { font-size: 15px; font-weight: 700; color: var(--ink); }
.sesscred__pkgsize { flex: 0 0 auto; font-size: 13px; font-weight: 700; color: var(--muted); }
.sesscred__row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); }
.sesscred__label { font-size: 13px; color: var(--muted); }
.sesscred__value { font-size: 14px; font-weight: 600; color: var(--ink); }
.sesscred__split { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.sesscred__chip {
  font-size: 12px; color: var(--ink-2);
  padding: 2px var(--space-2); border: 1px solid var(--line); border-radius: 999px;
  background: var(--bg);
}
/* ── CREDITS-WEEGSCHAAL-EN-GELDSIGNALEN — de weegschaal in het dossier ──────
   Vijf smalle kolommen, geen tabel-element: de rij moet op een telefoon kunnen
   krimpen zonder horizontaal te schuiven. Alleen een rij die NIET nul is krijgt
   kleur; een kloppende maand mag grijs en stil blijven. */
.sccrec { display: flex; flex-direction: column; gap: 2px; margin-top: var(--space-2); }
.sccrec__cap {
  font-size: 12px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--ink-2); margin-bottom: var(--space-1);
}
.sccrec__row {
  display: grid; grid-template-columns: minmax(0, 1.4fr) repeat(4, minmax(0, 1fr));
  align-items: center; gap: var(--space-1);
  padding: 4px 6px; border-radius: 8px;
}
.sccrec__row--head .sccrec__cell {
  font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase;
  letter-spacing: 0.04em;
}
.sccrec__row--off { background: color-mix(in oklab, var(--warn) 16%, transparent); }
.sccrec__cell { font-size: 13px; color: var(--ink); text-align: right; }
.sccrec__cell--per { text-align: left; color: var(--ink-2); }
.sccrec__why {
  border: none; background: transparent; cursor: pointer; padding: 0;
  font-size: 13px; font-weight: 700; color: var(--warn); text-align: right;
}
.sccrec__why:hover { text-decoration: underline; }
.sccrec__why:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sccrec__days { padding: 4px 6px 6px; display: flex; flex-direction: column; gap: 2px; }
.sccrec__day { font-size: 12px; color: var(--ink-2); }

/* ── FINDOSSIER-CREDITS-SALDO-IS-HET-ANTWOORD — het saldo als het antwoord ───
   Eén groot getal bovenaan, want dat is waar de coach voor komt; de weegschaal
   en het abonnement staan eronder als onderbouwing. De toon volgt dezelfde
   drempels als de agenda-chip (≤ 2 = laag, ≤ 0 = op).                        */
.fzcred__intro { display: flex; align-items: flex-start; gap: var(--space-1); }
.fzcred__introtxt { font-size: 13px; color: var(--ink-2); line-height: 1.4; }
.fzcred__help { background: none; border: 0; color: var(--muted); padding: 2px; display: flex; cursor: pointer; }
.fzcred__help:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.fzcred__rules {
  display: flex; flex-direction: column; gap: 3px;
  margin-top: var(--space-1); padding: var(--space-2);
  border-radius: var(--radius);
  background: color-mix(in oklab, var(--ink) 6%, transparent);
}
.fzcred__rule { font-size: 12px; color: var(--ink-2); }
.fzcred__tile {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  margin: var(--space-3) 0; padding: var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface);
}
.fzcred__num { font-size: 44px; font-weight: 800; line-height: 1; color: var(--ink); }
.fzcred__cap {
  font-size: 12px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
}
.fzcred__tile--low { border-color: var(--warn); }
.fzcred__tile--low .fzcred__num { color: var(--warn); }
.fzcred__tile--over { border-color: var(--danger); }
.fzcred__tile--over .fzcred__num { color: var(--danger); }
.fzcred__foot { display: flex; justify-content: flex-end; margin-top: var(--space-3); }

/* FINDOSSIER-DETAILS-EN-NOTITIES — Details- en Notities-tab van het dossier. */
.fzdet__sect { margin-bottom: var(--space-3); }
/* Een leesregel blijft naast zijn label staan — dat leest als een gegevenstabel.
   Een INVULregel zet zijn label erboven: op een sheet van ~400px houdt een veld
   naast een label te weinig over om een factuuradres in te lezen. */
.fzdet__row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 2px var(--space-2);
  padding: 4px 0;
}
.fzdet__row--ro { flex-wrap: nowrap; }
.fzdet__lbl { flex: 0 0 100%; font-size: 13px; color: var(--ink-2); }
.fzdet__row--ro .fzdet__lbl { flex: 0 0 40%; }
.fzdet__val { flex: 1 1 auto; font-size: 13px; color: var(--ink); min-width: 0; overflow-wrap: anywhere; }
.fzdet__inp { flex: 1 1 auto; min-width: 0; }
/* De WhatsApp-knop is een secundaire actie naast het nummer, nooit een
   accentkleur: hij opent een gesprek, hij bevestigt niets. */
.fzdet__wa { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; text-decoration: none; }
.fzdet__wa[hidden] { display: none; }
.fzdet__radios { display: flex; gap: var(--space-3); padding: 4px 0 var(--space-2); }
.fzdet__radio { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--ink); cursor: pointer; }
.fzdet__biz[hidden] { display: none; }
/* KLANTGEGEVENS — de verwijzing onder het alleen-lezen e-mailadres. Rustig, en
   met dezelfde inspringing als de waarden erboven. */
.fzdet__note { margin: 2px 0 0; font-size: 12px; line-height: 1.4; color: var(--ink-2); }
/* Een selectievak en een datumvak dragen dezelfde rij-opmaak als een tekstvak. */
select.fzdet__inp, input.fzdet__inp[type="date"] { flex: 1 1 auto; min-width: 0; }
.fzdet__foot { display: flex; justify-content: flex-end; margin-top: var(--space-3); }

/* COACH-KLANT-KAN-OOK-GRATIS-APP-KLANT-ZIJN — de Plus-schakelaar in de
   Account-sectie. Hij leent de .ctprof-toggle-schakelaar en .ctprof-opt__text
   van het coachprofiel, dus hier staat alleen wat de PLEK regelt: de rij en het
   datumveld dat eronder in- en uitklapt.

   `[hidden]` is op een flex-regel alleen een UA-regel op display en wordt door
   elke eigen display-regel stil verslagen — vandaar !important op de verborgen
   stand, net als bij .pkco__pane. */
.fzplus { padding: var(--space-2) 0 0; }
.fzplus__row { display: flex; align-items: flex-start; gap: var(--space-2); }
.fzplus__state { display: block; }
.fzplus__until { padding-top: var(--space-2); }
.fzplus__until[hidden] { display: none !important; }

.fznotes__intro { font-size: 13px; color: var(--ink-2); line-height: 1.4; margin-bottom: var(--space-2); }
.fznotes__list { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-2); }

.sesscred__foot { display: flex; justify-content: flex-end; }
.sesscred__link {
  padding: 2px var(--space-2);
  border: none; background: transparent; cursor: pointer;
  font-size: 13px; font-weight: 600; color: var(--accent);
}
.sesscred__link:hover { text-decoration: underline; }
.sesscred__link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ── GELD-KLANT-BETALINGEN-IN-DOSSIER ────────────────────────────────────────
   Dit was een kaart met een kop, een samenvattende regel en een knop naar de
   geldlade. GELD-DE-LADE-WORDT-DE-PAGINA haalde die kaart weg (de lade IS de
   pagina). Wat blijft is het DICHTE blok van een geleende klant: één zin die
   zegt wiens rekening dit is. Kop, knop en voet zijn daarmee dood en weg.    */
.cpayd {
  display: flex; flex-direction: column; gap: var(--space-2);
  margin-top: var(--space-3); padding: var(--space-3);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
  background: var(--surface);
}
.cpayd__line { font-size: 14px; color: var(--ink); }

.cpaysheet { display: flex; flex-direction: column; gap: var(--space-2); }
.cpaysheet__empty { color: var(--muted); font-size: 14px; text-align: center; }
.cpaysheet__row {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-2) 0; border-bottom: 1px solid var(--line);
}
.cpaysheet__row:last-child { border-bottom: none; }
.cpaysheet__main { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); }
.cpaysheet__left { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cpaysheet__label {
  font-size: 16px; font-weight: 600; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cpaysheet__meta { display: flex; align-items: center; gap: var(--space-2); }
.cpaysheet__date { font-size: 13px; color: var(--muted); }
.cpaysheet__src { font-size: 12px; color: var(--muted); font-style: italic; }
.cpaysheet__right { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; flex: 0 0 auto; }
.cpaysheet__amount { font-size: 16px; font-weight: 700; color: var(--ink); }
.cpaysheet__acts { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.cpaysheet__act { flex: 1 1 auto; }
.cpaysheet__method { flex: 1 1 140px; }
/* GELD-EEN-FOUTE-REKENING-KUN-JE-KWIJTSCHELDEN — het datumveld naast de methode.
   Een date-input draagt in WebKit zijn eigen intrinsieke breedte en zou zonder
   deze basis de hele rij op één regel duwen; met een eigen flex-basis wikkelt de
   rij netjes op 390 breed. */
.cpaysheet__date { flex: 1 1 140px; min-width: 0; }

/* ── FINDOSSIER-BETALINGEN-EN-BOEKINGEN ──────────────────────────────────── */
/* FINDOSSIER-DETAILS-EN-NOTITIES gaf deze schakelaar VIJF tabs en koos toen
   wikkelen boven schuiven, omdat een tab die uit beeld staat een deur is die de
   coach niet vindt.
   GELD-PAKKETTEN-EN-DOSSIER-NETJES draait dat om (audit 2026-09-10): die tweede
   regel maakte de kop van het vel twee rijen hoog en duwde de betalingen onder
   de schermrand — het echte antwoord van dit vel verdween dus om een deur te
   laten zien. Nu EEN regel die schuift: de eerste pil is de stand waar het vel
   op opent, de rest staat er zichtbaar half naast, en de rangorde van links naar
   rechts blijft intact. `flex: 0 0 auto` op de pil, anders perst flex ze alsnog
   samen in plaats van te schuiven; de scrollbar is verborgen omdat hij op de
   telefoon niet bestaat en op de Mac de rij een paar pixels hoger maakt.
   GELD-DE-LADE-WORDT-DE-PAGINA — dezelfde rij, nu op een PAGINA in plaats van
   in een lade: geen zijpadding meer van het paneel, en hij plakt onder de
   zoekbalk zoals de chiprij van de Geld-tab. De achtergrond is dus die van de
   pagina (--bg) en niet die van een paneel, anders schijnen de betaalrijen er
   tijdens het scrollen doorheen. De plakhoogte is dezelfde berekening als
   .cfilter: safe-area + de 40px-balk + tweemaal padding + de rand.          */
.cpaysheet__seg {
  display: flex; flex-wrap: nowrap; gap: var(--space-2);
  position: sticky; top: calc(env(safe-area-inset-top, 0px) + 40px + var(--space-2) * 2 + 1px);
  z-index: 5;
  padding: var(--space-2) 0; margin-bottom: var(--space-2);
  background: var(--bg);
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  scrollbar-width: none; -ms-overflow-style: none;
}
.cpaysheet__seg::-webkit-scrollbar { display: none; }
.cpaysheet__segbtn {
  flex: 0 0 auto; min-width: 0; padding: var(--space-2); border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface); cursor: pointer;
  font-size: 14px; font-weight: 600; color: var(--ink-2);
}
.cpaysheet__segbtn.is-on {
  background: color-mix(in srgb, var(--accent) 16%, var(--surface));
  color: var(--accent); border-color: var(--accent);
}
.cpaysheet__segbtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* GELD-PAKKETTEN-EN-DOSSIER-NETJES — de weg terug naar het sportdossier stond
   als spookknop in de KOP, naast het kruisje, en vocht daar om dezelfde hoek.
   Het is een uitgang, niet een actie op dit vel: een tekstknop onderaan.
   GELD-DE-LADE-WORDT-DE-PAGINA — hij staat nu onderaan de PAGINA, buiten de
   tabs, zodat hij op elke tab dezelfde uitgang blijft. */
.cpaysheet__exit {
  display: block; width: 100%; margin-top: var(--space-4);
  padding: var(--space-3); border: none;
  border-top: 1px solid var(--line); background: none; cursor: pointer;
  font-size: 14px; font-weight: 600; color: var(--accent); text-align: center;
}
.cpaysheet__exit:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.cpaysheet__secttl {
  margin: var(--space-3) 0 0; font-size: 12px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted);
}
/* GELD-ALLE-FACTUREN-IN-EEN-KEER-NAAR-DE-KLANT — de bulkknop staat ONDER de
   lijst die hij verstuurt, niet erboven: eerst zien wat het is, dan de daad.
   Volle breedte, want op 390 breed moet het aantal op de knop leesbaar blijven. */
.cpaysheet__bulk {
  margin-top: var(--space-4); padding-top: var(--space-3);
  border-top: 1px solid var(--line-2);
}
.cpaysheet__bulk > .cbtn { width: 100%; }
.cpaysheet__ref {
  font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 140px;
}
.cbook__bar {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--space-2); padding-bottom: var(--space-2); border-bottom: 1px solid var(--line);
}
.cbook__count { font-size: 13px; font-weight: 600; color: var(--ink); }
.cbook__tools { display: flex; align-items: center; gap: var(--space-2); }
.cbook__scope { flex: 0 0 auto; min-width: 120px; }
.cbook__csv { flex: 0 0 auto; }
.cbook__list { display: flex; flex-direction: column; }

/* ── COACH-PLATFORM-MIGRATION-ONBOARDING ─────────────────────────────────── */
.cmig-intro {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: var(--space-3); margin-bottom: var(--space-3);
}
.cmig-intro__lead { margin: 0; font-size: 14px; line-height: 1.5; color: var(--ink-2); }
.cmig-intro__sub {
  margin: var(--space-3) 0 var(--space-1); font-size: 13px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted);
}
.cmig-steps { margin: 0; padding-left: 20px; }
.cmig-steps__item { font-size: 14px; line-height: 1.6; color: var(--ink); }
.cmig-intro__note {
  margin: var(--space-3) 0 0; padding-top: var(--space-2); border-top: 1px solid var(--line-2);
  font-size: 13px; line-height: 1.5; color: var(--muted);
}
.cmig-actions { display: flex; gap: var(--space-2); margin-bottom: var(--space-3); }
.cmig__loading, .cmig__empty { font-size: 14px; color: var(--muted); }

.cmig-prog { margin-bottom: var(--space-2); }
.cmig-prog__lbl { font-size: 13px; font-weight: 600; color: var(--ink-2); margin-bottom: 6px; }
.cmig-prog__track { height: 6px; border-radius: 3px; background: var(--line-2); overflow: hidden; }
.cmig-prog__fill { height: 100%; background: var(--accent); transition: width 0.2s ease; }

.cmig-list { display: flex; flex-direction: column; gap: 1px; background: var(--line-2); border-radius: var(--radius); overflow: hidden; }
.cmig-row {
  display: flex; align-items: center; gap: var(--space-2);
  background: var(--surface); padding: var(--space-2) var(--space-3);
}
.cmig-row__id { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: var(--space-2); }
.cmig-row__name { font-size: 14px; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cmig-row__pill {
  flex: 0 0 auto; font-size: 11px; font-weight: 600; color: var(--warn);
  border: 1px solid var(--warn); border-radius: 999px; padding: 1px 8px;
}
.cmig-row__chips { display: flex; gap: 4px; flex: 0 0 auto; }
.cmig-chip {
  display: inline-flex; align-items: center; gap: 3px; padding: 2px 6px;
  border: 1px solid var(--line); border-radius: var(--radius);
  font-size: 11px; font-weight: 600; color: var(--muted);
}
.cmig-chip.is-on { border-color: var(--ok); color: var(--ok); }
.cmig-row__open { flex: 0 0 auto; }

.cmig-sheet__lead { margin: 0 0 var(--space-3); font-size: 14px; line-height: 1.5; color: var(--ink-2); }
.cmig-sheet__status { margin: var(--space-2) 0 0; font-size: 13px; color: var(--muted); }
.cmig-check { display: flex; align-items: center; gap: 8px; margin-top: var(--space-2); font-size: 14px; color: var(--ink); }
.cmig-check__hint { margin: 4px 0 var(--space-2) 24px; font-size: 12px; line-height: 1.5; color: var(--muted); }

.cmig-pick {
  display: flex; align-items: center; gap: var(--space-2); width: 100%;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: var(--space-2) var(--space-3); margin-bottom: var(--space-2);
  text-align: left; cursor: pointer; color: var(--ink);
}
.cmig-pick:active { background: var(--line-2); }
.cmig-pick__mid { flex: 1 1 auto; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cmig-pick__lbl { font-size: 14px; font-weight: 600; }
.cmig-pick__sub { font-size: 12px; color: var(--muted); }

.cmig-sum { margin-top: var(--space-3); }
.cmig-sum__row { display: flex; justify-content: space-between; gap: var(--space-2); padding: 6px 0; border-bottom: 1px solid var(--line-2); }
.cmig-sum__k { font-size: 13px; color: var(--muted); }
.cmig-sum__v { font-size: 13px; font-weight: 600; color: var(--ink); }
.cmig-sum__warn { margin: var(--space-2) 0 0; font-size: 13px; line-height: 1.5; color: var(--warn); }

.cmig-photos { margin-top: var(--space-3); }
.cmig-photo { display: flex; align-items: center; gap: var(--space-2); padding: 6px 0; border-bottom: 1px solid var(--line-2); }
.cmig-photo__name { flex: 1 1 auto; min-width: 0; font-size: 13px; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cmig-photo__date {
  flex: 0 0 auto; font: inherit; font-size: 13px; color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--radius); padding: 4px 6px; background: var(--surface);
}

/* ───────── COACH-CREDITS-TAB-FINANCE-HUB ─────────
   The Credits tab's three sub-tabs reuse the existing .ctoday__seg control; the
   only addition is a count pill on Requests. The segment keeps its own gap so
   the pill never touches the label, and it sits below the page head like the
   Review screen's segmented control. */
.cfin-seg { margin: 0 0 var(--space-3); }
.cfin-seg .ctoday__seg-btn { display: inline-flex; align-items: center; gap: 6px; }
.cfin-seg__badge {
  min-width: 18px; height: 18px; padding: 0 5px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-pill); background: var(--accent); color: var(--on-accent);
  font-size: 12px; font-weight: 700; line-height: 1;
}
.cfin-seg .ctoday__seg-btn.is-on .cfin-seg__badge { background: var(--accent); color: var(--on-accent); }
/* COACH-ALLEEN-VERTICAAL-SCROLLEN — three labelled tabs plus a badge ask 359px,
   which widened the document on a 320px phone and misses on a 375px one too.
   On phone widths they share the row instead of overflowing it. */
/* GELD-DUIM-MAAT — de oude grens stopte één pixel onder een moderne iPhone (390
   CSS-px breed), dus juist op de telefoon van de coach bleef dit een pilletje
   van ~150px tegen de linkerrand. De grens ligt nu boven elk telefoonformaat. */
@media (max-width: 480px) {
  .cfin-seg { display: flex; width: 100%; }
  .cfin-seg .ctoday__seg-btn { flex: 1 1 0; min-width: 0; justify-content: center; padding: var(--space-3) var(--space-4); gap: 4px; }
}

/* ───────── COACH-CALENDAR-APPOINTMENTS-CRUD ─────────
   Creating a session is a click on an empty hour of the grid, so the slot needs
   to LOOK clickable on hover without ever reading as a filled cell — a faint
   accent wash, no border, no cursor change on touch. */
.cal__slot { cursor: pointer; }
.cal__slot:hover,
.cal__slot:focus-visible {
  background: color-mix(in oklch, var(--accent) 10%, transparent);
  outline: none;
}
@media (hover: none) { .cal__slot:hover { background: none; } }

/* Date + time + duration on one row: the coach reads "when" as one fact. */
.appt-dt { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.appt-dt .acinput { flex: 1 1 8rem; min-width: 0; }
.appt-dt__time { flex: 0 0 6.5rem; }
.appt-dt__dur  { flex: 0 0 5rem; }
.appt-dt__unit { font-size: 12px; color: var(--muted); }

.appt-loc { display: flex; align-items: center; gap: 6px; }
.appt-loc .acinput { flex: 1 1 auto; min-width: 0; }
.appt-loc__clear {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; padding: 0;
  background: none; border: 1px solid var(--line); border-radius: var(--radius);
  color: var(--muted); cursor: pointer;
}

.appt-until { display: flex; flex-direction: column; gap: 6px; margin: 0 0 var(--space-3); }
.appt-until__hint { margin: 0; }
.appt-warn { margin: 0 0 var(--space-3); }
/* AGENDA-DUBBEL-GEBOEKT-ZIE-JE-VOOR-JE-OPSLAAT — geel, niet rood.
   .acform__hint--warn is var(--danger), en dat zegt "dit mag niet". Dubbel
   boeken MAG: twee klanten samen, of een privéblok dat niet in de weg zit. De
   regel wijst, hij houdt niet tegen, dus hij draagt het waarschuwingstoken dat
   de rest van de coach-app daarvoor gebruikt. Icoon + tekst, op één regel. */
.appt-warn--busy { color: var(--warn); display: flex; align-items: center; gap: 6px; }

/* Client chips — capped at two participants, so this never grows into a list. */
.appt-clients { display: flex; flex-direction: column; gap: 6px; }
.appt-clients__chips { display: flex; flex-wrap: wrap; gap: 6px; }
.appt-clients__chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 6px 3px 8px; border-radius: 999px;
  background: color-mix(in oklch, var(--accent) 12%, var(--surface));
  border: 1px solid var(--line);
  font-size: 12px; color: var(--ink);
}
.appt-clients__chip-x {
  display: inline-flex; padding: 0; background: none; border: 0;
  color: var(--muted); cursor: pointer;
}
.appt-clients__list {
  max-height: 168px; overflow: auto;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface);
}
.appt-clients__opt {
  display: block; width: 100%; text-align: left;
  padding: 7px var(--space-3); background: none; border: 0;
  font: inherit; font-size: 13px; color: var(--ink); cursor: pointer;
}
.appt-clients__opt:hover { background: color-mix(in oklch, var(--accent) 8%, transparent); }

.appt-detail { display: flex; flex-direction: column; }
.appt-detail__when { margin: 0; font-size: 15px; font-weight: 700; color: var(--ink); }
.appt-detail__loc  { margin: 2px 0 var(--space-3); font-size: 13px; color: var(--muted); }
/* AGENDA-AFZEGGEN-MET-EEN-REDEN — zelfde rust als de plaatsregel erboven: één
   stille regel in --muted, geen etiket en geen kleur. */
.appt-detail__prevcancel { margin: -6px 0 var(--space-3); font-size: 13px; color: var(--muted); }
.appt-detail__h    { margin: var(--space-3) 0 6px; font-size: 12px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.appt-detail__people { display: flex; flex-direction: column; gap: 6px; }
/* AGENDA-IN-EEN-DUO-ZEGT-IEDER-ZICHZELF-AF — `flex-wrap` erbij, want onder de
   naam van een deelnemer kan nu een eigen regel hangen (zijn toestand) en een
   eigen knoppenrij (afmelden / no-show). Zonder wrap zouden die naast de naam
   gaan staan en de naam wegdrukken. Voor wat er al stond verandert dit niets:
   de naam is `flex: 1 1 auto` met `min-width: 0`, dus die krimpt in plaats van
   over te lopen, en zonder overloop wrapt er ook niks. */
.appt-detail__person { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.appt-detail__person-name { flex: 1 1 auto; min-width: 0; font-size: 14px; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* De toestand van DEZE deelnemer. `flex-basis: 100%` zet hem op zijn eigen
   regel onder de naam, zodat in een duo per persoon leesbaar blijft wie er nog
   bij is. Grijs, niet rood: de sessie zelf gaat gewoon door voor de ander. */
.appt-detail__person-state { flex: 0 0 100%; margin: 0; font-size: 12px; color: var(--muted); }
.appt-detail__person-actions { display: flex; flex: 0 0 100%; flex-wrap: wrap; gap: 6px; }
.appt-detail__credit-warn { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin: 0 0 var(--space-2); font-size: 13px; color: var(--warn); }
/* AGENDA-DE-STILLE-KAPOTTE-KNOPPEN-WERKEN — het ongedaan-maken in het paneel.
   Het droeg de melding-klasse `ctoast__undo`, en die zet pointer-events UIT
   zolang de melding niet `--show` heeft; buiten een melding was deze knop dus
   onklikbaar. Eigen klasse, zelfde uiterlijk, wél klikbaar. */
.appt-detail__undo { flex: none; padding: 4px 10px; border: 1px solid currentColor; border-radius: var(--radius-sm); background: none; color: inherit; font: inherit; font-weight: 700; cursor: pointer; }
.appt-detail__cancelled { margin: 0 0 var(--space-3); font-size: 13px; font-weight: 700; color: var(--danger); }

/* CREDITS-KALENDER-KANONIEK — a no-show stays on the grid and stays charged, so
 * it must read as "this happened, but not as planned": faded, never hidden.
 * Hiding it would make the charged credit look like a bug. */
.cappt--noshow { opacity: .55; }
/* The badge is POSITIONED, not appended to the flow: a calendar card is laid out
 * absolutely on a fixed-height time grid, so an extra line in the flow would push
 * the client name out of a 30-minute block. */
.cappt__noshow-badge {
  position: absolute;
  right: 4px;
  bottom: 3px;
  padding: 0 5px;
  font-size: 10px;
  font-weight: 700;
  line-height: 15px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--on-accent);
  background: var(--danger);
  border-radius: 4px;
}

/* SAMENWERKING-SUBCOACH-IN-DE-AGENDA — a session a COLLEAGUE gives to a client of
 * mine. Deliberately the odd one out on the board: an outlined block with no fill,
 * because it is not an hour of MY day. It carries the colleague's name and it does
 * not open — editing stays with the calendar the session lives in. */
.cappt--othercoach {
  background: transparent !important;
  border: 2px solid var(--accent);
  cursor: default;
}
/* Positioned like the other card badges: the time grid gives a 30-minute block no
 * room for an extra line in the flow. */
.cappt__othercoach-badge {
  position: absolute;
  right: 4px;
  bottom: 3px;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  max-width: calc(100% - 8px);
  padding: 0 5px;
  overflow: hidden;
  font-size: 10px;
  font-weight: 700;
  line-height: 15px;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--on-accent);
  background: var(--accent);
  border-radius: 4px;
}
/* AGENDA-OPENT-OP-NU-EN-DE-KOP-PAST — an empty day says so. Two quiet lines
   above the grid, no illustration and no icon: the second line is the signifier
   for a door that already existed (tap an empty hour to plan). */
.cal__emptyday { margin: 0 0 8px; }
.cal__emptyday-t, .cal__emptyday-s { margin: 0; color: var(--muted); font-size: 13px; }
.cal__emptyday-t { font-weight: 600; }
.cal__emptyday-s { margin-top: 2px; font-size: 12px; }

.cal__othercoach-strip {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0 0 8px;
  padding: 6px 10px;
  font-size: 13px;
  color: var(--ink-2);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
}

/* AGENDA-APP-EERSTE-BURGER — an unrecognised Google row is a PROPOSAL until Sassu
 * owns it. Only the outline carries that: the gym-hue FILL stays, because it is the
 * one-glance morning-gym / evening-gym signal that every card is read by. */
.cappt--proposal { border: 1px dashed var(--accent); }
/* Positioned for the same reason the no-show badge is: the time grid has no room
 * for an extra line inside a 30-minute block. It sits TOP-right so a card that is
 * both a proposal and faded never stacks two badges on the same corner. */
.cappt__proposal-badge {
  position: absolute;
  right: 4px;
  top: 3px;
  padding: 0 5px;
  font-size: 10px;
  font-weight: 700;
  line-height: 15px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--on-accent);
  background: var(--accent);
  border-radius: 4px;
}
/* AFSPRAAK-VERZETTEN-IS-EEN-VOORSTEL — de klant vraagt om een andere tijd.
 * Een EIGEN badge naast die van Google, want het zijn twee verschillende
 * berichten: Google stelt een afspraak voor, een klant vraagt om een andere tijd.
 * Linksonder, zodat een blok dat allebei draagt geen twee etiketten stapelt. */
.cappt--acr { box-shadow: inset 0 0 0 2px var(--accent); }
/* AGENDA-EEN-AFSPRAAK-ZONDER-KLANT-VALT-OP — "geen klant" deelt deze regel in
 * plaats van een eigen etiketstijl te krijgen: de rode rand (cal__card--attention)
 * is het signaal, dit is alleen het woord erbij. Ze kunnen niet botsen op dezelfde
 * hoek — een verzetverzoek komt van een klant, en die is er dan dus. */
.cappt__acr-badge,
.cappt__noclient-badge {
  position: absolute;
  left: 4px;
  bottom: 3px;
  padding: 0 5px;
  font-size: 10px;
  font-weight: 700;
  line-height: 15px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--on-accent);
  background: var(--accent);
  border-radius: 4px;
}

/* Het voorstel in het afspraakblad. De momenten ZIJN de knoppen — er valt maar
 * één ding te doen met een moment dat je goedkeurt. */
.appt-acr {
  margin-top: var(--space-4);
  padding: var(--space-3);
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}
.appt-acr__msg  { margin: 0 0 6px; font-size: 13px; line-height: 1.45; color: var(--ink); }
.appt-acr__hint { margin: 0 0 8px; font-size: 12px; color: var(--muted); }
.appt-acr__slots { display: flex; flex-wrap: wrap; gap: 8px; }
.appt-acr__slot {
  flex: 1 1 auto;
  padding: 10px 12px;
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  background: var(--accent);
  color: var(--on-accent);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.appt-acr__slot:disabled { opacity: .45; cursor: default; }
/* AFSPRAAK-LET-OP-TWEE-DAGEN-ACHTER-ELKAAR — het labeltje. Op een slotknop
 * staat het IN de accentkleur-knop, dus het erft currentColor (--on-accent) en
 * krijgt geen eigen kleur: een tweede kleur op een gekleurde knop leest als een
 * waarschuwing, en dit is een mededeling. Op een hint-regel erft het --muted. */
.appt-acr__b2b {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-left: 6px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
  vertical-align: middle;
}
.appt-acr__b2b svg { flex: 0 0 auto; }
.appt-acr__note {
  width: 100%;
  margin-top: 8px;
  padding: 8px 10px;
  resize: vertical;
  font: inherit;
  font-size: 13px;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.appt-acr .cbtn--danger { width: 100%; margin-top: 8px; }

.appt-detail__nav { display: flex; flex-direction: column; gap: 4px; }
.appt-detail__nav-item {
  display: block; width: 100%; text-align: left;
  padding: 6px var(--space-3); background: none;
  border: 1px solid var(--line); border-radius: var(--radius);
  font: inherit; font-size: 13px; color: var(--ink); cursor: pointer;
}
.appt-detail__actions { display: flex; gap: 8px; margin-top: var(--space-4); }
.appt-detail__actions .cbtn { flex: 1 1 0; }

/* Scope toggle reuses the segmented-control idiom rather than inventing a
   second one — "this session" vs "the series" is the same kind of choice. */
.appt-scope { display: flex; gap: 4px; margin: 0 0 var(--space-3); }
.appt-scope__opt {
  flex: 1 1 0; padding: 7px var(--space-2);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  font: inherit; font-size: 13px; color: var(--ink); cursor: pointer;
}
.appt-scope__opt.is-on {
  background: color-mix(in srgb, var(--accent) 16%, var(--surface));
  color: var(--accent); border-color: var(--accent);
}

.appt-cancel__body  { margin: 0 0 var(--space-3); font-size: 14px; color: var(--ink); line-height: 1.45; }
.appt-cancel__check { display: flex; align-items: center; gap: 8px; margin: 0 0 4px; font-size: 13px; color: var(--ink); }
.appt-cancel__check.is-disabled { opacity: .5; }
.appt-cancel__sub { margin: 0 0 var(--space-3) 24px; font-size: 12px; color: var(--muted); line-height: 1.4; }
/* AGENDA-AFZEGGEN-MET-EEN-REDEN — de redenrij. Eigen blok onder de vinkjes en
   met opzet GEEN .appt-cancel__check / .appt-cancel__sub erin: drie buurpoorten
   pinnen het aantal vinkjes in dit blad en één pint de tekstlijst van
   .appt-cancel__sub op gelijkheid. De chips zelf lenen .cfin-chips__btn van de
   Geld-tab (44px raakdoel, tokens, aria-pressed) in plaats van een eigen
   chipvorm te worden. */
.acreason { margin: 0 0 var(--space-3); }
.acreason__lbl { margin: 0 0 6px; font-size: 12px; font-weight: 600; color: var(--muted); }
.acreason__chips { flex-wrap: wrap; }
.acreason__note { margin-top: var(--space-2); }
.acreason__note .acinput { width: 100%; }
.appt-cancel__actions { display: flex; gap: 8px; margin-top: var(--space-2); }
.appt-cancel__actions .cbtn { flex: 1 1 0; }

/* COACH-APPOINTMENT-CARD-MENU — the action list behind a calendar card. */
.calmenu__list { display: flex; flex-direction: column; gap: 2px; }
.calmenu__item {
  display: block; width: 100%; text-align: left;
  padding: var(--space-3); background: none; border: 0;
  border-radius: var(--radius); font: inherit; font-size: 15px;
  color: var(--ink); cursor: pointer;
}
.calmenu__item:hover:not(:disabled) { background: color-mix(in srgb, var(--ink) 6%, transparent); }
.calmenu__item:disabled { opacity: 0.5; cursor: default; }
.calmenu__item--danger { color: var(--danger); }
.calmenu__note { margin: 0; font-size: 13px; line-height: 1.45; color: var(--muted); }

/* ── COACH-ACTIVITY-TYPES-MANAGER — the coach's own activities ──
   Reuses the .ccal-feeds row idiom; only the colour dot, the kind tag and the
   stacked-sheet layer are new. The dot's colour is coach data, set inline. */
.cact__open {
  flex: 1 1 auto; display: flex; align-items: center; gap: var(--space-3);
  border: 0; background: none; padding: 0; min-width: 0;
  font: inherit; color: var(--ink); text-align: left; cursor: pointer;
}
.cact__dot {
  flex: 0 0 auto; width: 12px; height: 12px; border-radius: 999px;
  background: var(--cact-dot, var(--line));
}
.cact__tag {
  flex: 0 0 auto; padding: 2px 8px; border-radius: 999px;
  background: var(--line); color: var(--ink-2); font-size: 11px; font-weight: 600;
}
.cact__head { margin: var(--space-3) 0 0; color: var(--muted); font-size: 12px; font-weight: 600; }
.cact__row--off { opacity: 0.55; }
.cact__color { padding: 2px; height: 40px; }
.cact__toggle { flex-direction: row; align-items: center; gap: var(--space-2); }
.csheet--stacked { z-index: 60; }

/* ── AGENDA-ACTIVITEITEN-IN-JOUW-VOLGORDE — de coach schuift zijn eigen orde ──
   De greep is 28px breed en de duwknoppen zijn 34px: op 390 px staan greep,
   naam, soort-label en twee knoppen op één regel zonder dat de naam afbreekt,
   omdat .cact__open flex:1 1 auto met min-width:0 draagt en dus als enige
   krimpt. touch-action: none op de greep, anders leest iOS de eerste beweging
   als scrollen en begint het slepen nooit. */
.cact__grip {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 34px; color: var(--muted); cursor: grab; touch-action: none;
}
.cact__grip:active { cursor: grabbing; }
.ccal-feeds__row.is-dragging { opacity: 0.45; }
.cact__nudge { flex: 0 0 auto; display: flex; gap: 2px; }
.cact__nudge-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0;
  border: 1px solid var(--line); border-radius: var(--radius-2, 8px);
  background: none; color: var(--ink-2); cursor: pointer;
}
.cact__nudge-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.cact__nudge-btn:disabled { opacity: 0.35; cursor: default; }
.cact__order-hint {
  margin: var(--space-2) 0 0; color: var(--muted); font-size: 12px; line-height: 1.45;
}
.cact__cleanup {
  margin-top: var(--space-4); padding-top: var(--space-3); border-top: 1px solid var(--line);
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-2);
}
.cact__cleanup-line { margin: 0; color: var(--ink-2); font-size: 13px; line-height: 1.45; }

/* ── AGENDA-AFSPRAKEN-IN-BULK-AANPASSEN ────────────────────────────────────
   Telefoonmaat eerst (iPhone 13, 390 px). De drie snelknoppen mogen omlopen in
   plaats van te krimpen: "Vanaf vandaag" afgeknepen tot "Vanaf vand…" is geen
   knop meer. De twee datumvelden staan naast elkaar zolang ze passen en gaan
   daarna onder elkaar — ze horen bij elkaar, dus ze mogen nooit half naast en
   half onder staan. De lijst staat dicht en krijgt zijn eigen deur met een
   teller; opengeklapt is één rij een vinkje plus twee regels tekst, en het
   vinkje blijft bovenaan uitgelijnd zodat een duovermelding hem niet naar het
   midden duwt. */
.cbulk__quick { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: var(--space-3) 0 0; }
.cbulk__dates { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: var(--space-3) 0 0; }
.cbulk__date { display: flex; flex-direction: column; gap: 4px; flex: 1 1 140px; min-width: 0; }
.cbulk__date-lbl { color: var(--muted); font-size: 12px; }
.cbulk__note { margin: 4px 0 0; color: var(--muted); font-size: 12px; line-height: 1.45; }
.cbulk__note:empty { display: none; }
.cbulk__toggle {
  margin: var(--space-2) 0 0; padding: 0; border: 0; background: none;
  color: var(--accent); font-size: 13px; text-align: left; cursor: pointer;
}
.cbulk__list { margin: var(--space-2) 0 0; }
.cbulk__row {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--space-2);
  align-items: start; padding: var(--space-2) 0; border-top: 1px solid var(--line);
}
.cbulk__row:first-of-type { border-top: 0; }
.cbulk__chk { margin: 3px 0 0; width: 18px; height: 18px; accent-color: var(--accent); }
.cbulk__skip { margin-top: 2px; color: var(--muted); font-size: 12px; }
.cbulk__more, .cbulk__progress {
  margin: var(--space-2) 0 0; color: var(--muted); font-size: 12px; line-height: 1.45;
}
.cbulk__progress:empty { display: none; }

/* ───────── BEWEGINGSANALYSE-MEETSCHERM ─────────
   The coach's movement-analysis measuring screen. Layout and proportions follow
   the approved mock (_MOCK_bewegingsanalyse_{light,dark}_v1.png, panel 1); the
   voice button of phase 3 has its reserved gap in the footer already, so the bar
   will not re-flow when it lands. Coach surface only — no client screen renders
   any of this. */

/* DOSSIER-GYM-BEWEGINGSANALYSE-KAART — the entry moved from a title+line+button
   at the foot of the CLIENT panel to an accented card on the GYM panel. The
   accent border is what earns it the spot under the day card without a second
   filled button competing with it. Mobile-first: designed at 390px. */
.gym-ba {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-3); margin-bottom: var(--space-3);
  border: 1px solid var(--accent); border-radius: var(--radius);
  background: var(--surface);
}
.gym-ba__head { display: flex; align-items: flex-start; gap: var(--space-2); }
.gym-ba__head > svg { flex: 0 0 auto; color: var(--accent); margin-top: 1px; }
.gym-ba__lines { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.gym-ba__title { font-size: 15px; font-weight: 600; color: var(--ink); }
/* Two lines are reserved because the summary arrives after its own fetch: a
   one-line placeholder growing into a two-line sentence would shove everything
   below it down while the coach is already reading. */
.gym-ba__sub { font-size: 13px; line-height: 1.3; min-height: 2.6em; color: var(--ink-2); }
/* L227 — twee regels onder de titel: WANNEER er gemeten is, en WAT er open
   staat. De min-height van 2,6em hierboven hield die ruimte al vrij. */
.gym-ba__subl { display: block; }
.gym-ba__row { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.gym-ba__btn { flex: 1 1 auto; min-height: 44px; }
.gym-ba__note { margin: 0; font-size: 12px; line-height: 1.35; color: var(--muted); }

/* Joint picker: an anatomical body whose joints are real buttons. The FIGURE
   itself — .bp-stage, .bp-fig, .bp-mark, .bp-j*, .bp-spine* and the --bp-body /
   --bp-edge tokens — moved to /assets/css/joint-figure.css so the member surface
   can load the same drawing (HET-SKELETPOPPETJE-WORDT-GEDEELD). What stays below
   is the SCREEN around it, which is the coach's alone. */
.bp-q { margin: 16px 0 0; font-size: 19px; letter-spacing: -.01em; }
.bp-sub { margin: 4px 0 0; font-size: 13.5px; line-height: 1.4; color: var(--muted); }
.bp-day { position: relative; display: inline-flex; align-items: center; }
.bp-day__in {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; border: 0; padding: 0; background: none;
}
.bp-quick { display: flex; gap: 8px; padding: 12px 0 0; }
.bp-chip {
  padding: 8px 13px; border-radius: 999px; border: 1px solid var(--line);
  background: var(--surface); color: var(--ink-2); font: inherit; font-size: 12.5px; font-weight: 600;
}
.bp-draft { display: none; }
.bp-draft.is-on {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin: 12px 0 0; padding: 10px 12px; border-radius: 12px;
  border: 1px solid var(--line-2); background: var(--surface);
}
.bp-draft__t { font-size: 13px; line-height: 1.35; color: var(--ink-2); }
.bp-draft__go {
  flex: none; padding: 8px 12px; border-radius: 999px; border: 1px solid var(--accent);
  background: transparent; color: var(--ink); font: inherit; font-size: 13px; font-weight: 700;
}
.bp-stagewrap { display: flex; justify-content: center; padding: 10px 0 0; }
/* Sits UNDER the stage, not beside it: the left/right words hang outside the
   stage box and a line next to the body would run into them on a 390px phone. */
.bp-view { margin: 8px 0 0; font-size: 12px; line-height: 1.35; text-align: center; color: var(--muted); }
.bp-picked { display: flex; flex-wrap: wrap; gap: 7px; padding: 10px 0 0; }
.bp-tag {
  display: flex; align-items: center; gap: 7px; padding: 7px 8px 7px 12px; border-radius: 999px;
  border: 1px solid var(--accent); background: color-mix(in oklab, var(--accent) 12%, transparent);
  color: var(--ink); font: inherit; font-size: 13px; font-weight: 600;
}
.bp-tag i {
  font-style: normal; font-size: 11.5px; font-weight: 700;
  color: var(--on-accent); background: var(--accent);
  min-width: 19px; height: 19px; border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
}
.bp-foot { padding: 14px 0 4px; }
.bp-go {
  width: 100%; padding: 16px 0; border: 0; border-radius: 999px;
  background: var(--accent); color: var(--on-accent); font: inherit; font-size: 15.5px; font-weight: 700;
}
.bp-go:disabled { background: var(--line); color: var(--muted); }
.ba-start__err:empty { display: none; }
.ba-start__err { margin: 0; font-size: 13px; color: var(--danger); }
.ba-del {
  flex: none; display: flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0; border: 0; border-radius: var(--radius);
  background: none; color: var(--muted);
}
.ba-del:disabled { opacity: .5; }

/* Measuring screen. */
.ba-screen { display: flex; flex-direction: column; min-height: 0; }
.ba-loading { margin: var(--space-4) 0; color: var(--muted); font-size: 14px; }

.ba-top {
  display: flex; align-items: center; gap: 10px;
  padding: 4px 0 10px; border-bottom: 1px solid var(--line-2);
}
.ba-x, .ba-top__save, .ba-top__bin {
  background: none; border: 0; color: var(--ink-2); padding: 6px;
  border-radius: var(--radius); font: inherit; font-size: 14px;
}
.ba-top__bin { display: flex; align-items: center; }
.ba-top__bin:disabled { opacity: .5; }
.ba-top__mid { flex: 1; display: flex; flex-direction: column; align-items: center; line-height: 1.25; min-width: 0; }
.ba-top__who { font-size: 15px; font-weight: 700; }
.ba-top__where { font-size: 12.5px; color: var(--muted); }

.ba-prog { height: 4px; background: var(--line-2); margin: 0; border-radius: 999px; overflow: hidden; }
.ba-prog i { display: block; height: 100%; background: var(--accent); transition: width .18s ease; }

/* The pill strip: one row, scrolls itself, never pushes the card off screen. */
.ba-strip { display: flex; align-items: center; gap: 8px; padding: 8px 0 6px; min-width: 0; }
.ba-jselwrap { position: relative; flex: none; }
.ba-jsel {
  display: flex; align-items: center; gap: 5px; padding: 8px 11px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink);
  font: inherit; font-size: 13px; font-weight: 700;
}
.ba-jmenu {
  display: none; position: absolute; z-index: 20; top: calc(100% + 6px); left: 0; min-width: 150px;
  flex-direction: column; padding: 6px; border: 1px solid var(--line); border-radius: 14px;
  background: var(--surface); box-shadow: 0 10px 26px rgba(0,0,0,.16);
}
.ba-jmenu.is-on { display: flex; }
.ba-jmenu__i {
  padding: 10px 12px; border: 0; border-radius: 10px; background: transparent;
  color: var(--ink); font: inherit; font-size: 14px; font-weight: 600; text-align: left;
}
.ba-strip__rail {
  display: flex; gap: 6px; min-width: 0; overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
  mask-image: linear-gradient(to right, #000 84%, transparent);
}
.ba-strip__rail::-webkit-scrollbar { display: none; }
.ba-pill {
  flex: none; display: flex; align-items: center; gap: 5px; padding: 8px 12px; border-radius: 999px;
  border: 1px solid var(--line-2); background: transparent; color: var(--muted);
  font: inherit; font-size: 13px; font-weight: 600;
}
.ba-pill.is-done { color: var(--ink-2); }
.ba-pill.is-done svg { color: var(--accent); }
.ba-pill.is-on { background: var(--ink); border-color: var(--ink); color: var(--surface); }

/* Quiet, never an error: a lost signal in the gym is not the coach's problem. */
.ba-unsaved { margin: 4px 0 0; text-align: center; font-size: 12px; color: var(--muted); min-height: 15px; }

/* ─────────────────────────────────────────────────────────────────────────────
   DOSSIER-VOEDING-JE-SWIPET-DOOR-DE-EIWITSPREIDING-PER-DAG — the protein spread
   strip in the client dossier's Nutrition panel. One page per day, full width,
   barely any height. The swipe surface is taken over from the client app's
   .nut-consist__pages: native scroll + scroll-snap, so the strip follows the
   finger with the platform's own momentum and there is NO touch handler to
   fight pull-to-refresh with.
   Height budget: page 40px + the two 1px hairlines = 42px, under the 44px cap.
   ──────────────────────────────────────────────────────────────────────────── */
/* DOSSIER-NOORDSTER-ALS-OVERZICHT (bevinding #9) — de strook kwam zonder kop
   binnen en las als een losgeraakte scrollbalk. Hij krijgt dezelfde stille
   sectiekop als elk ander dossierblok. LET OP: `.dsec-title` draagt zelf
   `display: flex`, en dat verslaat de UA-regel voor `[hidden]` stil — zonder
   de regel hieronder blijft de kop staan boven een strook die er niet is. */
.psp-host__title { margin-bottom: 6px; }
.psp-host__title[hidden] { display: none; }
.psp {
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  margin: 10px 0 0;
}
.psp__pages {
  display: flex; overflow-x: auto; overflow-y: hidden;
  /* auto, NOT smooth: the only programmatic scroll is the jump to the newest
     day on first paint, and a strip that scrolls itself while you read it is a
     strip that moved. The swipe itself is the browser's. */
  scroll-snap-type: x mandatory; scroll-behavior: auto;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
}
.psp__pages::-webkit-scrollbar { display: none; }
.psp__page {
  flex: 0 0 100%; scroll-snap-align: start; box-sizing: border-box;
  height: 40px; padding: 0 12px 7px;
  display: flex; align-items: flex-end; gap: 0;
}
/* FIXED widths on the label and the total, not auto. MEASURED on the mock: with
   auto widths "Not logged" is wider than "112/140 g", so the rail started at
   283px on one page and 268px on the next — a 15px drift. This strip exists to
   compare the SPREAD of one day against another by swiping, and an axis that
   slides sideways between pages makes two identical breakfasts land in two
   different places. Every page now shares one time axis. */
.psp__lbl {
  flex: 0 0 48px; display: inline-flex; align-items: baseline; gap: 3px;
  font-family: 'Geist Sans', sans-serif; font-size: 11px; line-height: 1;
}
.psp__dow { color: var(--muted); }
.psp__dnum { color: var(--ink-2); font-variant-numeric: tabular-nums; }
/* The 12px side margins are the pills' overhang room: a pill is centred on its
   percentage, so at 0% and 100% half of it sits outside the rail. Without the
   margin the first and last meal of the day would be clipped by the label and
   the total. */
.psp__rail { position: relative; flex: 1 1 auto; min-width: 0; height: 24px; margin: 0 12px; }
.psp__line {
  position: absolute; left: 0; right: 0; bottom: 0; height: 6px;
  background: var(--line); border-radius: 999px;
}
/* 1px hairline, the same weight as the client app's own NOW line. */
.psp__now {
  position: absolute; bottom: 0; width: 1px; height: 18px;
  background: var(--accent); opacity: 0.55; pointer-events: none;
}
.psp__pill {
  position: absolute; bottom: 9px; transform: translateX(-50%);
  box-sizing: border-box; min-width: 20px; height: 15px; padding: 0 4px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line-2); border-radius: 999px;
  background: var(--surface); color: var(--ink-2);
  font-family: 'Geist Sans', sans-serif; font-size: 10px; line-height: 1;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.psp__pill-sup {
  position: absolute; top: -5px; right: -3px;
  font-size: 8px; line-height: 1; color: var(--accent);
}
.psp__tot {
  flex: 0 0 62px; text-align: right;
  font-family: 'Geist Sans', sans-serif; font-size: 10px;
  line-height: 1; color: var(--muted); font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* A day nobody logged is muted, NEVER red: the strip reports, it does not judge. */
.psp__tot--miss { opacity: 0.7; }

.ba-card {
  margin: 12px 0 0; padding: 16px;
  border: 1px solid var(--line-2); border-radius: 14px; background: var(--surface);
}
.ba-card__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ba-move { margin: 0; font-size: 27px; line-height: 1.1; letter-spacing: -.01em; }
.ba-help { background: none; border: 0; color: var(--muted); padding: 4px; display: flex; }
.ba-hint { margin: 0; font-size: 13px; line-height: 1.45; color: var(--ink-2); }
.ba-hint:not(.is-on) { display: none; }
/* BEWEGINGSANALYSE-METER-PERSPECTIEF — the measuring position, always open. */
.ba-pos { margin: 6px 0 0; font-size: 12.5px; line-height: 1.4; color: var(--muted); }
.ba-hint.is-on { margin-top: 8px; }
/* BEWEGINGSANALYSE-MEETUITLEG-EN-COMPENSATIE — the opened question mark. */
.ba-help__steps, .ba-help__watch { margin: 0; padding: 0 0 0 18px; }
.ba-help__steps li, .ba-help__watch li { margin: 0 0 3px; }
.ba-help__watch-h {
  margin: 8px 0 3px; font-size: 12px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted);
}
.ba-help__watch { list-style: none; padding-left: 0; }
.ba-help__watch li { position: relative; padding-left: 14px; }
.ba-help__watch li::before {
  content: ''; position: absolute; left: 2px; top: .55em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--accent);
}

.ba-side { display: flex; gap: 8px; margin-top: 12px; }
.ba-side__btn {
  flex: 1; padding: 9px 0; border: 1px solid var(--line); background: var(--surface);
  color: var(--ink-2); border-radius: 999px; font: inherit; font-size: 14px; font-weight: 600;
  display: flex; align-items: center; justify-content: center; gap: 6px;
}
.ba-side__btn.is-on {
  background: color-mix(in srgb, var(--accent) 16%, var(--surface));
  color: var(--accent); border-color: var(--accent);
}
.ba-side__done { color: var(--ok); display: flex; }
.ba-side__btn.is-on .ba-side__done { color: var(--accent); }

.ba-mirror {
  display: flex; margin: 8px 0 -4px auto; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0; background: none;
  border: 1px solid var(--line-2); border-radius: 8px; color: var(--muted); cursor: pointer;
}
.ba-mirror.is-on { color: var(--accent); border-color: var(--accent); }
.ba-vals { display: flex; gap: 10px; margin-top: 14px; }
.ba-val {
  flex: 1; border: 1px solid var(--line-2); border-radius: 12px;
  padding: 12px 10px 10px; text-align: center; background: var(--bg);
  display: flex; flex-direction: column; align-items: center; position: relative;
}
.ba-val:focus-within { border-color: var(--accent); }
.ba-val__lab {
  display: block; font-size: 12.5px; color: var(--muted);
  letter-spacing: .03em; text-transform: uppercase; font-weight: 700;
}
/* The number is the largest thing on the screen — that is the whole point. */
.ba-val__num {
  width: 100%; border: 0; background: none; color: var(--ink); text-align: center;
  font: inherit; font-size: 46px; font-weight: 750; letter-spacing: -.03em; line-height: 1.12;
  margin-top: 2px; padding: 0; min-width: 0;
}
.ba-val__num:focus { outline: none; }
.ba-val__deg { font-style: normal; font-size: 20px; font-weight: 600; color: var(--muted); }

/* ── the swipe dial ───────────────────────────────────────────────────────
   The wedge stands at the REAL angle, so the phone can be held beside the
   joint and read off against it; the scale only decides how far the ticks
   run. touch-action:none sits ONLY on the dial, so the page underneath keeps
   scrolling normally. */
.ba-val--dial { padding: 10px 8px 8px; }
.ba-mtr {
  position: relative; width: 100%; aspect-ratio: 1 / 1;
  touch-action: none; -webkit-user-select: none; user-select: none;
  cursor: ns-resize;
}
.ba-mtr > svg { display: block; width: 100%; height: 100%; }
/* The reading sits in the open corner, clear of both wedge and callout —
   data-corner is the diagonal of THIS movement's pivot, so it moves with the
   plate instead of assuming one fixed geometry. */
.ba-mtr { --ba-num-w: 2.7em; }
.ba-mtr--bidir { --ba-num-w: 3.1em; }
.ba-mtr .ba-val__num {
  position: absolute; top: 0; right: 4px; width: var(--ba-num-w); margin: 0;
  text-align: right; font-size: 34px; line-height: 1;
}
.ba-mtr[data-corner$="l"] .ba-val__num { right: auto; left: 4px; }
.ba-mtr[data-corner^="b"] .ba-val__num { top: auto; bottom: 0; }
.ba-mtr .ba-val__deg {
  position: absolute; top: 2px; right: -3px; font-size: 15px; pointer-events: none;
}
.ba-mtr[data-corner$="l"] .ba-val__deg { right: auto; left: calc(4px + var(--ba-num-w) - 3px); }
.ba-mtr[data-corner^="b"] .ba-val__deg { top: auto; bottom: 4px; }
.ba-mtr.is-tick > svg { filter: brightness(1.12); }

/* ── camera behind the dial ───────────────────────────────────────────────
   A live see-through only — nothing is captured. The video sits UNDER both
   dials and is deaf to pointers, so the swipe layer on .ba-mtr keeps working
   exactly as before; the card background drops away and the drawing gets a
   dark halo so it stays readable over a moving image. */
.ba-tools { display: flex; justify-content: flex-end; gap: 6px; margin: 8px 0 -4px; }
.ba-tools .ba-mirror { margin: 0; }
.ba-camwrap { position: relative; }
.ba-camwrap > .ba-vals { position: relative; z-index: 1; }
.ba-cam {
  position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0;
  object-fit: cover; border-radius: 12px; background: #000; pointer-events: none;
}
.ba-camwrap.is-cam .ba-val--dial { background: transparent; border-color: rgba(255, 255, 255, .5); }
.ba-camwrap.is-cam .ba-mtr > svg { filter: drop-shadow(0 0 2px rgba(0, 0, 0, .9)); }
.ba-camwrap.is-cam .ba-val__lab,
.ba-camwrap.is-cam .ba-val__num,
.ba-camwrap.is-cam .ba-val__deg {
  /* Legibility over an arbitrary camera image: the halo does the contrast work. */
  color: #fff; text-shadow: 0 1px 3px rgba(0, 0, 0, .95);
}

/* A physically impossible pair: a nudge to re-read, never a block. */
.ba-impossible { margin: 8px 2px 0; font-size: 12px; color: var(--muted); font-style: italic; }
.ba-impossible:empty { display: none; }

/* Which ruler the dial is printed on. Never a norm. */
.ba-card__head .ba-move { flex: 1; }
.ba-scale {
  font-size: 11px; font-weight: 600; letter-spacing: .03em; color: var(--muted);
  border: 1px solid var(--line-2); border-radius: 999px; padding: 3px 9px; white-space: nowrap;
}

.ba-gap {
  margin-top: 12px; padding: 9px 12px; border-radius: 10px;
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
}
.ba-gap:empty { display: none; }
.ba-gap.is-ok { background: color-mix(in oklab, var(--ok) 12%, transparent); }
/* Louder, not alarming: the course forbids any judgement beyond the difference. */
.ba-gap.is-hi { background: color-mix(in oklab, var(--warn) 16%, transparent); }
.ba-gap__n { font-size: 15px; font-weight: 700; }
.ba-gap__t { font-size: 12.5px; color: var(--ink-2); }

.ba-painwrap { margin-top: 14px; }
.ba-pain { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.ba-pain--shut { border: 0; background: transparent; padding: 0; }
.ba-painq {
  display: flex; align-items: center; gap: 6px; padding: 10px 14px; border-radius: 999px;
  border: 1px dashed color-mix(in oklab, var(--ink) 26%, transparent); background: transparent;
  color: var(--muted); font: inherit; font-size: 13.5px; font-weight: 600;
}
.ba-pain__lab, .ba-hinge__lab { font-size: 13px; color: var(--muted); font-weight: 600; }
.ba-chip {
  padding: 7px 13px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); color: var(--ink-2); font: inherit; font-size: 13.5px; font-weight: 600;
}
.ba-chip.is-on { background: var(--ink); border-color: var(--ink); color: var(--surface); }

.ba-hinge { margin-top: 14px; display: flex; flex-direction: column; gap: 12px; }
.ba-hinge__q { display: flex; align-items: center; gap: 7px; }
.ba-hinge__where { display: flex; flex-direction: column; gap: 6px; }
.ba-hinge__in {
  padding: 12px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--bg); color: var(--ink); font: inherit; font-size: 16px;
}

.ba-noteblk { margin-top: 12px; }
.ba-note {
  width: 100%; padding: 10px; border: 1px dashed var(--line); border-radius: 10px;
  background: none; color: var(--muted); font: inherit; font-size: 13.5px; text-align: left;
}
.ba-note.is-filled { color: var(--ink-2); border-style: solid; }
.ba-note__ta {
  width: 100%; padding: 10px; border: 1px solid var(--accent); border-radius: 10px;
  background: var(--bg); color: var(--ink); font: inherit; font-size: 15px; resize: vertical;
}

.ba-foot { margin-top: var(--space-4); padding-bottom: var(--space-3); display: flex; align-items: center; gap: 12px; }
.ba-nav {
  width: 52px; height: 52px; border-radius: 50%; border: 1px solid var(--line);
  background: var(--surface); color: var(--ink-2);
  display: flex; align-items: center; justify-content: center;
}
.ba-nav:disabled { opacity: .4; }
.ba-foot__slot {
  flex: 1; min-height: 60px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
}

/* ── BEWEGINGSANALYSE-STEM ── */
.ba-mic {
  width: 60px; height: 60px; flex: 0 0 auto; padding: 0; border-radius: 50%;
  border: 1px solid var(--accent); background: var(--accent); color: var(--on-accent);
  display: flex; align-items: center; justify-content: center;
  -webkit-tap-highlight-color: transparent; touch-action: none; user-select: none;
  transition: background .15s, transform .1s;
}
.ba-mic:active { transform: scale(.96); }
.ba-mic.is-rec {
  background: var(--danger, #e5484d); border-color: var(--danger, #e5484d);
  animation: ba-mic-pulse 1.15s ease-in-out infinite;
}
.ba-mic.is-busy svg { animation: ba-mic-spin .8s linear infinite; }
@keyframes ba-mic-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--danger, #e5484d) 55%, transparent); }
  50%      { box-shadow: 0 0 0 9px color-mix(in srgb, var(--danger, #e5484d) 0%, transparent); }
}
@keyframes ba-mic-spin { to { transform: rotate(360deg); } }
/* The spoken order, printed. Learned, not guessed. */
.ba-mic__rule { font-size: 11px; color: var(--muted); text-align: center; line-height: 1.2; }
/* The literal transcript. Holds its line so the footer never jumps. */
.ba-heard {
  margin: var(--space-3) 0 0; min-height: 18px; text-align: center;
  font-size: 13px; color: var(--muted); opacity: 0;
}
.ba-heard.is-on { opacity: 1; }
.ba-heard.is-miss { color: var(--danger, #e5484d); }

/* ───────── BEWEGINGSANALYSE-OVERZICHT-EN-RAPPORT ─────────
   What comes after the measuring: the overview, the comparison and the report.
   Layout follows the approved mock (_MOCK_bewegingsanalyse_{light,dark}_v1.png,
   panels 2 and 3). Coach surface only.

   The report has no server-side renderer — there is no PDF engine and no
   composer in v0.x — so the @media print block at the bottom of this file IS the
   PDF: the coach's own share sheet prints this page to A4. */

/* ── overview ── */
.ba-ov__head {
  display: flex; align-items: center; gap: 10px;
  padding: 4px 0 10px; border-bottom: 1px solid var(--line-2);
}
.ba-ov__headmid { flex: 1; display: flex; flex-direction: column; align-items: center; line-height: 1.25; min-width: 0; }
.ba-ov__who { font-size: 15px; font-weight: 700; }
.ba-ov__when { font-size: 12.5px; color: var(--muted); }
.ba-ov__share { background: none; border: 0; color: var(--ink-2); padding: 6px; display: flex; border-radius: var(--radius); }

/* The opening line is the only place that counts anything, so it gets to be
   the largest text on the screen. */
.ba-ov__lead { margin: var(--space-4) 0 0; font-size: 15.5px; line-height: 1.45; }
.ba-ov__lead1 { font-weight: 700; color: var(--accent); }
.ba-ov__lead2 { color: var(--ink-2); }

.ba-ov__joint { margin-top: var(--space-5); }
.ba-ov__jhead { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.ba-ov__jname {
  margin: 0 0 4px; font-size: 12.5px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--accent);
}
/* GYM-DE-BEWEGINGSANALYSE-TOONT-LINKS-EN-RECHTS-NAAST-ELKAAR (L227 v2) — de
   gewrichtskop zegt van welke DAG de getallen eronder komen. De chip zegt welke
   dag je LEEST; dat hoeft niet dezelfde te zijn, want een beweging die vandaag
   niet gemeten is houdt de stand van de laatste keer. */
.ba-ov__jdates { font-size: 11.5px; color: var(--muted); white-space: nowrap; }

.ba-ov__row {
  display: grid; grid-template-columns: minmax(0, 1fr) 62px 62px; align-items: center; gap: 6px;
  padding: 9px 0; border-bottom: 1px solid var(--line-2);
}
.ba-ov__row--single { grid-template-columns: minmax(0, 1fr) auto; }
/* GYM-HET-BEWEGINGSRAPPORT-TOONT-JE-NOTITIES (L236) — de notitie van de coach,
   onder haar eigen rij en over de hele tabelbreedte. Klein en gedempt, GEEN
   kleur: kleur is op dit scherm onbalans, en een notitie is geen signaal. De rij
   geeft haar onderstreping af aan de notitie, zodat het paar één blok blijft. */
.ba-ov__row.has-note { border-bottom: 0; padding-bottom: 2px; }
.ba-ov__rownote {
  padding: 0 0 9px; border-bottom: 1px solid var(--line-2);
  font-size: 12.5px; line-height: 1.4; color: var(--muted);
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.ba-ov__rownote__line { display: block; }
.ba-ov__rownote__line + .ba-ov__rownote__line { margin-top: 2px; }
.ba-ov__rownote__line > b { font-weight: 600; color: var(--ink-2); margin-right: 4px; }
.ba-ov__rownote__on { margin-left: 4px; white-space: nowrap; }
/* Passive and active per side: four numbers. The headers carry the SAME grid,
   otherwise the label does not stand over its number and the point is lost. */
/* GYM-DE-BEWEGINGSANALYSE-BEGINT-LINKS (L196) — de lucht tussen de twee paren is
   een LEGE RASTERBAAN (kolom 4), geen marge op een zijde. De oude regel hing aan
   [data-side="left"], en die duwde na het omzetten van de leesorde precies het
   verkeerde paar. Zes banen: naam · passief · actief · lucht · passief · actief. */
.ba-ov__row--pa,
.ba-ov__colhead {
  grid-template-columns: minmax(0, 1fr) 48px 48px 10px 48px 48px; column-gap: 4px; row-gap: 0;
}
.ba-ov__colhead {
  display: grid; align-items: center; padding: 0 0 3px; text-align: right;
  font-size: 10px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted);
}
.ba-ov__colhead--side { padding-bottom: 1px; }
.ba-ov__ch2 { grid-column: span 2; text-align: center; color: var(--ink-2); font-size: 10.5px; }
/* De eerste cel van het TWEEDE paar slaat de luchtbaan over. Positioneel — de
   klasse weet niet welke zijde erin staat, en hoeft dat ook niet te weten. */
.ba-ov__p2 { grid-column-start: 5; }
.ba-ov__ch2.ba-ov__p2 { grid-column: 5 / span 2; }
/* PASSIEF/ACTIEF raakten elkaar: 10px/.06em in een baan van 36px contentbox liep
   over de buur heen (gemeten labelgaten [8, 13, 0] px op 360 én 390). Smaller en
   krapper gespatieerd, en nooit afbreken. */
/* L227 v2 — het rondje ERVOOR kost 7px + 2px lucht in een baan van 48px, en die
   baan is door de L196-poort vastgezet. Daarom gaat het WOORD een halve punt
   omlaag en vervalt de letterspatiëring: gemeten op 360 én 390 houden de vier
   koplabels zo ≥8px lucht tussen hun tekstkaders (de poort van het spelerblad
   meet dat op de INK, niet op de rastercel). Nooit afbreken. */
.ba-ov__colhead--pa > * { font-size: 8.5px; letter-spacing: 0; white-space: nowrap; }
/* PASSIEF EN ACTIEF ONDUBBELZINNIG (Jayy 20-10: "ik zie het verschil tussen
   actief en passief niet"). Een OPEN rondje bij passief, een DICHT rondje bij
   actief: vorm, geen kleur, want kleur is op dit scherm van de onbalans. */
.ba-ov__chp, .ba-ov__cha {
  display: inline-flex; align-items: center; justify-content: flex-end; gap: 2px;
}
.ba-ov__chp { background: var(--bg); }
.ba-ov__gl { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; }
.ba-ov__gl--p { border: 1.5px solid var(--muted); }
.ba-ov__gl--a { background: var(--ink); }
.ba-ov__row--pa .ba-ov__v { font-size: 13.5px; }
.ba-ov__mv { font-size: 14.5px; color: var(--ink); min-width: 0; }
.ba-ov__v {
  display: flex; align-items: center; justify-content: flex-end; gap: 3px;
  font-size: 14.5px; color: var(--ink-2); font-variant-numeric: tabular-nums;
}
/* …en dezelfde tweedeling in de getallen zelf: de passieve kolom draagt een
   lichte band en een normale letter, de actieve staat vet op de voorgrond. Deze
   twee regels staan VÓÓR de markeringen hieronder: gelijke specificiteit, dus
   bronorde beslist, en een markering hoort altijd te winnen van de band. */
.ba-ov__v[data-kind="prom"] { background: var(--bg); font-weight: 400; color: var(--ink-2); }
.ba-ov__v[data-kind="arom"] { font-weight: 700; color: var(--ink); }
.ba-ov__v.is-empty { color: var(--muted); }
/* Marked PER SIDE — left can be fine while right is not, and that difference is
   the whole reason this screen exists. */
.ba-ov__v.is-hi { color: var(--ink); font-weight: 700; }
.ba-ov__mark {
  width: 7px; height: 7px; border-radius: 2px; flex: 0 0 auto;
  background: var(--warn, #d08700);
}
/* GYM-DE-BEWEGINGSANALYSE-HOUDT-ELKE-MEETDATUM (L227) — KLEUR IS ONBALANS.
   Amber = het gat passief-actief boven de twintig; violet = de lagere van twee
   kanten. In balans blijft de cel kleurloos: een rustig lichaam hoort rustig te
   lezen. Nooit alleen kleur — er hangt altijd een blokje of een streep bij. */
.ba-ov__v.is-gap { background: color-mix(in srgb, var(--warn) 26%, transparent); }
.ba-ov__v.is-side {
  background: color-mix(in srgb, var(--ba-side) 16%, transparent);
  box-shadow: inset 2px 0 0 var(--ba-side);
}
/* Samen: de amber achtergrond wint (dat is het signaal dat de methode noemt) en
   de violette streep blijft staan, zodat geen van beide verdwijnt. */
.ba-ov__v.is-gap.is-side {
  background: color-mix(in srgb, var(--warn) 26%, transparent);
  box-shadow: inset 2px 0 0 var(--ba-side);
}
.ba-ov__ar { flex: 0 0 auto; }
.ba-ov__ar--up { color: var(--accent); }
.ba-ov__ar--down { color: var(--muted); }
/* "was 70" onder het nieuwe getal — klein en grijs, want het is de vorige stand
   en niet het antwoord. Een cel met een pijl stapelt dus, net als een hertest. */
.ba-ov__was { font-size: 10.5px; color: var(--muted); line-height: 1.15; }
.ba-ov__v.has-was {
  flex-direction: column; align-items: flex-end; gap: 0; line-height: 1.2;
}
.ba-ov__row--pa .ba-ov__v.has-was { font-size: 12.5px; }

/* L227 v2 — DE DATUM-CHIPS. Jayy, 20-10: "iets dat swipebaar is, zodat we door
   datums heen kunnen swipen." Eén rij bovenaan voor de HELE analyse, in plaats
   van een kolom per datum per gewricht: de tabel blijft dan de tabel van de heup
   (links | rechts, elk passief | actief) en hoeft niet horizontaal te schuiven.
   Bij meer dan vier datums schuift de RIJ, nooit de pagina. */
.ba-ov__dates {
  display: flex; gap: 6px; margin-top: var(--space-3); padding-bottom: 2px;
  overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
}
.ba-ov__dates::-webkit-scrollbar { display: none; }
.ba-ov__date {
  flex: 0 0 auto; padding: 5px 11px; min-height: 30px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-2);
  font: inherit; font-size: 12px; font-weight: 700; white-space: nowrap; cursor: pointer;
}
.ba-ov__date.is-on {
  background: var(--accent); border-color: var(--accent); color: var(--on-accent);
}
/* L227 fase 4 — DE REGEL ONDER DE CHIPS: puntjes links (waar sta ik), schakelaar
   rechts (waartegen lees ik). Op 360 mag de schakelaar onder de puntjes vallen
   in plaats van zijn labels af te kappen — "t.o.v. vorige" is pas een keuze als
   je hem kunt lezen. */
.ba-ov__under {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; flex-wrap: wrap; margin-top: 6px;
}
.ba-ov__under .ba-ov__dots { margin-top: 0; }
/* Een SPOOR in --bg met twee knoppen erin. De gekozen knop krijgt accentrand en
   accenttekst op --surface en bewust GEEN gevuld accent: de gekozen chip erboven
   is het accent van dit scherm, en twee gevulde accenten vechten om één blik. */
.ba-ov__base {
  display: inline-flex; gap: 2px; padding: 2px; border-radius: 999px;
  background: var(--bg); border: 1px solid var(--line-2); margin-left: auto;
}
.ba-ov__basebtn {
  padding: 4px 10px; min-height: 26px; border: 1px solid transparent;
  border-radius: 999px; background: none; color: var(--muted);
  font: inherit; font-size: 11.5px; font-weight: 700; white-space: nowrap; cursor: pointer;
}
.ba-ov__basebtn.is-on {
  background: var(--surface); border-color: var(--accent); color: var(--accent);
}
.ba-ov__dots { display: flex; justify-content: center; gap: 5px; margin-top: 6px; }
.ba-ov__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--line); }
.ba-ov__dot.is-on { background: var(--accent); }
/* De veegzone. pan-y laat verticaal scrollen vrij: alleen een HORIZONTALE haal
   wisselt van dag. */
.ba-ov__body { touch-action: pan-y; }

/* L227 fase 4 — DE HELE PROGRESSIE van één beweging, opengeklapt onder haar rij.
   Dezelfde rasterbanen als .ba-ov__row(--pa), zodat L/R en P/A op exact dezelfde
   plek blijven staan als in de rij erboven: het oog hoeft niet te verspringen. */
.ba-ov__progchev {
  flex: 0 0 auto; margin-left: 4px; color: var(--muted);
  transition: transform .12s ease;
}
.ba-ov__mv { display: inline-flex; align-items: center; }
.ba-ov__row[role="button"] { cursor: pointer; }
.ba-ov__row.is-open .ba-ov__progchev { transform: rotate(90deg); }
/* Een linkerlijn in plaats van een eigen achtergrond: een band op de subrij zou
   de band van de PASSIEVE cel (ook --bg) overstemmen, en die band is wat passief
   van actief onderscheidt. De reeks hoort ingesprongen te lezen, niet anders
   gekleurd. */
.ba-ov__prog { margin: 0 0 4px 1px; padding-left: 7px; border-left: 2px solid var(--line-2); }
.ba-ov__progrow {
  display: grid; grid-template-columns: minmax(0, 1fr) 62px 62px;
  align-items: center; gap: 6px; padding: 5px 0;
  border-bottom: 1px solid var(--line-2);
}
.ba-ov__progrow--pa {
  grid-template-columns: minmax(0, 1fr) 48px 48px 10px 48px 48px; column-gap: 4px; row-gap: 0;
}
.ba-ov__progd {
  font-size: 11.5px; font-weight: 700; color: var(--muted); white-space: nowrap;
}
/* De subrij van de GEKOZEN chip krijgt een accentstreep: zo zie je in de reeks
   terug welke dag de tabel erboven toont. */
.ba-ov__progrow.is-sel { box-shadow: inset 3px 0 0 var(--accent); }
.ba-ov__progrow.is-sel .ba-ov__progd { color: var(--ink-2); }
.ba-ov__progrow .ba-ov__v { font-size: 12.5px; }
.ba-ov__progrow .ba-ov__v.has-was { font-size: 11.5px; }

/* De symbolensleutel: wat betekent dit teken. Geen uitlegzin — zonder sleutel
   zijn twee kleuren niet te lezen, mét sleutel is het één regel. */
.ba-ov__key {
  display: flex; flex-wrap: wrap; gap: 4px 12px; margin-top: 8px;
  font-size: 11px; color: var(--muted);
}
.ba-ov__keyit { display: inline-flex; align-items: center; gap: 4px; }
.ba-ov__keysw { width: 9px; height: 9px; border-radius: 2px; flex: 0 0 auto; }
.ba-ov__keysw--gap { background: color-mix(in srgb, var(--warn) 50%, transparent); }
.ba-ov__keysw--side {
  background: color-mix(in srgb, var(--ba-side) 30%, transparent);
  box-shadow: inset 2px 0 0 var(--ba-side);
}

.ba-ov__v--hinge { font-size: 13px; }
.ba-ov__arrow { font-style: normal; color: var(--muted); font-size: 12px; }
.ba-ov__g--re { color: var(--ink); }
/* A retest stacks under its first reading — four columns leave no width beside. */
.ba-ov__v.has-retest {
  flex-direction: column; align-items: flex-end; gap: 0; line-height: 1.2; font-size: 12px;
}
.ba-ov__row--pa .ba-ov__v.has-retest { font-size: 11.5px; }
.ba-ov__line { display: flex; align-items: center; justify-content: flex-end; gap: 3px; }

/* Pain has a block of its own because in this method it is what turns a session
   into a referral — not a footnote on a row. */
.ba-ov__pain {
  margin-top: var(--space-5); padding: 12px 14px; border-radius: 12px;
  background: color-mix(in oklab, var(--danger, #e5484d) 9%, transparent);
  border: 1px solid color-mix(in oklab, var(--danger, #e5484d) 22%, transparent);
}
.ba-ov__painh {
  margin: 0 0 4px; font-size: 11.5px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--danger, #e5484d);
}
.ba-ov__painrow { margin: 2px 0 0; font-size: 14px; color: var(--ink); }

/* BEWEGINGSANALYSE-NAAR-SCHEMA — the proposal button is the primary action and
   owns its own row; retest + report sit under it as a secondary pair. */
.ba-ov__next { margin-top: var(--space-5); display: flex; flex-direction: column; gap: 10px; }
.ba-ov__toschema {
  width: 100%; padding: 14px 0; border-radius: 999px; font-size: 15px;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
}
.ba-ov__hint { margin: -2px 0 0; color: var(--muted); font-size: 12.5px; line-height: 1.45; }
.ba-ov__acts { display: flex; flex-wrap: wrap; gap: 10px; }
.ba-ov__acts > * { flex: 1 1 40%; }

/* GYM-CARS-DAGRITME — the day-task sheet. Plain rows: a joint is a checkbox
   carrying the exact line the client will read, so nothing is a surprise. */
.ba-dt__lead { margin: 0 0 var(--space-4); font-size: 14px; color: var(--muted); }
.ba-dt__joints { display: flex; flex-direction: column; gap: 2px; }
.ba-dt__joint {
  display: flex; align-items: center; gap: 10px; padding: 9px 0;
  border-bottom: 1px solid var(--line-2); font-size: 14px; color: var(--ink);
  cursor: pointer;
}
.ba-dt__joint:last-child { border-bottom: 0; }
.ba-dt__jname { flex: 1; }
.ba-dt__pills { display: flex; flex-wrap: wrap; gap: 8px; }
.ba-dt__pills > * { flex: 1 1 30%; }
.ba-dt__pill { padding: 10px 0; font-size: 14px; }
.ba-dt__pill[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); }
.ba-dt__save {
  width: 100%; margin-top: var(--space-5); padding: 13px 0;
  border-radius: 999px; font-size: 15px; color: var(--on-accent);
}
.ba-ov__cadenceh {
  margin: 0 0 4px; font-size: 12.5px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--muted);
}

/* ── when do we measure again (BEWEGINGSANALYSE-HERTEST-CADANS) ── */
.ba-ov__cadence { margin-top: var(--space-5); }
.ba-ov__cadencepills { display: flex; gap: 8px; }
.ba-ov__cadencepills > * { flex: 1; }
.ba-ov__cadencepill { padding: 10px 0; font-size: 14px; }
.ba-ov__cadencewhen { margin: 8px 0 0; font-size: 13px; color: var(--muted); }

/* ── zet de hertest in je eigen agenda (HERTEST-ZET-IN-JE-AGENDA) ──
   Twee knoppen naast elkaar op een telefoon van 390px, en op 320px onder
   elkaar: "Add to Google Calendar" naast "Add to Apple Calendar" past daar
   niet zonder de tekst af te kappen, en een afgekapt label op een knop die
   een bestand downloadt laat de coach gokken welke agenda hij raakt. */
.ba-ov__cadenceagenda { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.ba-ov__cadencecal {
  flex: 1 1 150px; display: inline-flex; align-items: center; justify-content: center;
  gap: 7px; padding: 10px 12px; font-size: 13.5px; line-height: 1.15;
}
.ba-ov__cadencewarn { margin: 8px 0 0; font-size: 12.5px; color: var(--muted); }

/* ── retest: the first reading stays in view ── */
.ba-was {
  margin: 10px 0 0; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 8px 10px; border-radius: 10px; background: var(--bg); border: 1px solid var(--line-2);
}
.ba-was__lab { font-size: 11.5px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.ba-was__v { font-size: 14px; font-weight: 700; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.ba-was__g { font-size: 12.5px; color: var(--muted); }

/* The forward arrow on the last movement is the way out, so it reads as one. */
.ba-nav.is-finish { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }

/* ── report ── */
.ba-rep__bar { display: flex; align-items: center; gap: 8px; padding: 4px 0 10px; }
.ba-rep__bartitle { font-size: 15px; font-weight: 700; }

.ba-rep {
  padding: 22px 20px 26px; border: 1px solid var(--line-2); border-radius: 14px;
  background: var(--surface); color: var(--ink);
}
.ba-rep__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; }
.ba-rep__brand {
  display: block; font-size: 11px; font-weight: 700; letter-spacing: .22em; color: var(--accent);
}
.ba-rep__title { margin: 4px 0 0; font-size: 23px; line-height: 1.1; letter-spacing: -.01em; }
.ba-rep__meta { display: flex; flex-direction: column; align-items: flex-end; text-align: right; gap: 1px; }
.ba-rep__metaname { font-size: 13.5px; font-weight: 700; }
.ba-rep__metaline { font-size: 12px; color: var(--muted); }

/* Client language, not coach language: the course warns about the words you
   bring findings in, so this paragraph describes and stops. */
.ba-rep__intro {
  margin: 16px 0 0; padding: 12px 14px; border-radius: 10px;
  background: color-mix(in oklab, var(--accent) 7%, transparent);
  font-size: 13.5px; line-height: 1.5; color: var(--ink-2);
}
.ba-rep__joint { margin-top: 20px; }
.ba-rep__jname {
  margin: 0 0 6px; font-size: 11.5px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--accent);
}
/* L227 fase 4 — SINDS WANNEER staan deze getallen hier. Op papier is dit geen
   luxe: een getal van augustus naast een getal van oktober is zonder deze regel
   niet van elkaar te onderscheiden. Direct onder de gewrichtsnaam, klein. */
.ba-rep__jdates { margin: -2px 0 5px; font-size: 10.5px; color: var(--muted); }
.ba-rep__hinge { margin: 3px 0 0; font-size: 13px; color: var(--ink-2); }
.ba-rep__tbl { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.ba-rep__tbl th, .ba-rep__tbl td { padding: 5px 6px; }
/* GYM-HET-BEWEGINGSRAPPORT-TOONT-JE-NOTITIES (L236) — de notitie INLINE onder
   haar eigen rij, over de volle tabelbreedte. Gedempt en klein: dit is proza van
   de coach naast getallen, geen markering. */
.ba-rep__tbl tr.has-note td, .ba-rep__tbl tr.has-note th { padding-bottom: 1px; }
.ba-rep__noterow td { padding: 0 6px 6px; }
.ba-rep__rownote {
  font-size: 11.5px; line-height: 1.4; color: var(--muted);
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.ba-rep__rownote__line { display: block; }
.ba-rep__rownote__line > b { font-weight: 600; color: var(--ink-2); margin-right: 4px; }
.ba-rep__rownote__on { margin-left: 4px; white-space: nowrap; }
.ba-rep__thside {
  font-size: 11px; font-weight: 700; color: var(--ink-2); text-align: center;
  border-bottom: 1px solid var(--line-2);
}
.ba-rep__thsub {
  font-size: 9.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); text-align: right;
}
.ba-rep__thmv { width: 40%; }
.ba-rep__mv { text-align: left; font-weight: 500; color: var(--ink); }
.ba-rep__n { text-align: right; font-variant-numeric: tabular-nums; color: var(--ink-2); }
/* Quiet on purpose. A loud marking would be a verdict, and there is no verdict
   here — only a difference of more than twenty degrees. */
.ba-rep__n.is-hi {
  background: color-mix(in oklab, var(--warn, #d08700) 15%, transparent);
  color: var(--ink); font-weight: 700;
}
.ba-rep__legend {
  margin: 16px 0 0; display: flex; align-items: flex-start; gap: 7px;
  font-size: 11.5px; line-height: 1.45; color: var(--muted);
}
.ba-rep__swatch {
  width: 11px; height: 11px; flex: 0 0 auto; margin-top: 2px; border-radius: 3px;
  background: color-mix(in oklab, var(--warn, #d08700) 30%, transparent);
}
.ba-rep__notes:empty { display: none; }
.ba-rep__notes { margin-top: 18px; }
.ba-rep__note { margin: 3px 0 0; font-size: 12.5px; color: var(--ink-2); line-height: 1.45; }
.ba-rep__foot {
  margin: 18px 0 0; padding-top: 10px; border-top: 1px solid var(--line-2);
  font-size: 11px; color: var(--muted);
}

.ba-rep__acts { margin-top: var(--space-4); display: flex; flex-direction: column; gap: 10px; align-items: center; }
.ba-rep__share { width: 100%; display: flex; align-items: center; justify-content: center; gap: 8px; }
.ba-rep__optin { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--ink-2); }
.ba-rep__optinbox { width: 17px; height: 17px; accent-color: var(--accent); }

/* ── BEWEGINGSANALYSE-NAAR-SCHEMA — the concept in the schema-build panel ──
   Follows _MOCK_bewegingsanalyse_naar_schema_{light,dark}_v1.png. The concept
   takes the panel over; the sheet iframe is HIDDEN here, never removed, because
   detaching an iframe destroys its browsing context and forces a reload. */
.cide__panel--concept .cide__frame { display: none; }
/* BEWEGINGSANALYSE-CONCEPT-OP-DE-TELEFOON — the schema panel body clips its
   overflow (it exists to hold a full-height iframe), so a taller concept had its
   bottom button row cut off with no way to scroll to it. Make the body a flex
   column while the concept lives there, so cs-screen's own scroller gets a
   bounded height instead of growing past the clip. */
.cide__panel--concept .cide__panel-body { display: flex; flex-direction: column; }
.cide__panel--concept .cs-screen { flex: 1 1 auto; }

/* ── SCHEMA-SCHRIJVEN-KAN-OP-JE-TELEFOON-STAP-EEN — het leesvlak ──
   Onder 768px staat er ÉÉN paneel op het scherm, en het schema-vak toont de
   strength-iframe: die schrijft het PROGRAMMA, niet het concept. Een klaarstaand
   concept was daar dus onzichtbaar en publiceerde de coach blind. Het leesvlak
   neemt dat vak over zolang er een concept met oefeningen open staat. Vanaf
   768px verandert er niets: daar is de iframe de werkplek, en het leesvlak
   blijft uit beeld (display:none in de basisregel). */
.cspv {
  display: none; flex-direction: column; flex: 1 1 auto; min-height: 0;
  padding: 0 14px 14px; overflow-y: auto;
}
@media (max-width: 767px) {
  .cide__panel--preview .cide__frame { display: none; }
  .cide__panel--preview .cide__panel-body { display: flex; flex-direction: column; }
  .cide__panel--preview .cspv { display: flex; }
}
.cspv__head {
  margin-top: 14px; padding: 14px 14px 12px; border-radius: 12px;
  background: color-mix(in oklab, var(--accent) 8%, transparent);
  border: 1px solid color-mix(in oklab, var(--accent) 22%, transparent);
}
.cspv__badge {
  display: inline-block; font-size: 10.5px; font-weight: 800; letter-spacing: .09em;
  text-transform: uppercase; color: var(--on-accent); background: var(--accent);
  padding: 3px 8px; border-radius: 999px;
}
.cspv__t { margin: 8px 0 4px; font-size: 17px; letter-spacing: -.01em; color: var(--ink); }
.cspv__sub { margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--ink-2); }
.cspv__list { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
.cspv__row {
  display: flex; flex-direction: column; gap: 2px;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: 12px; background: var(--surface);
}
.cspv__name { font-size: 14px; font-weight: 700; color: var(--ink); line-height: 1.25; }
.cspv__set { font-size: 12.5px; color: var(--ink-2); }

.cs-screen { display: flex; flex-direction: column; min-height: 0; padding: 0 14px 14px; overflow-y: auto; }

.cs-lede {
  margin-top: 14px; padding: 14px 14px 12px; border-radius: 12px;
  background: color-mix(in oklab, var(--accent) 8%, transparent);
  border: 1px solid color-mix(in oklab, var(--accent) 22%, transparent);
}
.cs-lede__badge {
  display: inline-block; font-size: 10.5px; font-weight: 800; letter-spacing: .09em;
  text-transform: uppercase; color: var(--on-accent); background: var(--accent);
  padding: 3px 8px; border-radius: 999px;
}
.cs-lede__t { margin: 8px 0 4px; font-size: 17px; letter-spacing: -.01em; color: var(--ink); }
.cs-lede__sub { margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--ink-2); }

.cs-list { display: flex; flex-direction: column; gap: 10px; margin-top: 14px; }
.cs-empty { margin: 0; font-size: 13px; color: var(--muted); }
.cs-card { border: 1px solid var(--line); border-radius: 12px; background: var(--surface); padding: 12px 12px 10px; }
.cs-card__head { display: flex; align-items: center; gap: 8px; }
.cs-card__grip { color: var(--muted); display: flex; flex: none; }
/* svgIcon draws stroke-only; the grip is the one icon that wants solid dots. */
.cs-card__grip svg circle { fill: currentColor; stroke: none; }
.cs-card__title { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.2; }
.cs-card__name { margin: 0; font-size: 14px; font-weight: 700; color: var(--ink); line-height: 1.25; }
.cs-card__ops { display: flex; align-items: center; gap: 6px; flex: none; }
.cs-op {
  display: inline-flex; align-items: center; gap: 5px; padding: 6px 10px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-2);
  font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
}
.cs-op svg { color: var(--ink-2); }
.cs-op--danger { padding: 6px 8px; color: var(--danger); border-color: color-mix(in oklab, var(--danger) 35%, var(--line)); }
.cs-op--danger svg { color: var(--danger); }
/* Why-line: muted, small, with an accent rule down the left, so it reads as
   context the coach may skip — never as a heading. */
.cs-why {
  margin: 8px 0 0; padding: 6px 0 6px 10px; font-size: 12.5px; line-height: 1.4; color: var(--ink-2);
  border-left: 2px solid color-mix(in oklab, var(--accent) 55%, transparent); font-style: italic;
}
.cs-card__body { margin: 8px 0 0; display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.cs-set { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* SCHEMA-IMPORT-PLAK-JE-SCHEMA-OF-UPLOAD-DE-PDF — the suggestions under an
   uncertain imported name. One tap replaces the name; nothing else changes. */
.cs-sugs { margin: 6px 0 0; display: flex; flex-wrap: wrap; gap: 6px; }
.cs-sug {
  padding: 5px 10px; border-radius: 999px; border: 1px solid var(--line);
  background: transparent; color: var(--ink-2); font: inherit; font-size: 12.5px; cursor: pointer;
}
.cs-sug:hover { border-color: var(--accent); color: var(--ink); }

.cs-add {
  margin: 12px 0 0; padding: 11px 0; border-radius: 12px; border: 1px dashed var(--line);
  background: transparent; color: var(--ink-2); font: inherit; font-size: 13px; font-weight: 600;
  display: flex; align-items: center; justify-content: center; gap: 6px; cursor: pointer;
}

.cs-acts { margin-top: auto; padding: 16px 0 4px; display: flex; gap: 10px; }
.cs-acts .cbtn { flex: 1; padding: 14px 0; border-radius: 999px; font-size: 14.5px; }

/* ── print: the share sheet turns THIS into the PDF ──
   Strip every piece of app furniture and let the report be a document. Colours
   are forced to print-adjust:exact so the 20°-marking survives, because without
   it the legend line refers to a shading the client cannot see. */
@media print {
  @page { size: A4 portrait; margin: 14mm 12mm; }

  html, body {
    background: #fff !important; color: #000 !important;
    height: auto !important; overflow: visible !important;
    /* body.has-coachnav pads the bottom for the tabbar that is now hidden. */
    padding: 0 !important; margin: 0 !important;
  }
  /* The coach shell is a fixed-height flex column with its own scrollers; on
     paper every one of those has to stop being a box with a height. */
  #coach, .cmain, .ba-main, .ba-screen, .ba-repwrap {
    position: static !important; display: block !important;
    height: auto !important; max-height: none !important; min-height: 0 !important;
    overflow: visible !important; padding: 0 !important; margin: 0 !important;
  }
  /* Anything that is not the report itself. Class names verified against
     shellHeader() / buildTabbar() / coachToast() — a print rule that hides a
     selector nobody emits is a rule that silently does nothing. */
  .cshell, .csearch, .coachnav, .csheet, .ctoast,
  .ba-rep__bar, .ba-rep__acts, .ba-ov__head { display: none !important; }

  .ba-rep {
    border: 0 !important; border-radius: 0 !important; padding: 0 !important;
    background: #fff !important; color: #000 !important;
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
  .ba-rep__brand, .ba-rep__jname { color: #0b6b62 !important; }
  .ba-rep__intro {
    background: #f2f6f5 !important; color: #333 !important;
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
  .ba-rep__n.is-hi {
    background: #fbedd0 !important; color: #000 !important;
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
  .ba-rep__swatch {
    background: #fbedd0 !important; border: 1px solid #d9b76a !important;
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
  /* A joint's table split across two sheets loses its header and stops being
     readable, so a joint is kept whole. */
  .ba-rep__joint { break-inside: avoid; page-break-inside: avoid; }
  .ba-rep__legend, .ba-rep__foot { color: #555 !important; }
  /* L236 — op papier leest de notitie als grijs-op-wit, en hij mag nooit van
     zijn eigen rij afgescheurd worden door een bladovergang. */
  .ba-rep__rownote { color: #555 !important; }
  .ba-rep__noterow, .ba-rep__tbl tr.has-note { break-inside: avoid; page-break-inside: avoid; }
}

/* ───── GELD-TAB-TRAININ-LAYOUT-BASIS — chronological money list ─────
   The colour rule is the whole point of this block: --danger belongs to ONE
   state, a bill that is actually past its due date. A planned instalment on the
   1st of the month is neutral grey and a failed one is amber WITH a sentence,
   because a screen that is red every month start is a screen nobody reads. */

/* GELD-TWEE-DEUREN-OVERZICHT-EN-KLANTEN — two doors on top, the lenses as chips
   underneath. The row of secondary underlined links is gone. */
/* GELD-EEN-KOP-IN-PLAATS-VAN-VIER-LAGEN — er plakt nog PRECIES EEN rij: de
   chips. Kop en periodeknop scrollen mee, want die lees je één keer bij het
   openen; de chips gebruik je onderweg. Vier plakkende lagen aten 24% van een
   telefoon op voordat er een bedrag in beeld kwam. */
.cfin-lens {
  position: sticky; top: calc(env(safe-area-inset-top, 0px) + 40px + var(--space-2) * 2 + 1px);
  z-index: 5; background: var(--bg);
  /* 44px tikdoel + 3px lucht = 47px. Het plakkende blok mag niet boven 48px
     uitkomen: elke pixel hier is een pixel die de lijst NOOIT krijgt. */
  padding: 0 0 3px;
}
/* De onderste marge zou buiten de plakkende achtergrond vallen en de lijst
   eronder door laten schemeren. */
.cfin-lens > *:last-child { margin-bottom: 0; }

/* De rij schuift horizontaal weg in plaats van naar een tweede regel te
   springen: een plakkend blok dat van hoogte verandert duwt de lijst eronder
   op en neer terwijl je leest. */
.cfin-chips {
  display: flex; gap: 8px; margin: 0; align-items: center;
  overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.cfin-chips::-webkit-scrollbar { display: none; }
.cfin-chips__btn {
  border: 1px solid var(--line); background: var(--surface); color: var(--ink);
  border-radius: var(--radius-pill); padding: 0 var(--space-4); height: 44px; flex: 0 0 auto;
  font-size: 14px; font-weight: 600;
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
}
/* Een aangetikte chip is een filter, geen hoofdactie — een volvlak accent zou
   hem net zo hard laten roepen als de knoppen die echt iets doen. Gevulde
   accentknoppen elders houden --on-accent. */
.cfin-chips__btn.is-on {
  background: color-mix(in srgb, var(--accent) 16%, var(--surface));
  color: var(--accent); border-color: var(--accent);
}

/* 'Beheer ›' is geen filter over de lijst maar een uitstap naar andere
   schermen, dus hij draagt bewust geen chip-vorm. */
.cfin-chips__manage {
  margin-left: auto; flex: 0 0 auto; border: 0; background: none; cursor: pointer;
  color: var(--muted); font: inherit; font-size: 14px; font-weight: 600;
  height: 44px; padding: 0 var(--space-2);
  display: inline-flex; align-items: center; gap: 2px;
}
.cfin-chips__manage svg { stroke: currentColor; }

.cfin-periodbtn {
  margin-left: auto; border: 0; background: none; cursor: pointer;
  color: var(--muted); font: inherit; font-size: 14px; font-weight: 600;
  min-height: 44px; padding: 0 var(--space-2);
  display: inline-flex; align-items: center; gap: 2px;
}
.cfin-periodbtn__caret { stroke: currentColor; transform: rotate(90deg); }

.cfin-menu__row {
  width: 100%; display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3); min-height: 48px; padding: var(--space-3) 0;
  border: 0; border-bottom: 1px solid var(--line); background: none;
  color: var(--ink); font: inherit; font-size: 15px; cursor: pointer; text-align: left;
}
.cfin-menu__row svg { stroke: currentColor; opacity: .5; }
.cfin-menu__row.is-on { color: var(--accent); font-weight: 700; }
.cfin-menu__head {
  margin-top: var(--space-4); padding-bottom: var(--space-2);
  color: var(--muted); font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
}
.cfin-menu__custom { display: flex; gap: var(--space-2); margin-top: var(--space-3); }

/* GELD-DE-ADMINISTRATIEPOORT-SLIKT-NIET-DE-HELE-TAB — de deuren die open zijn
   als de administratie dicht zit, als gewone rijen op de pagina. Ze lenen de
   rij-stijl van het Beheer-blad zodat het dezelfde deuren blijven. */
.cadmin-doors { margin-top: var(--space-4); }
.cadmin-doors__pill {
  margin-left: auto; padding: 2px var(--space-2); border-radius: 999px;
  border: 1px solid var(--accent); color: var(--accent); background: none;
  font-size: 12px; font-weight: 700; white-space: nowrap;
}
.cadmin-seatnote { margin-top: var(--space-4); color: var(--muted); font-size: 14px; }
.client-search--fin { margin-top: var(--space-3); }

.cfin-period__date {
  font: inherit; font-size: 14px; padding: var(--space-3) var(--space-2);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink);
}

/* The health of the practice. Read before the month's money, so the label sits
   above the figure: the coach is scanning for what the number IS, not for a
   value he then has to go and identify. */
.cfin-kpi {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3);
  padding: var(--space-3); margin-bottom: var(--space-3);
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--radius);
}
.cfin-kpi__sub { font-size: 12px; color: var(--ink-2); }
/* GELD-ONTVANGEN-IS-WAT-JE-HIELD — de regel die zegt WAAROVER de drie getallen
   eronder gaan. Gedempt en klein: hij hoort bij de kop erboven, hij is geen
   vierde cijfer. */
.cfin-kpi__scope { margin: 0; font-size: 13px; color: var(--ink-2); }
/* GELD-DE-CIJFERS-TELLEN-KLANTEN-NIET-ABONNEMENTEN — "4 nieuw" en "42 zonder
   betaalafspraak" staan NAAST de drie cijfers, niet erin: ze zitten met opzet
   buiten de noemer en mogen dus niet als vierde tegel meelezen. Zelfde gedempte
   maat als de sub-regel, en over de volle breedte van het raster. */
.cfin-kpi__aside {
  grid-column: 1 / -1; margin: 0; font-size: 12px; color: var(--ink-2);
}
.cfin-kpi__names {
  grid-column: 1 / -1; margin: 0; padding-left: var(--space-4);
  font-size: 12px; color: var(--ink-2);
  display: grid; gap: var(--space-1);
}
/* GELD-EEN-GETAL-WINT — in een blad is er geen breedte voor drie kolommen. */
.cfin-kpi--sheet {
  grid-template-columns: minmax(0, 1fr); gap: var(--space-3);
  background: none; border: 0; padding: var(--space-3) 0; margin: 0;
}

/* GELD-DE-KLEINE-FOUTEN-EERST — de uitweg achter een foutzin. Tekstknop, geen
   accentvlak: hij hoort bij de zin en mag die niet overstemmen. */
.cfin-retry {
  background: none; border: 0; padding: 0; margin: 0; cursor: pointer;
  font: inherit; font-weight: 600; color: var(--accent);
  text-decoration: underline; text-underline-offset: 2px;
}

/* GELD-EEN-GETAL-WINT — ÉÉN stat-vorm voor de hele Geld-tab. Label boven, waarde
   eronder; het gewicht zit in de modifier en nergens anders, zodat twee bedragen
   naast elkaar nooit per ongeluk even zwaar wegen. */
.cstat { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cstat__lbl {
  font-size: 12px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted);
}
.cstat__val {
  color: var(--ink); font-variant-numeric: tabular-nums; line-height: 1.1;
}
/* 36px tegenover 20px: de verhouding moet groot genoeg zijn dat het oog het
   hero-bedrag ziet zonder te lezen. Op 32px was dat 1,6× en dat leest als
   "iets groter", niet als "dit is het antwoord". */
.cstat--hero .cstat__val { font-size: 36px; font-weight: 700; }
.cstat--sm   .cstat__val { font-size: 20px; font-weight: 700; }
.cstat--xs   .cstat__val { font-size: 14px; font-weight: 600; }
.cstat--danger .cstat__val { color: var(--danger); }

.cfin-hero {
  padding: var(--space-3); margin-bottom: var(--space-3);
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--radius);
}
.cfin-hero__pair { display: flex; gap: var(--space-4); margin-top: var(--space-3); }
.cfin-hero__pair .cstat { flex: 1; }
/* GELD-OPENSTAAND-IS-EEN-SALDO-GEEN-PERIODE — één regel onder de bedragen, want
   de periodekiezer staat er pal boven en Openstaand luistert er niet naar. */
.cfin-hero__scope {
  margin: var(--space-2) 0 0; font-size: 14px; color: var(--ink-2);
}
.cfin-hero__foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3);
  margin-top: var(--space-3); padding-top: var(--space-3);
  border-top: 1px solid var(--line-2);
}
.cfin-hero__vat {
  flex: 1; min-width: 0; font-size: 14px; color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.cfin-hero__foot .cfin-linkbtn:first-child { margin-right: auto; }
.cfin-linkbtn {
  background: none; border: 0; padding: 0; margin: 0; cursor: pointer;
  font: inherit; font-size: 14px; font-weight: 600; color: var(--accent);
  display: inline-flex; align-items: center; gap: 2px;
}

/* GELD-DE-FACTUUR-AAN-EEN-COLLEGA-TELT-MEE — wat je een collega moet, onder het
   hero. Geen kaartvlak zoals .cfin-hero: dit blok mag nooit even zwaar wegen als
   het bedrag erboven. Eén regel met kop en bedrag, en de rijen eronder in de
   gewone lijstvorm, zodat een factuur hier precies leest als een factuur daar.
   De marge staat op de kop en niet op het blok zelf: een leeg blok (de regel op
   prod, niet de uitzondering) hoort GEEN ruimte te laten staan tussen het hero
   en wat eronder komt. */
.cfin-pdue__head {
  display: flex; align-items: baseline; gap: var(--space-2);
  margin-bottom: var(--space-2);
}
.cfin-pdue__title {
  flex: 1; min-width: 0;
  font-size: 12px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted);
}
.cfin-pdue__amt {
  font-size: 20px; font-weight: 700; color: var(--ink);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.cfin-pdue__late {
  margin: 0 0 var(--space-2); font-size: 14px; color: var(--danger);
  font-variant-numeric: tabular-nums;
}
.cfin-pdue .cfin-list { margin-bottom: var(--space-4); }

/* GELD-EEN-GETAL-WINT — de enige strook die om een handeling vraagt. --danger-bg
   bestaat niet, dus de vlakvulling en de tekstkleur worden hier gemengd. */
.cfin-alert {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3); margin-bottom: var(--space-3);
  border-radius: var(--radius); font-size: 14px; font-weight: 600;
  background: color-mix(in srgb, var(--danger) 12%, transparent);
  color: color-mix(in srgb, var(--danger) 78%, var(--ink));
}
.cfin-alert__txt { flex: 1; min-width: 0; }
.cfin-alert__btn {
  background: none; border: 0; padding: 0; margin: 0; cursor: pointer;
  font: inherit; font-weight: 700; color: inherit;
  display: inline-flex; align-items: center; gap: 2px; white-space: nowrap;
}

.cfin-vatsheet { display: flex; gap: var(--space-4); padding: var(--space-3) 0; }
.cfin-vatsheet .cstat { flex: 1; }
.cfin-vatsheet__note { margin: 0 0 var(--space-2); font-size: 13px; color: var(--ink-2); }
/* GELD-ONTVANGEN-IS-WAT-JE-HIELD — de NAAM van het btw-begrip, boven de twee
   bedragen en met het gewicht van de zin die je eerst leest. Donkerder en
   zwaarder dan de toelichting eronder: die legt uit, deze benoemt. */
.cfin-vatsheet__head { margin: 0; font-size: 14px; font-weight: 600; color: var(--ink); }

.cfin-planned {
  margin-bottom: var(--space-4); padding-bottom: var(--space-2);
  /* GELD-RUIMTE-EN-MARGES — was 2px, de zwaarste lijn van de tab terwijl hij
     niets structureels scheidt; hij leest als een gewone scheiding. */
  border-bottom: 1px solid var(--line-2);
}
/* GELD-DE-LIJST-LEEST-ALS-EEN-BANKAPP — de kop draagt dezelfde vorm als de
   koppen in de historie (.cfin-list__dh) en leest als ÉÉN regel: het bedrag is
   geen tweede kolom aan de overkant maar hoort bij het woord ervoor. */
.cfin-planned__head {
  justify-content: flex-start; padding: 0 var(--space-4) var(--space-2);
}
.cfin-planned__title { font: inherit; color: inherit; }
.cfin-planned__exp { font: inherit; color: inherit; font-variant-numeric: tabular-nums; }

/* GELD-RUIMTE-EN-MARGES — het grootste en meest gelezen blok van de tab stond
   als enige kaal op de paginakleur, naast de totalen en de klantenlijst die wél
   op een kaart staan; en zijn rijtekst begon 8px van de rand tegen 12px erboven,
   een zichtbare trapjes-fout. */
.cfin-list {
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line-2);
  border-radius: var(--radius); overflow: hidden;
}
/* GELD-DE-LIJST-LEEST-ALS-EEN-BANKAPP — de telefoonstand is de basis: twee
   kolommen, twee regels elk. Links wie en waarvoor, rechts hoeveel en hoe het
   staat. Het vijfkoloms-raster stapelde hieronder tot datum, omschrijving en
   status om dezelfde ruimte vochten, met een derde regel eronder die het ritme
   brak. Er is nu precies ÉÉN regelset per stand. */
.cfin-row {
  display: grid; align-items: center; width: 100%;
  column-gap: var(--space-3); row-gap: 2px;
  grid-template-columns: minmax(0, 1fr) auto;
  padding: var(--space-3) var(--space-4); text-align: left;
  background: none; border: 0;
  font: inherit; color: var(--ink); cursor: pointer;
}
.cfin-row:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); }
/* REVIEW-GELD-EN-AFSPRAKEN-LANDEN-OP-HUN-BLAD (L212) — de rij die de knop op
   een Review-kaart aanwees. Een gekleurde ondergrond plus een streep aan de
   kop: geen extra doos om de rij heen (L183), dus ook geen tweede padding. */
.cfin-row--focus {
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  box-shadow: inset 3px 0 0 0 var(--accent);
}
/* Laad- en leegteksten hangen los in de lijst en zouden zonder dit op de rand
   van de kaart beginnen. */
.cfin-list > .cpay__loading,
.cfin-list > .cpay__empty,
.cfin-list > .cpay__note { padding: var(--space-3) var(--space-4); margin: 0; }
.cfin-row__client {
  font-size: 16px; font-weight: 600; color: var(--ink);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Omschrijving én datum in één span: zo kort de ZIN in als hij niet past, in
   plaats van dat twee cellen elkaar wegdrukken. */
.cfin-row__sub {
  font-size: 13px; color: var(--muted);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cfin-row__amt {
  font-size: 16px; font-weight: 700;
  font-variant-numeric: tabular-nums; text-align: right;
}
.cfin-row__status {
  font-size: 12px; text-align: right; justify-self: end;
  display: flex; gap: 4px; align-items: center; justify-content: flex-end;
}

/* De koppen die de randen vervangen. Niet plakkend: een blok dat meescrollt en
   van inhoud wisselt trekt het oog weg van de rij die je aan het lezen bent. */
.cfin-list__dh {
  display: flex; align-items: baseline; gap: 6px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--muted); margin: var(--space-4) 0 var(--space-2);
}
.cfin-list__dh--in { margin: 0; padding: var(--space-2) var(--space-4) 2px; }

/* Vanaf de tablet is er ruimte voor een echte tabel, en dan leest een kolom
   sneller dan twee regels. `display: contents` zet omschrijving en datum terug
   als eigen kolommen; de kolommen worden expliciet genummerd omdat de DOM-orde
   (naam eerst) niet de leesvolgorde van de tabel is. De statuskolom houdt een
   minimum, anders springt hij per rij met de lengte van het statuswoord. */
@media (min-width: 768px) {
  .cfin-row {
    grid-template-columns: 108px minmax(0, 1.1fr) minmax(0, 1.5fr) minmax(104px, auto) minmax(0, 0.7fr);
    row-gap: 0;
  }
  .cfin-row__sub { display: contents; }
  .cfin-row__sep { display: none; }
  .cfin-row__date { grid-column: 1; font-size: 13px; color: var(--muted); }
  .cfin-row__client { grid-column: 2; }
  .cfin-row__desc {
    grid-column: 3; font-size: 14px; color: var(--ink-2);
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .cfin-row__status { grid-column: 4; justify-self: start; justify-content: flex-start; text-align: left; }
  .cfin-row__amt { grid-column: 5; }
}

/* On a phone the three figures stack rather than shrink: the sub-text is the
   half that makes the number mean anything, and it is the half that dies first
   when a cell is squeezed to a third of a narrow screen. */
@media (max-width: 479px) {
  .cfin-kpi { grid-template-columns: minmax(0, 1fr); gap: var(--space-2); }
  /* KLANTENRIJ-NAAM-EERST-OP-DE-TELEFOON — dezelfde regel als op Klanten: de
     naam levert niet in. GEMETEN op 375px met 'Mariette van der Waterlanden'
     en € 1495,50: de naamkolom was 214px en de naam had 224px nodig — tien
     pixels te kort, en dan verdwijnt de laatste lettergreep.
     De tien pixels komen NIET uit de rechterkolom: die is 82px en wordt
     gedragen door het BEDRAG (83px), niet door het statuslabel (55px), en een
     half bedrag is geen bedrag. Ze komen uit de ruimte die audit L183 §3.2
     toch al als te grof aanwijst: 16px zijrand en 12px kolomgat op een
     telefoon van 375px. 16 → 12 per kant en 12 → 4 kolomgat geeft 16px terug:
     230px gemeten, voor een naam die er 224 nodig heeft — 6px lucht. Dat is
     bewust meer dan de 10px die het geval vroeg: met alleen de zijrand kwam de
     meting op 226 uit, en een poort die op 2px overleeft valt bij de eerste
     andere letterweergave om — dan repareert de volgende bouwer de poging in
     plaats van de poort.
     Het kolomgat mag naar 4px omdat het BEDRAG rechts uitlijnt in zijn eigen
     82px-kolom: de witruimte die je ziet staat tussen het einde van de naam en
     het begin van het getal, en die is in elke rij behalve de allerlangste
     naam tientallen pixels groot.
     De dagkoppen en de laad-/leegteksten verschuiven MEE: zij staan hier
     alleen omdat ze op de rijrand uitlijnen, en een kop die 4px uitsteekt is
     zichtbaarder dan de winst. */
  .cfin-row { padding-inline: var(--space-3); column-gap: var(--space-1); }
  .cfin-list__dh--in,
  .cfin-list > .cpay__loading,
  .cfin-list > .cpay__empty,
  .cfin-list > .cpay__note { padding-inline: var(--space-3); }
}

.cfin-status {
  display: inline-block; padding: 2px var(--space-2); border-radius: var(--radius-pill);
  font-size: 12px; font-weight: 600; white-space: nowrap;
  background: color-mix(in srgb, var(--muted) 16%, transparent); color: var(--ink-2);
}
/* GELD-DE-LIJST-LEEST-ALS-EEN-BANKAPP — kleur alleen bij afwijking. Betaald is
   wat de meeste rijen zijn: als die groen dragen, valt rood niet meer op. Alle
   gekleurde chips volgen nu ÉÉN recept (14% achtergrond, 78% tekst), zodat de
   kleur die je ziet ook echt het verschil tussen twee toestanden is. */
.cfin-status--overdue {
  background: color-mix(in srgb, var(--danger) 14%, transparent);
  color: color-mix(in srgb, var(--danger) 78%, var(--ink));
}
/* GELD-BETALING-BUITEN-DE-BOEKHOUDING — een neutraal label, geen alarm: buiten
   de boekhouding is een keuze van de coach, niet een probleem met de rij. */
.cfin-status--offbooks {
  background: transparent; color: var(--muted);
  border: 1px dashed var(--line-2); font-weight: 500;
}
.cpaysheet__src--offbooks { font-style: normal; }
/* GELD-DE-EERSTE-TERMIJN-MAG-BUITEN-DE-APP-BINNENKOMEN — net als off-books een
   neutraal label en geen alarm: de factuur bestaat, alleen niet bij ons. Een
   DOORGETROKKEN rand tegenover de streepjesrand van off-books, want dit is de
   rustiger van de twee: hier zit het geld gewoon in de boekhouding. */
.cfin-status--external {
  background: transparent; color: var(--muted);
  border: 1px solid var(--line-2); font-weight: 500;
}
/* GELD-OPENSTAAND-IS-EEN-SALDO-GEEN-PERIODE — een vervallen termijn is geen
   alarm en ook geen keuze van de coach: hij is simpelweg niet meer van deze
   tijd. Daarom als enige chip DOORGESTREEPT en gedempt, zodat je in één blik
   ziet dat dit bedrag nergens in meetelt. */
.cfin-status--expired {
  background: transparent; color: var(--muted);
  border: 1px solid var(--line-2); font-weight: 500;
  text-decoration: line-through;
}
.cfin-status--failed, .cfin-status--charged_back {
  background: color-mix(in srgb, var(--warn) 14%, transparent);
  color: color-mix(in srgb, var(--warn) 78%, var(--ink));
}
/* GELD-ONTVANGEN-IS-WAT-JE-HIELD — terugbetaald is geen alarm en geen fout: de
   coach heeft dit geld zelf teruggestuurd. Toch niet de neutrale grijstint van
   een gewone chip, want dit is de ENIGE rij op het scherm die een totaal omlaag
   haalt; hetzelfde recept als de andere gekleurde chips (14%/78%), in de
   waarschuwingskleur, zodat een min-bedrag opvalt zonder rood te schreeuwen. */
.cfin-status--refunded {
  background: color-mix(in srgb, var(--warn) 14%, transparent);
  color: color-mix(in srgb, var(--warn) 78%, var(--ink));
}
/* GELD-CREDITFACTUUR-DE-CIJFERS-EN-HET-DOSSIER — een creditfactuur is GEEN
   terugbetaling en mag er dus niet uitzien als een. De chip hierboven draagt de
   waarschuwingskleur omdat daar geld de rekening verliet; hier gebeurde dat
   niet, en de kleur zou de coach een kasmutatie laten zoeken die nergens staat.
   Gedempt met een randje, zoals elke chip die een FEIT over het document meldt
   in plaats van een toestand van het geld. */
.cfin-status--credited {
  background: transparent; color: var(--muted);
  border: 1px solid var(--line-2); font-weight: 500;
}
/* GELD-CREDITFACTUUR-DE-CIJFERS-EN-HET-DOSSIER — één creditfactuur in het
   dossier. Een leesregel en geen betaalrij: nummer en bedrag op de bovenste
   regel, datum en reden eronder in de gedempte kleur, en de pdf als enige
   uitgang. --warn blijft weg om dezelfde reden als bij de chip hierboven. */
.ccredoc {
  display: flex; flex-direction: column; gap: 2px;
  padding: 10px 2px; border-bottom: 1px solid var(--line-2);
}
.ccredoc__line { display: flex; justify-content: space-between; gap: 10px; align-items: baseline; }
.ccredoc__nr { font-weight: 600; }
.ccredoc__amt { font-variant-numeric: tabular-nums; font-weight: 600; }
.ccredoc__sub { margin: 0; color: var(--ink-2); font-size: 13px; }
.ccredoc__pdf { align-self: flex-start; margin-top: 6px; }
/* GELD-ONTVANGEN-IS-WAT-JE-HIELD — kwijtgescholden en overgeslagen tellen in
   GEEN enkel totaal, en dat moet je aan de rij kunnen zien. Ze droegen de
   standaard grijze chip, precies dezelfde als een rij die wél meetelt, en dan is
   de optelling boven de lijst niet na te rekenen. Gedempt en in dezelfde lijn
   als 'vervallen', want ze zeggen hetzelfde: dit bedrag komt nergens terug. */
.cfin-status--waived, .cfin-status--skipped {
  background: transparent; color: var(--muted);
  border: 1px solid var(--line-2); font-weight: 500;
}
/* BOEKHOUDING-TERUGWERKEND-EN-ZICHTBAAR-IN-GELD — ging deze factuur al naar de
   boekhouder? Verstuurd en wacht zijn de twee NORMALE uitkomsten, dus ze volgen
   de regel van dit scherm: kleur alleen bij afwijking. Hetzelfde stille recept
   als 'Factuur elders' — een gedempt randje, want dit is een feit over de
   factuur en geen toestand van het geld. Alleen tokens, dus licht en donker
   volgen vanzelf. */
.cfin-status--bkk {
  background: transparent; color: var(--muted);
  border: 1px solid var(--line-2); font-weight: 500;
}
/* Mislukt IS de afwijking: de ronde heeft het opgegeven en er komt niets meer
   aan bij de boekhouder tenzij een mens op 'opnieuw proberen' tikt. Zelfde
   14%/78%-recept als de andere gekleurde chips, in de waarschuwingskleur — niet
   in danger, want de factuur zelf is in orde; alleen de kopie ligt stil. */
.cfin-status--bkk-failed {
  background: color-mix(in srgb, var(--warn) 14%, transparent);
  color: color-mix(in srgb, var(--warn) 78%, var(--ink));
  border: 0; font-weight: 600;
}

.cfin-detail {
  position: fixed; inset: 0; z-index: 60;
  background: color-mix(in srgb, #000 45%, transparent);
  display: flex; justify-content: flex-end;
}
.cfin-detail__panel {
  width: min(420px, 100%); height: 100%; overflow-y: auto;
  background: var(--surface); border-left: 1px solid var(--line-2);
  display: flex; flex-direction: column;
  padding-bottom: calc(var(--space-4) + var(--safe-bottom));
}
.cfin-detail__top {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  padding: var(--space-4); border-bottom: 1px solid var(--line-2);
}
.cfin-detail__title { font-weight: 700; font-size: 16px; }
.cfin-detail__body { padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-3); }
.cfin-detail__head { display: flex; align-items: center; gap: var(--space-3); }
.cfin-detail__amt { font-size: 26px; font-weight: 700; font-variant-numeric: tabular-nums; }
.cfin-detail__note { margin: 0; font-size: 14px; color: var(--ink-2); }
.cfin-detail__fact {
  display: flex; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-2) 0; border-bottom: 1px solid var(--line-2); font-size: 14px;
}
.cfin-detail__fact-k { color: var(--muted); }
.cfin-detail__fact-v { text-align: right; word-break: break-all; }
.cfin-detail__acts { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-2); }
.cfin-detail__btn {
  font: inherit; font-weight: 600; padding: 10px var(--space-3); cursor: pointer;
  border: 1px solid var(--accent); border-radius: var(--radius);
  background: var(--accent); color: var(--on-accent);
}
.cfin-detail__btn--danger {
  background: none; border-color: var(--danger); color: var(--danger);
}
/* Opening a document is a secondary errand next to collecting money, so it
   never wears the accent. */
.cfin-detail__btn--ghost {
  background: none; border-color: var(--line-2); color: var(--ink);
}
/* GELD-CREDITFACTUUR-DE-KNOP (L203) — omlijnd en in de accentkleur, precies
   tussen de volle knop (dagelijks werk) en de grijze (bijzaak) in: een
   creditfactuur uitschrijven is een bewuste handeling, geen bijzaak en geen
   routine. De letter draagt --accent en niet --on-accent: die laatste is de
   kleur ÓP een gevulde accentvlak, en dit vlak is leeg. */
.cfin-detail__btn--outline {
  background: none; border-color: var(--accent); color: var(--accent);
}
/* GELD-DE-FACTUUR-GAAT-MET-EEN-TIK-NAAR-DE-KLANT — de verzenddatum hoort BIJ de
   knop, niet ernaast: hij verklaart waarom hij "opnieuw" heet. Een eigen regel
   onder het label, zodat de knop op 390 breed niet uitwaaiert. */
.cfin-detail__btn-sub {
  display: block; margin-top: 2px; font-size: 12px; font-weight: 500;
  color: var(--muted);
}
/* GELD-EEN-FOUTE-REKENING-KUN-JE-KWIJTSCHELDEN — het datumveld boven 'Betaling
   bevestigen'. WebKit geeft een date-input een eigen intrinsieke breedte en
   negeert de stretch van de kolom eromheen, dus zonder deze regel staat hij
   smal en links tussen knoppen die de volle breedte pakken. */
.cfin-detail__date { width: 100%; box-sizing: border-box; }

/* A failed payment used to explain itself only in a hover tooltip, which on a
   phone is no explanation at all. */
.cpay-sub__note { margin: 2px 0 0; font-size: 13px; color: var(--ink-2); }

/* GELD-DE-LIJST-LEEST-ALS-EEN-BANKAPP — onder de tabletgrens is dit een bottom
   sheet, LETTERLIJK het idioom van .csheet: elk ander blad in de coach-app komt
   van onderen, en dit ene schoof van rechts binnen. Boven 768px blijft het het
   zijpaneel dat naast de lijst staat. */
@media (max-width: 767.98px) {
  .cfin-detail { align-items: flex-end; justify-content: center; }
  /* GELD-DUIM-MAAT — een viewport-hoogte lost op iOS op naar de GROTE viewport,
     dus met de Safari-balk in beeld viel de knoppenrij onder de vouw. */
  .cfin-detail__panel {
    width: 100%; max-width: 520px; height: auto;
    max-height: min(80vh, var(--coach-vh, 80vh));
    border-left: 0; border-radius: var(--radius) var(--radius) 0 0;
  }
}

/* GELD-IPAD-GEBRUIKT-DE-BREEDTE — op een iPad was de Geld-tab een uitgerekte
   telefoon: honderden pixels dood onder de vouw, terwijl het detailpaneel als
   schermvullende modal OVER die lege helft opende. Vanaf 768px is het paneel
   een vaste rechterkolom en blijft de lijst er links naast leesbaar én
   klikbaar. Op de telefoon verandert er niets: daar blijft het een modal. */
@media (min-width: 768px) {
  :root { --fin-detail-w: min(420px, 40vw); }
  .cfin-detail {
    inset: 0 0 0 auto; width: var(--fin-detail-w);
    background: none;
    /* Geen sluier meer, dus ook geen vangnet voor kliks: alles wat de sluier
       vroeger opving hoort nu bij de lijst eronder. Het paneel zet dit terug. */
    pointer-events: none;
  }
  .cfin-detail__panel {
    width: 100%; pointer-events: auto;
    box-shadow: -8px 0 24px color-mix(in srgb, #000 12%, transparent);
  }
  /* De lijst schuift op zodat hij niet onder de kolom verdwijnt. */
  html:has(.cfin-detail) .cmain {
    padding-right: calc(var(--gutter) + var(--fin-detail-w) + var(--space-4));
  }
  /* De kaartenlijsten van Pakketten, de Klanten-deur en de facturenkasten
     halen hun scroll eruit door naast elkaar te staan. */
  .cmain > .cpay {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-4); align-items: start;
  }
  .cmain > .cpay > .cpay-card { margin-bottom: 0; }
  /* Laad-, leeg- en notitieteksten zijn geen kaart en horen over de volle
     breedte, anders lezen ze als een halve kolom naast niets. */
  .cmain > .cpay > :not(.cpay-card) { grid-column: 1 / -1; }
}

/* GELD-DE-LIJST-LEEST-ALS-EEN-BANKAPP — de derde stand (tablet MET paneel open,
   terug naar de telefoonstapel) is weg. Precies één regelset per stand: onder
   768px de twee kolommen, daarboven de tabel. Met het paneel open houdt de
   lijst op een iPad ~440px over; de omschrijvingskolom kort daar in, wat
   goedkoper is dan een derde vorm die apart gemeten en gepind moet worden. */

/* ── SAMENWERKING-SUBCOACH-TOEGANG ── */
/* The chip sits BESIDE .clib__name, never inside it: .clib__name ellipsises its
   own overflow, so a nested chip on a long client name is the first thing to
   disappear — exactly the row where knowing it is not your own client matters. */
/* DE-KLANTENLIJST-VERTELT-WAAROM — de regel WRAPT sinds er een tweede chip op
   staat. Zonder wrap wint een `flex: 0 0 auto`-chip het altijd van de naam, en
   op 390 breed at "Coach · door jou gegeven" de naam volledig op: de rij toonde
   het etiket zonder te zeggen van WIE. De naam krijgt de rest van de regel en
   de chip zakt eronder wanneer het niet past. Gevonden op de mock, niet op prod. */
.clib__nameline {
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px var(--space-2); min-width: 0;
}
.clib__nameline .clib__name {
  flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* KLANTEN-DE-KLANTENRIJ-ZEGT-WAT-DE-SERVER-AL-WEET — de gewichtstrendpijl pal
   achter de naam. flex:0 0 auto zodat hij NOOIT meekrimpt: .clib__name mag
   ellipsiseren, een half icoon bestaat niet. Gedempte kleur — een trend is een
   waarneming, geen waarschuwing, en stijgend gewicht is niet per definitie
   slecht (bulken is een doel). Daarom ook GEEN rood/groen. */
.clib__trend { flex: 0 0 auto; display: inline-flex; align-items: center; color: var(--muted); }
/* LEAD-BETAALD-ZONDER-INTAKE-MELDT-DE-COACH-METEEN — hetzelfde formaat en
   dezelfde plek als de trendpijl, maar WEL in de accentkleur: dit is geen
   waarneming maar openstaand werk van de coach zelf. flex:0 0 auto zodat hij
   nooit meekrimpt; .clib__name mag ellipsiseren, dit icoon niet. */
.clib__needsintake { flex: 0 0 auto; display: inline-flex; align-items: center; color: var(--accent); }
.clib__subchip {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 7px; border: 1px solid var(--line-2); border-radius: 999px;
  font-size: 11px; font-weight: 600; color: var(--muted); white-space: nowrap;
}
/* CONNECTOR-TOESTEMMING-ALS-PIL-BIJ-DE-COACH (L143) — de AI-stand op de
   naamregel, en bovenin het dossier dezelfde vorm. flex:0 0 auto zodat hij
   nooit meekrimpt: .clib__name mag ellipsiseren, een half woord ("AI: gev…")
   leest als een andere stand dan het is.

   Alleen 'aan' krijgt kleur. --muted voor de andere twee is dezelfde keuze die
   .clib__trend hierboven maakte en om dezelfde reden: dit is een waarneming,
   geen waarschuwing — een klant die geen toestemming geeft doet niets verkeerd,
   en een rode of oranje pil op zijn rij zou dat elke dag suggereren. Geen
   eigen hex: --accent en --muted staan in BEIDE themablokken bovenaan dit
   bestand, dus licht en donker volgen uit de tokens (--accent #006E7D op wit
   = 5,3:1, #6FE8FF op --surface = 12,6:1 volgens de meting daar). */
.clib__aipill,
.dossier-ident__aipill {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 7px; border: 1px solid var(--line-2); border-radius: 999px;
  font-size: 11px; font-weight: 600; color: var(--muted); white-space: nowrap;
}
.clib__aipill--on,
.dossier-ident__aipill--on { color: var(--accent); border-color: var(--accent); }

/* DE-KLANTENLIJST-VERTELT-WAAROM — de bronchip krijgt de VOLLE rijbreedte als
   gewrapte regel, net als .clib__metrics hierboven en om dezelfde reden: binnen
   .clib__mid is er op 390 breed ~180px, en daar past "Coach · door jou gegeven"
   niet in. Hij mag niet ellipsiseren: hij draagt de enige zichtbare aanwijzing
   waar het geld loopt, en een half etiket ("SF · nog via …") is precies de
   verwarring met de omgekeerde SF-markering in Trainin die deze fase moet
   voorkomen. */
.clib__srcline {
  flex: 1 0 100%; display: flex; align-items: center; gap: var(--space-2); min-width: 0;
}
/* In de gedeelde onderregel krimpt de CIJFERREGEL, nooit de chip: cijfers zijn
   ook half nog leesbaar, een half etiket is misleidend. */
.clib__srcline .clib__metrics { flex: 0 1 auto; min-width: 0; }
.clib__srcchip {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 7px; border: 1px solid var(--line-2); border-radius: 999px;
  font-size: 11px; font-weight: 600; color: var(--muted); white-space: nowrap;
  background: var(--surface-2, transparent);
}
/* De actieve telling naast 'Klanten'. Geen accentkleur: het is een aantal,
   geen waarschuwing. */
.ctoday__seg-count {
  margin-left: 6px; font-size: 12px; font-weight: 700; opacity: .7;
}
/* De oud-klantengroep: ingeklapt de standaardstand, want dit is de bodem van
   de lijst en niet de dagelijkse werkvoorraad. */
.clib-former { margin-top: var(--space-4); }
.clib-former__head {
  display: flex; align-items: center; gap: var(--space-2); cursor: pointer;
  padding: var(--space-2) 0; font-size: 13px; font-weight: 600; color: var(--muted);
}
/* GELD-PAKKETTEN-EN-DOSSIER-NETJES — geen UA-driehoek: list-style zet de
   moderne ::marker uit, de -webkit-regel de oude WebKit-variant, en de chevron
   uit ICON draait een kwartslag zodra de groep open staat. */
.clib-former__head { list-style: none; }
.clib-former__head::-webkit-details-marker { display: none; }
.clib-former__head::marker { content: ''; }
.clib-former__chev {
  margin-left: auto; flex: 0 0 auto; color: var(--muted);
  transition: transform .15s ease;
}
.clib-former[open] > .clib-former__head .clib-former__chev { transform: rotate(90deg); }
.clib-former .clib__row--former { opacity: .72; }

/* KLANTEN-WIE-HOORT-ERBIJ — de uitgenodigd-groep boven de lijst. Bewust GEEN
   .clib__row-vorm: dit zijn geen klanten en geen deuren, dus ook geen kaart met
   een rand die uitnodigt om te tikken. Een kopregel in dezelfde toon als de
   oud-klantengroep, daaronder platte regels. */
.clib-invited { margin-bottom: var(--space-3); }
.clib-invited__head {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) 0; font-size: 13px; font-weight: 600; color: var(--muted);
}
.clib-invited__row {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--space-2) 0;
  border-top: 1px solid var(--line);
}
.clib-invited__mail {
  font-size: 14px; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.clib-invited__when { font-size: 12px; color: var(--muted); }
.clib-invited__when--warn { color: var(--warn); font-weight: 600; }

/* KLANTEN-WIE-HOORT-ERBIJ — de rij-kebab. UIT DE FLOW, en dat is het hele punt:
   als flex-item kostte hij op 390px óf een extra regel per kaart (achteraan de
   rij) óf 28px van de klantnaam (op de bovenregel, "Mariett…"). Absoluut tegen
   de rechterrand verandert hij niets aan het wrapgedrag van de rij, en staat hij
   op ELKE kaart in dezelfde hoek — ook op een kaart die twee regels hoog is.
   De rij reserveert de ruimte zelf met padding-right, dus er is geen overlap met
   de statuspil of de Duo-knop. */
.clib__row--kebab { position: relative; padding-right: calc(var(--space-3) + 24px); }
.clib__kebab {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px;
  border-radius: var(--radius-sm, 8px);
  color: var(--muted); cursor: pointer;
}
.clib__kebab:hover { color: var(--accent); }
.clib__kebab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ── KLANTENRIJ-NAAM-EERST-OP-DE-TELEFOON (audit L183 §5.6, bevinding #14) ── */
/* De vorige reparatie (COACH-NIETS-LOOPT-NOG-BUITEN-ZIJN-VAK) liet de STATUSPIL
   meekrimpen zodat de naam niet meer tot "T…" afkapte. Dat was een ruil, en de
   notitie bij .clib__pill hierboven zei het al: de echte oplossing is een
   HERINDELING, en die hoort hier. Vier dingen vochten op 375px om één regel:
   avatar (40) + naam + pil + Duo-knop (~70) + de ⋮-reservering (36).
   Nu: de naamkolom krijgt de hele eerste regel, de pil zakt eronder, en de
   Duo-knop verhuist naar het ⋮-menu (de deur zelf blijft — openKebab leest
   dezelfde 479px-grens met matchMedia bij de TIK, niet bij het tekenen, dus
   draaien of slepen schuift de knop mee zonder hertekening).

   De grens is 479px en niet 600px: op een iPad van 768px past de rij met
   Duo-knop ruim (gemeten, bevinding #14 noemt alleen 375-430px).

   `:has(.clib__pill)` en niet `.clib__row` kaal: de statuspil is wat een
   KLANTrij onderscheidt van de andere twee gebruikers van deze rijvorm — de
   eigen-dossierdeur (.clib__row--self, alleen avatar + naam) en de
   sjabloonrij (.clib__row--static, met een 'Toewijzen…'-knop achteraan). Die
   twee houden hun huidige opmaak; een kale selector zou de sjabloonknop
   ongemeten naar een tweede regel duwen. */
@media (max-width: 479px) {
  .clib__row:has(.clib__pill) {
    flex-wrap: wrap;
    row-gap: var(--space-1);
    /* De avatar lijnt uit op de NAAM, niet op het midden van een rij die nu
       drie regels hoog is — gecentreerd zou hij naast de metaregel hangen. */
    align-items: flex-start;
  }
  /* Dit is het hele mechaniek: een flex-basis die de volledige RESTbreedte van
     de eerste regel opeist (rijbreedte − avatar − gap) laat niets anders meer
     op die regel passen. Geen `order`, geen extra wrapper, geen tweede
     container — en de bestaande gewrapte onderregels (.clib__srcline met
     `flex: 1 0 100%`) werken ongewijzigd door. 40px = .clib__avatar. */
  .clib__row:has(.clib__pill) .clib__mid {
    flex: 1 1 calc(100% - 40px - var(--space-3));
  }
  /* De pil onder de NAAM, niet onder de avatar: ingesprongen met exact de
     avatarbreedte + gap, zodat de linkerkantlijn van naam, meta en pil één
     lijn is. max-width houdt hem binnen die kantlijn, dus de ellipsis-regel
     hierboven blijft het vangnet voor een extreem lang statuslabel. */
  .clib__row:has(.clib__pill) .clib__pill {
    margin-left: calc(40px + var(--space-3));
    max-width: calc(100% - 40px - var(--space-3));
  }
  /* De rij-knop verdwijnt van het SCHERM, niet uit de app: hij staat op een
     telefoon als regel in het ⋮-menu. Beide varianten (de kale knop en de
     icoon-only kiezer naast een gekoppeld paar) gaan samen weg, want ze
     openen op die breedte allebei via datzelfde menu. */
  .clib__row:has(.clib__pill) .clib__duo { display: none; }
}

.ccoach { display: flex; flex-direction: column; gap: var(--space-2); }
.ccoach__row {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-2) 0; border-bottom: 1px solid var(--line);
}
.ccoach__row:last-of-type { border-bottom: 0; }
.ccoach__mid { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; }
.ccoach__name {
  font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ccoach__meta { font-size: 12px; color: var(--muted); }
.ccoach__rm {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0; border: 1px solid var(--line-2);
  border-radius: var(--radius); background: none; color: var(--danger);
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.ccoach__hint { margin: 0; font-size: 12px; color: var(--muted); line-height: 1.5; }
.ccoach__add { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.ccoach__input {
  flex: 1 1 8rem; min-width: 0; padding: 10px 12px;
  border: 1px solid var(--line-2); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); font: inherit; font-size: 14px;
}
.ccoach__btn { flex: 0 0 auto; padding: 10px 16px; font-size: 14px; }
.ccoach__btn:disabled { opacity: .45; cursor: default; }
/* Handing over ownership moves the billing relationship and cannot be undone,
   so the block is fenced off visually from the reversible add/remove above it. */
.ccoach__transfer {
  display: flex; flex-direction: column; gap: var(--space-2);
  margin-top: var(--space-2); padding-top: var(--space-3);
  border-top: 1px solid var(--line-2);
}
/* COACH-SLUIT-EEN-BEGELEIDING-AF — de geldwaarschuwing. Blijft staan (geen
   toast): hij noemt meerdere dingen en de coach moet hem kunnen naslaan terwijl
   hij ze gaat sluiten. `display: flex` staat hier op een KLASSE en zou daarmee
   winnen van de ingebouwde regel [hidden]{display:none} — gelijke
   specificiteit, latere regel wint — dus de verborgen stand krijgt zijn eigen
   regel. Zonder die ene regel toont de kaart de waarschuwing altijd, ook vóór
   de eerste poging. */
.ccoach__warn {
  display: flex; align-items: flex-start; gap: var(--space-2);
  padding: var(--space-3); border-radius: var(--radius);
  border: 1px solid var(--line-2); background: var(--surface-2, var(--surface));
  color: var(--ink-2);
}
.ccoach__warn[hidden] { display: none; }
.ccoach__warn-txt { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.ccoach__warn-line { margin: 0; font-size: 13px; line-height: 1.5; }

/* ── SAMENWERKING-PAKKET-TRAINERSVERGOEDING ──
   The collaboration card reuses the package card wholesale; only three things
   are new. The payout chip is the one amount two coaches genuinely share, so it
   reads as accent rather than as another grey meta chip. A pending proposal is
   dashed, because it is not an agreement yet — that difference has to survive a
   glance, and colour alone would not carry it in high-contrast mode. The review
   line is danger-toned and lives apart from the tally: those sessions are NOT
   in the total and must never look like they are. */
/* GELD-EEN-LADDER-EN-EEN-UITGANG — dit chipje draagt een hele zin en geen enkel
   woord, dus op het tintniveau van de statuschips woog het zwaarder dan de
   pakketprijs ernaast. Lichter omdat het langer is, niet omdat het minder telt. */
.cpay-sub__chip--payout {
  gap: 5px;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  color: var(--ink-2);
}
.cpart-card--proposed { border-style: dashed; }
.cpart-chip--proposed { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--ink); }
.cpart-chip--active   { background: color-mix(in srgb, var(--ok) 16%, transparent); color: var(--ink); }
.cpart-chip--ended    { background: var(--line-2); color: var(--muted); }
/* Factuurstatussen. Een concept is nadrukkelijk NIET groen: er is nog niets weg. */
.cpart-chip--draft    { background: var(--line-2); color: var(--ink); }
.cpart-chip--sent     { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--ink); }
.cpart-chip--paid     { background: color-mix(in srgb, var(--ok) 16%, transparent); color: var(--ink); }
.cpart-chip--void     { background: color-mix(in srgb, var(--danger) 16%, transparent); color: var(--ink); }
.cpart-card__tally {
  margin: var(--space-2) 0 0; font-size: 16px; font-weight: 700; color: var(--ink);
}
.cpart-card__review {
  display: flex; align-items: center; gap: 6px;
  margin: var(--space-1) 0 0; font-size: 13px; color: var(--danger);
}
.cpart-card__waiting {
  display: inline-flex; align-items: center; font-size: 14px; color: var(--muted);
}
.cpart-sec {
  margin-top: var(--space-3); padding-bottom: var(--space-1);
  border-bottom: 1px solid var(--line-2);
  font-size: 13px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted);
}
.cpart-line {
  display: flex; align-items: center; gap: var(--space-2);
  padding: 8px 0; border-bottom: 1px solid var(--line);
  font-size: 14px;
}
.cpart-line:last-child { border-bottom: 0; }
.cpart-line__when { flex: 0 0 5.5rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.cpart-line__who  { flex: 1 1 auto; min-width: 0; color: var(--ink); overflow-wrap: anywhere; }
.cpart-line__amt  { flex: 0 0 auto; font-weight: 600; font-variant-numeric: tabular-nums; }
.cpart-line--review .cpart-line__amt { color: var(--danger); font-weight: 600; }
/* A review line is a line the coach still has to settle, so it carries an input
   and two buttons. On a phone that never fits on one row: let it wrap. */
.cpart-line--review { flex-wrap: wrap; }
.cpart-line__input {
  flex: 0 1 8rem; min-width: 6rem; text-align: right;
  font-variant-numeric: tabular-nums;
}

/* CRM-DOSSIER-NAAST-FITNESSDOSSIER droeg hier .cfile-seg, de schakelregel boven
   beide dossiers. EEN-DOSSIERKOP-DIE-ZEGT-MET-WIE-JE-BEZIG-BENT heeft die rij
   geschrapt — de wissel woont in het kopmenu (.csettings-row--on markeert de
   stand waar je staat) en kost daar nul verticale pixels. */

/* De naam op de klantkaart in de Geld-tab is een deur, geen label. */
.cpay-card__name--door {
  border: 0; background: none; padding: 0; font: inherit; font-weight: 700;
  color: var(--ink); cursor: pointer; text-align: left;
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: color-mix(in srgb, var(--ink) 35%, transparent);
}
.cpay-card__name--door:hover { color: var(--accent); text-decoration-color: var(--accent); }

/* ── GELD-HET-COLLEGA-DOSSIER-DE-PAGINA ──────────────────────────────────────
   Eén pagina per collega. Acht blokken onder elkaar in één kolom — geen tabs,
   geen raster: de vraag waarmee een coach dit scherm opent is "hoe staan we er
   met hem voor", en dat leest van boven naar onder. Alles hier is een maat die
   elders op dit scherm al bestond (.cpay-card, .cpay-summary, .cpart-sec); het
   nieuwe is de sleutel-waarderij en de factuurrij met zijn knoppenbalk.

   De knoppen van een factuurrij staan NAAST de tikbare deur, niet erin: een
   knop in een knop is geldig-ogende HTML waarin de ene tik de andere opslokt,
   en dat is aan het scherm niet te zien. De flex-kolom hieronder is wat die
   broer-en-zus-opstelling er toch als één rij laat uitzien. */
.ccol { display: flex; flex-direction: column; gap: var(--space-3); }
.ccol-block { display: flex; flex-direction: column; gap: var(--space-2); }
.ccol-head__id { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.ccol-head__names { min-width: 0; }
.ccol-head__name { margin: 0; font-size: 20px; font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
.ccol-head__co { margin: 2px 0 0; font-size: 14px; color: var(--muted); overflow-wrap: anywhere; }
.ccol-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-3); }
/* Drie tegels naast elkaar passen op 390px alleen als ze mogen afbreken. */
.ccol-tiles { flex-wrap: wrap; margin-bottom: 0; }
.ccol-tiles .cpay-summary__stat { flex: 1 1 7rem; min-width: 0; }
.ccol-tiles .cpay-summary__lbl { overflow-wrap: anywhere; }
/* Goud, en ALLEEN boven nul: een tegel die altijd opvalt valt nooit op. */
.ccol-tile--due { border-left: 3px solid var(--warn); }
.ccol-actions { flex-wrap: wrap; }
.ccol-sec__title { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.ccol-sec { display: flex; flex-direction: column; gap: var(--space-2); }
.ccol-years { margin: 0; }
.ccol-invoices { display: flex; flex-direction: column; gap: var(--space-2); }
.ccol-zip { align-self: stretch; margin-top: var(--space-2); }

.ccol-inv {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: 4px var(--space-2);
  padding: var(--space-3); border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface);
}
.ccol-inv__open {
  grid-column: 1; grid-row: 1;
  display: flex; flex-direction: column; gap: 2px;
  border: 0; background: none; padding: 0; margin: 0;
  font: inherit; color: inherit; text-align: left; cursor: pointer; min-width: 0;
}
.ccol-inv__top { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); }
.ccol-inv__nr { font-weight: 700; font-size: 15px; color: var(--ink); }
.ccol-inv__amt { font-weight: 700; font-size: 15px; color: var(--ink); font-variant-numeric: tabular-nums; }
.ccol-inv__meta, .ccol-inv__dir, .ccol-inv__credit { font-size: 13px; color: var(--muted); overflow-wrap: anywhere; }
.ccol-inv__chip { grid-column: 2; grid-row: 1; align-self: start; }
.ccol-inv__acts {
  grid-column: 1 / -1; grid-row: 2;
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3);
  margin-top: var(--space-1);
}
/* Tekstknoppen, geen kaders: op één rij horen vier kaders tot de rand en dan
   leest de rij als vier gelijkwaardige wegen in plaats van als bijschriften. */
.ccol-link {
  border: 0; background: none; padding: 0; margin: 0;
  font: inherit; font-size: 14px; font-weight: 600;
  color: var(--accent); cursor: pointer;
}
.ccol-link--danger { color: var(--danger); }
.ccol-link--more { display: inline-flex; align-items: center; color: var(--muted); }
.ccol-link:hover { text-decoration: underline; }

.ccol-kv {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-3); padding: 8px 0; border-bottom: 1px solid var(--line);
  font-size: 14px;
}
.ccol-kv:last-child { border-bottom: 0; }
.ccol-kv__k { flex: 0 1 auto; color: var(--muted); min-width: 0; }
.ccol-kv__v {
  flex: 1 1 auto; min-width: 0; text-align: right;
  font-weight: 600; color: var(--ink); overflow-wrap: anywhere;
}
/* Goud en nooit leeg: een regel die ontbreekt leest als "dit hoeft niet". */
.ccol-kv__v--todo { color: var(--warn); }
.ccol-kv--total .ccol-kv__k { color: var(--ink); font-weight: 600; }
.ccol-note__text { margin: 0; font-size: 14px; line-height: 1.5; color: var(--ink); overflow-wrap: anywhere; }
.ccol-note__area { width: 100%; }

/* HET ANTWOORD STAAT BOVENAAN: tegoed en eerstvolgende incasso, zonder één tik
   en zonder scrollen — ook op 390px.

   GELD-DE-LADE-WORDT-DE-PAGINA — dit was een raster van twee tegels. Die tegels
   stonden pal boven de tabs die nu direct volgen en zeiden daar hetzelfde als
   Gepland zes regels lager. Eén regel die mag afbreken: geen vaste
   rasterkolommen meer, dus ook niet meer het geval waarop de oude flexrij
   omklapte (een lang bedrag dat zijn buur naar een tweede regel duwde). */
.czaak-answer { margin-bottom: var(--space-3); }
.czaak-top__sum {
  margin: 0 0 var(--space-1); font-size: 14px; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
/* Heeft deze klant geen bundel, dan BEGINT de regel bij de afschrijving, en dat
   stuk is als zinsdeel geschreven ('volgende afschrijving …'). De hoofdletter
   hoort bij de plek, niet bij de vertaling — anders heeft elk stuk twee
   sleutels, één voor vooraan en één voor midden in de regel. */
.czaak-top__sum::first-letter { text-transform: uppercase; }
.czaak-top__seg { color: var(--ink); }
.czaak-top__seg--warn { color: var(--warn); font-weight: 600; }
.czaak-top__seg--danger { color: var(--danger); font-weight: 600; }
/* De scheidingspunt hoort bij geen van beide feiten en spreekt dus zachter. De
   spaties zitten in de TEKST en niet in een marge, zodat een voorleesstem er
   ook een adempauze leest in plaats van "leftnext". */
.czaak-top__dot { color: var(--muted); }
.czaak-top__cta { margin-top: var(--space-2); }
.czaak-top__note { margin: 0; color: var(--muted); font-size: 13px; }
.czaak-top__note--danger { color: var(--danger); font-weight: 600; }

/* CONTRACT-EEN-LOPENDE-KLANT-TEKENT-ALSNOG — de ene rustige regel.
   --ink-2 en geen --danger, geen rand, geen badge: dat er nog niet getekend is
   is een OPEN PUNT en geen storing, en een scherm dat elk open punt in
   alarmkleur zet leert de coach alle kleur te negeren. De handeling staat als
   TEKSTKNOP naast de zin en niet als vlak eronder — hij hoort bij die ene
   regel, niet bij de pagina. Hij mag afbreken naar een tweede regel (wrap),
   want op 390px past "Ter ondertekening sturen" er niet altijd naast. */
.czaak-contract {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2);
  margin: var(--space-2) 0 0; font-size: 13px; color: var(--ink-2);
}
.czaak-contract__text { color: var(--ink-2); }
.czaak-contract__act {
  padding: 0; border: 0; background: none; font: inherit; color: var(--accent);
  text-decoration: underline; cursor: pointer;
}
.czaak-contract__act:disabled { opacity: .5; cursor: default; }

/* COACH-ZAAL-EN-HERKOMST — de zaal is het gebouw, de locatie is van jou.
   Een locatie zonder zaal is geen fout maar een open vraag, dus krijgt hij een
   zachte rand in plaats van een waarschuwkleur. */
.cvenue { display: block; }
.cvenue-row {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--line);
}
.cvenue-row:last-child { border-bottom: 0; }
.cvenue-row__name { flex: 1 1 auto; min-width: 0; font-weight: 600; color: var(--ink); }
.cvenue-row__cur {
  flex: 0 1 auto; min-width: 0; font-size: 13px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cvenue-row__cur--empty { font-style: italic; opacity: .8; }
.cvenue-row--off .cvenue-row__name { color: var(--muted); }

/* Zoekresultaten in de kiezer: het aantal coaches staat er niet als versiering
   maar als het argument om déze regel te kiezen in plaats van een nieuwe. */
.cvenue-res { display: block; margin: var(--space-3) 0 0; }
.cvenue-res__hit {
  display: flex; width: 100%; align-items: center; gap: var(--space-3);
  padding: var(--space-3); margin-bottom: var(--space-2);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface-2, var(--surface)); color: var(--ink);
  font: inherit; text-align: left; cursor: pointer;
}
.cvenue-res__hit:hover { border-color: var(--accent); }
.cvenue-res__txt { flex: 1 1 auto; min-width: 0; }
.cvenue-res__name { font-weight: 600; }
.cvenue-res__sub { font-size: 12px; color: var(--muted); }
.cvenue-act { display: block; width: 100%; margin-top: var(--space-3); }

/* De eigenaar-cijfers. Geen dashboard-esthetiek: vier getallen en de zin die
   zegt wat ze waard zijn. */
.cvenue-num { margin-top: var(--space-5); }
.cvenue-sum { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-bottom: var(--space-3); }
.cvenue-sum__cell { flex: 1 1 7rem; min-width: 0; }
.cvenue-sum__val { font-size: 20px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.cvenue-sum__lbl { font-size: 12px; color: var(--muted); }
.cvenue-org { font-size: 13px; color: var(--muted); margin: 0 0 var(--space-2); }
.cvenue-card--tipped { border-color: var(--accent); }
.cvenue-flag { font-size: 12px; font-weight: 700; color: var(--accent); }

/* ── NA-JE-GRATIS-MAAND-KIES-JE-ZELF — de keuzepagina en de herinneringsregel ──
   Eén kolom, één primaire knop, en 'Not now' direct eronder in dezelfde blok —
   niet onderaan de pagina, want dan is het een straf in plaats van een keuze.
   Alles past op 390px zonder scrollen: dat is de eis, niet een bijvangst. */
.cseat { padding: var(--space-4); max-width: 34rem; margin: 0 auto; }
.cseat__loading { color: var(--muted); font-size: 14px; }
.cseat__title { font-size: 20px; line-height: 1.25; margin: 0 0 var(--space-2); color: var(--ink); }
.cseat__lede { font-size: 14px; line-height: 1.45; color: var(--ink-2); margin: 0 0 var(--space-3); }
.cseat__lede--sub { color: var(--muted); }
.cseat__gets { list-style: none; margin: 0 0 var(--space-3); padding: 0; }
.cseat__get { display: flex; align-items: flex-start; gap: var(--space-2); font-size: 14px; color: var(--ink); padding: 2px 0; }
.cseat__get svg { flex: 0 0 auto; color: var(--accent); margin-top: 2px; }
.cseat__price { font-size: 18px; font-weight: 700; color: var(--ink); margin: 0 0 var(--space-3); }
/* FOUNDING-COACH-JE-EERSTE-KEER-BINNEN-IS-EEN-FEESTJE — het vinkje boven de kop.
   Een BLOK met auto-marges, niet inline-flex: .cseat is een gewoon blok en de
   kop eronder hoort er los onder te staan, niet ernaast (kaizen 2026-09-14).
   De cirkel is 72px, het vinkje erin 44px zoals de spec vraagt; de 12px marge
   eromheen is (72 - 44) / 2 en houdt het vinkje gecentreerd zonder flex. */
.cseat__hero {
  display: block; box-sizing: border-box;
  width: 72px; height: 72px; margin: var(--space-3) auto var(--space-4);
  border: 2px solid var(--accent); border-radius: 50%;
}
.cseat__hero > svg { display: block; width: 44px; height: 44px; margin: 12px auto; color: var(--accent); }
/* Kort en één keer: 300ms bij zijn allereerste keer, daarna nooit meer. */
.cseat__hero--pop { animation: cseat-hero-pop 300ms ease-out both; }
@keyframes cseat-hero-pop {
  from { transform: scale(.6); opacity: 0; }
  to   { transform: scale(1);  opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .cseat__hero--pop { animation: none; }
}
.cseat__cta {
  display: block; width: 100%; padding: 14px var(--space-4);
  border: 0; border-radius: var(--radius);
  background: var(--accent); color: var(--on-accent);
  font: inherit; font-weight: 700; cursor: pointer;
}
.cseat__cta:disabled { opacity: .6; cursor: default; }
.cseat__secondary {
  display: block; width: 100%; margin-top: var(--space-2); padding: 12px var(--space-4);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: transparent; color: var(--ink);
  font: inherit; font-weight: 600; cursor: pointer;
}
.cseat__keep { font-size: 13px; line-height: 1.4; color: var(--muted); margin: var(--space-2) 0 0; }

/* BETAALMETHODE-WIJZIGEN-KAN-GEWOON — de knop onder het administratie-aanbod,
   met een streep erboven zodat hij als een APARTE handeling leest en niet als
   een derde knop van dat aanbod. */
.cseat-paymethod {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--line);
}
.cseat-paymethod__sub {
  font-size: 13px; line-height: 1.4; color: var(--muted); margin: var(--space-2) 0 0;
}

/* COACHKASSA — twee kaartjes naast elkaar, ook op 390px. Elk bedrag komt van
   de server; hier staat alleen hoe het eruitziet. */
.cseat-plans { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-2); margin: 0 0 var(--space-3); }
.cseat-plan {
  display: flex; flex-direction: column; gap: var(--space-2);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: var(--space-3);
}
.cseat-plan__name { font-size: 15px; font-weight: 700; color: var(--ink); margin: 0; }
/* COACHKASSA-LEGT-UIT — wat de kaart bevat, direct onder de naam. */
.cseat-plan__what { font-size: 13px; line-height: 1.4; color: var(--muted); margin: 0; }
.cseat-plan__buy {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  width: 100%; padding: 10px var(--space-3);
  border: 0; border-radius: var(--radius);
  background: var(--accent); color: var(--on-accent);
  font: inherit; text-align: left; cursor: pointer;
}
.cseat-plan__buy:disabled { opacity: .5; cursor: default; }
/* De afstandsverklaring staat boven het HELE raster, over de volle breedte —
   niet in een kolom van 180px, waar dezelfde zin acht regels wordt. Vinkje en
   tekst op één regel, het vinkje bovenaan uitgelijnd zodat een tekst van drie
   regels hem niet naar het midden duwt. */
/* COACH-DEUR-OPEN-OP-IS-OP — de Founder-teller boven de kaartjes. Een kader met
   de accentlijn, niet een gekleurd vlak: het getal is het nieuws, niet de kleur,
   en een vol vlak zou op 390px de kaartjes eronder wegdrukken. */
.cseat-founder {
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  padding: var(--space-2) var(--space-3);
  margin: 0 0 var(--space-3);
}
.cseat-founder__head { margin: 0; font-size: 15px; font-weight: 700; color: var(--ink); }
.cseat-founder__sub { margin: 2px 0 0; font-size: 13px; line-height: 1.4; color: var(--muted); }

.cseat-consent {
  display: flex; align-items: flex-start; gap: 10px;
  margin: 0 0 var(--space-3);
  font-size: 13px; line-height: 1.45; color: var(--muted);
  cursor: pointer;
}
.cseat-consent__box { flex: 0 0 auto; margin: 2px 0 0; width: 18px; height: 18px; accent-color: var(--accent); }
.cseat-consent__text { flex: 1 1 auto; }
.cseat-consent__link { color: var(--accent); text-decoration: underline; }
.cseat-plan__amount { font-size: 18px; font-weight: 700; font-variant-numeric: tabular-nums; }
.cseat-plan__term { font-size: 12px; font-weight: 600; }
.cseat-plan__vat { font-size: 12px; color: var(--muted); margin: auto 0 0; }

/* ADMINISTRATIE-LOS-BIJKOPEN — drie regels geld, label links en bedrag rechts,
   zodat de bedragen onder elkaar uitlijnen en de eenmalige betaling zichtbaar
   naast de maandprijs staat. Tabular-nums, want cijfers die verspringen lezen
   als een ander getal. */
.cadmin {
  display: flex; flex-direction: column; gap: var(--space-2);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: var(--space-3); margin: 0 0 var(--space-2);
}
.cadmin__row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); }
.cadmin__label { font-size: 14px; color: var(--muted); }
/* Het bedrag breekt NOOIT af: '€63,00 per' op de ene regel en 'month' op de
   volgende leest als twee dingen. Het label mag krimpen, het bedrag niet. */
.cadmin__amount {
  font-size: 16px; font-weight: 700; color: var(--ink);
  font-variant-numeric: tabular-nums; white-space: nowrap; flex: 0 0 auto;
}
.cadmin__label { min-width: 0; }
.cadmin__honest + .cseat-plan__vat { margin-bottom: var(--space-2); }
.cadmin__suffix { font-size: 12px; font-weight: 600; color: var(--muted); }
.cadmin__honest { font-size: 13px; line-height: 1.4; color: var(--muted); margin: 0 0 var(--space-2); }

/* De herinnering: één regel op het scherm dat hij toch al opent. Geen modal,
   geen stip, geen kleurvlak dat om aandacht schreeuwt. */
.ctoday__nudge:empty { display: none; }
.cseat-nudge {
  display: flex; align-items: center; gap: var(--space-2);
  margin: var(--space-2) 0 0;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface);
}
.cseat-nudge__open {
  flex: 1 1 auto; min-width: 0;
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  padding: 10px var(--space-3);
  border: 0; background: transparent; color: var(--ink);
  font: inherit; font-size: 14px; text-align: left; cursor: pointer;
}
.cseat-nudge__open svg { flex: 0 0 auto; color: var(--muted); }
.cseat-nudge__x {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border: 0; background: transparent; color: var(--muted); cursor: pointer;
}

/* VOEDING-TREDE-FOTO-ZONDER-CIJFERS — the coach's meal-photo card in the
   nutrition panel. Reuses .photocard chrome; its own grid so the Photos-row
   thumbnail counter on the Client panel keeps counting only progress photos. */
.mealphotocard__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-2); }
.mealphotocard__thumb { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.mealphotocard__thumb img {
  width: 100%; aspect-ratio: 1 / 1; object-fit: cover;
  border: 1px solid var(--line-2); border-radius: var(--radius);
  background: var(--bg); display: block;
}
.mealphotocard__date { font-size: 11px; color: var(--muted); }

/* ── EIGEN-OEFENVIDEOS-STAAN-BIJ-DE-OEFENING-EN-NERGENS-ANDERS (v0.9.2610) ──
   The coach's own clip, attached to ONE exercise from that exercise's own row.
   Its own class family on purpose: the periodisation row head is a shared
   surface and a new control there may never borrow a neighbour's class. */
.cpz-vidbtn{ flex:0 0 auto; margin-left:6px; width:22px; height:22px; padding:0;
  display:inline-flex; align-items:center; justify-content:center;
  border:1px solid var(--cpz-line-strong); border-radius:50%;
  background:var(--cpz-white); color:var(--cpz-faint); cursor:pointer; font-family:inherit; }
.cpz-vidbtn:hover{ color:var(--cpz-accent); border-color:var(--cpz-accent); }
.cpz-vidbtn.is-on{ color:var(--cpz-accent); border-color:var(--cpz-accent);
  background:var(--cpz-accent-tint); }
.cpz-vidbtn svg{ fill:currentColor; stroke:none; }

.cpz-vidpick__ex{ font-size:13px; font-weight:700; margin:0 0 10px; }
.cpz-vidpick__empty{ font-size:13px; color:var(--cpz-muted); margin:0; }
.cpz-vidpick__list{ display:flex; flex-direction:column; gap:2px; max-height:52vh; overflow:auto; }
.cpz-vidpick__row{ display:flex; align-items:center; width:100%; min-height:44px;
  padding:8px 12px; border:0; border-radius:8px; background:transparent;
  color:inherit; font:inherit; text-align:left; cursor:pointer; }
.cpz-vidpick__row:hover{ background:var(--cpz-accent-tint); }
.cpz-vidpick__row.is-on{ background:var(--cpz-accent-tint); font-weight:700; }
.cpz-vidpick__nm{ flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cpz-vidpick__clear{ margin-top:12px; min-height:44px; width:100%; padding:8px 12px;
  border:1px solid var(--cpz-line-strong); border-radius:8px; background:transparent;
  color:var(--cpz-muted); font:inherit; cursor:pointer; }

/* ───────── COACH-JE-ZIET-WIE-WEGZAKT-EN-WIE-TERUGKOMT ─────────
   De kaart bovenaan de klantenlijst en de tijdlijnregel in het dossier.

   Geen grafiek, geen ring, geen rood: er staat NERGENS een kleur die van een
   telling een oordeel maakt. De enige accentkleur zit op de venster-schakelaar,
   want dat is een keuze van de coach en geen uitkomst over een klant. Op accent
   altijd --on-accent, nooit een eigen wit. */
.cretent {
  margin-bottom: var(--space-4);
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.cretent__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3); flex-wrap: wrap; margin-bottom: var(--space-3);
}
.cretent__title { margin: 0; font-size: 16px; font-weight: 700; color: var(--ink); }
.cretent__span {
  display: inline-flex; border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden;
}
.cretent__span-btn {
  padding: 5px var(--space-3); border: 0; background: var(--surface);
  color: var(--ink-2); font-size: 12px; font-weight: 600; cursor: pointer;
}
.cretent__span-btn + .cretent__span-btn { border-left: 1px solid var(--line); }
.cretent__span-btn.is-on {
  background: color-mix(in srgb, var(--accent) 16%, var(--surface));
  color: var(--accent); border-color: var(--accent);
}
.cretent__loading { margin: 0; color: var(--muted); font-size: 13px; }
.cretent__line {
  width: 100%; display: flex; align-items: baseline; gap: var(--space-2);
  padding: var(--space-2) 0; border: 0; border-top: 1px solid var(--line);
  background: none; color: var(--ink); font-size: 13px; line-height: 1.5;
  text-align: left; cursor: pointer;
}
.cretent__line:first-child { border-top: 0; }
.cretent__line[disabled] { cursor: default; opacity: 1; }
.cretent__line-label { flex: 0 0 auto; font-weight: 700; }
.cretent__line-text { flex: 1 1 auto; min-width: 0; color: var(--ink-2); }
.cretent__line svg { flex: 0 0 auto; color: var(--muted); align-self: center; }
.cretent__pct { margin: 0 0 var(--space-2); color: var(--muted); font-size: 12px; }
.cretent__foot {
  width: 100%; margin-top: var(--space-2); padding: var(--space-2) 0 0;
  border: 0; border-top: 1px solid var(--line); background: none;
  color: var(--ink-2); font-size: 13px; text-align: left; cursor: pointer;
}
.cretent__foot[disabled] { cursor: default; }
.cretent__people { display: flex; flex-direction: column; }
.cretent__person {
  display: flex; flex-direction: column; gap: 2px; width: 100%;
  padding: var(--space-3) 0; border: 0; border-bottom: 1px solid var(--line);
  background: none; text-align: left; cursor: pointer;
}
.cretent__person:last-child { border-bottom: 0; }
.cretent__person-name { color: var(--ink); font-size: 14px; font-weight: 600; }
.cretent__person-meta { color: var(--muted); font-size: 12px; }

.nutlapse__body { margin-top: var(--space-2); }
.nutlapse__loading, .nutlapse__empty { margin: 0; color: var(--muted); font-size: 13px; }
.nutlapse__list { margin: 0; padding: 0; list-style: none; }
.nutlapse__row {
  padding: 6px 0; border-bottom: 1px solid var(--line);
  color: var(--ink-2); font-size: 13px; line-height: 1.5;
}
.nutlapse__row:last-child { border-bottom: 0; }
.nutlapse__changes { margin: var(--space-2) 0 0; color: var(--muted); font-size: 12px; }

/* FYSIO-DRIE-OEFENINGEN-TWEE-KEER-PER-WEEK — de oefenstand-kaart.
   Drie regels, een weekdoel, een briefje. Geen kleurcodering en geen balk: dit
   is een INSTELLING, en de enige telling die hij toont (geoefend x van y) is een
   getal, geen oordeel. */
.exmode__hint { margin: 0 0 var(--space-2); font-size: 12px; color: var(--muted); }
.exmode__switch { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; color: var(--ink); cursor: pointer; }
.exmode__form[hidden] { display: none; }
.exmode__form { margin-top: var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); }
.exmode__row { display: flex; align-items: center; gap: 6px; }
.exmode__name { flex: 1 1 auto; min-width: 0; }
.exmode__name, .exmode__num, .exmode__note {
  border: 1px solid var(--line-2); border-radius: var(--radius-sm);
  padding: 8px 10px; font: inherit; font-size: 13px;
  background: var(--surface); color: var(--ink);
}
.exmode__num { width: 56px; text-align: center; font-variant-numeric: tabular-nums; }
.exmode__x { color: var(--muted); font-size: 12px; }
.exmode__goalrow { display: flex; }
.exmode__lbl { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--ink); }
.exmode__note { width: 100%; resize: vertical; }
.exmode__status { margin: 0; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.exmode__save { align-self: flex-start; }

/* ── CONTRACT-HET-DOSSIER-BEWAART-DE-OVEREENKOMST ───────────────────────────
   Het Documenten-blad. Eén vorm die op twee plekken staat: hier in het dossier
   van de coach en 1:1 hetzelfde in de app van de klant (public/assets/css/
   app.css, zelfde klassenamen) — een klant die zijn coach over de schouder
   kijkt hoort hetzelfde papier te zien. Titel boven, datum eronder in --ink-2,
   rechts een deur naar de bytes. Geen wisknop: een bewijsstuk verdwijnt alleen
   via cli/contract-retentie.php, zeven jaar na ondertekening. */
.cdocs__list { display: flex; flex-direction: column; }
.cdocs__row {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) 0; border-bottom: 1px solid var(--line);
}
.cdocs__row:last-child { border-bottom: none; }
.cdocs__txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cdocs__title {
  margin: 0; font-size: 15px; font-weight: 600; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cdocs__meta { margin: 0; font-size: 13px; color: var(--ink-2); }
.cdocs__open {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: var(--radius-sm);
  border: 1px solid var(--line-2); background: var(--surface);
  color: var(--ink); text-decoration: none;
}
.cdocs__open svg { width: 20px; height: 20px; }
.cdocs__open:hover { background: var(--line-2); }

/* DOSSIER-AFSPRAKEN-IN-PLAATS-VAN-LOGBOEK — de rij Afspraken in het dossier.
   Een LIJST, geen kalender: het datumblokje links is een anker om op te scannen
   ("welke dag?"), de tijd is het eerste dat je leest zodra je die dag gevonden
   hebt. Alle kleuren via tokens, zodat licht en donker meebewegen.

   `dappt` en niet `cappt`: die laatste is al bezet door de agendakaart
   (.cappt--noshow / .cappt__othercoach-badge hangen aan .cal__card). Twee
   onderdelen die hetzelfde voorvoegsel delen maar niets met elkaar te maken
   hebben, is precies hoe een latere `.cappt { }` twee schermen tegelijk
   verbouwt terwijl er maar naar één gekeken werd. */
.dappt__list { display: flex; flex-direction: column; }
.dappt__row {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) 0; border-bottom: 1px solid var(--line-2);
}
.dappt__row:first-child { padding-top: 0; }
/* Het blokje houdt één breedte voor elke rij, anders danst de tijdkolom mee
   met het aantal cijfers in de dag. */
.dappt__date {
  flex: 0 0 52px; display: flex; flex-direction: column; align-items: center;
  gap: 2px; padding: var(--space-2) 0;
  border: 1px solid var(--line); border-radius: 10px;
}
.dappt__dow {
  font-size: 11px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-2);
}
.dappt__daynum { font-size: 20px; font-weight: 700; line-height: 1; color: var(--ink); }
.dappt__texts { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.dappt__head { font-size: 15px; line-height: 1.3; color: var(--ink); }
.dappt__time { font-weight: 700; }
.dappt__sub { font-size: 13px; line-height: 1.3; color: var(--ink-2); }
/* De twee deuren onderaan: geen accentknoppen maar accentTEKST, want ze staan
   naast elkaar en twee gevulde knoppen zouden om dezelfde tik vechten. */
.dappt__door {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  width: 100%; padding: var(--space-3) 0; border: 0; background: none;
  color: var(--accent); font: inherit; font-weight: 700; text-align: left; cursor: pointer;
}
.dappt__door + .dappt__door { border-top: 1px solid var(--line-2); }
.dappt__door svg { flex: 0 0 auto; }
.dappt__empty { font-size: 14px; color: var(--ink-2); margin: 0 0 var(--space-3); }

/* AFSPRAAK-DE-VASTE-TIJDEN-VAN-DE-KLANT — het blok 'Vaste tijden' onder de
   afsprakenlijst in het dossier.

   TELEFOONMAAT EERST, en daarom staat de regel in TWEE lagen: bovenin dag +
   van-tot + wissen, eronder de schakelaar 'om de week'. Alles op één rij duwt
   op 390px de tijdvelden tot onder de 60px, en dan is een <input type="time">
   op iOS niet meer af te lezen. De dagkiezer krijgt met opzet meer ruimte dan
   de twee tijden samen: een verkeerde DAG is de fout die niemand terugleest.

   Kleuren via tokens, zoals .dappt ernaast — dit blok hoort bij die lijst en
   mag er niet als een vreemd kaartje naast komen te staan. */
.cfix { border-top: 1px solid var(--line); margin-top: var(--space-3); padding-top: var(--space-3); }
.cfix__title { margin: 0 0 var(--space-2); font-size: 15px; font-weight: 700; color: var(--ink); }
.cfix__hint { margin: 0 0 var(--space-2); font-size: 13px; color: var(--ink-2); }
.cfix__empty { margin: 0 0 var(--space-3); font-size: 14px; color: var(--ink-2); }
.cfix__list { display: flex; flex-direction: column; }
.cfix__row { padding: var(--space-2) 0; border-top: 1px solid var(--line-2); }
.cfix__row:first-child { border-top: 0; }
.cfix__top { display: flex; align-items: center; gap: var(--space-2); }
.cfix__day { flex: 2 1 0; min-width: 0; text-transform: capitalize; }
.cfix__time { flex: 1 1 0; min-width: 0; }
.cfix__dash { flex: 0 0 auto; color: var(--muted); }
.cfix__del {
  flex: 0 0 auto; border: 0; background: none; color: var(--muted);
  padding: var(--space-1); cursor: pointer; line-height: 0;
}
.cfix__switch {
  display: flex; align-items: center; gap: var(--space-2);
  margin-top: var(--space-2); cursor: pointer;
}
.cfix__swlabel { font-size: 13px; color: var(--ink-2); }
.cfix__anchor { margin-top: var(--space-2); width: 100%; }
.cfix__add {
  margin-top: var(--space-2);
  border: 1px solid var(--line); background: var(--surface);
  color: var(--ink-2); border-radius: var(--radius);
  padding: 4px var(--space-2); font-size: 12px; font-weight: 600; cursor: pointer;
  display: inline-flex; align-items: center; gap: 4px;
}
.cfix__add:disabled { opacity: .5; cursor: default; }
.cfix__err { margin: var(--space-2) 0 0; }
/* `.btn`-achtige knoppen erven width:100%; de opslaan-knop mag dat hier houden,
   maar hij heeft wel lucht boven zich nodig, anders plakt hij aan de foutregel. */
.cfix__save { margin-top: var(--space-2); }

/* AFSPRAAK-DE-KLANT-GEEFT-ZIJN-VASTE-TIJDEN-ZELF-DOOR — de herkomstregel BOVEN
   de lijst: 'Door de klant aangepast op <datum>'. Sinds 0646 kan de klant deze
   lijst zelf schrijven, en zonder deze regel kijkt de coach naar invoer die van
   zijn klant kan zijn en denkt hij dat hij zich iets verkeerd herinnert.

   Zwaarder dan de uitlegregel erboven (.cfix__hint) maar lichter dan de lijst:
   het is context om de lijst mee te lezen, geen alarm. --accent op de linkerrand
   zodat hij ook zonder de woorden te lezen als 'er is hier iets gebeurd' leest. */
.cfix__origin {
  margin: 0 0 var(--space-2);
  padding: 6px var(--space-2);
  border-left: 2px solid var(--accent);
  background: var(--surface-2, var(--surface));
  font-size: 13px;
  color: var(--ink);
}

/* ════ DOSSIER-EEN-KAART-DIEP (L183 herontwerp 2/6, 2026-10-13) ════
   De regel uit §3 van docs/COACH_RESPONSIVE_AUDIT_L183_2026-10-12.md:

     > EEN KAART DIEP. In een vak smaller dan 600px heeft inhoud hoogstens één
     > omlijst niveau boven zich. Alles wat binnen een kaart, paneel of vel
     > staat, is een SECTIE: een kop, een haarlijn of witruimte — geen tweede
     > rand, geen tweede achtergrond, geen tweede padding.

   Waarom dit de hele krapte oploste en niet een detail is: gemeten op 375 en
   402px liep de keten in het Voeding-paneel vier dozen diep —
   `.ddetail` (1) < `.ddetail__body` (16) < `.nutcard` (13) < `.nutstat` (13) =
   45px PER KANT bovenop de 16px paginarand en 17px paneelrand. Van 390px bleef
   238px tekst over. Hier eronder gaat elke doos BINNEN het vak weg, zodat de
   enige padding die een regel tekst nog kost die van het vak zelf is.

   DE SELECTOR: twee drempels, geen `@media`.
   `@container dbox (...)` vraagt het VAK (`.dossier__panel` / `.dsec__sheetbody`,
   zie coach.css:1510) en niet het scherm. Dat is geen stijlkeuze maar de poort
   van de vorige fase: inhoud van een dossiervak mag geen viewport-breakpoint
   meer dragen. 600px is daarbij de drempel uit §3 zelf — een vak dat ooit
   breder wordt (het periodiseringsvel groeit naar 1200px) houdt zijn kaarten,
   want dáár is een kaart-in-een-kaart leesbaar.

   WAT "FLUSH" PRECIES IS: rand, achtergrond, afronding en HORIZONTALE padding
   weg; verticale padding en marges blijven, want die dragen het ritme. Scheiden
   gebeurt met een haarlijn tussen twee opeenvolgende secties (§3.1), niet met
   een doos om elke sectie.

   DE LIJST HIERONDER IS DE FIX, NIET DE POORT. Wie morgen een nieuw kaarttype
   in een paneel zet en het hier vergeet, wordt gevonden door
   tests/visual/coach-dossier-een-kaart-diep.spec.js — die telt GEMETEN dozen in
   de computed style van de afnemer en kent deze lijst niet. */
@container dbox (max-width: 600px) {
  .northstar,
  .ddetail,
  .intake-card, .gymcard, .nutcard, .cctrl, .cadh, .dchat,
  .tabvis, .photocard, .nutrow, .cweek {
    border: 0;
    border-radius: 0;
    background: none;
    padding-inline: 0;
  }

  /* De Noordster houdt wat hem Noordster maakt — de kop en het accent-icoon —
     en verliest zijn doos ÉN zijn 3px accentstreep. Die streep markeerde het
     belangrijkste blok van het paneel; nu de doos weg is doet de ster in de kop
     dat werk, en §3.5 wil één accent per scherm. */
  .northstar { padding-block: 0; }

  /* De uitklapper: de knop en de inhoud eronder beginnen op dezelfde lijn als
     de rest van het paneel. Hij blijft herkenbaar aan zijn vette label met
     chevron, plus de haarlijn uit de zusterregel hieronder zodra er een andere
     sectie boven hem staat. */
  .ddetail__toggle { padding-inline: 0; }
  .ddetail__body { padding-inline: 0; }

  /* Twee secties onder elkaar krijgen een haarlijn ertussen in plaats van twee
     randen om elkaar heen. */
  :is(.northstar, .ddetail, .intake-card, .gymcard, .nutcard, .cctrl, .cadh, .dchat, .tabvis, .photocard, .nutrow, .cweek)
  + :is(.northstar, .ddetail, .intake-card, .gymcard, .nutcard, .cctrl, .cadh, .dchat, .tabvis, .photocard, .nutrow, .cweek) {
    border-top: 1px solid var(--line);
    /* DOSSIER-VLOEIENDE-RUIMTE — de lucht boven een haarlijn is hetzelfde
       sectieritme als de lucht tussen twee panelen. */
    padding-top: var(--section-gap);
  }

  /* HET ENE NIVEAU DAT BLIJFT: de tegel waar het getal in staat. Hij stond op
     `--bg` omdat zijn kaart `--surface` was; nu die kaart weg is zou hij
     oplossen in het paneel (dat ook `--bg` is) en alleen een rand overhouden.
     Omgekeerd dus: wit vlak op de grijze ondergrond, precies zoals de voor/na-
     mock van de audit (mock_dossier_390_na.png). */
  .northstar__stat, .nutstat {
    background: var(--surface);
  }
  .northstar__stat { border: 1px solid var(--line); }
  /* §3.5 — "Twee accentstrepen in elkaar" (bevinding #5) was de Noordster ÉN de
     TDEE-tegel erin. De Noordster was hier al zijn streep kwijt; met
     DOSSIER-NOORDSTER-ALS-OVERZICHT is de TDEE-TEGEL zelf weg — TDEE is nu een
     eigenschapsregel (`.northstar__prop`) zonder doos, en `.northstar__balance`
     bestaat niet meer, dus die twee staan hier niet langer. */
}

/* COACH-BEDRAGEN-EN-GEWICHTEN-MOGEN-EEN-KOMMA — een getalvakje dat de coach niet
   kan lezen kleurt rood en het blad slaat NIET op. De rand is het hele signaal:
   zonder dit zou een typefout stil als null over de lijn gaan en een bestaand
   bedrag of gewicht wissen. `.cdec` zelf is neutraal — hij bestaat zodat een
   poort de velden kan tellen die door decimalInput() zijn gegaan. */
.cdec--bad {
  border-color: var(--danger) !important;
  box-shadow: 0 0 0 2px color-mix(in oklab, var(--danger) 22%, transparent);
}

/* ── GELD-CREDITFACTUUR-DE-KNOP (L203) — het creditfactuur-blad ────────────
   Eén blok, want dit vel bestaat op twee schermen en een gedeelde klasse is de
   enige manier waarop die twee hetzelfde blijven lezen.

   .fincr__part DRAAGT ZIJN EIGEN display:none!important. `[hidden]` is alleen
   een regel uit het browser-stijlblad op display, en elke klasse die zelf een
   display zet verslaat hem stil — deze doos is een flexkolom, dus zonder deze
   regel zou 'Hele bedrag' het bedragveld laten staan. */
.fincr__part { display: flex; flex-direction: column; gap: var(--space-2); }
.fincr__part[hidden] { display: none !important; }
.fincr__seg {
  display: flex; border: 1px solid var(--line-2);
  border-radius: var(--radius); overflow: hidden;
}
.fincr__seg-btn {
  appearance: none; cursor: pointer; font: inherit; font-size: 14px; font-weight: 600;
  flex: 1 1 0; padding: 10px var(--space-2); border: 0;
  background: var(--surface); color: var(--muted);
}
.fincr__seg-btn + .fincr__seg-btn { border-left: 1px solid var(--line-2); }
.fincr__seg-btn.is-on { background: var(--accent); color: var(--on-accent); }
/* Het veld en 'van € 260,00' op ÉÉN regel: het totaal is geen tweede vraag maar
   de maat waartegen het getypte bedrag gelezen wordt. */
.fincr__amt { display: flex; align-items: center; gap: var(--space-2); }
.fincr__amt-in { flex: 1 1 auto; min-width: 0; }
.fincr__of { color: var(--muted); font-size: 14px; white-space: nowrap; }
.fincr__why, .fincr__note { margin: 0; font-size: 14px; color: var(--ink-2); }
.fincr__done {
  margin: 0; padding: var(--space-3); border-radius: var(--radius);
  background: var(--surface-2, var(--surface)); color: var(--ink); font-size: 14px;
}
