/* =============================================================================
   Jim v5 — the token contract
   Jim's brand tokens bound onto the Gluestack v5 semantic contract.

   Sources, quoted exactly, never from memory:
     GLUESTACK-V5-THEME.json  — 17 semantic roles per scheme, space-separated
                                RGB triples for nativewind vars(); 13 tva state
                                variants with specificity weights; 59 CLI
                                components. Source: gluestack-ui @ HEAD,
                                apps/starter-kit-next/components/ui/
                                gluestack-ui-provider/config.ts
     GLUESTACK-V5-COMPONENTS.json — 31 roots, 188 parts, 36 aria hooks,
                                extracted from @gluestack-ui/core@5.0.15
     tokens.css / DESIGN.md   — Jim's brand ramp, type, space, radius

   FORMAT. Every colour is a space-separated RGB triple, because that is what
   nativewind's vars() consumes and what every Gluestack class compiles against:
       bg-primary   ->  background-color: rgb(var(--primary) / <alpha>)
   The documentation pages in this project read the same triples through
   rgb(var(--x)). Docs and app cannot drift, because there is one value.

   TWO LAYERS.
     Layer 1  the 17 Gluestack semantic roles. Names are fixed by the framework.
              Never rename one. A Gluestack class will not find it.
     Layer 2  the Jim extension, prefixed --jim-. Roles Jim needs that Gluestack
              has no name for: the accent state ladder, the fourth surface tier,
              status colour, text-on-tint. Prefixed so a future Gluestack
              release cannot collide with them.

   AUDIT 2026-10-04. Reconciled with the copies in jim-v5-prototype; this file
   is the single source. Lines, meta text and status marks re-measured; see
   AUDIT-2026-10-04.md for every changed value and its contrast.

   BOTH SCHEMES ARE COMPLETE. Every role in Layer 1 and Layer 2 is declared in
   .gs-light and again in .gs-dark. There is no inheritance between the two and
   no partial override, so no role can resolve to a light value in a dark tree.
   Asserted by reference-parts.html.
   ============================================================================= */

/* ---------------------------------------------------------------------------
   LIGHT
   --------------------------------------------------------------------------- */
