/*
    Elevate apps: the one stylesheet of the coach app (coach/) and the client
    app (my/). Both shells link it from inc/head.php with ?v=<filemtime>, because
    the client app's service worker caches static files by URL.

    The website's design language (dark, Anton + Inter, red-to-orange accent,
    pill buttons) applied with an app's discipline: phone first (390, checked at
    320), a bottom tab bar under the thumb, 44px touch targets, one primary
    button style, right-to-left throughout (logical properties only).

    A page never restyles a component: it uses the classes below. The reference
    for page work is APPS-UI.md in the repo root.

    Contents
      1  Tokens               8  Badges                  14  Flash (toast)
      2  Base                 9  Lists, rows, facts      15  Sign-in screen
      3  Shell               10  Tiles, figures, meter   16  Right-to-left
      4  Page furniture      11  Tabs, segments, chips   17  Desktop
      5  Cards, notices      12  Tables                  18  Reduced motion
      6  Buttons             13  Media                   19  Screens (added with the pages)
      7  Forms
*/

/* ---------- 1  Tokens ---------- */

/* a condensed local face behind Anton, so display type keeps its shape when the web font is blocked */
@font-face {
    font-family: "Elevate Display";
    font-weight: 400;
    src: local("Impact"), local("HelveticaNeue-CondensedBlack"), local("HelveticaNeue-CondensedBold"),
         local("AvenirNextCondensed-Heavy"), local("RobotoCondensed-Bold"), local("Roboto Condensed Bold"),
         local("Arial Narrow Bold");
}

:root {
    color-scheme: dark;

    /* colour: surfaces, darkest to lightest */
    --field: #0e0c0b;            /* inputs, inset panels */
    --bg: #181513;               /* the page */
    --bg-2: #201c1a;             /* tab bar, raised strips */
    --surface: #272220;          /* cards */
    --surface-2: #302a27;        /* tiles and controls on a card */
    --surface-3: #3a3330;        /* pressed, selected */
    --line: #39322f;             /* separators, card edges */
    --line-strong: #756a64;      /* the edge of a control (3:1 on a card) */

    /* colour: text */
    --text: #e7e9ec;
    --text-strong: #fff;
    --muted: #9aa0aa;            /* 5.9:1 on a card */
    --placeholder: #858b95;

    /* colour: brand */
    --red: #D62F2A;
    --orange: #EF3B36;           /* fills, icons, rules, focus: never small text */
    --accent-text: #ff6b61;      /* links and accent text (5.6:1 on a card) */
    --btn-from: #C92A25;         /* primary button gradient: white text stays above 4.5:1 */
    --btn-to: #DC322C;
    --focus: #ff7a70;

    /* colour: status (text / tint / edge / solid for toasts) */
    --ok: #6fdcae;    --ok-bg: rgba(54, 192, 138, .16);    --ok-line: rgba(54, 192, 138, .42);    --ok-solid: #1c3128;
    --warn: #f7c653;  --warn-bg: rgba(245, 179, 1, .16);   --warn-line: rgba(245, 179, 1, .42);   --warn-solid: #3b2e10;
    --info: #8cc0ff;  --info-bg: rgba(76, 155, 255, .16);  --info-line: rgba(76, 155, 255, .42);  --info-solid: #1f2a3a;
    --off: #c3c7ce;   --off-bg: rgba(154, 160, 170, .16);  --off-line: rgba(154, 160, 170, .34);
    --bad: #ff8d85;   --bad-bg: rgba(239, 59, 54, .16);    --bad-line: rgba(239, 59, 54, .5);     --bad-solid: #3d1c1a;

    /* type */
    --font: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans Arabic", "Geeza Pro", Tahoma, Arial, sans-serif;
    --font-display: "Anton", "Elevate Display", Impact, "Arial Narrow", sans-serif;
    --display-weight: 400;
    --display-lh: 1.08;
    --caps: uppercase;           /* switched off in Arabic, with the tracking */
    --track: .04em;
    --track-wide: .14em;
    --lh: 1.5;

    --fs-xs: .6875rem;           /* 11  tab labels, badges, table heads */
    --fs-sm: .8125rem;           /* 13  muted lines, help, small buttons */
    --fs-md: .9375rem;           /* 15  body */
    --fs-lg: 1.0625rem;          /* 17  card titles */
    --fs-xl: clamp(1rem, 5.2vw, 1.375rem);   /* 22 (less on a narrow phone)  tile figures */
    --fs-title: 1.875rem;        /* 30  page title (Anton) */
    --fs-figure: 2.75rem;        /* 44  the one big number on a screen (Anton) */

    /* space (4px steps) */
    --s1: 4px;  --s2: 8px;  --s3: 12px;  --s4: 16px;  --s5: 20px;  --s6: 24px;  --s8: 32px;  --s10: 40px;

    /* shape */
    --r-sm: 8px;
    --r-md: 12px;                /* fields, tiles, inset panels */
    --r-lg: 16px;                /* cards */
    --r-pill: 999px;             /* buttons, badges, chips */
    --shadow-bar: 0 -10px 30px rgba(0, 0, 0, .38);
    --shadow-pop: 0 14px 40px rgba(0, 0, 0, .55);

    /* layout */
    --wrap: 760px;
    --gutter: 16px;
    --card-pad: 16px;
    --tap: 44px;
    --tabbar-h: 62px;

    /* the company mark, as on the website (drawn here so the apps need no image file) */
    --logo: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='36 64 523 143'%3E%3Cpath fill='%23fff' d='M287.4,174.3c-7-4-12.5-9.5-16.4-16.5c-4-7.1-5.9-15.1-5.9-24c0-8.9,2-16.9,5.9-24c4-7.1,9.4-12.6,16.4-16.5c7-4,14.9-5.9,23.7-5.9c9.4,0,17.7,2.1,24.8,6.4c7.2,4.2,12.7,10.3,16.5,18.1c3.8,7.8,5.5,16.8,4.9,27h-72.5c-2.6,0-4.5,2.4-3.9,4.9c1.5,6.2,4.5,11.3,9,15.4c5.7,5.1,12.7,7.7,21.2,7.7c6.3,0,12-1.3,16.9-3.9c4.9-2.6,8.6-6.3,11.1-11h15.6c-3.2,8.8-8.6,15.8-16.4,20.9c-7.7,5.1-16.8,7.6-27.2,7.6C302.3,180.2,294.4,178.2,287.4,174.3zM337,126.3c2.7,0,4.8-2.7,3.8-5.3c-1.9-5.1-5-9.4-9.3-13c-5.7-4.7-12.4-7.1-20.3-7.1c-7.9,0-14.6,2.3-20.2,7c-4.2,3.5-7.3,8-9.1,13.3c-0.9,2.6,1.1,5.2,3.8,5.2H337z'/%3E%3Cpath fill='%23fff' d='M401.5,176.4c-3.2-1.4-6.2-3.2-8.9-5.3c-2.4-1.9-5.8-0.2-5.8,2.8v30.9h-14.4v-116h14.4v5.8c0,2.6,3,4.1,5.1,2.4c2.9-2.4,6.1-4.4,9.7-6c5.8-2.5,12.2-3.8,19.2-3.8c8.6,0,16.3,2,23.2,6c6.9,4,12.3,9.5,16.1,16.5c3.8,7,5.8,15,5.8,23.9c0,8.9-1.9,16.9-5.8,23.9c-3.8,7-9.2,12.5-16.1,16.5c-6.9,4-14.6,6-23.2,6C413.6,180.2,407.3,178.9,401.5,176.4zM390.6,150.8c2.8,5,6.6,8.9,11.5,11.7c4.9,2.8,10.5,4.2,16.7,4.2c6.2,0,11.8-1.4,16.6-4.2c4.9-2.8,8.7-6.7,11.4-11.7c2.8-5,4.2-10.7,4.2-17c0-6.3-1.4-12-4.2-17c-2.8-5-6.6-8.9-11.4-11.7c-4.9-2.8-10.4-4.2-16.6-4.2c-6.2,0-11.8,1.4-16.7,4.2c-4.9,2.8-8.8,6.7-11.5,11.7c-2.8,5-4.2,10.7-4.2,17C386.4,140.1,387.8,145.8,390.6,150.8z'/%3E%3Cpath fill='%23fff' d='M493.7,172.2c-4.9-4.6-7.3-11.9-7.3-21.7v-44.3c0-3-2.4-5.4-5.4-5.4h-13.4v-12H482c2.5,0,4.5-2,4.5-4.5V67.6l14.4-1.5v18.3c0,2.5,2,4.5,4.5,4.5h20.3v12h-19.4c-3,0-5.4,2.4-5.4,5.4v42.6c0,6,1.3,10.3,4,13c2.7,2.7,7.1,4,13.3,4c2.7,0,5.6-0.2,8.6-0.5v13.4c-3.5,0.3-6.9,0.5-10.3,0.5C506.2,179.2,498.6,176.9,493.7,172.2z'/%3E%3Cpath fill='%23EF3B36' d='M540.5,177.2c-1.8-1.9-2.7-4.2-2.7-6.9s0.9-5,2.7-6.8c1.8-1.8,4.1-2.7,6.8-2.7c2.7,0,5,0.9,6.9,2.7c1.9,1.8,2.8,4.1,2.8,6.8s-0.9,5-2.8,6.9s-4.2,2.8-6.9,2.8C544.6,180,542.3,179.1,540.5,177.2z'/%3E%3Cpath fill='%23EF3B36' d='M212.6,139.5h-39.9c-3.9,0-7.2-3.2-7.2-7.2c0-3.9,3.2-7.2,7.2-7.2H213c13,0,23.7-10.6,23.7-23.6c0-13-10.6-23.7-23.7-23.7h-62.4c-5.1,0-9.7,2-13.1,5.2c-3.4-3.2-8.1-5.2-13.1-5.2H61.9c-13,0-23.7,10.6-23.7,23.7c0,13,10.6,23.6,23.7,23.6h40.3c3.9,0,7.2,3.2,7.2,7.2c0,4-3.2,7.2-7.2,7.2H62.3c-13.3,0-24.1,10.8-24.1,24.1c0,13.3,10.8,24.1,24.1,24.1h62.3c5,0,9.5-2.1,12.8-5.4c3.3,3.3,7.8,5.4,12.8,5.4h62.3c13.3,0,24.1-10.8,24.1-24.1C236.6,150.3,225.9,139.5,212.6,139.5zM212.6,175.6h-62.3c-3.2,0-6.7-2.6-6.7-5.8v-8.9h-12.2v8.8l0,0.1c0,3.2-3.4,5.8-6.7,5.8H62.3c-6.6,0-12-5.4-12-12c0-6.6,5.4-12,12-12h39.9c10.6,0,19.3-8.6,19.3-19.3c0-10.6-8.6-19.2-19.3-19.2H61.9c-6.4,0-11.6-5.2-11.6-11.6c0-6.4,5.2-11.6,11.6-11.6h62.4c3.6,0,6.6,2.7,7.1,6.2c0,0.4,0,9.7,0,9.7h12.1c0,0,0-9.2,0-9.7c0.5-3.5,3.4-6.2,7.1-6.2H213c6.4,0,11.6,5.2,11.6,11.6c0,6.4-5.2,11.6-11.6,11.6h-40.3c-10.6,0-19.2,8.6-19.2,19.2c0,10.6,8.6,19.3,19.2,19.3h39.9c6.6,0,12,5.4,12,12C224.6,170.2,219.2,175.6,212.6,175.6z'/%3E%3C/svg%3E");

    /* names the pages written before the redesign use in inline styles: do not use in new markup */
    --ink: var(--text-strong);
    --brand: var(--orange);
}

