/* ============================================================
   BRAINZIE — APP UI LAYER
   The application design system shared by every Brainzie app (Money,
   Poolside, MeetFlow, Musterpoint…). Lives in the brainzie-landing repo
   beside the brand it extends; apps copy it in at BUILD time — never fork.
   Live catalogue: /styleguide.html

   Load order in an app:
     brainzie-tokens.css → teamcore-components.css → brainzie-ui.css → <app theme>.css
   Apps must NOT load brainzie.css / brainzie-site.css — those style bare
   elements at brochure scale for the landing pages.
   The app's <html> carries data-bz-theming (opts into the dark palette in
   brainzie-tokens.css) and usually data-density (team.core spacing mode).

   PRINCIPLES
   - Sparse screens are relaxed and elegant: one composed column or split,
     generous rhythm, short copy. They are composed, never merely empty.
   - Dense screens show data: full width, data-density="dense", aligned
     columns, one line per row, tabular numerals.
   - Prose is never hard-wrapped into a narrow column on a wide screen.
   - Terms of art get a Term/Tooltip definition, not a bare title=.
   ============================================================ */

/* ============================ TEAM.CORE MAPPING ============================ */
/* Maps the generic Team.Core.Blazor.Components variables (--tcc-*) onto the
   Brainzie brand tokens, so every tcc component is on-brand in every app. */
:root {
  --tcc-font: var(--font-body);
  --tcc-font-display: var(--font-display);
  --tcc-radius: var(--radius);
  --tcc-radius-s: var(--radius-s);
  --tcc-shadow: var(--shadow);
  --tcc-shadow-s: var(--shadow-s);

  --tcc-btn-primary-bg: var(--brand);
  --tcc-btn-primary-fg: #FFFFFF;
  --tcc-btn-primary-bg-hover: var(--brand-deep);
  /* The ghost fill follows the paper, so it flips with the theme; team.core's own default is a light grey that left
     dark-theme ghost buttons as light text on a light pill. */
  --tcc-btn-ghost-bg: var(--paper-2);
  --tcc-btn-ghost-bg-hover: var(--line);
  --tcc-btn-ghost-fg: var(--ink);
  --tcc-btn-ghost-border: var(--line);
  --tcc-btn-ghost-fg-hover: var(--brand-deep);
  /* Tabs follow the ink, so the active tab stays readable on a dark page (team.core's own defaults are for light). */
  --tcc-tab-fg: var(--muted);
  --tcc-tab-fg-hover: var(--ink-soft);
  --tcc-tab-fg-active: var(--ink);
  --tcc-btn-danger-bg: var(--accent-coral);
  --tcc-btn-danger-fg: #FFFFFF;
  /* A secondary button is the brand's tint with its deep pink, never a grey: a grey pill is what people read as
     disabled, and a club looking at "Withdraw" beside each swimmer took it for a button they could not press (RG,
     2026-10-16). Quieter than the filled primary, so a row of them down a list does not shout. Chips and fields still
     follow the neutrals; team.core's own defaults are light greys, which drew them as light patches on a dark page. */
  --tcc-btn-secondary-bg: var(--brand-tint);
  --tcc-btn-secondary-fg: var(--brand-deep);
  --tcc-btn-secondary-bg-hover: color-mix(in srgb, var(--brand) 22%, var(--white));
  --tcc-chip-bg: var(--paper-2);
  --tcc-chip-fg: var(--ink-soft);
  --tcc-chipset-hover-bg: var(--line);
  --tcc-chip-accent-bg: var(--brand-tint);
  --tcc-chip-accent-fg: var(--brand-deep);

  --tcc-card-bg: var(--white);
  --tcc-card-border: var(--line);

  --tcc-field-bg: var(--paper-2);
  --tcc-field-bg-hover: var(--line);
  --tcc-field-fg: var(--ink);
  --tcc-field-label: var(--muted);
  --tcc-field-placeholder: var(--muted);
  --tcc-field-line: var(--muted);
  --tcc-field-disabled-bg: var(--paper-2);
  --tcc-field-accent: var(--brand);
  --tcc-tooltip-bg: var(--ink);
  --tcc-tooltip-fg: var(--paper);

  --tcc-banner-info-bg: #EEE7FB;
  --tcc-banner-info-border: var(--secondary);
  --tcc-banner-info-fg: #3A2270;
  --tcc-banner-success-bg: #EAFAF3;
  --tcc-banner-success-border: var(--good);
  --tcc-banner-success-fg: #0C5C3C;
  --tcc-banner-warning-bg: #FFF1E0;
  --tcc-banner-warning-border: var(--accent-orange);
  --tcc-banner-warning-fg: #8A4B00;
  --tcc-banner-urgent-bg: var(--brand-tint);
  --tcc-banner-urgent-border: var(--brand);
  --tcc-banner-urgent-fg: var(--brand-deep);

  /* DataGrid / .tcc-table — mapped through the brand neutrals so they flip correctly in dark mode. */
  --tcc-grid-fg: var(--ink);
  --tcc-grid-muted: var(--muted);
  --tcc-grid-line: var(--line);
  --tcc-grid-surface: var(--white);
  --tcc-grid-head-bg: color-mix(in srgb, var(--ink) 4%, var(--white));
  --tcc-grid-stripe: color-mix(in srgb, var(--ink) 3%, var(--white));
  --tcc-grid-hover: color-mix(in srgb, var(--brand) 8%, var(--white));
  --tcc-grid-selected: var(--brand-tint);
  --tcc-grid-accent: var(--brand);
  --tcc-grid-totals-bg: color-mix(in srgb, var(--ink) 5%, var(--white));
  --tcc-grid-group-bg: color-mix(in srgb, var(--brand) 6%, var(--white));
  --tcc-grid-group-divider: color-mix(in srgb, var(--ink) 22%, transparent);
  --tcc-grid-up: var(--good);
  --tcc-grid-down: var(--bad);

  /* Controlled error experience (team.core ErrorView / AppErrorBoundary / QueryResultView error panel).
     Mapped through the brand neutrals, so the dark palette's --ink/--white overrides flip the body automatically;
     the header keeps white text on the deep brand in both. */
  --tcc-error-header-bg: var(--brand-deep);
  --tcc-error-header-fg: #FFFFFF;
  --tcc-error-body-bg: var(--white);
  --tcc-error-body-fg: var(--ink);
  --tcc-error-accent: var(--brand);
}