:root,
.gs-light,
[data-scheme="light"] {
  color-scheme: light;

  /* -- Layer 1: the 17 Gluestack semantic roles ---------------------------- */

  /* Johnson Red. The only accent in the system. #CC0000.
     Measured 5.89:1 on --background. Carries primary action and nothing else. */
  --primary: 204 0 0;                 /* #CC0000  DESIGN.md primary            */
  --primary-foreground: 255 255 255;  /* #FFFFFF  5.89:1 on --primary          */

  /* Surface tiers. Depth is a tier plus a 1dp border. There are no shadows. */
  --background: 255 255 255;          /* #FFFFFF  canvas,   tier 0             */
  --card: 245 245 245;                /* #F5F5F5  surface,  tier 1             */
  --muted: 245 245 245;               /* #F5F5F5  surface,  tier 1             */
  --secondary: 238 238 238;           /* #EEEEEE  surface-2, tier 2            */
  --accent: 238 238 238;              /* #EEEEEE  surface-2, tier 2            */
  /* --card and --muted are co-valued at tier 1, and --secondary and --accent
     at tier 2. That is deliberate, and it is how the stock Gluestack theme
     behaves too (--card 255 255 255 equals --background 255 255 255). A
     secondary control at rest and a hovered row carry the same visual weight;
     they diverge on the next step, where both move to --jim-surface-3. */

  /* --popover is raised, and in light it raises toward white while the page
     body sits on tier 1 cards. In dark it raises the other way, toward light.
     One role, opposite directions, because "raised" is a relationship. */
  --popover: 255 255 255;             /* #FFFFFF                               */
  --popover-foreground: 31 31 31;     /* #1F1F1F  16.48:1 on --popover         */

  /* Foreground ramp. */
  --foreground: 0 0 0;                /* #000000  21.00:1 on --background      */
  --secondary-foreground: 31 31 31;   /* #1F1F1F  14.21:1 on --secondary       */
  --accent-foreground: 31 31 31;      /* #1F1F1F  14.21:1 on --accent          */
  --muted-foreground: 98 98 98;       /* #626262  meta text clears 4.5:1 on ALL
                                         four tiers: 6.10 bg, 5.59 card,
                                         5.26 secondary, 4.62 surface-3.
                                         Was #6D6D6D, which measured 4.46 on
                                         --secondary, so meta text on a hovered
                                         row dropped under AA.                 */

  /* Status. Gluestack names exactly one status role. */
  --destructive: 220 38 38;           /* #DC2626   4.83:1 on --background      */

  /* Lines. A four-step ladder, measured against canvas / card / secondary.
     There are no shadows, so a line is the only thing that groups. Each step
     has one job and a contrast band, and light and dark land in the same band:
       --jim-border-faint  ~1.2:1  divides rows INSIDE one group
       --border            ~1.6:1  the edge of a group: Card, list, menu
       --jim-border-strong ~2.2:1  structural rule, today, a selected edge
       --input             >=3:1   the boundary of a control (WCAG 1.4.11)
     The old --border (#E8E8E8) measured 1.23 / 1.12 / 1.06 and grouped
     nothing on a phone in daylight; the old --input (#D4D4D4) measured 1.48:1,
     so an empty Input, Checkbox, Radio or Switch failed 1.4.11. */
  --border: 200 200 200;              /* #C8C8C8  1.67 bg  1.53 card  1.44 sec */
  --input: 136 136 136;               /* #888888  3.54 bg  3.25 card  3.06 sec */
  --ring: 41 98 255;                  /* #2962FF   4.90:1 on --background      */

  /* -- Layer 2: the Jim extension ------------------------------------------ */

  /* Accent state ladder. Contrast rises through the sequence, it never drops:
     5.89 -> 8.21 -> 10.95 against --primary-foreground. */
  --jim-primary-hover: 163 0 0;       /* #A30000   8.21:1 vs primary-fg        */
  --jim-primary-press: 128 0 0;       /* #800000  10.95:1 vs primary-fg        */
  --jim-primary-tint: 255 235 235;    /* #FFEBEB  badge sized, never a panel   */
  --jim-primary-on-tint: 204 0 0;     /* #CC0000   5.14:1 on --jim-primary-tint*/
  --jim-primary-text: 204 0 0;        /* #CC0000   5.89:1 on --background,
                                         red ink (DESIGN.md primary-text)     */

  /* The fourth surface tier. Gluestack has no name for it. It is the press
     step, the progress and slider track, and the switch track when off. */
  --jim-surface-3: 224 224 224;       /* #E0E0E0                               */

  /* Foreground steps Gluestack has no name for. */
  --jim-fg-1: 31 31 31;               /* #1F1F1F  16.48:1 on --background      */
  --jim-fg-2: 66 66 66;               /* #424242  10.05:1 on --background      */
  --jim-fg-muted: 158 158 158;        /* #9E9E9E   2.68:1 — DISABLED ONLY.
                                         Disabled is the one state permitted to
                                         drop below 4.5:1. Never use it for
                                         enabled text.                         */
  --jim-fg-inverse: 245 245 245;      /* #F5F5F5  for tooltip, on --jim-fg-1   */

  --jim-border-strong: 172 172 172;   /* #ACACAC  2.27 bg  2.08 card  1.96 sec
                                         No longer == --input: a structural
                                         rule must stay lighter than a control. */
  --jim-border-faint: 232 232 232;    /* #E8E8E8  1.23 bg  1.12 card  (the old
                                         --border, kept for in-group dividers)  */

  /* Destructive state ladder, against --primary-foreground:
     4.83 -> 6.47 -> 7.84. Rising. */
  --jim-destructive-hover: 185 28 28; /* #B91C1C                               */
  --jim-destructive-press: 162 24 24; /* #A21818                               */
  --jim-destructive-tint: 253 236 236;/* #FDECEC                               */
  --jim-destructive-text: 185 28 28;  /* #B91C1C   5.66:1 on tint              */
  /* The tinted destructive Button (negative-tint). Its surface steps darker on
     hover and press, so its label steps too. Reconciled from jim-v5-prototype,
     which kept the rest label on all three and let contrast fall 5.66 -> 5.25
     -> 4.83. Here no state measures under rest: 5.66 -> 6.36 -> 5.85. */
  --jim-destructive-tint-hover: 247 227 227; /* #F7E3E3                        */
  --jim-destructive-tint-press: 241 217 217; /* #F1D9D9                        */
  --jim-destructive-text-hover: 162 24 24;   /* #A21818  6.36:1 on tint-hover  */
  --jim-destructive-text-press: 162 24 24;   /* #A21818  5.85:1 on tint-press  */

  /* Status colours are not accents. They mark state; they never take an action.
     Each has three roles: a mark (3:1 bar), a tint, and a text colour that
     holds 4.5:1 on that tint. */
  --jim-success: 18 138 61;           /* #128A3D  mark, 3:1 bar: 4.44 bg,
                                         4.07 card, 3.83 sec, 3.36 surface-3.
                                         Was #16A34A: 2.84 on --secondary and
                                         2.50 on the Progress track, so a green
                                         mark failed its own bar. #128A3D is
                                         tokens.css --green-600.                */
  --jim-success-tint: 236 247 238;    /* #ECF7EE                               */
  --jim-success-text: 16 129 56;      /* #108138   4.53:1 on tint              */
  --jim-warn: 176 122 12;             /* #B07A0C  mark, 3:1 bar: 3.73 bg,
                                         3.42 card, 3.21 sec. Was #D49414 at
                                         2.61 on the canvas, under the bar on
                                         every tier. #B07A0C is tokens.css
                                         --amber-600. Never on surface-3 (2.82). */
  --jim-warn-tint: 253 244 220;       /* #FDF4DC                               */
  --jim-warn-text: 141 97 7;          /* #8D6107   4.98:1 on tint              */

  /* Link. Shares its hue with --ring on purpose: focus and navigation are the
     same promise. --jim-link-text is the on-tint variant, because plain --link
     measures 4.41:1 on its own tint and fails. */
  --jim-link: 41 98 255;              /* #2962FF   4.90:1 on --background      */
  --jim-link-tint: 238 243 255;       /* #EEF3FF  tokens.css --blue-50         */
  --jim-link-text: 30 79 219;         /* #1E4FDB  tokens.css --blue-600,
                                                   5.91:1 on --jim-link-tint   */

  /* -- Layer 3: derived status lines --------------------------------------
     JIM-V2-STYLING.json, statusSurfaceRule. Across 188 tinted status surfaces
     in the v2 render, 60 carry a border and 31 of those derive it with
     color-mix. Zero use a raw status colour at partial alpha, because that
     reads as a coloured outline drawn around a tint rather than as an edge.

     The rule: mix the status colour TOWARD the neutral border token.
       border:1px solid color-mix(in oklab,var(--danger) 35%, var(--border))
       border-color:color-mix(in oklab, var(--warn) 40%, var(--border))
     Those two canonical examples set the range at 35-45%. --danger is quoted
     at 35 and --warn at 40; the remaining hues take 40, the midpoint.

     These resolve to whole colours, not channel triplets, so they are used as
     var(--jim-*-line) and never wrapped in rgb(). They are declared in both
     schemes because a custom property computes where it is DECLARED: a single
     :root declaration would bake in the light --border and leak it into a dark
     subtree. Same reason every other role is restated below. */
  --jim-destructive-line: color-mix(in oklab, rgb(var(--destructive)) 35%, rgb(var(--border)));
  --jim-warn-line:        color-mix(in oklab, rgb(var(--jim-warn)) 40%, rgb(var(--border)));
  --jim-success-line:     color-mix(in oklab, rgb(var(--jim-success)) 40%, rgb(var(--border)));
  --jim-link-line:        color-mix(in oklab, rgb(var(--jim-link)) 40%, rgb(var(--border)));
  --jim-primary-line:     color-mix(in oklab, rgb(var(--primary)) 40%, rgb(var(--border)));
}