/* ---------- 2  Base ---------- */

*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scroll-padding-bottom: calc(var(--tabbar-h) + 32px); }
body {
    margin: 0;
    min-height: 100vh;
    min-height: 100dvh;
    font-family: var(--font);
    font-size: var(--fs-md);
    line-height: var(--lh);
    color: var(--text);
    background: var(--bg);
    font-variant-numeric: tabular-nums;
    overflow-wrap: break-word;
    -webkit-font-smoothing: antialiased;
    -webkit-tap-highlight-color: transparent;
}

h1, h2, h3, h4, p, figure, dl, dd { margin: 0; }
h1, h2, h3, h4 { color: var(--text-strong); line-height: 1.25; }
p { margin-bottom: var(--s3); }
b, strong { font-weight: 700; color: var(--text-strong); }
small { font-size: var(--fs-sm); }
img, svg { max-width: 100%; }
a { color: var(--accent-text); text-underline-offset: 3px; }
hr { border: 0; border-top: 1px solid var(--line); margin: var(--s4) 0; }

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

/* text typed by people (names, notes) may be Arabic on an English screen: never tracked */
[dir="auto"] { letter-spacing: 0; }

.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.muted { color: var(--muted); font-size: var(--fs-sm); }
.strong { color: var(--text-strong); font-weight: 700; }
.help { color: var(--muted); font-size: var(--fs-sm); margin: 6px 0 0; }
.no-wrap, .nowrap { white-space: nowrap; }
.end { text-align: end; }
.eyebrow { display: block; color: var(--accent-text); font-size: var(--fs-xs); font-weight: 700; letter-spacing: var(--track-wide); text-transform: var(--caps); }
.money { font-weight: 700; color: var(--text-strong); white-space: nowrap; }
/* money is one left-to-right run: <span class="money" dir="ltr">50.000 <small>OMR</small></span> */
.money small, .tiles .money small { display: inline; margin: 0; font-family: var(--font); font-size: .75em; font-weight: 600; letter-spacing: 0; color: var(--muted); }

/* ---------- 3  Shell ---------- */

.skip { position: absolute; inset-inline-start: 12px; top: -80px; z-index: 100; padding: 10px 16px; border-radius: var(--r-pill); background: var(--text-strong); color: var(--bg); font-weight: 700; text-decoration: none; }
.skip:focus { top: calc(8px + env(safe-area-inset-top)); }

/* The top bar holds the tab bar, which is fixed to the bottom of a phone: never
   give .topbar a transform, filter or backdrop-filter (it would capture it). */
.topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s3);
    min-height: 56px;
    padding-block: calc(6px + env(safe-area-inset-top)) 6px;
    padding-inline: max(var(--gutter), env(safe-area-inset-left)) max(var(--gutter), env(safe-area-inset-right));
    background: var(--bg);
    border-bottom: 1px solid var(--line);
}
.brand { display: block; flex: 0 0 auto; height: 30px; aspect-ratio: 523 / 143; background: var(--logo) center / contain no-repeat; color: var(--text-strong); font-weight: 700; text-decoration: none; }
.brand::after { content: ""; position: absolute; }
.tools { display: flex; align-items: center; gap: var(--s2); min-width: 0; }
.who { display: none; color: var(--muted); font-size: var(--fs-sm); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 220px; }
/* language and sign-out: 44px to touch, a 36px pill to look at (drawn on the inner span / ::before) */
.lang, .signout {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--tap);
    min-height: var(--tap);
    padding: 0;
    border: 0;
    border-radius: var(--r-pill);
    background: none;
    color: var(--text);
    font: inherit;
    font-size: var(--fs-sm);
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
}
.lang span { display: inline-flex; align-items: center; min-height: 36px; padding: 0 14px; border: 1px solid var(--line-strong); border-radius: var(--r-pill); }
.signout::before { content: ""; position: absolute; inset: 4px; border: 1px solid var(--line-strong); border-radius: var(--r-pill); }
.signout svg { width: 18px; height: 18px; flex: 0 0 auto; }
.signout span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.signout:active { transform: none; }

/* the primary navigation: a tab bar on a phone, links in the top bar on a desktop (section 16) */
.tabbar {
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 40;
    display: flex;
    justify-content: center;
    padding-inline: max(4px, env(safe-area-inset-left)) max(4px, env(safe-area-inset-right));
    padding-bottom: env(safe-area-inset-bottom);
    background: var(--bg-2);
    border-top: 1px solid var(--line);
    box-shadow: var(--shadow-bar);
}
.tabbar a {
    position: relative;
    flex: 1 1 0;
    min-width: 0;
    max-width: 128px;
    min-height: var(--tabbar-h);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap: 3px;
    padding: 10px 2px 6px;
    color: var(--muted);
    font-size: var(--fs-xs);
    font-weight: 600;
    line-height: 1.2;
    text-decoration: none;
}
.tabbar a svg { width: 24px; height: 24px; flex: 0 0 auto; }
/* a long label (Arabic) takes a second line rather than being cut */
.tabbar a span { display: -webkit-box; max-width: 100%; overflow: hidden; text-align: center; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
.tabbar a.on { color: var(--text-strong); }
.tabbar a.on svg { color: var(--orange); }
.tabbar a.on::before { content: ""; position: absolute; top: -1px; inset-inline: 24%; height: 3px; border-radius: 0 0 3px 3px; background: var(--orange); }
.tabbar a:active { background: var(--surface); }
.tabbar a:focus-visible { outline-offset: -4px; border-radius: var(--r-md); }
.ico { fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* the page column; the bottom padding keeps the last control clear of the tab bar */
.wrap {
    max-width: var(--wrap);
    margin: 0 auto;
    padding-block: var(--s4) calc(var(--tabbar-h) + env(safe-area-inset-bottom) + var(--s6));
    padding-inline: max(var(--gutter), env(safe-area-inset-left)) max(var(--gutter), env(safe-area-inset-right));
}
/* signed out there is no tab bar */
.signed-out { --tabbar-h: 0px; }

/* ---------- 4  Page furniture ---------- */

.page-head { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--s2) var(--s3); margin: var(--s1) 0 var(--s4); }
.page-head > .back, .page-head > .page-sub, .page-head > .eyebrow { flex: 1 0 100%; margin: 0; }
.page-title {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    font-family: var(--font-display);
    font-weight: var(--display-weight);
    font-size: var(--fs-title);
    line-height: var(--display-lh);
    letter-spacing: .01em;
    text-transform: var(--caps);
    color: var(--text-strong);
}
.page-sub { color: var(--muted); font-size: var(--fs-md); }
.back { display: inline-flex; align-items: center; gap: 6px; min-height: var(--tap); margin: -6px 0 2px; color: var(--muted); font-size: var(--fs-sm); font-weight: 600; text-decoration: none; }
.back:hover { color: var(--text-strong); }

/* a label above a group of cards or a list; an optional link sits at the far end */
.section-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3); margin: var(--s6) 0 var(--s2); }
.section-head h2, .section-head h3 { font-size: var(--fs-sm); font-weight: 700; letter-spacing: var(--track-wide); text-transform: var(--caps); color: var(--muted); }
.section-head a { font-size: var(--fs-sm); font-weight: 600; text-decoration: none; white-space: nowrap; }