/* Dark: banner fills need translucent-on-dark values (the light pastels would glare).
   Same two-selector opt-in gate as brainzie-tokens.css — keep the blocks in sync. */
@media (prefers-color-scheme: dark) {
  :root[data-bz-theming]:not([data-theme="light"]) {
    --tcc-btn-ghost-fg: var(--ink);
    --tcc-banner-info-bg: rgba(109, 40, 217, .22);
    --tcc-banner-info-fg: #D8CCFF;
    --tcc-banner-success-bg: rgba(24, 160, 107, .20);
    --tcc-banner-success-fg: #8EE9C4;
    --tcc-banner-warning-bg: rgba(251, 139, 36, .20);
    --tcc-banner-warning-fg: #FFCF99;
    --tcc-banner-urgent-bg: rgba(216, 27, 114, .22);
    --tcc-banner-urgent-fg: #FF9EC8;
    --tcc-chip-accent-fg: #FF9EC8;
    --tcc-btn-secondary-fg: #FF9EC8;
    --tcc-btn-secondary-bg-hover: rgba(216, 27, 114, .34);
  }
}
:root[data-bz-theming][data-theme="dark"] {
  --tcc-btn-ghost-fg: var(--ink);
  --tcc-banner-info-bg: rgba(109, 40, 217, .22);
  --tcc-banner-info-fg: #D8CCFF;
  --tcc-banner-success-bg: rgba(24, 160, 107, .20);
  --tcc-banner-success-fg: #8EE9C4;
  --tcc-banner-warning-bg: rgba(251, 139, 36, .20);
  --tcc-banner-warning-fg: #FFCF99;
  --tcc-banner-urgent-bg: rgba(216, 27, 114, .22);
  --tcc-banner-urgent-fg: #FF9EC8;
  --tcc-chip-accent-fg: #FF9EC8;
  --tcc-btn-secondary-fg: #FF9EC8;
  --tcc-btn-secondary-bg-hover: rgba(216, 27, 114, .34);
}

/* ============================ RESET & BASE (app scale) ============================ */
/* Apps do not load the brochure layer, so the reset and element base live here —
   at APPLICATION scale: headings that head a working screen, not a hero. */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
  font-family: var(--font-body);
  color: var(--ink);
  background: var(--paper);
  line-height: var(--tcc-line-normal, 1.55);
  -webkit-font-smoothing: antialiased;
}
img, svg { max-width: 100%; }
a { color: var(--brand-deep); text-decoration: none; }
a:hover { text-decoration: underline; }
::selection { background: var(--brand-tint); }

h1, h2, h3, h4 { font-family: var(--font-display); line-height: var(--tcc-line-tight, 1.25); letter-spacing: -0.02em; font-weight: 700; color: var(--ink); }
h1 { font-size: 1.6rem; }
h2 { font-size: 1.25rem; }
h3 { font-size: 1.05rem; }
p  { color: var(--ink-soft); }

