/* ============================================================
   Elioplus Design System - design tokens
   ============================================================

   Every global custom property the design system defines, and the only place a
   raw colour, size or radius is written down.

   Two layers, in this order:

     1. PRIMITIVES   raw values with no meaning attached (ramps, radii, shadows).
                     Nothing here names a role or a product concept.
     2. SEMANTICS    what a value is FOR (--ds-text-muted, --ds-border,
                     --ds-success). This is the layer a consuming application's
                     components should reach for; the primitives above exist so
                     these have somewhere to point.

   One neutral ramp. Tailwind gray and slate were both in use for the same roles
   in the application this came from, alongside five older Chakra-era greys.
   Every call site was classified by what it is FOR and moved onto the semantic
   layer, and the duplicate ramps are gone.

   Nothing in this file may name a product concept. A consuming application keeps
   its own brand values in its own stylesheet, linked after this one, where it may
   both add tokens and override any semantic defined here - see the load order in
   README.md.

   The MudBlazor theme a consumer builds has to agree with these values, because
   MudBlazor's theme is C# and cannot read CSS. Elioplus.DesignSystem.Theming
   .DesignTokens.FindDrift() reads this file back out of the assembly and reports
   any entry that has drifted.
   ============================================================ */
/* ── 1. Primitives ─────────────────────────────────────────── */

:root {
    /* Neutral - Tailwind "gray". The dominant ramp in the dashboard and admin. */
    --ds-gray-50:   #f9fafb;
    --ds-gray-100:  #f3f4f6;
    --ds-gray-200:  #e5e7eb;
    --ds-gray-300:  #d1d5db;
    --ds-gray-400:  #9ca3af;
    /* Off-ramp step. Tailwind has nothing between 400 and 500, and the boundary of an
       input needs 3:1 against both white and the alt surface; 400 manages 2.5 and 500 is
       heavy enough to read as filled. This is the lightest value that clears it (3.34). */
    --ds-gray-450:  #858d9b;
    --ds-gray-500:  #6b7280;
    --ds-gray-600:  #4b5563;
    --ds-gray-700:  #374151;
    --ds-gray-800:  #1f2937;
    --ds-gray-900:  #111827;

    --ds-white: #ffffff;

    /* Blue */
    --ds-blue-50:  #eff6ff;
    --ds-blue-100: #dbeafe;
    --ds-blue-200: #bfdbfe;
    --ds-blue-500: #3b82f6;
    --ds-blue-600: #2563eb;
    --ds-blue-700: #1d4ed8;
    --ds-blue-900: #1e3a8a;

    /* Indigo / violet */
    --ds-indigo-50:  #eef2ff;
    --ds-indigo-100: #e0e7ff;
    --ds-indigo-500: #6366f1;
    --ds-indigo-600: #4f46e5;
    --ds-indigo-700: #4338ca;

    /* Green */
    --ds-green-50:  #f0fdf4;
    --ds-green-100: #d1fae5;
    --ds-green-500: #10b981;
    --ds-green-600: #059669;
    --ds-green-700: #047857;
    --ds-green-800: #065f46;

    /* Amber */
    --ds-amber-100: #fef3c7;
    --ds-amber-500: #f59e0b;
    --ds-amber-600: #d97706;
    --ds-amber-800: #92400e;

    /* Red */
    --ds-red-50:  #fef2f2;
    --ds-red-100: #fee2e2;
    --ds-red-500: #ef4444;
    --ds-red-600: #dc2626;
    --ds-red-800: #991b1b;

    /* Type scale. The sizes in use, named once so the same size
       stops being written three ways - 12px, 0.75rem and .75rem were all the same
       thing, as were 14px/0.875rem and 13px/0.8125rem. Values are px because the rem
       values here were all authored against the 16px root and gain nothing from being
       relative. 13px is this system's body size; 14px is MudBlazor's. */
    --ds-text-10: 10px;
    --ds-text-11: 11px;
    --ds-text-12: 12px;
    --ds-text-13: 13px;
    --ds-text-14: 14px;
    --ds-text-15: 15px;
    --ds-text-16: 16px;
    --ds-text-18: 18px;
    --ds-text-20: 20px;
    --ds-text-22: 22px;
    --ds-text-24: 24px;
    --ds-text-28: 28px;
    --ds-text-32: 32px;

    /* Line height for a heading, which needs less than running text. */
    --ds-leading-tight: 1.3;

    /* Weights */
    --ds-weight-medium:   500;
    --ds-weight-semibold: 600;
    --ds-weight-bold:     700;

    /* Radii - the sizes actually in use. */
    --ds-radius-sm:   6px;
    --ds-radius-md:   8px;
    --ds-radius-lg:   12px;
    /* A fully-rounded pill; used by DsStatusBadge. */
    --ds-radius-pill: 999px;

    /* The type family the system is designed against, and what html/body is set to.
       A consuming application overrides this in its own brand stylesheet. */
    --ds-font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

    /* Shadows */
    --ds-shadow-md: 0 4px 16px rgba(0, 0, 0, 0.07);
}