/* ---------------------------------------------------------------------------
   DARK
   Same role list, restated in full. Nothing inherits from the light block.
   --------------------------------------------------------------------------- */
.gs-dark,
[data-scheme="dark"] {
  color-scheme: dark;

  /* -- Layer 1: the 17 Gluestack semantic roles ---------------------------- */

  /* PRIMARY-ON, Baker 2026-10-06 ("Deeper red"): the accent FILL keeps the
     light red in dark so its label stays white, 5.89:1. Red INK on a dark
     surface is --jim-primary-text (#FF4747), because #CC0000 as text on the
     canvas is only 3.26:1. */
  --primary: 204 0 0;                 /* #CC0000  DESIGN.md dark-primary       */
  --primary-foreground: 255 255 255;  /* #FFFFFF   5.89:1 on --primary         */

  --background: 15 15 15;             /* #0F0F0F  canvas,    tier 0            */
  --card: 20 20 20;                   /* #141414  surface,   tier 1            */
  --muted: 20 20 20;                  /* #141414  surface,   tier 1            */
  --secondary: 28 28 28;              /* #1C1C1C  surface-2, tier 2            */
  --accent: 28 28 28;                 /* #1C1C1C  surface-2, tier 2            */

  --popover: 28 28 28;                /* #1C1C1C  raised toward light          */
  --popover-foreground: 240 240 240;  /* #F0F0F0  14.95:1 on --popover         */

  --foreground: 240 240 240;          /* #F0F0F0  16.82:1 on --background      */
  --secondary-foreground: 228 228 228;/* #E4E4E4  13.40:1 on --secondary       */
  --accent-foreground: 228 228 228;   /* #E4E4E4  13.40:1 on --accent          */
  --muted-foreground: 154 154 154;    /* #9A9A9A   6.81 bg  6.55 card
                                                    6.06 sec  5.38 surface-3   */

  --destructive: 242 101 101;         /* #F26565   6.23:1 on --background      */

  /* Same ladder, same bands as light. */
  --border: 56 56 56;                 /* #383838  1.63 bg  1.57 card  1.45 sec */
  --input: 104 104 104;               /* #686868  3.44 bg  3.31 card  3.06 sec */
  --ring: 127 160 255;                /* #7FA0FF   7.64:1 on --background      */

  /* -- Layer 2: the Jim extension ------------------------------------------ */

  /* Same ladder as light, white label: 5.89 -> 8.21 -> 10.95. */
  --jim-primary-hover: 163 0 0;       /* #A30000   8.21:1 vs primary-fg        */
  --jim-primary-press: 128 0 0;       /* #800000  10.95:1 vs primary-fg        */
  --jim-primary-tint: 49 12 12;       /* #310C0C                               */
  --jim-primary-on-tint: 255 71 71;   /* #FF4747   5.25:1 on --jim-primary-tint*/
  --jim-primary-text: 255 71 71;      /* #FF4747   5.70:1 on --background      */

  --jim-surface-3: 38 38 38;          /* #262626                               */

  --jim-fg-1: 228 228 228;            /* #E4E4E4  15.08:1 on --background      */
  --jim-fg-2: 196 196 196;            /* #C4C4C4  10.99:1 on --background      */
  --jim-fg-muted: 110 110 110;        /* #6E6E6E   3.76:1 — DISABLED ONLY      */
  --jim-fg-inverse: 15 15 15;         /* #0F0F0F  for tooltip, on --jim-fg-1   */

  --jim-border-strong: 76 76 76;      /* #4C4C4C  2.23 bg  2.15 card  1.98 sec */
  --jim-border-faint: 39 39 39;       /* #272727  1.28 bg  1.23 card           */

  /* 6.23 -> 7.58 -> 9.07 against --primary-foreground. */
  --jim-destructive-hover: 244 129 129;/* #F48181                              */
  --jim-destructive-press: 246 153 153;/* #F69999                              */
  --jim-destructive-tint: 48 19 19;   /* #301313                               */
  --jim-destructive-text: 242 101 101;/* #F26565   5.56:1 on tint              */
  /* Rising: 5.56 -> 6.47 -> 7.39. */
  --jim-destructive-tint-hover: 54 22 22;    /* #361616                        */
  --jim-destructive-tint-press: 60 25 25;    /* #3C1919                        */
  --jim-destructive-text-hover: 244 129 129; /* #F48181  6.47:1 on tint-hover  */
  --jim-destructive-text-press: 246 153 153; /* #F69999  7.39:1 on tint-press  */

  --jim-success: 63 191 106;          /* #3FBF6A  8.10 bg  7.20 sec  6.39 s-3 */
  --jim-success-tint: 16 39 24;       /* #102718                               */
  --jim-success-text: 63 191 106;     /* #3FBF6A   6.69:1 on tint              */
  --jim-warn: 229 172 60;             /* #E5AC3C  9.40 bg  8.36 sec  7.42 s-3 */
  --jim-warn-tint: 47 36 16;          /* #2F2410                               */
  --jim-warn-text: 229 172 60;        /* #E5AC3C   7.46:1 on tint              */

  --jim-link: 127 160 255;            /* #7FA0FF   7.64:1 on --background      */
  --jim-link-tint: 20 30 58;          /* #141E3A  --jim-link base at 18% over
                                                   --background               */
  --jim-link-text: 127 160 255;       /* #7FA0FF   6.56:1 on --jim-link-tint   */

  /* -- Layer 3: derived status lines --------------------------------------
     Same mix ratios as light, restated in full. The inputs differ, so the
     outputs do: dark --border is #272727, so a status line lands dark and
     low-contrast against the canvas while still reading as an edge on its own
     tint. That is the point of mixing toward the neutral rather than toward
     transparent — the line belongs to the surface tier, not to the hue. */
  --jim-destructive-line: color-mix(in oklab, rgb(var(--destructive)) 35%, rgb(var(--border)));
  --jim-warn-line:        color-mix(in oklab, rgb(var(--jim-warn)) 40%, rgb(var(--border)));
  --jim-success-line:     color-mix(in oklab, rgb(var(--jim-success)) 40%, rgb(var(--border)));
  --jim-link-line:        color-mix(in oklab, rgb(var(--jim-link)) 40%, rgb(var(--border)));
  --jim-primary-line:     color-mix(in oklab, rgb(var(--primary)) 40%, rgb(var(--border)));
}

