/* =====================================================================
   FoodManuERP Design Tokens - THE single source of visual truth.
   Rules (see CLAUDE.md section 4):
   - Every colour, size, radius, shadow and motion value in the app comes from here.
   - Light theme lives on :root; dark theme overrides the same names under .fm-dark.
   - Never hard-code hex/px in components or pages; reference var(--fm-*).
   - AppTheme.cs maps these values into MudBlazor's palette. Keep both in sync.
   ===================================================================== */

:root {
  /* ---------- Brand & semantic colours (light) ---------- */
  --fm-primary: #3358d4;
  --fm-primary-hover: #2a49b5;
  --fm-primary-soft: #e9eefb;
  --fm-primary-contrast: #ffffff;

  --fm-accent: #3a7bd5;
  --fm-accent-soft: #e6eefa;

  --fm-success: #1f9d55;
  --fm-success-soft: #e4f5ec;
  --fm-success-contrast: #ffffff;
  --fm-warning: #c27c12;
  --fm-warning-soft: #fbf1df;
  --fm-warning-contrast: #1f1300;
  --fm-danger: #d1434b;
  --fm-danger-soft: #fbe6e7;
  --fm-danger-contrast: #ffffff;
  --fm-info: #3a7bd5;
  --fm-info-soft: #e6eefa;
  --fm-neutral: #6b7280;
  --fm-neutral-soft: #eef0f3;

  /* Tone as TEXT, not as a fill. The tone colours above are graphic colours (chips, bars, borders, charts) and
     WCAG only asks 3:1 of those; the same value used for 10.5 px words lands at 3.4-3.8:1, which is what the KPI
     status lines and the plan board's shortage badge were rendering at. These are the same hues carried down to
     clear 4.5:1 on white AND on their own -soft tint. Use --tone-text (kit.css) or these directly for words;
     keep the plain tone for anything drawn rather than read. Dark mode needs no pair: its tones are already 5.6+. */
  --fm-primary-text: #3358d4;
  --fm-success-text: #15773f;
  --fm-warning-text: #8f5b0d;
  --fm-danger-text: #bd2f37;
  --fm-info-text: #2f66b4;
  --fm-neutral-text: #4f5663;

  /* ---------- Surfaces & text (light) ---------- */
  --fm-bg: #f6f6f7;
  --fm-surface: #ffffff;
  --fm-surface-2: #fafafb;
  --fm-surface-3: #f1f2f4;
  /* The row under the cursor. Deliberately well clear of --fm-surface-3: at 5 % grey on white a hover was
     there in theory and invisible in practice across a 1,500 px row. The -active pair is for a row that opens
     something, so the interaction colour carries it. */
  --fm-row-hover: #e6e9ef;
  --fm-row-hover-active: #dee6fa;
  --fm-border: #e5e7ea;
  --fm-border-strong: #d2d5da;
  /* A form field is a WELL, not a patch of page. Measured 2026-09-09: the fill was 1.08:1 against its own
     ground and the border only 1.24:1 against the fill, so "where can I type" was a guess the reader had to
     make. The FILL carries the separation and the border firms the edge; light recesses, so the field is darker
     than the page it sits on.
     Deliberately GENTLE (owner, 2026-09-09, on seeing the first attempt at 1.19:1 - "it is too much"): this is
     ~1.12:1, about half that step. Enough to find a field without looking for it, not enough to make a form of
     nine fields read as nine grey boxes. The border does the rest of the work at --fm-border-strong. */
  --fm-field-bg: #e7eaef;
  --fm-field-border: #d2d5da;
  --fm-field-border-hover: #b9bfc9;
  --fm-text: #1c1f26;
  /* The quiet end of the ramp is MEASURED, not chosen by eye. At 10.5 px (--fm-fs-xs) everything here is
     "small text" to WCAG, so each step has to clear 4.5:1 against the LIGHTEST ground it lands on - which is
     --fm-bg, not white. The old pair failed that: text-3 was 2.87:1 on the page background and carried the
     page-header subtitle, every grid column header, every ErpCodeName code and the row count. The ramp is
     now 15.1 / 7.4 / 5.1 against white, so the three levels still read as three levels. */
  --fm-text-2: #4f5663;
  --fm-text-3: #686e79;
  --fm-text-inverse: #ffffff;
  --fm-overlay: rgba(28, 31, 38, 0.4);
  --fm-focus-ring: #3358d4;          /* solid: a focus indicator needs 3:1, and 30% alpha gave 1.5:1 */

  /* ---------- Chart palette (categorical, fixed order) ---------- */
  --fm-chart-1: #3358d4;
  --fm-chart-2: #c27c12;
  --fm-chart-3: #1f9d55;
  --fm-chart-4: #7c5cc4;
  --fm-chart-5: #1f9c96;
  --fm-chart-6: #c94f86;
  --fm-chart-7: #3a7bd5;
  --fm-chart-8: #8c929c;
  --fm-chart-grid: #e5e7ea;

  /* ---------- Typography ---------- */
  --fm-font-sans: "Inter", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --fm-font-mono: "JetBrains Mono", Consolas, "Courier New", monospace;
  /* A rem here is 14 px, not 16, and that is OUR doing: the `html, body` rule further down this file sets
     font-size to --fm-fs-sm, so the token applies twice - html lands on 14 px (the rem base) and body on
     12.25 px. Measured in Chromium; it is NOT a MudBlazor default. The app was designed, reviewed and approved
     at this rendered scale, so the px values below are the truth, not the aspiration. Write sizes with these
     tokens, never a raw rem, or you get 12.5 % less than you meant. */
  /* 2xs is the small-uppercase micro-label size ONLY (sidebar sections, palette groups, trace band titles,
     keycaps): letterspaced caps that divide content rather than carry it. Never use it for a value someone
     reads - the smallest DATA size is --fm-fs-xs. */
  --fm-fs-2xs: 0.6875rem; /* 9.625 */
  --fm-fs-xs: 0.75rem;   /* 10.5 */
  --fm-fs-sm: 0.875rem;  /* 12.25 */
  --fm-fs-md: 1rem;      /* 14 */
  --fm-fs-lg: 1.25rem;   /* 17.5 */
  --fm-fs-xl: 1.5rem;    /* 21 */
  --fm-fs-2xl: 2rem;     /* 28 */
  --fm-fs-3xl: 2.5rem;   /* 35 */
  --fm-fw-regular: 400;
  --fm-fw-medium: 500;
  --fm-fw-semibold: 600;
  --fm-fw-bold: 700;
  --fm-lh-tight: 1.25;
  --fm-lh-normal: 1.5;

  /* ---------- Spacing (4px base) ---------- */
  --fm-space-1: 4px;
  --fm-space-2: 8px;
  --fm-space-3: 12px;
  --fm-space-4: 16px;
  --fm-space-5: 20px;
  --fm-space-6: 24px;
  --fm-space-8: 32px;
  --fm-space-10: 40px;
  --fm-space-12: 48px;
  --fm-space-16: 64px;

  /* ---------- Radius ---------- */
  --fm-radius-sm: 6px;
  --fm-radius-md: 8px;
  --fm-radius-lg: 10px;
  --fm-radius-xl: 14px;
  --fm-radius-full: 999px;

  /* ---------- Elevation (soft, low-chrome) ---------- */
  --fm-shadow-1: 0 1px 2px rgba(28, 31, 38, 0.04);
  --fm-shadow-2: 0 3px 10px rgba(28, 31, 38, 0.07);
  --fm-shadow-3: 0 10px 28px rgba(28, 31, 38, 0.12);

  /* ---------- Motion ---------- */
  --fm-motion-fast: 120ms;
  --fm-motion-base: 200ms;
  --fm-motion-slow: 320ms;
  --fm-ease: cubic-bezier(0.2, 0, 0, 1);

  /* ---------- Layout ---------- */
  --fm-sidebar-w: 248px;
  --fm-sidebar-w-mini: 72px;
  --fm-topbar-h: 56px;
  --fm-page-max-w: 1600px;
  --fm-page-pad: var(--fm-space-6);
  --fm-grid-gap: var(--fm-space-4);

  /* ---------- Z-index ---------- */
  /* MudBlazor stack: drawer 1100, popover 1200, appbar 1300, dialog 1400, snackbar 1500, tooltip 1600.
     Our slide-over sits above the sidebar and below popovers, and starts under the top bar. */
  --fm-z-sticky: 10;
  --fm-z-drawer: 1150;
  --fm-z-dialog: 1400;
  --fm-z-toast: 1500;

  /* ---------- Floor (tablet) ---------- */
  --fm-floor-target: 56px;      /* minimum touch target height */
  --fm-floor-target-lg: 80px;   /* primary action height */
  /* Same 14 px rem base as the desktop scale above, so these render 12.5 % under the round number they were
     chosen for; the px in the comments is what the tablet actually shows. These were picked for arm's-length
     reading, so if a real terminal ever reads short, this scale is the first place to look. */
  --fm-floor-fs-sm: 1.125rem;   /* 15.75 */
  --fm-floor-fs-md: 1.5rem;     /* 21 */
  --fm-floor-fs-lg: 2.25rem;    /* 31.5 */
  --fm-floor-fs-xl: 3.5rem;     /* 49 - numeric readouts */
  --fm-floor-gap: var(--fm-space-4);
  --fm-floor-radius: var(--fm-radius-lg);

  color-scheme: light;
}

