/* ==========================================================================
   Charity Link Stock & Loan — Fluent-informed design system

   Built against the design critique of 2026-09-07, which found the app had
   105 lines of CSS and no authored typography, one grey doing three jobs, and
   brand colour appearing only as chrome. The measurements behind each fix are
   noted where they explain a value.

   Structure comes from hairline strokes, not grey fills or drop shadows.
   Colour is reserved for state and action. Type carries rank.
   ========================================================================== */

:root {
  /* --- Type ------------------------------------------------------------
     Fluent's ramp. Bootstrap's default jumped 28px -> 14px with almost
     nothing between, which is why pages read as having exactly two sizes. */
  --fs-caption: 0.75rem;    /* 12 - badges, table headers */
  --fs-body:    0.875rem;   /* 14 - the workhorse */
  --fs-base:    0.9375rem;  /* 15 - form controls, prose */
  --fs-subtitle:1rem;       /* 16 - section headings */
  --fs-title-3: 1.25rem;    /* 20 - card titles */
  --fs-title-2: 1.5rem;     /* 24 - page titles */
  --fs-display: 1.75rem;    /* 28 - dashboard figures */

  --fw-regular: 400;
  --fw-semibold: 600;       /* Fluent almost never uses 700 */

  /* --- Surfaces --------------------------------------------------------
     Three tones, not one. The critique found page background, card header
     and table header were all #f8f9fa, which is why no page could
     distinguish itself from any other. */
  --canvas:       #f5f5f4;  /* the page behind everything */
  --surface:      #ffffff;  /* cards, tables, panels */
  --surface-alt:  #faf9f8;  /* table headers, hover, subtle fills */
  --surface-sel:  #eef0f8;  /* selected row, active nav */

  --stroke:       #e4e2e0;  /* the hairline that does the structural work */
  --stroke-strong:#c8c6c4;

  --ink:          #1b1a19;
  --ink-secondary:#605e5c;
  --ink-tertiary: #8a8886;

  /* --- Brand ----------------------------------------------------------- */
  --brand-primary: #2f3d8f;
  --brand-primary-dark: #24306f;
  --brand-accent: #7b4fc4;

  /* --- Stock state -----------------------------------------------------
     One colour per state, used identically in tables, on the dashboard and
     on detail pages. Previously "Available", "On Loan" and "Awaiting
     Inspection" were all the same grey badge. */
  --state-available:  #0f7b3d;
  --state-onloan:     #2f3d8f;
  --state-picked:     #7b4fc4;
  --state-inspection: #9a6700;
  --state-damaged:    #b8500f;
  --state-missing:    #b32d2e;
  --state-writtenoff: #8a8886;

  --radius-sm: 2px;
  --radius: 4px;            /* Fluent's default. Bootstrap ships 6px, and
                               that extra softness is most of why the app
                               read "web app" rather than "Windows tool". */
  --radius-lg: 6px;

  --shadow-2: 0 1px 2px rgba(0,0,0,.10), 0 0 1px rgba(0,0,0,.08);
  --shadow-8: 0 3px 8px rgba(0,0,0,.10), 0 0 2px rgba(0,0,0,.08);

  /* Bootstrap remapping */
  --bs-primary: var(--brand-primary);
  --bs-primary-rgb: 47, 61, 143;   /* was never set, so .text-primary still
                                      rendered Bootstrap #0d6efd — a second,
                                      unbranded blue on the dashboard */
  --bs-link-color: var(--brand-primary);
  --bs-link-hover-color: var(--brand-primary-dark);
  --bs-link-color-rgb: 47, 61, 143;
  --bs-border-color: var(--stroke);
  --bs-border-radius: var(--radius);
  --bs-border-radius-sm: var(--radius-sm);
  --bs-border-radius-lg: var(--radius-lg);
  --bs-body-color: var(--ink);
  --bs-body-font-size: var(--fs-base);
  --bs-secondary-color: var(--ink-secondary);
}

