/* RXG Equi Intermotion — UI redesign (Tesstarossa's plan; K.J. approved 20 Oct 2026; Phase 1)
   Wada palette, one job per colour:
     olive   #253121  chrome (sidebar, rail, tab bar), primary buttons, Confirmed
     cream   #FAC55F  "you are here" and "needs you" only: on olive or as a dot, never text on paper
     pink    #F6BDC1  Tentative only, never a button
     citrine #A37821  the logo only
   Phase 2a (21 Oct 2026): the calendar and the session drawer carry no citrine. The client page and
   the phone Day view still carry older citrine marks until Phases 3 and 2b.
*/

:root {
  --color-olive: #253121;
  --color-cream: #FAC55F;
  --color-pink: #F6BDC1;
  --color-citrine: #A37821;

  --color-ink: #1A1F18;
  --color-ink-muted: #3F463A;
  --color-paper: #F7F4EC;
  --color-border: rgba(37, 49, 33, 0.12);
  --color-border-strong: rgba(37, 49, 33, 0.28);
  /* Form-field edges must reach 3:1 (WCAG 1.4.11). 0.28 measured 1.74:1; 0.56 gives
     3.37 on the page, 3.44 on cards and 3.31 on tinted drawers. */
  --color-input-border: rgba(37, 49, 33, 0.56);
  --color-surface-2: #F3EEE2;           /* sunken fill: read-only fields, edit drawers, hover band */
  --color-rule: var(--color-border-strong);
  --color-chip: #2F3A2A;                /* confirmed booking chip fill (paper text 10.9:1) */
  --color-danger: #7A1F1F;              /* the one red: errors, danger actions, negatives */
  --color-focus: var(--color-olive);    /* focus ring: 13.3:1 on the card */

  /* Washes: one hue each, at set strengths (no one-off rgba values in rules). */
  --olive-wash-1: rgba(37, 49, 33, 0.04);
  --olive-wash-2: rgba(37, 49, 33, 0.06);
  --olive-wash-3: rgba(37, 49, 33, 0.08);
  --olive-wash-4: rgba(37, 49, 33, 0.12);
  --olive-wash-5: rgba(37, 49, 33, 0.16);
  --olive-scrim: rgba(37, 49, 33, 0.18);  /* the drawer's scrim (Phase 2a spec 4.1) */
  --ink-wash: rgba(26, 31, 24, 0.12);      /* a tag on a pink chip */
  --olive-line: rgba(37, 49, 33, 0.35);
  --paper-wash: rgba(247, 244, 236, 0.10);
  --cream-wash: rgba(250, 197, 95, 0.35);
  --pink-wash: rgba(246, 189, 193, 0.55);
  --danger-wash: rgba(122, 31, 31, 0.05);
  --danger-line: rgba(122, 31, 31, 0.45);
  --state-pending-fill: color-mix(in srgb, var(--color-pink) 30%, var(--color-surface));
  --color-flash: color-mix(in srgb, var(--color-cream) 25%, var(--color-surface));
  --color-danger-soft: color-mix(in srgb, var(--color-danger) 10%, var(--color-surface));
  /* Year view heat: one hue, light → dark */
  --heat-1: color-mix(in srgb, var(--color-olive) 22%, var(--color-surface));
  --heat-2: color-mix(in srgb, var(--color-olive) 45%, var(--color-surface));
  --heat-3: color-mix(in srgb, var(--color-olive) 70%, var(--color-surface));

  --color-surface: #FFFCF7;
  --color-text: var(--color-ink);
  --color-chrome: var(--color-olive);

  --state-focus-ring: rgba(37, 49, 33, 0.22);  /* field focus halo: olive (citrine is the logo only) */

  --font-display: 'Cormorant Garamond', Georgia, 'Times New Roman', serif;
  --font-body: 'Source Sans 3', system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* Type scale: the only font sizes. --text-* bundle size, weight and line height. */
  --fs-label: 0.75rem;    /* 12px is the smallest text anywhere (plan 2.2) */
  --fs-xs: 0.75rem;       /* small pills, small buttons, calendar day numbers */
  --fs-sm: 0.8125rem;     /* buttons, nav links, status pills (uppercase UI) */
  --fs-chip: 0.85rem;
  --fs-meta: 0.875rem;
  --fs-ui: 0.9375rem;
  --fs-body: 1.0625rem;
  --fs-lead: 1.375rem;    /* side-column headings, balance figure */
  --fs-title: 1.75rem;
  --fs-display-sm: 2.25rem; /* h1 below 1200px, login wordmark */
  --fs-display: 2.75rem;
  --fs-hero: 3rem;
  --fs-brand: 1.85rem;    /* the logo only */

  --text-hero: 700 var(--fs-hero)/1.05 var(--font-display);
  --text-display: 600 var(--fs-display)/1.1 var(--font-display);
  --text-title: 600 var(--fs-title)/1.2 var(--font-display);
  --text-body: 400 var(--fs-body)/1.55 var(--font-body);
  --text-ui: 500 var(--fs-ui)/1.4 var(--font-body);
  --text-label: 600 var(--fs-label)/1.3 var(--font-body);
  --text-chip: 600 var(--fs-chip)/1.25 var(--font-body);
  --text-meta: 400 var(--fs-meta)/1.45 var(--font-body);

  --tracking-hero: -0.02em;
  --tracking-label: 0.12em;
  --tracking-btn: 0;       /* buttons are Title Case with no tracking (plan 2.3, 20 Oct 2026) */

  --space-px: 1px;         /* cell gaps in the dense year grid */
  --space-hair: 0.125rem; /* 2px nudges between stacked text */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 2.5rem;
  --space-8: 3rem;
  --space-10: 4rem;

  --space-page-x: var(--space-8);
  --space-page-y: 2.25rem;
  --space-card: 1.5rem 1.75rem;

  /* Plan 2.4 (20 Oct 2026): cards 16, controls 10, status pills and avatars round */
  --radius: 16px;      /* cards, panels, grid container, tables, login card, modals */
  --radius-sm: 10px;   /* chips, buttons, inputs, selects */
  --radius-xs: 4px;    /* tiny elements (legend swatches, Needs Ack tag) where 8px collapses to a capsule */
  --radius-pill: 999px; /* status pills */

  --shadow-card: 0 1px 2px rgba(37, 49, 33, 0.04), 0 6px 20px rgba(37, 49, 33, 0.05); /* the one soft card shadow (plan 2.5) */
  --shadow-pop: 0 6px 24px rgba(37, 49, 33, 0.18); /* toasts, pop-overs */
  --shadow-float: 0 12px 40px rgba(26, 31, 24, 0.18), 0 2px 6px rgba(26, 31, 24, 0.08); /* the drawer and the toast (Phase 2a) */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1); /* the drawer's entry curve (plan 8) */
  /* Motion tokens (Phase 5A, spec 2.2): every duration in a transition or animation is one of these. */
  --dur-press: 120ms;       /* button press and release */
  --dur-hover: 120ms;       /* colour change on hover (hover devices only) */
  --dur-fold: 200ms;        /* fold chevron turn */
  --dur-toast-in: 200ms;
  --dur-toast-out: 160ms;
  --dur-drawer-in: 260ms;
  --dur-drawer-out: 160ms;
  --dur-sheet-in: 280ms;
  --dur-sheet-out: 180ms;
  --dur-fade-reduced: 150ms; /* the one replacement fade when motion is reduced */
  --dur-busy-delay: 300ms;   /* the busy dim waits this long, so quick actions do not flicker */
  --ring-focus: 0 0 0 3px var(--state-focus-ring); /* fields and date fields on focus */
  --ring-error: 0 0 0 3px var(--danger-wash);
  --shadow-soft: var(--shadow-card); /* section cards: the same one shadow */

  /* App shell (plan section 3): sidebar from 1200px, rail from 744px. */
  --side-w: 248px;
  --rail-w: 88px;
  --on-olive: rgba(247, 244, 236, 0.92);   /* text on the olive chrome */
  --on-olive-2: rgba(247, 244, 236, 0.72); /* quieter text on olive (6.9:1); the phone tab bar too */
  --content-max: 80rem;
  --row-height: 3.25rem;
  /* Phone layout (K.J. 19 Oct 2026): sizes and washes used at 743px and below. */
  --m-tap: 44px;        /* minimum touch target */
  /* T1: the padding that centres a .btn label (line-height 1.2, 1px border) in a 44px box; em is the button's own. */
  --m-btn-pad-y: max(var(--space-2), calc((var(--m-tap) - 1.2em - 2px) / 2));
  /* T1c: the same for a Month session chip (line-height 1.25, no border). */
  --m-mini-pad-y: calc((var(--m-tap) - 1.25em) / 2);
  --m-time-col: 52px;   /* the Today list's time column (Phase 2b) */
  --m-topbar: 56px;
  --m-tabbar: 68px;
  --m-pad: var(--space-4);
  --pinned-top: 0px;    /* the bars pinned to the top and bottom; base.html measures them (Phase 5B) */
  --pinned-bottom: 0px;
  --m-scrim: rgba(26, 31, 24, 0.42);
  --m-paper-80: rgba(247, 244, 236, 0.8);
  --m-card-min: 4.5rem;  /* a Clients row card at least 72px tall (Phase 3a) */
  --client-row: 3.75rem; /* a Clients table row, 60px (Phase 3a) */
  --client-name-min: 8rem;  /* the Name column never squeezes below this (Shiva, 21 Oct 2026) */
  --client-name-max: 20rem; /* a long client name wraps inside this width */
  --m-taken: rgba(63, 70, 58, 0.45);
  --m-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%233F463A' stroke-width='1.8'%3E%3Cpath d='M6 9.5l6 6 6-6'/%3E%3C/svg%3E");
  --rail-bar: 4px;      /* Confirmed / Tentative pill: straight bar, inset 9px */
  --rail-inset: 9px;
  --rail-pad: 20px;

  --bg: var(--color-paper);
  --card: var(--color-surface);
  --ink: var(--color-ink);
  --muted: var(--color-ink-muted);
  --line: var(--color-border);
  --error: var(--color-danger);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: var(--text-body);
  font-family: var(--font-body);
  line-height: 1.55;
  min-height: 100vh;
}

/* —— App shell (UI redesign Phase 1, plan section 3) ———————————————————————————
   1200px and wider: a 248px olive sidebar. 744-1199px: an 88px olive rail. 743px and
   narrower: a paper top bar and an olive tab bar (phone block at the end of this file).
   Olive is the chrome; cream marks "you are here"; the logo is the only citrine. */
.app { min-height: 100vh; display: grid; grid-template-columns: var(--side-w) minmax(0, 1fr); }
.app-body { min-width: 0; }

.side {
  --side-pad: var(--space-4);
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  padding: var(--space-5) var(--side-pad) var(--space-4);
  background: var(--color-chrome);
  color: var(--on-olive);
}
.brand {
  display: block;
  flex: none;
  padding: 0 var(--space-3) var(--space-5);
  color: var(--color-citrine);
  text-decoration: none;
}
.brand-eyebrow {
  display: block;
  font: 600 var(--fs-xs)/1 var(--font-body);
  letter-spacing: 0.22em;
  text-transform: uppercase;
}
.brand-word {
  display: block;
  margin-top: var(--space-1);
  font: 600 var(--fs-brand)/1 var(--font-display);
  letter-spacing: 0.01em;
}
.brand-mono { display: none; font: 600 var(--fs-display-sm)/1 var(--font-display); }

/* The nav scrolls on a short screen; the account block below it never does. */
.side-nav {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  margin: 0 calc(-1 * var(--side-pad));
  padding: var(--space-1) var(--side-pad);  /* room for the focus ring on the first and last item */
}
.nav-group { margin-top: var(--space-4); }
.nav-group:first-child { margin-top: 0; }
.nav-label {
  display: block;
  padding: 0 var(--space-3) var(--space-1);
  font: 600 var(--fs-xs)/1 var(--font-body);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--on-olive-2);
}
.nav-item, .logout-btn {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  min-height: 42px;
  padding: 0 var(--space-3);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--on-olive-2);
  text-decoration: none;
  text-align: left;
  font: 500 var(--fs-ui)/1.2 var(--font-body);
  letter-spacing: 0;
  text-transform: none;
  cursor: pointer;
}
.nav-item svg, .logout-btn svg { width: 20px; height: 20px; flex: none; }
.nav-item.active { color: var(--color-paper); background: var(--paper-wash); }
/* "You are here": a cream bar on the sidebar's own edge. */
.nav-item.active::before {
  content: "";
  position: absolute;
  left: calc(-1 * var(--side-pad));
  top: 10px;
  bottom: 10px;
  width: 3px;
  border-radius: 0 var(--radius-xs) var(--radius-xs) 0;
  background: var(--color-cream);
}

.side-account {
  flex: none;
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--paper-wash);
}
.account-link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 48px;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--color-paper);
  text-decoration: none;
}
.account-link.active { background: var(--paper-wash); }
.avatar {
  display: grid;
  place-items: center;
  flex: none;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--color-cream);
  color: var(--color-olive);
  font: 700 var(--fs-sm)/1 var(--font-body);
  letter-spacing: 0.02em;
  text-decoration: none;
}
.who { display: block; min-width: 0; }
.who-name, .who-role { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.who-name { color: var(--color-paper); font: 600 var(--fs-meta)/1.25 var(--font-body); }
.who-role { color: var(--on-olive-2); font: 400 var(--fs-sm)/1.25 var(--font-body); }
.logout-form { display: block; margin: var(--space-1) 0 0; }
@media (hover: hover) and (pointer: fine) {
  .nav-item:hover, .account-link:hover, .logout-btn:hover { color: var(--color-paper); background: var(--paper-wash); filter: none; }
}
.logout-btn:active { filter: none; }

/* Short screens (a laptop at 1280 x 720): tighter rows keep the whole sidebar in view. */
@media (max-height: 760px) and (min-width: 1200px) {
  .side { padding-top: var(--space-4); }
  .brand { padding-bottom: var(--space-4); }
  .nav-group { margin-top: var(--space-3); }
  .nav-item, .logout-btn { min-height: 38px; }
}

/* 744-1199px: the same items as an 88px rail (icon over a 12px label). */
@media (max-width: 1199px) {
  .app { grid-template-columns: var(--rail-w) minmax(0, 1fr); }
  .side { --side-pad: var(--space-2); padding: var(--space-5) var(--side-pad) var(--space-3); }
  .brand { padding: 0 0 var(--space-4); text-align: center; }
  .brand-eyebrow, .brand-word { display: none; }
  .brand-mono { display: block; }
  .nav-label { display: none; }
  .nav-group { margin-top: var(--space-2); padding-top: var(--space-2); border-top: 1px solid var(--paper-wash); }
  .nav-group:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
  .nav-item, .logout-btn {
    flex-direction: column;
    justify-content: center;
    gap: var(--space-1);
    min-height: 56px;
    padding: var(--space-1) var(--space-hair);
    text-align: center;
    font: 600 var(--fs-xs)/1.15 var(--font-body);
  }
  .side-account { padding-top: var(--space-2); }
  .account-link { justify-content: center; padding: var(--space-1) 0; }
  .who { display: none; }
}

/* Every page starts at the same left edge (plan 2.7); only the width limit differs. */
main {
  padding: var(--space-page-y) var(--space-page-x) var(--space-10);
  max-width: var(--content-max);
  margin: 0;
}
/* Calendar: full width of the page, same left edge */
main:has(.calendar-page) { max-width: none; width: 100%; }
@media (max-width: 1199px) {
  main { padding: var(--space-5) var(--space-6) var(--space-8); }
}
/* Signed out: the sign-in page owns the whole screen. */
body.is-login main { max-width: none; padding: 0; }

main a:not(.btn),
.card a:not(.btn) {
  color: var(--color-olive);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
@media (hover: hover) and (pointer: fine) {
main a:not(.btn):hover,
.card a:not(.btn):hover {
  color: var(--color-ink);
  border-bottom-color: var(--olive-line);
}
}

.card {
  background: var(--card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: var(--space-card);
  box-shadow: var(--shadow-card);
}
.card.narrow {
  min-width: 400px;
  max-width: 440px;
  width: 100%;
  margin: 0 auto;
  padding: var(--space-card);
}

h1 {
  margin-top: var(--space-3);
  margin-bottom: var(--space-6);
  font: var(--text-display);
  font-family: var(--font-display);
  font-size: var(--fs-display) !important;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: var(--tracking-hero);
  color: var(--ink);
}
h1.hero {
  font: var(--text-hero);
  font-family: var(--font-display);
  letter-spacing: var(--tracking-hero);
  margin-bottom: var(--space-5);
}
@media (max-width: 1199px) { h1 { font-size: var(--fs-display-sm) !important; } }
h2 {
  font: var(--text-title);
  font-family: var(--font-display);
  color: var(--ink);
  margin-top: 0;
}
/* Cormorant's own figures are old-style ("18" reads as "ı8"): serif numbers use lining
   figures (plan 2.1). */
h1, h2, h3, .brand-word, .brand-mono, .m-wordmark, .login-wordmark { font-variant-numeric: lining-nums; }
.summary-grid > div:first-child dd strong, .finance-figures > div dd strong, .rate-now strong { font-variant-numeric: lining-nums tabular-nums; }

label {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-2);
  margin: var(--space-3) 0;
  font: var(--text-label);
  font-family: var(--font-body);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--muted);
}
label > input,
label > select,
label > textarea {
  width: 100%;
}

input, select, textarea, button {
  font-family: var(--font-body);
  font-size: var(--fs-ui);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-input-border);
  background: var(--color-surface);
  color: var(--ink);
}

input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--color-olive);
  box-shadow: var(--ring-focus);
}

/* One button language (plan 2.6, K.J. 20 Oct 2026): Primary = olive, one per view; Secondary
   = outline (.btn.ghost or .btn.secondary); Quiet = text (.btn.quiet); Danger = red outline
   (.btn.danger). Title Case in the HTML, never uppercased; citrine is not a button colour. */
button {
  background: var(--color-olive);
  color: var(--color-paper);
  border: 1px solid transparent;
  cursor: pointer;
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--fs-ui);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: var(--tracking-btn);
}
@media (hover: hover) and (pointer: fine) {
  button:hover { filter: brightness(1.3); }
}

/* The sidebar's Log Out (.logout-btn, in the shell above) is the only button drawn on olive;
   scoped to .side, as the old top-bar style was, so no page button turns invisible. */
.inline { display: inline; margin: 0; }

.error { color: var(--error); }
.muted { color: var(--muted); font: var(--text-meta); font-family: var(--font-body); }

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-4);
  align-items: flex-end;
  margin-bottom: var(--space-4);
}
/* Dates as DD/MM/YYYY (follow-up 7): app/static/dmy-date.js puts a text box and a small
   calendar button in front of each native date input, which stays only to carry the ISO
   value and open its picker. */
.dmy { display: inline-flex; align-items: stretch; gap: var(--space-1); position: relative; width: 100%; max-width: 12rem; }
.dmy .dmy-text { flex: 1 1 auto; min-width: 0; font-variant-numeric: tabular-nums; }
.dmy .dmy-pick { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  padding: 0 var(--space-2); background: var(--color-surface); color: var(--color-olive); letter-spacing: normal; }
.dmy .dmy-pick:disabled { opacity: .45; cursor: default; }
input.dmy-native, .date-field input.dmy-native {
  position: absolute !important; inset: auto 0 0 auto !important; width: 1px !important; height: 1px !important;
  opacity: 0 !important; pointer-events: none !important; padding: 0 !important; border: 0 !important; z-index: -1 !important;
}
.date-field.dmy-wrap .date-display { display: none; }
.date-field.dmy-wrap { min-width: 0; }
.dmy .dmy-text[aria-invalid="true"] { border-color: var(--color-danger) !important; }
/* M-07 (Shiva, 19 Oct 2026): in a stacked form the date box sits under its label at full
   width, as the native date input did on f04b02b. Phone already does this; inline and
   filter date fields keep the compact 12rem box. */
@media (min-width: 744px) { .stack-form label .dmy { display: flex; max-width: 100%; } }
/* M-06 (Tesstarossa, 19 Oct 2026): `hidden` always hides, whatever display a class sets. */
[hidden] { display: none !important; }
.filters > label { margin: 0; }
.filters > label:not(.check) {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.filters input[type="date"],
.filters select,
.filters button {
  height: 2.5rem;
  border-radius: var(--radius-sm);
  min-width: 0;
}
.filters button { align-self: flex-end; }
/* Every checkbox: box beside its sentence-case label; the label is part of the
   click target, so the target is the full row (WCAG 2.5.8). */
label.check {
  display: flex;
  flex-direction: row;
  gap: var(--space-2);
  align-items: center;
  min-height: 2.5rem;
  margin: var(--space-2) 0;
  text-transform: none;
  letter-spacing: 0;
  font: var(--text-body);
  font-family: var(--font-body);
  color: var(--ink);
  cursor: pointer;
}
.filters label.check { margin: 0; }
label.check input[type="checkbox"] {
  width: 1.15rem; height: 1.15rem; padding: 0; margin: 0; flex: none;
  accent-color: var(--color-olive);
}

table {
  width: 100%;
  border-collapse: separate; /* lets hover-band end cells take a radius; only border-bottom on cells, so rules stay single hairlines */
  border-spacing: 0;
  font: var(--text-body);
  font-family: var(--font-body);
}
th, td {
  text-align: left;
  padding: var(--space-4) var(--space-3);
  border-bottom: 1px solid var(--line);
  height: var(--row-height);
  vertical-align: middle;
}
th {
  font: var(--text-label);
  font-family: var(--font-body);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--muted);
  height: auto;
  padding-top: var(--space-3);
  padding-bottom: var(--space-3);
}

/* Bookings: no pink-wash rows / rails — paper only */
tr.tentative,
tr.review {
  background: transparent;
  box-shadow: none;
}
@media (hover: hover) and (pointer: fine) {
.bookings-table tbody tr:hover,
table:not(.cal-grid):not(.cal-month):not(.year-mini) tbody tr:hover {
  background: transparent; /* hover band painted on cells so its ends can round */
}
.bookings-table tbody tr:hover > td,
.bookings-table tbody tr:hover > th,
table:not(.cal-grid):not(.cal-month):not(.year-mini) tbody tr:hover > td,
table:not(.cal-grid):not(.cal-month):not(.year-mini) tbody tr:hover > th {
  background: var(--color-surface-2);
}
.bookings-table tbody tr.tentative:hover,
.bookings-table tbody tr.review:hover {
  background: transparent;
  box-shadow: none;
}
/* Rounded ends on the hover band (frameless ledger inside the rounded card) */
table:not(.cal-grid):not(.cal-month):not(.year-mini) tbody tr:hover > :first-child {
  border-top-left-radius: var(--radius-sm);
  border-bottom-left-radius: var(--radius-sm);
}
table:not(.cal-grid):not(.cal-month):not(.year-mini) tbody tr:hover > :last-child {
  border-top-right-radius: var(--radius-sm);
  border-bottom-right-radius: var(--radius-sm);
}
}

/* —— Calendar page, toolbar and session states (UI redesign Phase 2a, spec 2-3; K.J. 21 Oct 2026) ——
   The title and Book Session sit in the page header above the card. The toolbar is one
   row: Today, arrows, range, Day / Week / Month, coach filter, "N to mark". */
.calendar-page {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
  position: relative;
  width: 100%;
  align-items: start;
}
#calendar-root,
#bookings-root {
  min-width: 0;
  width: 100%;
}

.icon-btn {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-olive);
  cursor: pointer;
}
.icon-btn svg { width: 20px; height: 20px; }
@media (hover: hover) and (pointer: fine) {
  .icon-btn:hover, main a.icon-btn:hover { background: var(--olive-wash-2); filter: none; color: var(--color-olive); }
}
main a.icon-btn { border-bottom: 0; }

