/* ============================================================================
   HCTC Fleet UI  --  drop-in tokens + components            (2026-09-24, v0.3)
   v0.3: FIX --fl-blue / --fl-solid-fill kept their LIGHT values in dark mode
         (measured #097ABF / #0869a5 under body.dark-theme on FPS, PM, Perform
         and Budget). Both are var() aliases declared on :root, and a var()
         inside a custom property is substituted where it is DECLARED, so the
         :root alias froze the light --fl-primary before body's dark block ran.
         They are now re-declared inside the dark block (section 2).
         NEW sections 9-11: menu button + drawer backdrop (mandatory <=1024px),
         collapse control + 52px rail, and a generic .fl-icon. Section 8 turns
         the menu button on below the breakpoint and keeps content inside a
         390px screen. No token values changed; no existing rule changed.
   v0.2: accessible --fl-*-text tokens for small coloured text; .fl-pill,
         .fl-kpi-value.up/.down, .fl-tile-hero.up/.down, .fl-nav-badge and
         .fl-pill--solid retargeted. Fills and every other rule unchanged.
   ----------------------------------------------------------------------------
   Every literal below was read out of a production file on telcor (10.1.7.200):
     [FPS]    C:\fps\client\src\index.css            (dbca307, 2026-08-31)
     [PM]     C:\hctcpm\styles.css                    (c34a0a4)
     [BUDGET] C:\hctc-budget\public\styles.css        (a2c205f)  .dash-hero-*
     [OMNI]   C:\omni\public\css\dashboard.css        (d522cb9)  .dash-card / .card-header
              C:\omni\public\js\netnew-dashboard.js              header pill markup
   Anything marked CHOICE is a decision, not a quotation; the reason is inline.

   Namespacing: every class is prefixed `fl-` so this file can be included next
   to an app's existing stylesheet without fighting its `.sidebar` / `.card` /
   `.stat-card` rules. Apps alias or migrate markup at their own pace. (CHOICE)

   Dark mode: the fleet uses four different switches. All are honoured here:
     body.dark-theme        FPS, PM, Perform, Budget
     body.dark-mode         Omni, Core Score, ServiceIQ, JSA, Core Recon, PM (also)
     html[data-theme=dark]  AvalService, Final Span
     html.dark              Procure, LINEWALK (dark by default, .light is the delta)
   ============================================================================ */