/* --------------------------------------------------------------------------
   Typography

   Segoe UI Variable first: on Bryan's Windows machines this is the actual
   Microsoft typeface, which is the one place "Windows-like" is literally
   satisfiable rather than approximated.
   -------------------------------------------------------------------------- */
body {
  font-family: "Segoe UI Variable Text", "Segoe UI", -apple-system,
               BlinkMacSystemFont, system-ui, "Helvetica Neue", Arial, sans-serif;
  font-size: var(--fs-base);
  line-height: 1.5;
  color: var(--ink);
  background-color: var(--canvas);
  -webkit-font-smoothing: antialiased;
}

h1, .h1, h2, .h2, h3, .h3, h4, .h4, h5, .h5, h6, .h6 {
  font-family: "Segoe UI Variable Display", "Segoe UI Variable Text",
               "Segoe UI", system-ui, sans-serif;
  font-weight: var(--fw-semibold);
  color: var(--ink);
  letter-spacing: -0.008em;
  line-height: 1.3;
}

h1, .h1, .h3 { font-size: var(--fs-title-2); }
h2, .h2, .h5 { font-size: var(--fs-subtitle); }
.h4 { font-size: var(--fs-title-3); }
.h6 { font-size: var(--fs-body); }

.small, small { font-size: var(--fs-body); }

/* Nested .small and <code> inside .small were compounding em sizes down to
   10.5px and 12.25px. Pin them. */
.small .small, .small code, code.small { font-size: var(--fs-caption); }

code {
  font-size: var(--fs-caption);
  color: var(--ink-secondary);
  background: var(--surface-alt);
  border: 1px solid var(--stroke);
  border-radius: var(--radius-sm);
  padding: .1em .35em;
}

/* The two highest-value lines in the whole redesign: quantities now align by
   place value, so scanning a column of numbers works. */
.table td, .table th, .stat-figure, .h4, .display-6 {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* --------------------------------------------------------------------------
   Surfaces — hairlines, not grey bars
   -------------------------------------------------------------------------- */
.card {
  background: var(--surface);
  border: 1px solid var(--stroke);
  border-radius: var(--radius);
  box-shadow: var(--shadow-2);
}

/* The single most repeated element in the old UI was a grey card header, and
   it is why every page looked like the same page. White with a rule instead. */
.card-header,
.card-header.bg-body-tertiary {
  background: var(--surface) !important;
  border-bottom: 1px solid var(--stroke);
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  color: var(--ink);
  padding: .625rem .875rem;
}

.card-footer { background: var(--surface-alt); border-top: 1px solid var(--stroke); }
.card-body { padding: .875rem; }

/* --------------------------------------------------------------------------
   Tables
   -------------------------------------------------------------------------- */
.table { --bs-table-color: var(--ink); margin-bottom: 0; }

.table > thead th,
.table-light > th,
.table > thead > tr > th {
  background: var(--surface-alt) !important;
  border-bottom: 1px solid var(--stroke) !important;
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--ink-secondary);
  padding: .5rem .75rem;
  white-space: nowrap;
}

.table > tbody > tr > td {
  font-size: var(--fs-body);
  padding: .625rem .75rem;
  border-bottom-color: var(--stroke);
  vertical-align: middle;
}

.table-hover > tbody > tr:hover > * {
  --bs-table-bg-state: var(--surface-alt);
}

.table-sm > tbody > tr > td { padding: .375rem .75rem; }

/* --------------------------------------------------------------------------
   Stock state — one colour per state, used everywhere identically
   -------------------------------------------------------------------------- */
.state {
  display: inline-flex;
  align-items: center;
  gap: .4em;
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  color: var(--ink-secondary);
  white-space: nowrap;
}

/* The dot carries the colour; the label always carries the meaning, so state
   is never conveyed by colour alone (WCAG 2.1 AA, PRD s50). */
.state::before {
  content: "";
  width: .5rem;
  height: .5rem;
  border-radius: 50%;
  background: currentColor;
  flex: 0 0 auto;
}