.cal-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  margin: 0 0 var(--space-4);
}
.cal-stepper { display: inline-flex; align-items: center; gap: var(--space-1); }
.cal-stepper .btn { display: inline-flex; align-items: center; min-height: 44px; padding-top: 0; padding-bottom: 0; }
.cal-range {
  margin: 0 var(--space-2) 0 var(--space-1);
  font: var(--text-title);
  font-variant-numeric: lining-nums;
  color: var(--ink);
}
.cal-spacer { flex: 1 1 0; }
/* Day / Week / Month: a segmented control made of links. */
.cal-switch { display: inline-flex; padding: var(--space-hair); border-radius: var(--radius-sm); background: var(--color-surface-2); }
main .cal-switch a {
  display: inline-flex;
  align-items: center;
  min-height: 38px;
  padding: 0 var(--space-4);
  border-bottom: 0;
  border-radius: calc(var(--radius-sm) - var(--space-hair));
  font: 600 var(--fs-meta)/1 var(--font-body);
  color: var(--muted);
}
@media (hover: hover) and (pointer: fine) {
  main .cal-switch a:hover { color: var(--ink); border-bottom: 0; }
}
main .cal-switch a.active, main .cal-switch a.active:hover { background: var(--color-surface); color: var(--ink); box-shadow: 0 1px 2px var(--olive-wash-4); }
.cal-coach { margin: 0; }
.cal-coach select { width: auto; min-width: 9.5rem; min-height: 44px; }
.cal-coach-label { display: inline-flex; align-items: center; min-height: 44px; padding: 0 var(--space-2); font: 600 var(--fs-ui)/1 var(--font-body); color: var(--ink); }
.chip.to-mark {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: 0 var(--space-4);
  border-radius: var(--radius-pill);
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface);
  color: var(--ink);
  font: 600 var(--fs-meta)/1 var(--font-body);
}
@media (hover: hover) and (pointer: fine) {
  .chip.to-mark:hover { background: var(--color-surface-2); filter: none; }
}
/* The cream dot means "needs you"; its olive ring keeps it visible on pale fills. */
.dot-cream, .pill.status-needs-ack::before {
  content: "";
  display: inline-block;
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-cream);
  box-shadow: 0 0 0 1px var(--olive-line);
}
.year-link { display: flex; justify-content: flex-end; margin: var(--space-3) 0 0; }
.cal-note { margin: 0 0 var(--space-4); }

.cal-scroll {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--color-border);
  border-radius: var(--radius); /* overflow-x:auto clips grid to curve; interior cell lines stay square */
  background: var(--color-surface);
}
.cal-grid {
  width: 100%;
  min-width: 0;
  border-collapse: separate;
  border-spacing: 0;
  table-layout: fixed;
  font: var(--text-chip);
  font-family: var(--font-body);
}
.cal-grid th, .cal-grid td {
  border-bottom: 1px solid var(--line);
  border-right: 1px solid var(--line);
  vertical-align: top;
  padding: var(--space-1);
  height: auto;
}
/* Outer edge belongs to .cal-scroll's 1px border — no doubled line running into the 16px curve */
.cal-grid tr > :last-child { border-right: 0; }
.cal-grid tbody tr:last-child > th,
.cal-grid tbody tr:last-child > td { border-bottom: 0; }
.cal-grid thead th {
  position: sticky;
  top: 0;
  background: var(--color-paper);
  z-index: 1;
  text-align: center;
  padding: var(--space-3) var(--space-1);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--muted);
  font: var(--text-label);
  font-family: var(--font-body);
}
.cal-grid .time-col {
  width: 3.6rem;
  text-align: right;
  padding-right: var(--space-2);
  color: var(--muted);
  font-weight: 600;
  font: var(--text-meta);
  font-family: var(--font-body);
  background: var(--color-paper);
}
.cal-grid .dow {
  display: block;
  font-weight: 600;
  color: var(--ink);
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--fs-ui);
  font-family: var(--font-body);
  margin-top: var(--space-hair);
}
.cal-grid .dom {
  display: block;
  font-size: var(--fs-xs);
  color: var(--muted);
  font-weight: 400;
}
.cal-grid th.today {
  background: var(--olive-wash-2);
  box-shadow: inset 0 3px 0 var(--color-olive);
}
/* Tesstarossa's look pass on Phase 2a (21 Oct 2026): today's column body is unwashed, so it
   never looks like a weekend; today is told by the olive bar on its header. */
.cal-grid td.today {
  background: transparent;
}
.cal-grid th.weekend, .cal-grid td.weekend {
  background: var(--olive-wash-1);
}
.cal-grid th.today.weekend {
  background: var(--olive-wash-3);
  box-shadow: inset 0 3px 0 var(--color-olive);
}
.cal-grid td.today.weekend {
  background: transparent;  /* a today that falls on a weekend is treated the same way */
}
/* Day: one column, wide enough to read; the hour column stays narrow. */
.cal-grid.cal-day thead th:not(.time-col) { text-align: left; padding-left: var(--space-4); }
/* On an iPad the seven days keep a readable width and scroll inside the card, never the page. */
@media (max-width: 1199px) {
  .cal-grid:not(.cal-day) { min-width: 760px; }
}
/* Phase 2c (spec 9, K.J. 21 Oct 2026): Day by coach. Each coach's column is at least 116px, so
   four fit on an upright iPad from 744px and more scroll sideways inside the card. While the grid
   scrolls sideways the hour column stays put, and a soft fade at the right edge says there is more. */
.cal-grid.by-coach { --cols: 1; min-width: calc(3.6rem + var(--cols) * 116px); }
.cal-grid .time-col { position: sticky; left: 0; z-index: 4; }
.cal-grid thead .time-col { z-index: 5; }
.cal-grid.by-coach thead th.coach-head {
  text-align: left;
  text-transform: none;
  letter-spacing: 0;
  padding: var(--space-2) var(--space-3);
  color: var(--ink);
}
.coach-head-in { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
.coach-head .avatar { width: 30px; height: 30px; font-size: var(--fs-xs); background: var(--color-surface-2); }
.coach-who { display: block; min-width: 0; }
.coach-name, .coach-count { display: block; overflow-wrap: anywhere; }  /* wraps, never cut off */
.coach-name { font: 600 var(--fs-ui)/1.2 var(--font-body); }
.coach-count { font: 400 var(--fs-xs)/1.3 var(--font-body); color: var(--muted); }
.coach-count > span { white-space: nowrap; }  /* breaks between "2 sessions" and "1 to mark" only */
.cal-scroll-wrap { position: relative; }
/* A slot reached with the arrow keys stops clear of the hour column and the fade. */
.cal-scroll { scroll-padding-left: 3.6rem; scroll-padding-right: 36px; }
.cal-scroll-wrap::after {
  content: "";
  position: absolute;
  top: 1px;
  right: 1px;
  bottom: 1px;
  width: 36px;
  border-radius: 0 var(--radius) var(--radius) 0;
  background: linear-gradient(90deg, transparent, var(--color-surface));
  opacity: 0;
  pointer-events: none;
  z-index: 6;
}
.cal-scroll-wrap.fade::after { opacity: 1; }
/* Narrow columns (an iPad) give the name the room; the avatar shows on desktop. */
@media (max-width: 1199px) {
  .coach-head .avatar { display: none; }
}
/* One "now" dot, at the left end of the line, not one per coach. */
.cal-grid.by-coach td.slot + td.slot .now-line::before { display: none; }

/* One hour is 66px (spec 3.7): a name, "09:00 · Coach" and a state tag fit on three lines. */
.slot {
  position: relative;
  height: 66px;
  min-height: 66px;
  padding: var(--space-hair);
}
.slot.empty { cursor: pointer; }
.slot-add {
  width: 100%;
  height: 100%;
  min-height: 2.75rem; /* 44px tap area */
  background: transparent;
  color: var(--muted);
  border: 1px dashed transparent;
  padding: 0;
  font-size: var(--fs-body);
  line-height: 1;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  opacity: 0;
  transition: opacity var(--dur-hover) ease, background var(--dur-hover) ease, border-color var(--dur-hover) ease;
}
.slot-add:focus,
.slot-add:focus-visible {
  opacity: 1;
}
@media (hover: hover) and (pointer: fine) {
  .slot.empty:hover .slot-add { opacity: 1; }
}
/* Touch screens have no hover: show the "+" all the time there. Coarse pointers too (Tesstarossa on 5A,
   26 Oct 2026): a touch tablet or stylus phone can report hover and match neither this nor the mouse rule. */
@media (hover: none), (pointer: coarse) {
  .slot-add { opacity: 1; border-color: var(--olive-line); }
}
.slot-add:focus,
.slot-add:focus-visible {
  border-color: var(--color-olive);
  color: var(--color-olive);
  background: var(--olive-wash-1);
  filter: none;
  opacity: 1;
}
@media (hover: hover) and (pointer: fine) {
  .slot-add:hover {
    border-color: var(--color-olive);
    color: var(--color-olive);
    background: var(--olive-wash-1);
    filter: none;
    opacity: 1;
  }
}
/* The "now" line: static, set when the page is drawn (spec 3.6). */
.now-line {
  position: absolute;
  left: 0;
  right: 0;
  height: 0;
  border-top: 2px solid var(--color-olive);
  z-index: 3;
  pointer-events: none;
}
.now-line::before {
  content: "";
  position: absolute;
  left: 0;
  top: -6px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--color-olive);
}

/* Session states (spec 2). Confirmed = olive. Not Marked = olive with a cream dot.
   Tentative = pink. Done = sunk grey. No-show = a red outline. Plan = paper with a
   dashed edge; Clash adds a red tag. No rail, no citrine. */
.lanes { display: flex; flex-wrap: wrap; gap: var(--space-hair); }
button.booking-chip,
.booking-chip {
  position: relative;
  display: flex;
  flex: 1 1 100%;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-hair);
  width: 100%;
  min-width: 0;
  min-height: 60px;
  text-align: left;
  background: var(--color-olive);
  color: var(--color-paper);
  border: 0 none transparent;
  box-shadow: none;
  border-radius: var(--radius-sm);
  overflow: hidden;
  padding: var(--space-1) var(--space-2);
  font: var(--text-chip);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: 0;
  text-transform: none;
  cursor: pointer;
  white-space: normal;
}
button.booking-chip.narrow, .booking-chip.narrow { flex: 1 1 calc(50% - var(--space-hair)); min-height: 44px; padding: var(--space-1); }
@media (hover: hover) and (pointer: fine) {
  button.booking-chip:hover, .booking-chip:hover { background: var(--color-chip); filter: none; }
}
.booking-chip .name,
.booking-chip .sub {
  display: block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.booking-chip .sub { font-size: var(--fs-xs); font-weight: 500; opacity: 0.85; }
.booking-chip .tags { display: flex; flex-wrap: wrap; gap: var(--space-1); }
.booking-chip .tag {
  display: inline-block;
  padding: 0 var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--paper-wash);
  font-size: var(--fs-label);
  line-height: 16px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  white-space: nowrap;
}
/* Not Marked: a cream dot, nothing more (spec 2.2). */
.booking-chip.needs-ack::after {
  content: "";
  position: absolute;
  top: 8px;
  right: 8px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-cream);
  box-shadow: 0 0 0 1px var(--olive-line);
}
.booking-chip.needs-ack .name { padding-right: var(--space-3); }
button.booking-chip.tentative, .booking-chip.tentative { background: var(--color-pink); color: var(--ink); }
.booking-chip.tentative .tag { background: var(--ink-wash); }
@media (hover: hover) and (pointer: fine) {
  button.booking-chip.tentative:hover, .booking-chip.tentative:hover { background: var(--color-pink); filter: brightness(0.96); }
}
button.booking-chip.completed, .booking-chip.completed {
  background: var(--color-surface-2);
  color: var(--muted);
  box-shadow: inset 0 0 0 1px var(--color-border);
}
.booking-chip.completed .tag { background: var(--olive-wash-3); }
button.booking-chip.no-show, .booking-chip.no-show {
  background: var(--color-surface);
  color: var(--color-danger);
  box-shadow: inset 0 0 0 1.5px var(--color-danger);
}
.booking-chip.no-show .tag { background: var(--danger-wash); box-shadow: inset 0 0 0 1px var(--danger-line); }
@media (hover: hover) and (pointer: fine) {
  button.booking-chip.completed:hover, .booking-chip.completed:hover,
  button.booking-chip.no-show:hover, .booking-chip.no-show:hover { background: var(--olive-wash-3); }
}
/* Check entry (from the Sheet): the small tag only; red outlines belong to No-show. */
.booking-chip .tag.review {
  background: var(--color-surface);
  color: var(--color-danger);
}
/* KJ #2: a planned Fixed Weekly session: not yet booked, so no fill and a dashed edge
   (muted text 9.5:1). Clash = that coach already has a booking then; red on the tag only. */
button.booking-chip.planned, .booking-chip.planned {
  background: var(--color-paper);
  color: var(--muted);
  font-weight: 500;
  border: 1px dashed var(--color-input-border);
  padding: calc(var(--space-1) - var(--space-px)) calc(var(--space-2) - var(--space-px));
  box-shadow: none;
}
.booking-chip.planned.narrow { padding: calc(var(--space-1) - var(--space-px)); }
.booking-chip.planned .tag { background: transparent; box-shadow: inset 0 0 0 1px var(--color-input-border); }
.booking-chip.planned.clash .tag { background: var(--color-danger); color: var(--color-paper); box-shadow: none; }
@media (hover: hover) and (pointer: fine) {
  button.booking-chip.planned:hover, .booking-chip.planned:hover { background: var(--color-surface-2); color: var(--ink); }
}

/* The key: five items (spec 2). */
.legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  align-items: center;
  margin-top: var(--space-4);
  font: var(--text-meta);
  font-family: var(--font-body);
  color: var(--muted);
}
.legend.key > span { display: inline-flex; align-items: center; gap: var(--space-2); }
.swatch {
  position: relative;
  display: inline-block;
  flex: none;
  width: 14px;
  height: 14px;
  border-radius: var(--radius-xs);
  box-sizing: border-box;
}
.swatch.confirmed { background: var(--color-olive); }
.swatch.tentative { background: var(--color-pink); }
.swatch.completed { background: var(--color-surface-2); box-shadow: inset 0 0 0 1px var(--color-border-strong); }
.swatch.needs-ack { background: var(--color-olive); }
.swatch.needs-ack::after {
  content: "";
  position: absolute;
  top: 2px;
  right: 2px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--color-cream);
}
.swatch.planned { background: var(--color-paper); border: 1.5px dashed var(--color-input-border); }

.flash {
  background: var(--cream-wash);
  color: var(--color-olive);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius);
  border: 1px solid var(--color-border-strong);
  font: var(--text-body);
  font-family: var(--font-body);
}

/* Pages that redirect to an anchor (#packages, #leave) pin the message to the
   viewport so it is seen wherever the page lands. */
.flash-toast {
  position: fixed;
  top: 0.75rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1000;
  width: max-content;
  max-width: min(640px, calc(100vw - 32px));
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  background: var(--color-flash);
  box-shadow: var(--shadow-pop);
}
/* Phone trial fix F7 (K.J. 2 Nov 2026): on the client and leave pages the message sits in the page under
   the title instead of covering it; it floats as above only when the page lands on a section (#packages).
   The skip link's #main is not a section. */
body:not(:has(:target:not(#main))) .flash-toast[data-in-page] {
  position: static;
  transform: none;
  width: auto;
  max-width: none;
  justify-content: space-between;  /* the bar is the page's width: × at its end */
  margin: 0 0 var(--space-4);
  box-shadow: none;
}
.flash-toast.flash-error {
  background: var(--color-danger-soft);
  color: var(--error);
  border-color: var(--danger-line);
}
.flash-close {
  background: transparent;
  border: none;
  color: inherit;
  padding: 0 var(--space-1);
  font-size: var(--fs-body);
  line-height: 1;
  cursor: pointer;
}

.booking-panel .panel-card {
  background: var(--card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: var(--space-6) var(--space-5);
  position: sticky;
  top: 0.75rem;
  box-shadow: var(--shadow-card);
}
.panel-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}
.panel-head h2 { margin: 0; }
.panel-actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-4);
}
.panel-actions form { width: 100%; margin: 0; }
.panel-actions .btn,
.panel-actions button,
.booking-panel .stack .btn,
.booking-panel form > button[type="submit"] {
  width: 100%;
  display: block;
  text-align: center;
}
.booking-panel .stack .btn { margin-top: var(--space-2); }

.btn, a.btn {
  display: inline-block;
  text-align: center;
  background: var(--color-olive);
  color: var(--color-paper);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-5);
  text-decoration: none;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: var(--fs-ui);
  font-weight: 600;
  letter-spacing: var(--tracking-btn);
  line-height: 1.2;
}
@media (hover: hover) and (pointer: fine) {
  .btn:hover, a.btn:hover { filter: brightness(1.3); }
}
/* Secondary: outline. (.ghost and .secondary are the same button; pink is never a button.) */
.btn.ghost, a.btn.ghost, .btn.secondary, a.btn.secondary {
  background: var(--color-surface);
  color: var(--color-olive);
  border: 1px solid var(--color-input-border);
  filter: none;
}
@media (hover: hover) and (pointer: fine) {
  .btn.ghost:hover, a.btn.ghost:hover, .btn.secondary:hover, a.btn.secondary:hover {
    background: var(--color-surface-2);
    filter: none;
  }
}
/* Quiet: text only, for the least important action beside a primary. */
.btn.quiet, a.btn.quiet {
  background: transparent;
  color: var(--color-olive);
  border-color: transparent;
  padding-left: var(--space-3);
  padding-right: var(--space-3);
  filter: none;
}
@media (hover: hover) and (pointer: fine) {
  .btn.quiet:hover, a.btn.quiet:hover { background: var(--olive-wash-2); filter: none; }
}
/* Danger: red outline. */
.btn.danger {
  background: var(--color-surface);
  color: var(--error);
  border: 1px solid var(--danger-line);
  filter: none;
}
@media (hover: hover) and (pointer: fine) {
  .btn.danger:hover { background: var(--danger-wash); filter: none; }
}
.btn.small {
  padding: var(--space-2) var(--space-3);
  font-size: var(--fs-xs);
}

.stack label { margin-top: var(--space-2); }

@media (max-width: 700px) {
  main { padding: var(--space-4); }
  .card { padding: var(--space-5); }
  .card.narrow {
    min-width: 0;
    max-width: 100%;
    padding: var(--space-6) var(--space-5);
  }
  .cal-grid { min-width: 640px; width: 100%; }
  h1 { font-size: var(--fs-display-sm); }
  h1.hero { font-size: var(--fs-display-sm); }
  .login-club { padding: var(--space-6) var(--space-4); }
  .login-wordmark { font-size: var(--fs-display-sm); }
}

/* Packages / remaining — ink/muted only, never citrine */
.warn-text {
  color: var(--color-ink-muted);
  font-weight: 650;
}
.muted-row { opacity: 0.65; }
.inline-form { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
/* Rows with fields (Add Leave, Client Away, Link With): line up on the boxes' bottom
   edge and give the button the boxes' height, like the filter bars. */
.inline-form:has(> label) { align-items: flex-end; }
.inline-form:has(> label) > label { margin-bottom: 0; }
.inline-form:has(> label) > label :is(input, select),
.inline-form > label ~ button { height: 2.5rem; }
.row-actions { white-space: nowrap; }
.small { font: var(--text-meta); font-family: var(--font-body); }
label.block { display: block; margin-bottom: var(--space-2); }

.narrow-form { max-width: 560px; }
.stack-form label { display: block; margin: var(--space-3) 0; }
.stack-form input[type="text"],
.stack-form input[type="email"],
.stack-form input[type="tel"],
.stack-form input[type="date"],
.stack-form select,
.stack-form textarea {
  width: 100%;
  max-width: 100%;
}
/* Plan AM1: a closed box (the area postcodes before Yes) reads closed, like a disabled button. */
.stack-form input:disabled,
.stack-form select:disabled {
  background: var(--olive-wash-2);
  color: var(--muted);
  border-style: dashed;
  cursor: not-allowed;
}
/* Plan AM1 (Tesstarossa's look pass): one answer per line; each country box beside its postcode. */
.area-box label.radio { display: flex; margin: 0 0 var(--space-2); }
.area-pair { display: grid; grid-template-columns: minmax(0, 1fr) 4.5rem; gap: var(--space-3); }
.pdpa-note {
  font: var(--text-meta);
  font-family: var(--font-body);
  color: var(--color-ink-muted);
  font-weight: 400;
}
.detail-grid {
  display: grid;
  grid-template-columns: 10rem 1fr;
  gap: var(--space-2) var(--space-4);
  margin: 0 0 var(--space-5);
}
.detail-grid dt {
  color: var(--muted);
  font: var(--text-label);
  font-family: var(--font-body);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}
.detail-grid dd { margin: 0; font: var(--text-body); font-family: var(--font-body); }

.tag-pill {
  display: inline-block;
  font: var(--text-chip);
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  vertical-align: middle;
  margin-left: var(--space-1);
  background: var(--olive-wash-3);
  color: var(--ink);
  letter-spacing: 0;
  text-transform: none;
}
.tag-pill.inactive {
  background: var(--olive-wash-3);
  color: var(--muted);
}

.danger-zone {
  margin: var(--space-4) 0 var(--space-5);
  padding: var(--space-4) var(--space-4);
  border: 1px solid var(--danger-line);
  background: var(--danger-wash);
  border-radius: var(--radius);
}
.danger-zone form { margin: var(--space-2) 0; }
.perm-delete { margin-top: var(--space-3); }
.perm-delete summary { cursor: pointer; color: var(--error); font-weight: 600; }
hr { border: none; border-top: 1px solid var(--line); margin: var(--space-5) 0; }

/* Status pills: soft (match source chips); tentative = pink tint + 5px rail */
.pill {
  display: inline-block;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  overflow: hidden;
  font: var(--text-chip);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: 500;
  letter-spacing: 0.02em;
  line-height: 1.3;
  white-space: nowrap;
  border: 0 none transparent;
  box-sizing: border-box;
}
/* Confirmed / Tentative pill rail (K.J. 19 Oct 2026, phone spec v2): a straight 4px bar
   with square ends, inset 9px, instead of an inset shadow that bent into a crescent on
   the 999px pill. */
.pill.status-tentative,
.pill.status-confirmed {
  position: relative;
  color: var(--color-olive);
  border-left: 0 none transparent !important;
  padding-left: var(--rail-pad);
  font-weight: 600;
}
.pill.status-tentative { background: var(--state-pending-fill); }
.pill.status-confirmed { background: var(--olive-wash-3); }
.pill.status-tentative::before,
.pill.status-confirmed::before {
  content: "";
  position: absolute;
  left: var(--rail-inset);
  top: calc(50% - 6px);
  width: var(--rail-bar);
  height: 12px;
  border-radius: 0;
  background: var(--color-citrine);
}
.pill.status-tentative::before { background: var(--color-pink); }
.pill.status-completed {
  background: var(--olive-wash-4);
  color: var(--color-olive);
}
.pill.status-cancelled,
.pill.status-no_show {  /* Plan C1: a no-show, like a cancellation, used no session */
  background: var(--olive-wash-3);
  color: var(--muted);
}
.pill.source,
.pill.trial {
  background: var(--olive-wash-2);
  color: var(--muted);
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
}


/* —— Date inputs: ISO under the hood, display like "13 Nov 2026" —— */
.date-field {
  position: relative;
  display: block;
  width: 100%;
  min-width: 9.75rem;
  min-height: 2.5rem;
}
.date-field .date-display {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 2.5rem;
  padding: var(--space-2) var(--space-3);
  background: var(--color-surface);
  border: 1px solid var(--color-input-border);
  border-radius: var(--radius-sm);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-ui);
  line-height: 1.3;
  pointer-events: none;
  white-space: nowrap;
}
.date-field .date-display.is-empty {
  color: var(--muted);
}
/* K.J. 3 Nov 2026: under Reschedule's date, a muted "Leave" when the coach is on approved leave that day. */
.date-leave { display: block; margin-top: var(--space-1); font: 500 var(--fs-sm)/1.3 var(--font-body); letter-spacing: normal; text-transform: none; color: var(--color-ink-muted); }  /* inside the field's label */
.date-leave[hidden] { display: none; }
.date-field input[type="date"],
.date-field input[data-date-input] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  opacity: 0;
  cursor: pointer;
  border: none;
  background: transparent;
  color-scheme: light;
  z-index: 2;
  -webkit-appearance: none;
  appearance: none;
}
.date-field:focus-within .date-display {
  border-color: var(--color-olive);
  box-shadow: var(--ring-focus);
}
/* Hide native calendar glyph (picker still opens via transparent overlay).
   The overlay is absolutely positioned, so a plain date input must be its
   containing block — otherwise it stretches to the page and adds a sideways scroll. */