/* ---- 1. Tokens: light (default) ------------------------------------------ */
:root {
  /* Surfaces                                       [FPS] :root */
  --fl-bg:            #E9F2F9;
  --fl-surface:       #ffffff;
  --fl-surface-2:     #f0f5fa;
  --fl-surface-3:     #e2edf5;
  --fl-border:        rgba(9, 122, 191, 0.15);
  --fl-border-strong: rgba(9, 122, 191, 0.25);

  /* Brand                                          [FPS] :root */
  --fl-primary:       #097ABF;
  --fl-primary-hover: #0869a5;
  --fl-primary-dim:   rgba(9, 122, 191, 0.10);

  /* Accent hues (card top bars, pills, badges)     [FPS] :root */
  /* --fl-blue and --fl-solid-fill (below) are var() aliases. They are
     re-declared in the dark block: an alias on :root resolves against :root's
     own --fl-primary, i.e. the light value, no matter what body carries. */
  --fl-blue:    var(--fl-primary);
  --fl-green:   #22c55e;  --fl-green-dim:  rgba(34, 197, 94, 0.12);
  --fl-amber:   #f59e0b;  --fl-amber-dim:  rgba(245, 158, 11, 0.12);
  --fl-red:     #ef4444;  --fl-red-dim:    rgba(239, 68, 68, 0.12);
  --fl-purple:  #a855f7;  --fl-purple-dim: rgba(168, 85, 247, 0.12);
  --fl-cyan:    #06b6d4;  --fl-cyan-dim:   rgba(6, 182, 212, 0.12);

  /* Accent hues AS SMALL TEXT (pills, badges, coloured captions).
     CORRECTION 2026-09-22 (v0.2): v0.1 used the raw hue as pill text. At
     0.7rem on #ffffff that fails WCAG AA -- amber #f59e0b 2.15:1, green
     #22c55e 2.28:1, cyan #06b6d4 2.43:1, red #ef4444 3.76:1, purple #a855f7
     3.96:1, blue #3b82f6 3.68:1 -- and worse on the 12% tinted pill fill
     (amber 1.96:1). Core Recon caught this and shipped app-local tokens; the
     fleet tokens below replace them. The fills (--fl-*-dim) are unchanged;
     only the text colour moves. Ratios are on #ffffff / on the 12% tint.
     Do not "simplify" these back to the raw hue.                              */
  --fl-blue-text:   #0869a5;   /* 5.88 / 5.01   [FPS] --color-primary-hover      */
  --fl-green-text:  #166534;   /* 7.13 / 6.43   green-800                        */
  --fl-amber-text:  #92400e;   /* 7.09 / 6.46   amber-800, [BUDGET] .dash-var-chip.caution */
  --fl-red-text:    #b91c1c;   /* 6.47 / 5.55   red-700, Core Recon --cr-red-text */
  --fl-purple-text: #a21caf;   /* 6.32 / 5.48   fuchsia-700, Core Recon --cr-purple-text */
  --fl-cyan-text:   #0e7490;   /* 5.36 / 4.79   cyan-700                         */
  /* White text on a solid brand fill: #097ABF gives 4.62:1 but the dark
     primary #3b82f6 only 3.68:1, so solid fills use the hover shade in both
     modes (5.88:1 light, 5.17:1 dark).                                        */
  --fl-solid-fill:  var(--fl-primary-hover);

  /* Text                                           [FPS] :root */
  --fl-text:           #1a202c;
  --fl-text-secondary: #4a5568;
  --fl-text-muted:     #718096;
  --fl-text-inverse:   #ffffff;

  /* Type                                           [FPS] :root */
  --fl-font-sans: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --fl-font-mono: 'JetBrains Mono', 'Fira Code', ui-monospace, monospace;

  /* Spacing scale                                  [FPS] --sp-* */
  --fl-sp-1: 0.25rem;  --fl-sp-2: 0.5rem;   --fl-sp-3: 0.75rem;
  --fl-sp-4: 1rem;     --fl-sp-5: 1.25rem;  --fl-sp-6: 1.5rem;
  --fl-sp-8: 2rem;     --fl-sp-10: 2.5rem;  --fl-sp-12: 3rem;

  /* Radii                                          [FPS] --radius-* */
  --fl-radius-sm: 0.375rem;
  --fl-radius-md: 0.5rem;
  --fl-radius-lg: 0.75rem;
  --fl-radius-xl: 1rem;
  --fl-radius-pill: 999px;

  /* Shadows                                        [FPS] --shadow-* */
  --fl-shadow-sm: 0 1px 3px rgba(0,0,0,0.08);
  --fl-shadow-md: 0 4px 16px rgba(0,0,0,0.10);
  --fl-shadow-lg: 0 8px 32px rgba(0,0,0,0.12);

  /* Motion                                         [FPS] */
  --fl-transition:      all 0.18s ease;
  --fl-transition-fast: all 0.1s ease;

  /* Layout                                         [FPS]/[PM] */
  --fl-sidebar-width: 240px;

  /* Component-level knobs (all read from the references, see spec section 4) */
  --fl-kpi-bar:          3px;        /* [FPS] .stat-card::before height        */
  --fl-kpi-value-size:   1.75rem;    /* [FPS] StatCard inline fontSize         */
  --fl-kpi-value-weight: 800;        /* [FPS] .card-value                      */
  --fl-kpi-label-size:   11px;       /* [BUDGET] .dash-hero-label              */
  --fl-kpi-caption-size: 12px;       /* [BUDGET] .dash-hero-sub                */
  --fl-kpi-icon-size:    1.5rem;     /* [FPS] StatCard icon div                */
  --fl-tile-pad-x:       20px;       /* [OMNI] .dash-card .card-header/.card-body */
  --fl-tile-pad-y:       16px;       /* [OMNI] .card-header                    */
}