/* =====================================================================
   Dark theme: same token names, different values. Toggled by adding
   class "fm-dark" to <html> (ThemeService does this).
   ===================================================================== */
.fm-dark {
  --fm-primary: #6f8fff;
  --fm-primary-hover: #8fa8ff;
  --fm-primary-soft: rgba(111, 143, 255, 0.16);
  --fm-primary-contrast: #0f1115;

  --fm-accent: #6aa3f0;
  --fm-accent-soft: rgba(106, 163, 240, 0.16);

  --fm-success: #45c17c;
  --fm-success-soft: rgba(69, 193, 124, 0.16);
  --fm-success-contrast: #0f1115;
  --fm-warning: #e0a03a;
  --fm-warning-soft: rgba(224, 160, 58, 0.16);
  --fm-warning-contrast: #0f1115;
  --fm-danger: #ef6b71;
  --fm-danger-soft: rgba(239, 107, 113, 0.16);
  --fm-danger-contrast: #0f1115;
  --fm-info: #6aa3f0;
  --fm-info-soft: rgba(106, 163, 240, 0.16);
  --fm-neutral: #9aa0ab;
  --fm-neutral-soft: rgba(154, 160, 171, 0.14);
  /* On the dark ground the tones already measure 5.6:1 and up, so text uses them unchanged. */
  --fm-primary-text: var(--fm-primary);
  --fm-success-text: var(--fm-success);
  --fm-warning-text: var(--fm-warning);
  --fm-danger-text: var(--fm-danger);
  --fm-info-text: var(--fm-info);
  --fm-neutral-text: var(--fm-neutral);

  --fm-bg: #0f1115;
  --fm-surface: #16181d;
  --fm-surface-2: #1b1e24;
  --fm-surface-3: #22262e;
  --fm-row-hover: #2a2f3a;
  --fm-row-hover-active: #23304d;
  --fm-border: #2a2e37;
  --fm-border-strong: #3a3f4a;
  /* Dark RAISES instead of recessing, and that is arithmetic rather than taste: the page ground is #0f1115,
     so going darker has almost nowhere to go - pure black would still only reach 1.10:1 - while going lighter
     reads as the same well with room to spare. Kept gentle to match light: ~1.15:1. */
  --fm-field-bg: #1c1f27;
  --fm-field-border: #3a3f4a;
  --fm-field-border-hover: #4a5160;
  --fm-text: #e6e7ea;
  --fm-text-2: #a2a7b2;
  --fm-text-3: #8b919d;   /* was #6f7580 = 4.08:1 on the dark ground; now 5.97:1 */
  --fm-text-inverse: #0b1220;
  --fm-overlay: rgba(0, 0, 0, 0.6);
  --fm-focus-ring: #93b0ff;          /* solid, and light enough to read on the dark ground */

  --fm-chart-1: #6f8fff;
  --fm-chart-2: #e0a03a;
  --fm-chart-3: #45c17c;
  --fm-chart-4: #a58cf0;
  --fm-chart-5: #4ec4bd;
  --fm-chart-6: #e07aa8;
  --fm-chart-7: #6aa3f0;
  --fm-chart-8: #9aa0ab;
  --fm-chart-grid: #2a2e37;

  --fm-shadow-1: 0 1px 2px rgba(0, 0, 0, 0.35);
  --fm-shadow-2: 0 3px 10px rgba(0, 0, 0, 0.4);
  --fm-shadow-3: 0 10px 28px rgba(0, 0, 0, 0.5);

  color-scheme: dark;
}