input[type="date"] { position: relative; }
input[type="date"]::-webkit-calendar-picker-indicator {
  opacity: 0;
  display: block;
  width: 100%;
  height: 100%;
  cursor: pointer;
  position: absolute;
  inset: 0;
}
input[type="time"] {
  color-scheme: light;
  appearance: none;
  -webkit-appearance: none;
  min-height: 2.5rem;
  background: var(--color-surface);
  border: 1px solid var(--color-input-border);
  border-radius: var(--radius-sm);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-ui);
  padding: var(--space-2) var(--space-3);
}
.empty-hint {
  margin: 0 0 var(--space-4);
  font: var(--text-meta);
  font-family: var(--font-body);
}
.empty-cell {
  color: var(--muted);
  font-weight: 400;
}


/* —— Login: club presence —— */
.login-club {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: var(--space-8) var(--space-5) var(--space-10);
  gap: var(--space-7);
}
.login-masthead {
  text-align: center;
  max-width: 32rem;
}
.login-kicker {
  margin: 0 0 var(--space-3);
  font: var(--text-label);
  font-family: var(--font-body);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--color-ink-muted);
}
.login-wordmark {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-hero);
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--color-citrine);  /* Phase 4e (3.16): the whole wordmark is the logo, so all citrine */
}
.login-wordmark em {
  font-style: italic;
  font-weight: 500;
  color: inherit;
}
.login-tagline {
  margin: var(--space-4) 0 0;
  font: var(--text-meta);
  font-family: var(--font-body);
  color: var(--color-ink-muted);
  letter-spacing: 0.04em;
}
.login-club .card.narrow {
  margin: 0;
}
.login-club .card.narrow form label {
  margin: 0 0 var(--space-4);
}
.login-club .card.narrow form button[type="submit"] {
  width: 100%;
  margin-top: var(--space-2);
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-5);
}
.card.narrow form label {
  margin: 0 0 var(--space-4);
}
.card.narrow form button[type="submit"] {
  width: 100%;
  margin-top: var(--space-1);
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-5);
}


/* P1 session ledger / coach signup */
.company-total { margin-top: var(--space-4); font-size: var(--fs-body); }
.row-actions form { display: inline-block; margin-right: var(--space-1); }
button.danger { background: transparent; color: var(--color-danger); border-color: var(--color-danger); }


/* P2 client activity + balance sessions */
.client-id-tag {
  margin-left: var(--space-2);
  font: var(--text-meta);
  font-family: var(--font-body);
  font-weight: 500;
  color: var(--color-ink-muted);
  letter-spacing: 0.04em;
}
.balance-sessions {
  margin: var(--space-1) 0 var(--space-3);
  font: var(--text-body);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  color: var(--color-olive);
}
.balance-sessions strong {
  font-size: var(--fs-lead);
  font-weight: 650;
}
.balance-sessions.balance-zero,
.balance-sessions.balance-zero strong,
.balance-sessions.balance-negative,
.balance-sessions.balance-negative strong {
  color: var(--color-danger);
}
.balance-active-note {
  margin: calc(-1 * var(--space-2)) 0 var(--space-3);
}
.packages-history td { vertical-align: top; }
.pkg-summary {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  margin: 0 0 var(--space-4);
}
.pkg-summary > div { display: flex; flex-direction: column; gap: var(--space-hair); }
.pkg-summary dt {
  font: var(--text-meta);
  font-family: var(--font-body);
  color: var(--muted);
}
.pkg-summary dd { margin: 0; font-family: var(--font-body); color: var(--ink); }
.weekly-end-date {
  margin: var(--space-1) 0 var(--space-3);
  font-family: var(--font-body);
  color: var(--color-olive);
}
.weekly-end-date strong { font-weight: 650; }
.shared-pill { margin-left: var(--space-1); }
.pkg-members .member-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  margin: var(--space-1) 0;
}
.pkg-members .member-link label { display: block; margin: var(--space-1) 0; font-size: var(--fs-chip); }
.pkg-members select { width: 100%; max-width: 12rem; }
.filters select.member-multi { height: auto; min-width: 11rem; }
input[readonly] { background: var(--color-surface-2); color: var(--muted); }
.pkg-actions { white-space: nowrap; }
.pkg-edit { display: inline-block; margin-right: var(--space-1); }
.pkg-edit summary {
  cursor: pointer;
  padding-block: var(--space-hair);  /* 24px target (WCAG 2.5.8) */
  font: var(--text-meta);
  color: var(--color-olive);
}
.pkg-edit-form {
  margin-top: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--color-rule);
  border-radius: var(--radius);
  background: var(--color-surface-2);
  min-width: 14rem;
}
.pkg-edit-form label { display: block; margin: var(--space-1) 0; font-size: var(--fs-chip); }
.pkg-edit-form input { width: 100%; max-width: 12rem; }
/* C4 Refund / transfer: the field that doesn't apply is hidden (form labels are block). */
.adjust-form [hidden] { display: none; }
/* Each on its own line, so the actions column doesn't widen the table (measured at
   1366 px: one line 1517 px of table, stacked 1198 px; before C4 1243 px). */
.pkg-adjust, .pkg-adjust-history { display: block; margin-top: var(--space-1); }
.adjust-list { list-style: none; margin: 0; padding: 0; white-space: normal; }
.adjust-list li + li { margin-top: var(--space-3); padding-top: var(--space-3); border-top: 1px solid var(--color-rule); }
.activity-scroll {
  max-height: calc(2.5rem + 10 * var(--row-height));
  overflow-y: auto;
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  /* overflow already auto both axes → clips table to curve */
  background: var(--color-surface);
}
.activity-scroll .activity-table {
  margin: 0;
}
.activity-scroll thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--color-surface);
  box-shadow: 0 1px 0 var(--line);
}
.activity-table .activity-when { white-space: nowrap; font-variant-numeric: tabular-nums; }
.activity-kind {
  display: inline-block;
  padding: var(--space-hair) var(--space-2);
  border-radius: var(--radius-pill);
  font: var(--text-meta);
  background: var(--olive-wash-3);
  color: var(--color-olive);
}
.activity-kind.kind-package_purchased { background: var(--olive-wash-4); }
/* Phase 3c: kinds follow the colour roles (cream only for needs-you, pink only for Tentative, red only for No-show). */
.activity-kind.kind-session_completed, .activity-kind.kind-package_deactivated, .activity-kind.kind-package_deleted { background: var(--color-surface-2); color: var(--color-ink-muted); }
.activity-kind.kind-booking_cancelled { background: var(--color-surface); color: var(--color-ink-muted); box-shadow: inset 0 0 0 var(--space-px) var(--color-border-strong); }
.activity-kind.kind-booking_no_show { background: var(--color-surface); color: var(--color-danger); box-shadow: inset 0 0 0 var(--space-px) var(--danger-line); }
.amount-plus { color: var(--color-olive); font-weight: 600; }

.pkg-actions .btn.danger.small {
  background: transparent;
  color: var(--color-danger);
  border: 1px solid var(--danger-line);
}
@media (hover: hover) and (pointer: fine) {
  .pkg-actions .btn.danger.small:hover { background: var(--danger-wash); }
}


/* BUG-007 beta overdraw — unmistakable, not a hard block */
.flash.overdraw-banner,
.overdraw-banner {
  background: var(--pink-wash);
  border: 2px solid var(--danger-line);
  color: var(--color-ink);
  font-weight: 600;
  padding: var(--space-3) var(--space-4);
}
.overdraw-text {
  color: var(--color-danger);
  font-weight: 700;
}
.tag-pill.overdraw-pill {
  background: var(--color-pink);
  color: var(--color-ink);
  font-size: var(--fs-label);
  margin-left: var(--space-1);
}
/* Plan 6b: a balance owed, and a package's payments (existing tokens only). */
.tag-pill.owed-pill {
  background: var(--pink-wash);
  color: var(--color-ink);
  font-size: var(--fs-label);
}
.pay-list {
  list-style: none;
  margin: 0 0 var(--space-2);
  padding: 0;
}
.pay-list li {
  display: grid;
  gap: var(--space-1);
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--color-border);
}
.pay-list li.voided { color: var(--color-ink-muted); }

.session-when { color: var(--color-text); }

/* P5: fully redeemed package (palette-locked: existing ink/muted tints only) */
.tag-pill.completed-pill {
  background: var(--olive-wash-5);
  color: var(--ink);
  font-weight: 600;
}

/* P6: idle sign-out countdown (palette-locked) */
.idle-warning {
  position: fixed; left: 50%; bottom: 1.25rem; transform: translateX(-50%); z-index: 1000;
  background: var(--color-olive); color: var(--color-paper); padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-sm); font-family: var(--font-body); font-size: var(--fs-meta);
  box-shadow: var(--shadow-pop);
}
.idle-warning[hidden] { display: none; }

/* P7: Client Summary card (palette-locked: theme surface, border, radius) */
.client-summary {
  margin: var(--space-3) 0 var(--space-4); padding: var(--space-3) var(--space-4) var(--space-2);
  background: var(--color-surface); border: 1px solid var(--line); border-radius: var(--radius);
}
.client-summary .summary-title { margin: 0 0 var(--space-2); font-size: var(--fs-body); }
.summary-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(11.5rem, 1fr)); gap: var(--space-2) var(--space-4); margin: 0; }
.summary-grid > div { min-width: 0; }
.summary-grid dt { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.summary-grid dd { margin: var(--space-hair) 0 0; }
.summary-grid .balance-negative dd strong { color: var(--color-danger); }
.summary-past summary { cursor: pointer; font-size: var(--fs-sm); color: var(--muted); }
.summary-note { margin: var(--space-2) 0 0; }

/* KJ #9: list search box (Client Profiles, Coaches) */
.list-search {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  margin: var(--space-2) 0 var(--space-4);
}
.list-search input[type="search"] {
  flex: 1 1 280px;
  max-width: 460px;
}

/* KJ #6: Bookings rows open the booking panel on the calendar */
tr.row-link { cursor: pointer; }
@media (hover: hover) and (pointer: fine) {
  tr.row-link:hover td { background: var(--olive-wash-1); }
}

/* KJ #10: Linked Clients card */
.link-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
.link-list { list-style: none; padding: 0; margin: 0 0 var(--space-3); }
.link-list li { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-1) 0; }
.link-unlink { display: inline-flex; margin: 0; }

/* Month view */
.cal-month { width: 100%; table-layout: fixed; border-collapse: collapse; }
.cal-month th { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.06em; padding: var(--space-2); }
.cal-month td.mday { vertical-align: top; height: 7.5rem; padding: var(--space-1); border: 1px solid var(--color-border); }
/* Neighbouring-month days: a sunken fill, not opacity (opacity cut text to 2.6:1). */
.cal-month td.mday.other-month { background: var(--color-surface-2); }
.cal-month td.mday.other-month .mday-num { color: var(--muted); font-weight: 600; }
.cal-month td.mday.today { box-shadow: inset 0 0 0 2px var(--color-olive); }  /* Phase 2a: olive, not citrine */
.cal-month td.mday.weekend { background: var(--olive-wash-1); }
.mday-num { display: inline-flex; align-items: center; justify-content: center; min-width: 1.5rem; min-height: 1.5rem; border-radius: var(--radius-xs); font-weight: 700; font-size: var(--fs-chip); text-decoration: none; color: var(--color-ink); margin-bottom: var(--space-1); }
.booking-chip.mini { display: block; width: 100%; min-height: 0; flex: none; text-align: left; padding: var(--space-hair) var(--space-1); margin: 0 0 var(--space-1); font-size: var(--fs-label); line-height: 1.25; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.booking-chip.mini .name { display: inline; }
.booking-chip.mini.needs-ack::after { top: 5px; right: 5px; width: 6px; height: 6px; }
.booking-chip.mini.needs-ack { padding-right: var(--space-4); }
.booking-chip.mini.planned { padding: 0 var(--space-hair); }
.booking-chip.mini .time { font-weight: 700; }
.mday-more { display: block; font-size: var(--fs-label); font-weight: 600; color: var(--color-olive); }

/* Year view: one hue (olive), light → dark by sessions per day */
.year-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: var(--space-4) var(--space-5); }
.year-month h2 { font-size: var(--fs-body); margin: 0; }
.year-month h2 a { color: var(--color-ink); text-decoration: none; display: inline-flex; align-items: center; min-height: 24px; }
.year-month p { margin: var(--space-hair) 0 var(--space-1); }
.year-mini { border-collapse: separate; border-spacing: 2px; }
.year-mini th { font-size: var(--fs-label); color: var(--muted); font-weight: 600; padding: 0; text-align: center; }
.year-mini td { padding: 0; }
.yday { display: inline-block; width: 1.65rem; height: 1.5rem; line-height: 1.5rem; text-align: center; font-size: var(--fs-label); border-radius: var(--radius-xs); text-decoration: none; color: var(--color-ink); }
.yday.lvl-0 { background: var(--olive-wash-1); }
.yday.lvl-1 { background: var(--heat-1); }
.yday.lvl-2 { background: var(--heat-2); }
.yday.lvl-3 { background: var(--heat-3); color: var(--color-surface); }
.yday.lvl-4 { background: var(--color-olive); color: var(--color-surface); }
/* The card's link colour (olive, `.card a:not(.btn)`) outranks the two dark cells above and
   made the busiest days olive on olive; one rule that outranks it, hover too (Phase 2a). */
main .yday.lvl-3, main .yday.lvl-4, main .yday.lvl-3:hover, main .yday.lvl-4:hover { color: var(--color-surface); }
/* Today and hover are inset rings, so the outline stays free for the focus ring. */
.yday.today { box-shadow: inset 0 0 0 2px var(--color-olive); }
@media (hover: hover) and (pointer: fine) {
  .yday:hover { box-shadow: inset 0 0 0 2px var(--color-olive); }
}
.year-legend .yday { width: 1rem; height: 1rem; line-height: 1rem; vertical-align: middle; margin: 0 var(--space-px); }

/* KJ #3: package row opened from an Activity link */
tr.row-highlight td { background: var(--cream-wash); }
/* Year view: override the global table cell padding / row lines so months stay compact. */
.year-mini, .year-mini tr, .year-mini th, .year-mini td { border: none; background: none; }
.year-mini th, .year-mini td { padding: var(--space-px); height: auto; }

/* —— Designed states (UI 5-star B1) ——————————————————————————————————————
   One focus ring everywhere: 2px olive, 2px off the element (13.3:1 on the card).
   On the olive nav it turns cream. Fields keep an olive border + halo. */
:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }
.side :focus-visible, .tabbar :focus-visible { outline-color: var(--color-cream); }
input:focus-visible, select:focus-visible, textarea:focus-visible { outline: none; }

/* Pressed */
button:active, .btn:active { filter: brightness(0.86); } /* the press scale is in the Phase 5A block at the end */

/* Disabled: dashed and quiet, so it never reads as a live button. */
button:disabled, .btn:disabled, .btn[aria-disabled="true"] {
  background: var(--olive-wash-2);
  color: var(--muted);
  border: 1px dashed var(--color-input-border);
  cursor: not-allowed;
  filter: none;
}

/* Loading: htmx marks the busy form / button with .htmx-request; plain forms get
   .is-submitting (base.html). The dim only appears after 300 ms, so quick actions
   don't flicker. */
.htmx-request button[type="submit"], button.htmx-request,
form.is-submitting button[type="submit"], [aria-busy="true"] {
  cursor: progress;
  animation: im-busy 0s linear var(--dur-busy-delay) forwards;
}
@keyframes im-busy { to { opacity: 0.6; } }

/* Field with a problem (set aria-invalid="true") */
input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"] {
  border-color: var(--color-danger);
  box-shadow: var(--ring-error);
}

/* —— UI B2: calendar extras —————————————————————————————————————————— */
.skip-link { position: absolute; left: -9999px; top: 0.75rem; z-index: 2000; }
.skip-link:focus {
  left: 1rem;
  background: var(--color-surface);
  color: var(--color-olive);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-pop);
}
main:focus { outline: none; }
.legend-help { margin: var(--space-2) 0 0; font: var(--text-meta); }
.cal-empty { margin: 0 0 var(--space-3); }

/* —— UI B3: booking panel ————————————————————————————————————————————
   Order inside the panel: who / when / balance → the next step (one primary) →
   who asked → Reschedule (tucked away) → cancel (always last). */
.panel-head h2:focus { outline: none; }
.panel-head h2:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 4px; }
.panel-summary { margin: 0 0 var(--space-4); }
.panel-client { margin: 0; font-weight: 600; font-size: var(--fs-body); }
.panel-client a { color: var(--ink); }
.panel-when { margin: var(--space-1) 0 var(--space-2); }
.panel-pills { display: flex; flex-wrap: wrap; gap: var(--space-1); margin: 0 0 var(--space-3); }
.panel-facts { display: grid; grid-template-columns: auto 1fr; gap: var(--space-1) var(--space-4); margin: 0; }
.panel-facts > div { display: contents; }
.panel-facts dt { font: var(--text-label); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--muted); align-self: center; }
.panel-facts dd { margin: 0; }
.panel-times { margin: var(--space-2) 0 0; color: var(--muted); }  /* Plan C1 */
.num { font-variant-numeric: tabular-nums; }
.negative { color: var(--color-danger); font-weight: 600; }
.notice {
  margin: 0 0 var(--space-4);
  padding: var(--space-3) var(--space-4);
  background: var(--cream-wash);
  border-radius: var(--radius-sm);
}
/* What an action will do — always right under its button. */
.consequence { margin: var(--space-2) 0 0; font: var(--text-meta); color: var(--muted); }
.panel-actions .consequence, .panel-danger .consequence { text-align: left; }
.panel-actions form + form, .panel-danger form + form { margin-top: var(--space-4); }
.panel-error { margin: 0 0 var(--space-3); padding: var(--space-2) var(--space-3); background: var(--color-danger-soft); border-radius: var(--radius-sm); }

/* Ledger actions change a balance or coach pay: solid olive (13.3:1), never citrine,
   so they never look like a routine save. */
.btn.ledger, button.ledger { background: var(--color-olive); color: var(--color-paper); }
.btn.ledger-ghost { background: transparent; color: var(--color-olive); border: 2px solid var(--color-olive); }
@media (hover: hover) and (pointer: fine) {
  .btn.ledger-ghost:hover { background: var(--olive-wash-2); filter: none; }
}

.who-asked { border: 0; padding: 0; margin: var(--space-5) 0 var(--space-3); }
/* Name split N2 (Tesstarossa look pass on PR 228, K.J. 28 Oct 2026 "Yes, fix it now"): the tick's help
   line hugs the tick, as every other help line hugs its box. */
.name-box .field > label.check { margin: 0 0 var(--space-1); }
.who-asked legend { font: var(--text-label); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--muted); padding: 0; margin-bottom: var(--space-2); }
label.radio {
  display: inline-flex; flex-direction: row; align-items: center; gap: var(--space-2);
  margin: 0 var(--space-4) 0 0; min-height: 1.5rem;
  font: var(--text-ui); text-transform: none; letter-spacing: 0; color: var(--ink);
}
label.radio input { width: 1.15rem; height: 1.15rem; margin: 0; accent-color: var(--color-olive); }

.panel-more { margin: var(--space-3) 0; border-top: 1px solid var(--line); padding-top: var(--space-3); }
.panel-more > summary {
  cursor: pointer; list-style-position: inside; min-height: 1.5rem;
  font: var(--text-ui); font-weight: 600; color: var(--color-olive);
}
.panel-danger { margin-top: var(--space-4); padding-top: var(--space-4); border-top: 1px solid var(--line); }
/* C2: a free trial's warnings matter only once Free trial is ticked (never block). */
.trial-notes { display: none; margin-top: var(--space-2); }
.trial-field:has(input:checked) .trial-notes { display: block; }
.trial-notes .notice { margin: 0 0 var(--space-2); }
/* C2b: waiting free trial requests on the Calendar (CoS only). */
.trial-requests p { margin: 0; }
.trial-request-list { list-style: none; margin: var(--space-2) 0 0; padding: 0; display: grid; gap: var(--space-2); }
.trial-request-list li { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.trial-decline { margin-top: var(--space-4); }
/* Access levels: the Change Log (CoS only) — the details column reads as small notes. */
.change-details { font: var(--text-meta); color: var(--ink); min-width: 16rem; }

/* —— UI B4: numbers and wording —————————————————————————————————————
   Counts and money line up on the right with equal-width digits. */
th.num, td.num { text-align: right; font-variant-numeric: tabular-nums; }
td.num-time { font-variant-numeric: tabular-nums; }
.tag-pill.review-pill { background: var(--color-danger-soft); color: var(--color-danger); }

/* —— UI B5: page pattern + client profile ————————————————————————————
   Every page: breadcrumb → title row (title left, actions right) → content.
   Profile: work on the left (packages, schedule, links, activity), reference on the
   right (personal details, away dates, delete). Below 1200 px it stacks. */
.page-header { margin: 0 0 var(--space-5); }
.breadcrumb { margin: 0 0 var(--space-2); font: var(--text-meta); }
.page-title-row { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-end; gap: var(--space-4); }
.page-title-row h1 { margin: 0; }
.page-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
/* Finance sub-pages (Finance split PR 2, K.J. 20 Oct 2026): pill tabs that wrap, never scroll sideways.
   Phase 4d (look only): the calendar's segmented switch, olive active, 44px, still wrapping. */
.fin-tabs { display: flex; flex-wrap: wrap; gap: var(--space-hair); margin: var(--space-3) 0 var(--space-2); padding: var(--space-hair); border-radius: var(--radius-sm); background: var(--color-surface-2); width: fit-content; max-width: 100%; }
main .fin-tabs a { display: inline-flex; align-items: center; min-height: 44px; padding: 0 var(--space-4); border: 0; border-radius: calc(var(--radius-sm) - var(--space-hair)); font: var(--text-meta); font-weight: 600; color: var(--muted); background: transparent; }
@media (hover: hover) and (pointer: fine) {
  main .fin-tabs a:hover { color: var(--color-ink); border: 0; }
}
main .fin-tabs a.active, main .fin-tabs a.active:hover { background: var(--color-olive); color: var(--color-paper); }
/* 4d: the month selector is a quiet 44px select; the money tables keep every column and scroll in their box. */
.filters select[name="month"] { min-height: 44px; height: 44px; background: var(--color-surface-2); border-color: transparent; font-weight: 600; }
.finance-table th, .pricing-table th { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); font-weight: 600; white-space: nowrap; }
.finance-table tfoot th, .finance-table tbody th, .pricing-table tbody th { text-transform: none; letter-spacing: 0; font-size: inherit; color: var(--ink); }
.finance-table td.num, .finance-table th.num, .pricing-table td.num { font-variant-numeric: lining-nums tabular-nums; text-align: right; }
.finance-table tbody td, .finance-table tfoot th { padding-top: var(--space-3); padding-bottom: var(--space-3); }
/* 4d: Overview figures as the strip pattern: four equal tiles, serif lining figures. */
.finance-figures { margin: var(--space-3) 0 var(--space-4); }
.finance-figures > div { padding: var(--space-3) var(--space-4); border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); }
.finance-figures > div dd strong { font-variant-numeric: lining-nums tabular-nums; }
/* An amount in the comparison line never breaks between "RM" and the figure. */
.finance-figures .amt { white-space: nowrap; }
/* The first tile is not a hero here: all four figures are the same size and none breaks mid-amount. */
.finance-figures > div dd strong, .summary-grid.finance-figures > div:first-child dd strong { white-space: nowrap; line-height: 1.15; }
@media (max-width: 743px) {
  .summary-grid.finance-figures { grid-template-columns: 1fr 1fr; }
  .finance-figures > div { padding: var(--space-3); }
  .summary-grid.finance-figures > div dd strong, .summary-grid.finance-figures > div:first-child dd strong { font-size: var(--fs-lead); line-height: 1.15; }
}
/* 4d: only the Incomplete reasons are the red-outlined note (outline, not a wash, never cream). */
/* Same specificity as .inline-error (declared later), so this needs the doubled class to win. */
.inline-error.incomplete-note { background: transparent; border-width: 1.5px; font-weight: 400; }
.incomplete-note p { margin: 0 0 var(--space-2); }
.incomplete-note ul { margin: 0; padding-left: var(--space-5); }
/* PR 114 look pass (Tesstarossa, 26 Oct 2026): "Fix it" reads as a link, not by colour alone; its 44px tap area
   comes from padding offset by a negative margin, so the reason lines keep normal spacing.
   `:not(.btn)` so it outranks `.card a:not(.btn)` (text-decoration: none): the box sits in a card. */