.state-available  { color: var(--state-available); }
.state-on-loan    { color: var(--state-onloan); }
.state-picked     { color: var(--state-picked); }
.state-awaiting-inspection { color: var(--state-inspection); }
.state-damaged    { color: var(--state-damaged); }
.state-quarantined,
.state-under-repair { color: var(--state-inspection); }
.state-missing    { color: var(--state-missing); }
.state-written-off { color: var(--state-writtenoff); }

/* Bootstrap's .badge is 0.75em, so a badge inside .small compounds down to
   10.5px. Pin it to the caption size wherever it appears. */
.badge {
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  border-radius: var(--radius-sm);
}
.status-badge { font-size: var(--fs-caption); letter-spacing: .01em; }

/* --------------------------------------------------------------------------
   Buttons — one filled primary per page, everything else subtle
   -------------------------------------------------------------------------- */
.btn {
  --bs-btn-font-size: var(--fs-body);
  --bs-btn-font-weight: var(--fw-semibold);
  --bs-btn-border-radius: var(--radius);
  --bs-btn-padding-y: .375rem;
  --bs-btn-padding-x: .75rem;
}

.btn-primary {
  --bs-btn-bg: var(--brand-primary);
  --bs-btn-border-color: var(--brand-primary);
  --bs-btn-hover-bg: var(--brand-primary-dark);
  --bs-btn-hover-border-color: var(--brand-primary-dark);
  --bs-btn-active-bg: var(--brand-primary-dark);
  --bs-btn-active-border-color: var(--brand-primary-dark);
  --bs-btn-disabled-bg: var(--brand-primary);
  --bs-btn-disabled-border-color: var(--brand-primary);
}

.btn-outline-primary {
  --bs-btn-color: var(--brand-primary);
  --bs-btn-border-color: var(--stroke-strong);
  --bs-btn-hover-bg: var(--surface-sel);
  --bs-btn-hover-color: var(--brand-primary-dark);
  --bs-btn-hover-border-color: var(--brand-primary);
}

/* #6c757d on #f8f9fa measured 4.45:1 — a hair under AA. */
.btn-outline-secondary {
  --bs-btn-color: #5c636a;
  --bs-btn-border-color: var(--stroke-strong);
  --bs-btn-hover-bg: var(--surface-alt);
  --bs-btn-hover-color: var(--ink);
  --bs-btn-hover-border-color: var(--stroke-strong);
}

/* --------------------------------------------------------------------------
   Navigation
   -------------------------------------------------------------------------- */
.navbar.app-nav {
  background-color: var(--brand-primary);
  border-bottom: none !important;
  padding-top: .375rem;
  padding-bottom: .375rem;
  box-shadow: var(--shadow-2);
}

