/* ============================================================================
   gym.css — the app's design system (Billiards Club edition).

   Lives in the RCL so BOTH hosts (web + WinForms BlazorWebView desktop) get the
   same look from one file, served as _content/Baize.Shared/css/gym.css.

   HOW THEMING WORKS NOW
   ---------------------
   The whole app is driven by ONE small set of "primitive" tokens (--c-*). Six
   themes (3 dark, 3 light) each set those primitives; everything else — the
   --gym-* component tokens, the --club-* floor tokens, and the Bootstrap /
   DevExpress variables the grids read — is bridged from the primitives in a
   single mapping block. So a theme is ~24 lines, and switching one attribute
   on <html> (data-club-theme) re-skins the entire application, custom screens
   and DevExpress components alike.

   RULES (kept from the project's conventions):
     - Colour comes from tokens, never hardcoded at the call site.
     - Font weight ceiling is 500 (medium). Never 600/700 — nothing reads bold.
     - Type ceiling is 1.32rem; body text is 11-12px.
     - Typeface is Segoe UI, with the bundled Inter behind it so the offline
       desktop host still has something if Segoe is ever missing.
   ========================================================================== */

/* ---------------------------------------------------------------------------
   0) TYPOGRAPHY — Segoe UI is the face; Inter (variable) is bundled locally and
      sits behind it in the stack so the offline desktop host still renders if
      Segoe is unavailable.
      Served from the RCL: _content/Baize.Shared/fonts/…, i.e. ../fonts from
      this stylesheet.
   --------------------------------------------------------------------------- */
@font-face {
  font-family: "InterVar";
  font-style: normal;
  font-weight: 100 700;
  font-display: swap;
  src: url("../fonts/inter-latin-var.woff2") format("woff2");
}

/* ---------------------------------------------------------------------------
   1) THEME PRIMITIVES — one block per theme. Felt Club is also the default
      (applied when no data-club-theme attribute is present yet).
   --------------------------------------------------------------------------- */

/* Dark · Felt Club — green-felt slate + brass gold accent (premium club).
   Surfaces from the dark-ops slate family; gold brightened for AA on dark. */
[data-club-theme="felt"], :root:not([data-club-theme]) {
  color-scheme: dark;
  --c-bg:#0f140f; --c-panel:#172018; --c-panel-2:#1d271e; --c-line:#2a362b; --c-line-2:#3d4c3e;
  --c-ink:#eef3ee; --c-ink-2:#c2ccc2; --c-ink-3:#889186;
  --c-accent:#e1b24c; --c-accent-ink:#1e1608; --c-accent-text:#ecc168; --c-accent-bg:rgba(225,178,76,.14);
  --c-success:#34d399; --c-success-bg:rgba(52,211,153,.15);
  --c-warn:#f5b849;    --c-warn-bg:rgba(245,184,73,.15);
  --c-info:#7cb2e8;    --c-info-bg:rgba(124,178,232,.15);
  --c-danger:#f0745c;  --c-danger-bg:rgba(240,116,92,.15);
  --c-neutral:#5a5245; --c-neutral-bg:rgba(150,137,122,.14);
  /* Occupancy heat ramp — one hue, light->dark, validated against this theme's own panel. */
  --c-heat-1:#806c33; --c-heat-2:#a0833b; --c-heat-3:#c19b44; --c-heat-4:#e6be67;
  --c-shadow:0 1px 3px rgba(0,0,0,.48); --c-overlay:rgba(6,10,6,.62);
  --c-glow:1;
}

/* Dark · Midnight — cold navy-slate + operational green (design-system default).
   Slate surfaces from the Financial/IoT dark palettes; green = status positive. */
[data-club-theme="midnight"] {
  color-scheme: dark;
  --c-bg:#0a0f1a; --c-panel:#121a2b; --c-panel-2:#182134; --c-line:#293449; --c-line-2:#3b4a63;
  --c-ink:#f1f5fb; --c-ink-2:#aeb9cc; --c-ink-3:#8593a8;
  --c-accent:#22c55e; --c-accent-ink:#052012; --c-accent-text:#4ade80; --c-accent-bg:rgba(34,197,94,.14);
  --c-success:#22c55e; --c-success-bg:rgba(34,197,94,.16);
  --c-warn:#fbbf24;    --c-warn-bg:rgba(251,191,36,.16);
  --c-info:#38bdf8;    --c-info-bg:rgba(56,189,248,.16);
  --c-danger:#f87171;  --c-danger-bg:rgba(248,113,113,.16);
  --c-neutral:#46536a; --c-neutral-bg:rgba(110,124,142,.16);
  /* Occupancy heat ramp — one hue, light->dark, validated against this theme's own panel. */
  --c-heat-1:#1a7346; --c-heat-2:#1d8e4e; --c-heat-3:#1faa56; --c-heat-4:#43ce76;
  --c-shadow:0 1px 3px rgba(0,0,0,.5); --c-overlay:rgba(2,5,10,.64);
  --c-glow:1;
}

/* Dark · Graphite — neutral slate + azure accent (the calm, sober option).
   Structural slate from the Financial dark palette; blue accent for focus. */
[data-club-theme="graphite"] {
  color-scheme: dark;
  --c-bg:#0e1117; --c-panel:#161b23; --c-panel-2:#1c222d; --c-line:#2a313d; --c-line-2:#3e4756;
  --c-ink:#edf1f7; --c-ink-2:#b4bdcb; --c-ink-3:#8590a0;
  --c-accent:#3b82f6; --c-accent-ink:#041226; --c-accent-text:#7aa9f7; --c-accent-bg:rgba(59,130,246,.14);
  --c-success:#34d399; --c-success-bg:rgba(52,211,153,.15);
  --c-warn:#fbbf24;    --c-warn-bg:rgba(251,191,36,.15);
  --c-info:#3b82f6;    --c-info-bg:rgba(59,130,246,.15);
  --c-danger:#f87171;  --c-danger-bg:rgba(248,113,113,.15);
  --c-neutral:#414a58; --c-neutral-bg:rgba(120,132,150,.15);
  /* Occupancy heat ramp — one hue, light->dark, validated against this theme's own panel. */
  --c-heat-1:#295191; --c-heat-2:#2f61b2; --c-heat-3:#3572d4; --c-heat-4:#5895f7;
  --c-shadow:0 1px 3px rgba(0,0,0,.45); --c-overlay:rgba(4,7,12,.62);
  --c-glow:1;
}

/* Light · Daylight — clean slate + accessible blue (the bright-room default).
   Surfaces & neutrals straight from the SaaS light palette. */