.incomplete-note li { margin-bottom: var(--space-2); line-height: 1.5; }
.incomplete-note li a:not(.btn) { text-decoration: underline; text-underline-offset: 2px; font-weight: 600; white-space: nowrap; border-bottom: 0; }
.incomplete-note li a { display: inline-block; min-height: 0; padding: var(--space-3) var(--space-1); margin: calc(-1 * var(--space-3)) 0; }
/* 4d: Pricing tiers as rows of cards. The scheduled count sits on the tier row. */
.pricing-tier { padding: var(--space-4) 0; border-top: 1px solid var(--color-border); }
.pricing-tier:first-of-type { border-top: 0; }
.pricing-tier-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); margin-bottom: var(--space-2); }
.pricing-tier-head h3 { margin: 0; }
.pricing-table tr.pricing-pay td { border-top: 1px solid var(--color-border-strong); }
.pricing-scheduled { margin: var(--space-2) 0 var(--space-3); padding: var(--space-2) var(--space-4); border: 1px solid var(--color-border-strong); border-radius: var(--radius-sm); }
.pricing-scheduled h4 { margin: 0 0 var(--space-1); }
.pricing-scheduled ul { margin: 0; padding-left: var(--space-5); }
.section-card {
  background: var(--card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: var(--space-6);
  box-shadow: var(--shadow-soft);
  min-width: 0;
}
.section-card > h2:first-child, .section-card > :first-child > h2:first-child { margin-top: 0; }
.summary-card { margin-bottom: var(--space-5); padding: var(--space-5) var(--space-6); }
.summary-card .client-summary { margin: 0; padding: 0; border: 0; background: none; }
.profile-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-5); align-items: start; }
@media (min-width: 1200px) {
  .profile-layout { grid-template-columns: minmax(0, 2.2fr) minmax(18rem, 1fr); }
}
.profile-main, .profile-aside { display: grid; gap: var(--space-5); min-width: 0; }
.profile-aside h2 { font-size: var(--fs-lead); }
.profile-aside .detail-grid { grid-template-columns: 8.5rem 1fr; }
.table-scroll { overflow-x: auto; }
#add-package:focus { outline: none; }
/* Summary numbers: the balance is the headline. */
.summary-grid dd { font-variant-numeric: tabular-nums; }
.summary-grid > div:first-child dd strong { font-size: var(--fs-title); font-weight: 600; font-family: var(--font-display); }
/* Finance's four figures (PR3) are equal headlines, so each gets the first tile's size. */
.finance-figures > div dd strong { font-size: var(--fs-title); font-weight: 600; font-family: var(--font-display); }
@media (max-width: 700px) { .section-card { padding: var(--space-5); } }
.packages-card { margin-bottom: var(--space-5); }
.packages-history td:nth-child(2), .packages-history td:nth-child(6) { white-space: nowrap; }
/* Long rules live behind a "help" disclosure so the section reads in one line. */
.help-inline { margin: calc(-1 * var(--space-2)) 0 var(--space-4); font: var(--text-meta); }
.help-inline > summary { cursor: pointer; color: var(--color-olive); text-decoration: underline; text-underline-offset: 2px; width: fit-content; min-height: 24px; }
.help-inline > p { margin: var(--space-2) 0 0; max-width: 72ch; }
/* Personal details stay in view while working down the main column. */
@media (min-width: 1200px) { .profile-aside { position: sticky; top: var(--space-5); } }
.profile-layout { margin-bottom: var(--space-5); }
.profile-layout + .section-card { margin-bottom: var(--space-5); }
.packages-history td.num { white-space: nowrap; }
/* Finance (PR2): an amount stays on one line; the table scrolls inside its box. */
.finance-table td.num, .finance-table th.num { white-space: nowrap; }
/* Coach profile Pay by Month: the top-up and its working never break mid-figure (as .finance-table). */
td.pay-topup { white-space: nowrap; }
/* Finance month close (PR4): the line names keep their width; the books' amounts are
   short right-aligned fields; the explanation takes the rest. */
.finance-recon td:first-child { min-width: 9rem; }
.finance-recon input[name^="books_"] { width: 9rem; text-align: right; font-variant-numeric: tabular-nums; }
.finance-recon input[name^="explain_"] { width: 100%; min-width: 14rem; }
.finance-acks { margin: var(--space-4) 0; }
.finance-pending { margin-bottom: var(--space-4); }
/* Finance trend (PR5): one olive series on hairline grid lines; the zero line is a
   step stronger. Lines stay 1 px however the chart is scaled. */
.trend-chart { display: block; width: 100%; min-width: 560px; max-width: 760px; height: auto; }
/* On a phone the chart scrolls inside its box: start at the latest month (right-hand end). */
.trend-scroll { direction: rtl; }
.trend-scroll > .trend-chart { direction: ltr; margin-left: 0; margin-right: auto; }
.trend-bar { fill: var(--color-olive); }
.trend-grid { stroke: var(--color-border); stroke-width: 1; vector-effect: non-scaling-stroke; shape-rendering: crispEdges; }
.trend-zero { stroke: var(--olive-line); stroke-width: 1; vector-effect: non-scaling-stroke; shape-rendering: crispEdges; }
.trend-axis { fill: var(--color-ink-muted); font: var(--text-meta); font-variant-numeric: tabular-nums; }
.trend-current { fill: var(--color-ink); font-weight: 600; }
.trend-incomplete { fill: var(--color-surface); stroke: var(--color-ink-muted); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
/* Edit disclosures live in nowrap action cells; their forms must wrap normally
   (label text above the field), or fields poke out of the box and widen the page. */
.pkg-edit > form { white-space: normal; }
.pkg-edit > form input:not([type="checkbox"]):not([type="radio"]),
.pkg-edit > form select { display: block; width: 100%; max-width: 100%; margin-top: var(--space-1); }
/* 12 columns: tighter side padding so the whole package row fits at 1440 px. */
.packages-history th, .packages-history td { padding-left: var(--space-2); padding-right: var(--space-2); }

/* One-line summary under a title or section heading; detail goes in .help-inline. */
.section-lede { margin: var(--space-2) 0 var(--space-3); max-width: 80ch; color: var(--color-ink-muted); }
.page-header .help-inline { margin: 0; }
/* UI B7: an error shown next to the form or section that failed. */
.inline-error {
  margin: var(--space-3) 0;
  padding: var(--space-3) var(--space-4);
  color: var(--color-danger);
  background: var(--danger-wash);
  border: 1px solid var(--danger-line);
  border-radius: var(--radius-sm);
  font-weight: 600;
  scroll-margin-top: calc(2 * var(--space-8));  /* keep the section heading in view */
}
.section-card > h2[tabindex="-1"]:focus { outline: none; }
section h2[id] { scroll-margin-top: var(--space-5); }

/* —— Coach profile (KJ 10 Oct 2026) ————————————————————————————————————— */
.summary-alert { color: var(--color-danger); font-weight: 600; }
.summary-grid .is-alert dd, .summary-grid .is-alert dd a { color: var(--color-danger); font-weight: 600; }
.rate-now { margin: 0 0 var(--space-2); font: var(--text-body); }
.rate-now strong { font-family: var(--font-display); font-size: var(--fs-lead); }
.pattern-table td { vertical-align: top; }
.pattern-slot { display: block; white-space: nowrap; font: var(--text-meta); }
.rate-table th, .rate-table td { padding-left: var(--space-2); padding-right: var(--space-2); }
.rate-table .rate-from, .rate-table td.num { white-space: nowrap; }
/* A side column taller than the screen must scroll with the page, not stick. */
.profile-aside.is-static { position: static; }
/* Rate edit row sits under its rate; the change log is a quiet list. */
.rate-table tr.has-edit > td { border-bottom: 0; }
.rate-table .rate-edit-row > td { padding-top: 0; }
.change-log { list-style: none; margin: 0; padding: 0; font: var(--text-meta); }
.change-log li { padding: var(--space-2) 0; border-bottom: 1px solid var(--line); }

/* —— Booking drawer, toast and nav count (UI redesign Phase 2a, spec 4-6; K.J. 21 Oct 2026) ——
   744px and wider: a 420px drawer slides in from the right OVER the page (the calendar
   never squeezes) with a light olive scrim. 743px and narrower: the existing bottom sheet
   (Phase 2b gives it its own motion). #booking-panel is always in the page; data-open
   says open or closed. Motion: transform and opacity only, interruptible transitions;
   entering uses the drawer curve, leaving is quicker; a keyboard open or close has none. */
.eyebrow {
  font: var(--text-label);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--muted);
}
.panel-name {
  margin: var(--space-1) 0 0;
  font: 600 var(--fs-display-sm)/1.05 var(--font-display);
  font-variant-numeric: lining-nums;
  overflow-wrap: anywhere;
}
.panel-name:focus { outline: none; }
.panel-name:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 4px; }
main a.p-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  min-height: 44px;
  font: 600 var(--fs-meta)/1 var(--font-body);
  color: var(--color-olive);
}
.booking-panel .panel-head { margin: 0; min-height: 44px; }
.booking-panel .panel-head .icon-btn { margin-right: calc(-1 * var(--space-2)); }
.booking-panel .panel-summary { margin: 0 0 var(--space-4); }
.booking-panel .panel-when { margin: var(--space-2) 0 var(--space-3); font: 500 var(--fs-body)/1.4 var(--font-body); }
.booking-panel .panel-facts {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-3);
  margin: var(--space-4) 0 0;
  padding: var(--space-4) 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.booking-panel .panel-facts > div { display: block; }
.booking-panel .panel-facts dt { align-self: auto; }
.booking-panel .panel-facts dd { margin: var(--space-1) 0 0; font: 600 var(--fs-body)/1.25 var(--font-body); }
/* Pills in the drawer follow the same colours as the chips (spec 2): no citrine rail. */
.booking-panel .pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: 26px;
  padding: 0 var(--space-3);
  font: 600 var(--fs-sm)/1 var(--font-body);
  letter-spacing: 0;
}
.booking-panel .pill.status-confirmed { background: var(--color-olive); color: var(--color-paper); padding-left: var(--space-3); }
.booking-panel .pill.status-tentative { background: var(--color-pink); color: var(--ink); padding-left: var(--space-3); }
.booking-panel .pill.status-tentative::before, .booking-panel .pill.status-confirmed::before { content: none; }
.booking-panel .pill.status-completed { background: var(--color-surface-2); color: var(--muted); }
.booking-panel .pill.status-no_show { background: var(--color-surface); color: var(--color-danger); box-shadow: inset 0 0 0 1px var(--danger-line); }
.pill.status-needs-ack { background: var(--cream-wash); color: var(--ink); }
.booking-panel .panel-actions form + form { margin-top: var(--space-4); }
.booking-panel .panel-actions .btn { min-height: 44px; }
.booking-panel .panel-more > summary { display: flex; align-items: center; min-height: 44px; }
.booking-panel .panel-danger { border-top: 1px solid var(--line); padding-top: var(--space-3); }
.booking-panel .panel-danger > summary { color: var(--color-danger); }
/* Cancel: one tap per reason (spec 4.6). */
.cancel-block .group-label { margin: var(--space-2) 0 var(--space-2); }
.reasons { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--space-2); }
.reasons form { display: flex; margin: 0; width: auto; }
.reasons form + form { margin-top: 0; }  /* beats ".panel-danger form + form", which stacked the chips */
.booking-panel form > button[type="submit"].chip-btn,
.chip-btn {
  display: inline-flex;
  align-items: center;
  width: auto;
  min-height: 44px;
  padding: 0 var(--space-4);
  border-radius: var(--radius-pill);
  border: 1px solid var(--color-input-border);
  background: var(--color-surface);
  color: var(--ink);
  font: 600 var(--fs-meta)/1 var(--font-body);
  text-transform: none;
  letter-spacing: 0;
}
.booking-panel form > button[type="submit"].chip-btn.client, .chip-btn.client { border-color: var(--color-olive); color: var(--color-olive); }
@media (hover: hover) and (pointer: fine) {
  .booking-panel form > button[type="submit"].chip-btn:hover, .chip-btn:hover { background: var(--color-surface-2); filter: none; }
}
.cancel-pair { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.cancel-pair form { margin: 0; }
.cancel-pair .btn { width: 100%; min-height: 44px; display: block; }
.reason-group[hidden] { display: none; }
.link-btn {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-olive);
  font: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}
@media (hover: hover) and (pointer: fine) {
  .link-btn:hover { filter: none; color: var(--ink); }
}

/* Toast (spec 5): bottom-left on a desktop and an iPad, bottom-centre on the phone.
   It sits above the scrim, so Undo stays reachable with the drawer open. */
.toast-region {
  position: fixed;
  z-index: 95;
  left: calc(var(--side-w) + 28px);
  bottom: 28px;
  max-width: min(440px, calc(100vw - var(--side-w) - 56px));
  pointer-events: none;
}
.toast {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  min-height: 52px;
  padding: var(--space-1) var(--space-2) var(--space-1) var(--space-4);
  border-radius: var(--radius-sm);
  background: var(--color-ink);
  color: var(--color-paper);
  box-shadow: var(--shadow-float);
  font: 500 var(--fs-ui)/1.3 var(--font-body);
  opacity: 0;
  transform: translateY(16px);
  transition: transform var(--dur-toast-out) var(--ease-out), opacity var(--dur-toast-out) var(--ease-out);
  pointer-events: none;
}
.toast.show { opacity: 1; transform: none; transition-duration: var(--dur-toast-in); pointer-events: auto; }
.toast:not(:has(form)) { padding-right: var(--space-4); }
.toast form { margin: 0; }
.toast .toast-undo {
  min-height: 44px;
  padding: 0 var(--space-3);
  border: 0;
  background: transparent;
  color: var(--color-cream);
  font: 700 var(--fs-ui)/1 var(--font-body);
}
.toast .toast-undo:focus-visible { outline-color: var(--color-cream); }
@media (hover: hover) and (pointer: fine) {
  .toast .toast-undo:hover { background: var(--paper-wash); filter: none; }
}
@media (max-width: 1199px) {
  .toast-region { left: calc(var(--rail-w) + 24px); max-width: min(440px, calc(100vw - var(--rail-w) - 48px)); }
}
@media (max-width: 743px) {
  /* The toast sits bottom-centre, above the Book button and the tab bar (spec 5.1). */
  .toast-region { left: var(--space-4); right: var(--space-4); bottom: calc(var(--m-tabbar) + var(--space-10) + var(--space-5)); max-width: none; display: flex; justify-content: center; }
  .cal-switch { display: none; }
}

/* The "to mark" count: cream on the olive chrome ("needs you"). Hidden at 0. */
.nav-count {
  margin-left: auto;
  min-width: 22px;
  height: 22px;
  padding: 0 var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--color-cream);
  color: var(--color-olive);
  font: 700 var(--fs-xs)/22px var(--font-body);
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.nav-count[hidden] { display: none; }
@media (max-width: 1199px) {
  .nav-item .nav-count { position: absolute; top: 2px; right: 8px; min-width: 20px; height: 20px; padding: 0 var(--space-1); line-height: 20px; }
}
@media (max-width: 743px) {
  .tab .nav-count { position: absolute; top: 4px; left: calc(50% + 6px); right: auto; min-width: 20px; height: 20px; padding: 0 var(--space-1); line-height: 20px; }
}
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: calc(-1 * var(--space-px));
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.scrim {
  position: fixed;
  inset: 0;
  z-index: 85;
  background: var(--olive-scrim);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-drawer-out) ease;
}
.booking-panel[data-open="true"] + .scrim { opacity: 1; pointer-events: auto; transition-duration: var(--dur-drawer-in); }
.booking-panel[data-instant], .booking-panel[data-instant] + .scrim { transition: none !important; }
.panel-handle { display: none; }  /* the sheet's grab handle (743px and narrower) */

@media (min-width: 744px) {
  .booking-panel {
    position: fixed;
    z-index: 90;
    top: 0;
    right: 0;
    bottom: 0;
    width: 420px;
    max-width: 100%;
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--color-surface);
    box-shadow: var(--shadow-float);
    transform: translateX(100%);
    visibility: hidden;
    transition: transform var(--dur-drawer-out) var(--ease-out), visibility 0s linear var(--dur-drawer-out);
  }
  .booking-panel[data-open="true"] {
    transform: none;
    visibility: visible;
    transition: transform var(--dur-drawer-in) var(--ease-drawer), visibility 0s;
  }
  .booking-panel .panel-card {
    position: static;
    padding: var(--space-3) var(--space-5) var(--space-6);
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
  }
}
@media (min-width: 744px) and (max-width: 1023px) {
  .booking-panel { width: 400px; }
}
@media (max-width: 743px) {
  .scrim { z-index: 75; background: var(--m-scrim); }
}
/* Reduced motion: slides become 150ms fades; the toast and scrim just fade. */
@media (prefers-reduced-motion: reduce) {
  .booking-panel { transform: none; opacity: 0; transition: opacity var(--dur-fade-reduced) ease, visibility 0s linear var(--dur-fade-reduced); }
  .booking-panel[data-open="true"] { opacity: 1; transition: opacity var(--dur-fade-reduced) ease, visibility 0s; }
  .scrim, .booking-panel[data-open="true"] + .scrim { transition: none; }
}
@media (prefers-reduced-motion: reduce) {
  .toast, .toast.show { transform: none; transition: opacity var(--dur-fade-reduced) ease; }
}

/* ===== Phone layout (K.J. 19 Oct 2026; spec rxg-equi-ui/mobile/v2, main 976dff1) =====
   Everything below applies at 743px and narrower only (it was 600px; the redesign plan
   moves the phone shell up to 743px, K.J. 20 Oct 2026, so 744px and wider is the iPad
   rail). .m-only = phone only; .d-only = desktop only. Tokens and radii as in :root.
   Tap targets are at least 44px. */
.m-only, .m-only-inline { display: none !important; }
.addpkg-sheet { display: contents; }