/* rgba(255,255,255,.55) measured 4.11:1 on the navy — under AA. */
.app-nav .nav-link {
  color: rgba(255, 255, 255, .86);
  font-size: var(--fs-body);
  border-radius: var(--radius);
  padding: .375rem .625rem;
}
.app-nav .nav-link:hover,
.app-nav .nav-link:focus { color: #fff; background: rgba(255, 255, 255, .12); }

/* The critique found no active state anywhere: three levels deep you could
   not tell which section you were in. */
.app-nav .nav-link.active {
  color: #fff;
  background: rgba(255, 255, 255, .18);
  font-weight: var(--fw-semibold);
  box-shadow: inset 0 -2px 0 var(--brand-accent);
}

.app-nav .navbar-text { color: rgba(255, 255, 255, .86); }

.brand-mark {
  width: 24px; height: 24px;
  border-radius: var(--radius);
  background: linear-gradient(135deg, var(--brand-accent), #a98ade);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: .75rem; color: #fff;
}

.nav-tabs {
  --bs-nav-tabs-border-color: var(--stroke);
  font-size: var(--fs-body);
}
.nav-tabs .nav-link { color: var(--ink-secondary); border-radius: 0; }
.nav-tabs .nav-link.active {
  color: var(--brand-primary);
  font-weight: var(--fw-semibold);
  border-color: transparent transparent var(--brand-primary);
  border-bottom-width: 2px;
}

/* --------------------------------------------------------------------------
   Forms
   -------------------------------------------------------------------------- */
.form-control, .form-select {
  font-size: var(--fs-base);
  border-color: var(--stroke-strong);
  border-radius: var(--radius);
}
.form-label {
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  color: var(--ink);
  margin-bottom: .25rem;
}
.form-text { font-size: var(--fs-caption); color: var(--ink-secondary); }

/* One authored focus style. Bootstrap's default glow measured 1.20:1 against
   the navy navbar — technically present, practically invisible. */
:focus-visible,
.btn:focus-visible,
.nav-link:focus-visible,
.page-link:focus-visible,
a:focus-visible {
  outline: 2px solid var(--brand-accent);
  outline-offset: 2px;
  box-shadow: none !important;
}
.app-nav :focus-visible { outline-color: #fff; }
.form-control:focus, .form-select:focus {
  border-color: var(--brand-accent);
  box-shadow: 0 0 0 2px rgba(123, 79, 196, .35);
}

/* --------------------------------------------------------------------------
   Page furniture
   -------------------------------------------------------------------------- */
.page-title { font-size: var(--fs-title-2); font-weight: var(--fw-semibold); }
.page-lede { font-size: var(--fs-body); color: var(--ink-secondary); max-width: 68ch; }

/* Fluent's command bar: page actions in one predictable place instead of
   scattered across the header. */
.command-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem;
  padding: .5rem 0 .75rem;
  border-bottom: 1px solid var(--stroke);
  margin-bottom: 1rem;
}

/* Reading measure. Every page was container-fluid with no cap, so six
   inventory rows sat in a 2000px field on a large monitor. */
.app-main { max-width: 1600px; margin-inline: auto; }

.stat-figure {
  font-size: var(--fs-display);
  font-weight: var(--fw-semibold);
  line-height: 1.15;
}
.stat-label {
  font-size: var(--fs-caption);
  color: var(--ink-secondary);
  text-transform: uppercase;
  letter-spacing: .04em;
}

footer { background: var(--surface) !important; border-top: 1px solid var(--stroke); }

/* --------------------------------------------------------------------------
   Mobile

   Warehouse screens are used one-handed on a phone while holding a box, so
   every tap target meets WCAG 2.5.5's 44px. The previous rule listed only
   .btn/.form-control/.form-select and missed bare anchors, leaving 19px-tall
   links on the reports and warehouse pages.
   -------------------------------------------------------------------------- */
@media (max-width: 767.98px) {
  .btn, .form-control, .form-select, .navbar-toggler { min-height: 44px; }
  .btn-sm, .btn-close { min-height: 44px; min-width: 44px; }
  .btn-close { background-position: center; }

  .card-body a:not(.btn),
  .list-group-item a:not(.btn),
  .table a:not(.btn),
  .offcanvas .nav-link {
    display: inline-block;
    min-height: 44px;
    line-height: 2.6;
  }

  .card-body { padding: .75rem; }

  /* Wrapping eight actions onto a phone produced a 217px-tall bar before any
     content appeared. Scrolling keeps it one row; the primary action is
     leftmost so it is always the one visible. */
  .command-bar {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    padding-bottom: .5rem;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
    mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent);
  }
  .command-bar::-webkit-scrollbar { display: none; }
  .command-bar > * { flex: 0 0 auto; scroll-snap-align: start; }
  .command-bar .vr { display: none; }

  /* The brand and the footer credit are links too. */
  .navbar-brand { min-height: 44px; display: inline-flex; align-items: center; }
  footer a { display: inline-block; min-height: 44px; line-height: 2.75; }
}

.btn-lg, .form-control-lg { min-height: 48px; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: .01ms !important; }
}