[data-club-theme="daylight"] {
  color-scheme: light;
  --c-bg:#f6f8fb; --c-panel:#ffffff; --c-panel-2:#eef2f7; --c-line:#e2e8f0; --c-line-2:#cbd5e1;
  --c-ink:#0f172a; --c-ink-2:#475569; --c-ink-3:#7a899c;
  --c-accent:#2563eb; --c-accent-ink:#ffffff; --c-accent-text:#2563eb; --c-accent-bg:rgba(37,99,235,.08);
  --c-success:#16a34a; --c-success-bg:rgba(22,163,74,.10);
  --c-warn:#d97706;    --c-warn-bg:rgba(217,119,6,.12);
  --c-info:#2563eb;    --c-info-bg:rgba(37,99,235,.10);
  --c-danger:#dc2626;  --c-danger-bg:rgba(220,38,38,.10);
  --c-neutral:#94a3b8; --c-neutral-bg:rgba(100,116,139,.12);
  /* Occupancy heat ramp — one hue, light->dark, validated against this theme's own panel. */
  --c-heat-1:#8eaef5; --c-heat-2:#6b95f1; --c-heat-3:#487cee; --c-heat-4:#2563eb;
  --c-shadow:0 1px 3px rgba(15,23,42,.08); --c-overlay:rgba(15,23,42,.35);
  --c-glow:0;
}

/* Light · Cream — warm hospitality ivory + brass/brown (the club in daylight).
   Warm neutrals from the bakery/luxury light palettes; gold #A16207 meets AA. */
[data-club-theme="cream"] {
  color-scheme: light;
  --c-bg:#fbf6ec; --c-panel:#fffdf9; --c-panel-2:#f3ebdc; --c-line:#eadfcb; --c-line-2:#d8c7a9;
  --c-ink:#3a2e1c; --c-ink-2:#6b5c45; --c-ink-3:#9a8b72;
  --c-accent:#a16207; --c-accent-ink:#ffffff; --c-accent-text:#8a5205; --c-accent-bg:rgba(161,98,7,.11);
  --c-success:#2f8f57; --c-success-bg:rgba(47,143,87,.12);
  --c-warn:#b45309;    --c-warn-bg:rgba(180,83,9,.13);
  --c-info:#3f7cae;    --c-info-bg:rgba(63,124,174,.12);
  --c-danger:#c0392b;  --c-danger-bg:rgba(192,57,43,.10);
  --c-neutral:#c3b79c; --c-neutral-bg:rgba(150,135,105,.14);
  /* Occupancy heat ramp — one hue, light->dark, validated against this theme's own panel. */
  --c-heat-1:#ceac7b; --c-heat-2:#bf9454; --c-heat-3:#b07b2e; --c-heat-4:#a16207;
  --c-shadow:0 1px 3px rgba(80,60,20,.10); --c-overlay:rgba(60,45,15,.35);
  --c-glow:0;
}

/* Light · Mint — fresh green light (calm, easy on the eyes).
   Soft green surfaces from the grocery/fresh palette; emerald #059669 meets AA. */
[data-club-theme="mint"] {
  color-scheme: light;
  --c-bg:#f0faf5; --c-panel:#ffffff; --c-panel-2:#e6f3ec; --c-line:#d8ede1; --c-line-2:#bedccc;
  --c-ink:#0f2a1e; --c-ink-2:#46604f; --c-ink-3:#7c9385;
  --c-accent:#059669; --c-accent-ink:#ffffff; --c-accent-text:#047857; --c-accent-bg:rgba(5,150,105,.10);
  --c-success:#059669; --c-success-bg:rgba(5,150,105,.12);
  --c-warn:#d97706;    --c-warn-bg:rgba(217,119,6,.12);
  --c-info:#0e7490;    --c-info-bg:rgba(14,116,144,.12);
  --c-danger:#dc2626;  --c-danger-bg:rgba(220,38,38,.10);
  --c-neutral:#a7c0b4; --c-neutral-bg:rgba(120,150,135,.13);
  /* Occupancy heat ramp — one hue, light->dark, validated against this theme's own panel. */
  --c-heat-1:#82bcab; --c-heat-2:#58a58f; --c-heat-3:#2e8e73; --c-heat-4:#047857;
  --c-shadow:0 1px 3px rgba(20,50,40,.08); --c-overlay:rgba(15,40,30,.35);
  --c-glow:0;
}

/* ---------------------------------------------------------------------------
   1b) NATIVE DEVEXPRESS SKINS — the chain runs the OTHER WAY.

      For a club palette the primitives above are literals which we then push
      into --bs-* / --dxbl-* (section 2), so DevExpress follows the club. When the
      operator picks a native DevExpress theme instead, theme.js removes
      data-club-theme and sets data-skin="dx", and this block DERIVES the very
      same --c-* primitives from whatever the theme publishes. Everything
      downstream — headings, KPI tiles, station tiles, pills, the rail — then
      recolours with the theme, because nothing downstream owns a literal.

      Two families publish different things, hence the two-step fallback:
        classic  →  --bs-*        (a full Bootstrap palette, its own surfaces)
        fluent   →  --DS-*        (design tokens; no --bs-* at all)
      The final literal is only ever reached in the instant before a stylesheet
      lands.

      Fluent surfaces come from the semantic tokens rather than the raw
      --DS-neutral ramp because the ramp is absolute: light mode picks
      neutral-10 and dark mode neutral-230, so a fixed index would invert in
      dark. surface-neutral-MUTED-rest is deliberately not used — it resolves to
      alpha 0, which would leave the page transparent.
   --------------------------------------------------------------------------- */