/* =============================================================================
   NON-COLOUR TOKENS
   Scheme independent, so declared once. DESIGN.md owns these values.
   ============================================================================= */
:root {
  /* -- Type. Thirteen scales, every one with an explicit line height, because
        Gluestack's Text leaves it unset at the default size and the result
        collides on a 360dp column. ---------------------------------------- */
  --font-display: 'Bricolage Grotesque', ui-sans-serif, system-ui, sans-serif;
  --font-body: 'Geist', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono: 'Geist Mono', ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, monospace;

  --fs-display-lg: 3rem;      --lh-display-lg: 1.05;  --ls-display-lg: -0.02em;
  --fs-display-md: 2.375rem;  --lh-display-md: 1.05;  --ls-display-md: -0.02em;
  --fs-display-sm: 1.875rem;  --lh-display-sm: 1.18;  --ls-display-sm: -0.01em;
  --fs-heading-lg: 1.5rem;    --lh-heading-lg: 1.18;
  --fs-heading-md: 1.25rem;   --lh-heading-md: 1.18;
  --fs-heading-sm: 1.125rem;  --lh-heading-sm: 1.4;
  --fs-body-lg: 1rem;         --lh-body-lg: 1.55;
  --fs-body-md: 0.9375rem;    --lh-body-md: 1.55;
  --fs-body-sm: 0.875rem;     --lh-body-sm: 1.4;
  --fs-label-md: 0.8125rem;   --lh-label-md: 1.4;
  --fs-label-sm: 0.75rem;     --lh-label-sm: 1.4;
  --fs-caption: 0.6875rem;    --lh-caption: 1.4;
  --fs-mono: 0.875rem;        --lh-mono: 1.55;

  --fw-regular: 400; --fw-medium: 500; --fw-semibold: 600; --fw-bold: 700;

  /* -- Space. A 4dp grid. ---------------------------------------------------*/
  --space-none: 0;
  --space-xs: 0.25rem;   /*  4dp */
  --space-sm: 0.5rem;    /*  8dp */
  --space-md: 0.75rem;   /* 12dp */
  --space-lg: 1rem;      /* 16dp */
  --space-xl: 1.25rem;   /* 20dp */
  --space-2xl: 1.5rem;   /* 24dp */
  --space-3xl: 2rem;     /* 32dp */
  --space-4xl: 2.5rem;   /* 40dp */

  /* -- Radius. Cards md, controls sm, chips and avatars pill. ---------------*/
  --radius-xs: 4px;
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-xl: 22px;
  --radius-pill: 999px;

  /* -- Android target. Samsung Galaxy S21, Android 13, 360dp reference. -----*/
  --tap-min: 48px;       /* hard floor at every breakpoint, no exceptions.
                            A TARGET floor. The drawn box may be smaller when
                            the target is extended to 48dp (see --control-h). */
  --tap-comfortable: 56px;
  --gutter-phone: 16px;
  --gutter-wide: 24px;

  /* -- Control height. Reconciled from jim-v5-prototype, where chrome controls
        (Button, Input, SelectTrigger, DateTimePickerTrigger, TabsTrigger)
        relaxed to 36px from 600dp up because "600 is where the pointer starts".
        That premise is false for this app: an Android tablet at 800-1440dp is
        still a finger. DESIGN.md forbids a target under 48dp at any width, so
        the prototype's rule is kept only for the DRAWN box. --control-h is the
        visual height; --control-slop extends the hit area back to --tap-min on
        each side (hitSlop in React Native, a transparent ::before here). The
        target never drops under 48dp. Same split Material 3 uses for its 40dp
        buttons. Label hit areas, icon squares and calendar cells keep the
        full 48dp box at every width. ------------------------------------------*/
  --control-h: var(--tap-min);
  --control-pad: var(--space-lg);   /* inline padding, comes down with the height */
  --control-slop: calc((var(--tap-min) - var(--control-h)) / 2);

  /* -- Width ladder. Absolute px, declared once.
        On the React Native engine the root font size resolves to 14px, not the
        16px a browser assumes, so a rem-derived breakpoint compiles narrow: a
        stock `md:` at 48rem becomes 672px instead of 768px, silently, with no
        error to point at. Absolute px removes the class of bug. -------------*/
  --bp-floor: 320px;     /* clamps below this, does not reflow                 */
  --bp-phone: 360px;     /* Galaxy S21, the reference design                   */
  --bp-rail: 600px;      /* tab bar becomes a rail                             */
  --bp-two: 800px;       /* two panes at full phone column width each          */
  --bp-detail: 1120px;   /* list pane plus 80 mono columns unscrolled          */
  --bp-wide: 1440px;     /* nothing further is revealed; the band caps         */
  --rail-w: 80px;
  --measure-max: 500px;  /* 75 characters of 15px Geist                        */

  /* -- Motion. -------------------------------------------------------------*/
  --dur-fast: 120ms; --dur-base: 200ms; --dur-mid: 320ms; --dur-slow: 560ms;
  --ease-out-quint: cubic-bezier(0.32, 0.72, 0, 1);
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);

  /* -- Focus. Every focusable element gets this ring. ----------------------*/
  --focus-ring: 0 0 0 2px rgb(var(--background)), 0 0 0 4px rgb(var(--ring));
}

/* The rail rung. The drawn control comes down to 36px; --control-slop (6px a
   side) keeps the target at 48dp. Keyed to --bp-rail because 600 is already
   where the tab bar becomes a rail, and a width query ports to the React
   Native engine while a pointer query does not. */
@media (min-width: 600px) {
  :root { --control-h: 36px; --control-pad: var(--space-md); }
}