/* Intro line under a page or section title. Never a narrow ribbon: it uses the width it's given. */
.lead { font-size: .98rem; color: var(--ink-soft); max-width: 96ch; }
.eyebrow { font-family: var(--font-display); text-transform: uppercase; letter-spacing: .16em; font-size: .72rem; font-weight: 600; color: var(--secondary); }
.spacer { flex: 1; }

/* ============================ PAGE SHELLS ============================ */
/* .app-page          — the default working page.
   .app-page--narrow  — single-task pages (settings, a form).
   .app-page--wide    — data-dense pages: (almost) all the viewport, pair with data-density="dense".
   .app-page--sparse  — welcome/empty/landing-within-app moments: relaxed rhythm, composed column. */
.app-page { max-width: 1080px; margin-inline: auto; padding: 24px 24px 64px; }
.app-page--narrow { max-width: 720px; }
.app-page--wide { max-width: min(1600px, 96vw); }
.app-page--sparse { max-width: 1080px; padding-top: 40px; }

/* Sticky identity bar at the top of every page: brand mark + wordmark, actions on the right. */
.app-page__bar { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; position: sticky; top: var(--tcc-shell-banners-height, 0px); z-index: 30; background: var(--paper); padding: 10px 0; border-bottom: 1px solid var(--line); }
.app-page__bar img { width: 34px; height: 34px; }
.app-page__bar .name { font-family: var(--font-display); font-weight: 700; font-size: 1.15rem; letter-spacing: -.03em; color: var(--ink); }
.app-page__account { font-family: var(--font-display); font-size: .85rem; color: var(--muted); }
.app-page__brand { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; border-radius: 8px; }
.app-page__brand:hover .name { color: var(--brand-deep); }
.app-page__brand:hover img { transform: scale(1.06); transition: transform .12s ease; }
.app-page__section { margin-top: 24px; }
.app-page__link { font-family: var(--font-display); font-size: .9rem; color: var(--ink-soft); }
.app-page__link:hover { color: var(--brand-deep); }

/* The theme toggle is team.core's ThemeToggle — a ghost Button, styled by the --tcc-btn-* tokens above — so there is no
   .theme-toggle rule here to fight it. */

/* ============================ QUIET LEGAL / FOOT LINE ============================ */
/* One quiet line at the foot of a page: legal links, revoke note, separators. Never a stack of paragraphs. */
.bz-footline { margin-top: auto; padding: 26px 16px 14px; text-align: center; font-size: .82rem; color: var(--muted); width: 100%; }
.bz-footline a { color: var(--ink-soft); text-decoration: none; }
.bz-footline a:hover { color: var(--brand); text-decoration: underline; }
.bz-footline .sep { margin: 0 8px; opacity: .6; }

/* ============================ LOADING & PROGRESS ============================ */
.spinner { display: inline-block; width: 18px; height: 18px; flex: none; border: 2px solid var(--line); border-top-color: var(--brand); border-radius: 50%; animation: bz-spin .8s linear infinite; }
.spinner--lg { width: 30px; height: 30px; border-width: 3px; }
@keyframes bz-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.loading-panel { display: flex; align-items: center; gap: 16px; padding: 24px 4px; }
.loading-panel--center { justify-content: center; text-align: left; padding: 28px 18px; background: var(--white); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-s); }
.loading-panel__title { font-family: var(--font-display); font-weight: 600; color: var(--ink); margin: 0; }
.loading-panel__status { color: var(--muted); margin: 3px 0 0; font-size: .92rem; }
.loading-bar { height: 6px; border-radius: 999px; background: var(--line); margin-top: 10px; overflow: hidden; }
.loading-bar span { display: block; height: 100%; background: var(--brand); border-radius: 999px; transition: width .2s ease; }

/* ============================ STAT TILES ============================ */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 14px; margin: 4px 0; }
.stat { background: var(--white); border: 1px solid var(--line); border-radius: var(--radius-s); padding: 14px 16px; box-shadow: var(--shadow-s); }
.stat__label { font-family: var(--font-display); font-size: .72rem; text-transform: uppercase; letter-spacing: .1em; color: var(--muted); }
.stat__value { font-family: var(--font-display); font-weight: 700; font-size: clamp(1.3rem, 3vw, 1.7rem); color: var(--ink); letter-spacing: -.02em; margin-top: 4px; font-variant-numeric: tabular-nums; }
.stat__value.up { color: var(--good); }
.stat__value.down { color: var(--bad); }
.stat__sub { font-size: .82rem; color: var(--muted); margin-top: 4px; }
.stat__sub.up { color: var(--good); }
.stat__sub.down { color: var(--bad); }

/* ============================ SPARSE COMPOSITIONS ============================ */
/* Welcome / gateway screens: a composed split — message left, action card right —
   instead of a centred ribbon with giant margins. Collapses to one column on small screens. */