:root[data-skin="dx"] {
  --c-panel:   var(--bs-tertiary-bg, var(--DS-color-surface-neutral-default-rest, canvas));
  --c-bg:      var(--bs-body-bg,     var(--DS-color-surface-neutral-default-rest, canvas));
  --c-ink:     var(--bs-body-color,      var(--DS-color-content-neutral-default-rest, canvastext));
  --c-ink-2:   var(--bs-secondary-color, var(--DS-color-content-neutral-subdued-rest, graytext));
  --c-line:    var(--bs-border-color,    var(--DS-color-border-neutral-default-rest, buttonborder));

  /* Derived from the two the theme really owns, so they track light and dark
     without needing a variable per family. */
  --c-panel-2: color-mix(in srgb, var(--c-ink) 6%,  var(--c-panel));
  --c-line-2:  color-mix(in srgb, var(--c-ink) 20%, var(--c-panel));
  --c-ink-3:   color-mix(in srgb, var(--c-ink) 58%, transparent);

  --c-accent:      var(--bs-primary, var(--DS-primary-90, linktext));
  --c-accent-text: var(--bs-primary, var(--DS-primary-90, linktext));
  /* Text ON the accent. Picked from the theme's own extremes rather than a flat
     white, which disappears on a pale accent like Fluent Desert. */
  --c-accent-ink:  var(--bs-body-bg, var(--DS-color-surface-neutral-default-rest, canvas));
  --c-accent-bg:   color-mix(in srgb, var(--c-accent) 14%, transparent);

  --c-success: var(--bs-success, var(--DS-success-90, canvastext));
  --c-warn:    var(--bs-warning, var(--DS-warning-90, canvastext));
  --c-info:    var(--bs-info,    var(--DS-info-90,    canvastext));
  --c-danger:  var(--bs-danger,  var(--DS-danger-90,  canvastext));
  --c-neutral: var(--c-ink-3);
  --c-success-bg: color-mix(in srgb, var(--c-success) 14%, transparent);
  --c-warn-bg:    color-mix(in srgb, var(--c-warn)    14%, transparent);
  --c-info-bg:    color-mix(in srgb, var(--c-info)    14%, transparent);
  --c-danger-bg:  color-mix(in srgb, var(--c-danger)  14%, transparent);
  --c-neutral-bg: color-mix(in srgb, var(--c-ink)     10%, transparent);

  --c-shadow: 0 1px 3px color-mix(in srgb, var(--c-ink) 22%, transparent);
  --c-overlay: color-mix(in srgb, var(--c-ink) 55%, transparent);
  --c-glow: 0;

  /* The ramp again, but from what the DevExpress theme itself publishes rather than
     mixed off one accent — Bootstrap ships a real subtle/border/emphasis set, and Fluent
     ships a numbered ramp, so use them and only fall back to mixing.
     These are declared AFTER the bridge maps the club versions, and win by being later
     with equal specificity. */
  --gym-brand-500: var(--bs-primary,               var(--DS-primary-90,  var(--c-accent)));
  --gym-brand-50:  var(--bs-primary-bg-subtle,     var(--DS-primary-20,  var(--c-accent-bg)));
  --gym-brand-300: var(--bs-primary-border-subtle, var(--DS-primary-60,  color-mix(in srgb, var(--c-accent) 45%, var(--c-panel))));
  --gym-brand-600: var(--bs-link-hover-color,      var(--DS-primary-100, var(--c-accent)));
  --gym-brand-700: var(--bs-primary-text-emphasis, var(--DS-primary-120, color-mix(in srgb, var(--c-accent) 65%, var(--c-ink))));

  /* THE TOP BAR CARRIES THE THEME'S OWN COLOUR, not a shared neutral. brand-700 is the
     primary darkened for text, so it is dark enough for light labels and unmistakably
     that theme's hue. (The --gym-rail-* names date from when this was a left rail; the
     bar reads them now.) Scoped to DevExpress skins only: the club palettes own their
     chrome — felt's green, cream's ivory — and must not be repainted. */
  --gym-rail-bg: var(--gym-brand-700);
  --gym-rail-ink: color-mix(in srgb, var(--c-panel) 92%, transparent);
  --gym-rail-ink-dim: color-mix(in srgb, var(--c-panel) 58%, transparent);
  --gym-rail-line: color-mix(in srgb, var(--c-panel) 16%, transparent);
  --gym-rail-active: color-mix(in srgb, var(--gym-brand-500) 34%, transparent);

  /* Page titles take the theme's deep brand shade instead of plain body ink. */
  --gym-heading: var(--gym-brand-700);
}

/* DARK DevExpress skins need the ramp to flip. Bootstrap redefines
   --bs-primary-text-emphasis as a LIGHTENED primary under [data-bs-theme=dark], so the
   classic themes handle themselves. Fluent's --DS-primary-* is an absolute ramp that does
   not move with the mode sheet, so its 120 step stayed a deep shade and painted a dark
   heading on a dark page. Step 60 is the light end of the same hue. */
:root[data-skin="dx"][data-bs-theme="dark"] {
  --gym-brand-700: var(--bs-primary-text-emphasis, var(--DS-primary-60, color-mix(in srgb, var(--c-accent) 60%, var(--c-ink))));
  /* The rail wants a dark brand tint behind light labels, not the lightened text shade. */
  --gym-rail-bg: color-mix(in srgb, var(--gym-brand-500) 22%, var(--c-bg));
  --gym-rail-ink: var(--c-ink);
  --gym-rail-ink-dim: var(--c-ink-3);
}

/* ---------------------------------------------------------------------------
   2) BRIDGE — map primitives onto the tokens the whole app already uses, plus
      the Bootstrap/DevExpress variables so grids & inputs follow the palette.

      Specificity note: :root[data-club-theme] (0,2,0) beats the DevExpress
      base's html[data-bs-theme] (0,1,1) for these same variables, and gym.css
      is loaded AFTER the DevExpress stylesheet, so our values win. The host
      page sets data-club-theme synchronously before first paint.

      THE PUSH HALF IS CLUB-ONLY. Writing --bs-* from --c-* is what makes the
      DevExpress controls wear the club palette — but under a native DevExpress
      skin those same writes would overwrite the theme's own palette with values
      derived from it, a loop that resolves to nothing. So the --bs-* / --dxbl-*
      writes are scoped to club skins; the --gym-* mapping below is not, because
      it is one-way and both kinds of skin need it.
   --------------------------------------------------------------------------- */