@media (max-width: 743px) {
  .m-only { display: block !important; }
  .m-only-inline { display: inline !important; }
  .d-only, .d-only-inline { display: none !important; }
  body { padding-bottom: calc(var(--m-tabbar) + var(--space-4)); }

  /* Shell (plan 3.3): the sidebar/rail gives way to a thin paper top bar (citrine wordmark,
     your avatar) and an olive tab bar; the other pages sit under More. */
  .app { display: block; }
  .side { display: none; }
  .m-top.m-only {
    position: sticky; top: 0; z-index: 30; display: flex !important; align-items: center; justify-content: space-between;
    height: var(--m-topbar); padding: 0 var(--m-pad); background: var(--color-paper); border-bottom: 1px solid var(--color-border);
  }
  .m-wordmark { font: 600 var(--fs-lead)/1 var(--font-display); font-variant-numeric: lining-nums; letter-spacing: 0.01em; color: var(--color-citrine); text-decoration: none; }
  .m-top .avatar { width: var(--m-tap); height: var(--m-tap); }
  main { padding: var(--space-3) var(--m-pad); }
  h1 { font-size: var(--fs-display-sm); }

  /* Tab bar: Calendar · Clients · Packages · More (every role), cream marks where you are. */
  .tabbar.m-only {
    display: grid !important; grid-auto-flow: column; grid-auto-columns: 1fr;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 70; height: var(--m-tabbar);
    background: var(--color-chrome); border-top: 1px solid var(--paper-wash);
  }
  .tab {
    position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-1);
    min-height: var(--m-tap); padding: 0; color: var(--on-olive-2); text-decoration: none; background: none; border: 0; border-radius: 0;
    font: 600 var(--fs-xs)/1 var(--font-body); letter-spacing: 0; text-transform: none; cursor: pointer;
  }
  .tab svg { width: 22px; height: 22px; }
  .tab.active { color: var(--color-paper); }
  .tab.active::before {
    content: ""; position: absolute; top: 0; left: 30%; right: 30%; height: 3px;
    background: var(--color-cream); border-radius: 0 0 var(--radius-xs) var(--radius-xs);
  }

  /* More sheet (per role). */
  .m-more { position: fixed; inset: 0 0 var(--m-tabbar) 0; z-index: 65; background: var(--m-scrim); }
  .m-more[hidden] { display: none !important; }
  .m-more-sheet {
    position: absolute; left: 0; right: 0; bottom: 0; max-height: calc(100vh - var(--m-tabbar) - 20px); overflow: auto;
    background: var(--color-surface); border-radius: var(--radius) var(--radius) 0 0; padding: var(--space-2) var(--m-pad) var(--space-3);
  }
  .menu { list-style: none; margin: 0; padding: 0; }
  .menu li { border-bottom: 1px solid var(--color-border); }
  .menu-group { margin: 0; border: 0; padding: var(--space-3) 0 var(--space-hair); font: var(--text-label); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-ink-muted); }
  .menu a, .menu button {
    display: flex; align-items: center; width: 100%; min-height: 48px; color: var(--color-ink); text-decoration: none;
    font: 500 1rem/1 var(--font-body); background: none; border: 0; padding: 0; text-transform: none; letter-spacing: 0; cursor: pointer;
  }
  .menu .note { margin-left: auto; font-size: var(--fs-meta); color: var(--color-ink-muted); }
  .menu .out { color: var(--color-danger); }
  .role-line { margin: var(--space-2) 0 0; }

  /* Calendar: the Today list replaces the week grid (UI redesign Phase 2b, spec 7). */
  #calendar-root.card { padding: 0; border: 0; box-shadow: none; background: transparent; }
  #week-calendar { display: none !important; }
  .m-daybar { position: sticky; top: var(--m-topbar); z-index: 25; background: var(--color-paper); border-bottom: 1px solid var(--color-border); padding: var(--space-2) 0; }
  .m-weekhead { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-2); }
  .m-weekhead h1 { margin: 0; font: 600 1.6rem/1.1 var(--font-display); font-variant-numeric: lining-nums; letter-spacing: -0.02em; }
  .m-arrows { display: flex; gap: var(--space-2); }
  /* Rebuilt (review item P1): a 44px round button drawn with a ring, so the link's own bottom border can't show. */
  main a.m-icon-btn, main a.m-icon-btn:hover {
    width: var(--m-tap); height: var(--m-tap); display: inline-flex; align-items: center; justify-content: center;
    border: 0; border-radius: 50%; background: var(--color-surface); box-shadow: inset 0 0 0 1px var(--color-border-strong); color: var(--color-olive);
  }
  .m-icon-btn svg { width: 18px; height: 18px; }
  .m-days { display: grid; grid-template-columns: repeat(7, 1fr); gap: var(--space-1); }
  .m-dayb { position: relative; min-height: 52px; border-radius: var(--radius-sm); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-px); color: var(--color-ink-muted); text-decoration: none; }
  .m-dayb .dw { font: 600 var(--fs-label)/1.2 var(--font-body); letter-spacing: 0.08em; text-transform: uppercase; }
  .m-dayb .dn { font: 600 1.05rem/1.1 var(--font-body); color: var(--color-ink); }
  .m-dayb.today { box-shadow: inset 0 3px 0 var(--color-olive); background: var(--olive-wash-2); }
  .m-dayb.selected { background: var(--color-olive); }
  .m-dayb.selected .dw { color: var(--m-paper-80); }
  .m-dayb.selected .dn { color: var(--color-paper); }
  /* A muted dot: the day has sessions. A cream dot: some of them are still to mark (needs you). */
  .m-dayb .dot { position: absolute; bottom: var(--space-1); width: 4px; height: 4px; border-radius: var(--radius-pill); background: var(--color-ink-muted); opacity: 0.55; }
  .m-dayb .dot.mark { width: 6px; height: 6px; background: var(--color-cream); box-shadow: 0 0 0 1px var(--olive-line); opacity: 1; }
  .m-dayb.selected .dot { background: var(--color-cream); box-shadow: none; opacity: 1; }
  .m-filters { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2); margin-top: var(--space-2); font-size: var(--fs-meta); }
  .pill-mark { display: inline-flex; align-items: center; gap: var(--space-2); height: 26px; padding: 0 var(--space-3); border-radius: var(--radius-pill); background: var(--cream-wash); color: var(--color-ink); font: 600 var(--fs-sm)/1 var(--font-body); }
  .m-coach select { min-height: var(--m-tap); border-radius: var(--radius-pill); border-color: var(--color-input-border); padding: 0 var(--space-3); font: 600 var(--fs-meta)/1 var(--font-body); width: auto; }
  /* The day's sessions as cards, in time order (spec 7.4); colours as the calendar's states (spec 2). */
  .m-agenda { display: grid; gap: var(--space-2); margin: 0; padding: var(--space-3) 0 calc(var(--m-tap) + var(--space-10)); list-style: none; }
  .m-row { display: grid; grid-template-columns: var(--m-time-col) minmax(0, 1fr); gap: var(--space-3); align-items: stretch; }
  .m-time { padding-top: var(--space-4); font: 600 var(--fs-ui)/1 var(--font-body); font-variant-numeric: tabular-nums; }
  .m-time small { display: block; margin-top: var(--space-1); font: 400 var(--fs-xs)/1 var(--font-body); color: var(--color-ink-muted); }
  .m-card { position: relative; display: flex; align-items: center; gap: var(--space-3); min-height: 64px; padding: var(--space-2) var(--space-2) var(--space-2) var(--space-4); border-radius: var(--radius); }
  .m-card.conf { background: var(--color-olive); color: var(--color-paper); }
  .m-card.tent { background: var(--color-pink); color: var(--color-ink); }
  .m-card.done { background: var(--color-surface-2); color: var(--color-ink-muted); box-shadow: inset 0 0 0 1px var(--color-border); }
  .m-card.noshow { background: var(--color-surface); color: var(--color-danger); box-shadow: inset 0 0 0 1.5px var(--color-danger); }
  .m-card.plan, .m-card.clash { background: var(--color-paper); color: var(--color-ink-muted); border: 1px dashed var(--color-input-border); }
  /* Not Marked on a tentative card: the cream dot (a confirmed one has the ring below). */
  .m-card.tent.mark::after { content: ""; position: absolute; top: var(--space-3); right: var(--space-3); width: 8px; height: 8px; border-radius: 50%; background: var(--color-cream); box-shadow: 0 0 0 1px var(--olive-line); }
  .m-who { flex: 1; min-width: 0; align-self: stretch; display: flex; flex-direction: column; justify-content: center; min-height: var(--m-tap); padding: 0; border: 0; background: none; color: inherit; font: inherit; text-align: left; }
  .m-who .n { font: 600 var(--fs-body)/1.25 var(--font-body); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .m-who .m { font: 400 var(--fs-sm)/1.35 var(--font-body); opacity: 0.85; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .m-tag { flex: none; padding-right: var(--space-2); font: 600 var(--fs-label)/1 var(--font-body); letter-spacing: 0.04em; }
  .m-card.clash .m-tag { color: var(--color-danger); }
  /* The cream ring: one tap marks the session done; the toast carries Undo. */
  .m-ring-form { margin: 0; flex: none; }
  .m-ring { display: grid; place-items: center; width: var(--m-tap); height: var(--m-tap); padding: 0; border: 2px solid var(--color-cream); border-radius: 50%; background: transparent; color: var(--color-cream); }
  .m-ring svg { width: 20px; height: 20px; }
  /* Free time shows once per gap (spec 7.6). */
  .m-free { padding-left: calc(var(--m-time-col) + var(--space-3)); }
  .m-free button { display: flex; align-items: center; justify-content: space-between; width: 100%; min-height: var(--m-tap); padding: 0 var(--space-4); border: 1px dashed var(--color-border-strong); border-radius: var(--radius); background: transparent; color: var(--color-ink-muted); font: 400 var(--fs-meta)/1 var(--font-body); text-align: left; }
  .m-free button b { color: var(--color-olive); font-weight: 600; }
  .m-now { display: grid; grid-template-columns: var(--m-time-col) minmax(0, 1fr); gap: var(--space-3); align-items: center; }
  .m-now span { font: 700 var(--fs-label)/1 var(--font-body); color: var(--color-olive); font-variant-numeric: tabular-nums; }
  .m-now i { position: relative; display: block; height: 2px; border-radius: var(--radius-xs); background: var(--color-olive); }
  .m-now i::before { content: ""; position: absolute; left: calc(-1 * var(--space-1)); top: calc(-1 * var(--space-1)); width: 10px; height: 10px; border-radius: 50%; background: var(--color-olive); }
  .m-empty { display: grid; justify-items: center; gap: var(--space-3); margin-top: var(--space-3); padding: var(--space-8) var(--space-4); border: 1px dashed var(--color-border-strong); border-radius: var(--radius); color: var(--color-ink-muted); text-align: center; }
  .m-empty p { margin: 0; }
  /* The floating Book button (spec 7.7): olive, 56px, above the tab bar. */
  .m-fab { position: fixed; right: var(--space-4); bottom: calc(var(--m-tabbar) + var(--space-4)); z-index: 60; display: inline-flex; align-items: center; gap: var(--space-2); height: 56px; padding: 0 var(--space-5) 0 var(--space-4); border: 0; border-radius: var(--radius-pill); background: var(--color-olive); color: var(--color-paper); box-shadow: var(--shadow-float); font: 700 var(--fs-body)/1 var(--font-body); }
  .m-fab svg { width: 20px; height: 20px; }

  /* Look pass (Tesstarossa, 19 Oct): a heading focused by code when a sheet opens shows
     no box; controls keep their :focus-visible ring. */
  h1[tabindex="-1"]:focus, h2[tabindex="-1"]:focus, h3[tabindex="-1"]:focus,
  .panel-head h2[tabindex="-1"]:focus-visible { outline: none; box-shadow: none; }

  /* Form controls: one control style on phone (selects get a drawn chevron). */
  select, textarea,
  input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="submit"]),
  .date-field .date-display {
    /* Phase 5G fix (WCAG 1.4.11; St. Michael's go 27 Oct 2026): the 3:1 field edge, as on desktop
       (--color-rule is 28 %, about 1.7:1). */
    min-height: var(--m-tap); border-radius: var(--radius-sm); border: 1px solid var(--color-input-border);
    background-color: var(--color-surface); color: var(--color-ink);
  }
  /* M1 amend A1 (Tesstarossa, 27 Oct 2026): the rule above outranks the desktop invalid rule, so a refused
     text, email, tel or password box lost its red edge on phones. This one has the same weight (an attribute
     and three :not, as its four :not) and comes later, so it wins. Selects, textareas and date boxes keep theirs. */
  input[aria-invalid="true"]:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]) { border-color: var(--color-danger); }
  .date-field { min-height: var(--m-tap); }
  .date-field .date-display { text-transform: none; letter-spacing: normal; font-weight: 400; }
  .date-field input[type="date"], .date-field input[data-date-input] { border: 0; background: transparent; }
  select {
    -webkit-appearance: none; appearance: none; padding-right: var(--space-7);
    background-image: var(--m-chevron); background-repeat: no-repeat;
    background-position: right var(--space-3) center; background-size: var(--space-4);
  }
  .m-coach select { border-radius: var(--radius-pill); border-color: var(--color-input-border); padding-right: var(--space-7); }
  .dmy { max-width: none; }
  .dmy .dmy-pick { min-width: var(--m-tap); min-height: var(--m-tap); }

  /* Shiva M-02 (19 Oct 2026): every tap target at least 44px on phone. Bigger hit area
     only: same text, same colour; inline-flex keeps the words centred in the taller box. */
  main a:not([class]), .booking-panel a:not([class]), .m-more a:not([class]),
  main summary, .booking-panel summary,
  label.check, label.radio, .check-label, .radio-label,
  .back-link, a.back, .show-inactive {
    display: inline-flex; align-items: center; min-height: var(--m-tap); min-width: var(--m-tap);
  }
  main a:not([class]) { justify-content: center; }
  main p > a:not([class]), main li > a:not([class]) { justify-content: flex-start; }
  main summary, .booking-panel summary { display: flex; width: 100%; }
  main .help-inline > summary { min-height: var(--m-tap); }
  main summary::-webkit-details-marker { display: none; }
  main summary::before, .booking-panel summary::before { content: "\25B8"; margin-right: var(--space-2); }
  main details[open] > summary::before, .booking-panel details[open] > summary::before { transform: rotate(90deg); }
  main summary.btn::before, .booking-panel summary.btn::before { content: none; }
  #leave input, #leave select, .leave-row input, .leave-row select, #add-leave input, #add-leave select { min-height: var(--m-tap); min-width: calc(var(--m-tap) * 3); }
  /* Booking / New Booking = bottom sheet (Phase 2b, spec 8): the same shell as the drawer, sliding
     up (280ms in, 180ms out). A handle at the top; it drags from the handle and the header only
     (drawer.js), so scrolling the content never closes it. At most 85% of the screen. */
  .booking-panel {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 80; max-height: 85vh; max-height: 85dvh;
    overflow-y: auto; overscroll-behavior: contain; background: var(--color-surface);
    border-radius: var(--radius) var(--radius) 0 0; box-shadow: var(--shadow-float);
    transform: translateY(100%); visibility: hidden;
    transition: transform var(--dur-sheet-out) var(--ease-out), visibility 0s linear var(--dur-sheet-out);
  }
  .booking-panel[data-open="true"] { transform: none; visibility: visible; transition: transform var(--dur-sheet-in) var(--ease-drawer), visibility 0s; }
  .booking-panel .panel-card {
    position: static; border: 0; border-radius: 0; background: transparent; box-shadow: none;
    padding: 0 var(--m-pad) calc(var(--space-5) + env(safe-area-inset-bottom));
  }
  .panel-handle { display: flex; justify-content: center; padding: var(--space-2) 0; touch-action: none; }
  .panel-handle::before { content: ""; width: 40px; height: 4px; border-radius: var(--radius-pill); background: var(--olive-wash-5); }
  .booking-panel .panel-head { touch-action: none; }
  .panel-name { font-size: var(--fs-title); }
  .panel-facts { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-2); }
  .panel-facts > div { display: block; }
  .panel-facts dd { margin: var(--space-hair) 0 0; font-weight: 600; }
  .booking-panel .btn, .booking-panel button[type="submit"], .booking-panel select, .booking-panel input:not([type="radio"]):not([type="checkbox"]) { min-height: var(--m-tap); }
  .booking-panel .consequence { display: none; }
  .m-actions { margin-top: var(--space-3); }
  .m-actions > form, .m-actions > .btn { margin: 0 0 var(--space-2); }
  .m-actions .btn { width: 100%; display: flex; align-items: center; justify-content: center; min-height: 52px; }
  .booking-panel .m-actions .btn { display: flex; }
  .booking-panel .m-actions .m-two { flex-direction: column; gap: var(--space-1); }
  .m-two small { display: block; }
  .m-two small { font: 500 var(--fs-xs)/1 var(--font-body); letter-spacing: 0; text-transform: none; opacity: 0.85; }
  .m-hint { margin: calc(-1 * var(--space-1)) 0 var(--space-2); text-align: center; font-size: var(--fs-sm); color: var(--color-ink-muted); }
  .m-history { margin: 0 0 var(--space-3); padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); background: var(--color-surface-2); }
  .m-history ol { list-style: none; margin: 0; padding: 0; }
  .m-history li { display: grid; grid-template-columns: 112px 1fr; gap: var(--space-2); font-size: var(--fs-meta); padding: var(--space-hair) 0; }
  .m-history time { color: var(--color-ink-muted); font-variant-numeric: tabular-nums; }
  .m-resched-form .label { margin: var(--space-2) 0 var(--space-1); }
  .m-mini-days { display: grid; grid-template-columns: repeat(7, 1fr); gap: var(--space-1); }
  .m-slots { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-2); }
  .m-seg { display: grid; grid-template-columns: 1fr 1fr; border: 1px solid var(--color-border-strong); border-radius: var(--radius-sm); overflow: hidden; margin-bottom: var(--space-3); }
  .m-mini-days label, .m-slots label, .m-seg label { margin: 0; position: relative; }
  .m-mini-days input, .m-slots input, .m-seg input { position: absolute; opacity: 0; pointer-events: none; }
  .m-mini-days span, .m-slots span, .m-seg span {
    min-height: var(--m-tap); display: flex; flex-direction: column; align-items: center; justify-content: center;
    border-radius: var(--radius-sm); border: 1px solid var(--color-border-strong); font: 500 var(--fs-ui)/1.1 var(--font-body); font-variant-numeric: tabular-nums; cursor: pointer;
  }
  .m-mini-days small { font: 600 var(--fs-xs)/1 var(--font-body); letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-ink-muted); margin-bottom: var(--space-hair); }
  .m-seg span { border: 0; border-radius: 0; font-weight: 600; }
  .m-mini-days input:checked + span, .m-slots input:checked + span, .m-seg input:checked + span { background: var(--color-olive); color: var(--color-paper); border-color: var(--color-olive); }
  .m-mini-days input:checked + span small { color: var(--m-paper-80); }
  /* K.J. 3 Nov 2026: the coach's approved leave day, muted; still pickable (the server refuses the move). */
  .m-mini-days small.m-leave { margin: var(--space-hair) 0 0; letter-spacing: 0; text-transform: none; font-weight: 500; }
  /* Shiva on PR 276 (3 Nov 2026): at 150% text "Leave" filled its tile edge to edge and widened it. Now the
     word takes the tile's width instead of setting it (width 0, at least the tile), keeps a hair inside the
     border, and ends in "..." if it doesn't fit (the radio's label still says ", leave"). At 100% nothing moves. */
  .m-mini-days small.m-leave { width: 0; min-width: 100%; padding: 0 var(--space-hair); box-sizing: border-box; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: center; }
  /* Tess on PR 272: the day numbers sit on one line whether or not a tile carries "Leave": each tile fills its row
     and starts at the top, so the Leave line goes below the number instead of lifting it. */
  .m-mini-days span { height: 100%; justify-content: flex-start; padding-top: calc(var(--space-1) + var(--space-hair)); box-sizing: border-box; }
  .m-slots input:disabled + span { color: var(--m-taken); border-style: dashed; cursor: not-allowed; }
  .m-mini-days input:focus-visible + span, .m-slots input:focus-visible + span, .m-seg input:focus-visible + span { outline: 2px solid var(--color-focus); outline-offset: 2px; }

  /* Pages: tighter cards, tables scroll sideways, 44px controls. */
  .card, .section-card { padding: var(--space-4); border-radius: var(--radius); }
  .page-title-row { flex-wrap: wrap; gap: var(--space-2); }
  .page-actions { flex-wrap: wrap; }
  .btn, button.btn, select, input:not([type="checkbox"]):not([type="radio"]), textarea { min-height: var(--m-tap); }
  .btn.small { min-height: var(--m-tap); }
  table { display: block; overflow-x: auto; }
  /* `main a:not(.btn)` (olive link colour) is more specific than a bare a.m-cta, so the label
     vanished on the olive bar (Shiva, 20 Oct 2026): name main, and keep the colour on hover. */
  main a.m-cta, main a.m-cta:hover {
    position: fixed; left: var(--m-pad); right: var(--m-pad); bottom: calc(var(--m-tabbar) + 10px); z-index: 60;
    display: flex !important; align-items: center; justify-content: center; min-height: 52px; border-radius: var(--radius-sm);
    background: var(--color-olive); color: var(--color-paper); text-decoration: none; box-shadow: var(--shadow-pop);
    font: 600 var(--fs-ui)/1 var(--font-body); letter-spacing: var(--tracking-btn);
  }
  body:has(.m-cta) { padding-bottom: calc(var(--m-tabbar) + var(--space-10) + var(--space-3)); }
  .m-desk-note { margin-top: var(--space-3); padding: var(--space-3) var(--space-3); border-radius: var(--radius-sm); background: var(--color-surface-2); font-size: var(--fs-meta); color: var(--color-ink-muted); }

  /* Client page: Summary first, all 9 fields in 2 columns, plus the empty 6b Owed slot. */
  .summary-grid { grid-template-columns: 1fr 1fr; gap: var(--space-3) var(--space-3); }
  .summary-grid > div:first-child dd strong { font-size: var(--fs-hero); line-height: 0.95; }
  .slot-6b-cell dd { color: var(--color-ink-muted); border: 1px dashed var(--color-input-border); border-radius: var(--radius-xs); padding: 0 var(--space-1); display: inline-block; }
  .profile-layout { display: block; }
  .addpkg-sheet { display: none; }
  .addpkg-sheet.open {
    display: block; position: fixed; left: 0; right: 0; bottom: 0; z-index: 80; max-height: 88vh; overflow: auto;
    background: var(--color-surface); border-radius: var(--radius) var(--radius) 0 0; padding: var(--space-4) var(--m-pad) var(--space-5);
    box-shadow: 0 0 0 100vmax var(--m-scrim);
  }
  .addpkg-sheet .pkg-add-form { display: flex; flex-direction: column; align-items: stretch; }
  .m-sheet-x { position: absolute; top: 6px; right: 8px; width: var(--m-tap); height: var(--m-tap); background: none; border: 0; font-size: var(--fs-lead); color: var(--color-ink-muted); cursor: pointer; }

  /* Packages: Package Types on desktop only. Finance: read only. */
  section[aria-labelledby="package-types"] { display: none; }
  main:has(.m-finance) section:has(#month-close),
  main:has(.m-finance) section:has(#entries),
  main:has(.m-finance) section:has(#settings),
  main:has(.m-finance) form[method="post"] { display: none !important; }  /* .m-finance is left off Coach Pay */
  main .fin-tabs a { min-height: var(--m-tap); padding: 0 var(--space-3); }
  main:has(.m-pricing) > section, main:has(.m-pricing) .section-lede { display: none; }

  /* Leave list. */
  .leave-row { display: flex; justify-content: space-between; align-items: center; gap: var(--space-3); min-height: 64px; border-bottom: 1px solid var(--color-border); padding: var(--space-2) 0; }
  .leave-row:last-child { border-bottom: 0; }
  .leave-who { margin: 0; font-weight: 600; }
  .leave-row .muted { margin: var(--space-hair) 0 0; }
  .leave-actions { display: flex; gap: var(--space-2); flex: none; }
}
/* Leave list on wider screens (reached from the phone More list). */
.leave-row { display: flex; justify-content: space-between; align-items: center; gap: var(--space-3); padding: var(--space-2) 0; border-bottom: 1px solid var(--color-border); }
.leave-actions { display: flex; gap: var(--space-2); }
/* Reduced motion on the phone sheet (Shiva Tier D on 2b): repeated after the phone block, which sets
   translateY(100%) and a 280ms slide again at the same specificity. A 150ms fade instead. */
@media (max-width: 743px) and (prefers-reduced-motion: reduce) {
  .booking-panel { transform: none; opacity: 0; transition: opacity var(--dur-fade-reduced) ease, visibility 0s linear var(--dur-fade-reduced); }
  .booking-panel[data-open="true"] { opacity: 1; transition: opacity var(--dur-fade-reduced) ease, visibility 0s; }
}

/* ===== Phase 3a: the Clients list (K.J. approved the spec 21 Oct 2026; PHASE-3-CLIENTS.md
   section 2). Table from 744px; row cards from 743px down. The card has no padding of its
   own here: the toolbar and the table carry theirs. Tokens only (design-lint). ===== */
.client-list-card { padding: 0; }
.client-list-card .client-flash { margin: var(--space-4) var(--space-5) 0; }
.client-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--color-border);
}
.client-toolbar .list-search { flex: 1 1 16rem; min-width: 0; margin: 0; }
.client-toolbar .list-search input[type="search"] { flex: 1 1 100%; max-width: none; min-height: var(--m-tap); }
.client-toolbar .btn { min-height: var(--m-tap); }
.client-count { margin-left: auto; white-space: nowrap; font-variant-numeric: tabular-nums; }
.client-hint { margin: var(--space-3) var(--space-5) 0; }

/* Sideways stays a safety net; a wrapped name must not add a stray vertical scrollbar (1px of overflow). */
.client-table-wrap { overflow-y: hidden; }
.client-table { width: 100%; border-collapse: collapse; }
.client-table th {
  padding: var(--space-3) var(--space-5);
  text-align: left;
  font: var(--text-label);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--color-ink-muted);
  border-bottom: 1px solid var(--color-border);
}
.client-table th.num { text-align: right; }
/* A11y audit A7 (K.J. 28 Oct 2026): the name cell is a row header (<th scope="row">) and keeps the look of the
   plain cell it was: every td rule below has a twin for a body th at the same specificity. */
.client-table td, .client-table th:where(tbody *) {
  height: var(--client-row);
  padding: 0 var(--space-5);
  border-top: 1px solid var(--color-border);
  font: var(--text-ui);
  color: var(--color-ink);
}
.client-table tbody tr:first-child td, .client-table tbody tr:first-child th:where(tbody *) { border-top: 0; }
.client-table th:where(tbody *) { text-transform: none; letter-spacing: normal; white-space: normal; }
.client-table td.client-phone, .client-table td.client-last { overflow-wrap: anywhere; }
.client-table td.client-name, .client-table th.client-name { min-width: var(--client-name-min); max-width: var(--client-name-max); }
.client-table td.client-name a, .client-table th.client-name a { overflow-wrap: anywhere; }
/* 1024 to 1199px: the rail takes 88px, so the cells take less padding to fit six columns. */
@media (min-width: 1024px) and (max-width: 1199px) {
  .client-table th, .client-table td { padding-left: var(--space-3); padding-right: var(--space-3); }
}
.client-table td.client-name a, .client-table th.client-name a { font: 600 var(--fs-body)/1.2 var(--font-body); text-decoration: none; }
.client-table td.num { text-align: right; }
.client-table tr.is-inactive td, .client-table tr.is-inactive th:where(tbody *) { color: var(--color-ink-muted); }
.client-table tr.is-inactive td.client-name a, .client-table tr.is-inactive th.client-name a { color: var(--color-ink-muted); }
.client-balance {
  font: 600 var(--fs-lead)/1 var(--font-display);
  font-variant-numeric: lining-nums tabular-nums;
  color: var(--color-ink);
}
.client-balance.is-neg { color: var(--color-danger); }
.client-balance.is-zero { color: var(--color-ink-muted); }
.pill.client-status { font-size: var(--fs-sm); }
.client-status.is-active { background: var(--olive-wash-3); color: var(--color-olive); }
.client-status.is-inactive { background: var(--color-surface-2); color: var(--color-ink-muted); }
@media (hover: hover) and (pointer: fine) {
  .client-table tbody tr:hover td, .client-table tbody tr:hover th:where(tbody *) { background: var(--olive-wash-2); }
}

/* Row cards (743px and down): the whole card is one link, at least 72px tall. */
.client-cards { display: none; margin: 0; padding: 0; list-style: none; }
.client-card-item { border-top: 1px solid var(--color-border); }
.client-card-item:first-child { border-top: 0; }
.client-list-card a.client-card,
.client-list-card a.client-card:hover { border-bottom: 0; text-decoration: none; }
.client-card {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--m-card-min);
  padding: var(--space-3) var(--m-pad);
}
@media (hover: hover) and (pointer: fine) {
  .client-card:hover { background: var(--olive-wash-2); }
}
.client-card-text { display: flex; flex: 1 1 auto; flex-direction: column; gap: var(--space-hair); min-width: 0; }
.client-card-name { font: 600 var(--fs-body)/1.25 var(--font-body); color: var(--color-ink); overflow-wrap: anywhere; }
.client-card-meta { font: var(--text-meta); color: var(--color-ink-muted); overflow-wrap: anywhere; }
.client-card-balance {
  display: flex;
  flex: 0 0 auto;
  flex-direction: column;
  align-items: flex-end;
  font: 600 var(--fs-title)/1 var(--font-display);
  font-variant-numeric: lining-nums tabular-nums;
  color: var(--color-ink);
}
.client-card-balance small { font: 500 var(--fs-xs)/1.2 var(--font-body); color: var(--color-ink-muted); }
.client-card-balance.is-neg { color: var(--color-danger); }
.client-card-balance.is-zero { color: var(--color-ink-muted); }
.client-card-item.is-inactive .client-card-name,
.client-card-item.is-inactive .client-card-meta,
.client-card-item.is-inactive .client-card-balance { color: var(--color-ink-muted); }
.client-card-item.is-inactive .client-card-balance.is-neg { color: var(--color-danger); }

.client-empty { padding: var(--space-6) var(--space-5); text-align: center; color: var(--color-ink-muted); }
.client-empty p { margin: 0; }
.client-empty .btn { margin-left: var(--space-2); }
.client-nomatch { margin: 0; padding: var(--space-6) var(--space-5); text-align: center; }
.client-footnote { margin: 0; padding: var(--space-3) var(--space-5) var(--space-4); border-top: 1px solid var(--color-border); }

