:root {
  --brand: #1b2a41;
  --brand-2: #0f4c81;
  --brand-soft: #e8edf4;
  --series: #2f6fed;
  --grid: #e6e8eb;
  --ink-2: #6c757d;
  --tabbar-h: 60px;
  --circuit: #7c4dff;
  --circuit-soft: #f3efff;
  --swipe-w: 80px;      /* how far a swiped line slides; app.js reads this for the gesture */
  /* One width per column of the sets × reps rows, shared by the header labels and the inputs below them. */
  --sr-w-chk: 1.5rem; --sr-w-sr: 11rem; --sr-w-weight: 7.5rem; --sr-w-btn: 3.4rem;
}
.bg-brand { background: var(--brand) !important; }
/* Standalone (home-screen) mode on iOS: keep the app bar clear of the status bar / notch. */
.navbar.bg-brand { padding-top: calc(.5rem + env(safe-area-inset-top)); }
.bg-brand-gradient { background: linear-gradient(160deg, var(--brand) 0%, var(--brand-2) 100%); }
.min-w-0 { min-width: 0; }
/* App shell: the window itself never scrolls — the .page-scroll pane does. iOS Safari's collapsing
   toolbar therefore has no root scroll to react to, and the tab bar, a flex row, physically cannot move. */
html { height: 100%; }
body.has-tabbar, body.has-bottombar { height: 100%; height: 100dvh; overflow: hidden; display: flex; flex-direction: column; }
.page-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; scroll-behavior: smooth; }
#saved-workouts { scroll-margin-top: .75rem; }
/* The appointment the trainer tapped on the schedule, lit up on the client page. */
.list-group-item.appt-hl { box-shadow: inset 3px 0 0 var(--brand-2); background: var(--brand-soft); scroll-margin-top: .75rem; }
body.has-bottombar .page-scroll { padding-bottom: calc(5.5rem + env(safe-area-inset-bottom)); }   /* keep >= .bottom-bar's rendered height */
.mw-420 { max-width: 420px; }
.mw-480 { max-width: 480px; }
.mw-640 { max-width: 640px; margin-left: auto; margin-right: auto; }
.mw-1100 { max-width: 1100px; margin-left: auto; margin-right: auto; }