:root[data-club-theme], :root:not([data-skin]) {
  /* Bootstrap / DevExpress core surfaces so DX components adopt the palette */
  --bs-body-bg: var(--c-bg);
  --bs-body-color: var(--c-ink);
  --bs-border-color: var(--c-line);
  --bs-secondary-bg: var(--c-panel-2);
  --bs-tertiary-bg: var(--c-panel);
  --bs-emphasis-color: var(--c-ink);
  --dxbl-client-component-palette-primary: var(--c-accent);
  --dxbl-client-component-palette-success: var(--c-success);
  --dxbl-client-component-palette-warning: var(--c-warn);
  --dxbl-client-component-palette-info: var(--c-info);
  --dxbl-client-component-palette-danger: var(--c-danger);

  /* Popup and dropdown SURFACES. The club palettes never set these, so dialogs and open
     combo lists kept the stock DevExpress grey on a green felt page.

     Setting the VARIABLES rather than fighting the selectors is the only thing that works
     here: DevExpress paints the popup from
         .dxbl-modal > .dxbl-modal-root > .dxbl-popup            (0,3,0)
         .dxbl-modal > .dxbl-modal-root > .dxbl-popup > .dxbl-modal-content   (0,4,0)
     so any sane class-based override loses on specificity. Feeding --dxbl-popup-bg lets
     DevExpress paint its own element with our colour.

     Not set for the DevExpress skins: there the theme's own value is the right one. */
  --dxbl-edit-dropdown-bg: var(--c-panel);
  --dxbl-edit-dropdown-color: var(--c-ink);

  /* Brand ramp, club flavour: mixed off the palette's own accent. The DevExpress skins
     build the same five tokens from what their stylesheet publishes (section 1b). */
  --gym-brand-500: var(--c-accent);
  --gym-brand-50:  var(--c-accent-bg);
  --gym-brand-300: color-mix(in srgb, var(--c-accent) 45%, var(--c-panel));
  --gym-brand-600: var(--c-accent-text);
  --gym-brand-700: var(--c-accent-text);

  /* Club palettes own their rail and their heading colour — felt's green, cream's ivory —
     so these stay neutral here and only the DevExpress skins brand-tint them. */
  --gym-rail-bg: var(--c-panel);
  --gym-rail-ink: var(--c-ink-2);
  --gym-rail-ink-dim: var(--c-ink-3);
  --gym-rail-line: var(--c-line);
  --gym-rail-active: var(--c-accent-bg);
  --gym-heading: var(--c-ink);
}

/* The one-way half: every skin needs these, club or DevExpress. */
:root[data-club-theme], :root[data-skin="dx"], :root:not([data-skin]) {
  /* --gym-* component tokens */
  --gym-bg: var(--c-bg);
  --gym-surface: var(--c-panel);
  --gym-surface-2: var(--c-panel-2);
  --gym-border: var(--c-line);
  --gym-border-strong: var(--c-line-2);
  --gym-ink: var(--c-ink);
  --gym-ink-soft: var(--c-ink-2);
  --gym-ink-mute: var(--c-ink-3);
  --gym-danger: var(--c-danger);   --gym-danger-bg: var(--c-danger-bg);
  --gym-success: var(--c-success); --gym-success-bg: var(--c-success-bg);
  --gym-warn: var(--c-warn);       --gym-warn-bg: var(--c-warn-bg);
  --gym-info: var(--c-info);       --gym-info-bg: var(--c-info-bg);
  --gym-accent: var(--c-accent);
  --gym-accent-ink: var(--c-accent-ink);
  --gym-accent-bg: var(--c-accent-bg);
  /* The accent as TEXT on a surface. Not the same colour as --gym-accent on every
     theme: cream's brass reads #a16207 as a fill but needs the darker #8a5205 to
     clear AA as type, and felt's gold goes the other way. Use this for words. */
  --gym-accent-text: var(--c-accent-text);
  --gym-shadow: var(--c-shadow);

  /* Brand mark (the 8-ball on the login card and the sidebar). Derived rather than
     literal so it stays legible on every skin: the ball takes the ink colour, the
     spot and the numeral take the surface behind it, so the two can never collide.
     On a dark skin that reads as a light ball on dark — inverted from a real 8-ball,
     but the alternative is a black ball vanishing into a black card. */
  --gym-mark-ball: var(--c-ink);
  --gym-mark-spot: var(--c-panel);
  --gym-mark-edge: color-mix(in srgb, var(--c-panel) 30%, transparent);

  /* --club-* floor tokens (consumed by billiards.css) */
  --club-bg: var(--c-bg);
  --club-panel: var(--c-panel);
  --club-panel-2: var(--c-panel-2);
  --club-line: var(--c-line);
  --club-line-strong: var(--c-line-2);
  --club-ink: var(--c-ink);
  --club-ink-soft: var(--c-ink-2);
  --club-ink-mute: var(--c-ink-3);
  --club-accent: var(--c-accent);
  --club-accent-ink: var(--c-accent-ink);
  --club-accent-text: var(--c-accent-text);
  --club-accent-bg: var(--c-accent-bg);
  --club-brass: var(--c-accent);
  --club-success: var(--c-success); --club-success-bg: var(--c-success-bg);
  --club-warn: var(--c-warn);       --club-warn-bg: var(--c-warn-bg);
  --club-info: var(--c-info);       --club-info-bg: var(--c-info-bg);
  --club-danger: var(--c-danger);   --club-danger-bg: var(--c-danger-bg);
  --club-neutral: var(--c-neutral); --club-neutral-bg: var(--c-neutral-bg);
  /* Occupancy heat ramp. Sequential = magnitude, so it is ONE hue stepping light->dark,
     never a rainbow. The four steps are literals per theme rather than a color-mix off
     the accent because the accents differ too much in lightness: a single mix formula
     that cleared the 2:1 light-end contrast on felt collapsed the step gaps on graphite
     and mint. Each set is validated on its own theme's panel for monotone lightness,
     adjacent step separation, light-end contrast and hue spread. */
  /* THE TABLE ITSELF. A billiards cloth is green in every club on earth, so these are
     object colours rather than theme colours and they do not change with the skin —
     recolouring the cloth to match a blue theme would stop it reading as a table. They
     are still tokens so a club with red cloth can say so in one place. */
  --club-felt:        #1f7a4d;
  --club-felt-snooker:#14603c;
  --club-rail:        #5b3a21;
  --club-pocket:      #10140f;
  --club-ball-cue:    #f4f1e6;
  --club-ball-1:      #d64545;
  --club-ball-2:      #e0a32e;
  --club-ball-3:      #3f7cae;
  --club-ball-4:      #efe7d2;
  --club-felt-line:   rgba(255,255,255,.34);
  /* The console corner of the club: dark plastic on a screen-lit backdrop. */
  --club-console:     #2b3038;
  --club-console-2:   #1a1e24;
  --club-console-mk:  #8f98a6;

  --club-heat-1: var(--c-heat-1);
  --club-heat-2: var(--c-heat-2);
  --club-heat-3: var(--c-heat-3);
  --club-heat-4: var(--c-heat-4);
  --club-overlay: var(--c-overlay);
  --club-shadow: var(--c-shadow);

  /* Spacing / radius / type scale */
  --gym-1: .25rem; --gym-2: .5rem; --gym-3: .75rem; --gym-4: 1rem; --gym-5: 1.5rem; --gym-6: 2rem;
  --gym-radius:  .625rem;
  --gym-radius-s:.4rem;
  --gym-fs-xs: 0.69rem; --gym-fs-sm: 0.77rem; --gym-fs-md: 0.88rem; --gym-fs-lg: 1.01rem; --gym-fs-xl: 1.32rem;

  /* Motion — expo-out entrance curve, subtle by design-system guidance. */
  --gym-ease: cubic-bezier(.16, 1, .3, 1);
}