/* ---- 2. Tokens: dark ----------------------------------------------------- */
body.dark-theme,
body.dark-mode,
html[data-theme="dark"],
html.dark:not(.light) {
  /* [FPS] body.dark-theme -- the darker of the two dark palettes in the fleet.
     Omni/Budget/HW currently sit on #0f172a / #1e293b / #334155 (slate); the
     product owner asked for the fleet to come DOWN to this. */
  --fl-bg:            #0a0f1e;
  --fl-surface:       #151b2e;
  --fl-surface-2:     #1e2638;
  --fl-surface-3:     #252d3d;
  --fl-border:        rgba(9, 122, 191, 0.25);
  --fl-border-strong: rgba(9, 122, 191, 0.35);

  --fl-primary:       #3b82f6;
  --fl-primary-hover: #2563eb;
  --fl-primary-dim:   rgba(59, 130, 246, 0.15);

  /* v0.3 FIX. These two are aliases of the primaries above. Declared only on
     :root (v0.1-v0.2) they computed to #097ABF / #0869a5 in dark mode on every
     body.dark-* app, because var() in a custom property is resolved on the
     element that declares it and :root never sees body's dark --fl-primary.
     Re-declaring them HERE resolves them on the same element as the dark
     primaries. (html-level switches happened to work before because the dark
     block and :root are the same element there.) Resolved: #3b82f6 / #2563eb. */
  --fl-blue:       var(--fl-primary);
  --fl-solid-fill: var(--fl-primary-hover);

  --fl-green-dim:  rgba(34, 197, 94, 0.15);
  --fl-amber-dim:  rgba(245, 158, 11, 0.15);
  --fl-red-dim:    rgba(239, 68, 68, 0.15);
  --fl-purple-dim: rgba(168, 85, 247, 0.15);
  --fl-cyan-dim:   rgba(6, 182, 212, 0.15);

  /* Accent hues as small text, dark. Ratios on #151b2e / on the 15% tint.
     The raw hues mostly pass on the dark surface (amber 7.96, green 7.50,
     cyan 7.04) but red 4.54, purple 4.32 and blue 4.65 sit at the AA line and
     drop below it on the tinted fill (3.93 / 3.64 / 3.85), so every hue gets
     the same one-step-lighter treatment for consistency.                     */
  --fl-blue-text:   #60a5fa;   /* 6.73 / 5.57   [OMNI] dark .drill-modal-back    */
  --fl-green-text:  #4ade80;   /* 9.81 / 7.55   [SERVICEIQ] .data-freshness-value.fresh, Core Recon dark */
  --fl-amber-text:  #fbbf24;   /* 10.24 / 7.86  [BUDGET] dark .cap-class-dreg, Core Recon dark */
  --fl-red-text:    #f87171;   /* 6.18 / 5.35   [BUDGET] dark yoy-decrease, Core Recon dark */
  --fl-purple-text: #c084fc;   /* 6.47 / 5.45   [AVAL] dark --color-purple       */
  --fl-cyan-text:   #22d3ee;   /* 9.46 / 7.38   [AVAL] dark --color-info         */

  --fl-text:           #e2e8f0;
  --fl-text-secondary: #a0aec0;
  /* CHOICE: FPS uses #718096 for muted in dark, which is 4.2:1 on #151b2e and
     fails AA for the 11px uppercase KPI label. Budget's dark muted #94A3B8
     (6.4:1) is used instead. #718096 stays available as --fl-text-faint. */
  --fl-text-muted:     #94a3b8;
  --fl-text-faint:     #718096;
  --fl-text-inverse:   #0a0f1e;

  --fl-shadow-sm: 0 1px 3px rgba(0,0,0,0.4);
  --fl-shadow-md: 0 4px 16px rgba(0,0,0,0.35);
  --fl-shadow-lg: 0 8px 32px rgba(0,0,0,0.45);
}
:root { --fl-text-faint: #718096; } /* light: same as muted [FPS] */

/* ---- 3. Layout shell ----------------------------------------------------- */
.fl-app {                                   /* [FPS] .app-layout */
  display: flex;
  min-height: 100vh;
  font-family: var(--fl-font-sans);
  background: var(--fl-bg);
  color: var(--fl-text);
  -webkit-font-smoothing: antialiased;
}
.fl-main {                                  /* [FPS] .main-content */
  margin-left: var(--fl-sidebar-width);
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
.fl-page { padding: var(--fl-sp-6); flex: 1; }   /* [FPS] .page-content */

/* ---- 4. Left sidebar nav                          [FPS] .sidebar, .nav-* ---- */
.fl-sidebar {
  width: var(--fl-sidebar-width);
  background: var(--fl-surface);
  border-right: 2px solid var(--fl-border);
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 0; left: 0; bottom: 0;
  z-index: 100;
  box-shadow: var(--fl-shadow-sm);
  transition: transform 0.25s ease;
}
.fl-sidebar-nav {
  flex: 1;
  overflow-y: auto;
  padding: var(--fl-sp-6) 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.fl-nav-section { display: flex; flex-direction: column; gap: 2px; }

/* Top-level item: rounded pill, 13px/500, 16px stroke icon */
.fl-nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px 10px 20px;
  margin: 0 8px;
  color: var(--fl-text-secondary);
  font-size: 13px;
  font-weight: 500;
  font-family: var(--fl-font-sans);
  cursor: pointer;
  text-decoration: none;
  border: none;
  border-radius: var(--fl-radius-md);
  background: transparent;
  text-align: left;
  width: calc(100% - 16px);
  transition: all 0.15s ease;
}
.fl-nav-item:hover        { background: var(--fl-surface-2); color: var(--fl-text); }
.fl-nav-item:hover svg    { stroke: var(--fl-primary); }
.fl-nav-item.active       { background: rgba(9,122,191,0.15); color: var(--fl-text); font-weight: 600; }
.fl-nav-item.active svg   { stroke: var(--fl-primary); }
.fl-nav-item > span       { flex: 1; }

.fl-nav-item svg,
.fl-nav-section-header svg,
.fl-nav-subitem svg {
  width: 16px; height: 16px; flex-shrink: 0;
  stroke: currentColor; fill: none;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}

/* Count badge on an item                          [PM] .sidebar-badge */
.fl-nav-badge {
  margin-left: auto;
  background: var(--fl-solid-fill);   /* v0.2: was --fl-primary; white on #3b82f6 is 3.68:1 in dark */
  color: #fff;
  font-size: 0.7rem;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: var(--fl-radius-pill);
  min-width: 22px;
  text-align: center;
}

/* Accordion group (Operations, Administration) */
.fl-nav-accordion { margin-top: var(--fl-sp-2); }
.fl-nav-section-header {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 12px 20px;
  background: transparent;
  border: none;
  color: var(--fl-text);
  font-size: 0.9375rem;
  font-weight: 600;
  font-family: var(--fl-font-sans);
  cursor: pointer;
  text-align: left;
  transition: all 0.15s ease;
}
.fl-nav-section-header:hover                 { color: var(--fl-primary); }
.fl-nav-section-header:hover svg:first-child { stroke: var(--fl-primary); }
.fl-nav-section-header svg:first-child       { width: 20px; height: 20px; }
.fl-nav-section-header > span                { flex: 1; }
.fl-nav-chevron        { display: flex; align-items: center; opacity: 0.5; transition: transform 0.2s ease, opacity 0.2s ease; }
.fl-nav-chevron svg    { width: 14px; height: 14px; }
.fl-nav-chevron.rotated{ transform: rotate(180deg); opacity: 1; }
.fl-nav-section-header:hover .fl-nav-chevron { opacity: 1; }

.fl-nav-submenu {
  max-height: 0;
  overflow: hidden;
  background: rgba(0,0,0,0.1);
  transition: max-height 0.25s ease;
}
.fl-nav-submenu.open { max-height: 300px; }

.fl-nav-subitem {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px 10px 48px;
  width: 100%;
  color: var(--fl-text-secondary);
  font-size: 13px;
  font-weight: 500;
  font-family: var(--fl-font-sans);
  cursor: pointer;
  text-decoration: none;
  border: none;
  background: transparent;
  border-left: 3px solid transparent;
  text-align: left;
  transition: all 0.15s ease;
}
.fl-nav-subitem:hover      { background: rgba(9,122,191,0.08); color: var(--fl-text); }
.fl-nav-subitem:hover svg  { stroke: var(--fl-primary); }
.fl-nav-subitem.active     { background: rgba(9,122,191,0.15); color: var(--fl-text); border-left-color: var(--fl-primary); font-weight: 600; }
.fl-nav-subitem.active svg { stroke: var(--fl-primary); }
.fl-nav-subitem > span     { flex: 1; }

.fl-sidebar-footer { padding: var(--fl-sp-4); border-top: 1px solid var(--fl-border); }

/* ---- 5. Section heading                          [BUDGET] .dash-hero-group-label */
.fl-section        { margin-bottom: 18px; }
.fl-section:last-of-type { margin-bottom: 0; }
.fl-section-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--fl-text-muted);
  margin: 0 0 8px 2px;
}

