/* =========================================================================
   DEX-OS — DESIGN TOKENS
   =========================================================================

   Every value the interface uses, defined once. Components reference tokens
   and never literals, so a change here changes the whole system and a change
   anywhere else is a bug.

   ── The brief this is answering ──────────────────────────────────────────
   This is an internal system that finance clerks in Lagos and warehouse staff
   in Johannesburg look at for eight hours a day. It optimises for legibility
   at density, low eye fatigue, and unmistakable state — is this row archived,
   is this approval mine, is this figure masked.

   That is a different problem from a storefront. A high-contrast accent that
   looks superb on one hero image becomes exhausting across a 200-row invoice
   list, so the working surface is deliberately quiet and the identity lives
   in the chrome.

   ========================================================================= */

:root {
    /* ─── NEUTRALS ────────────────────────────────────────────────────────
       Very slightly cool rather than pure grey. Pure #808080 greys read as
       dead against white and make long sessions feel harsh; a few degrees of
       blue keeps large surfaces calm without anyone noticing why.          */
    --dx-neutral-0:   #ffffff;
    --dx-neutral-25:  #fcfcfd;
    --dx-neutral-50:  #f8f9fb;
    --dx-neutral-100: #f1f3f7;
    --dx-neutral-150: #e8ebf1;
    --dx-neutral-200: #dde1ea;
    --dx-neutral-300: #c3c9d6;
    --dx-neutral-400: #9aa2b4;
    --dx-neutral-500: #737c91;
    --dx-neutral-600: #565e72;
    --dx-neutral-700: #3f4658;
    --dx-neutral-800: #2a3040;
    --dx-neutral-900: #1a1e2b;
    --dx-neutral-950: #11141d;

    /* ─── IDENTITY ────────────────────────────────────────────────────────
       DEX EMPIRE green, taken down from a signage lime to something that can
       sit next to text without vibrating. Used in the chrome, the active
       state and nowhere that competes with data.                           */
    --dx-brand-50:  #eefbf3;
    --dx-brand-100: #d5f5e2;
    --dx-brand-200: #ade9c9;
    --dx-brand-300: #77d6a8;
    --dx-brand-400: #41bd85;
    --dx-brand-500: #1c9f68;   /* primary */
    --dx-brand-600: #0f8054;
    --dx-brand-700: #0c6644;
    --dx-brand-800: #0b5138;
    --dx-brand-900: #09432f;

    /* ─── SEMANTIC ────────────────────────────────────────────────────────
       Deliberately distinguishable without relying on hue alone — every
       status also carries a label and a shape. Roughly 8% of men have some
       colour vision deficiency, and this system is read by warehouse and
       finance staff across five countries.                                 */
    --dx-success-50:  #eefbf3;
    --dx-success-500: #1c9f68;
    --dx-success-700: #0c6644;

    --dx-warning-50:  #fff8eb;
    --dx-warning-500: #d97706;
    --dx-warning-700: #92400e;

    --dx-danger-50:   #fef2f2;
    --dx-danger-500:  #dc2626;
    --dx-danger-700:  #991b1b;

    --dx-info-50:     #eff6ff;
    --dx-info-500:    #2563eb;
    --dx-info-700:    #1d4ed8;

    /* RESTRICTED fields (§6.2 L5). Distinct from every other state — a
       masked value must never be mistaken for an empty one.                */
    --dx-restricted-bg: #f4f1fb;
    --dx-restricted-fg: #6d4aa8;

    /* ─── SURFACES ────────────────────────────────────────────────────────*/
    --dx-bg-app:      var(--dx-neutral-50);
    --dx-bg-surface:  var(--dx-neutral-0);
    --dx-bg-sunken:   var(--dx-neutral-100);
    --dx-bg-chrome:   var(--dx-neutral-950);
    --dx-bg-hover:    var(--dx-neutral-100);
    --dx-bg-selected: var(--dx-brand-50);

    /* ─── INK ─────────────────────────────────────────────────────────────
       Never pure black on white. #000 on #fff is a contrast ratio of 21:1,
       which is past the point of comfort and produces halation on long
       reads. 900 on 0 gives roughly 15:1 — still far above WCAG AAA.       */
    --dx-ink-primary:   var(--dx-neutral-900);
    --dx-ink-secondary: var(--dx-neutral-600);
    --dx-ink-tertiary:  var(--dx-neutral-500);
    --dx-ink-disabled:  var(--dx-neutral-400);
    --dx-ink-inverse:   var(--dx-neutral-0);
    --dx-ink-brand:     var(--dx-brand-700);

    /* ─── BORDERS ─────────────────────────────────────────────────────────
       Structure comes from hairlines, not shadows. Dense data tables with
       drop shadows look busy and print badly, and this system will be
       printed — §6.2 lists `print` as an audited action for a reason.      */
    --dx-border-subtle: var(--dx-neutral-150);
    --dx-border-default: var(--dx-neutral-200);
    --dx-border-strong: var(--dx-neutral-300);
    --dx-border-focus:  var(--dx-brand-500);

    /* ─── TYPE ────────────────────────────────────────────────────────────
       System stack: it renders instantly, matches the OS the user already
       trusts, and adds no webfont request to a screen that may be opened
       five hundred times a day over Nigerian mobile data.                  */
    --dx-font-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI",
                    Roboto, "Helvetica Neue", Arial, sans-serif;

    /* Tabular figures matter more here than the typeface does. Money in a
       column must align digit for digit or the eye cannot scan it.         */
    --dx-font-mono: ui-monospace, "SF Mono", "Cascadia Mono", "Segoe UI Mono",
                    "Roboto Mono", Menlo, Consolas, monospace;

    --dx-text-2xs: 0.6875rem;  /* 11px — metadata, table meta only          */
    --dx-text-xs:  0.75rem;    /* 12px — labels, badges                     */
    --dx-text-sm:  0.8125rem;  /* 13px — table body. The workhorse.         */
    --dx-text-base:0.875rem;   /* 14px — forms, body                        */
    --dx-text-md:  1rem;       /* 16px — section headings                   */
    --dx-text-lg:  1.125rem;   /* 18px — page titles                        */
    --dx-text-xl:  1.375rem;   /* 22px — dashboard figures                  */
    --dx-text-2xl: 1.75rem;    /* 28px — hero metrics                       */

    --dx-weight-normal:   400;
    --dx-weight-medium:   500;
    --dx-weight-semibold: 600;
    --dx-weight-bold:     700;

    --dx-leading-tight:   1.25;
    --dx-leading-normal:  1.5;
    --dx-leading-relaxed: 1.65;

    /* Slight negative tracking on large text only. Applying it to 13px body
       text is the most common way an interface becomes quietly harder to
       read while looking more designed.                                    */
    --dx-tracking-tight:  -0.011em;
    --dx-tracking-normal: 0;
    --dx-tracking-wide:   0.04em;

    /* ─── SPACE ───────────────────────────────────────────────────────────
       4px base. Everything is a multiple, so vertical rhythm holds without
       anyone measuring.                                                    */
    --dx-space-0:  0;
    --dx-space-1:  0.25rem;
    --dx-space-2:  0.5rem;
    --dx-space-3:  0.75rem;
    --dx-space-4:  1rem;
    --dx-space-5:  1.25rem;
    --dx-space-6:  1.5rem;
    --dx-space-8:  2rem;
    --dx-space-10: 2.5rem;
    --dx-space-12: 3rem;
    --dx-space-16: 4rem;

    /* ─── RADIUS ──────────────────────────────────────────────────────────
       Restrained. Heavy rounding reads as consumer software and costs
       horizontal space in dense tables.                                    */
    --dx-radius-sm:   3px;
    --dx-radius-md:   5px;
    --dx-radius-lg:   8px;
    --dx-radius-xl:   12px;
    --dx-radius-full: 999px;

    /* ─── ELEVATION ───────────────────────────────────────────────────────
       Only for things that genuinely float. Everything else uses a border. */
    --dx-shadow-xs: 0 1px 2px rgba(17, 20, 29, 0.04);
    --dx-shadow-sm: 0 1px 3px rgba(17, 20, 29, 0.06), 0 1px 2px rgba(17, 20, 29, 0.04);
    --dx-shadow-md: 0 4px 12px rgba(17, 20, 29, 0.08), 0 2px 4px rgba(17, 20, 29, 0.04);
    --dx-shadow-lg: 0 12px 32px rgba(17, 20, 29, 0.12), 0 4px 8px rgba(17, 20, 29, 0.06);
    --dx-shadow-focus: 0 0 0 3px rgba(28, 159, 104, 0.18);

    /* ─── LAYOUT ──────────────────────────────────────────────────────────*/
    --dx-rail-width:          232px;
    --dx-rail-width-collapsed: 56px;
    --dx-topbar-height:       52px;
    --dx-row-height:          38px;
    --dx-row-height-compact:  32px;

    /* ─── MOTION ──────────────────────────────────────────────────────────
       Fast and few. In a tool people use all day, animation is latency.    */
    --dx-ease: cubic-bezier(0.2, 0, 0.13, 1);
    --dx-duration-instant: 80ms;
    --dx-duration-fast:    140ms;
    --dx-duration-normal:  220ms;

    --dx-z-rail:    100;
    --dx-z-topbar:  200;
    --dx-z-dropdown: 400;
    --dx-z-overlay: 600;
    --dx-z-modal:   700;
    --dx-z-toast:   900;
}