/* Make the app surface actually paint the theme background (both hosts) and set the
   type system. Inter with tabular figures so money columns and timers never jitter. */
html, body {
  /* margin:0 is load-bearing and must NOT be left to Bootstrap. The classic DevExpress
     themes bundle Bootstrap's reboot, which zeroes it; the Fluent sheets do not, so under
     any Fluent skin the browser default body margin of 8px came back. With .app-shell at
     height:100vh that made the document 100vh + 16px — a permanent 16px overflow and the
     scrollbar down the right-hand border, at every window size. */
  margin: 0; padding: 0;
  background: var(--c-bg); color: var(--c-ink);
  font-family: "Segoe UI", "Segoe UI Variable Text", "InterVar", "Inter", -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
}
.gym-num, .bc-timer, .bc-amt, .bc-kpi-val, .bc-dock-big, .bc-trow, .bc-qrow,
[class*="tabular"] { font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------------------
   3) COMPONENT CLASSES — weight ceiling 500, type ceiling 1.32rem.
   --------------------------------------------------------------------------- */

/* Page scaffold */
.gym-page        { padding: var(--gym-5); max-width: 1600px; }
.gym-page-head   { margin-bottom: var(--gym-4); }
.gym-page-head h1,
.gym-page-title  { font-size: var(--gym-fs-xl); font-weight: 500; margin: 0; color: var(--gym-ink); letter-spacing: -.01em; }
.gym-page-sub    { color: var(--gym-ink-soft); font-size: var(--gym-fs-sm); margin: var(--gym-1) 0 0; }
.gym-page-bar    { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--gym-4); flex-wrap: wrap; }
.gym-actions     { display: flex; align-items: center; gap: var(--gym-2); flex-wrap: wrap; }

/* Card / panel */
.gym-card {
  background: var(--gym-surface);
  border: 1px solid var(--gym-border);
  border-radius: var(--gym-radius);
  box-shadow: var(--gym-shadow);
  padding: var(--gym-4);
}
.gym-card + .gym-card { margin-top: var(--gym-4); }
.gym-card-head  { display: flex; align-items: center; justify-content: space-between; gap: var(--gym-3); margin-bottom: var(--gym-3); }
.gym-card-title { font-size: var(--gym-fs-lg); font-weight: 500; margin: 0; }
.gym-card-sub   { color: var(--gym-ink-soft); font-size: var(--gym-fs-sm); }
.gym-card-flush { padding: 0; overflow: hidden; }

/* Toolbar / filter strip */
.gym-toolbar { display: flex; align-items: flex-end; gap: var(--gym-3); flex-wrap: wrap; }
.gym-field   { display: flex; flex-direction: column; gap: var(--gym-1); }
.gym-field > label { font-size: var(--gym-fs-sm); color: var(--gym-ink-soft); }
.gym-field-sm  { width: 9rem; }
.gym-field-md  { width: 14rem; }
.gym-field-lg  { width: 22rem; }
.gym-field-grow{ flex: 1 1 16rem; min-width: 12rem; }

/* Stat tiles */
.gym-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: var(--gym-3); }
.gym-stat {
  background: var(--gym-surface);
  border: 1px solid var(--gym-border);
  border-left: 3px solid var(--gym-accent);
  border-radius: var(--gym-radius);
  padding: var(--gym-3) var(--gym-4);
}
.gym-stat-value { font-size: var(--gym-fs-xl); font-weight: 500; line-height: 1.15; color: var(--gym-ink); font-variant-numeric: tabular-nums; }
.gym-stat-label { font-size: var(--gym-fs-sm); color: var(--gym-ink-soft); margin-top: var(--gym-1); }
.gym-stat-foot  { font-size: var(--gym-fs-xs); color: var(--gym-ink-mute); margin-top: var(--gym-1); }
.gym-stat-danger  { border-left-color: var(--gym-danger); }
.gym-stat-success { border-left-color: var(--gym-success); }
.gym-stat-warn    { border-left-color: var(--gym-warn); }
.gym-stat-clickable { cursor: pointer; }
.gym-stat-clickable:hover { border-color: var(--gym-border-strong); box-shadow: var(--gym-shadow); }

/* Banners */
.gym-banner { border-radius: var(--gym-radius-s); padding: var(--gym-2) var(--gym-3); font-size: var(--gym-fs-sm); }
.gym-banner + .gym-banner { margin-top: var(--gym-2); }
.gym-banner-error   { background: var(--gym-danger-bg);  color: var(--gym-danger); }
.gym-banner-success { background: var(--gym-success-bg); color: var(--gym-success); }
.gym-banner-warn    { background: var(--gym-warn-bg);    color: var(--gym-warn); }
.gym-banner-info    { background: var(--gym-info-bg);    color: var(--gym-info); }

/* Selectable tiles */
.gym-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: var(--gym-3); }
.gym-tile {
  background: var(--gym-surface);
  border: 1px solid var(--gym-border);
  border-radius: var(--gym-radius);
  padding: var(--gym-3);
  cursor: pointer;
  display: flex; gap: var(--gym-3); align-items: flex-start;
  transition: border-color .12s ease, box-shadow .12s ease, transform .12s ease;
}
.gym-tile:hover     { border-color: var(--gym-border-strong); box-shadow: var(--gym-shadow); transform: translateY(-1px); }
.gym-tile-active    { border-color: var(--gym-accent); box-shadow: 0 0 0 1px var(--gym-accent) inset; }
.gym-tile-ico       { font-size: 1.01rem; color: var(--gym-accent); line-height: 1.2; }
.gym-tile-name      { font-weight: 500; font-size: var(--gym-fs-md); }
.gym-tile-desc      { color: var(--gym-ink-soft); font-size: var(--gym-fs-xs); margin-top: 2px; line-height: 1.35; }

/* Section label */
.gym-section {
  font-size: var(--gym-fs-xs); font-weight: 500; letter-spacing: .04em;
  text-transform: uppercase; color: var(--gym-ink-mute); margin: var(--gym-5) 0 var(--gym-2);
}
.gym-section:first-child { margin-top: 0; }