/* ---------- 5  Cards, notices, empty states ---------- */

.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); padding: var(--card-pad); margin-bottom: var(--s3); }
.card > :last-child { margin-bottom: 0; }
.card h2 { font-size: var(--fs-lg); font-weight: 700; margin: 0 0 var(--s2); }
.card h3 { font-size: var(--fs-md); font-weight: 700; margin: var(--s4) 0 var(--s2); }
.card > p.muted { font-size: var(--fs-sm); }

/* a fold-out card: the summary is the whole top row */
details.card { padding: 0; }
details.card > summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s3);
    min-height: 56px;
    padding: var(--s3) var(--card-pad);
    list-style: none;
    cursor: pointer;
    font-size: var(--fs-lg);
    font-weight: 700;
    color: var(--text-strong);
    border-radius: var(--r-lg);
}
details.card > summary::-webkit-details-marker { display: none; }
details.card > summary::after {
    content: "";
    flex: 0 0 auto;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: 1px solid var(--line-strong);
    background:
        linear-gradient(var(--text-strong), var(--text-strong)) center / 12px 2px no-repeat,
        linear-gradient(var(--text-strong), var(--text-strong)) center / 2px 12px no-repeat;
}
details.card[open] > summary { margin-bottom: 0; border-bottom: 1px solid var(--line); border-radius: var(--r-lg) var(--r-lg) 0 0; }
details.card[open] > summary::after { background: linear-gradient(var(--text-strong), var(--text-strong)) center / 12px 2px no-repeat; }
details.card > :not(summary) { margin-inline: var(--card-pad); }
details.card > summary + * { margin-top: var(--s3); }
details.card > :last-child:not(summary) { margin-bottom: var(--card-pad); }

/* folds outside a card heading. details.fold: a quiet line ("Later (5)", "Other date").
   details.add: the summary is a button ("Add a measurement"); the form opens under it. */
details.fold > summary, details.add > summary { display: inline-flex; align-items: center; gap: var(--s2); min-height: var(--tap); list-style: none; cursor: pointer; }
details.fold > summary::-webkit-details-marker, details.add > summary::-webkit-details-marker { display: none; }
details.fold > summary { color: var(--text); font-size: var(--fs-sm); font-weight: 600; }
details.fold > summary::after { content: ""; flex: 0 0 auto; width: 7px; height: 7px; margin-inline-start: 2px; border-block-end: 2px solid var(--muted); border-inline-end: 2px solid var(--muted); transform: translateY(-2px) rotate(45deg); transition: transform .18s ease; }
details.fold[open] > summary::after { transform: translateY(2px) rotate(-135deg); }
details.add > summary { padding: 10px 20px; padding-inline-start: 14px; border: 1.5px solid var(--line-strong); border-radius: var(--r-pill); color: var(--text-strong); font-size: var(--fs-sm); font-weight: 700; line-height: 1.2; letter-spacing: var(--track); text-transform: var(--caps); }
details.add > summary::before { content: ""; flex: 0 0 auto; width: 14px; height: 14px; background: linear-gradient(currentColor, currentColor) center / 14px 2px no-repeat, linear-gradient(currentColor, currentColor) center / 2px 14px no-repeat; }
details.add[open] > summary { margin-bottom: var(--s3); }
details.add[open] > summary::before { background: linear-gradient(currentColor, currentColor) center / 14px 2px no-repeat; }

/* a message that belongs to the page: an alert, a callout, the answer beside a control
   (the reply to a saved action is .flash). Empty, it takes no room. */
.notice { display: block; padding: var(--s3) 14px; margin: 0 0 var(--s3); border: 1px solid var(--off-line); border-inline-start-width: 4px; border-radius: var(--r-md); background: var(--off-bg); color: var(--text); font-size: var(--fs-md); }
.notice:empty { display: none; }
.notice b { display: block; }
.notice a { color: inherit; font-weight: 600; }
.notice > :last-child { margin-bottom: 0; }
.notice.ok { background: var(--ok-bg); border-color: var(--ok-line); }
.notice.ok b { color: var(--ok); }
.notice.warn { background: var(--warn-bg); border-color: var(--warn-line); }
.notice.warn b { color: var(--warn); }
.notice.info { background: var(--info-bg); border-color: var(--info-line); }
.notice.info b { color: var(--info); }
.notice.bad { background: var(--bad-bg); border-color: var(--bad-line); }
.notice.bad b { color: var(--bad); }

/* nothing to show yet */
.empty { padding: var(--s6) var(--s4); text-align: center; color: var(--muted); font-size: var(--fs-sm); }
.empty b { display: block; margin-bottom: var(--s1); font-size: var(--fs-md); color: var(--text); }
.empty .btn { margin-top: var(--s3); }

/* a line with a mark at its start: health flags, what to work on */
.flag { position: relative; margin: var(--s2) 0; font-size: var(--fs-md); display: flow-root; }
.flag > .badge:first-child { float: inline-start; margin-inline-end: 10px; min-width: 24px; padding-inline: 6px; }
@supports selector(:has(a)) {
    .flag:has(> .badge:first-child) { padding-inline-start: 34px; }
    .flag > .badge:first-child { float: none; position: absolute; inset-inline-start: 0; top: 0; margin: 0; }
}

/* ---------- 6  Buttons ---------- */

button, .btn, a.pay-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--s2);
    min-height: var(--tap);
    padding: 10px 20px;
    border: 1.5px solid transparent;
    border-radius: var(--r-pill);
    background: linear-gradient(135deg, var(--btn-from), var(--btn-to));
    color: #fff;
    font: inherit;
    font-size: var(--fs-sm);
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: var(--track);
    text-transform: var(--caps);
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
    transition: transform .12s ease, background-color .12s ease, border-color .12s ease;
}
button:active, .btn:active { transform: scale(.97); }
button:disabled, .btn[aria-disabled="true"] { opacity: .5; cursor: default; transform: none; }

/* secondary: the same shape, no fill */
.btn.ghost { background: transparent; border-color: var(--line-strong); color: var(--text-strong); }
/* destructive: never the loudest thing in a row */
.btn.warn { background: transparent; border-color: var(--bad-line); color: var(--bad); }
/* an action that is only words; with .warn, the quiet way to delete or remove */
.btn.quiet { background: transparent; border-color: transparent; color: var(--accent-text); padding-inline: var(--s2); }
.btn.quiet.warn { color: var(--bad); }
.btn.block { display: flex; width: 100%; }

/* small: narrower and lighter, still 44px high on a phone (36px with a mouse, section 17) */
button.small, .btn.small { padding: 6px 14px; font-size: .75rem; }

.actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.actions.end { justify-content: flex-end; }
.contact { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); margin-top: var(--s3); }
.save { margin-top: var(--s4); }

/* the page's primary action, kept above the tab bar while a long form scrolls */
.savebar { position: sticky; bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom)); z-index: 20; margin: var(--s4) calc(var(--gutter) * -1) 0; padding: var(--s3) var(--gutter); background: linear-gradient(to top, var(--bg) 70%, transparent); }
.savebar > button, .savebar > .btn { width: 100%; }
/* its message sits in the bar, above the button, not as a toast */
.savebar .flash { position: relative; inset: auto; max-width: none; margin: 0 0 var(--s2) !important; box-shadow: none; animation: flash-in .22s ease-out; }

/* ---------- 7  Forms ---------- */

label { display: block; margin: 14px 0 6px; font-size: var(--fs-sm); font-weight: 600; color: var(--text); }
label .muted { font-weight: 400; }
.field { margin: 0 0 14px; }
.field > label:first-child { margin-top: 0; }

input, select, textarea {
    display: block;
    width: 100%;
    min-width: 0;
    min-height: 48px;
    margin: 0;
    padding: 12px 14px;
    border: 1px solid var(--line-strong);
    border-radius: var(--r-md);
    background-color: var(--field);
    color: var(--text-strong);
    font: inherit;
    font-size: 1rem;             /* 16px: no zoom on focus on an iPhone */
    line-height: 1.4;
    text-align: start;
    -webkit-appearance: none;
    appearance: none;
}
input::placeholder, textarea::placeholder { color: var(--placeholder); opacity: 1; font-size: var(--fs-md); }
input:focus-visible, select:focus-visible, textarea:focus-visible { border-color: var(--orange); outline-offset: 1px; }
input:disabled, select:disabled, textarea:disabled { opacity: .55; }
/* a field the browser fills in itself (a saved username or password, a phone number) keeps the dark
   field: WebKit paints autofill pale yellow over any background, so it is covered from inside */
input:-webkit-autofill, input:-webkit-autofill:hover, input:-webkit-autofill:focus, textarea:-webkit-autofill, select:-webkit-autofill {
    -webkit-text-fill-color: var(--text-strong);
    caret-color: var(--text-strong);
    -webkit-box-shadow: 0 0 0 100px var(--field) inset;
    box-shadow: 0 0 0 100px var(--field) inset;
}
input[readonly] { color: var(--muted); }
/* one-line fields are all one height, whatever the browser's picker adds */
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]), select { height: 3rem; }
textarea { min-height: 84px; resize: vertical; line-height: 1.5; }

select {
    padding-inline-end: 42px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23e7e9ec' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 18px;
    text-overflow: ellipsis;
}
select option { background: var(--surface); color: var(--text-strong); }

