/* ═══════════════════════════════════════════════════════════════
   CameraCashier Portal — app.css
   Design system: Direction B (Warm & Approachable) — default
   Direction A (Refined Pro) available via data-theme="a" on <html>
   ═══════════════════════════════════════════════════════════════ */

/* ── Design tokens — Direction B (default) ──────────────────────── */
:root {
  /* Brand primitives (locked — from TallyTill badge) */
  --cc-blue:      #1565C0;
  --cc-blue-lt:   #90CAF9;
  --cc-blue-dk:   #0d47a1;
  --cc-green:     #1B3D2A;   /* forest green — primary brand */
  --cc-green-md:  #2D6040;   /* aperture ring tone */
  --cc-green-dk:  #111A14;   /* near-black */
  --cc-amber:     #D97746;   /* badge centre — CTAs, active states */

  /* Direction B: Warm & Approachable */
  --sidebar-bg:           #1b3d2a;
  --sidebar-border:       #2a5940;
  --sidebar-text:         #6ea882;
  --sidebar-text-hover:   #a8d4b6;
  --sidebar-text-active:  #ffffff;
  --sidebar-active-bg:    rgba(255, 255, 255, 0.09);
  --sidebar-active-bar:   #f4a261;

  --content-bg:   #faf8f4;
  --card-bg:      #ffffff;
  --border:       #e2dbd0;
  --border-focus: #d97746;

  --text-primary:   #1c2a1e;
  --text-secondary: #4f6855;

  /* Muted text, WCAG-corrected. It was #8aa290, which is 2.74:1 on --card-bg and 2.59:1 on
     --content-bg — a normative failure of WCAG 2.2 SC 1.4.3 (4.5:1 for text this size), and the
     token is the Portal's default for help text, placeholders, table sub-values and every
     .text-muted in the app. Same treatment --accent-strong got, and for the same reason: the hue
     is kept (H135, the forest-green family) and pushed dark enough to clear the bar rather than
     swapped for a different colour. Measured, not eyeballed — 4.99:1 on --card-bg #ffffff and
     4.70:1 on --content-bg #faf8f4, which is the darker of the two surfaces it actually sits on
     and therefore the binding one. MutedTextContrastTests computes both from this file and fails
     the build if either drops below 4.5. Still a clear step lighter than --text-secondary
     (5.75:1 on --content-bg), so the three-tier hierarchy survives the fix. */
  --text-muted:     #5b7662;
  --text-inverse:   #ffffff;

  --accent:        #d97746;
  --accent-hover:  #c0612e;
  --accent-light:  #fff4ee;
  --accent-text:   #ffffff;

  /* The brand accent is a decorative colour and stays as-is, but it fails WCAG 1.4.3 the moment
     it CARRIES text: white on #d97746 is 3.14:1 and #d97746 as body text on --surface-2 is 2.96:1,
     both short of the 4.5:1 minimum. This is the same hue pushed dark enough to clear it —
     5.0:1 against white, 4.7:1 as text on --surface-2 — so anything text-bearing uses this and
     the brand colour is unchanged everywhere it is purely decorative. */
  --accent-strong: #b8501f;

  --success:       #2E7D32;
  --success-hover: #1b5e20;
  --success-light: #e8f5e9;
  --success-text:  #1b5e20;

  --warning:       #d97706;
  --warning-hover: #b45309;
  --warning-light: #fef3c7;
  --warning-text:  #854d0e;

  --danger:        #c62828;
  --danger-hover:  #b71c1c;
  --danger-light:  #fce8e8;
  --danger-text:   #b71c1c;

  --info:          #0277bd;
  --info-light:    #e1f5fe;
  --info-text:     #01579b;

  --code-bg:       #f5f0e8;
  --code-text:     #9a3412;

  /* Typography */
  --font-sans:   'Plus Jakarta Sans', system-ui, -apple-system, sans-serif;
  --font-mono:   'DM Mono', 'Cascadia Code', ui-monospace, monospace;
  --text-2xs:  0.625rem;
  --text-xs:   0.6875rem;
  --text-sm:   0.8125rem;
  --text-base: 0.875rem;
  --text-md:   1rem;
  --text-lg:   1.125rem;
  --text-xl:   1.375rem;
  --text-2xl:  1.75rem;

  /* Spacing */
  --space-1:   0.25rem;
  --space-2:   0.5rem;
  --space-3:   0.75rem;
  --space-4:   1rem;
  --space-5:   1.25rem;
  --space-6:   1.5rem;
  --space-8:   2rem;
  --space-10:  2.5rem;
  --card-pad:        1.5rem;
  --card-pad-sm:     1rem;

  /* Border radius — sharp by design */
  --radius-none: 0px;
  --radius-sm:   2px;
  --radius:      2px;
  --radius-md:   4px;
  --radius-lg:   6px;
  --radius-full: 9999px;

  /* Shadows */
  --shadow-xs:    0 1px 2px rgba(0, 0, 0, 0.04);
  --shadow-sm:    0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04);
  --shadow-md:    0 4px 12px rgba(0, 0, 0, 0.07), 0 2px 4px rgba(0, 0, 0, 0.04);
  --shadow-lg:    0 8px 30px rgba(0, 0, 0, 0.10), 0 4px 10px rgba(0, 0, 0, 0.05);
  --shadow-focus: 0 0 0 3px rgba(217, 119, 70, 0.22);

  /* Layout */
  --topnav-height: 58px;
  --input-height-sm: 30px;
  --input-height-md: 36px;
  --input-height-lg: 44px;
}