/* =========================================================================
   DARK THEME
   =========================================================================
   Not an inversion. Inverted palettes produce grey text on near-black that
   smears, because light text on dark reads visually heavier at the same
   weight. Surfaces are lifted rather than flipped, and ink is pulled back
   from pure white for the same halation reason as above.
   ========================================================================= */

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --dx-bg-app:      #0d1017;
        --dx-bg-surface:  #141822;
        --dx-bg-sunken:   #0d1017;
        --dx-bg-chrome:   #090b11;
        --dx-bg-hover:    #1c2130;
        --dx-bg-selected: rgba(28, 159, 104, 0.14);

        --dx-ink-primary:   #e6e9f0;
        --dx-ink-secondary: #a3abbd;
        --dx-ink-tertiary:  #79819a;
        --dx-ink-disabled:  #545c72;
        --dx-ink-inverse:   #0d1017;
        --dx-ink-brand:     var(--dx-brand-300);

        --dx-border-subtle:  #1e2431;
        --dx-border-default: #29313f;
        --dx-border-strong:  #39424f;

        --dx-success-50: rgba(28, 159, 104, 0.14);
        --dx-warning-50: rgba(217, 119, 6, 0.14);
        --dx-danger-50:  rgba(220, 38, 38, 0.14);
        --dx-info-50:    rgba(37, 99, 235, 0.14);

        --dx-restricted-bg: rgba(109, 74, 168, 0.18);
        --dx-restricted-fg: #b9a3e8;

        --dx-shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.3);
        --dx-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4);
        --dx-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.45);
        --dx-shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.55);
    }
}