/* native pickers: sized like every other field, their value at the start */
input[type="date"], input[type="time"], input[type="month"], input[type="datetime-local"] { padding-inline: 12px; }
input::-webkit-date-and-time-value { text-align: start; min-height: 1.4em; }
input::-webkit-calendar-picker-indicator { opacity: .85; cursor: pointer; }
input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }

input[type="checkbox"], input[type="radio"] {
    display: inline-block;
    flex: 0 0 auto;
    width: 22px;
    min-width: 22px;
    height: 22px;
    min-height: 0;
    padding: 0;
    margin: 0;
    border: 0;
    background: none;
    accent-color: var(--orange);
    -webkit-appearance: auto;
    appearance: auto;
    cursor: pointer;
}
label.check { display: flex; align-items: center; gap: var(--s3); min-height: var(--tap); margin: var(--s1) 0; font-size: var(--fs-md); cursor: pointer; }
label.plain { font-weight: 400; align-items: flex-start; padding-block: 8px; }
label.plain > input { margin-top: 1px; }

input[type="file"] { min-height: 52px; padding: 7px; border-style: dashed; color: var(--muted); font-size: var(--fs-sm); cursor: pointer; }
input[type="file"]::file-selector-button {
    min-height: 36px;
    margin-inline-end: var(--s3);
    padding: 6px 14px;
    border: 1px solid var(--line-strong);
    border-radius: var(--r-pill);
    background: var(--surface-2);
    color: var(--text-strong);
    font: inherit;
    font-size: var(--fs-sm);
    font-weight: 700;
    cursor: pointer;
}

fieldset { min-width: 0; margin: var(--s4) 0 0; padding: var(--s3) 0 0; border: 0; border-top: 1px solid var(--line); }
legend { padding: 0; padding-inline-end: var(--s3); font-size: var(--fs-sm); font-weight: 700; letter-spacing: var(--track-wide); text-transform: var(--caps); color: var(--muted); }

/* two fields side by side; one column on the narrowest phones */
.cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0 var(--s3); align-items: end; }
.cols > div { min-width: 0; }
.cols.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 349.98px) {
    .cols, .cols.three { grid-template-columns: minmax(0, 1fr); }
}

/* a panel that folds out under a row: reschedule, collect a payment, a payment link */
.move-form, .collect-form, .linkbox { margin-top: var(--s3); padding: var(--s1) var(--s3) var(--s3); border: 1px solid var(--line); border-radius: var(--r-md); background: var(--bg); }
.linkbox { padding-top: var(--s3); }
.linkbox .help { margin-top: 0; }

/* one exercise per row: name, sets, reps, weight */

/* ---------- 8  Badges ---------- */

/* a status word, as written (not upper-cased: scripts and tests read it as it appears) */
.badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 24px;
    padding: 2px 10px;
    border: 1px solid var(--off-line);
    border-radius: var(--r-pill);
    background: var(--off-bg);
    color: var(--off);
    font-size: .75rem;
    font-weight: 700;
    line-height: 1.3;
    white-space: nowrap;
    vertical-align: middle;
}
.badge.ok { background: var(--ok-bg); border-color: var(--ok-line); color: var(--ok); }
.badge.warn { background: var(--warn-bg); border-color: var(--warn-line); color: var(--warn); }
.badge.info { background: var(--info-bg); border-color: var(--info-line); color: var(--info); }
.badge.bad { background: var(--bad-bg); border-color: var(--bad-line); color: var(--bad); }
.badge.off { background: var(--off-bg); border-color: var(--off-line); color: var(--off); }
/* how many are waiting */
.count { display: inline-flex; align-items: center; justify-content: center; min-width: 22px; height: 22px; padding: 0 6px; border-radius: var(--r-pill); background: var(--btn-from); color: #fff; font-size: var(--fs-xs); font-weight: 700; }

/* ---------- 9  Lists, entries, facts ---------- */

/* THE list row: .rows > .row (a div, an li, or an a when the whole row goes somewhere)
     .row-main     what or when: a <b> line, .muted lines under it
     .row-end      status, amount or one small control, at the far end
     .row-actions  an optional second line of buttons
     .row-fold     an optional panel that opens under the row
   .list a and .entry below are the same row under the names the older pages use. */
.rows { list-style: none; margin: 0; padding: 0; }
.row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s3); min-height: 60px; padding: 10px 0; border-bottom: 1px solid var(--line); color: inherit; font-size: var(--fs-md); text-decoration: none; }
.row:last-child { border-bottom: 0; }
.row-main { flex: 1 1 0; min-width: 0; }
.row-main > b, .row-main > .muted { display: block; }
.row-end { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; flex: 0 0 auto; max-width: 60%; text-align: end; }
.row-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); flex: 1 0 100%; }
.row-fold { flex: 1 0 100%; min-width: 0; }
a.row { flex-wrap: nowrap; }
a.row::after, .list a::after { content: ""; flex: 0 0 auto; width: 8px; height: 8px; margin-inline: 0 2px; border-block-start: 2px solid var(--muted); border-inline-end: 2px solid var(--muted); transform: rotate(45deg); }
a.row:active, .list a:active { background: var(--surface-2); }
.card > .rows:last-child, .card > .list:last-child { margin-bottom: -6px; }
.card > .rows:first-child, .card > .list:first-child { margin-top: -6px; }
/* a heading inside a list grouped by day */
.day, .card .day { margin: var(--s4) 0 0; padding-bottom: 6px; border-bottom: 1px solid var(--line); color: var(--muted); font-size: var(--fs-xs); font-weight: 700; letter-spacing: var(--track-wide); text-transform: var(--caps); }
.day:first-child, .card .day:first-child { margin-top: 0; }

/* rows that go somewhere (older name) */
.list a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s3);
    min-height: 60px;
    padding: 10px 0;
    border-bottom: 1px solid var(--line);
    color: inherit;
    text-decoration: none;
}
.list a:last-child { border-bottom: 0; }
.list a > span:first-child { flex: 1 1 auto; min-width: 0; }
.list b { display: block; font-size: var(--fs-md); }
.list a > span:first-child > .muted { display: block; }
.list .side { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; flex: 0 0 auto; text-align: end; }
.list .side br { display: none; }
/* a round mark at the start of a row: initials */
.initial { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 40px; height: 40px; border-radius: 50%; background: var(--surface-3); color: var(--text-strong); font-size: var(--fs-sm); font-weight: 700; }

/* rows with their own lines and buttons (older name) */
.entry { padding: var(--s3) 0; border-bottom: 1px solid var(--line); font-size: var(--fs-md); }
.entry:first-child { padding-top: var(--s1); }
.entry:last-child { border-bottom: 0; padding-bottom: 0; }
.entry > div { margin-top: var(--s1); }
.entry .entry-head, .entry-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); margin-top: 0; }
.entry-head > span:first-child { min-width: 0; }
.entry-head > b { flex: 0 0 auto; }
.entry .entry-head + .entry-head { margin-top: var(--s1); }
.entry .actions { margin-top: var(--s3); }
.entry-head.muted b { color: inherit; }

/* live search results */
.results { margin-top: var(--s2); }
.results div { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); min-height: 52px; padding: 6px 0; border-bottom: 1px solid var(--line); font-size: var(--fs-md); }
.results p { margin: var(--s2) 0 0; }

/* label and value pairs */
.facts { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s2) var(--s4); margin: 0 0 var(--s3); font-size: var(--fs-md); }
.facts dt { color: var(--muted); font-size: var(--fs-sm); padding-top: 2px; }
.facts dd { margin: 0; min-width: 0; overflow-wrap: anywhere; color: var(--text-strong); }
.facts dd a, .facts dd .muted { white-space: nowrap; }

.sets { list-style: none; margin: 6px 0 0; padding: 0; }
.sets li { display: flex; justify-content: space-between; gap: var(--s3); padding: 3px 0; }

/* ---------- 10  Tiles, figures, meter ---------- */

.tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s2); }
.tiles.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.tiles.five { grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); }
.tiles > div, .tiles > a, .stat { display: block; min-width: 0; padding: 10px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--bg); color: inherit; text-decoration: none; }
.tiles b, .stat b { display: block; margin-top: 2px; font-family: var(--font-display); font-weight: var(--display-weight); font-size: var(--fs-xl); line-height: 1.2; letter-spacing: .01em; color: var(--text-strong); overflow-wrap: anywhere; }
.tiles small, .stat small { display: block; margin-top: 2px; color: var(--muted); font-size: .75rem; line-height: 1.35; }
.tiles .badge { margin-bottom: 6px; min-height: 20px; padding: 1px 8px; font-size: .75rem; white-space: normal; text-align: center; }
.tiles .alert { border-color: var(--bad-line); }
.tiles .alert b { color: var(--bad); }
@media (max-width: 349.98px) {
    /* round T (L5): 12 px at the least, even on a 320 px phone */
    .tiles .badge { padding-inline: 5px; font-size: .75rem; }
}

/* the one number a screen is about, with its unit: <p class="figure">9 <span class="unit">sessions left</span></p>
   .figure.sm is the same idea inside a row or a tile */
.big, .figure { margin: 0; font-family: var(--font-display); font-weight: var(--display-weight); font-size: var(--fs-figure); line-height: 1.05; color: var(--text-strong); }
.figure.sm { font-size: 1.75rem; line-height: 1.15; }
.big small, .figure small, .big .muted, .figure .muted, .figure .unit { font-family: var(--font); font-size: var(--fs-md); font-weight: 400; letter-spacing: 0; color: var(--muted); text-transform: none; }
.figure.sm .unit { font-size: var(--fs-sm); }