/* Direction A: Refined Pro — opt-in via data-theme="a" */
[data-theme="a"] {
  --sidebar-bg:           #0d1e35;
  --sidebar-border:       #1a3052;
  --sidebar-text:         #6b93bb;
  --sidebar-text-hover:   #b3cfe4;
  --sidebar-text-active:  #ffffff;
  --sidebar-active-bg:    rgba(21, 101, 192, 0.12);
  --sidebar-active-bar:   #1565C0;
  --content-bg:   #f0f5fa;
  --border:       #d4e3f0;
  --border-focus: #1565C0;
  --text-primary:   #0e1e33;
  --text-secondary: #3d5a78;
  /* Same correction as Direction B above, in this theme's own hue (H210). #7a9ab8 was 2.94:1 on
     white and 2.68:1 on this theme's --content-bg; this is 5.55:1 and 5.06:1. Direction A is
     opt-in via data-theme="a" but it is reachable from the theme toggle, so it is a live surface
     and MutedTextContrastTests holds it to the same bar. */
  --text-muted:     #4f6b87;
  --accent:        #1565C0;
  --accent-hover:  #0d47a1;
  --accent-light:  #e3f0fc;
  --font-sans:     'DM Sans', system-ui, -apple-system, sans-serif;
  --shadow-focus:  0 0 0 3px rgba(21, 101, 192, 0.22);
}

/* ── Reset & base ────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

html, body {
  height: 100%;
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--text-primary);
  background: var(--content-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1 { font-size: var(--text-xl); font-weight: 700; color: var(--text-primary); margin-bottom: .25rem; }

/* Routes.razor mounts <FocusOnNavigate Selector="h1" />, so every navigation programmatically focuses
   the page's first heading. That is deliberate and stays — it is what moves a screen reader to the new
   page instead of leaving it at the top of the chrome. The side effect is that the browser then paints
   a focus ring around the heading, which sits there until the next click.

   Suppress the ring, never the focus. An <h1> is not in the tab order and carries no positive tabindex
   anywhere in this Portal, so there is no keyboard user who can reach it and be left without an
   indicator; the ring conveys nothing here and reads as a stray border around the page title. Focus
   rings on real controls are untouched — this selector names h1 and nothing else.

   PublicLayout.razor and Home.razor each already carried a scoped copy of this rule. That is the
   evidence it belongs here: the same fix written twice, on the two pages someone happened to look at,
   while every other page in the Portal kept the border. Those two are now redundant; they are left in
   place only because Home's targets a class rather than the element, and proving that class is always
   an h1 is not worth coupling to this change. */