/* Empty state */
.gym-empty { text-align: center; color: var(--gym-ink-soft); padding: var(--gym-6) var(--gym-4); }
.gym-empty-ico  { font-size: 1.32rem; color: var(--gym-ink-mute); display: block; margin-bottom: var(--gym-2); }
.gym-empty-text { font-size: var(--gym-fs-sm); }

/* Utilities */
.gym-muted   { color: var(--gym-ink-soft); }
.gym-mute-xs { color: var(--gym-ink-mute); font-size: var(--gym-fs-xs); }
.gym-num     { font-variant-numeric: tabular-nums; }
.gym-grow    { flex: 1 1 auto; }
.gym-row     { display: flex; align-items: center; gap: var(--gym-2); }
.gym-split   { display: flex; align-items: center; justify-content: space-between; gap: var(--gym-2); }
.gym-split-view { display: grid; grid-template-columns: minmax(0, 1fr) 22rem; gap: var(--gym-4); align-items: start; }
@media (max-width: 1200px) { .gym-split-view { grid-template-columns: 1fr; } }

/* ---------------------------------------------------------------------------
   3b) DEVEXPRESS COMPONENT ALIGNMENT — so every form field, dropdown, grid and
       button across all pages matches the club design: Inter type, our surfaces,
       rounded corners, accent focus. Colours flow from the --bs-* / --dxbl-* bridge
       above; these rules add the type + shape the base theme doesn't carry.
   --------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
   MODULE BAR — the top level of navigation. Modules run across here; the rail
   below-left carries the pages of whichever one is lit. Same surface as the
   rail so the two read as one frame around the page, which is what makes the
   theme's brand colour the largest thing on screen.
   --------------------------------------------------------------------------- */
.mod-bar {
  flex: none;
  display: flex; align-items: center; gap: .35rem;
  height: 3rem; padding: 0 .6rem;
  /* Plain surface, not the theme's brand colour. A saturated band across the top competed
     with the page for attention all shift; the theme still shows in the headings, the KPI
     stripes and every control. */
  background: var(--gym-surface);
  color: var(--gym-ink);
  border-bottom: 1px solid var(--gym-border);
}

.mod-toggle {
  flex: none; width: 2rem; height: 2rem; border-radius: var(--gym-radius-s, .4rem);
  color: var(--gym-ink); font-size: 0.92rem;
}
.mod-toggle:hover { background: color-mix(in srgb, var(--gym-ink) 12%, transparent); }

.mod-brand { display: flex; align-items: center; gap: .5rem; padding: 0 .5rem 0 .3rem; flex: none; }
.mod-brand-icon { flex: none; }
.mod-brand-text {
  font-size: 0.81rem; font-weight: 400; letter-spacing: -.01em; white-space: nowrap;
  color: var(--gym-ink);
}

/* The tabs themselves. A module is a set of routes, not a route, so these are buttons and
   the active one is decided by matching the URL — see AppModules.Active. */
/* NOT IN USE. No markup renders .mod-tab — DxMenu renders .mod-item, which is styled
   further down. Kept because it is the hand-built fallback if the bar ever stops using
   DxMenu; weights held at 400 so a revival matches the rest of the bar. */
.mod-tabs { display: flex; align-items: center; gap: .2rem; min-width: 0; overflow: hidden; margin-left: .4rem; }
.mod-tab {
  display: flex; align-items: center; gap: .45rem;
  padding: .45rem .8rem; border-radius: var(--gym-radius-s, .4rem);
  font-size: 0.77rem; font-weight: 400; white-space: nowrap;
  color: var(--gym-rail-ink-dim, var(--gym-ink-mute));
  position: relative; transition: background .12s ease, color .12s ease;
}
.mod-tab:hover { background: color-mix(in srgb, var(--gym-rail-ink, var(--gym-ink)) 10%, transparent);
                 color: var(--gym-rail-ink, var(--gym-ink)); }
.mod-tab.active { color: var(--gym-rail-ink, var(--gym-ink)); font-weight: 400;
                  background: var(--gym-rail-active, var(--gym-accent-bg)); }
/* An underline as well as the tint, so the active module survives a colour-blind read. */
.mod-tab.active::after {
  content: ""; position: absolute; left: .55rem; right: .55rem; bottom: -1px;
  height: 2px; border-radius: 2px 2px 0 0; background: var(--gym-brand-500, var(--gym-accent));
}
.mod-tab-ico { font-size: 0.84rem; }

/* DxMenu brings its own surface and spacing; strip both so the modules read as tabs on
   the bar rather than a component dropped onto it. */
/* flex:0 1 auto, not min-width:0 — DxMenu measures its container to decide whether to
   collapse, and a zero-width container makes it fold every module away. */
.mod-menu { background: transparent; border: none; margin-left: .4rem; flex: 0 1 auto; }
.mod-menu .dxbl-menu-horizontal { background: transparent; border: none; }

/* THE CLICKABLE ELEMENT IS A BUTTON. DevExpress renders each item as
       li.mod-item > dxbl-menu-item > button.dxbl-btn.dxbl-btn-text-none
   There is no .dxbl-menu-item-link in this version, which is why earlier attempts at the
   tab styling and the active state matched nothing at all.

   !important, scoped to this bar: DevExpress's own button rules outrank any class chain of
   ours, and they won under some skins and lost under others — dark tab labels on a
   saturated bar under Fluent while Felt looked fine. These are our own chrome, so forcing
   them here is contained. */
.mod-menu .dxbl-btn {
  color: var(--gym-ink-soft) !important;
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  border-radius: var(--gym-radius-s, .4rem) !important;
  padding: .45rem .8rem !important;
  font-size: 0.77rem;
  font-weight: 400 !important;
}
.mod-menu .dxbl-btn:hover { color: var(--gym-accent) !important; }

/* The ICONS carry the theme on every module, not just the active one — DevExpress renders
   them as a span.dxbl-image inside the button. Labels stay ink so the bar keeps its
   contrast; the colour lives in the icon and in whichever module is open. */
.mod-menu .dxbl-btn .dxbl-image { color: var(--gym-accent) !important; }
/* Active module: the accent on the label, no filled box and no border — these are flat
   dropdown buttons. The weight change carries it for a colour-blind read. */
.mod-item.active .dxbl-btn {
  color: var(--gym-accent) !important;
  font-weight: 400 !important;
  background: transparent !important;
  position: relative;
}
/* An underline as well as the tint, so the active module survives a colour-blind read.
   There is a rule saying exactly that further up for .mod-tab — but .mod-tab is not in
   any markup; DxMenu renders .mod-item. With the weight now flat at 400 the accent was
   the ONLY thing marking the open module, so this is the channel that has to carry it. */