/* =====================================================================
   Base reset & global type. Keep minimal; components own their styles.
   ===================================================================== */
html, body {
  margin: 0;
  padding: 0;
  background: var(--fm-bg);
  color: var(--fm-text);
  font-family: var(--fm-font-sans);
  font-size: var(--fm-fs-sm);
  line-height: var(--fm-lh-normal);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

*:focus-visible {
  outline: 2px solid var(--fm-focus-ring);
  outline-offset: 2px;
}

/* MudBlazor removes the outline on its own buttons and links and relies on a ripple, which leaves a keyboard
   user with a 6% grey tint (measured 1.08:1) to find themselves by. Its rules carry a class, so the bare
   `*:focus-visible` above loses; these mirror that shape and add an `html` prefix to win. */
html .mud-button-root:focus-visible,
html .mud-icon-button:focus-visible,
html .mud-nav-link:focus-visible,
html .mud-table-row:focus-visible,
html .mud-list-item:focus-visible,
html a:focus-visible {
  outline: 2px solid var(--fm-focus-ring);
  outline-offset: 2px;
}

/* Utility classes allowed in pages (tokens only). */
.fm-text-2 { color: var(--fm-text-2); }
.fm-text-danger { color: var(--fm-danger); }
.fm-text-3 { color: var(--fm-text-3); }
.fm-mono { font-family: var(--fm-font-mono); }
.fm-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fm-stack { display: flex; flex-direction: column; gap: var(--fm-space-4); }
.fm-row { display: flex; align-items: center; gap: var(--fm-space-3); }
/* Grid cell holding a value plus a chip (expiry + state): one line, never split. */
.fm-cell { display: inline-flex; align-items: center; gap: var(--fm-space-2); white-space: nowrap; }
.fm-grow { flex: 1 1 auto; min-width: 0; }

/* Skeleton shimmer used by ErpSkeleton and grids. */
@keyframes fm-shimmer {
  0% { background-position: -400px 0; }
  100% { background-position: 400px 0; }
}
.fm-skeleton {
  border-radius: var(--fm-radius-sm);
  background: linear-gradient(90deg, var(--fm-surface-3) 25%, var(--fm-surface-2) 37%, var(--fm-surface-3) 63%);
  background-size: 800px 100%;
  animation: fm-shimmer 1.4s var(--fm-ease) infinite;
}