/* App-bar brand: logo + company + location */
.brand-logo { width: 34px; height: 34px; border-radius: .5rem; object-fit: contain; background: #fff; flex-shrink: 0; margin-right: .6rem; }
.brand-logo-empty { display: grid; place-items: center; background: rgba(255,255,255,.15); color: #fff; font-size: 1.1rem; }
.logo-preview { width: 64px; height: 64px; border-radius: .6rem; object-fit: contain; background: #fff; border: 1px solid var(--bs-border-color); }

.loc-switch { font-size: inherit; line-height: inherit; max-width: 14rem; vertical-align: baseline; text-decoration: none; }
.loc-switch:hover, .loc-switch:focus { color: #fff !important; }
.brand .dropdown-menu { font-size: .9rem; }

/* Non-production banner (APP_ENV) */
.env-banner { background: #ffc107; color: #000; font-size: .7rem; font-weight: 700; letter-spacing: .05em; text-align: center; padding: .15rem .5rem; }

/* Mobile bottom tab bar: a normal flex row at the foot of the app shell, not position: fixed. */
.tabbar {
  flex-shrink: 0;
  display: flex; justify-content: space-around;
  height: calc(var(--tabbar-h) + env(safe-area-inset-bottom));
  padding-bottom: env(safe-area-inset-bottom);
  background: var(--bs-body-bg); border-top: 1px solid var(--bs-border-color);
}
.tabbar-item { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-decoration: none; color: var(--bs-secondary-color); font-size: .7rem; gap: 2px; }
.tabbar-item i { font-size: 1.35rem; line-height: 1; }
.tabbar-item.active { color: var(--brand-2); font-weight: 600; }

/* Fixed action bar (Finish session) */
.bottom-bar { position: fixed; left: 0; right: 0; bottom: 0; background: var(--bs-body-bg); border-top: 1px solid var(--bs-border-color); padding: .6rem 1rem calc(.6rem + env(safe-area-inset-bottom)); z-index: 1020; transform: translateZ(0); -webkit-transform: translateZ(0); }

/* Big, thumb-friendly targets */
.btn, .form-control, .form-select { min-height: 44px; }
.btn-sm, .form-select-sm, .form-control-sm, .input-group-sm .btn, .input-group-sm .form-control { min-height: 36px; }
.btn-link.btn-sm, .btn-link.p-0 { min-height: 0; }

/* Schedule */
.day-strip { display: flex; gap: .4rem; overflow-x: auto; scrollbar-width: none; padding: .5rem 0 .75rem; }
.day-strip::-webkit-scrollbar { display: none; }
.day-chip { flex: 0 0 auto; width: 3.1rem; text-align: center; border-radius: .9rem; padding: .35rem 0; background: rgba(255,255,255,.12); line-height: 1.15; color: #fff; text-decoration: none; }
.day-chip small { display: block; font-size: .65rem; opacity: .75; text-transform: uppercase; }
.day-chip strong { font-size: 1.05rem; }
.day-chip.active { background: #fff; color: var(--brand); }
.avatar { width: 2.6rem; height: 2.6rem; border-radius: 50%; background: var(--brand-soft); color: var(--brand); font-weight: 600; display: grid; place-items: center; flex-shrink: 0; }
.avatar.sm { width: 1.9rem; height: 1.9rem; font-size: .7rem; }
.session { display: flex; gap: .85rem; align-items: center; text-decoration: none; color: inherit; }
.session .time { width: 4.2rem; flex-shrink: 0; font-variant-numeric: tabular-nums; line-height: 1.2; }
.session .time small { display: block; color: var(--ink-2); }
.session .time .ap { font-size: .7rem; font-weight: 400; margin-left: .1rem; }
.session > i { flex-shrink: 0; }
.session.done { opacity: .55; }
.gap-slot { border: 1px dashed #cfd4da; color: #8a929a; text-align: center; font-size: .85rem; padding: .5rem; border-radius: .5rem; }
.chip-row { display: flex; gap: .4rem; overflow-x: auto; scrollbar-width: none; padding-bottom: .25rem; }
/* The exercise page's jump bar (All exercises · in-progress chips · Next) stays pinned at the top of the
   pane while the card scrolls, so the trainer can always hop between exercises. Bleeds over main's padding. */
#in-progress { position: sticky; top: 0; z-index: 100; background: var(--bs-tertiary-bg); margin: -1rem -1rem .5rem; padding: .75rem 1rem .5rem; border-bottom: 1px solid var(--bs-border-color); }
.chip-row::-webkit-scrollbar { display: none; }
.chip-row .badge { flex: 0 0 auto; font-weight: 500; padding: .45rem .7rem; }
/* History: client search with suggestions dropping below the box */
.history-search { position: relative; }
.history-suggest { position: absolute; left: 0; right: 0; top: 100%; z-index: 1050; max-height: 60vh; overflow-y: auto; margin-top: .25rem; }

/* Schedule: gym chips and the trainer dropdown share one line; the chips scroll, the dropdown keeps a usable width. */
.schedule-filter { display: flex; align-items: center; gap: .5rem; }
.schedule-filter .chip-row { flex: 0 1 auto; min-width: 0; padding-bottom: 0; }
.schedule-filter .dropdown { flex: 1 0 9rem; min-width: 9rem; }

/* Session start picker */
.pick { cursor: pointer; }
.pick.planned { border-left: 4px solid var(--series); }
.mb-badge { font-size: .65rem; background: #fff3cd; color: #664d03; border: 1px solid #ffe69c; }

/* Logging screen */
.exercise .form-control { text-align: center; font-variant-numeric: tabular-nums; font-size: 1.1rem; }
.exercise.done { background: #f2fbf4; }
.exercise.done .name { text-decoration: line-through; color: var(--ink-2); }
.sr-group { width: 8.4rem; flex-shrink: 0; }
.sr-group .form-control { padding-left: .2rem; padding-right: .2rem; }
.field-labels { display: flex; font-size: .65rem; color: var(--ink-2); text-transform: uppercase; letter-spacing: .03em; margin-bottom: .15rem; }
.field-labels span:first-child { width: 8.4rem; flex-shrink: 0; margin-right: .5rem; }
.inc-row .btn { padding: .3rem 0; font-size: .85rem; font-variant-numeric: tabular-nums; min-height: 38px; }
.inc-row .btn.minus { color: #b02a37; }
.exercise.is-saving { opacity: .7; }
.exercise.focus .form-control { font-size: 1.35rem; }
.exercise.focus .weight-big { font-size: 1.35rem; font-weight: 600; }
.exercise.focus .card-header { background: #fff; }
.sr-lg { width: var(--sr-w-sr); }
.exercise.focus .field-labels span.w-auto { width: auto; }
.exercise.focus.done { background: #f2fbf4; }
.exercise-row.done .name { text-decoration: line-through; color: var(--ink-2); }
.exercise-row.started { border-left: 3px solid #ffc107; }
.tabular { font-variant-numeric: tabular-nums; }
.kb-bell { border: 2px solid rgba(0,0,0,.15); border-radius: .5rem; padding: .3rem 0; min-width: 0; display: flex; flex-direction: column; align-items: center; line-height: 1.1; font-variant-numeric: tabular-nums; }
.kb-bell .kg { font-weight: 700; font-size: .95rem; }
.kb-bell .kg::after { content: 'kg'; font-size: .6rem; font-weight: 400; margin-left: 1px; }
.kb-bell .lb { font-size: .65rem; opacity: .85; }
.kb-bell.current { outline: 3px solid var(--bs-primary); outline-offset: 1px; }
.kb-pink { background: #f48fb1; color: #222; }
.kb-blue { background: #1e88e5; color: #fff; }
.kb-yellow { background: #fdd835; color: #222; }
.kb-purple { background: #8e24aa; color: #fff; }
.kb-green { background: #43a047; color: #fff; }
.kb-orange { background: #fb8c00; color: #fff; }
.kb-red { background: #e53935; color: #fff; }
.kb-grey { background: #9e9e9e; color: #fff; }
.kb-white { background: #fff; color: #222; }
/* A weight box that holds one of the bells' weights wears the bell's colour: a ring round the box and the "lb" tab
   filled in. Classes, not inline colours, for the same CSP reason as the bands below. */
.block-weight.kb-ring { border-radius: var(--bs-border-radius-lg); box-shadow: 0 0 0 3px var(--kb); }
.block-weight.kb-ring .input-group-text { background: var(--kb); color: var(--kb-ink); border-color: var(--kb); font-weight: 600; }
.kb-c-pink   { --kb: #f48fb1; --kb-ink: #222; }
.kb-c-blue   { --kb: #1e88e5; --kb-ink: #fff; }
.kb-c-yellow { --kb: #fdd835; --kb-ink: #222; }
.kb-c-purple { --kb: #8e24aa; --kb-ink: #fff; }
.kb-c-green  { --kb: #43a047; --kb-ink: #fff; }
.kb-c-orange { --kb: #fb8c00; --kb-ink: #fff; }
.kb-c-red    { --kb: #e53935; --kb-ink: #fff; }
.kb-c-grey   { --kb: #9e9e9e; --kb-ink: #fff; }
.kb-c-white  { --kb: #fff; --kb-ink: #222; }
.block-weight.kb-ring.kb-c-white { box-shadow: 0 0 0 3px #fff, 0 0 0 4px #adb5bd; }
.block-weight.kb-ring.kb-c-white .input-group-text { border-color: #adb5bd; }
/* The tempo panel slides in from the side. Bootstrap's own .offcanvas-end is 400px, which is wider
   than the phones this is used on, so it gets a width that always leaves the page showing behind it. */
.tempo-panel.offcanvas-end { width: 88vw; max-width: 360px; }
.tempo-panel .offcanvas-body { display: flex; flex-direction: column; }
.tempo-panel .offcanvas-body > p { flex: 1 1 auto; }

/* Tempo: a quiet stopwatch until one is set, then the same pill as tempo_badge() — stopwatch + tempo. */
.tempo-badge { background: #6f42c1; color: #fff; font-weight: 600; font-variant-numeric: tabular-nums; }
.tempo-btn { padding: 0 .35rem; color: var(--bs-secondary-color); border: 1px solid transparent; line-height: 1.4; }
.tempo-btn.is-set { background: #6f42c1; color: #fff; border-color: #6f42c1; border-radius: 50rem; padding: .1rem .6rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.tempo-btn.is-set:hover, .tempo-btn.is-set:focus-visible { background: #59359a; border-color: #59359a; color: #fff; }

/* Resistance bands: the band-work counterpart to the bells, and coloured the same way — a class per band, because
   the page's CSP has no 'unsafe-inline' for styles, so an inline background would simply be dropped. A band has no
   weight, so tapping one notes it in the detail line instead of touching the weight box. */
.band-chip { border: 2px solid rgba(0,0,0,.15); border-radius: .5rem; padding: .3rem .15rem; min-width: 0; display: flex; flex-direction: column; align-items: center; line-height: 1.1; text-align: center; overflow: hidden; }
.band-chip .nm { font-weight: 700; font-size: .78rem; }
.band-chip .lvl { font-size: .58rem; opacity: .85; white-space: nowrap; }
.band-chip.current { outline: 3px solid var(--bs-primary); outline-offset: 1px; }
.band-tan    { background: #d2b48c; color: #222; }
.band-yellow { background: #fdd835; color: #222; }
.band-red    { background: #e53935; color: #fff; }
.band-green  { background: #43a047; color: #fff; }
.band-blue   { background: #1e88e5; color: #fff; }
.band-black  { background: #212121; color: #fff; }
.band-silver { background: #c0c0c0; color: #222; }
.band-gold   { background: #d4af37; color: #222; }
/* The mini bands go by strength, not colour: same shape, shaded light to dark so the ladder still reads. */
.band-mini-light  { background: #e9ecef; color: #222; }
.band-mini-medium { background: #adb5bd; color: #222; }
.band-mini-heavy  { background: #495057; color: #fff; }
.kb-preview .band-chip, .kb-preview .kb-bell { flex: 0 0 auto; min-width: 3.4rem; }
/* Fill the width on a phone, but stop growing and sit centred once there is room to spare. */
.kb-row .kb-bell, .band-row .band-chip { flex: 1 1 0; max-width: 4.5rem; }
.band-row .band-chip.band-mini-light, .band-row .band-chip.band-mini-medium, .band-row .band-chip.band-mini-heavy { max-width: 5.5rem; }

/* Org -> Exercises: the kettlebell / band flags as tappable pills that save themselves. */
.ex-flag { display: inline-flex; align-items: center; gap: .25rem; border: 1px solid var(--bs-border-color); border-radius: 999px; padding: .1rem .5rem; font-size: .75rem; cursor: pointer; white-space: nowrap; color: var(--bs-secondary-color); }
.ex-flag input { position: absolute; opacity: 0; pointer-events: none; }
.ex-flag.on { background: #fff3cd; border-color: #ffc107; color: #664d03; }
.ex-flag.band.on { background: #cff4fc; border-color: #0dcaf0; color: #055160; }
.ex-flag i { font-size: .7rem; }
/* One row per sets x reps block, each with its own weight: [ sets x reps ] [ weight ] [ split ].
   Swipe a line left (iOS style) to uncover the Delete tucked behind it. */
.sr-blocks [data-block] + [data-block] { margin-top: .5rem; }
.sr-line { position: relative; touch-action: pan-y; }
.icon-inline { width: 1em; height: 1em; vertical-align: -.125em; }   /* hand-drawn kettlebell / band, sized like a bi- icon */
/* The sets / reps / weight boxes lose the browser's spinner arrows — they're typed or set by the bells. */
.sr-group .form-control, .block-weight .form-control { -moz-appearance: textfield; appearance: textfield; }
.sr-group .form-control::-webkit-outer-spin-button, .sr-group .form-control::-webkit-inner-spin-button,
.block-weight .form-control::-webkit-outer-spin-button, .block-weight .form-control::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.sr-swipe { position: relative; z-index: 1; background: var(--bs-card-bg, var(--bs-body-bg)); transition: transform .18s ease-out; }
.sr-line.swiping .sr-swipe { transition: none; }
.sr-line.swipe-open .sr-swipe { transform: translateX(calc(-1 * var(--swipe-w))); }
.sr-del { position: absolute; top: 0; right: 0; bottom: 0; width: calc(var(--swipe-w) - 6px); border: 0; border-radius: var(--bs-border-radius-lg);
  background: var(--bs-danger); color: #fff; font-weight: 600; font-size: .85rem;
  opacity: 0; pointer-events: none; transition: opacity .15s; }
.sr-line.swiping .sr-del, .sr-line.swipe-open .sr-del { opacity: 1; }
.sr-line.swipe-open .sr-del { pointer-events: auto; }
.sr-blocks .sr-line:only-child .sr-del { display: none; }   /* the only line has nowhere to go */
/* A list row can be an .sr-line too (saved workouts): clip the slide and square the Delete off. */
.list-group-item.sr-line { overflow: hidden; }
.list-group-item.sr-line .sr-del { border-radius: 0; }
.list-group-item.sr-line .sr-swipe { background: var(--bs-list-group-bg, #fff); }
/* Hold the "lb" tab and a plate popup lands above it: +5 +10 +25 +45 onto that line. */
.block-weight .input-group-text { user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
.weight-pop { position: fixed; z-index: 1080; display: flex; gap: .35rem; padding: .35rem; border-radius: .75rem;
  background: var(--bs-body-bg); border: 1px solid var(--bs-border-color); }
.weight-pop .btn { min-width: 3.1rem; font-weight: 600; font-variant-numeric: tabular-nums; }
/* The Kettlebell Colors / Resistance Bands links fold their pickers out and back in. */
[data-kb-show] .chev, [data-band-show] .chev { display: inline-block; font-size: .7em; transition: transform .15s; }
[data-kb-show][aria-expanded="true"] .chev, [data-band-show][aria-expanded="true"] .chev { transform: rotate(180deg); }
.block-weight { width: var(--sr-w-weight); flex-shrink: 0; }
.block-weight .input-group-text { padding-left: .4rem; padding-right: .4rem; }
.sr-head { margin-bottom: .15rem; text-transform: uppercase; letter-spacing: .03em; font-size: .65rem; }
.sr-head-chk { width: var(--sr-w-chk); flex-shrink: 0; }
.sr-head-sr { width: var(--sr-w-sr); flex-shrink: 0; }
.line-check { flex-shrink: 0; width: var(--sr-w-chk); height: var(--sr-w-chk); margin: 0; }
.sr-blocks [data-block].line-done .sr-group, .sr-blocks [data-block].line-done .block-weight { opacity: .55; }
.sr-head-w { width: var(--sr-w-weight); flex-shrink: 0; }
.sr-head-btn { width: var(--sr-w-btn); flex-shrink: 0; }
.cell-sr .mixed { cursor: help; font-weight: 700; }
.exercise.focus #ex-detail { font-size: 1rem; }
.import-grid td.src, .import-grid th.src { background: #fff8e6; }
.import-grid td.src { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .8rem; white-space: nowrap; }
.import-session > summary { cursor: pointer; }
.import-list td { vertical-align: middle; }

/* Stats */
/* Dashboard KPI tiles: a hero revenue card and a 2-up (3-up on wide) grid of stats. */
.kpi-hero .label, .kpi-card .label { font-size: .68rem; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kpi-hero .label { color: rgba(255,255,255,.75); }
.kpi-hero .value { font-size: 2rem; font-weight: 700; line-height: 1.15; }
.kpi-hero .sub { font-size: .8rem; color: rgba(255,255,255,.75); }
.kpi-card .value { font-size: 1.45rem; font-weight: 700; line-height: 1.2; }
.kpi-card .sub { font-size: .72rem; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kpi-card .label i { font-size: .85rem; }

/* The dashboard's gyms × periods grid. Deliberately not a Bootstrap .table: its cells paint their
   background with an inset box-shadow, which fights the selected row / column highlight. Every cell
   holds a full-size link so the whole box is the tap target. */
.gym-grid { width: 100%; border-collapse: collapse; font-size: .9rem; }
.gym-grid th, .gym-grid td { padding: 0; border-bottom: 1px solid var(--bs-border-color); }
.gym-grid tbody tr:last-child th, .gym-grid tbody tr:last-child td { border-bottom: 0; }
.gym-grid a, .gym-grid .pad { display: block; padding: .45rem .45rem; text-decoration: none; color: inherit; }
.gym-grid a:hover, .gym-grid a:focus-visible { background: var(--brand-soft); }
.gym-grid thead th { font-size: .72rem; font-weight: 600; text-transform: uppercase; letter-spacing: .03em; color: var(--ink-2); }
.gym-grid .gym { text-align: left; font-weight: 500; max-width: 8rem; }
.gym-grid .gym a, .gym-grid .gym .pad { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gym-grid .num { text-align: right; font-variant-numeric: tabular-nums; width: 5.2rem; }
.gym-grid .num a, .gym-grid .num .pad { text-align: right; }
.gym-grid .total th, .gym-grid .total td { font-weight: 700; border-bottom: 2px solid var(--brand-soft); }
.gym-grid .loose { color: var(--ink-2); font-size: .82rem; }
/* The selection: a tinted column and row, and the one cell where they meet filled dark blue with
   white figures. The intersection rules carry the row's specificity (.sel-row td) plus a class, or
   the lighter row tint would paint over them. */
.gym-grid .sel-col { background: var(--brand-soft); }
.gym-grid .sel-row th, .gym-grid .sel-row td { background: var(--brand-soft); font-weight: 700; }
.gym-grid td.sel-cell, .gym-grid .sel-row td.sel-cell { background: var(--brand); }
.gym-grid td.sel-cell a, .gym-grid .sel-row td.sel-cell a { color: #fff; font-weight: 700; }
.gym-grid td.sel-cell a:hover, .gym-grid td.sel-cell a:focus-visible { background: var(--brand-2); color: #fff; }

/* ?debug=1 record counts: plain dense tables, numbers right-aligned and tabular. */
.diag-grid { width: 100%; border-collapse: collapse; font-size: .78rem; }
.diag-grid th, .diag-grid td { padding: .2rem .4rem; border-bottom: 1px solid var(--bs-border-color); text-align: left; white-space: nowrap; }
.diag-grid thead th { font-weight: 600; color: var(--ink-2); text-transform: uppercase; font-size: .7rem; letter-spacing: .02em; }
.diag-grid .num { text-align: right; font-variant-numeric: tabular-nums; }
.diag-grid code, .diag-grid + .small code { white-space: nowrap; }

.stat { text-align: center; border-radius: .75rem; padding: .5rem .25rem; }
.stat .value { font-size: 1.4rem; font-weight: 600; line-height: 1.1; }
.stat .label { font-size: .7rem; color: var(--ink-2); text-transform: uppercase; letter-spacing: .03em; }

/* Workout builder */
.ex-row .form-control { font-size: .95rem; }
.ex-row input[type=number] { padding-left: .25rem; padding-right: .25rem; }
.w-sets { width: 3.4rem; flex: 0 0 3.4rem; }
.w-weight { width: 4.5rem; flex: 0 0 4.5rem; }
.w-x { width: 2rem; flex: 0 0 2rem; }
/* Circuits in the builder: a link button between every two rows; linked rows share a tinted bracket. */
/* The button is the full gap between rows (easy to hit); the pill in the middle is what shows. */
.ex-join { display: flex; justify-content: center; align-items: center; width: 100%; height: 1.9rem; padding: 0; border: 0; background: none; }
.ex-join span { display: inline-flex; align-items: center; gap: .2rem; font-size: .75rem; font-weight: 600; line-height: 1; padding: .2rem .6rem; border-radius: 999px; border: 1px dashed var(--circuit); color: var(--circuit); background: var(--bs-body-bg); }
.ex-join span .bi { font-size: .95rem; }
.ex-join:hover span, .ex-join:focus-visible span { background: var(--circuit-soft); }
.ex-join.linked { background: var(--circuit-soft); border-left: 3px solid var(--circuit); }
.ex-join.linked span { border-style: solid; background: var(--circuit); color: #fff; }
.ex-row.in-circuit { background: var(--circuit-soft); border-left: 3px solid var(--circuit); padding: .25rem .25rem .25rem .35rem; }
.ex-row.c-first { border-top-right-radius: .5rem; }
.ex-row.c-last { border-bottom-right-radius: .5rem; }
.circuit-label { font-size: .75rem; font-weight: 600; color: var(--circuit); text-transform: uppercase; letter-spacing: .03em; padding: .1rem 0 .15rem .1rem; }
/* Circuits in the session list and on the exercise page */
.circuit-head { background: var(--circuit-soft); color: var(--circuit); font-size: .75rem; font-weight: 600; text-transform: uppercase; letter-spacing: .03em; border-left: 3px solid var(--circuit); }
.exercise-row.in-circuit { border-left: 3px solid var(--circuit); }
.exercise-row.in-circuit.started { border-left-color: #ffc107; }
.circuit-tag { color: var(--circuit); font-weight: 600; }
.log-join { border-top: 0; border-bottom: 0; }
.log-join.linked { border-left: 3px solid var(--circuit); }
.log-join .ex-join.linked { border-left: 0; }
.badge.text-bg-circuit { background: var(--circuit-soft); color: var(--circuit); }
.w-when { width: 6.2rem; }
.w-email { width: 9rem; max-width: 100%; }
/* A staff row is avatar + name + counts + (for an inactive trainer) an email box and an activate button. On a phone
   that is wider than the screen, so the row wraps and the name keeps a floor — without one, min-width:0 let it
   collapse to nothing and the name rendered one letter per line. */
.staff-row .staff-name { flex: 1 1 8rem; min-width: 8rem; }
.w-date { width: 4.4rem; }
.w-when-long { width: 8.6rem; }
.import-session > summary > * { min-width: 0; }
.summary-plain { list-style: none; cursor: pointer; }
.summary-plain::-webkit-details-marker { display: none; }

/* Org tree */
.org-loc { margin-left: 1.25rem; position: relative; }
.org-loc::before { content: ''; position: absolute; left: -.85rem; top: -.5rem; bottom: 50%; width: .85rem; border-left: 2px solid #cfd4da; border-bottom: 2px solid #cfd4da; border-bottom-left-radius: .5rem; }

/* Charts */
.chart { position: relative; }
.chart svg { display: block; width: 100%; height: auto; touch-action: pan-y; }
.chart .grid line { stroke: var(--grid); stroke-width: 1; }
.chart .axis text { fill: var(--ink-2); font-size: 10px; }
.chart .series { fill: none; stroke: var(--series); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart .area { fill: var(--series); opacity: .1; }
.chart .dot { fill: var(--series); stroke: #fff; stroke-width: 2; }
.chart .bar { fill: var(--series); }
.chart .end-label { fill: #212529; font-size: 11px; font-weight: 600; }
.chart .crosshair { stroke: #adb5bd; stroke-width: 1; pointer-events: none; }
.chart .hot { fill: var(--series); stroke: #fff; stroke-width: 2; pointer-events: none; }
.chart .tip { position: absolute; top: 0; transform: translate(-50%, 0); background: #212529; color: #fff; font-size: .75rem; padding: .25rem .5rem; border-radius: .35rem; white-space: nowrap; pointer-events: none; }
.chart .tip strong { font-size: .9rem; }
.chart .tip .key { display: inline-block; width: 10px; height: 2px; background: var(--series); vertical-align: middle; margin-right: .3rem; }
.chart .hidden { display: none; }
.delta-up { color: #198754; } .delta-flat { color: var(--ink-2); }

/* Client page: progress grid */
.progress-grid .table { table-layout: auto; }
.progress-grid th, .progress-grid td { vertical-align: middle; padding: .3rem .4rem; }
.progress-grid .sticky-col { position: sticky; left: 0; background: #fff; z-index: 1; max-width: 9.5rem; min-width: 7.5rem; box-shadow: 2px 0 0 rgba(0,0,0,.05); }
.progress-grid thead .sticky-col { background: var(--bs-table-bg, #f8f9fa); }
.progress-grid .spark { display: block; color: var(--bs-primary); opacity: .8; }
.progress-grid .cell-w { font-weight: 600; font-variant-numeric: tabular-nums; line-height: 1.1; }
.progress-grid .cell-w sup { font-size: .6em; color: var(--bs-primary); }
.progress-grid .cell-sr { font-size: .65rem; color: var(--ink-2); line-height: 1.1; }
.progress-grid .cell-up { background: #e6f6ea; }
.progress-grid .cell-down { background: #fde8e8; }
.progress-grid .cell-same { background: #f4f5f7; }
.progress-grid .cell-first { background: #eef4fb; }
.progress-grid .cell-empty { opacity: .4; }

/* Widths that used to ride on inline style attributes; the CSP has no 'unsafe-inline' for styles, so they never
   applied. Same look, from a class. */
.cell-workout { max-width: 12rem; }
.col-fileas { min-width: 22rem; }
.w-name-in { min-width: 12rem; max-width: 16rem; }
.w-16 { max-width: 16rem; }
.w-14 { max-width: 14rem; }
.w-10 { max-width: 10rem; }
.tiny { font-size: .65rem; }

/* History: a set ladder as step boxes — sets × reps over the weight, an arrow to the next — wrapping on a phone. */
.steps { display: flex; flex-wrap: wrap; align-items: center; gap: .25rem .2rem; }
.step { display: inline-flex; flex-direction: column; align-items: center; min-width: 2.6rem; padding: .1rem .35rem; border: 1px solid var(--bs-border-color); border-radius: .4rem; background: var(--bs-body-bg); line-height: 1.15; font-variant-numeric: tabular-nums; }
.step-sr { font-size: .72rem; color: var(--bs-secondary-color); white-space: nowrap; }
.step-w { font-weight: 600; white-space: nowrap; }
.step-arrow { font-size: .7rem; color: var(--bs-secondary-color); }
.step-unit { font-size: .72rem; color: var(--bs-secondary-color); margin-left: .1rem; }
.w-steps { width: 60%; }
/* Exercise card header: help (and the done tick) on the left, "2 of 5" on the right; the name keeps clear of both. */
.exercise-title .title-pad-wide { padding-left: 4.25rem; padding-right: 4.25rem; }

/* ---------------------------------------------------------------------------
   The monthly financial update (/org/report): a dark report sheet inside the
   normal light app. Everything is scoped to .report so it cannot leak out.
   --------------------------------------------------------------------------- */
.report { background: #111316; color: #e9e7e4; border-radius: .75rem; padding: 1rem; margin: -.25rem 0 1rem; }
.report .rpt-head { border-bottom: 1px solid #2b2f34; }
.report .rpt-title { font-size: 1.35rem; font-weight: 500; letter-spacing: .01em; }
.report .rpt-sub { font-size: .7rem; text-transform: uppercase; letter-spacing: .12em; color: #8b8f96; margin-top: .15rem; }
.report .rpt-btn { color: #c9cdd3; border: 1px solid #2b2f34; background: #16181c; }
.report .rpt-btn:hover { color: #fff; border-color: #3b4047; }
.report .rpt-note { font-size: .72rem; color: #7f848b; }
.report .rpt-foot { border-top: 1px solid #2b2f34; font-size: .68rem; text-transform: uppercase; letter-spacing: .08em; color: #6f747b; }

.report .tile { background: #16181c; border-top: 2px solid #5fd39a; border-radius: .35rem; padding: .7rem .8rem; }
.report .tile-label { font-size: .64rem; text-transform: uppercase; letter-spacing: .1em; color: #8b8f96; }
.report .tile-value { font-size: 1.7rem; font-weight: 300; line-height: 1.25; font-variant-numeric: tabular-nums; }
.report .tile-sub { font-size: .7rem; color: #9aa0a7; font-variant-numeric: tabular-nums; }
.report .tile-sub.up { color: #5fd39a; }
.report .tile-sub.down { color: #e8806f; }

.report .panel { background: #16181c; border-radius: .35rem; padding: .85rem; }
.report .panel-title { font-size: .66rem; text-transform: uppercase; letter-spacing: .12em; color: #c3a46b; margin-bottom: .5rem; }

/* Chart: bars this year in brass, last year in grey behind them. */
.report .rpt-chart { width: 100%; height: auto; }
.report .rpt-chart .axis { stroke: #2b2f34; stroke-width: 1; }
.report .rpt-chart .bar-now { fill: #d8b878; }
.report .rpt-chart .bar-now.sel { fill: #f0d7a0; }
.report .rpt-chart .bar-prev { fill: #3a3f46; }
.report .rpt-chart .lbl { font-size: 11px; text-anchor: middle; fill: #8b8f96; font-family: inherit; }
.report .rpt-chart .lbl.month { font-size: 10px; letter-spacing: .14em; }
.report .rpt-chart .lbl.val { font-size: 10px; fill: #b9bec5; }
.report .rpt-chart .lbl.val.prev { fill: #6f747b; }
.report .rpt-chart .lbl.sel { fill: #f0d7a0; font-weight: 600; }
.report .rpt-chart .lbl.legend { text-anchor: start; font-size: 10px; }

.report .rpt-grid { width: 100%; border-collapse: collapse; font-size: .8rem; }
.report .rpt-grid th, .report .rpt-grid td { padding: .3rem .35rem; border-bottom: 1px solid #22262b; text-align: left; white-space: nowrap; }
.report .rpt-grid thead th { font-size: .62rem; text-transform: uppercase; letter-spacing: .08em; color: #7f848b; font-weight: 500; }
.report .rpt-grid tbody th { font-size: .7rem; text-transform: uppercase; letter-spacing: .05em; color: #a7acb3; font-weight: 500; }
.report .rpt-grid .num { text-align: right; font-variant-numeric: tabular-nums; }
.report .rpt-grid .strong { color: #fff; font-weight: 600; }
.report .rpt-grid .dim { color: #80858c; }
.report .rpt-grid .up { color: #5fd39a; }
.report .rpt-grid .down { color: #e8806f; }
.report .rpt-grid .total th, .report .rpt-grid .total td { border-top: 1px solid #3a3f46; border-bottom: 0; color: #fff; font-weight: 600; }

.report .hl { margin-bottom: .55rem; }
.report .hl-label { font-size: .74rem; color: #a7acb3; }
.report .hl-note { font-size: .74rem; font-weight: 600; text-align: right; }
.report .hl-note.good { color: #5fd39a; }
.report .hl-note.bad { color: #e8806f; }
.report .hl-note.flat { color: #d8b878; }
.report .hl-bar { width: 100%; height: .25rem; display: block; appearance: none; -webkit-appearance: none; border: 0; background: #22262b; margin-top: .2rem; }
.report .hl-bar::-webkit-progress-bar { background: #22262b; }
.report .hl-bar.good::-webkit-progress-value { background: #5fd39a; }
.report .hl-bar.bad::-webkit-progress-value { background: #e8806f; }
.report .hl-bar.flat::-webkit-progress-value { background: #d8b878; }
.report .hl-bar.good::-moz-progress-bar { background: #5fd39a; }
.report .hl-bar.bad::-moz-progress-bar { background: #e8806f; }
.report .hl-bar.flat::-moz-progress-bar { background: #d8b878; }

.report .cmt { border-left: 2px solid #c3a46b; padding-left: .6rem; }
.report .cmt-head { font-size: .68rem; text-transform: uppercase; letter-spacing: .08em; color: #c3a46b; margin-bottom: .25rem; }
.report .cmt-body { font-size: .8rem; line-height: 1.5; color: #b9bec5; }
.report .rpt-edit { font-size: .74rem; color: #8b8f96; cursor: pointer; }
.report details[open] .rpt-edit { color: #c3a46b; }
.report .form-control { background: #1c1f24; border-color: #2b2f34; color: #e9e7e4; }
.report .form-control:focus { background: #1c1f24; color: #fff; border-color: #c3a46b; box-shadow: none; }
.report .form-control::placeholder { color: #6f747b; }

/* Report filters: the MTD/YTD toggle and the location chips, dark like the sheet they sit on. */
.report .rpt-filters .chip-row { gap: .3rem; }
.report .rpt-chip { flex: 0 0 auto; display: inline-block; padding: .2rem .7rem; border-radius: 999px; font-size: .72rem;
  letter-spacing: .04em; text-transform: uppercase; text-decoration: none; color: #9aa0a7; background: #16181c; border: 1px solid #2b2f34; }
.report .rpt-chip:hover { color: #e9e7e4; border-color: #3b4047; }
.report .rpt-chip.on { background: #c3a46b; border-color: #c3a46b; color: #15171a; font-weight: 600; }
.report .rpt-grid tbody tr.picked th, .report .rpt-grid tbody tr.picked td { background: #1d2126; }
.report .rpt-grid tbody th a { color: inherit; text-decoration: none; border-bottom: 1px dotted #4a4f56; }
.report .rpt-grid tbody th a:hover { color: #f0d7a0; border-bottom-color: #c3a46b; }

/* Unfinished workouts on the schedule: a count you can open, with the usual swipe-to-delete rows. */
.open-sessions > summary { display: flex; align-items: center; gap: .25rem; cursor: pointer; list-style: none;
  padding: .4rem .6rem; border-radius: .5rem; background: var(--bs-warning-bg-subtle, #fff3cd); border: 1px solid var(--bs-warning-border-subtle, #ffe69c); }
.open-sessions > summary::-webkit-details-marker { display: none; }
.open-sessions[open] > summary { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
/* The day strip's appointment tally: the icon sits with the number rather than above it. */
.day-chip small.tally { opacity: .85; white-space: nowrap; }
.day-chip small.tally .bi { font-size: .6rem; vertical-align: baseline; }