.total { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3); margin: var(--s4) 0 var(--s2); padding-top: var(--s3); border-top: 1px solid var(--line); font-size: var(--fs-md); }
.total b { font-family: var(--font-display); font-weight: var(--display-weight); font-size: 1.625rem; white-space: nowrap; }

/* how much of something is used: <div class="meter"><span style="width:60%"></span></div> */
.meter { height: 8px; border-radius: var(--r-pill); background: var(--field); overflow: hidden; }
.meter > span { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--red), var(--orange)); }
.meter.ok > span { background: var(--ok); }

/* ---------- 11  Tabs, segmented control, chips ---------- */

/* tabs: the views of one screen (client record, earnings). .nav.subnav is the name the pages use */
.tabs, .nav.subnav { display: flex; gap: 0; margin: 0 0 var(--s4); border-bottom: 1px solid var(--line); }
.tabs a, .nav.subnav a {
    position: relative;
    flex: 1 1 0;
    min-width: 0;
    min-height: var(--tap);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 10px 4px;
    color: var(--muted);
    font-size: var(--fs-sm);
    font-weight: 600;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
}
.tabs a.on, .tabs a[aria-current], .nav.subnav a.on { color: var(--text-strong); }
.tabs a.on::after, .tabs a[aria-current]::after, .nav.subnav a.on::after { content: ""; position: absolute; inset-inline: 0; bottom: -1px; height: 3px; border-radius: 3px 3px 0 0; background: var(--orange); }

/* segmented control: one of two to four options, side by side. Children are links,
   buttons, or <label><input type="radio"><span>Text</span></label> */
.seg { display: flex; gap: 4px; padding: 3px; border: 1px solid var(--line); border-radius: var(--r-pill); background: var(--field); }
.seg > label { position: relative; display: flex; flex: 1 1 0; min-width: 0; margin: 0; }
.seg > a, .seg > button, .seg > label > span { flex: 1 1 0; min-width: 0; min-height: var(--tap); padding: 6px 8px; border: 0; border-radius: var(--r-pill); background: transparent; color: var(--muted); font-size: var(--fs-sm); font-weight: 600; line-height: 1.2; letter-spacing: 0; text-transform: none; text-align: center; text-decoration: none; display: flex; align-items: center; justify-content: center; cursor: pointer; }
.seg > .on, .seg > [aria-pressed="true"], .seg > [aria-current], .seg > label > input:checked + span { background: var(--surface-3); color: var(--text-strong); }

/* chips: a set of choices that wraps (time slots, filters, the options of a short select).
   .chip on a link or button, or <label><input type="radio"><span>Text</span></label> inside .chips */
.chips { display: flex; flex-wrap: wrap; gap: var(--s2); }
.chips > label { position: relative; display: inline-flex; margin: 0; }
.chip, .chips > label > span { display: inline-flex; align-items: center; justify-content: center; min-height: var(--tap); padding: 8px 16px; border: 1px solid var(--line-strong); border-radius: var(--r-pill); background: var(--field); color: var(--text); font: inherit; font-size: var(--fs-sm); font-weight: 600; line-height: 1.2; letter-spacing: 0; text-transform: none; text-decoration: none; cursor: pointer; }
.chip.on, .chip[aria-pressed="true"], .chips > label > input:checked + span { background: var(--btn-from); border-color: var(--btn-from); color: #fff; }
.chip:disabled, .chips > label > input:disabled + span { opacity: .45; cursor: default; }
/* the radio (or checkbox) itself covers its chip, unseen: the keyboard and screen readers still reach it */
.seg > label > input, .chips > label > input { position: absolute; inset: 0; width: 100%; height: 100%; min-width: 0; margin: 0; opacity: 0; cursor: pointer; }
.seg > label > input:focus-visible + span, .chips > label > input:focus-visible + span { outline: 2px solid var(--focus); outline-offset: 2px; }

/* a rating: five <button type="button" class="star"> in .stars; .on (or aria-pressed) fills one */
.stars { display: flex; margin: var(--s1) 0; }
.star { min-width: var(--tap); min-height: var(--tap); padding: 0; border: 0; background: none; color: var(--line-strong); font-size: 1.75rem; line-height: 1; letter-spacing: 0; cursor: pointer; }
.star.on, .star[aria-pressed="true"] { color: var(--warn); }

/* ---------- 12  Tables ---------- */

/* From 640px a table is a table. Narrower, it is a list: every row becomes a
   block (first cell the row's title, td.actions a line of buttons), unless it
   is a small grid of figures (table.data), which stays a table. */
table { width: 100%; border-collapse: collapse; font-size: var(--fs-md); }
tbody tr + tr { border-top: 1px solid var(--line); }
tbody tr.move-row { border-top: 0; }
thead tr { border-bottom: 1px solid var(--line-strong); }
th { padding: var(--s2); text-align: start; vertical-align: bottom; color: var(--muted); font-size: var(--fs-xs); font-weight: 700; letter-spacing: var(--track); text-transform: var(--caps); }
td { padding: var(--s3) var(--s2); text-align: start; vertical-align: middle; }
th:first-child, td:first-child { padding-inline-start: 0; }
th:last-child, td:last-child { padding-inline-end: 0; }
/* a cell of buttons stays a real cell (so the column sizes itself); its buttons sit at the end */
td.actions { display: table-cell; text-align: end; }
td.actions > * { margin-block: 3px; margin-inline-start: 6px; vertical-align: middle; }
td.muted { font-size: var(--fs-sm); }
tr.move-row > td { padding-top: 0; }

@media (max-width: 639.98px) {
    table:not(.data), table:not(.data) > tbody { display: block; }
    table:not(.data) > thead { display: none; }
    table:not(.data) tr { display: flex; flex-wrap: wrap; align-items: center; gap: 6px var(--s3); padding: var(--s3) 0; }
    table:not(.data) tr:first-child { padding-top: var(--s1); }
    table:not(.data) tbody tr:last-child { padding-bottom: 0; }
    table:not(.data) td { display: block; min-width: 0; padding: 0; flex: 0 1 auto; }
    table:not(.data) td:last-child { margin-inline-start: auto; }
    table:not(.data) td.muted, table:not(.data) td[colspan] { flex: 1 1 100%; margin-inline-start: 0; }
    table:not(.data) td.actions { display: flex; flex: 1 1 100%; justify-content: flex-start; margin: var(--s1) 0 0; }
    table:not(.data) td.actions > * { margin: 0; }
    table:not(.data) td:empty { display: none; }
    table:not(.data) tr.move-row { padding-top: 0; }
    /* a cell can carry its column's name: <td data-label="Slot"> */
    table:not(.data) td[data-label]::before { content: attr(data-label) " "; color: var(--muted); font-size: var(--fs-sm); }

    table.data th, table.data td { padding: var(--s2) 6px; }
    table.data th:first-child, table.data td:first-child { padding-inline-start: 0; }
    table.data th:last-child, table.data td:last-child { padding-inline-end: 0; }
}
/* where the browser can tell: a table with headings and no buttons is a grid of figures, a lone button sits at the end of its row */
@supports selector(:has(a)) {
    @media (max-width: 639.98px) {
        table:has(> thead):not(:has(.actions, button, .btn)) { display: table; }
        table:has(> thead):not(:has(.actions, button, .btn)) > thead { display: table-header-group; }
        table:has(> thead):not(:has(.actions, button, .btn)) > tbody { display: table-row-group; }
        table:has(> thead):not(:has(.actions, button, .btn)) tr { display: table-row; }
        table:has(> thead):not(:has(.actions, button, .btn)) td { display: table-cell; padding: var(--s2) 6px; }
        table:has(> thead):not(:has(.actions, button, .btn)) td:first-child { padding-inline-start: 0; }
        table:has(> thead):not(:has(.actions, button, .btn)) td:last-child { padding-inline-end: 0; }
        table:not(.data) td.actions:not(:has(> :nth-child(2))) { flex: 0 0 auto; margin: 0; margin-inline-start: auto; }
    }
}

/* ---------- 13  Media ---------- */

.avatar { width: 96px; height: 120px; border-radius: var(--r-md); object-fit: cover; object-position: top center; background: var(--field); border: 1px solid var(--line); display: flex; align-items: center; justify-content: center; color: var(--muted); font-size: var(--fs-xs); text-align: center; flex: 0 0 auto; }
.photo-row { display: flex; align-items: center; gap: 14px; }
.photo-row > div { flex: 1 1 0; min-width: 0; }
.photo-row label:first-child { margin-top: 0; }
.photos { display: grid; grid-template-columns: repeat(auto-fill, minmax(112px, 1fr)); gap: 10px; margin: 10px 0 4px; }
.photos figure { display: flex; flex-direction: column; margin: 0; border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; background: var(--bg-2); }
.photos img { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; }
.photos .tools { display: flex; flex-wrap: wrap; justify-content: center; align-content: center; flex: 1 1 auto; gap: 6px; padding: var(--s2) 6px; }
.photos .tools .small { padding-inline: 10px; }
.trend { display: block; width: 100%; height: 84px; color: var(--orange); margin: 4px 0 6px; }

/* ---------- 14  Flash (toast) ---------- */

/* #msg is where a page shows the reply to an action. Empty it takes no room;
   as .flash it is a toast above the tab bar (a tap puts it away, see inc/foot.php). */
#msg { margin: 0; font-size: var(--fs-sm); }
#msg:empty { display: none; }
p#msg:not(:empty):not(.flash) { margin: var(--s3) 0; }
.flash {
    position: fixed;
    z-index: 60;
    inset-inline: var(--s3);
    bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom) + var(--s3));
    max-width: 520px;
    margin: 0 auto !important;
    padding-block: var(--s3);
    padding-inline: 14px 44px;
    border: 1px solid var(--ok-line);
    border-radius: var(--r-md);
    background: var(--ok-solid);
    color: var(--ok);
    font-size: var(--fs-md) !important;
    font-weight: 600;
    box-shadow: var(--shadow-pop);
    cursor: pointer;
    animation: flash-in .22s ease-out, flash-out .3s ease-in 6s forwards;
}
.flash::after { content: "\00d7"; position: absolute; inset-inline-end: 14px; top: 50%; transform: translateY(-50%); font-size: 1.25rem; line-height: 1; opacity: .75; }
/* on a page with a sticky save bar the toast rides above it */
body:has(.savebar) #msg.flash:not(.savebar *) { bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom) + 84px); }
/* a refusal stays until it is read */
.flash.bad { border-color: var(--bad-line); background: var(--bad-solid); color: var(--bad); animation: flash-in .22s ease-out; }
@keyframes flash-in { from { opacity: 0; transform: translateY(10px); } }
@keyframes flash-out { to { opacity: 0; visibility: hidden; } }