h1:focus, h1:focus-visible { outline: none; }
h2 { font-size: var(--text-lg); font-weight: 600; }
h3 { font-size: var(--text-md); font-weight: 600; }
h4 { font-size: .9375rem;       font-weight: 600; }
h5 { font-size: var(--text-base); font-weight: 500; }

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-hover); }

/* ── Top-nav layout ──────────────────────────────────────────────── */
.cc-layout {
  display: flex;
  flex-direction: column;
  height: 100vh;
  overflow: hidden;
}

.cc-content {
  flex: 1;
  overflow-y: auto;
  background: var(--content-bg);
}

.cc-page {
  padding: 32px 40px;
}

/* ── Page header ─────────────────────────────────────────────────── */
.page-header           { margin-bottom: 1.75rem; }
.page-header h1        { margin-bottom: .25rem; }
.page-header .lead     { color: var(--text-secondary); font-size: var(--text-sm); margin: 0; }

/* ── Cards ───────────────────────────────────────────────────────── */
.cc-card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-xs);
  overflow: hidden;
}
/* The Portal's eyebrow label — small, bold, uppercase, letterspaced, in the secondary text colour.
   ONE definition, shared by everything that wants the treatment. It started life inside
   .cc-card-header, which is why every panel heading in the app already reads this way; naming it
   lets a stat-card label ask for the same thing without also inheriting a card header's padding,
   border and flex layout. The alternative — a second copy of the four declarations on some page's
   own <style> block — is how two headings on one screen end up nearly, but not quite, alike.

   THE UPPERCASING IS CSS AND HAS TO STAY CSS. text-transform changes the glyphs, not the string,
   so a screen reader still reads the label as it was written and the source text stays
   translatable. Uppercasing in C# throws away both, and ToUpper() is culture-dependent besides. */
.cc-eyebrow,
.cc-card-header {
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--text-secondary);
}
.cc-card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 11px 20px;
  border-bottom: 1px solid var(--border);
}
.cc-card-body    { padding: var(--card-pad); }
.cc-card-body-sm { padding: var(--card-pad-sm); }
.cc-card-footer {
  padding: 12px 20px;
  background: var(--content-bg);
  border-top: 1px solid var(--border);
  display: flex;
  gap: 8px;
  align-items: center;
}

/* Bootstrap card — keep working pages styled */
.card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-xs);
}
.card-header {
  background: transparent;
  border-bottom: 1px solid var(--border);
  padding: 11px 20px;
  font-size: 10.5px;
  font-weight: 700;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: .08em;
}
.card-body   { padding: var(--card-pad); }
.card-footer { padding: 12px 20px; background: var(--content-bg); border-top: 1px solid var(--border); }

/* Stat cards */
.cc-stat-card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  box-shadow: var(--shadow-xs);
  transition: box-shadow .15s, transform .15s;
}
.cc-stat-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}
.cc-stat-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  margin-bottom: 28px;
}

/* Bootstrap colour card overrides */
.text-bg-primary, .text-bg-success, .text-bg-warning,
.text-bg-danger,  .text-bg-info    {
  background: var(--card-bg) !important;
  border: 1px solid var(--border) !important;
  color: var(--text-primary) !important;
  box-shadow: var(--shadow-xs);
}
.text-bg-primary .card-title { color: var(--accent)   !important; font-size: .75rem; text-transform: uppercase; letter-spacing: .06em; }
.text-bg-success .card-title { color: var(--success)  !important; font-size: .75rem; text-transform: uppercase; letter-spacing: .06em; }
.text-bg-warning .card-title { color: var(--warning)  !important; font-size: .75rem; text-transform: uppercase; letter-spacing: .06em; }
.text-bg-danger  .card-title { color: var(--danger)   !important; font-size: .75rem; text-transform: uppercase; letter-spacing: .06em; }
.text-bg-primary .card-text,
.text-bg-success .card-text,
.text-bg-warning .card-text,
.text-bg-danger  .card-text  { font-size: 2rem; font-weight: 700; line-height: 1.1; color: var(--text-primary) !important; }