.mod-item.active .dxbl-btn::after {
  content: ""; position: absolute; left: .5rem; right: .5rem; bottom: 0;
  height: 2px; border-radius: 2px 2px 0 0; background: var(--gym-accent);
}

/* The dropdown is a popup and takes the popup surface set per skin. Its items carry the
   theme the same way the bar does: accent icons throughout, accent on hover, and the page
   you are actually on marked in accent at semibold. */
.mod-subitem .dxbl-btn { font-weight: 400 !important; }
.mod-subitem .dxbl-btn .dxbl-image { color: var(--gym-accent) !important; }
.mod-subitem .dxbl-btn:hover {
  background: var(--gym-accent-bg) !important;
  color: var(--gym-accent) !important;
}
.mod-subitem.current .dxbl-btn {
  color: var(--gym-accent) !important; font-weight: 400 !important;
  background: var(--gym-accent-bg) !important;
  box-shadow: inset 2px 0 0 var(--gym-accent) !important;   /* not colour alone */
}

/* Skin picker list: same treatment, so the menu and the theme list match. */
.club-skin .dxbl-btn:hover, .dxbl-drop-down-button-item:hover {
  background: var(--gym-accent-bg) !important;
  color: var(--gym-accent) !important;
}

.mod-spacer { flex: 1 1 auto; }

/* ── where you are ────────────────────────────────────────────────────────
   The page name and its live detail, sitting immediately after the module tabs
   so "what can I reach" and "what am I looking at" read as one line. Replaces
   the title block each page used to draw for itself.

   A rule separates it from the tabs rather than a heavier device: the bar is
   deliberately a plain surface (see .mod-bar) and a second coloured band here
   would undo that. The theme shows in the name's accent tint. */
.mod-page {
  display: flex; align-items: baseline; gap: .5rem;
  min-width: 0; flex: 0 1 auto;
  padding-left: .75rem; margin-left: .4rem;
  border-left: 1px solid var(--gym-border);
}
.mod-page-name {
  font-size: 0.79rem; font-weight: 400; color: var(--gym-accent-text, var(--gym-accent));
  white-space: nowrap;
}
/* The detail is the part that can run long, so it is the part that truncates.
   Same accent as the name, and NO opacity fade: --gym-accent-text is picked to clear
   AA as type on this surface, and dimming it would spend that margin on 12px text.
   The hierarchy comes from size and weight instead — .78rem regular under .9rem
   semibold — which costs nothing in contrast. */
.mod-page-sub {
  font-size: 0.69rem; font-weight: 400;
  color: var(--gym-accent-text, var(--gym-accent));
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  min-width: 0; font-variant-numeric: tabular-nums;
}

/* Narrow: the figures go before the name does — the name is what orients you.
   760px, not 900: the figures were disappearing on a perfectly roomy window. Between
   here and there the ellipsis on .mod-page-sub does the work, which degrades far more
   gracefully than dropping the line outright. */
@media (max-width: 760px) { .mod-page-sub { display: none; } }
@media (max-width: 560px) { .mod-page { display: none; } }


.mod-user {
  display: flex; align-items: center; gap: .45rem; flex: none;
  padding: 0 .5rem; font-size: 0.72rem;
  color: var(--gym-ink-mute);
}
.mod-user-name { white-space: nowrap; max-width: 12rem; overflow: hidden; text-overflow: ellipsis; }

/* The skin picker is the accent dot itself — one fixed swatch, so it needs no responsive
   step and can never be squeezed out. (An earlier version was a named combo that CSS hid
   below 1200px, leaving the picker unreachable on a narrower window.) */
.mod-theme { flex: none; display: inline-flex; }
.mod-signout {
  flex: none; width: 2rem; height: 2rem; border-radius: var(--gym-radius-s, .4rem);
  color: var(--gym-ink-mute); font-size: 0.88rem;
}
.mod-signout:hover { color: var(--gym-danger); background: color-mix(in srgb, var(--gym-danger) 14%, transparent); }

/* Narrow: the tab labels go first (icons still identify them), then the brand wordmark and
   the user name. The bar never wraps — it is the frame, not content. */
@media (max-width: 1200px) {
  .mod-brand-text { display: none; }
  .mod-user-name { display: none; }
}
@media (max-width: 992px) {
  .mod-menu .dxbl-menu-item-text-container { display: none; }
  .mod-menu .dxbl-btn { padding: .45rem .6rem; }
}

/* ---------------------------------------------------------------------------
   SCROLLBARS. Nothing styled these, so the browser painted its own — which on a
   dark skin is the black strip down the right-hand border. They are chrome like
   everything else and take the theme: a thin bar, a transparent track so it does
   not read as a band, and a thumb from the palette.

   Both syntaxes on purpose: scrollbar-color is the standard one (Firefox, and
   Chrome 121+), ::-webkit-scrollbar covers older Chrome and Edge, which is what
   a shop counter is likely to be running.
   --------------------------------------------------------------------------- */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--c-line-2) transparent;
}
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--c-line-2);
  border-radius: 6px;
  /* Inset by a transparent border so the thumb reads as a floating bar rather than
     a full-width strip against the page edge. */
  border: 2px solid transparent;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--c-ink-3); background-clip: content-box; }
::-webkit-scrollbar-corner { background: transparent; }

/* Everything DevExpress renders takes OUR face and OUR size, not its packaged ones.
   font-size was missing here, which is why the grids on the report pages stayed at the
   DevExpress default while the rest of the app got smaller — the inventory table was the
   most obvious case. */
.dxbl-input, .dxbl-text-edit, .dxbl-combobox, .dxbl-spin-edit, .dxbl-memo,
.dxbl-date-edit, .dxbl-btn, .dxbl-grid, .dxbl-checkbox, .dxbl-tabs, .dxbl-listbox,
.dxbl-popup, .dxbl-modal { font-family: inherit; }

/* DevExpress drives its own typography from variables, and its selectors outrank any
   sane class chain of ours (the same lesson as --dxbl-popup-bg further down). Feeding the
   variables is what actually works: overriding .dxbl-grid-header directly left the header
   at 14px while the body text around it was 11.5px. */
/* ON THE ELEMENT, NOT ON :root. DevExpress declares these variables on .dxbl-grid
   itself, so a :root value never reaches them — setting them there actually pushed the
   grid from 11.5px UP to its 14px default. Exactly the trap documented for
   --dxbl-popup-bg further down. */