/* ── 2. Semantics ──────────────────────────────────────────── */

:root {
    /* Text. --ds-text-primary is the strong heading colour; --ds-text-body is the
       everyday paragraph colour. Both are in heavy use and are not the same value. */
    --ds-text-primary:   var(--ds-gray-900);
    --ds-text-body:      var(--ds-gray-700);
    --ds-text-secondary: var(--ds-gray-500);
    /* Muted is text a user still has to read - timestamps, counts, helper lines - so it
       has to clear 4.5:1. It used to be gray-400 at 2.5:1. Three *readable* grey levels
       cannot all pass on white and still look distinct, so the third level moved to a
       different job: --ds-text-disabled below, for content that is switched off or
       purely decorative, which WCAG exempts. */
    --ds-text-muted:     var(--ds-gray-500);
    --ds-text-disabled:  var(--ds-gray-400);
    --ds-text-inverse:   var(--ds-white);

    /* Surfaces */
    --ds-surface:        var(--ds-white);
    --ds-surface-alt:    var(--ds-gray-50);
    --ds-surface-sunken: var(--ds-gray-100);
    /* A neutral chip, count badge or overflow tag sits one step above sunken, so that it
       reads as a token placed ON a card rather than as a recess in it. */
    --ds-surface-chip:   var(--ds-gray-200);

    /* Lines. Four jobs, not one:
         --ds-border          the edge of a card or panel. Decorative: the surface is
                              identifiable without it, so it is not held to 3:1.
         --ds-divider         the hairline between rows in a list or table.
         --ds-border-emphasis a heavier edge - outlined buttons, hover and drop states.
         --ds-border-input    the boundary of a text field, which IS the affordance a
                              user has to see, so this one clears 3:1 (3.34 on white).
         --ds-border-hover    what an outlined control's edge darkens to on hover. It is
                              a transient state on an already-visible boundary, so it is
                              not held to 3:1 on its own. */
    --ds-border:          var(--ds-gray-200);
    --ds-divider:         var(--ds-gray-100);
    --ds-border-emphasis: var(--ds-gray-300);
    --ds-border-input:    var(--ds-gray-450);
    --ds-border-hover:    var(--ds-gray-400);

    /* Accent. These are the system's default brand values, not a law: an application
       with its own palette redefines them in its brand stylesheet, which is linked
       after this file, and everything pointing at them follows.

       Whatever a consumer settles on, its MudBlazor theme has to carry the same
       values, or a Color.Primary control and a CSS rule render two different blues.
       DesignTokens.FindDrift() exists to catch exactly that. */
    --ds-primary:          #2f6fe4;
    --ds-primary-hover:    #2460cc;
    --ds-primary-strong:   var(--ds-blue-700);
    --ds-primary-surface:  var(--ds-blue-100);
    --ds-primary-subtle:   var(--ds-blue-50);
    --ds-secondary:        #596dd9;
    --ds-tertiary:         var(--ds-indigo-600);

    /* Status, each with the surface and on-surface text used by its badge.
       The base colours are the ones a filled button or chip is painted with, so each
       has to carry its own label legibly. Success, error and info sit one ramp step
       darker than the mid-tone for that reason - white on green-500 is 2.5:1, on
       green-700 it is 5.5:1. Amber is the exception: no amber that passes with white
       is still amber, so warning keeps its hue and takes dark ink instead. */
    --ds-success:         var(--ds-green-700);
    --ds-success-surface: var(--ds-green-100);
    --ds-success-text:    var(--ds-green-800);

    --ds-warning:          var(--ds-amber-500);
    --ds-warning-surface:  var(--ds-amber-100);
    --ds-warning-text:     var(--ds-amber-800);
    /* The ink a filled warning surface carries: white on amber-500 is 2.2:1. */
    --ds-warning-contrast: var(--ds-gray-900);

    --ds-error:           var(--ds-red-600);
    --ds-error-surface:   var(--ds-red-100);
    --ds-error-text:      var(--ds-red-800);

    --ds-info:            var(--ds-blue-600);
    --ds-info-surface:    var(--ds-blue-100);
    --ds-info-text:       var(--ds-blue-700);

    /* Blazor form validation and the error boundary. These are the framework
       template's own colours, kept at their original values and named here so an
       application can restyle them without overriding the rules in base.css. */
    --ds-valid:          #26b050;
    --ds-invalid:        #e50000;
    --ds-error-boundary: #b32121;
}