@media (max-width: 1023px) {
  /* Row cards below 1024px (Tesstarossa, 21 Oct 2026: the six-column table did not fit the iPad
     card). The search stays pinned at the top of the page area while the list scrolls (spec 2.5). */
  .client-toolbar {
    position: sticky;
    top: 0;
    z-index: 20;
    padding: var(--space-3) var(--m-pad);
    background: var(--color-surface);
  }
  .client-toolbar .client-count { margin-left: auto; }
  .client-table-wrap { display: none; }
  .client-cards { display: block; }
  .client-footnote { padding-left: var(--m-pad); padding-right: var(--m-pad); }
  .client-hint { margin-left: var(--m-pad); margin-right: var(--m-pad); }
  .client-empty, .client-nomatch { padding-left: var(--m-pad); padding-right: var(--m-pad); }
}
@media (max-width: 743px) {
  /* The phone has a top bar: the search pins under it. */
  .client-toolbar { top: var(--m-topbar); }
}
.client-nomatch a { display: inline-block; padding: var(--space-3) var(--space-1); }

/* ===== Phase 3b: the top of the client page (K.J. approved the spec 21 Oct 2026; PHASE-3-CLIENTS.md
   section 3). Header, the five-figure strip, More Figures, package cards, the Sessions card.
   Olive for chrome, cream only for "Owes" and "you are here", red only for Overdraw, No-show and
   destructive buttons. Tokens only (design-lint). ===== */
.client-head-text { min-width: 0; }
.client-head h1 { overflow-wrap: anywhere; }
.client-head h1 .tag-pill { font-family: var(--font-body); vertical-align: middle; margin-left: var(--space-2); }
.client-head .client-meta { margin: var(--space-1) 0 0; font: var(--text-meta); overflow-wrap: anywhere; }
.client-meta .meta-plain { display: none; }
.client-actions .btn { min-height: var(--m-tap); display: inline-flex; align-items: center; justify-content: center; }

.client-strip { padding: var(--space-4) var(--space-5); }
.client-strip .client-summary { margin: 0; padding: 0; border: 0; background: none; }
.strip-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr) repeat(3, minmax(0, 1fr)); gap: var(--space-3) var(--space-5); }
.strip-grid dd, .more-grid dd { overflow-wrap: anywhere; }
.strip-grid > div { display: flex; flex-direction: column; }
.client-strip .strip-grid > div dd { margin-top: auto; padding-top: var(--space-hair); font: var(--text-ui); font-weight: 600; font-variant-numeric: lining-nums tabular-nums; }
.client-strip .strip-grid > .strip-balance dd strong { font-size: var(--fs-display-sm); line-height: 1; }
.client-strip .strip-grid .strip-next dd .muted { font-weight: 400; }
/* Trials note, Option A (K.J. 28 Oct 2026; Tesstarossa's look pass on PR 198): the note hangs under Done,
   so the figure stays level with the others, and the strip grows only when a note is there. It
   stays inside its own cell (Shiva's Tier D on PR 198, F2): below 1024px that cell can be narrower
   than the note (74px at 744, 72px at 375), so the note wraps there and the strip keeps room for
   two note lines; from 1024px the cell is 119px or more and one line is enough. */
.client-strip .strip-grid > div dd:has(.strip-note) { position: relative; }
.client-strip .strip-note { position: absolute; top: 100%; left: 0; right: 0; }
.client-strip:has(.strip-note) { padding-bottom: calc(var(--space-4) + 1.45 * var(--fs-meta)); }
@media (max-width: 1023px) {
  .client-strip:has(.strip-note) { padding-bottom: calc(var(--space-4) + 2 * 1.45 * var(--fs-meta)); }
}
.more-figs { margin: var(--space-2) 0 var(--space-5); }
.more-figs > summary, .old-row {
  display: inline-flex; align-items: center; gap: var(--space-2); min-height: var(--m-tap); cursor: pointer;
}
.more-figs > summary { list-style: none; padding: 0 var(--space-1); font: var(--text-ui); font-weight: 600; color: var(--color-olive); }
.more-figs > summary::-webkit-details-marker { display: none; }
.chev { width: var(--space-4); height: var(--space-4); flex: none; transition: transform var(--dur-fold) var(--ease-out); }
.more-figs[open] > summary .chev, .old-row[aria-expanded="true"] .chev { transform: rotate(180deg); }
.more-card { margin-top: var(--space-1); padding: var(--space-4) var(--space-5); }
.more-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--space-3) var(--space-5); }
.more-grid dd { font: var(--text-ui); font-weight: 600; font-variant-numeric: tabular-nums; }

.overdraw-line {
  margin: 0 0 var(--space-5); padding: var(--space-3) var(--space-4);
  border: 1px solid var(--danger-line); border-radius: var(--radius-sm);
  background: var(--color-surface); color: var(--color-danger); font: var(--text-ui);
}

.card-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); margin: 0 0 var(--space-4); }
.card-head h2 { margin: 0; }
.empty-line { margin: 0; padding: var(--space-4) 0; color: var(--color-ink-muted); }
.empty-line a { font-weight: 600; }

/* Package cards */
.pkg { padding: var(--space-5); border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); min-width: 0; }
.pkg + .pkg, .pkg + .old-list { margin-top: var(--space-4); }
.pkg.row-highlight { background: var(--cream-wash); }
.pkg-top { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); }
.pkg-name { font: 600 var(--fs-body)/1.3 var(--font-body); }
.pkg-name small { margin-left: var(--space-2); font: var(--text-meta); color: var(--color-ink-muted); }
.pkg-pills { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.pkg-pill {
  display: inline-flex; align-items: center; gap: var(--space-2); padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill); font: var(--text-chip); font-size: var(--fs-sm); line-height: 1.3; white-space: nowrap;
}
.pkg-pill.is-active { background: var(--olive-wash-3); color: var(--color-olive); }
.pkg-pill.is-tag { background: var(--color-surface-2); color: var(--color-ink-muted); }
.pkg-pill.is-over { background: var(--color-surface); color: var(--color-danger); box-shadow: inset 0 0 0 var(--space-px) var(--danger-line); }
.pkg-pill.is-owes { background: var(--cream-wash); color: var(--color-ink); }
.pkg-pill.is-owes::before { content: ""; width: var(--space-2); height: var(--space-2); border-radius: var(--radius-pill); background: var(--color-cream); box-shadow: 0 0 0 var(--space-px) var(--color-border-strong); }
.meter { height: var(--space-2); margin-top: var(--space-4); border-radius: var(--radius-pill); background: var(--olive-wash-4); overflow: hidden; }
.meter > i { display: block; height: 100%; border-radius: var(--radius-pill); background: var(--color-olive); }
.meter.is-over > i { background: var(--color-danger); }
.meter-label { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-1) var(--space-3); margin: var(--space-2) 0 0; font: var(--text-meta); color: var(--color-ink-muted); }
.meter-label b { color: var(--color-ink); font-weight: 700; font-variant-numeric: lining-nums tabular-nums; }
.meter-label .overdraw-text b { color: var(--color-danger); }
.pkg-facts { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-3) var(--space-4); margin: var(--space-4) 0 0; }
.pkg-facts > div { min-width: 0; }
.pkg-facts dt { font: var(--text-label); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--color-ink-muted); }
.pkg-facts dd { margin: var(--space-1) 0 0; font: var(--text-ui); font-weight: 600; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.pkg-facts dd small { display: block; margin-top: var(--space-hair); font: var(--text-meta); font-weight: 400; color: var(--color-ink-muted); }
.pkg-facts dd small.inline-small { display: inline; margin: 0; }
.pkg-facts .is-wide { grid-column: span 2; }
.pkg-actions { display: flex; flex-wrap: wrap; gap: var(--space-1); margin: var(--space-4) 0 0; padding-top: var(--space-2); border-top: 1px solid var(--color-border); }
.pkg-actions .btn { min-height: var(--m-tap); }
.pkg-actions .btn[aria-expanded="true"] { background: var(--olive-wash-3); }
.pkg-actions .btn.is-danger-text { color: var(--color-danger); margin-left: auto; }
.pkg-cant { margin: 0; }
.pkg-panel { margin-top: var(--space-3); padding: var(--space-4); border-radius: var(--radius-sm); background: var(--color-paper); border: 1px solid var(--color-border); }
.pkg-panel[hidden], .old-detail[hidden], [data-sessions-pane][hidden], [data-past-extra][hidden] { display: none; }
.pkg-panel h3 { margin: 0 0 var(--space-3); font: 600 var(--fs-body)/1.2 var(--font-body); }
/* As many columns as hold a whole date or a whole Reason (C8, Tesstarossa's look pass: three clipped them at 1280). */
.pkg-panel .fields { display: grid; grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); gap: var(--space-3); }
.pkg-panel .fields label { margin: 0; font: var(--text-label); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--color-ink-muted); }
.pkg-panel .fields .span-2 { grid-column: span 2; }
.pkg-panel .fields .span-all { grid-column: 1 / -1; }
.pkg-panel .pkg-edit-form input:not([type="checkbox"]):not([type="radio"]),
.pkg-panel .pkg-edit-form select { display: block; width: 100%; max-width: 100%; margin-top: var(--space-1); font-weight: 400; text-transform: none; letter-spacing: 0; }
.pkg-panel .pkg-edit-form .btn { margin-top: var(--space-3); }
.pkg-panel .adjust-list { margin: 0; padding-left: var(--space-5); }
.pkg-panel .adjust-list li { margin-bottom: var(--space-3); }

/* Older packages: one line each, opening the full card in place */
.old-list { margin-top: var(--space-4); border-top: 1px solid var(--color-border); }
.old-row {
  display: flex; width: 100%; gap: var(--space-3); padding: 0 var(--space-1); border: 0; border-bottom: 1px solid var(--color-border);
  background: transparent; text-align: left; font: var(--text-ui); color: var(--color-ink);
}
.old-main { flex: 1 1 auto; min-width: 0; font-weight: 600; }
.old-main small { margin-left: var(--space-2); font: var(--text-meta); font-weight: 400; color: var(--color-ink-muted); }
.old-use { color: var(--color-ink-muted); font: var(--text-meta); white-space: nowrap; }
.old-row .chev { color: var(--color-ink-muted); }
.old-detail { padding: var(--space-4) 0 var(--space-2); }

/* Add Package panel: three fields across on a desktop and an iPad, one on the phone sheet */
.pkg-add-form.add-fields { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3); align-items: end; margin: 0; }
.pkg-add-form.add-fields > label { margin: 0; }
.pkg-add-form.add-fields input:not([type="checkbox"]):not([type="radio"]), .pkg-add-form.add-fields select { display: block; width: 100%; max-width: 100%; margin-top: var(--space-1); }
.pkg-add-form.add-fields > .btn { grid-column: 1 / -1; justify-self: start; }
.pkg-add-form.add-fields > label[hidden] { display: none; }
/* The payment and Sponsored wrappers add no box of their own: their fields sit in the same grid. */
.pkg-add-form.add-fields > div[data-payment-fields], .pkg-add-form.add-fields > div[data-sponsored-fields] { display: contents; }
.pkg-add-form.add-fields > div[hidden] { display: none; }
.pkg-add-form.add-fields > div > label { margin: 0; }
.pkg-add-form.add-fields > .inline-error { grid-column: 1 / -1; margin: 0; }
.pkg-add-form.add-fields > .inline-error[hidden] { display: none; }
/* Read-only Price and Expires read as shown, not typed, at every width (the phone sheet too). */
.pkg-add-form [data-price-shown], .pkg-add-form [data-expiry-input][readonly],
.addpkg-sheet .pkg-add-form [data-price-shown], .addpkg-sheet .pkg-add-form [data-expiry-input][readonly] { background: var(--color-surface-2); color: var(--muted); }
.how-fold { margin: var(--space-4) 0 0; }

/* Sessions card */
.seg { display: inline-flex; border: 1px solid var(--color-input-border); border-radius: var(--radius-sm); overflow: hidden; }
.seg-btn { min-height: var(--m-tap); padding: 0 var(--space-4); border: 0; background: var(--color-surface); color: var(--color-olive); font: var(--text-ui); font-weight: 600; cursor: pointer; }
.seg-btn[aria-pressed="true"] { background: var(--color-olive); color: var(--color-paper); }
.session-list { margin: 0; padding: 0; list-style: none; }
.session-list li { border-top: 1px solid var(--color-border); }
.session-list li:first-child { border-top: 0; }
main a.session-row, main a.session-row:hover {
  display: flex; align-items: center; gap: var(--space-4); min-height: var(--m-tap); padding: var(--space-2) var(--space-1);
  color: var(--color-ink); text-decoration: none; border-bottom: 0;
}
.session-d { font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }
.session-c { flex: 1 1 auto; min-width: 0; color: var(--color-ink-muted); overflow-wrap: anywhere; }
@media (hover: hover) and (pointer: fine) { main a.session-row:hover { background: var(--olive-wash-2); } }
.sess-pill { padding: var(--space-1) var(--space-3); border-radius: var(--radius-pill); font: var(--text-chip); font-size: var(--fs-sm); white-space: nowrap; }
.sess-pill.is-confirmed { background: var(--olive-wash-3); color: var(--color-olive); }
.sess-pill.is-tentative { background: var(--state-pending-fill); color: var(--color-olive); }
.sess-pill.is-done { background: var(--color-surface-2); color: var(--color-ink-muted); }
.sess-pill.is-noshow { background: var(--color-surface); color: var(--color-danger); box-shadow: inset 0 0 0 var(--space-px) var(--danger-line); }
.sess-pill.is-lmc { background: var(--color-surface); color: var(--color-ink-muted); box-shadow: inset 0 0 0 var(--space-px) var(--color-border-strong); }
.sess-pill.is-cancelled { background: var(--color-surface); color: var(--color-ink-muted); }
.more-link { display: inline-flex; align-items: center; min-height: var(--m-tap); margin-top: var(--space-2); padding: 0; border: 0; background: none; color: var(--color-olive); font: var(--text-ui); font-weight: 600; cursor: pointer; }
.sessions-card { margin-bottom: var(--space-5); }

@media (max-width: 1199px) {
  .more-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .pkg-panel .fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 743px) {
  /* The header's actions go: Add Package and Book sit pinned above the tab bar. */
  .client-actions .btn:not(.quiet) { display: none; }
  /* The phone's generic summary and link rules (tap size, a leading arrow) are not wanted on these two. */
  main .more-figs > summary { display: inline-flex; width: auto; }
  main .more-figs > summary::before { content: none; }
  /* Spec amends (Tesstarossa, 22 Oct 2026): the "(%)" suffix and the coach link are for 744px and up. */
  .long-label, .client-meta .meta-link { display: none; }
  .client-meta .meta-plain { display: inline; }
  .client-strip { padding: var(--space-4); }
  .strip-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-3) var(--space-2); }
  .strip-grid > .strip-next { grid-column: 1 / -1; grid-row: 1; }
  .client-strip .strip-grid > .strip-balance dd strong { font-size: var(--fs-title); }
  .more-card { padding: var(--space-3) var(--space-4); }
  .more-grid { grid-template-columns: 1fr 1fr; }
  .pkg { padding: var(--space-4); }
  .pkg-facts { grid-template-columns: 1fr 1fr; }
  .pkg-panel .fields, .pkg-add-form.add-fields { grid-template-columns: 1fr; }
  .pkg-panel .fields .span-2, .pkg-panel .fields .span-all { grid-column: auto; }
  .pkg-actions .btn.is-danger-text { margin-left: 0; }
  .old-main small { display: block; margin: var(--space-hair) 0 0; }
  .old-use { display: none; }
  .session-row { flex-wrap: wrap; }
  main a.m-cta.m-cta-pair, main a.m-cta.m-cta-pair:hover { left: calc(50% + var(--space-1)); }
  main a.m-cta-add, main a.m-cta-add:hover {
    position: fixed; left: var(--m-pad); right: calc(50% + var(--space-1)); bottom: calc(var(--m-tabbar) + 10px); z-index: 60;
    display: flex !important; align-items: center; justify-content: center; min-height: 52px; border-radius: var(--radius-sm);
    background: var(--color-surface); color: var(--color-olive); border: 1px solid var(--color-input-border); text-decoration: none;
    box-shadow: var(--shadow-pop); font: 600 var(--fs-ui)/1 var(--font-body);
  }
  /* Screen fixes (K.J. 28 Oct 2026): the pair sits on a strip of page colour, so a control under it (for a
     client with no packages, the Sessions Upcoming · Past switch) shows no edge between or around the buttons.
     Its top is 4px under the --pinned-bottom line (base.html), the 2px focus outline and its 2px offset that run
     below a control scrolled to that line (Tesstarossa and Shiva Tier D on pull request 231). */
  body:has(main a.m-cta-pair)::after {
    content: ""; position: fixed; left: 0; right: 0; bottom: var(--m-tabbar); height: calc(52px + 10px + var(--space-2) - 4px);
    z-index: 59; background: var(--bg); pointer-events: none;
  }
}

/* ===== Phase 3c: the lower sections of the client page (K.J. approved the spec 21 Oct 2026;
   PHASE-3-CLIENTS.md section 4). Fixed Weekly, Client Away, Linked Clients and From Other Clients as
   cards of rows; Activity as rows; Details beside the main column from 1200px; Deactivate or Delete
   folded last. Folds open and swap at once (only the chevron turns). Tokens only (design-lint). ===== */
.profile-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-5); align-items: start; margin-bottom: var(--space-5); }
.profile-main { display: grid; gap: var(--space-5); min-width: 0; }
.profile-aside { min-width: 0; }
@media (min-width: 1200px) {
  .profile-layout { grid-template-columns: minmax(0, 1fr) minmax(18rem, 21rem); }
  .profile-aside { position: sticky; top: var(--space-5); }
}
.profile-main > .section-card, .profile-aside > .section-card { margin: 0; }
.profile-main .card-head { margin-bottom: var(--space-3); }

/* Rows: one card of rows per section (Fixed Weekly rules, away periods, links) */
.rule-list { list-style: none; margin: 0; padding: 0; }
.rule-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4);
  padding: var(--space-3) 0; border-top: 1px solid var(--color-border);
}
.rule-list > .rule-row:first-child { border-top: 0; }
.rule-row.is-muted .rule-when { color: var(--color-ink-muted); }
.rule-main { flex: 1 1 14rem; min-width: 0; display: flex; flex-direction: column; gap: var(--space-hair); }
.rule-when { font: var(--text-ui); font-weight: 600; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.row-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1); }
.row-actions form { margin: 0; }
.row-actions .btn { min-height: var(--m-tap); }
.row-actions .row-edit { display: inline-block; margin: 0; }
.row-actions .row-edit[open] { flex: 1 1 100%; }
/* An open Edit takes the row's full width: its form sits under the row, not in the button column. */
.rule-row:has(> .row-actions > .row-edit[open]) > .row-actions { flex: 1 1 100%; }
.row-actions .row-edit > summary { list-style: none; cursor: pointer; }
.row-actions .row-edit > summary::-webkit-details-marker { display: none; }
.row-actions .row-edit > form { margin-top: var(--space-3); max-width: 28rem; white-space: normal; }
.row-actions .row-edit > form input:not([type="checkbox"]):not([type="radio"]),
.row-actions .row-edit > form select { display: block; width: 100%; max-width: 100%; margin-top: var(--space-1); }
.row-actions .row-edit > form .btn { margin-top: var(--space-3); }
.row-actions .row-edit[open] > summary { background: var(--olive-wash-3); }
.row-actions .btn.is-danger-text { color: var(--color-danger); }
.links-card .rule-row .rule-main a { font-weight: 600; }

/* Quiet fold buttons: Add Slot, Add Away, Link Client, and the rule Edit */
.add-fold { margin-top: var(--space-3); }
.add-fold > summary { display: inline-flex; align-items: center; min-height: var(--m-tap); list-style: none; cursor: pointer; }
.add-fold > summary::-webkit-details-marker { display: none; }
.add-fold[open] > summary { background: var(--olive-wash-3); }
.rule-form {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3); align-items: end;
  margin: var(--space-3) 0 0; padding: var(--space-4); border: 1px solid var(--color-border);
  border-radius: var(--radius-sm); background: var(--color-paper);
}
.rule-form > label { margin: 0; font: var(--text-label); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--color-ink-muted); }
.rule-form > label input:not([type="checkbox"]):not([type="radio"]), .rule-form > label select {
  display: block; width: 100%; max-width: 100%; margin-top: var(--space-1); text-transform: none; letter-spacing: 0; font-weight: 400;
}
.rule-form > .btn { justify-self: start; }
.help-inline.how-fold { margin-top: var(--space-4); }

/* Deactivate or Delete: the heading is the fold's button */
.danger-card .fold-head { margin: 0; font-size: var(--fs-lead); }
.fold-toggle {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); width: 100%; min-height: var(--m-tap);
  padding: 0; border: 0; background: none; color: inherit; font: inherit; text-align: left; cursor: pointer;
}
.fold-toggle .chev { color: var(--color-ink-muted); }
.fold-toggle[aria-expanded="true"] .chev { transform: rotate(180deg); }
.fold-body { margin-top: var(--space-3); }
.danger-card .danger-zone { border: 0; padding: 0; background: none; }
.danger-card .danger-zone .btn.danger { min-height: var(--m-tap); }

/* More Details (the side column) and More Figures' look */
.more-details { margin-top: var(--space-3); padding-top: var(--space-3); border-top: 1px solid var(--color-border); }
.more-details > summary {
  display: inline-flex; align-items: center; gap: var(--space-2); min-height: var(--m-tap); list-style: none; cursor: pointer;
  font: var(--text-ui); font-weight: 600; color: var(--color-olive);
}
.more-details > summary::-webkit-details-marker { display: none; }
.more-details[open] > summary .chev { transform: rotate(180deg); }
.more-details .detail-grid { margin-top: var(--space-3); }
/* Long emails, names and notes wrap inside the card; the label column never grows. */
.details-card .detail-grid { grid-template-columns: minmax(0, 8.5rem) minmax(0, 1fr); margin-bottom: 0; }
.details-card .detail-grid dd { min-width: 0; overflow-wrap: anywhere; }
@media (min-width: 1200px) {
  /* The side column is narrow: each label sits above its value, as on the package cards. */
  .details-card .detail-grid { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .details-card .detail-grid dt { margin-top: var(--space-3); }
  .details-card .detail-grid dt:first-child { margin-top: 0; }
  .details-card .detail-grid dd { margin-top: var(--space-hair); }
}
.details-card .pdpa-note { margin: var(--space-3) 0 0; }

/* Activity: rows, the newest ten first, Show All for the rest */
.activity-list { list-style: none; margin: 0; padding: 0; }
.activity-row {
  /* The kind pill sits under the date, so the summary keeps the width in the main column at 1200px and up. */
  display: grid; grid-template-columns: minmax(0, 9.5rem) minmax(0, 1fr) auto auto;
  grid-template-areas: "when text amount link" "kind text amount link";
  align-items: start; gap: var(--space-1) var(--space-4); padding: var(--space-2) 0; border-top: 1px solid var(--color-border);
}
.activity-when { grid-area: when; padding-top: var(--space-1); }
.activity-row > .activity-kind { grid-area: kind; justify-self: start; }
.activity-text { grid-area: text; padding-top: var(--space-1); }
.activity-amount { grid-area: amount; padding-top: var(--space-1); }
.activity-link { grid-area: link; }
.activity-list > .activity-row:first-child { border-top: 0; }
.activity-when { font: var(--text-meta); color: var(--color-ink-muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.activity-text { min-width: 0; overflow-wrap: anywhere; font: var(--text-ui); }
.activity-amount { text-align: right; font: var(--text-ui); font-weight: 600; font-variant-numeric: tabular-nums; }
.activity-link { white-space: nowrap; font: var(--text-ui); }
.activity-link a { display: inline-flex; align-items: center; min-height: var(--m-tap); }

@media (max-width: 1199px) {
  .rule-form { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 743px) {
  .rule-form { grid-template-columns: 1fr; }
  /* Shiva Tier D finding 2: the phone's generic summary arrow is not wanted beside More Details' chevron (as More Figures). */
  main .more-details > summary { display: inline-flex; width: auto; }
  main .more-details > summary::before { content: none; }
  .rule-form > label { grid-column: auto; }
  .rule-row { padding: var(--space-3) 0; }
  /* Two lines per activity row: when and kind, then the summary and its amount; the link on its own line. */
  .activity-row {
    /* Look-pass amend A (Tesstarossa, 23 Oct 2026): the summary takes the full row; the sessions figure joins the date and kind line. */
    grid-template-columns: minmax(0, 1fr) auto auto; grid-template-areas: "when amount kind" "text text text" "link link link";
    gap: var(--space-1) var(--space-3);
  }
  .activity-row > .activity-kind { justify-self: end; }
  .activity-when, .activity-text, .activity-amount { padding-top: 0; }
  .activity-link a { min-height: var(--m-tap); }
}

/* ===== Phase 4b: the Bookings and Packages pages (K.J. approved the spec 23 Oct 2026;
   PHASE-4-PAGES.md 3.1 to 3.7). One card per list: a head, a toolbar, the table from 1024px and
   one row card per row below (Q4, as the Clients list). Package Types is one markup that turns
   into cards; its actions sit in the row's panel (2.4). Olive chrome, cream only for Owes, pink
   only Tentative, red only No-show, Overdraw and Delete. Tokens only (design-lint). ===== */
.list-card-box { padding: 0; }
.list-card-box + .list-card-box, .add-pkg-panel + .list-card-box { margin-top: var(--space-5); }
.list-card-box > .flash { margin: var(--space-4) var(--space-5) 0; }
.list-head {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--color-border);
}
.list-head h2 { margin: 0; }
.list-head .btn { min-height: var(--m-tap); }
.list-toolbar {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-3) var(--space-4);
  margin: 0; padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--color-border);
}
.list-toolbar-form { display: contents; }
.tool-field {
  display: flex; flex: 0 1 auto; flex-direction: column; gap: var(--space-1); min-width: 0; margin: 0;
  font: var(--text-label); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--color-ink-muted);
}
.tool-field select, .tool-field input:not([type="checkbox"]) {
  min-height: var(--m-tap); min-width: 0; max-width: 100%;
  font: var(--text-ui); text-transform: none; letter-spacing: 0; color: var(--color-ink);
}
.tool-field select { max-width: 16rem; }
.tool-search { flex: 1 1 14rem; }
.list-toolbar .list-search { margin: 0; }
.list-toolbar .list-search input[type="search"] { flex: 1 1 100%; max-width: none; min-height: var(--m-tap); }
.list-toolbar label.tool-check { min-height: var(--m-tap); margin: 0; }
.list-count { flex: 1 1 auto; margin: 0; align-self: center; text-align: right; font-variant-numeric: tabular-nums; }