.dxbl-grid {
  --dxbl-grid-font-size: 11.5px;
  --dxbl-grid-header-font-weight: 500;
  --dxbl-grid-footer-font-weight: 500;
  --dxbl-grid-group-footer-font-weight: 500;
}
.dxbl-popup, .dxbl-modal {
  --dxbl-popup-font-size: 11.5px;
  --dxbl-popup-header-font-size: 13px;
  --dxbl-popup-header-font-weight: 500;
}
.dxbl-btn { --dxbl-btn-font-size: 11.5px; }

/* NOTHING READS BOLD.
   Two reasons this is global rather than scoped to .bc-page: <b> and <strong> are used
   throughout the pages, and DxPopup/DxDropDown portal their markup to the end of <body>,
   outside .bc-page entirely — so a scoped rule left every dialog's emphasis at the
   browser default 700. DevExpress's own headers and buttons are pinned for the same
   reason: their stylesheet ships 600s and outranks a plain class. */
b, strong, th, h1, h2, h3, h4, h5, h6, legend, summary { font-weight: 500; }
.dxbl-grid-header, .dxbl-grid-header-content,
.dxbl-btn, .dxbl-tabs .dxbl-tab, .dxbl-popup-header { font-weight: 500 !important; }

/* Best-effort editor rounding + focus accent (variables ignored where a given
   build doesn't define them — harmless). Applies under every skin: the field
   METRICS are the app's, only the colours belong to the theme, and --c-accent
   now resolves under a DevExpress skin too. */
:root[data-club-theme], :root[data-skin="dx"], :root:not([data-skin]) {
  --dxbl-border-radius: .5rem;
  --dxbl-text-edit-border-radius: .5rem;
  --dxbl-combobox-border-radius: .5rem;
  --dxbl-spin-edit-border-radius: .5rem;
  --dxbl-memo-border-radius: .5rem;
  --dxbl-date-edit-border-radius: .5rem;
  --dxbl-btn-border-radius: .5rem;
  --dxbl-focus-color: var(--c-accent);
}

/* CHECKBOX TICK — the same shadowing trap as the dialog surface below. DevExpress
   declares --dxbl-checkbox-* on .dxbl-checkbox itself, so a :root value never reaches it
   and every tick stayed the stock violet on a felt page. Override on the component root. */
:root[data-club-theme] .dxbl-checkbox,
:root:not([data-skin]) .dxbl-checkbox {
  --dxbl-checkbox-check-element-checked-bg: var(--c-accent);
  --dxbl-checkbox-check-element-checked-color: var(--c-accent-ink);
  --dxbl-checkbox-check-element-checked-hover-bg: var(--c-accent);
  --dxbl-checkbox-check-element-checked-border-color: var(--c-accent);
  --dxbl-checkbox-check-element-unchecked-border-color: var(--c-line-2);
}

/* DIALOG SURFACE. Setting --dxbl-popup-bg on :root does nothing: DevExpress declares it
   on .dxbl-modal, an ANCESTOR of the popup, and the nearer declaration shadows ours —
   which is why the dialogs stayed #37353d on a green felt page through two earlier
   attempts. Overriding it on the same element it is declared on is what works; the
   selectors that PAINT with it are three and four parts deep and cannot be outranked.

   Club skins only. Under a DevExpress skin the theme's own surface is the correct one. */
:root[data-club-theme] .dxbl-modal,
:root:not([data-skin]) .dxbl-modal {
  --dxbl-popup-bg: var(--c-panel);
  --dxbl-popup-color: var(--c-ink);
  --dxbl-popup-border-color: var(--c-line-2);
}

/* Editor roots: rounded, comfortable, accent focus ring. Scoped and non-!important
   so DevExpress internals (dropdown buttons, spinners) keep working. */
.dxbl-text-edit, .dxbl-combobox, .dxbl-spin-edit, .dxbl-memo, .dxbl-date-edit {
  border-radius: .5rem;
}
.dxbl-text-edit:focus-within, .dxbl-combobox:focus-within,
.dxbl-spin-edit:focus-within, .dxbl-memo:focus-within, .dxbl-date-edit:focus-within {
  border-color: var(--gym-accent);
  box-shadow: 0 0 0 2px var(--gym-accent-bg);
}
.dxbl-input::placeholder { color: var(--gym-ink-mute); opacity: 1; }

/* Pager: the current page was painted in the DevExpress theme's own accent — a violet chip
   sitting under a gold grid on the club skins, which read as a stray bit of another app.
   Club skins only; under a DevExpress skin its accent IS the right one. */
:root[data-club-theme] .dxbl-pager,
:root:not([data-skin]) .dxbl-pager {
  --dxbl-pager-active-page-btn-bg: var(--gym-accent);
  --dxbl-pager-active-page-btn-border-color: var(--gym-accent);
  --dxbl-pager-active-page-btn-color: var(--gym-accent-ink);
  --dxbl-pager-btn-active-bg: var(--gym-accent);
  --dxbl-pager-btn-active-border-color: var(--gym-accent);
  --dxbl-pager-btn-active-color: var(--gym-accent-ink);
}

/* Grids: header sits on the muted surface, rows hover on an accent tint, cells align
   to the club rhythm. */
.dxbl-grid { --dxbl-grid-bg: var(--gym-surface); border-radius: .5rem; overflow: hidden; }
.dxbl-grid .dxbl-grid-header { background: var(--gym-surface-2); color: var(--gym-ink-soft); font-weight: 500; }
.dxbl-grid .dxbl-grid-table > tbody > tr:hover > td { background: var(--gym-accent-bg); }

/* Weight ceiling — never bolder than semibold anywhere. */
strong, b, h1, h2, h3, h4, h5, h6 { font-weight: 500; }

/* ---------------------------------------------------------------------------
   5) RESPONSIVE — there is no sidebar to step down any more; the top bar
      handles narrow windows itself (labels drop, then DxMenu collapses the
      modules into its hamburger).
   --------------------------------------------------------------------------- */

/* ---------------------------------------------------------------------------
   4) MOTION — expo-out easing on the interactive components, a subtle press
      scale for tactility, and full respect for prefers-reduced-motion.
   --------------------------------------------------------------------------- */
.gym-tile, .gym-stat-clickable { transition-timing-function: var(--gym-ease); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  /* Drop the atmospheric glow/gradient so nothing shimmers for motion-sensitive users. */
  .bc-timer, .bc-dock-big { text-shadow: none !important; }
  .bc-tile:hover, .bc-tabcard:hover, .bc-item:hover, .gym-tile:hover { transform: none !important; }
}