:root[data-theme="dark"] {
    --dx-bg-app:      #0d1017;
    --dx-bg-surface:  #141822;
    --dx-bg-sunken:   #0d1017;
    --dx-bg-chrome:   #090b11;
    --dx-bg-hover:    #1c2130;
    --dx-bg-selected: rgba(28, 159, 104, 0.14);

    --dx-ink-primary:   #e6e9f0;
    --dx-ink-secondary: #a3abbd;
    --dx-ink-tertiary:  #79819a;
    --dx-ink-disabled:  #545c72;
    --dx-ink-inverse:   #0d1017;
    --dx-ink-brand:     var(--dx-brand-300);

    --dx-border-subtle:  #1e2431;
    --dx-border-default: #29313f;
    --dx-border-strong:  #39424f;

    --dx-success-50: rgba(28, 159, 104, 0.14);
    --dx-warning-50: rgba(217, 119, 6, 0.14);
    --dx-danger-50:  rgba(220, 38, 38, 0.14);
    --dx-info-50:    rgba(37, 99, 235, 0.14);

    --dx-restricted-bg: rgba(109, 74, 168, 0.18);
    --dx-restricted-fg: #b9a3e8;

    --dx-shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.3);
    --dx-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4);
    --dx-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.45);
    --dx-shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.55);
}

/* Respect the user's motion preference. Vestibular disorders are not rare,
   and this is software people cannot choose not to use. */
@media (prefers-reduced-motion: reduce) {
    :root {
        --dx-duration-instant: 0ms;
        --dx-duration-fast:    0ms;
        --dx-duration-normal:  0ms;
    }
}