/* ---------- 15  Sign-in screen ---------- */

.signed-out { background: radial-gradient(120% 420px at 50% 0, rgba(214, 47, 42, .2), transparent 70%) no-repeat var(--bg); }
.signed-out .topbar { background: transparent; border-bottom-color: transparent; }
.signin { max-width: 420px; margin: 0 auto; padding-top: min(9vh, 72px); }
.signin .page-title { font-size: 2.375rem; margin: var(--s2) 0 var(--s3); }
.signin .page-title::after { content: ""; display: block; width: 54px; height: 4px; margin-top: var(--s3); border-radius: 2px; background: linear-gradient(90deg, var(--red), var(--orange)); }
.signin .page-sub { margin-bottom: var(--s5); }
.signin .card { padding: var(--s5); }
.signin .card > label:first-child, .signin .card > div > label:first-child { margin-top: 0; }
.signin .save { display: flex; flex-direction: column; gap: var(--s2); }
.signin .save > button { width: 100%; min-height: 50px; }
.signin p#msg:not(:empty) { margin: var(--s4) 0 0; padding: var(--s3) 14px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--bg); color: var(--text); font-size: var(--fs-md); }
/* a refusal (wrong password, no number typed) reads as one */
.signin p#msg.bad:not(:empty) { border-color: var(--bad-line); background: var(--bad-bg); color: var(--bad); }
.signin .code { font-size: 1.5rem; font-weight: 700; letter-spacing: .3em; text-align: center; }

/* ---------- 16  Right-to-left (Arabic) ---------- */

/* Inter and Anton have no Arabic: display type falls to the text face, heavier,
   and nothing is upper-cased or tracked. */
[dir="rtl"] {
    --font-display: var(--font);
    --display-weight: 800;
    --display-lh: 1.35;
    --caps: none;
    --track: 0;
    --track-wide: 0;
    --lh: 1.7;
    --fs-xs: .75rem;
    --fs-xl: clamp(.875rem, 4.4vw, 1.125rem);
}
[dir="rtl"] .page-title, [dir="rtl"] .tiles b, [dir="rtl"] .big, [dir="rtl"] .figure, [dir="rtl"] .total b { letter-spacing: 0; }
[dir="rtl"] input, [dir="rtl"] textarea, [dir="rtl"] select { text-align: right; }
[dir="rtl"] input::-webkit-date-and-time-value { text-align: right; }
[dir="rtl"] select { background-position: left 12px center; }
[dir="rtl"] .list a::after, [dir="rtl"] a.row::after { transform: rotate(-45deg); }
/* the chevron of a fold: down when closed, up when open, as in English */
[dir="rtl"] details.fold > summary::after { transform: translateY(-2px) rotate(-45deg); }
[dir="rtl"] details.fold[open] > summary::after { transform: translateY(2px) rotate(135deg); }
[dir="rtl"] .signout svg { transform: scaleX(-1); }
[dir="rtl"] .signin .code { text-align: center; }

/* ---------- 17  Desktop ---------- */

@media (min-width: 640px) {
    :root { --card-pad: 20px; --gutter: 24px; }
    .wrap { padding-top: var(--s6); }
    .save > button, .save > .btn { min-width: 180px; }
    .who { display: block; }
    .signout { gap: 6px; padding: 0 16px; }
    .signout span { position: static; width: auto; height: auto; overflow: visible; clip: auto; }
}
@media (max-width: 639.98px) {
    /* on a phone the button that finishes a form spans it */
    .save > button:not(.small), .save > .btn:not(.small) { width: 100%; }
}

/* wide enough for the navigation to sit in the top bar */
@media (min-width: 860px) {
    :root { --tabbar-h: 0px; --fs-title: 2.25rem; }
    .topbar { position: sticky; top: 0; z-index: 40; min-height: 64px; gap: var(--s6); padding-block: 0; padding-inline: max(24px, calc((100vw - 1120px) / 2)); }
    .tabbar { position: static; flex: 1 1 auto; justify-content: flex-start; gap: var(--s1); padding: 0; background: none; border: 0; box-shadow: none; }
    .tabbar a { flex: 0 0 auto; flex-direction: row; justify-content: center; max-width: none; min-height: 64px; padding: 0 14px; font-size: .875rem; color: #cfd3d9; }
    .tabbar a svg { display: none; }
    .tabbar a span { display: block; white-space: nowrap; }
    .tabbar a.on { color: var(--text-strong); }
    .tabbar a.on::before { top: auto; bottom: -1px; inset-inline: 14px; border-radius: 3px 3px 0 0; }
    .tabbar a:hover { color: var(--text-strong); }
    .tabbar a:active { background: none; }
    .wrap { padding-block: var(--s8) var(--s10); }
    .flash { bottom: var(--s6); }
    .signin { padding-top: min(12vh, 120px); }
}
/* between a tablet and a full desktop the name gives its room to the navigation */
@media (min-width: 860px) and (max-width: 1039.98px) {
    .who { display: none; }
}

@media (min-width: 640px) {
    /* buttons in a table row are compact, so four fit beside the row's text */
    td.actions > button, td.actions > .btn { padding-inline: 12px; font-size: .75rem; }
}
@media (min-width: 640px) and (pointer: fine) {
    button.small, .btn.small, td.actions > button, td.actions > .btn { min-height: 36px; }
}

@media (hover: hover) {
    .btn.ghost:hover { border-color: var(--text-strong); }
    .btn.warn:hover { background: var(--bad-bg); }
    .list a:hover b { color: var(--accent-text); }
    .lang:hover, .signout:hover { color: var(--text-strong); }
    .lang:hover span, .signout:hover::before { border-color: var(--text-strong); }
    .tabs a:hover, .nav.subnav a:hover { color: var(--text-strong); }
}

/* ---------- 18  Reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { transition-duration: .01ms !important; scroll-behavior: auto !important; }
    button:active, .btn:active { transform: none; }
    .flash { animation: flash-out .01ms linear 6s forwards; }
    .flash.bad { animation: none; }
}

/* ---------- 19  Screens ----------
   Components added when the screens were rebuilt on the system. They follow
   the same rules as everything above: tokens only, logical properties only,
   no page-specific rules. */

/* === Today, Clients, the client record === */

/* Page furniture */

/* .page-stat: the figure a record is about, beside its title (sessions left on a client's page).
   <div class="page-stat"><p class="figure">9 <span class="unit">sessions left</span></p><p class="muted">expires ...</p></div> */
.page-stat { flex: 0 0 auto; max-width: 100%; margin-inline-start: auto; text-align: end; }
.page-stat > p { margin: 0; }
/* .page-id: the title and the line under it as one block, so .page-stat sits beside both */
.page-id { flex: 1 1 0; min-width: 0; }
.page-id > .page-sub { margin: 2px 0 0; }

/* a line of buttons, or a fold, that stands on the page between the cards */
.wrap > .actions, .wrap > details.add, .wrap > details.fold { margin-bottom: var(--s3); }

/* Cards, notices */

/* inside a notice: an icon before its heading, a list of what it is about,
   and a closing link that is a line of its own (44px to touch) */
.notice b > .ico { width: 18px; height: 18px; margin-inline-end: 6px; vertical-align: -3px; }
.notice ul { margin: var(--s1) 0; padding: 0; padding-inline-start: 1.25em; }
.notice li { margin: 3px 0; }
.notice p { margin: var(--s2) 0 0; }
.notice:not(.account-reminder) > a:last-child { display: flex; align-items: center; width: fit-content; min-height: var(--tap); margin-bottom: calc(var(--s3) * -1); }
/* round T (L3): the link inside the WhatsApp-number reminder is part of its sentence */
.account-reminder a { display: inline; min-height: 0; margin: 0; }

/* details.fold.wide: a fold whose summary is the whole line, its chevron at the far end
   (a list of folds: one workout each) */
details.fold.wide > summary { display: flex; justify-content: space-between; width: 100%; font-size: var(--fs-md); font-weight: 400; }

/* the first group of a card needs no rule above it */
.card > fieldset:first-child { margin-top: 0; padding-top: 0; border-top: 0; }

/* Buttons */

/* buttons that share their line equally: the outcome pair of a session, the two ways to reach a client.
   With room to spare (a desktop) they keep a button's width instead of stretching. */
.actions.equal > *, .row-actions.equal > * { flex: 1 1 0; min-width: 0; padding-inline: var(--s2); }
@media (min-width: 640px) {
    .actions.equal > *, .row-actions.equal > * { flex: 0 1 200px; }
}
/* the action at the start, the way out (cancel, delete, decline) at the far end */
.actions.split, .row-actions.split { justify-content: space-between; }

/* Forms */

/* in the fold under a row the date needs more of the line than the time (its picker icon cut the year at 390px) */
@media (min-width: 350px) {
    .move-form > .cols { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: 0 var(--s2); }
}

/* One exercise: its name on a line, then sets, reps and weight side by side, each
   under a small label: <div class="ex"><label><span class="sr-only">Exercise</span><input></label>
   <label><span>Sets</span><input></label> x3</div>. */
.ex { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px var(--s2); margin: 0 0 var(--s3); padding: 0 0 var(--s3); border-bottom: 1px solid var(--line); }
.ex > label { margin: 0; }
.ex > label:first-child { grid-column: 1 / -1; }
.ex > label > span:not(.sr-only) { display: block; margin-bottom: 2px; color: var(--muted); font-size: .75rem; font-weight: 600; }
.ex input { padding-inline: 12px; }

/* Lists, rows */

/* .row-link: a row with its own buttons cannot be one <a>, so its first line is the link
   (time and client on a session row). It takes the room .row-end leaves; the chevron follows the text. */
.row-link { display: flex; align-items: center; gap: var(--s3); flex: 1 1 0; min-width: 0; min-height: var(--tap); border-radius: var(--r-sm); color: inherit; text-decoration: none; }
.row-link > .row-main { flex: 0 1 auto; }
.row-link::after { content: ""; flex: 0 0 auto; width: 8px; height: 8px; border-block-start: 2px solid var(--muted); border-inline-end: 2px solid var(--muted); transform: rotate(45deg); }
[dir="rtl"] .row-link::after { transform: rotate(-45deg); }
.row-link:active { background: var(--surface-2); }

/* .row-lead: what a row starts with, in the display face: the time of a session.
   Always its own left-to-right run, set against the start edge of the row. */
.row-lead { flex: 0 0 auto; min-width: 3.4em; font-family: var(--font-display); font-weight: var(--display-weight); font-size: var(--fs-xl); line-height: 1.2; letter-spacing: .01em; color: var(--text-strong); white-space: nowrap; }
[dir="rtl"] .row-lead { min-width: 4.4em; letter-spacing: 0; text-align: end; }

/* .badge-line: a word badge, then a line of facts beside it, wrapping under it when narrow
   (a task's priority, then its category and branch). A short mark at a line's start is .flag.
   <p class="badge-line muted"><span class="badge bad">Urgent</span><span>Maintenance &middot; Azaiba</span></p> */
.badge-line { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1) var(--s2); margin: 0 0 var(--s2); }
.badge-line > .badge { flex: 0 0 auto; }

