/**
 * TrackIt design tokens — "Graphite".
 *
 * Every colour, space, radius and shadow in the app resolves to a token here.
 * Restyling means editing this file, not hunting through an 11,000-line HTML
 * document.
 *
 * This also replaces the previous dark-mode approach, which redefined
 * Tailwind's own utility classes globally:
 *
 *     .dark .text-gray-800 { color: #e2e8f0; }
 *     .dark .bg-gray-50    { background-color: #1e293b; }
 *
 * That hijacks every element using those utilities, including ones that chose
 * them for unrelated reasons, so a change intended for body text silently
 * repainted borders, chips and disabled states. Semantic tokens swap by role
 * instead, so nothing is affected at a distance.
 *
 * Theme switching keys off `html.dark`, matching the existing
 * `tailwind.config = { darkMode: 'class' }` setup.
 *
 * Direction: high contrast, tight geometry, vivid data. The app is used on a
 * phone in kitchens and gyms -- glanced at, in bad light -- so legibility margin
 * was weighted over softness.
 */

:root {
    /* ---- Surfaces ------------------------------------------------------ */
    --tk-page: #f4f6f8;
    --tk-surface: #ffffff;
    --tk-surface-raised: #ffffff;
    --tk-surface-sunken: #e8ecf1;
    --tk-surface-inverse: #0a0e14;

    /* ---- Ink ----------------------------------------------------------- */
    --tk-ink: #0a0e14;
    --tk-ink-secondary: #3d4855;
    /* Raised from #6b7787, which failed AA. Muted text is the app's most
       common secondary voice -- hero labels, units, the inactive nav -- and it
       measured 4.20 on --tk-page and 3.84 on --tk-surface-sunken against a 4.5
       floor. This clears 5.00 / 5.42 / 4.57 on page / surface / sunken. */
    --tk-ink-muted: #5f6b7b;
    --tk-ink-inverse: #ffffff;

    /* ---- Lines --------------------------------------------------------- */
    --tk-border: rgba(10, 14, 20, 0.12);
    --tk-border-strong: rgba(10, 14, 20, 0.24);
    --tk-ring: rgba(124, 58, 237, 0.35);

    /* ---- Brand --------------------------------------------------------- */
    /* Primary actions are ink, not a hue. The three macro hues below are the
       only saturated colour in the product, so a coloured button would compete
       with the data for attention and risk reading as a fourth series. Violet
       is the accent for focus, links and Pro -- chosen because it is far from
       all three macro hues. */
    --tk-action: #0a0e14;
    --tk-action-hover: #1c2531;
    --tk-action-ink: #ffffff;
    --tk-accent: #7c3aed;
    --tk-accent-hover: #6b2bd9;
    --tk-accent-soft: #f0e9fe;
    /* The app icon's purple-to-pink, for the signed-out home page's headline.
       Darker stops in light mode so the pink end still clears 3:1 on white
       at headline size. */
    --tk-brand-gradient: linear-gradient(120deg, #7c3aed 0%, #c026d3 55%, #e11d74 100%);

    /* ---- Macro series -------------------------------------------------- */
    /* Validated as a categorical palette against this surface, all pairs, both
       modes (dataviz scripts/validate_palette.js). Worst colour-blind
       separation dE 11.5 light / 11.0 dark; worst normal-vision 28.4 / 24.6.
       Protein/carbs/fat carry the three hues; secondary nutrients stay neutral
       rather than taking a fourth, which cannot clear the CVD floors alongside
       these three. */
    --tk-protein: #2563eb;
    --tk-carbs: #f97316;
    --tk-fat: #10b981;
    --tk-protein-soft: #e5edfd;
    --tk-carbs-soft: #fdeee1;
    --tk-fat-soft: #e0f7ef;
    --tk-nutrient-neutral: #6b7787;

    /* ---- Status (fixed, never themed) ---------------------------------- */
    /* Reserved. Never reused for a series, and always shipped with an icon or
       label so state is not carried by colour alone. */
    --tk-good: #0ca30c;
    --tk-warning: #fab219;
    --tk-serious: #ec835a;
    --tk-critical: #d03b3b;
    --tk-streak: #f59e0b;

    /* The same hues as *text*. The five above are validated as marks -- a dot,
       a border, a chart series -- and moving them would invalidate that. As
       text they answer to 4.5:1 instead, and measured against the surfaces
       they actually appear on, three of the six theme/colour combinations
       failed: light good 3.10, light warning 1.55, dark critical 3.29. Where a
       hue already passed, its ink is the hue. Use these for text and for a
       chip's label; keep the base for the mark. */
    --tk-good-ink: #097b09;
    --tk-warning-ink: #8d6103;
    --tk-critical-ink: #bd2e2e;

    /* ---- Type ---------------------------------------------------------- */
    --tk-font: 'Inter', 'Noto Sans SC', system-ui, -apple-system, 'Segoe UI', sans-serif;
    --tk-text-xs: 0.75rem;
    --tk-text-sm: 0.875rem;
    --tk-text-base: 1rem;
    --tk-text-lg: 1.125rem;
    --tk-text-xl: 1.375rem;
    --tk-text-2xl: 1.75rem;
    --tk-text-hero: 2.75rem;

    /* ---- Space --------------------------------------------------------- */
    --tk-space-1: 0.25rem;
    --tk-space-2: 0.5rem;
    --tk-space-3: 0.75rem;
    --tk-space-4: 1rem;
    --tk-space-5: 1.5rem;
    --tk-space-6: 2rem;

    /* ---- Radius -------------------------------------------------------- */
    /* Tight geometry is the defining move of this direction. */
    --tk-radius-sm: 0.375rem;
    --tk-radius: 0.5rem;
    --tk-radius-lg: 0.625rem;
    --tk-radius-full: 999px;

    /* ---- Elevation ----------------------------------------------------- */
    /* Crisp and shallow -- definition comes from the hairline, not the blur. */
    --tk-shadow-sm: 0 1px 2px rgba(10, 14, 20, 0.08);
    --tk-shadow: 0 1px 3px rgba(10, 14, 20, 0.10), 0 1px 2px rgba(10, 14, 20, 0.06);
    --tk-shadow-lg: 0 8px 24px rgba(10, 14, 20, 0.16);

    /* ---- Motion -------------------------------------------------------- */
    --tk-ease: cubic-bezier(0.2, 0, 0.13, 1);
    --tk-duration: 160ms;
}

html.dark {
    --tk-page: #0d1117;
    --tk-surface: #161b22;
    --tk-surface-raised: #1c232d;
    --tk-surface-sunken: #0a0e14;
    --tk-surface-inverse: #f0f4f8;

    --tk-ink: #f0f4f8;
    --tk-ink-secondary: #9aa7b6;
    /* Lifted from #707d8d: 4.12 on --tk-surface and 3.77 on
       --tk-surface-raised, both under the 4.5 floor. Now 5.46 / 4.99 / 4.56 on
       page / surface / raised. */
    --tk-ink-muted: #7e8b9b;

    /* Dark: good 4.71 and warning 7.24 already clear the floor, so their ink
       stays the hue. Only critical needed lifting, from 3.29. */
    --tk-good-ink: #0ca30c;
    --tk-warning-ink: #fab219;
    --tk-critical-ink: #de7575;
    --tk-ink-inverse: #0a0e14;

    --tk-border: rgba(255, 255, 255, 0.12);
    --tk-border-strong: rgba(255, 255, 255, 0.22);
    --tk-ring: rgba(167, 139, 250, 0.40);

    /* Inverted so the primary action stays the highest-contrast element. */
    --tk-action: #f0f4f8;
    --tk-action-hover: #ffffff;
    --tk-action-ink: #0a0e14;
    --tk-brand-gradient: linear-gradient(120deg, #8b5cf6 0%, #d946ef 55%, #ff1f7a 100%);
    --tk-accent: #a78bfa;
    --tk-accent-hover: #b9a3fb;
    --tk-accent-soft: #241a45;

    /* Re-stepped for the dark surface and validated as a set -- not an
       automatic lightening of the light values. */
    --tk-protein: #3b82f6;
    --tk-carbs: #de7015;
    --tk-fat: #12a877;
    --tk-protein-soft: #12203a;
    --tk-carbs-soft: #2e1c0c;
    --tk-fat-soft: #08281d;
    --tk-nutrient-neutral: #707d8d;

    --tk-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.5);
    --tk-shadow: 0 1px 3px rgba(0, 0, 0, 0.55);
    --tk-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.6);
}

/**
 * Reduced motion.
 *
 * Zeroing --tk-duration only reaches rules that use the token. The inline
 * <style> in index.html carries ~25 hardcoded animations -- sheet-up,
 * zoom-in-up, rotate-gradient, the toast slides -- and every one of
 * them ignored the preference entirely. The sweep below is the safety net, and
 * it is !important so it wins over those inline rules despite coming first in
 * the cascade.
 *
 * 0.01ms rather than 0: a zero-duration transition never fires transitionend,
 * and four accordion handlers wait on that event to apply `hidden` and reset
 * max-height. At zero they would collapse visually and then never clean up, so
 * the next expansion misbehaves. An imperceptible non-zero duration still
 * dispatches the event, which is why this idiom is written the way it is.
 *
 * animation-iteration-count is capped because `animation: none` on an infinite
 * decorative loop is what is wanted, but a one-shot animation with fill-mode
 * forwards still has to run once to leave its element in the final state.
 */
@media (prefers-reduced-motion: reduce) {
    :root { --tk-duration: 0.01ms; }

    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}