/* ---- 6. KPI / stat card                    [FPS] .stat-card + [BUDGET] .dash-hero-* */
.fl-kpi-grid {                              /* [FPS] .stats-grid */
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: var(--fl-sp-4);
  margin-bottom: var(--fl-sp-6);
}
.fl-kpi-grid--wide { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); } /* [BUDGET] .dash-hero-grid */

.fl-kpi {
  position: relative;
  overflow: hidden;
  background: var(--fl-surface);
  border: 1px solid var(--fl-border);
  border-radius: var(--fl-radius-lg);
  padding: var(--fl-sp-5);
  text-align: left;
  text-decoration: none;
  color: inherit;
  display: block;
  transition: var(--fl-transition);
}
.fl-kpi:hover              { border-color: var(--fl-border-strong); }
.fl-kpi.interactive        { cursor: pointer; }
.fl-kpi.interactive:hover  { box-shadow: var(--fl-shadow-md); transform: translateY(-1px); }

/* The colored accent bar across the top edge      [FPS] .stat-card::before */
.fl-kpi::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: var(--fl-kpi-bar);
  background: var(--fl-kpi-accent, var(--fl-primary));
}
.fl-kpi--blue   { --fl-kpi-accent: var(--fl-blue); }
.fl-kpi--green  { --fl-kpi-accent: var(--fl-green); }
.fl-kpi--amber  { --fl-kpi-accent: var(--fl-amber); }
.fl-kpi--red    { --fl-kpi-accent: var(--fl-red); }
.fl-kpi--purple { --fl-kpi-accent: var(--fl-purple); }
.fl-kpi--cyan   { --fl-kpi-accent: var(--fl-cyan); }
.fl-kpi--muted  { --fl-kpi-accent: var(--fl-text-muted); }