/* live search results that may run long: the box scrolls, not the page */
.results.capped { max-height: 17.5rem; overflow-y: auto; overscroll-behavior: contain; }

/* Tiles, figures */

/* a figure that needs attention (two sessions left or fewer) */
.figure.warn { color: var(--warn); }

/* .tiles.lead: on a phone the first tile is the headline and takes the line, the rest pair up
   (five tiles leave no orphan, and an amount gets half the width) */
@media (max-width: 639.98px) {
    .tiles.lead { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .tiles.lead > :first-child { grid-column: 1 / -1; }
}
/* a tile that goes somewhere: the link fills the tile and carries a chevron */
.tiles .tile-go { position: relative; display: block; margin: -10px; padding: 10px; padding-inline-end: 28px; border-radius: inherit; color: inherit; text-decoration: none; }
.tiles .tile-go::after { content: ""; position: absolute; inset-inline-end: 12px; top: 50%; width: 8px; height: 8px; margin-top: -5px; border-block-start: 2px solid var(--muted); border-inline-end: 2px solid var(--muted); transform: rotate(45deg); }
[dir="rtl"] .tiles .tile-go::after { transform: rotate(-45deg); }
.tiles .tile-go:active { background: var(--surface-2); }

/* Tabs */

/* tabs can be a link target (client.php?tab=fitness#tabs), so a new tab opens at its content;
   on a desktop the sticky top bar must not cover them */
.tabs, .nav.subnav { scroll-margin-top: var(--s2); }
@media (min-width: 860px) {
    .tabs, .nav.subnav { scroll-margin-top: 80px; }
}

/* === Classes, Earnings, Payments, Hours, Profile, Meetings, Shoots === */

/* buttons that share their line equally are .actions.equal / .row-actions.equal (above) */
/* When: the date and time a card is about */

/* <div class="card-top"><p class="when"><span dir="ltr">Sun 04 Oct</span> <span dir="ltr">6:00pm</span></p><span class="badge warn">Full</span></div> */
.when { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--s2); margin: 0 0 var(--s1); font-family: var(--font-display); font-weight: var(--display-weight); font-size: 1.5rem; line-height: 1.2; letter-spacing: .01em; text-transform: var(--caps); color: var(--text-strong); }
.when > span + span { color: var(--accent-text); }
[dir="rtl"] .when { font-size: 1.25rem; letter-spacing: 0; }
/* a card's first line: the when at the start, one status badge at the far end */
.card-top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s2) var(--s3); margin-bottom: var(--s1); }
.card-top > .when { flex: 1 1 auto; min-width: 0; margin: 0; }
.card-top > .badge { flex: 0 0 auto; margin-top: 3px; }
.card-top + h2 { margin-bottom: var(--s1); }

/* Lines of actions */

/* the quiet, destructive one sits away from the others */
.actions > .apart, .row-actions > .apart { margin-inline-start: auto; }
/* a status under a row's lines (when it is too long for the row's end) */
.row-main > .badge { margin-top: var(--s1); }
/* a button inside a row's end keeps to the edge of the card */
.row-end > .btn.quiet { margin-inline-end: calc(var(--s2) * -1); }

/* one field with its button: <form class="field-row"><select></select><button class="btn ghost">Add</button></form>
   (.searchbar is the same thing heading a card: its space is below it, not above) */
.field-row, .searchbar { display: flex; align-items: center; gap: var(--s2); margin-top: var(--s3); }
.searchbar { margin: 0 0 var(--s3); }
.field-row > input, .field-row > select, .searchbar > input { flex: 1 1 0; min-width: 0; }
.field-row > button, .field-row > .btn, .searchbar > button, .searchbar > .btn { flex: 0 0 auto; }
.field > .field-row { margin-top: 0; }
.linkbox > .field-row { margin-top: var(--s2); }
/* on the narrowest phones a select keeps the whole line, so its words are not cut; its button goes under it */
@media (max-width: 349.98px) {
    .field-row:has(> select) { flex-wrap: wrap; }
    .field-row > select { flex-basis: 100%; }
    .field-row > select ~ button, .field-row > select ~ .btn { flex: 1 1 auto; }
}

/* Rows */

/* more about a row, on its own full-width line under the name and the figure */
.row-note { flex: 1 0 100%; min-width: 0; margin: 0; color: var(--muted); font-size: var(--fs-sm); }
.row-note.bad { color: var(--bad); font-weight: 600; }
/* round T (M5): what a field needs, said under it; and a warning before a choice is sent */
.field-msg { margin: 6px 0 0; font-size: var(--fs-sm); line-height: 1.4; }
.field-msg.bad { color: var(--bad); font-weight: 600; }
.field-msg.warn { padding: 8px 10px; border: 1px solid var(--warn-line); border-radius: var(--r-md); background: var(--warn-bg); color: var(--warn); }
[aria-invalid="true"] { border-color: var(--bad-line) !important; }
.chips:has([aria-invalid="true"]) > label > span { border-color: var(--bad-line); }
.row > .notice, .row > .meter { flex: 1 0 100%; min-width: 0; margin: 0; }
.row > .notice { margin-block: var(--s1); }
/* a figure at a row's end reads as one line with its unit; what it counts goes under it */
.row-end > .figure { white-space: nowrap; }

/* a fold at the foot of a card, under its list */
.card > details.add, .card > details.fold { margin-top: var(--s3); }
.card > .rows + details.add { margin-top: var(--s4); }
details.fold > .card:first-of-type, details.fold > summary + .rows { margin-top: var(--s2); }

/* The primary action as a fold */

/* <details class="add primary"><summary>Record a payment</summary><div class="card">form</div></details>
   closed, the summary is the page's primary button; open, it steps back so the form's own button leads */