.bz-welcome { display: grid; grid-template-columns: 1.15fr .85fr; gap: clamp(32px, 6vw, 88px); align-items: start; margin-top: clamp(16px, 5vh, 56px); }
.bz-welcome__msg h1 { font-size: clamp(1.9rem, 3.2vw, 2.6rem); margin-bottom: 14px; max-width: 22ch; }
.bz-welcome__msg .lead { font-size: 1.08rem; max-width: 52ch; }
/* The action card: the one thing to do on this screen, framed and calm. */
.bz-welcome__action {
  background: var(--white); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow-s); padding: 26px 26px 22px;
  display: grid; gap: 12px; align-content: start;
  position: sticky; top: calc(72px + var(--tcc-shell-banners-height, 0px));
}
.bz-welcome__action h2 { font-size: 1.1rem; }
@media (max-width: 880px) {
  .bz-welcome { grid-template-columns: 1fr; }
  .bz-welcome__action { position: static; max-width: 440px; }
}

/* Proof points: short claim + one-line support, in place of paragraph essays. */
.bz-proof { display: grid; gap: 14px; margin-top: 26px; }
.bz-proof__item { display: flex; gap: 12px; align-items: flex-start; }
.bz-proof__ico { flex: 0 0 34px; width: 34px; height: 34px; border-radius: 10px; display: grid; place-items: center; font-size: 1.05rem; background: var(--brand-tint); }
.bz-proof__item h3 { font-size: .98rem; margin-bottom: 1px; }
.bz-proof__item p { font-size: .9rem; color: var(--ink-soft); margin: 0; max-width: 52ch; }

/* One quiet caveat/footnote line inside a composition (not a paragraph block). */
.bz-hint { font-size: .84rem; color: var(--muted); }

/* ============================ ALIGNED ROW GRID ============================ */
/* THE dense-list primitive: a (possibly multi-column) list of rows whose inner
   columns align across every row and every panel column, because the tracks are
   defined ONCE on the container and each row subgrids into them.
   Canonical shape (4 tracks): toggle · swatch · label · meta.
     <ul class="bz-rowgrid"> <li class="bz-rowgrid__row">…4 cells…</li> </ul>
   Rows are ONE line: labels ellipsise (put the full text in a Tooltip/title).
   A row spanning every panel column (a divider, a nested section) gets
   .bz-rowgrid__span. Needs a different shape? Follow this pattern in the app
   layer — don't stretch this one with more modifiers. */
.bz-rowgrid {
  list-style: none; margin: 0; padding: 4px;
  display: grid;
  grid-template-columns: repeat(auto-fill, 20px 16px minmax(140px, 1.5fr) minmax(90px, 1fr));
  column-gap: 10px;
}
.bz-rowgrid__row {
  display: grid; grid-template-columns: subgrid; grid-column: span 4;
  align-items: center; column-gap: 10px;
  padding: 5px 4px; border-bottom: 1px solid var(--line);
  font-size: .88rem; border-radius: 6px; transition: background .1s ease;
}
.bz-rowgrid__row--active { background: var(--brand-tint); box-shadow: inset 3px 0 0 var(--brand); }
.bz-rowgrid__span { grid-column: 1 / -1; }
.bz-rowgrid__toggle { width: 16px; height: 16px; margin: 0; accent-color: var(--brand); cursor: pointer; }
.bz-rowgrid__swatch { width: 11px; height: 11px; border-radius: 3px; display: inline-block; }
.bz-rowgrid__swatch--none { background: transparent; box-shadow: inset 0 0 0 1px var(--line); border-radius: 999px; }
.bz-rowgrid__label { display: flex; align-items: center; gap: 7px; min-width: 0; }
.bz-rowgrid__name { font-family: var(--font-display); font-weight: 600; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
button.bz-rowgrid__name { background: none; border: none; cursor: pointer; font: inherit; padding: 0; text-align: left; }
button.bz-rowgrid__name:hover { color: var(--brand-deep); text-decoration: underline; }
.bz-rowgrid__meta { font-size: .78rem; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: right; font-variant-numeric: tabular-nums; }
.bz-rowgrid__row--active .bz-rowgrid__name { color: var(--brand-deep); }
/* Dimmed variants (closed/archived/merged rows). */
.bz-rowgrid__row--dim { opacity: .62; }
@media (max-width: 560px) {
  /* One panel column on phones; the meta may need to give way first. */
  .bz-rowgrid { grid-template-columns: 20px 16px minmax(0, 1.5fr) minmax(70px, 1fr); }
  .bz-rowgrid__row { grid-column: 1 / -1; }
}

/* ============================ DELTAS & DIRECTION ============================ */
.delta-up { color: var(--good); }
.delta-down { color: var(--bad); }
.delta-flat { color: var(--muted); }