.list-table-wrap { overflow-y: hidden; }
.list-table { width: 100%; border-collapse: collapse; }
.list-table th {
  padding: var(--space-3) var(--space-5); text-align: left; white-space: nowrap;
  font: var(--text-label); text-transform: uppercase; letter-spacing: var(--tracking-label);
  color: var(--color-ink-muted); border-bottom: 1px solid var(--color-border);
}
.list-table th.num, .list-table td.num { text-align: right; }
.list-table td, .list-table th:where(tbody *) {
  height: var(--client-row); padding: var(--space-2) var(--space-5); border-top: 1px solid var(--color-border);
  font: var(--text-ui); color: var(--color-ink); vertical-align: middle;
}
.list-table tbody tr:first-child td, .list-table tbody tr:first-child th:where(tbody *) { border-top: 0; }
.list-table th:where(tbody *) { text-transform: none; letter-spacing: normal; white-space: normal; }
/* 1024 to 1199px: the rail takes 88px, so the cells take less padding to fit the columns. */
@media (min-width: 1024px) and (max-width: 1199px) {
  .list-table th, .list-table td { padding-left: var(--space-3); padding-right: var(--space-3); }
}
.list-table td.list-name, .list-table th.list-name { min-width: var(--client-name-min); max-width: var(--client-name-max); font-weight: 600; overflow-wrap: anywhere; }
.list-table td.list-name a, .list-table th.list-name a { font-weight: 600; text-decoration: none; overflow-wrap: anywhere; }
.list-table td.list-wrap { overflow-wrap: anywhere; }
.bookings-table td.list-note { max-width: 18rem; }
/* Look-pass amend 1 (Tesstarossa, 23 Oct 2026): a long note shows two lines and an ellipsis; the drawer keeps it whole. */
.list-note-text { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; }
.list-nowrap { white-space: nowrap; }
.list-sub { display: block; font: var(--text-meta); color: var(--color-ink-muted); white-space: normal; }
/* C7: a package's expiry state under its date (Packages table, drawer Package fact): its own muted
   meta line that may wrap, never the cell's bold body text (Tesstarossa look pass, 3 Nov 2026). */
.expiry-state { display: block; margin-top: var(--space-hair); font: var(--text-meta); font-weight: 400;
  color: var(--color-ink-muted); white-space: normal; }
/* C8: a package's suspension records in its panel: quiet rows, with Undo folded away. */
.suspension-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.suspension-undo { margin-top: var(--space-1); }
/* Expiry Decisions: a slim group label between the rows, not a band of its own. */
.expiry-group { margin: 0; padding: var(--space-3) var(--space-5) var(--space-1); border-top: 1px solid var(--color-border);
  font: var(--text-label); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--color-ink-muted); }
#expiry-decisions .list-head > p { flex-basis: 100%; margin: 0; }
.list-head + .expiry-group { border-top: 0; }
/* Close, Expired Packages: Approve and Hold (with its reason) on one line where there is room. */
.lapse-actions { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-2) var(--space-4); margin-top: var(--space-2); }
.lapse-actions .stack-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-2); margin: 0; }
.lapse-actions .stack-form label { margin: 0; }
.list-fig { font: 600 var(--fs-lead)/1 var(--font-display); font-variant-numeric: lining-nums tabular-nums; }
.list-state .state-pill + .state-pill { margin-left: var(--space-1); }
.list-table tr.is-off td, .list-table tr.is-off th:where(tbody *), .list-table tr.is-off td.list-name a, .list-table tr.is-off th.list-name a { color: var(--color-ink-muted); }
/* An All Packages row is one link to the client's page at that package (spec 3.6). */
.package-table tbody tr { position: relative; }
/* Nine columns: the cells keep tighter padding, the meter sits over its figure. */
.package-table th, .package-table td { padding-left: var(--space-3); padding-right: var(--space-3); }
.package-table td.list-used .mini-meter { display: block; width: 100%; margin: 0 0 var(--space-1); }  /* fills its cell, so the column takes no more than its text */
.list-table td.list-coach { min-width: 6rem; overflow-wrap: anywhere; }
.list-coach-sub { display: none; font-weight: 400; overflow-wrap: anywhere; }
/* 1024 to 1199px: nine columns do not fit beside the rail, so the coach's name sits under the client's. */
@media (min-width: 1024px) and (max-width: 1199px) {
  .package-table .list-coach { display: none; }
  .package-table .list-coach-sub { display: block; }
  .package-table th, .package-table td { padding-left: var(--space-2); padding-right: var(--space-2); }
}
.package-table a.row-cover::after { content: ""; position: absolute; inset: 0; }
/* Design call 2B (K.J. 28 Oct 2026): a Bookings row's client name is a real button, drawn as the plain name; its
   cover stretches over the row (a click anywhere opens the booking). Keyboard: the ring round the name, the
   row band shaded. */
.bookings-table tbody tr { position: relative; }
.bookings-table button.row-cover {
  display: inline; padding: 0; margin: 0; border: 0; border-radius: var(--radius-xs); background: none;
  color: inherit; font: inherit; letter-spacing: inherit; text-align: inherit; overflow-wrap: anywhere;
}
.bookings-table button.row-cover::after { content: ""; position: absolute; inset: 0; }
.bookings-table button.row-cover:active { filter: none; }
.bookings-table tbody tr:has(.row-cover:focus-visible) > td,
.bookings-table tbody tr:has(.row-cover:focus-visible) > th { background: var(--olive-wash-2); }
/* Rounded ends, as the hover band (Tesstarossa's look pass on PR 200, 28 Oct 2026). */
.bookings-table tbody tr:has(.row-cover:focus-visible) > :first-child { border-top-left-radius: var(--radius-sm); border-bottom-left-radius: var(--radius-sm); }
.bookings-table tbody tr:has(.row-cover:focus-visible) > :last-child { border-top-right-radius: var(--radius-sm); border-bottom-right-radius: var(--radius-sm); }
@media (hover: hover) and (pointer: fine) {
  .bookings-table button.row-cover:hover { filter: none; }
  .bookings-table tbody tr:hover .row-cover { text-decoration: underline; text-underline-offset: 3px; }
  .bookings-table tbody tr:hover td, .package-table tbody tr:hover td, .bookings-table tbody tr:hover th:where(tbody *), .package-table tbody tr:hover th:where(tbody *) { background: var(--olive-wash-2); }
}

/* State pills: the calendar's (Confirmed olive, Tentative pink, Done sunk, No-show red outline,
   Cancelled muted with its reason); Package Types and packages use the quiet olive and sunk ones. */
.state-pill {
  display: inline-flex; align-items: center; padding: var(--space-1) var(--space-3); border-radius: var(--radius-pill);
  font: var(--text-chip); font-size: var(--fs-sm); line-height: 1.3; white-space: nowrap;
}
.state-pill.is-confirmed { background: var(--color-olive); color: var(--color-paper); }
.state-pill.is-tentative { background: var(--color-pink); color: var(--color-ink); }
.state-pill.is-done, .state-pill.is-off { background: var(--color-surface-2); color: var(--color-ink-muted); }
.state-pill.is-noshow, .state-pill.is-over { background: var(--color-surface); color: var(--color-danger); box-shadow: inset 0 0 0 var(--space-px) var(--danger-line); }
.state-pill.is-cancelled { background: var(--color-surface); color: var(--color-ink-muted); box-shadow: inset 0 0 0 var(--space-px) var(--color-border-strong); }
.state-pill.is-tag { background: var(--olive-wash-2); color: var(--color-ink-muted); }
.state-pill.is-onsale { background: var(--olive-wash-3); color: var(--color-olive); }

/* Used / Total: a small meter before the figure; red when overdrawn. */
.mini-meter {
  display: inline-block; width: var(--space-10); height: var(--space-2); margin-right: var(--space-2);
  border-radius: var(--radius-pill); background: var(--olive-wash-4); overflow: hidden; vertical-align: middle;
}
.mini-meter > i { display: block; height: 100%; border-radius: var(--radius-pill); background: var(--color-olive); }
.mini-meter.is-over > i { background: var(--color-danger); }

/* Row cards (1023px and down): the whole card is one link or one button, at least 72px tall. */
.list-cards { display: none; margin: 0; padding: 0; list-style: none; }
.list-cards > li { border-top: 1px solid var(--color-border); }
.list-cards > li:first-child { border-top: 0; }
/* Look-pass amend 3 (Tesstarossa, 23 Oct 2026): the name keeps at least 12rem; a pill too long to sit beside it drops under it. */
.list-card {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); width: 100%; min-height: var(--m-card-min);
  margin: 0; padding: var(--space-3) var(--m-pad); border: 0; border-radius: 0; background: none;
  color: var(--color-ink); font: inherit; text-align: left; text-decoration: none; cursor: pointer;
}
.list-card-box a.list-card, .list-card-box a.list-card:hover { border-bottom: 0; text-decoration: none; }
@media (hover: hover) and (pointer: fine) {
  .list-card:hover { background: var(--olive-wash-2); }
}
.list-card-text { display: flex; flex: 1 1 12rem; flex-direction: column; gap: var(--space-hair); min-width: 0; }
.list-card-name { font: 600 var(--fs-body)/1.25 var(--font-body); color: var(--color-ink); overflow-wrap: anywhere; }
.list-card-meta { font: var(--text-meta); color: var(--color-ink-muted); overflow-wrap: anywhere; }
.list-card-end { display: flex; flex: 0 0 auto; flex-direction: column; align-items: flex-end; gap: var(--space-1); }
.list-cards > li.is-off .list-card-name { color: var(--color-ink-muted); }
.list-empty, .list-nomatch { margin: 0; padding: var(--space-6) var(--space-5); text-align: center; color: var(--color-ink-muted); }
.list-empty .link-btn, .list-empty a { display: inline-flex; align-items: center; min-height: var(--m-tap); font-weight: 600; }

/* Panels: a row's forms (Package Types), the New Type form, the Add Package chooser. */
.list-panel { padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--color-border); background: var(--color-paper); }
.list-panel-row > td { height: auto; padding: var(--space-4) var(--space-5); border-top: 0; background: var(--color-paper); }
.list-open[aria-expanded="true"] { background: var(--olive-wash-3); }
.type-panel { display: grid; gap: var(--space-4); }
.type-panel-more { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-3) var(--space-4); padding-top: var(--space-4); border-top: 1px solid var(--color-border); }
.type-panel-more .list-form { flex: 1 1 20rem; }
.type-panel-more > .inline, .type-panel-more > p { margin: 0; }
.list-form { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3) var(--space-4); align-items: end; margin: 0; }
.list-form > label:not(.check) {
  display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; margin: 0;
  font: var(--text-label); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--color-ink-muted);
}
.list-form > label:not(.check) input, .list-form > label:not(.check) select {
  width: 100%; min-height: var(--m-tap); font: var(--text-ui); text-transform: none; letter-spacing: 0; color: var(--color-ink);
}
.list-form > label.check { grid-column: 1 / -1; margin: 0; min-height: var(--m-tap); }
.list-form-actions { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: var(--space-2); }
.list-form-actions .btn, .type-panel-more .btn { min-height: var(--m-tap); }
.list-form-inline { grid-template-columns: minmax(0, 14rem) auto; }
.list-form-inline .list-form-actions { grid-column: auto; }
.list-how { margin: 0; padding: var(--space-3) var(--space-5) var(--space-4); border-top: 1px solid var(--color-border); }
.list-how p { margin: var(--space-2) 0 0; }
/* Look-pass amend 2 (Tesstarossa, 23 Oct 2026): the fold and its Pricing link are 44px targets at every size. */
.list-how > summary { display: flex; align-items: center; min-height: var(--m-tap); list-style: none; }
.list-how > summary::-webkit-details-marker { display: none; }
.list-how > summary::before { content: "\25B8"; display: inline-block; margin-right: var(--space-2); }
.list-how[open] > summary::before { transform: rotate(90deg); }
.list-how p a { display: inline-flex; align-items: center; min-height: var(--m-tap); }
.type-card-meta { display: none; }
/* Add Package (the header's primary) shows the client chooser while the address names it. */
.add-pkg-panel { margin: 0 0 var(--space-5); }
.add-pkg-panel:not(:target) { display: none; }
.add-pkg-panel h2 { margin: 0 0 var(--space-4); }
.add-pkg-panel .list-form { grid-template-columns: minmax(0, 24rem) auto; }
.add-pkg-panel .list-form-actions { grid-column: auto; }
.add-pkg-panel p { margin: var(--space-3) 0 0; }

@media (max-width: 1023px) {
  .list-table-wrap { display: none; }
  .list-cards { display: block; }
  .list-head, .list-toolbar, .list-panel, .list-how { padding-left: var(--m-pad); padding-right: var(--m-pad); }
  .list-empty, .list-nomatch { padding-left: var(--m-pad); padding-right: var(--m-pad); }
  .list-form { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Package Types as cards: the name and one meta line, the status on the right; the card is the Edit button. */
  .type-table, .type-table tbody { display: block; }
  .type-table thead { display: none; }
  .type-table tr.type-row {
    position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center;
    gap: var(--space-1) var(--space-3); min-height: var(--m-card-min); padding: var(--space-3) var(--m-pad);
    border-top: 1px solid var(--color-border);
  }
  .type-table tbody tr.type-row:first-child { border-top: 0; }
  .type-table tr.type-row > td { display: block; height: auto; padding: 0; border: 0; min-width: 0; max-width: none; }
  .type-table td.list-name { grid-column: 1; grid-row: 1 / span 2; }
  .type-table td.list-name > .list-sub { display: none; }
  .type-table .type-card-meta { display: block; font: var(--text-meta); font-weight: 400; color: var(--color-ink-muted); }
  .type-table tr.type-row > td.type-col { display: none; }
  .type-table td.list-state { grid-column: 2; grid-row: 1; text-align: right; }
  .type-table td.list-state .list-sub { display: none; }
  .type-table td.list-actions { grid-column: 2; grid-row: 2; text-align: right; }
  .type-table .list-open::after { content: ""; position: absolute; inset: 0; }
  .type-table tr.list-panel-row { display: block; }
  .type-table tr.list-panel-row > td { display: block; padding: var(--space-4) var(--m-pad); }
}
@media (max-width: 743px) {
  .tool-field { flex: 1 1 9rem; }
  .tool-field .dmy { max-width: none; }
  .list-count { flex-basis: 100%; text-align: left; }
  .list-form, .list-form-inline, .add-pkg-panel .list-form { grid-template-columns: minmax(0, 1fr); }
  .list-form-inline .list-form-actions, .add-pkg-panel .list-form-actions { grid-column: 1 / -1; }
}

/* ===== Phase 4c: the Coaches list and the coach page (K.J. approved the spec 23 Oct 2026;
   PHASE-4-PAGES.md 3.8 to 3.11). The list is the 4b list card (table from 1024px, one row card
   below); the coach page follows the client page: header, a five-figure strip and More Figures,
   cards of rows, and a side column with Personal Details and Pay Settings (rows whose forms open
   in panels, one at a time). Cream only for "Not Marked Done" above 0 and a pending leave the
   Chief of Staff must answer. Tokens only (design-lint). ===== */
.list-foot { margin: 0; padding: var(--space-3) var(--space-5) var(--space-4); border-top: 1px solid var(--color-border); }
.coach-table tbody tr { position: relative; }
.coach-table a.row-cover::after { content: ""; position: absolute; inset: 0; }
.coach-table td.list-name .tag-pill { position: relative; margin-left: var(--space-1); }
@media (hover: hover) and (pointer: fine) {
  .coach-table tbody tr:hover td, .coach-clients-table tbody tr:hover td, .coach-clients-table tbody tr:hover th:where(tbody *) { background: var(--olive-wash-2); }
}

/* The strip: five figures, each a serif lining figure; Not Marked Done carries a cream dot above 0. */
.coach-strip .strip-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); }
/* `> div` matches the shared strip's first-figure rule, so all five read the same size. */
.coach-strip .strip-grid > div dd strong { font: 600 var(--fs-display-sm)/1 var(--font-display); font-variant-numeric: lining-nums tabular-nums; }
/* The link keeps its 44px height on the phone but sits at the start, like the other figures. */
.coach-strip .strip-grid dd a { display: inline-flex; align-items: flex-end; justify-content: flex-start; min-height: var(--m-tap); min-width: var(--m-tap); text-decoration: none; color: inherit; }
.coach-strip .is-todo dd { display: flex; align-items: center; gap: var(--space-2); }
.coach-strip .is-todo dd::after {
  content: ""; width: var(--space-2); height: var(--space-2); border-radius: var(--radius-pill);
  background: var(--color-cream); box-shadow: 0 0 0 var(--space-px) var(--color-border-strong);
}

/* Lists inside a section card: the card's own padding is the row's edge. */
.list-table.in-card th, .list-table.in-card td { padding-left: var(--space-3); padding-right: var(--space-3); }
.list-table.in-card th:first-child, .list-table.in-card td:first-child { padding-left: 0; }
.list-table.in-card th:last-child, .list-table.in-card td:last-child { padding-right: 0; }
.coach-clients-table tbody tr { position: relative; }
.coach-clients-table a.row-cover::after { content: ""; position: absolute; inset: 0; }
.list-cards.in-card .list-card { padding-left: 0; padding-right: 0; }
.list-card.is-static { cursor: default; }
/* Look-pass amend 1: the top-up working sits on its own line under its month, so the Top-up
   cell keeps only the amount on one line. */
.pay-month-table tr.pay-topup-note td { height: auto; padding-top: 0; border-top: 0; }

/* Weekly Pattern: a row per weekday, its slots wrapping beside the day. */
.pattern-list .rule-row { flex-wrap: nowrap; align-items: baseline; }
.pattern-list .pattern-day { flex: 0 0 var(--space-10); }
.pattern-slots { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); min-width: 0; }
.pattern-list .pattern-slot { display: inline-block; white-space: normal; overflow-wrap: anywhere; font: var(--text-ui); }

/* Leave rows: Approve and Reject on the row; Edit opens the row's form with Delete under it. */
.leave-list .row-edit .leave-delete { display: block; margin-top: var(--space-3); }
.leave-list .row-actions .btn.small { min-height: var(--m-tap); }

/* Side column */
.details-edit { margin: var(--space-3) 0 0; }
.details-edit a { display: inline-flex; align-items: center; min-height: var(--m-tap); font-weight: 600; }
.coach-layout .profile-aside { display: grid; gap: var(--space-5); align-content: start; }
.pay-settings h2 { margin: 0 0 var(--space-2); }
.set-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3);
  padding: var(--space-3) 0; border-top: 1px solid var(--color-border);
}
.set-list > .set-row:first-child { border-top: 0; }
.set-main { display: flex; flex: 1 1 10rem; flex-direction: column; gap: var(--space-hair); min-width: 0; overflow-wrap: anywhere; }
.set-label { font: var(--text-label); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--color-ink-muted); }
.set-value { font: var(--text-ui); }
.set-row .btn { min-height: var(--m-tap); }
.set-panel { margin: 0 0 var(--space-3); padding: var(--space-3); border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-paper); min-width: 0; }
.set-panel[hidden] { display: none; }
.set-panel h3 { margin: 0 0 var(--space-2); font: 600 var(--fs-body)/1.2 var(--font-body); }
.set-panel h4 { margin: var(--space-4) 0 var(--space-2); font: var(--text-label); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--color-ink-muted); }
.set-panel .stack-form input:not([type="checkbox"]):not([type="radio"]), .set-panel .stack-form select { display: block; width: 100%; max-width: 100%; }
.set-panel .btn { min-height: var(--m-tap); }
.set-panel .rate-table { width: 100%; }
.set-panel .rate-table th, .set-panel .rate-table td { padding-left: var(--space-1); padding-right: var(--space-1); }
.set-panel .rate-table th:first-child, .set-panel .rate-table td:first-child { padding-left: 0; }
.set-panel .rate-table th { white-space: normal; }
.set-panel .rate-table .btn.small { min-height: var(--m-tap); }
.set-panel .rate-table th:last-child, .set-panel .rate-table td:last-child { padding-right: 0; }
/* From 1200px the side column holds Pay Settings' panels: a little wider than the client page's. */
@media (min-width: 1200px) {
  .coach-layout { grid-template-columns: minmax(0, 1fr) minmax(20rem, 24rem); }
}

@media (max-width: 1023px) {
  .coach-strip .strip-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 743px) {
  .coach-strip .strip-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .coach-strip .strip-grid > div dd strong { font-size: var(--fs-title); }
  /* The client page pins its actions above the tab bar; the coach page keeps Add Leave in its header. */
  .coach-head .client-actions .btn:not(.quiet) { display: inline-flex; }
}

/* ===== Phase 4e: the small pages (K.J. gave the go 25 Oct 2026; PHASE-4-PAGES.md 3.16 to 3.20). ===== */
/* Sign In: a 400px card under the wordmark (3.16; the wordmark colour is in the login block above). */
.login-club .card.narrow { min-width: 0; max-width: 400px; }
/* Not Available: the same centred card, one sentence and a button (3.17). */
.card.not-available { max-width: 400px; margin: var(--space-10) auto; text-align: center; }
.card.not-available h1 { margin-bottom: var(--space-3); }
/* Something Went Wrong (app/server_error.py): the reference larger and letter-spaced, so it can be read
   out (K.J. 28 Oct 2026, "Larger, letter-spaced"). */