.fl-kpi-icon {                              /* [FPS] StatCard icon div: 1.5rem, mb .5rem */
  font-size: var(--fl-kpi-icon-size);
  line-height: 1;
  margin-bottom: var(--fl-sp-2);
  color: var(--fl-text-secondary);
}
.fl-kpi-icon svg { width: 1em; height: 1em; stroke: currentColor; fill: none; stroke-width: 2; }

.fl-kpi-value {                             /* [FPS] .card-value 800 @1.75rem; [BUDGET] tabular-nums, lh 1.1 */
  font-size: var(--fl-kpi-value-size);
  font-weight: var(--fl-kpi-value-weight);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: var(--fl-text);
  margin-bottom: 4px;
}
.fl-kpi-label {                             /* [BUDGET] .dash-hero-label */
  font-size: var(--fl-kpi-label-size);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  color: var(--fl-text-muted);
}
.fl-kpi-caption {                           /* [BUDGET] .dash-hero-sub */
  font-size: var(--fl-kpi-caption-size);
  color: var(--fl-text-muted);
  margin-top: 4px;
}
/* Semantic value colouring, optional             [BUDGET] yoy-increase / decrease
   v0.2: text tokens, not raw hues. The value is large text (3:1 threshold) but
   raw green #22c55e is only 2.28:1 on white; Budget itself uses #065f46/#991b1b
   light and #10b981/#f87171 dark for exactly this reason. */