details.add.primary > summary { display: flex; justify-content: center; width: 100%; min-height: 50px; border-color: transparent; background: linear-gradient(135deg, var(--btn-from), var(--btn-to)); color: #fff; }
details.add.primary[open] > summary { border-color: var(--line-strong); background: transparent; color: var(--text-strong); }
@media (min-width: 640px) {
    details.add.primary > summary { display: inline-flex; width: auto; min-width: 240px; }
}

/* Stepper: previous / label / next */

/* <div class="stepper"><a class="chip" href aria-label="Previous month">&larr;</a><h2>October 2026</h2><span></span></div>
   an empty span keeps the label centred when there is nothing to step to */
.stepper { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); margin-bottom: var(--s4); }
.stepper > .chip { flex: 0 0 auto; min-width: var(--tap); padding-inline: var(--s3); font-size: var(--fs-md); }
.stepper > span:empty { flex: 0 0 auto; width: var(--tap); }
.stepper > h2, .card .stepper > h2 { flex: 1 1 auto; min-width: 0; margin: 0; text-align: center; }

/* the screen's figure, then what explains it */
.figure + .muted, .figure + .sums { margin-top: var(--s2); }
.figure + .meter { margin-top: var(--s3); }

/* Sums: what a figure or a balance is made of */

/* Lines of label and amount, the amounts in a column at the far end.
   <dl class="sums"><dt>Package price</dt><dd>money</dd> ...</dl>
   or one <div> per line when the label is a badge and a long amount may drop under it:
   <dl class="sums"><div><dt><span class="badge warn">Waiting for approval</span></dt><dd>money</dd></div> ...</dl>
   .sums.ruled draws a rule above it (under a figure and its meter); it closes with the shared .total line. */
.sums { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s2) var(--s4); align-items: baseline; margin: 0 0 var(--s3); font-size: var(--fs-md); }
.sums dt { color: var(--muted); }
.sums dd { margin: 0; text-align: end; }
.sums > div { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 2px var(--s2); }
.sums > div dt { font-size: var(--fs-sm); }
.sums > div dd { margin-inline-start: auto; }
.sums.ruled { margin: var(--s3) 0; padding-top: var(--s3); border-top: 1px solid var(--line); }
.sums + .total { margin-top: var(--s3); }

/* Icon button */

/* a square button for one symbol; say what it does in aria-label */
.btn.icon { width: var(--tap); min-width: var(--tap); padding: 0; font-size: 1.125rem; letter-spacing: 0; }

/* Photo list: one photo per row, its place and its controls */

/* <ul class="photo-list"><li><img><b>Photo 2 of 4</b><button class="btn quiet warn small">Remove</button><div class="actions">move buttons</div></li></ul> */
.photo-list { display: grid; gap: var(--s2); margin: var(--s3) 0; padding: 0; list-style: none; }
.photo-list > li { display: grid; grid-template-columns: 72px minmax(0, 1fr) auto; align-items: center; gap: var(--s1) var(--s3); padding: var(--s2); padding-inline-end: var(--s3); border: 1px solid var(--line); border-radius: var(--r-md); background: var(--bg); }
.photo-list img { grid-row: 1 / span 2; display: block; width: 72px; height: 96px; border-radius: var(--r-sm); object-fit: cover; background: var(--field); }
.photo-list b { grid-column: 2; grid-row: 1; font-size: var(--fs-md); }
.photo-list li > .btn.quiet { grid-column: 3; grid-row: 1; margin-inline-end: calc(var(--s2) * -1); }
.photo-list .actions { grid-column: 2 / span 2; grid-row: 2; }
@media (max-width: 349.98px) {
    .photo-list > li { grid-template-columns: 56px minmax(0, 1fr) auto; column-gap: var(--s2); }
    .photo-list img { width: 56px; }
}
@media (min-width: 640px) {
    .photo-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* === Client app: Book, Pay, Progress, My details === */

/* Day strip:
   The next two weeks as buttons that set a date field: a week to a line on a
   phone, both weeks on one line where there is room.
   <div class="days" role="group"><button type="button" class="chip" data-date="2026-10-03" aria-pressed="false"><small>Sat</small><b>3</b></button>...</div> */
.days { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--s1); margin: var(--s3) 0 var(--s1); }
.days > .chip { flex-direction: column; gap: 1px; min-height: 56px; margin: 0; padding: 6px 0; border-radius: var(--r-md); }
.days > .chip small { font-size: var(--fs-xs); font-weight: 600; line-height: 1.2; color: var(--muted); }
.days > .chip b { font-size: var(--fs-lg); font-weight: 700; line-height: 1.2; color: inherit; }
.days > .chip[aria-pressed="true"] small { color: inherit; }
@media (max-width: 349.98px) {
    /* seven would be 33px wide: five keeps each one a thumb wide */
    .days { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}
@media (min-width: 640px) {
    .days { grid-template-columns: repeat(14, minmax(0, 1fr)); }
}

/* Labelled group:
   A small heading over a set of chips (Morning / Afternoon / Evening).
   <div class="group"><h3>Morning</h3><div class="chips">...</div></div> */
.group { margin: var(--s4) 0 0; }
.group > h3, .card .group > h3 { margin: 0 0 var(--s2); color: var(--muted); font-size: var(--fs-xs); font-weight: 700; letter-spacing: var(--track-wide); text-transform: var(--caps); }

/* the place a day's times load into; what is said about the chosen time follows it */
.slots ~ .notice { margin-top: var(--s4); }

/* Ends:
   One line with something at each end: the dates under the two ends of a chart.
   <div class="ends muted"><span>21 Aug</span><span>2 Oct</span></div> */
.ends { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s3); }
.ends > :last-child { text-align: end; }

/* Growing text field:
   A textarea that starts one line high and grows with what is typed (the page
   script sets its height): <textarea class="grow" rows="1"> */
textarea.grow { min-height: 3rem; resize: none; overflow: hidden; }

/* A row that keeps its words:
   .row-main.wide is never squeezed by what sits at the row's end: when a button
   or a long badge will not fit beside 11em of text (a 320px phone), it drops to
   the next line instead of breaking the date into three.
   <div class="row"><div class="row-main wide">...</div><div class="row-end"><button ...></div></div> */
.row-main.wide { flex-basis: 11em; }

/* Buttons inside a notice or under a list:
   A question with its two answers, or a callout with its one action. */
.notice > .actions, .notice > .save { margin-top: var(--s3); }
.rows + .actions, .meter + .rows, .tiles + .actions { margin-top: var(--s3); }

/* === Client app: progress photos and charts (round M) === */

/* Photo tile: a progress photo that opens large when tapped, in .photos or .compare.
   <figure><button type="button" class="photo-open" aria-label="Open the photo from 2 Oct"><img alt=""></button><figcaption>2 Oct</figcaption></figure> */
.photo-open { display: block; width: 100%; min-height: 0; padding: 0; border: 0; border-radius: 0; background: var(--field); cursor: zoom-in; }
.photo-open:active { transform: none; }
.photos figcaption, .compare figcaption { padding: var(--s2); color: var(--muted); font-size: var(--fs-sm); text-align: center; }
.photos figcaption b, .compare figcaption b { color: var(--text); margin-inline-end: var(--s1); }

/* Before and after: the first and the latest photo side by side.
   <div class="compare"><figure>...</figure><figure>...</figure></div> */
.compare { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); margin: var(--s2) 0 var(--s4); }
.compare figure { margin: 0; border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; background: var(--bg-2); }
.compare img { display: block; width: 100%; aspect-ratio: 3 / 4; object-fit: cover; }

/* Lightbox: one photo large over the page (a <dialog> opened with showModal()).
   <dialog class="lightbox"><img><p></p><form method="dialog" class="actions end"><button class="btn ghost small">Close</button></form></dialog> */
.lightbox { width: min(92vw, 640px); max-height: 92vh; padding: var(--s3); border: 1px solid var(--line-strong); border-radius: var(--r-lg); background: var(--surface); color: var(--text); box-shadow: var(--shadow-pop); }
.lightbox::backdrop { background: rgba(0, 0, 0, .8); }
.lightbox img { display: block; width: 100%; max-height: 70vh; object-fit: contain; border-radius: var(--r-md); background: var(--field); }
.lightbox p { margin: var(--s2) 0 0; color: var(--muted); font-size: var(--fs-sm); text-align: center; }
.lightbox .actions { margin-top: var(--s3); }

/* Charts in one card: each measure its own block, a rule between them.
   <div class="chart"><h3>Waist</h3><p class="muted">...</p><div dir="ltr"><svg class="trend">...</svg><div class="ends">...</div></div></div> */
.chart + .chart { margin-top: var(--s4); padding-top: var(--s3); border-top: 1px solid var(--line); }
.card .chart > h3 { margin-top: 0; }

/* === Coach pay statements (partner programme, 2026-10-10) === */

/* A figure's explanation on its own line under its label in .sums.
   <div><dt>Top-up<small class="help">share earned − basic</small></dt><dd>...</dd></div> */
.sums dt .help { display: block; margin-top: 2px; font-size: var(--fs-xs); }

/* Printing a pay statement (the browser's print to PDF): black on white, notices as bordered boxes, without the
   app's bars, buttons and the forms to answer it (.no-print) */
@media print {
    .topbar, .tabbar, .skip, .subnav, .actions, details.fold, .no-print, #msg, .account-reminder { display: none !important; }
    html, body, .wrap, .card, .notice { background: #fff !important; box-shadow: none !important; }
    body, body * { color: #000 !important; text-shadow: none !important; }
    .card, .notice { border: 1px solid #999 !important; break-inside: avoid; }
    .badge { background: #fff !important; border: 1px solid #666 !important; }
    .sums.ruled { border-color: #999 !important; }
}