/* ── Buttons ─────────────────────────────────────────────────────── */
.cc-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border-radius: var(--radius);
  padding: 7px 16px;
  font-size: var(--text-sm);
  font-weight: 500;
  cursor: pointer;
  font-family: var(--font-sans);
  border: 1px solid;
  transition: all .12s;
  line-height: 1.4;
  white-space: nowrap;
  text-decoration: none;
}
.cc-btn-primary   { background: var(--accent);     color: #fff;                    border-color: var(--accent); }
.cc-btn-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: #fff; }
.cc-btn-secondary { background: transparent;        color: var(--text-primary);    border-color: var(--border); }
.cc-btn-secondary:hover { background: var(--border); }
.cc-btn-danger    { background: transparent;        color: var(--danger);          border-color: var(--danger); }
.cc-btn-danger:hover { background: var(--danger-light); }
.cc-btn-success   { background: transparent;        color: var(--success);         border-color: var(--success); }
.cc-btn-success:hover { background: var(--success-light); }
.cc-btn-sm        { padding: 4px 10px; font-size: 12px; }
.cc-btn-lg        { padding: 10px 22px; font-size: var(--text-base); }

/* Bootstrap btn overrides */
.btn {
  font-size: var(--text-sm);
  font-weight: 500;
  border-radius: var(--radius);
  padding: 7px 16px;
  transition: all .12s ease;
  line-height: 1.4;
  font-family: var(--font-sans);
}
.btn-primary               { background: var(--accent);       border-color: var(--accent);       color: #fff; }
.btn-primary:hover         { background: var(--accent-hover); border-color: var(--accent-hover); color: #fff; }
.btn-primary:focus         { box-shadow: var(--shadow-focus); }
.btn-outline-primary       { color: var(--accent);  border-color: var(--accent); }
.btn-outline-primary:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn-danger                { background: var(--danger);  border-color: var(--danger);  color: #fff; }
.btn-danger:hover          { background: var(--danger-hover); border-color: var(--danger-hover); }
.btn-outline-danger        { color: var(--danger);  border-color: var(--danger); }
.btn-outline-danger:hover  { background: var(--danger); color: #fff; }
.btn-outline-success       { color: var(--success); border-color: var(--success); }
.btn-outline-success:hover { background: var(--success); color: #fff; }
.btn-secondary             { background: transparent; border-color: var(--border); color: var(--text-primary); }
.btn-secondary:hover       { background: var(--border); color: var(--text-primary); }
.btn-sm                    { font-size: 12px; padding: 4px 10px; }
.btn-link                  { color: var(--accent); }
.btn-link:hover            { color: var(--accent-hover); }

/* ── Forms ───────────────────────────────────────────────────────── */
.cc-input {
  width: 100%;
  height: var(--input-height-md);
  padding: 0 12px;
  font-size: var(--text-sm);
  font-family: var(--font-sans);
  color: var(--text-primary);
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  outline: none;
  transition: border-color .12s, box-shadow .12s;
}
.cc-input:focus {
  border-color: var(--border-focus);
  box-shadow: var(--shadow-focus);
}
.cc-input::placeholder { color: var(--text-muted); }

.cc-label      { font-size: var(--text-sm); font-weight: 500; color: var(--text-primary); margin-bottom: 5px; display: block; }
.cc-help-text  { font-size: var(--text-xs); color: var(--text-muted); margin-top: 4px; }
.cc-error-text { font-size: var(--text-xs); color: var(--danger); margin-top: 4px; }

.form-control, .form-select {
  font-size: var(--text-sm);
  border-color: var(--border);
  border-radius: var(--radius);
  color: var(--text-primary);
  padding: 7px 12px;
  background-color: var(--card-bg);
  font-family: var(--font-sans);
  transition: border-color .12s, box-shadow .12s;
}
/* Owner item 3: the shorthand above sets padding-right to 12px on .form-select too, which put select
   text under Bootstrap's arrow on every select in the Portal. Bootstrap's own 2.25rem comes back for the
   select, with the arrow kept clear of the edge. PortalStylePassTests pins it — including that this rule
   stays AFTER the shorthand, because the order is the whole fix.
   The value is --cc-select-chevron-space (css/portal-ui.css :root, 2.25rem — #510's token for the room the
   arrow takes), so this padding and FormField's error-state padding and icon cannot drift apart. The
   fallback is the same 2.25rem, for a page that somehow lacks portal-ui.css. */
.form-select {
  padding-right: var(--cc-select-chevron-space, 2.25rem);
  background-position: right .7rem center;
}
.form-select-sm {
  padding-right: 1.9rem;
  background-position: right .55rem center;
  background-size: 14px 10px;
}
.form-control:focus, .form-select:focus {
  border-color: var(--border-focus);
  box-shadow: var(--shadow-focus);
  outline: none;
}
.form-control::placeholder { color: var(--text-muted); }
.form-label { font-size: var(--text-sm); font-weight: 500; color: var(--text-primary); margin-bottom: 5px; }
.form-text  { font-size: var(--text-xs); color: var(--text-secondary); }
.input-group-text { font-size: var(--text-sm); border-color: var(--border); background: var(--content-bg); color: var(--text-secondary); border-radius: var(--radius); }

/* ── Tables ──────────────────────────────────────────────────────── */
.cc-table { width: 100%; border-collapse: collapse; }
.cc-th {
  padding: 9px 16px;
  text-align: left;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--text-secondary);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.cc-td {
  padding: 11px 16px;
  font-size: var(--text-sm);
  color: var(--text-primary);
  border-bottom: 1px solid var(--border);
  /* Matches `.table tbody td` below. Bootstrap gets this from `.align-middle` on the <table>
     inheriting through `.table > tbody { vertical-align: inherit }`; a .cc-table has no such
     chain, so a row mixing a one-line name with a two-line sub-value would top-align without it. */
  vertical-align: middle;
}
.cc-tr:hover { background: var(--content-bg); }

.table {
  font-size: var(--text-sm);
  color: var(--text-primary);
}
.table thead th {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--text-secondary);
  border-bottom: 1px solid var(--border);
  padding: 9px 16px;
  white-space: nowrap;
  background: transparent;
}
.table tbody td {
  padding: 11px 16px;
  vertical-align: middle;
  border-color: var(--border);
}
.table tbody tr:hover { background: var(--content-bg); }
.table tbody tr:last-child td { border-bottom: none; }
.table-striped > tbody > tr:nth-of-type(odd) > * { background-color: transparent; }

/* ── Badges ──────────────────────────────────────────────────────── */
.cc-badge {
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius-full);
  font-size: 11px;
  font-weight: 600;
  padding: 2px 9px;
  letter-spacing: .02em;
}
.cc-badge-success  { background: var(--success-light); color: var(--success-text); }
.cc-badge-warning  { background: var(--warning-light); color: var(--warning-text); }
.cc-badge-danger   { background: var(--danger-light);  color: var(--danger-text); }
.cc-badge-info     { background: var(--info-light);    color: var(--info-text); }
.cc-badge-neutral  { background: #f1f5f9; color: #475569; }
.cc-badge-accent   { background: var(--accent-light);  color: var(--accent); }

.badge {
  font-size: 11px;
  font-weight: 600;
  border-radius: var(--radius-full);
  padding: 2px 9px;
  letter-spacing: .02em;
}
.badge.bg-success { background: var(--success-light) !important; color: var(--success-text) !important; }
.badge.bg-danger  { background: var(--danger-light)  !important; color: var(--danger-text)  !important; }
.badge.bg-warning { background: var(--warning-light) !important; color: var(--warning-text) !important; }
.badge.bg-primary { background: var(--accent-light)  !important; color: var(--accent)       !important; }
.badge.bg-info    { background: var(--info-light)    !important; color: var(--info-text)    !important; }
.badge.bg-secondary { background: #f1f5f9 !important; color: var(--text-secondary) !important; }

/* ── Alerts ──────────────────────────────────────────────────────── */
.cc-alert {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 16px;
  border-radius: var(--radius);
  border: 1px solid;
  font-size: var(--text-sm);
  line-height: 1.5;
}
.cc-alert-success { background: var(--success-light); border-color: #a7d7aa; color: var(--success-text); }
.cc-alert-warning { background: var(--warning-light); border-color: #f6d55c; color: var(--warning-text); }
.cc-alert-danger  { background: var(--danger-light);  border-color: #f5aaaa; color: var(--danger-text); }
.cc-alert-info    { background: var(--info-light);    border-color: #90caf9; color: var(--info-text); }

.alert {
  border-radius: var(--radius);
  font-size: var(--text-sm);
  border-width: 1px;
  border-style: solid;
  padding: 12px 16px;
}
.alert-success { background: var(--success-light); border-color: #a7d7aa; color: var(--success-text); }
.alert-warning { background: var(--warning-light); border-color: #f6d55c; color: var(--warning-text); }
.alert-danger  { background: var(--danger-light);  border-color: #f5aaaa; color: var(--danger-text); }
.alert-info    { background: var(--info-light);    border-color: #90caf9; color: var(--info-text); }

/* ── Tabs ────────────────────────────────────────────────────────── */
.cc-tabs         { display: flex; border-bottom: 1px solid var(--border); margin-bottom: 24px; gap: 0; }
.cc-tab          { padding: 10px 20px; font-size: var(--text-sm); cursor: pointer; border: none; background: transparent; color: var(--text-secondary); border-bottom: 2px solid transparent; margin-bottom: -1px; transition: all .12s; font-family: var(--font-sans); }
.cc-tab:hover    { color: var(--text-primary); }
.cc-tab.active   { color: var(--accent); font-weight: 600; border-bottom-color: var(--accent); }

/* ── Code ────────────────────────────────────────────────────────── */
code, .code {
  font-size: .85em;
  color: var(--code-text);
  background: var(--code-bg);
  padding: .125rem .375rem;
  border-radius: var(--radius);
  font-family: var(--font-mono);
}

/* ── Utility ─────────────────────────────────────────────────────── */
.text-muted     { color: var(--text-muted) !important; }
.text-secondary { color: var(--text-secondary) !important; }
.text-success   { color: var(--success) !important; }
.text-danger    { color: var(--danger) !important; }
.text-warning   { color: var(--warning) !important; }
.text-accent    { color: var(--accent) !important; }

/* ── Responsive breakpoints ──────────────────────────────────────── */
@media (max-width: 1023px) {
  .cc-tn-item span      { display: none; }
  .cc-tn-item           { padding: 0 10px; }
  .cc-topnav-subtitle   { display: none; }
  .cc-theme-toggle      { display: none; }
  .cc-stat-grid         { grid-template-columns: repeat(2, 1fr); }
  .cc-dashboard-lower   { grid-template-columns: 1fr; }
}

@media (max-width: 639px) {
  .cc-topnav-items      { display: none !important; }
  .cc-hamburger         { display: flex !important; }
  .cc-topnav-settings   { display: none; }
  .cc-page              { padding: 20px 16px; }
  .cc-stat-grid         { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .cc-dashboard-lower   { grid-template-columns: 1fr; }
}

/* ── Blazor validation ───────────────────────────────────────────── */
.valid.modified:not([type=checkbox]) { outline: 1px solid var(--success); }
.invalid                             { outline: 1px solid var(--danger); }
.validation-message                  { color: var(--danger); font-size: var(--text-xs); }

/* ── Blazor error UI ─────────────────────────────────────────────── */
#blazor-error-ui {
  background: var(--danger-light);
  border-top: 2px solid var(--danger);
  color: var(--danger-text);
  padding: .75rem 1.5rem;
  position: fixed;
  bottom: 0; left: 0; right: 0;
  z-index: 9999;
  display: none;
  font-size: var(--text-sm);
  font-weight: 500;
}
#blazor-error-ui .dismiss { cursor: pointer; float: right; font-weight: 700; }
#blazor-error-ui .reload  { color: var(--danger-text); text-decoration: underline; }

.blazor-error-boundary {
  background: var(--danger-light);
  border: 1px solid var(--danger);
  border-radius: var(--radius);
  padding: 1rem;
  color: var(--danger-text);
}
.blazor-error-boundary::after { content: "An error has occurred."; }

/* ── Print ───────────────────────────────────────────────────────── */
@media print {
  .no-print { display: none !important; }
  .print-only { display: block !important; }
  nav, aside, header, footer { display: none !important; }
  body { background: white !important; }
}
.print-only { display: none; }

/* ── Stripe partner mark ─────────────────────────────────────────
   One shared treatment for the official Stripe wordmark wherever it sits beside a heading of ours
   (Payment Processing, Setup step 3, the dashboard Payouts card). Size is set per-instance on the
   <img> so each stays in proportion; this only governs alignment and weight.

   Deliberately understated: Stripe's Marks Usage Agreement requires their mark be less prominent
   than our own branding, and these all sit under the TallyTill nav mark. Never restyle the artwork
   itself — no filters, no recolouring. See wwwroot/brand/stripe/README.md. */
.stripe-mark {
  display: inline-block;
  vertical-align: middle;
  opacity: 0.72;
  transition: opacity 0.15s ease;
}
.stripe-mark:hover { opacity: 1; }

/* ═══════════════════════════════════════════════════════════════
   Portal usability pass (2026-09-25) — ux/ux-nav-pickers.
   Approved mockups: C:\Users\relaw\.claude\plans\portal-ux-mockups (M1, M4, M6, M7).
   See docs/design/PORTAL_NAV_AND_PICKERS.md.
   ═══════════════════════════════════════════════════════════════ */

/* ── Tabs in the house ink (approved) ────────────────────────────
   Bootstrap's .nav-tabs are link-blue, the one blue thing on a green-and-amber Portal. The CSA tabs, and
   the Products and CRM tabs that share the markup, are drawn in the house text colour with an amber edge
   on the active tab — the same amber the top bar underlines its active section with. */
.nav-tabs { border-bottom-color: var(--border); }
.nav-tabs .nav-link { color: var(--text-secondary); }
.nav-tabs .nav-link:hover,
.nav-tabs .nav-link:focus-visible { color: var(--text-primary); border-color: transparent; }
.nav-tabs .nav-link.active {
  color: var(--text-primary);
  font-weight: 600;
  background: var(--card-bg);
  border-color: var(--border) var(--border) var(--card-bg);
  box-shadow: inset 0 2px 0 var(--accent);
}

/* ── Status colours (approved) ───────────────────────────────────
   One token pair per StatusTones value (Foundation/Rules/StatusChipRules.cs), rendered by StatusChip.
   A status is a chip on a FULL-STRENGTH row, never a faded row: "Closed to new members" is the dark
   forest badge, not opacity. StatusChipTests reads these tokens and fails if a tone has no pair, and
   checks every foreground clears WCAG 4.5:1 on its background. */
:root {
  --status-neutral-bg:   #f1f5f9;  --status-neutral-fg:   #475569;
  --status-locked-bg:    #e4eee7;  --status-locked-fg:    #1b3d2a;
  --status-held-bg:      #fef3c7;  --status-held-fg:      #854d0e;
  --status-closed-bg:    #1b3d2a;  --status-closed-fg:    #ffffff;
  --status-packed-bg:    #e1f5fe;  --status-packed-fg:    #01579b;
  --status-done-bg:      #e8f5e9;  --status-done-fg:      #1b5e20;
  --status-unclaimed-bg: #fce8e8;  --status-unclaimed-fg: #b71c1c;
  --status-muted-bg:     #f1f1ef;  --status-muted-fg:     #57534e;
}
.cc-status { white-space: nowrap; gap: 4px; }
.cc-status i { font-size: .85em; line-height: 1; }
.cc-status-neutral   { background: var(--status-neutral-bg);   color: var(--status-neutral-fg); }
.cc-status-locked    { background: var(--status-locked-bg);    color: var(--status-locked-fg); }
.cc-status-held      { background: var(--status-held-bg);      color: var(--status-held-fg); }
.cc-status-closed    { background: var(--status-closed-bg);    color: var(--status-closed-fg); }
.cc-status-packed    { background: var(--status-packed-bg);    color: var(--status-packed-fg); }
.cc-status-done      { background: var(--status-done-bg);      color: var(--status-done-fg); }
.cc-status-unclaimed { background: var(--status-unclaimed-bg); color: var(--status-unclaimed-fg); }
.cc-status-muted     { background: var(--status-muted-bg);     color: var(--status-muted-fg); }