.fl-kpi-value.up   { color: var(--fl-green-text); }
.fl-kpi-value.down { color: var(--fl-red-text); }

/* ---- 7. Tile with header section (no separator)   [OMNI] .dash-card ------ */
.fl-tile {
  background: var(--fl-surface);
  border: 1px solid var(--fl-border);
  border-radius: var(--fl-radius-lg);   /* Omni: 12px = 0.75rem */
  box-shadow: var(--fl-shadow-sm);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  height: 100%;
}
.fl-tile:hover { border-color: var(--fl-border-strong); }

/* Header: title left, pill right. DELTA vs Omni: no border-bottom, no separate
   header background. The header/body distinction is carried by the 16px top
   padding + the title weight, and the body starting at 12px below. */
.fl-tile-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fl-sp-3);
  padding: var(--fl-tile-pad-y) var(--fl-tile-pad-x) 0;
  border-bottom: none;          /* explicit: Omni has 1px solid #e5e7eb / #334155 here */
  background: transparent;      /* explicit: Omni dark has #1a2332 here */
}
.fl-tile-title {
  /* CHOICE: Omni is 0.95rem/700. 0.9375rem/600 lines up with FPS .card-title
     (600) and Budget .card-header h2 (15px/600) so tiles and cards share one
     title weight across the fleet. */
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--fl-text);
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.fl-tile-title svg { width: 16px; height: 16px; color: var(--fl-primary); stroke: currentColor; fill: none; stroke-width: 2; }
.fl-tile-body {
  padding: 12px var(--fl-tile-pad-x) var(--fl-tile-pad-x);   /* Omni .card-body is 20px all round */
  flex: 1;
  min-width: 0;
}
.fl-tile-body--center { text-align: center; }