.server-error-ref { font-family: var(--font-body); font-size: var(--fs-lead); letter-spacing: var(--tracking-label); }
/* The same message inside the open booking drawer (Shiva's Tier D on PR 222): in the card's flow, under its header. */
.booking-panel .flash-toast[data-error-ref] { position: static; transform: none; width: auto; max-width: none; margin: 0 0 var(--space-4); box-shadow: none; }
.list-card.is-static { cursor: default; }
/* My Account: signed-in devices as rows, at least 56px (3.19). */
.device-list { list-style: none; margin: 0 0 var(--space-4); padding: 0; }
.device-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-3); min-height: 56px; padding: var(--space-2) 0; border-top: 1px solid var(--color-border); }
.device-row:first-child { border-top: 0; }
.device-name { font-weight: 600; flex: 1 1 10rem; }
.device-this { font-weight: 600; font-size: var(--fs-sm); margin-left: var(--space-2); padding: 0 var(--space-2); border-radius: var(--radius-pill); background: var(--olive-wash-2); white-space: nowrap; }
/* New / Edit Client and Coach: one card, fields three across from 1024px, two on an iPad, one on a phone (2.5, 3.20). */
.form-page { max-width: 64rem; }
.form-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0 var(--space-5); align-items: start; }
@media (min-width: 744px) { .form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .form-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.form-grid > :not(label):not(.field) { grid-column: 1 / -1; }
.form-grid > label.check { grid-column: 1 / -1; }
.form-grid .field > label { margin-bottom: var(--space-1); }
.form-grid .field > p { margin: 0 0 var(--space-3); }
.form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); margin-top: var(--space-4); }
.form-actions button[type="submit"], .form-actions .btn { min-height: var(--m-tap); }
/* #86 polish (Tesstarossa): a pill has overflow hidden, so its baseline is its bottom edge and the Due now chip rode high; centre it on the text. */
.area-export-page p > .pill { vertical-align: middle; }
.area-export-page p > .pill.status-needs-ack::before { margin-right: var(--space-1); }
/* Small fixes (K.J. 27 Oct 2026): the cards touched; the gap Old Clients and a client page's cards have. */
.area-export-page > .card + .card { margin-top: var(--space-5); }
/* PDPA I3 look pass (Tesstarossa amends 1, 2; K.J. 27 Oct 2026). The list's tick boxes: .stack-form label
   (block) comes later than label.check, so on 744px and up the box lost its gap and centring; 44px rows
   on every width. The cards get the gap a client page's cards have. */
.old-clients-page td label.check { display: flex; align-items: center; gap: var(--space-2); min-height: var(--m-tap); margin: 0; }
/* The same again in a form that stacks its labels (C8, Tesstarossa's look pass; the refund panel's box too). */
.stack-form label.check { display: flex; align-items: center; gap: var(--space-2); min-height: var(--m-tap); margin: var(--space-2) 0; }
.suspend-ticks label.check { margin: 0; }  /* a list of ticks keeps its rows 44px apart */
.suspend-form .consequence { margin-bottom: var(--space-3); }
.old-clients-page > .card + .card { margin-top: var(--space-5); }
.login-club .card.narrow button[type="submit"] { min-height: 44px; }

/* Free sessions PR C look pass (Tesstarossa 26 Oct 2026). Referral and Sponsored: a table from 1024px,
   one card per referrer or client below it (the ten-column table did not fit a phone). The EBITDA
   table's "of which" rows are indented and muted so they are not added twice. A warning's links sit on
   their own line on a phone. Tokens only. */
.fin-cards { display: none; margin: 0; padding: 0; list-style: none; }
.fin-card { padding: var(--space-3) 0; border-top: 1px solid var(--color-border); }
.fin-card:first-child { border-top: 0; }
.fin-card-name { margin: 0 0 var(--space-2); font: 600 var(--fs-body)/1.25 var(--font-body); color: var(--color-ink); overflow-wrap: anywhere; }
.fin-card-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2) var(--space-4); margin: 0; }
.fin-card-grid div { min-width: 0; }
.fin-card-grid dt { font: var(--text-meta); color: var(--color-ink-muted); }
.fin-card-grid dd { margin: 0; font-variant-numeric: lining-nums tabular-nums; overflow-wrap: anywhere; }
.fin-card-total { margin: var(--space-3) 0 0; padding-top: var(--space-3); border-top: 1px solid var(--color-border); font-weight: 600; }
.fin-amount { white-space: nowrap; }  /* "RM" stays with its figure */
.f1-of td:first-child { padding-left: var(--space-6); color: var(--color-ink-muted); }
.f1-of td.num { color: var(--color-ink-muted); }
.finance-table.wrap-first th:first-child, .finance-table.wrap-first td:first-child { white-space: normal; }
.flag-actions { display: inline; }
@media (max-width: 1023px) {
  .fin-wide { display: none; }
  .fin-cards { display: block; }
}
@media (max-width: 743px) {
  .flag-actions { display: block; margin-top: var(--space-1); }
  .flag-actions a { display: inline-flex; align-items: center; min-height: var(--m-tap); }
}

/* ===== Phase 5A: motion (spec PHASE-5-MOTION-A11Y.md section 2; K.J. 26 Oct 2026) =====
   Press: a small scale on buttons only (not chips, rows, links or nav items: frequent or large).
   Disabled buttons do nothing. Every moving rule above has a partner in a reduced-motion block
   (tests/test_phase5_motion.py fails when one is missing). */
.btn, .tab, .m-ring, .toast .toast-undo, .m-fab {
  transition: transform var(--dur-press) var(--ease-out);
}
.btn:active:not(:disabled):not([aria-disabled="true"]),
.tab:active, .m-ring:active, .toast .toast-undo:active, .m-fab:active {
  transform: scale(0.97);
}
@media (prefers-reduced-motion: reduce) {
  .btn, .tab, .m-ring, .toast .toast-undo, .m-fab { transition: none; }
  .btn:active:not(:disabled):not([aria-disabled="true"]),
  .tab:active, .m-ring:active, .toast .toast-undo:active, .m-fab:active { transform: none; }
  .chev { transition: none; }
}

/* ===== Phase 5B: page-wide accessibility (spec PHASE-5-MOTION-A11Y.md section 3; K.J. 26 Oct 2026) =====
   Focus not obscured (WCAG 2.4.11): a control reached with Tab never sits under a pinned bar. The pinned
   bars change height with the page and with text zoom, so base.html measures them and sets
   --pinned-top and --pinned-bottom; the browser keeps a focused control (and an anchor jump) clear of them. */
html {
  scroll-padding-top: var(--pinned-top, 0px);
  scroll-padding-bottom: var(--pinned-bottom, 0px);
}
/* Forced colours, Windows high contrast (Q3, K.J. 26 Oct 2026: a small safety pass, not a second design).
   Shadows and fills are dropped there, so a field's focus halo, a pill's fill and "you are here" get a
   real line in system colours. */
@media (forced-colors: active) {
  input:focus-visible, select:focus-visible, textarea:focus-visible { outline: 2px solid Highlight; outline-offset: 2px; }
  .btn, .seg-btn, .chip-btn, .m-fab, main a.m-cta, main a.m-cta-add { border: 1px solid ButtonText; }
  .pill, .tag-pill, .state-pill, .sess-pill, .pkg-pill, .client-status, .activity-kind, .nav-count { border: 1px solid CanvasText; }
  /* Session chips: the fills are gone, so the edge carries the state's shape (Plan dashed, No-show heavy;
     the No-show's red inset is a shadow and vanishes). Named as the chip rules name them, so this wins. */
  button.booking-chip, .booking-chip, .m-card, .chip.to-mark { border: 1px solid CanvasText; }
  button.booking-chip.planned, .booking-chip.planned, .m-card.plan, .m-card.clash { border-style: dashed; }
  button.booking-chip.no-show, .booking-chip.no-show, .m-card.noshow { border-width: 3px; }
  .nav-item.active, .tab.active, main .cal-switch a.active, main .fin-tabs a.active, .seg-btn[aria-pressed="true"],
  .m-mini-days input:checked + span, .m-slots input:checked + span, .m-seg input:checked + span,
  .yday.today, .m-dayb.selected { outline: 2px solid Highlight; outline-offset: -2px; }
  .cal-grid th.today, .m-dayb.today { border-top: 3px solid CanvasText; }  /* today's olive bar is a shadow */
  button:disabled, .btn:disabled, .btn[aria-disabled="true"] { color: GrayText; border-color: GrayText; }
}

/* ===== Phase 5C: calendar, drawer, sheet and toast (spec section 4; K.J. 26 Oct 2026) =====
   Forced colours drop fills, so "Not Marked" (a cream dot) vanished (seen in the 5B screenshot). The dots
   keep their own colour as text-coloured marks, and the key's swatches get an edge. */
@media (forced-colors: active) {
  .booking-chip.needs-ack::after, .swatch.needs-ack::after, .dot-cream, .pill.status-needs-ack::before,
  .m-dayb .dot.mark, .m-card.tent.mark::after { forced-color-adjust: none; background: CanvasText; }
  .swatch { border: 1px solid CanvasText; }
  .swatch.planned { border-style: dashed; }
}

/* ===== Phase 5D: tables (spec PHASE-5-MOTION-A11Y.md section 3, WCAG 1.3.1; K.J. 26 Oct 2026) =====
   A cell that names its row is a row header (<th scope="row" class="row-name">) for screen readers, and
   looks exactly like the plain cell it was: no label type, no capitals, no bold, and it wraps. */
th.row-name { font: inherit; text-transform: none; letter-spacing: 0; color: inherit; white-space: normal; }
/* A totals figure (tfoot) is a cell now, not a header; it keeps the look the header cell gave it. */
tfoot td.foot-fig { font: var(--text-label); font-family: var(--font-body); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--muted); height: auto; padding-top: var(--space-3); padding-bottom: var(--space-3); }
.finance-table tfoot td.foot-fig { font-size: inherit; text-transform: none; letter-spacing: 0; color: var(--ink); }

/* —— Passkeys P2 (stream kj-passkeys-p2, Tesstarossa look pass amends 5 and 6, 26 Oct 2026) ——
   One passkey per row on desktop: name with its date line under it, Remove on the right.
   Phone: stacked. The codes sheet's two buttons share one left edge when they wrap. */
.passkey-row { flex-wrap: nowrap; }
.passkey-row .passkey-what { display: flex; flex-direction: column; gap: var(--space-1); flex: 1 1 auto; min-width: 0; }
.passkey-row .passkey-what .device-name { flex: none; }
@media (max-width: 743px) {
  .passkey-row { flex-direction: column; align-items: flex-start; }
}
.recovery-sheet .sheet-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
@media print { .recovery-sheet .sheet-actions { display: none; } }
/* Passkeys P3 (Tesstarossa look pass amend 1, 27 Oct 2026): the recovery fold on One More Step
   reads as a Quiet text button, as the app's other folds do, with a 44px target and room around it. */
.recovery-details { margin-top: var(--space-4); }
.recovery-details > summary { display: inline-flex; align-items: center; min-height: var(--m-tap); list-style: none; cursor: pointer; font: var(--text-ui); font-weight: 600; color: var(--color-olive); }
.recovery-details > summary::-webkit-details-marker { display: none; }
.recovery-details[open] > summary { margin-bottom: var(--space-3); }

/* ===== Phase 5E: forms (spec PHASE-5-MOTION-A11Y.md section 3; K.J. 27 Oct 2026) =====
   The date box's hidden format hint sits inside an upper-case label; a screen reader would read it in
   capitals (Tesstarossa 5E amend). */
.dmy-format { text-transform: none; letter-spacing: normal; }

/* ===== T1: touch sizes on any touch screen (PHONE-TABLET-PLAN.md; K.J. 27 Oct 2026, "T1 touch sizes") =====
   The phone's 44px floor (Shiva M-02 and "Pages: ... 44px controls" in the 743px block) was tied to
   width, so an upright iPad (744 to 1199px, touch) got the mouse sizes: 35px buttons, 21px back links.
   The same floor for a coarse pointer at 744px and up. Sizes only: no display change on buttons (a
   class that hides a button must still win), the rail, cards and tables stay as they are; a mouse
   at any width is unchanged. Phones keep their own block above. */
@media (pointer: coarse) and (min-width: 744px) {
  /* Buttons: the floor, and the label kept in the middle of the taller box (line-height 1.2, 1px border). */
  .btn, button.btn, a.btn, .btn.small {
    min-height: var(--m-tap);
    padding-top: var(--m-btn-pad-y);
    padding-bottom: var(--m-btn-pad-y);
  }
  select, textarea,
  input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]),
  .date-field, .date-field .date-display { min-height: var(--m-tap); }
  .dmy .dmy-pick { min-width: var(--m-tap); min-height: var(--m-tap); }
  /* Small links, back links and folds, as on the phone (Shiva M-02): a bigger hit area, same words. */
  main a:not([class]), .booking-panel a:not([class]),
  main summary, .booking-panel summary,
  label.check, label.radio, .check-label, .radio-label,
  .back-link, a.back, .show-inactive {
    display: inline-flex; align-items: center; min-height: var(--m-tap); min-width: var(--m-tap);
  }
  main p > a:not([class]), main li > a:not([class]) { justify-content: flex-start; }
  main summary, .booking-panel summary { display: flex; }
  /* Rules with a class outrank `main summary` / `main a`: "How This Works" (24px) and the client page's coach link. */
  main .help-inline > summary { min-height: var(--m-tap); }
  .client-meta .meta-link { display: inline-flex; align-items: center; min-height: var(--m-tap); }
  main summary::-webkit-details-marker { display: none; }
  main summary::before, .booking-panel summary::before { content: "\25B8"; margin-right: var(--space-2); }
  main details[open] > summary::before, .booking-panel details[open] > summary::before { transform: rotate(90deg); }
  main summary.btn::before, .booking-panel summary.btn::before { content: none; }
  /* Day · Week · Month (38px for the mouse). Finance tabs are 44px already. */
  main .cal-switch a { min-height: var(--m-tap); }
  /* T1b (K.J. 27 Oct 2026, "Fix now"): the Month view's day numbers (24px for the mouse). */
  .mday-num { min-width: var(--m-tap); min-height: var(--m-tap); }
  /* T1c (K.J. 27 Oct 2026, "Fix now", PR 165): the Month view's session chips and "+N more" (19 to 20px for the
     mouse, 4px apart). The cells grow taller; the chip keeps its look. */
  .booking-chip.mini, .booking-chip.mini.planned { min-height: var(--m-tap); padding-top: var(--m-mini-pad-y); padding-bottom: var(--m-mini-pad-y); }
  .mday-more { display: flex; align-items: center; min-height: var(--m-tap); }
}

/* ===== T3: Month on the phone, a month of dots (PHONE-TABLET-PLAN.md; K.J. 27 Oct 2026) =====
   48px day buttons (Tesstarossa's call: room for the dots under the number). The dots as on the
   phone's week strip: muted = the day has sessions, cream = some are still to mark (needs you). */
@media (max-width: 743px) {
  .m-month { margin-top: var(--space-2); }
  .m-mgrid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--space-hair); text-align: center; }
  .m-mgrid .dow { padding: var(--space-2) 0; font: 600 var(--fs-label)/1 var(--font-body); letter-spacing: 0.08em; color: var(--color-ink-muted); }
  main a.m-mday, main a.m-mday:hover {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-1);
    min-height: 48px; min-width: 0; border: 0; border-radius: var(--radius-sm); color: var(--color-ink); text-decoration: none;
  }
  .m-mday .dn { font: 600 1.05rem/1 var(--font-body); font-variant-numeric: tabular-nums; }
  .m-mday.out .dn { color: var(--color-ink-muted); font-weight: 500; }
  main a.m-mday.today { background: var(--color-olive); }
  .m-mday.today .dn { color: var(--color-paper); }
  .m-mday .dots { display: flex; gap: var(--space-hair); height: 6px; }
  .m-mday .dots b, .m-mlegend b { width: 6px; height: 6px; border-radius: var(--radius-pill); background: var(--color-ink-muted); opacity: 0.55; }
  .m-mday .dots b.c, .m-mlegend b.c { background: var(--color-cream); box-shadow: 0 0 0 1px var(--olive-line); opacity: 1; }
  .m-mday.today .dots b { background: var(--m-paper-80); opacity: 1; }
  .m-mday.today .dots b.c { background: var(--color-cream); box-shadow: none; }
  .m-mlegend { display: flex; flex-wrap: wrap; gap: var(--space-4); margin: var(--space-3) 0 0; font-size: var(--fs-meta); }
  .m-mlegend span { display: inline-flex; align-items: center; gap: var(--space-2); }
  .m-mlegend b { display: inline-block; }
}

/* ===== T5: Bookings below 1024px, day headings and a Filter fold (PHONE-TABLET-PLAN.md; K.J. 27 Oct 2026) =====
   The cards sit under a day heading that stays at the top while its cards scroll (today's in ink, the
   rest muted); newest first as before. The five filters fold behind "Filter · N Set" once the page's
   script has run; without it they stay open. From 1024px the table and the open toolbar are unchanged. */
.filter-fields { display: contents; }
.filter-toggle { display: none; }
@media (max-width: 1023px) {
  /* Tesstarossa amend 1 (27 Oct 2026, as E2): the button and the count line have their own row, open or shut;
     the fields sit under them. */
  .list-toolbar.fold-ready { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; }
  .list-toolbar.fold-ready .filter-toggle { display: inline-block; grid-row: 1; grid-column: 1; }
  .list-toolbar.fold-ready .list-count { grid-row: 1; grid-column: 2; text-align: left; }
  .list-toolbar.fold-ready .filter-fields {
    display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-3) var(--space-4); grid-row: 2; grid-column: 1 / -1;
  }
  .list-toolbar.fold-ready:not(.is-open) .filter-fields { display: none; }
  .booking-days .list-day {
    position: sticky; top: 0; z-index: 2; margin: 0; padding: var(--space-3) var(--m-pad) var(--space-2);
    background: var(--color-paper); border-bottom: 1px solid var(--color-border);
    font: var(--text-label); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--color-ink-muted);
  }
  .booking-days .list-day.is-today { color: var(--color-ink); }
  .booking-days .list-day .visually-hidden { text-transform: none; }  /* A11y audit A9: the words as typed */
  .list-day-cards { margin: 0; padding: 0; list-style: none; }
  .list-day-cards > li + li { border-top: 1px solid var(--color-border); }
}
/* The phone's top bar is sticky too: the day heading stops under it. From and To one per row, so the
   whole DD/MM/YYYY shows (Tesstarossa amend 1: the To box read "DD/MM/YYY" at 375px). */
@media (max-width: 743px) {
  .booking-days .list-day { top: var(--m-topbar); }
  .filter-fields .tool-field:has(.date-field) { flex-basis: 100%; }
}

/* ===== T6: the phone's "to mark" chip says what it counts (PHONE-TABLET-PLAN.md Q2 (a); K.J. 27 Oct 2026) =====
   "4 today · 7 in all"; the chip is a button now (it opens the oldest), with a 44px target around the 26px pill. */
@media (max-width: 743px) {
  .m-mark-chip { display: inline-flex; align-items: center; min-height: var(--m-tap); padding: 0; border: 0; background: none; color: inherit; font: inherit; cursor: pointer; }
}

/* ===== T4: client page below 1200px, empty sections together and Add Package folded (PHONE-TABLET-PLAN.md C1, C2,
   D1; K.J. 27 Oct 2026) =====
   An empty section (client_detail.html marks it .is-empty) is one 56px row: its title, its empty line, its Add button.
   Rows next to each other join into one card under "Also on File"; the page order is kept. Opening the row's Add
   fold, or a refused save's message in it (Shiva Tier D low 2, 27 Oct 2026), shows the whole section in place.
   1200px and up is unchanged. */
.also-head, .t-addpkg-open { display: none; }
.health-card .fold-sub { display: none; }  /* the empty row's "None recorded" (below 1200px only) */
@media (max-width: 1199px) {
  .profile-main > .also-head {
    display: block; margin: 0; padding: var(--space-5) var(--space-5) var(--space-2);
    background: var(--card); border: 1px solid var(--color-border); border-bottom: 0; border-radius: var(--radius) var(--radius) 0 0;
  }
  .profile-main > .section-card.is-empty { padding: var(--space-2) var(--space-5); box-shadow: none; }
  .profile-main > .also-head + .is-empty, .profile-main > .is-empty + .is-empty {
    margin-top: calc(-1 * var(--space-5)); border-top-left-radius: 0; border-top-right-radius: 0;
  }
  .profile-main > .is-empty:has(+ .is-empty) { border-bottom: 0; border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
  .profile-main > .is-empty + .is-empty { border-top-color: var(--color-border); }
  /* The row: title and empty line on the left, the Add button on the right. */
  .profile-main > .is-empty:not(.health-card):not(:has(> .add-fold[open], .inline-error:not([hidden]))) {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; column-gap: var(--space-3); min-height: 56px;
  }
  .is-empty:not(.health-card):not(:has(> .add-fold[open], .inline-error:not([hidden]))) > :not(.card-head):not(.empty-line):not(.add-fold) { display: none; }
  /* Health Notes is already one folded row (its own fold button, PDPA I2); it only joins the card. */
  .is-empty:not(:has(> .add-fold[open], .inline-error:not([hidden]))) > .card-head { grid-column: 1; margin: 0; }
  .is-empty:not(:has(> .add-fold[open], .inline-error:not([hidden]))) > .empty-line { grid-column: 1; padding: 0; font: var(--text-meta); }
  .is-empty:not(:has(> .add-fold[open], .inline-error:not([hidden]))) > .add-fold { grid-column: 2; grid-row: 1 / span 2; margin: 0; }
  .is-empty > .card-head h2 { font: 600 var(--fs-body)/1.25 var(--font-body); letter-spacing: 0; }
  .is-empty .empty-act { display: none; }  /* C2: the action is said once, by the row's button */
  .health-card.is-empty .fold-head { margin: 0; }
  .health-card.is-empty .fold-head, .health-card.is-empty .fold-toggle { font: 600 var(--fs-body)/1.25 var(--font-body); letter-spacing: 0; }
  /* Tesstarossa amend 2 (27 Oct 2026, as C1): title over its muted "None recorded", the chevron on the right,
     the same height as the other rows. */
  .health-card.is-empty .fold-toggle { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0 var(--space-3); align-content: center; min-height: var(--m-tap); }
  .health-card.is-empty .fold-sub { display: block; grid-column: 1; grid-row: 2; font: var(--text-meta); color: var(--color-ink-muted); }
  .health-card.is-empty .fold-toggle .chev { grid-column: 2; grid-row: 1 / span 2; }
}
/* D1: from 744 to 1199px (the phone has its sheet), once client-page.js has run. */
@media (min-width: 744px) and (max-width: 1199px) {
  .t-fold-ready .t-addpkg-open:not([hidden]) {
    display: flex; align-items: center; justify-content: space-between; width: 100%; min-height: var(--m-tap);
    margin-top: var(--space-3); padding: 0; border: 0; border-top: 1px solid var(--color-border); background: none;
    color: var(--color-olive); font: var(--text-ui); font-weight: 600; cursor: pointer;
  }
  .t-addpkg-open[aria-expanded="true"] .chev { transform: rotate(180deg); }
  .t-fold-ready .addpkg-sheet:not(.open) { display: none; }
  .t-fold-ready .addpkg-sheet.open { display: block; }
}

/* Surname capitals (K.J. 3 Nov 2026, option A on the surname-capitals mockup; app/names.py marked_name): the Last
   name in bold capitals wherever a full client name shows; bin / binti / a/l / a/p stay lower-case
   and regular. Display only: the capitals are drawn from data-shown with empty alternative text, and the
   typed words inside are at font-size 0 (a visually hidden span lost the space after the name in
   Chrome's accessible name), so a screen reader and a copy get the name as typed (K.J.
   3 Nov 2026, "Read as typed"; a browser without the alt-text syntax keeps the first content line and
   still shows the name). In a list the
   whole name was 600, so the First name drops to 500 and the row gets no heavier; a chip is bold
   already, so there the capitals add no weight. */
.nm-last { font-weight: 700; letter-spacing: 0.03em; }
.nm-last::before { content: attr(data-shown); content: attr(data-shown) / ""; text-transform: uppercase; }
/* Tesstarossa's re-check on PR 271 (3 Nov 2026): letter-spacing comes down as an absolute length, so the
   hidden letters still took width (a double space after the capitals); 0 here makes them take none. */
.nm-typed { font-size: 0; letter-spacing: 0; }
.nm-join { font-weight: 400; }
.client-name .nm-given, .client-card-name .nm-given, .list-name .nm-given, .list-card-name .nm-given,
.m-who .n .nm-given { font-weight: 500; }
.booking-chip .nm-last, .booking-chip .nm-given, .booking-chip .nm-join { font-weight: inherit; }
/* Tesstarossa's look pass on PR 271 (3 Nov 2026): no letter-spacing on a chip, so a capital name is cut no
   more often than today (21 week chips cut at 1440: 3 today, 5 with the spacing, 3 without). */
.booking-chip .nm-last { letter-spacing: 0; }