/* Header pill                                     [OMNI] .badge .bg-info.bg-opacity-25 .text-info, font-size .7rem */
.fl-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;                         /* [FPS] .badge */
  border-radius: var(--fl-radius-pill);
  font-size: 0.7rem;                        /* [OMNI] */
  font-weight: 600;                         /* [OMNI] BY AGREEMENT badge */
  letter-spacing: 0.04em;                   /* [OMNI] BY AGREEMENT badge */
  text-transform: uppercase;
  white-space: nowrap;
  line-height: 1.6;
  /* v0.2 CORRECTION: fill stays the 12%/15% tint, text uses the --fl-*-text
     tokens (see section 1). Raw hue text failed AA at this size. Omni's own
     Bootstrap `.text-info` (#0dcaf0) is 1.96:1 on white -- do not copy it. */
  background: var(--fl-primary-dim);
  color: var(--fl-blue-text);
}
.fl-pill--cyan   { background: var(--fl-cyan-dim);   color: var(--fl-cyan-text); }   /* nearest to Omni's bg-info */
.fl-pill--green  { background: var(--fl-green-dim);  color: var(--fl-green-text); }
.fl-pill--amber  { background: var(--fl-amber-dim);  color: var(--fl-amber-text); }
.fl-pill--red    { background: var(--fl-red-dim);    color: var(--fl-red-text); }
.fl-pill--purple { background: var(--fl-purple-dim); color: var(--fl-purple-text); }
.fl-pill--solid  { background: var(--fl-solid-fill); color: #fff; }             /* [OMNI] BY AGREEMENT; v0.2 hover shade so white clears AA in dark */

/* Big number inside a tile body                   [OMNI] netnew inline: 3rem/700 */
.fl-tile-hero { font-size: 3rem; font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; }
.fl-tile-hero.up   { color: var(--fl-green-text); }   /* v0.2: was raw hue */
.fl-tile-hero.down { color: var(--fl-red-text); }
.fl-tile-note { font-size: 0.85rem; color: var(--fl-text-muted); margin-top: var(--fl-sp-2); } /* [OMNI] .text-muted mt-2 .85rem */

/* ---- 8. Responsive                               [FPS] ---- */
/* v0.3 RULE: below 1024px the rail is off-canvas, so the page MUST render a
   visible menu button (section 9) that opens it as a drawer, and the content
   must fit a 390px screen with no sideways scroll. The breakpoint is FPS's. */
@media (max-width: 1024px) {
  .fl-sidebar       { transform: translateX(-100%); }
  .fl-sidebar.open  { transform: translateX(0); }
  .fl-main          { margin-left: 0; }
  /* .fl-topbar / .fl-menu-btn are switched on at the end of section 9: their
     base display:none is declared there, and a later equal-specificity rule
     would otherwise win. */
}
@media (max-width: 640px) {
  .fl-page     { padding: var(--fl-sp-4); }
  .fl-kpi-grid { grid-template-columns: 1fr 1fr; }
}

/* ---- 9. Menu button + drawer backdrop (v0.3)     [FPS] App.tsx mobile header ---- */
/* Stays in the markup permanently; section 8 shows it only <=1024px. FPS's
   reference is a surface-coloured bar (menu button + app name) above the page
   content; the button alone is enough for apps that already have a top bar.
   Markup:
     <div class="fl-topbar">
       <button class="fl-menu-btn" type="button" aria-label="Open menu"
               aria-controls="sidebar" aria-expanded="false">
         <svg viewBox="0 0 24 24"><line x1="3" y1="6" x2="21" y2="6"/>
           <line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
       </button>
       <span class="fl-topbar-title">App name</span>
     </div>
   Open = add .open to .fl-sidebar and render .fl-sidebar-backdrop; clicking
   the backdrop (or a nav item) closes it.                                   */
.fl-topbar {
  display: none;
  align-items: center;
  gap: var(--fl-sp-3);
  padding: 10px var(--fl-sp-4);                    /* [FPS] .75rem 1rem, rounded to the 4px grid */
  background: var(--fl-surface);
  border-bottom: 1px solid var(--fl-border);
  position: sticky; top: 0;
  z-index: 90;                                     /* under the sidebar (100) and backdrop (99) */
}
.fl-topbar-title { font-size: 0.9375rem; font-weight: 700; color: var(--fl-text); }
.fl-menu-btn {
  display: none;
  align-items: center;
  justify-content: center;
  width: 40px; height: 40px;                       /* CHOICE: >= 24px WCAG 2.2 target; 40 matches a .btn-sm box */
  padding: 0; margin: 0;
  border: 1px solid var(--fl-border);
  border-radius: var(--fl-radius-md);
  background: var(--fl-surface);
  color: var(--fl-text-secondary);                 /* 7.53:1 light / 7.58:1 dark -- visible in BOTH themes */
  cursor: pointer;
  transition: all 0.15s ease;
}
.fl-menu-btn:hover { background: var(--fl-surface-2); color: var(--fl-text); }
.fl-menu-btn svg   { width: 20px; height: 20px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.fl-sidebar-backdrop {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.5);                     /* [FPS] Sidebar.tsx overlay */
  z-index: 99;
}
@media (max-width: 1024px) {                       /* same breakpoint as section 8 */
  .fl-topbar   { display: flex; }
  .fl-menu-btn { display: inline-flex; }
}

/* ---- 10. Collapse control + 52px rail (v0.3)     [OMNI] .sidebar-collapse-toggle ---- */
/* Optional. Where an app offers collapse/expand the control is drawn with
   THEME TOKENS so it is visible in both themes -- rgba(255,255,255,.5) on the
   white light-mode rail (what PM and Perform shipped) is invisible. The
   collapsed rail is 52px: a 40px pill (52 - 2*6 margin) with the 16px icon
   centred, no clipped active pill, no label, no empty submenu band. The class
   goes on .fl-sidebar; .fl-main follows via the sibling selector, so keep the
   sidebar before main in the DOM (as the section 2 markup does). Collapse is a
   desktop affordance: the rules live inside min-width 1025px, so below the
   breakpoint the class is inert and the drawer is always full width.       */
.fl-sidebar-collapse {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: auto 8px 8px;                            /* pinned to the bottom of the rail */
  padding: 10px 14px 10px 20px;                    /* same box as .fl-nav-item */
  width: calc(100% - 16px);
  border: 1px solid var(--fl-border);
  border-radius: var(--fl-radius-md);
  background: transparent;
  color: var(--fl-text-muted);                     /* 4.02:1 light / 6.67:1 dark; hover lifts to --fl-text (a control, not body text) */
  font-family: var(--fl-font-sans);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  text-align: left;
  transition: all 0.15s ease;
}
.fl-sidebar-collapse:hover { background: var(--fl-surface-2); color: var(--fl-text); }
.fl-sidebar-collapse svg   { width: 16px; height: 16px; flex-shrink: 0; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; transition: transform 0.2s ease; }
.fl-sidebar-collapse > span { flex: 1; }
@media (min-width: 1025px) {
  .fl-sidebar.collapsed              { width: 52px; }
  .fl-sidebar.collapsed ~ .fl-main   { margin-left: 52px; }
  .fl-sidebar.collapsed .fl-nav-item,
  .fl-sidebar.collapsed .fl-nav-section-header,
  .fl-sidebar.collapsed .fl-nav-subitem,
  .fl-sidebar.collapsed .fl-sidebar-collapse {
    justify-content: center;
    gap: 0;
    padding: 10px 0;
    margin-left: 6px; margin-right: 6px;
    width: 40px;
    border-left-width: 0;                          /* sub-item rule would offset the icon */
  }
  .fl-sidebar.collapsed .fl-nav-item > span,
  .fl-sidebar.collapsed .fl-nav-section-header > span,
  .fl-sidebar.collapsed .fl-nav-subitem > span,
  .fl-sidebar.collapsed .fl-sidebar-collapse > span,
  .fl-sidebar.collapsed .fl-nav-badge,
  .fl-sidebar.collapsed .fl-nav-chevron,
  .fl-sidebar.collapsed .fl-nav-submenu        { display: none; }
  .fl-sidebar.collapsed .fl-sidebar-collapse svg { transform: rotate(180deg); }
}

/* ---- 11. Icons (v0.3)                            [FPS] Sidebar.tsx ---- */
/* Chrome icons (nav items, group headers, menu / collapse / close buttons,
   tile-title glyphs) are inline SVG line icons in the Feather/lucide style:
   24-unit viewBox, stroke currentColor, fill none, stroke-width 2, round caps
   and joins, rendered at 16px (20px for a group header, 20px for the menu
   button). Not emoji, not an icon font, not a unicode glyph: those ignore
   currentColor, render differently per OS font, and cannot be stroked. The
   nav rules in section 4 already size their own svgs; .fl-icon is the same
   thing for an svg anywhere else (buttons, table cells, KPI icons).        */
.fl-icon {
  width: 16px; height: 16px;
  flex-shrink: 0;
  vertical-align: -3px;
  stroke: currentColor; fill: none;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
