/* =============================================================================
   Jim v5 component layer.

   Every class below is named for a real @gluestack-ui/core@5.0.15 export, taken
   from GLUESTACK-V5-COMPONENTS.json. `InputField` is `InputField`. A part is
   never renamed, never abbreviated to its parent, never invented.

   States are addressed by the 13 tva variant names from GLUESTACK-V5-THEME.json
   through [data-state~="..."], so a static specimen can show `hover` and
   `disabled` at the same time without a pointer. The names and their order of
   precedence match the tailwind plugin's specificity weights:

     indeterminate 1 · checked 1 · read-only 1 · flip 1 · required 2 ·
     invalid 2 · focus 3 · focus-visible 4 · hover 5 · pressed 6 · active 6 ·
     loading 7 · disabled 10

   Rules are written in weight order, low to high, so the cascade reproduces
   the plugin's resolution: `disabled` last, and it wins.

   No colour literal appears in this file. No shadow is used for elevation.
   Every interactive element clears the 48dp tap floor at every width.
   Chrome controls (Button, Input, SelectTrigger, DateTimePickerTrigger) draw
   at --control-h, which is --tap-min below 600 and 36px above it. Above 600
   their TARGET stays 48dp: a transparent ::before extends the hit area by
   --control-slop on each side (hitSlop in React Native). Label hit areas
   (Checkbox, Radio, SwitchRow), TabsTrigger, icon squares and calendar cells
   keep the full 48dp box at every width.
   ============================================================================= */

/* =============================================================================
   BUTTON — button: Button, ButtonGroup, ButtonIcon, ButtonSpinner, ButtonText,
   Context (6 parts). Supports: hover, pressed, active, focus, focus-visible,
   disabled, loading.
   ============================================================================= */
.Button {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--space-sm);
  min-height: var(--control-h);            /* drawn: 48 on phone, 36 from 600 */
  padding: 0 var(--control-pad);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);         /* controls are sm */
  font-family: var(--font-body);
  font-size: var(--fs-label-md); line-height: var(--lh-label-md);
  font-weight: var(--fw-semibold);
  cursor: pointer; text-decoration: none; white-space: nowrap;
  transition: background-color var(--dur-fast) var(--ease-standard),
              border-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard);
}
/* The target. Zero on the phone, 6px a side from 600, so the hit area is
   48dp at every width while the drawn box comes down. Transparent; it paints
   nothing and takes no layout space. */
.Button, .Input, .SelectTrigger, .DateTimePickerTrigger { isolation: isolate; }
.Button::before, .Input::before, .SelectTrigger::before, .DateTimePickerTrigger::before {
  content: ""; position: absolute; z-index: -1;   /* under the field, so a tap
                                                     inside still reaches it */
  /* An absolute box is placed from the PADDING edge, so the 1px border is
     added back: the box covers the border box plus the slop. Measured target
     at 1440: 36 drawn + 6 + 6 = 48. At 360 the slop is 0 and the box is the
     border box. */
  inset: calc((var(--control-slop) + 1px) * -1) -1px;
}
.ButtonText { font: inherit; color: inherit; }
.ButtonIcon { width: 16px; height: 16px; flex: none; display: block; color: currentColor; }
.ButtonGroup { display: inline-flex; align-items: center; gap: var(--space-md); flex-wrap: wrap; }
.ButtonGroup[data-orientation="vertical"] { flex-direction: column; align-items: stretch; }
.ButtonGroup[data-attached="true"] { gap: 0; }
.ButtonGroup[data-attached="true"] .Button { border-radius: 0; }
.ButtonGroup[data-attached="true"] .Button:first-child { border-start-start-radius: var(--radius-sm); border-end-start-radius: var(--radius-sm); }
.ButtonGroup[data-attached="true"] .Button:last-child { border-start-end-radius: var(--radius-sm); border-end-end-radius: var(--radius-sm); }
.ButtonGroup[data-attached="true"] .Button + .Button { margin-inline-start: -1px; }

/* ButtonSpinner. Borrows the label colour so it is legible on any variant. */
.ButtonSpinner {
  width: 15px; height: 15px; flex: none; border-radius: var(--radius-pill);
  border: 2px solid currentColor; border-top-color: transparent;
  animation: gs-spin 700ms linear infinite;
}
@keyframes gs-spin { to { transform: rotate(360deg); } }

/* -- action="primary": the accent. One per screen. ------------------------ */
.Button[data-action="primary"] { background: rgb(var(--primary)); color: rgb(var(--primary-foreground)); }
.Button[data-action="primary"][data-state~="hover"] { background: rgb(var(--jim-primary-hover)); }   /* 5.89 -> 8.21 L, 5.70 -> 6.70 D */
.Button[data-action="primary"][data-state~="pressed"],
.Button[data-action="primary"][data-state~="active"] { background: rgb(var(--jim-primary-press)); }  /* -> 10.95 L, 7.90 D */

/* -- action="secondary": tier 2 fill, no accent. -------------------------- */
.Button[data-action="secondary"] { background: rgb(var(--secondary)); color: rgb(var(--secondary-foreground)); border-color: rgb(var(--border)); }
.Button[data-action="secondary"][data-state~="hover"] { background: rgb(var(--jim-surface-3)); border-color: rgb(var(--jim-border-strong)); }
.Button[data-action="secondary"][data-state~="pressed"],
.Button[data-action="secondary"][data-state~="active"] { background: rgb(var(--jim-surface-3)); border-color: rgb(var(--muted-foreground)); color: rgb(var(--foreground)); }

/* -- variant="outline": the border carries it. ---------------------------- */
.Button[data-variant="outline"] { background: transparent; color: rgb(var(--jim-fg-1)); border-color: rgb(var(--input)); }
.Button[data-variant="outline"][data-state~="hover"] { background: rgb(var(--secondary)); border-color: rgb(var(--muted-foreground)); color: rgb(var(--foreground)); }  /* border steps UP, never down: 3.06 -> 5.26 L, 3.06 -> 6.06 D */
.Button[data-variant="outline"][data-state~="pressed"],
.Button[data-variant="outline"][data-state~="active"] { background: rgb(var(--jim-surface-3)); color: rgb(var(--foreground)); }

/* -- variant="link": text only. Underline, not a colour change. ----------- */
.Button[data-variant="link"] { background: transparent; border-color: transparent; color: rgb(var(--jim-link)); padding: 0 var(--space-xs); }
.Button[data-variant="link"][data-state~="hover"] { text-decoration: underline; text-underline-offset: 3px; }
.Button[data-variant="link"][data-state~="pressed"],
.Button[data-variant="link"][data-state~="active"] { color: rgb(var(--jim-link-text)); text-decoration: underline; }

/* -- action="negative": destructive. -------------------------------------- */
.Button[data-action="negative"] { background: rgb(var(--destructive)); color: rgb(var(--primary-foreground)); }
.Button[data-action="negative"][data-state~="hover"] { background: rgb(var(--jim-destructive-hover)); }  /* 4.83 -> 6.47 L, 6.23 -> 7.58 D */
.Button[data-action="negative"][data-state~="pressed"],
.Button[data-action="negative"][data-state~="active"] { background: rgb(var(--jim-destructive-press)); } /* -> 7.84 L, 9.07 D */

/* Destructive, tinted. Reconciled from jim-v5-prototype. A solid --destructive
   fill and the solid --primary fill read as the same red at a glance, so a row
   offering both spends the accent twice. Jim v2 draws this one as Mantine
   variant="light" color="red": a tint, not a fill. --jim-destructive-tint behind
   --jim-destructive-text, the pair .Badge[data-action="error"] already uses.

   Reach for it when destructive is the QUIETER of two actions in one row.
   data-action="negative" stays correct for a destructive action that is the
   only emphasis present, such as the confirm inside a delete dialog.

   It has no elevation in the DESIGN.md sense (a tint, not a filled surface),
   so it never takes the trailing primary slot beside a filled button.

   Measured: 5.66 rest -> 6.36 hover -> 5.85 press light, 5.56 -> 6.47 -> 7.39
   dark. The label steps with the surface, so no state measures under rest.
   Disabled needs no rule of its own: [data-variant][data-state~="disabled"]
   below already claims it. */
.Button[data-variant="negative-tint"] {
  background: rgb(var(--jim-destructive-tint));
  color: rgb(var(--jim-destructive-text));
  border-color: transparent;
}
.Button[data-variant="negative-tint"][data-state~="hover"] { background: rgb(var(--jim-destructive-tint-hover)); color: rgb(var(--jim-destructive-text-hover)); }
.Button[data-variant="negative-tint"][data-state~="pressed"],
.Button[data-variant="negative-tint"][data-state~="active"] { background: rgb(var(--jim-destructive-tint-press)); color: rgb(var(--jim-destructive-text-press)); }

/* -- variant="ghost": no chrome at rest. The label DARKENS on hover in light
      and LIGHTENS in dark. It is never dimmed toward the background. ------- */
.Button[data-variant="ghost"] { background: transparent; border-color: transparent; color: rgb(var(--jim-fg-2)); }
.Button[data-variant="ghost"][data-state~="hover"] { background: rgb(var(--card)); color: rgb(var(--jim-fg-1)); }   /* 10.05 -> 15.12 L, 10.99 -> 14.49 D */
.Button[data-variant="ghost"][data-state~="pressed"],
.Button[data-variant="ghost"][data-state~="active"] { background: rgb(var(--secondary)); color: rgb(var(--foreground)); } /* -> 18.10 L, 14.95 D */

/* -- focus, focus-visible: weight 3 and 4, above hover's declaration order
      for the ring but below the fill rules, so both are visible at once. --- */
.Button[data-state~="focus"] { box-shadow: var(--focus-ring); outline: none; }
.Button[data-state~="focus-visible"] { box-shadow: var(--focus-ring); outline: none; }
.Button:focus-visible { box-shadow: var(--focus-ring); outline: none; }

/* -- loading: weight 7. It outranks pressed and active at weights 6, so these
      rules are declared after them and re-assert the rest fill. A button that
      is already submitting must not also render a press, which is what makes
      a second tap visibly inert. The label stays put so the button does not
      resize mid-tap. ------------------------------------------------------ */
.Button[data-state~="loading"] { cursor: progress; }
.Button[data-state~="loading"] .ButtonText { opacity: 0.9; }
.Button[data-action="primary"][data-state~="loading"] { background: rgb(var(--primary)); color: rgb(var(--primary-foreground)); }
.Button[data-action="secondary"][data-state~="loading"] { background: rgb(var(--secondary)); color: rgb(var(--secondary-foreground)); border-color: rgb(var(--border)); }
.Button[data-action="negative"][data-state~="loading"] { background: rgb(var(--destructive)); color: rgb(var(--primary-foreground)); }
.Button[data-variant="outline"][data-state~="loading"] { background: transparent; color: rgb(var(--jim-fg-1)); border-color: rgb(var(--input)); }
.Button[data-variant="ghost"][data-state~="loading"] { background: transparent; color: rgb(var(--jim-fg-2)); }
.Button[data-variant="link"][data-state~="loading"] { background: transparent; color: rgb(var(--jim-link)); text-decoration: none; }
.Button[data-variant="negative-tint"][data-state~="loading"] {
  background: rgb(var(--jim-destructive-tint));
  color: rgb(var(--jim-destructive-text));
  border-color: transparent;
}

/* -- disabled: weight 10, declared last and matched at the same specificity
      tier as the compound state rules above, so it wins on order the way the
      plugin's weights say it should. A single-attribute selector would sit at
      (0,2,0) and quietly LOSE to a two-attribute rule such as
      [data-action="primary"][data-state~="hover"] at (0,3,0), which would put
      a hover fill on a disabled button. The [data-action] and [data-variant]
      forms below raise it to that tier.
      This is the one state permitted to fall below 4.5:1. ------------------- */
.Button[data-state~="disabled"],
.Button[data-action][data-state~="disabled"],
.Button[data-variant][data-state~="disabled"],
.Button:disabled {
  background: rgb(var(--secondary)); color: rgb(var(--jim-fg-muted));
  border-color: rgb(var(--border)); cursor: not-allowed; box-shadow: none;
  text-decoration: none;
}

/* =============================================================================
   FAB — fab: Fab, FabIcon, FabLabel (3 parts).
   ============================================================================= */
.Fab {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-sm);
  min-height: 56px; min-width: 56px; padding: 0 var(--space-lg);
  border: none; border-radius: var(--radius-lg);
  background: rgb(var(--primary)); color: rgb(var(--primary-foreground));
  font-family: var(--font-body); font-size: var(--fs-label-md); font-weight: var(--fw-semibold);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-standard);
}
.Fab[data-size="icon"] { padding: 0; width: 56px; border-radius: var(--radius-pill); }
.FabIcon { width: 20px; height: 20px; flex: none; display: block; }
.FabLabel { font: inherit; color: inherit; }
.Fab[data-state~="hover"] { background: rgb(var(--jim-primary-hover)); }
.Fab[data-state~="pressed"] { background: rgb(var(--jim-primary-press)); }
.Fab[data-state~="focus-visible"], .Fab:focus-visible { box-shadow: var(--focus-ring); outline: none; }
.Fab[data-state~="disabled"] { background: rgb(var(--secondary)); color: rgb(var(--jim-fg-muted)); cursor: not-allowed; }

/* =============================================================================
   PRESSABLE — pressable: Pressable (1 part).
   ============================================================================= */
.Pressable {
  display: block; width: 100%; min-height: var(--tap-min);
  padding: var(--space-md) var(--space-lg);
  text-align: left; border: 1px solid rgb(var(--border));
  border-radius: var(--radius-sm);
  background: rgb(var(--background)); color: rgb(var(--jim-fg-1));
  font: inherit; cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-standard);
}
.Pressable[data-state~="hover"] { background: rgb(var(--card)); color: rgb(var(--foreground)); }
.Pressable[data-state~="pressed"] { background: rgb(var(--secondary)); color: rgb(var(--foreground)); }
.Pressable[data-state~="focus-visible"], .Pressable:focus-visible { box-shadow: var(--focus-ring); outline: none; }
.Pressable[data-state~="disabled"] { color: rgb(var(--jim-fg-muted)); background: rgb(var(--card)); cursor: not-allowed; }
/* The selected row in a list (aria-current="true"), lifted from the agents and
   chat screens where each wrote its own. The edge goes to --foreground
   (21.00 L, 16.82 D) so selection reads without colour and without the
   accent; the row itself steps to the canvas. */
.Pressable[aria-current="true"] { background: rgb(var(--background)); border-color: rgb(var(--foreground)); }

/* =============================================================================
   LINK — link: Context, Link, LinkText, UseLink (4 parts).
   ============================================================================= */
.Link { display: inline-flex; align-items: center; min-height: var(--tap-min); text-decoration: none; }
.LinkText {
  color: rgb(var(--jim-link)); font-size: var(--fs-body-md); line-height: var(--lh-body-md);
  /* Same rule as a status line: derived toward the neutral, not the hue at
     partial alpha. A resting underline sits below its own label; at full
     strength it competes with the text. */
  text-decoration: underline; text-decoration-color: var(--jim-link-line); text-underline-offset: 3px;
}
.Link[data-state~="hover"] .LinkText { text-decoration-color: currentColor; }
.Link[data-state~="pressed"] .LinkText { color: rgb(var(--jim-link-text)); }
.Link[data-state~="focus-visible"] .LinkText, .Link:focus-visible .LinkText { box-shadow: var(--focus-ring); border-radius: var(--radius-xs); outline: none; }
.Link[data-state~="disabled"] .LinkText { color: rgb(var(--jim-fg-muted)); text-decoration: none; cursor: not-allowed; }

/* =============================================================================
   INPUT — input: Input, InputContext, InputGroup, InputIcon, InputSlot
   (5 parts). InputField is the RN TextInput the Input wraps; the docs render it
   under that name because that is what an engineer writes.
   Supports: hover, focus, invalid, disabled, read-only, required.
   ============================================================================= */
.Input {
  position: relative;
  display: flex; align-items: center; gap: var(--space-sm);
  min-height: var(--control-h); padding: 0 var(--space-md);
  background: rgb(var(--background));
  border: 1px solid rgb(var(--input)); border-radius: var(--radius-sm);
  transition: border-color var(--dur-fast) var(--ease-standard), background-color var(--dur-fast) var(--ease-standard);
}
.InputField {
  flex: 1; min-width: 0; border: none; background: transparent; outline: none;
  color: rgb(var(--foreground));
  font-family: var(--font-body); font-size: var(--fs-body-md); line-height: var(--lh-body-md);
  padding: var(--space-sm) 0;
}
.InputField::placeholder { color: rgb(var(--muted-foreground)); }   /* 5.17:1 L, 6.81:1 D */
.InputSlot { display: inline-flex; align-items: center; justify-content: center; flex: none; min-width: 24px; min-height: 24px; background: none; border: none; padding: 0; cursor: pointer; color: rgb(var(--muted-foreground)); }
.InputSlot:hover { color: rgb(var(--foreground)); }
/* A 24dp slot is a drawn size, not a target. The slop brings it to 48dp
   (24 + 12 each side) without growing the Input around it. */
.InputSlot { position: relative; }
.InputSlot::before { content: ""; position: absolute; inset: calc(var(--space-md) * -1); }
.InputSlot:focus-visible { box-shadow: var(--focus-ring); border-radius: var(--radius-xs); outline: none; }
.InputIcon { width: 16px; height: 16px; display: block; flex: none; color: currentColor; }
.InputGroup { display: flex; align-items: stretch; }
.InputGroup > .Input { border-radius: 0; flex: 1; min-width: 0; }
.InputGroup > :first-child { border-start-start-radius: var(--radius-sm); border-end-start-radius: var(--radius-sm); }
.InputGroup > :last-child { border-start-end-radius: var(--radius-sm); border-end-end-radius: var(--radius-sm); }
.InputGroup > * + * { margin-inline-start: -1px; }
.InputGroup .InputGroupAddon {
  display: inline-flex; align-items: center; padding: 0 var(--space-md);
  background: rgb(var(--secondary)); color: rgb(var(--secondary-foreground));
  border: 1px solid rgb(var(--input));
  font-family: var(--font-mono); font-size: var(--fs-label-md);
}

/* weight 1: read-only */
.Input[data-state~="read-only"] { background: rgb(var(--card)); border-color: rgb(var(--border)); }
.Input[data-state~="read-only"] .InputField { color: rgb(var(--jim-fg-2)); }
/* weight 2: required, invalid */
.Input[data-state~="required"] { border-color: rgb(var(--input)); }
.Input[data-state~="invalid"] { border-color: rgb(var(--destructive)); }
/* weight 3/4: focus */
.Input[data-state~="focus"], .Input[data-state~="focus-visible"], .Input:focus-within {
  border-color: rgb(var(--ring)); box-shadow: var(--focus-ring); outline: none;
}
.Input[data-state~="invalid"][data-state~="focus"] { border-color: rgb(var(--destructive)); box-shadow: 0 0 0 2px rgb(var(--background)), 0 0 0 4px rgb(var(--destructive)); }
/* weight 5: hover */
.Input[data-state~="hover"] { border-color: rgb(var(--muted-foreground)); }
/* weight 10: disabled */
.Input[data-state~="disabled"] { background: rgb(var(--card)); border-color: rgb(var(--border)); cursor: not-allowed; box-shadow: none; }
.Input[data-state~="disabled"] .InputField { color: rgb(var(--jim-fg-muted)); }
.Input[data-state~="disabled"] .InputField::placeholder { color: rgb(var(--jim-fg-muted)); }

/* =============================================================================
   TEXTAREA — textarea: Textarea, TextareaContext, TextareaRoot (3 parts).
   TextareaInput is the RN TextInput inside TextareaRoot.
   ============================================================================= */
.TextareaRoot, .Textarea {
  display: block; padding: var(--space-md);
  background: rgb(var(--background));
  border: 1px solid rgb(var(--input)); border-radius: var(--radius-sm);
  transition: border-color var(--dur-fast) var(--ease-standard);
}
.TextareaInput {
  display: block; width: 100%; min-height: 96px; resize: vertical;
  border: none; background: transparent; outline: none;
  color: rgb(var(--foreground));
  font-family: var(--font-body); font-size: var(--fs-body-md); line-height: var(--lh-body-lg);
}
.TextareaInput::placeholder { color: rgb(var(--muted-foreground)); }
.Textarea[data-state~="hover"], .TextareaRoot[data-state~="hover"] { border-color: rgb(var(--muted-foreground)); }
.Textarea[data-state~="focus"], .TextareaRoot[data-state~="focus"], .TextareaRoot:focus-within { border-color: rgb(var(--ring)); box-shadow: var(--focus-ring); }
.Textarea[data-state~="invalid"], .TextareaRoot[data-state~="invalid"] { border-color: rgb(var(--destructive)); }
.Textarea[data-state~="read-only"], .TextareaRoot[data-state~="read-only"] { background: rgb(var(--card)); }
.Textarea[data-state~="read-only"] .TextareaInput, .TextareaRoot[data-state~="read-only"] .TextareaInput { color: rgb(var(--jim-fg-2)); }
.TextareaRoot[data-state~="disabled"] { background: rgb(var(--card)); border-color: rgb(var(--border)); cursor: not-allowed; box-shadow: none; }
.TextareaRoot[data-state~="disabled"] .TextareaInput { color: rgb(var(--jim-fg-muted)); }

/* =============================================================================
   FORM CONTROL — form-control: FormControl, FormControlError, FormControlErrorIcon,
   FormControlErrorText, FormControlHelper, FormControlHelperText,
   FormControlLabel, FormControlLabelText (8 parts).
   ============================================================================= */
.FormControl { display: block; }
.FormControlLabel { display: flex; align-items: center; gap: var(--space-xs); margin-bottom: var(--space-sm); }
.FormControlLabelText { font-size: var(--fs-label-md); line-height: var(--lh-label-md); font-weight: var(--fw-medium); color: rgb(var(--jim-fg-1)); }
.FormControlLabelAstrick { color: rgb(var(--destructive)); font-size: var(--fs-label-md); }
.FormControlHelper { margin-top: var(--space-sm); }
.FormControlHelperText { font-size: var(--fs-label-sm); line-height: var(--lh-label-sm); color: rgb(var(--muted-foreground)); }
.FormControlError { display: none; align-items: flex-start; gap: var(--space-xs); margin-top: var(--space-sm); }
.FormControlErrorIcon { width: 14px; height: 14px; flex: none; margin-top: 2px; color: rgb(var(--jim-destructive-text)); }
.FormControlErrorText { font-size: var(--fs-label-sm); line-height: var(--lh-body-lg); color: rgb(var(--jim-destructive-text)); }
.FormControl[data-state~="invalid"] .FormControlError { display: flex; }
.FormControl[data-state~="invalid"] .FormControlHelper { display: none; }
.FormControl[data-state~="disabled"] .FormControlLabelText,
.FormControl[data-state~="disabled"] .FormControlHelperText { color: rgb(var(--jim-fg-muted)); }

/* =============================================================================
   CHECKBOX — checkbox: Checkbox, CheckboxGroup, CheckboxGroupContext,
   CheckboxIcon, CheckboxIndicator, CheckboxLabel, CheckboxProvider (7 parts).
   Supports: checked, indeterminate, hover, focus-visible, disabled, invalid.
   ============================================================================= */
.Checkbox {
  display: flex; align-items: center; gap: var(--space-md);
  min-height: var(--tap-min); padding: var(--space-xs) 0;
  cursor: pointer; user-select: none;
}
.CheckboxGroup { display: flex; flex-direction: column; }
.CheckboxIndicator {
  width: 20px; height: 20px; flex: none;
  display: grid; place-items: center;
  border: 1px solid rgb(var(--input)); border-radius: var(--radius-xs);
  background: rgb(var(--background));
  transition: background-color var(--dur-fast) var(--ease-standard), border-color var(--dur-fast) var(--ease-standard);
}
.CheckboxIcon { width: 12px; height: 12px; display: block; color: rgb(var(--primary-foreground)); opacity: 0; }
.CheckboxLabel { font-size: var(--fs-body-md); line-height: var(--lh-body-md); color: rgb(var(--jim-fg-1)); }
/* weight 1: checked / indeterminate */
.Checkbox[data-state~="checked"] .CheckboxIndicator { background: rgb(var(--primary)); border-color: rgb(var(--primary)); }
.Checkbox[data-state~="checked"] .CheckboxIcon { opacity: 1; }
.Checkbox[data-state~="indeterminate"] .CheckboxIndicator { background: rgb(var(--primary)); border-color: rgb(var(--primary)); }
.Checkbox[data-state~="indeterminate"] .CheckboxIndicator::after {
  content: ""; width: 10px; height: 2px; border-radius: 1px;
  background: rgb(var(--primary-foreground));
}
.Checkbox[data-state~="indeterminate"] .CheckboxIcon { display: none; }
/* weight 2: invalid */
.Checkbox[data-state~="invalid"] .CheckboxIndicator { border-color: rgb(var(--destructive)); }
/* weight 4: focus-visible */
.Checkbox[data-state~="focus-visible"] .CheckboxIndicator, .Checkbox:focus-visible .CheckboxIndicator { box-shadow: var(--focus-ring); outline: none; }
/* weight 5: hover */
.Checkbox[data-state~="hover"] .CheckboxIndicator { border-color: rgb(var(--muted-foreground)); }
.Checkbox[data-state~="hover"][data-state~="checked"] .CheckboxIndicator { background: rgb(var(--jim-primary-hover)); border-color: rgb(var(--jim-primary-hover)); }
.Checkbox[data-state~="hover"] .CheckboxLabel { color: rgb(var(--foreground)); }
/* weight 10: disabled. Raised to the same specificity tier as the compound
   [hover][checked] rule above, so weight 10 actually beats weight 5 + 1. */
.Checkbox[data-state~="disabled"] { cursor: not-allowed; }
.Checkbox[data-state~="disabled"][data-state~="disabled"] .CheckboxIndicator { background: rgb(var(--secondary)); border-color: rgb(var(--border)); box-shadow: none; }
.Checkbox[data-state~="disabled"][data-state~="disabled"] .CheckboxIndicator::after { background: rgb(var(--jim-fg-muted)); }
.Checkbox[data-state~="disabled"][data-state~="disabled"] .CheckboxIcon { color: rgb(var(--jim-fg-muted)); }
.Checkbox[data-state~="disabled"][data-state~="disabled"] .CheckboxLabel { color: rgb(var(--jim-fg-muted)); }

/* =============================================================================
   RADIO — radio: Radio, RadioGroup, RadioGroupContext, RadioIcon,
   RadioIndicator, RadioLabel, RadioProvider (7 parts).
   ============================================================================= */
.Radio { display: flex; align-items: center; gap: var(--space-md); min-height: var(--tap-min); padding: var(--space-xs) 0; cursor: pointer; user-select: none; }
.RadioGroup { display: flex; flex-direction: column; }
.RadioIndicator {
  width: 20px; height: 20px; flex: none; display: grid; place-items: center;
  border: 1px solid rgb(var(--input)); border-radius: var(--radius-pill);
  background: rgb(var(--background));
  transition: border-color var(--dur-fast) var(--ease-standard);
}
.RadioIcon { width: 10px; height: 10px; border-radius: var(--radius-pill); background: rgb(var(--primary)); display: block; opacity: 0; }
.RadioLabel { font-size: var(--fs-body-md); line-height: var(--lh-body-md); color: rgb(var(--jim-fg-1)); }
.Radio[data-state~="checked"] .RadioIndicator { border-color: rgb(var(--primary)); border-width: 2px; }
.Radio[data-state~="checked"] .RadioIcon { opacity: 1; }
.Radio[data-state~="invalid"] .RadioIndicator { border-color: rgb(var(--destructive)); }
.Radio[data-state~="focus-visible"] .RadioIndicator, .Radio:focus-visible .RadioIndicator { box-shadow: var(--focus-ring); outline: none; }
.Radio[data-state~="hover"] .RadioIndicator { border-color: rgb(var(--muted-foreground)); }
.Radio[data-state~="hover"][data-state~="checked"] .RadioIndicator { border-color: rgb(var(--jim-primary-hover)); }
.Radio[data-state~="hover"][data-state~="checked"] .RadioIcon { background: rgb(var(--jim-primary-hover)); }
.Radio[data-state~="hover"] .RadioLabel { color: rgb(var(--foreground)); }
/* weight 10: disabled, raised to beat the compound [hover][checked] rule. */
.Radio[data-state~="disabled"] { cursor: not-allowed; }
.Radio[data-state~="disabled"][data-state~="disabled"] .RadioIndicator { background: rgb(var(--secondary)); border-color: rgb(var(--border)); border-width: 1px; box-shadow: none; }
.Radio[data-state~="disabled"][data-state~="disabled"] .RadioIcon { background: rgb(var(--jim-fg-muted)); }
.Radio[data-state~="disabled"][data-state~="disabled"] .RadioLabel { color: rgb(var(--jim-fg-muted)); }

/* =============================================================================
   SWITCH — switch: Switch (1 part). Hooks: useSwitch, useSwitch.web.
   The whole row is the target, so the 20dp thumb still clears 48dp.
   ============================================================================= */
.SwitchRow { display: flex; align-items: center; justify-content: space-between; gap: var(--space-lg); min-height: var(--tap-min); cursor: pointer; }
.Switch {
  position: relative; width: 44px; height: 26px; flex: none;
  border-radius: var(--radius-pill);
  background: rgb(var(--jim-surface-3));
  border: 1px solid rgb(var(--input));
  cursor: pointer; padding: 0;
  transition: background-color var(--dur-base) var(--ease-out-quint), border-color var(--dur-fast) var(--ease-standard);
}
.Switch::after {
  content: ""; position: absolute; top: 2px; inset-inline-start: 2px;
  width: 20px; height: 20px; border-radius: var(--radius-pill);
  background: rgb(var(--background)); border: 1px solid rgb(var(--input));
  transition: transform var(--dur-base) var(--ease-out-quint);
}
.Switch[data-state~="checked"] { background: rgb(var(--primary)); border-color: rgb(var(--primary)); }
.Switch[data-state~="checked"]::after { transform: translateX(18px); border-color: rgb(var(--primary)); }
.Switch[data-state~="hover"] { border-color: rgb(var(--muted-foreground)); }
.Switch[data-state~="hover"][data-state~="checked"] { background: rgb(var(--jim-primary-hover)); border-color: rgb(var(--jim-primary-hover)); }
.Switch[data-state~="focus-visible"], .Switch:focus-visible { box-shadow: var(--focus-ring); outline: none; }
/* weight 10: disabled, raised to beat the compound [hover][checked] rule. */
.Switch[data-state~="disabled"][data-state~="disabled"] { background: rgb(var(--secondary)); border-color: rgb(var(--border)); cursor: not-allowed; box-shadow: none; }
.Switch[data-state~="disabled"][data-state~="disabled"]::after { background: rgb(var(--card)); border-color: rgb(var(--border)); }

/* =============================================================================
   SLIDER — slider: Context, Slider, SliderFilledTrack, SliderThumb, SliderTrack
   (5 parts). Hooks: useMove, usePanResponder, useSlider, useSliderThumb.
   ============================================================================= */
.Slider { display: flex; align-items: center; min-height: var(--tap-min); padding: var(--space-md) 0; }
.SliderTrack { position: relative; flex: 1; height: 4px; border-radius: var(--radius-pill); background: rgb(var(--jim-surface-3)); }
.SliderFilledTrack { position: absolute; inset-block: 0; inset-inline-start: 0; border-radius: var(--radius-pill); background: rgb(var(--primary)); }
.SliderThumb {
  position: absolute; top: 50%; width: 20px; height: 20px;
  margin-inline-start: -10px; transform: translateY(-50%);
  border-radius: var(--radius-pill);
  background: rgb(var(--primary)); border: 2px solid rgb(var(--background));
  cursor: grab;
}
.Slider[data-state~="hover"] .SliderThumb { background: rgb(var(--jim-primary-hover)); }
.Slider[data-state~="hover"] .SliderFilledTrack { background: rgb(var(--jim-primary-hover)); }
.Slider[data-state~="active"] .SliderThumb { background: rgb(var(--jim-primary-press)); cursor: grabbing; transform: translateY(-50%) scale(1.15); }
.Slider[data-state~="focus-visible"] .SliderThumb, .SliderThumb:focus-visible { box-shadow: var(--focus-ring); outline: none; }
.Slider[data-state~="disabled"] .SliderFilledTrack { background: rgb(var(--jim-fg-muted)); }
.Slider[data-state~="disabled"] .SliderThumb { background: rgb(var(--jim-fg-muted)); cursor: not-allowed; }
.Slider[data-orientation="vertical"] { flex-direction: column; height: 160px; padding: 0 var(--space-md); }
.Slider[data-orientation="vertical"] .SliderTrack { width: 4px; height: 100%; flex: 1; }

/* =============================================================================
   PROGRESS — progress: Progress, ProgressContext, ProgressFilledTrack (3 parts).
   ============================================================================= */
.Progress { width: 100%; height: 6px; border-radius: var(--radius-pill); background: rgb(var(--jim-surface-3)); overflow: hidden; }
.ProgressFilledTrack { height: 100%; border-radius: var(--radius-pill); background: rgb(var(--primary)); transition: width var(--dur-mid) var(--ease-out-quint); }
.Progress[data-status="success"] .ProgressFilledTrack { background: rgb(var(--jim-success)); }
.Progress[data-status="error"] .ProgressFilledTrack { background: rgb(var(--destructive)); }

/* =============================================================================
   SELECT — select: Select, SelectBackdrop, SelectContent, SelectContext,
   SelectDragIndicator, SelectDragIndicatorWrapper, SelectFlatList, SelectIcon,
   SelectInput, SelectItem, SelectPortal, SelectScrollView,
   SelectSectionHeaderText, SelectSectionList, SelectTrigger,
   SelectVirtualizedList (16 parts).
   On Android the Select opens as a sheet, which is why it owns a backdrop and
   a drag indicator at all.
   ============================================================================= */
.Select { display: block; }
.SelectTrigger {
  display: flex; align-items: center; gap: var(--space-sm); width: 100%;
  position: relative;
  min-height: var(--control-h); padding: 0 var(--space-md);
  background: rgb(var(--background)); border: 1px solid rgb(var(--input));
  border-radius: var(--radius-sm); cursor: pointer; text-align: left;
  transition: border-color var(--dur-fast) var(--ease-standard);
}
.SelectInput { flex: 1; min-width: 0; border: none; background: transparent; outline: none; color: rgb(var(--foreground)); font-family: var(--font-body); font-size: var(--fs-body-md); line-height: var(--lh-body-md); padding: var(--space-sm) 0; cursor: pointer; }
.SelectInput::placeholder { color: rgb(var(--muted-foreground)); }
.SelectIcon { width: 16px; height: 16px; flex: none; display: block; color: rgb(var(--muted-foreground)); transition: transform var(--dur-fast) var(--ease-standard); }
.SelectTrigger[data-state~="hover"] { border-color: rgb(var(--muted-foreground)); }
.SelectTrigger[data-state~="focus"], .SelectTrigger[data-state~="focus-visible"], .SelectTrigger:focus-visible { border-color: rgb(var(--ring)); box-shadow: var(--focus-ring); outline: none; }
.SelectTrigger[data-state~="invalid"] { border-color: rgb(var(--destructive)); }
/* weight 1: flip — the caret rotates when the sheet opens above the trigger */
.SelectTrigger[data-state~="flip"] .SelectIcon { transform: rotate(180deg); }
.SelectTrigger[data-state~="disabled"] { background: rgb(var(--card)); border-color: rgb(var(--border)); cursor: not-allowed; box-shadow: none; }
.SelectTrigger[data-state~="disabled"] .SelectInput { color: rgb(var(--jim-fg-muted)); }
.SelectTrigger[data-state~="disabled"] .SelectIcon { color: rgb(var(--jim-fg-muted)); }

.SelectBackdrop, .ActionsheetBackdrop, .ModalBackdrop, .AlertDialogBackdrop,
.PopoverBackdrop, .BottomSheetBackdrop {
  position: absolute; inset: 0; background: rgb(0 0 0 / 0.55);
}
.SelectPortal { position: relative; }
.SelectContent, .ActionsheetContent, .BottomSheetContent {
  background: rgb(var(--popover)); color: rgb(var(--popover-foreground));
  border: 1px solid rgb(var(--border)); border-bottom: none;
  border-start-start-radius: var(--radius-lg); border-start-end-radius: var(--radius-lg);
  padding: var(--space-sm) 0 var(--space-lg);
}
.SelectDragIndicatorWrapper, .ActionsheetDragIndicatorWrapper, .BottomSheetDragIndicatorWrapper { display: flex; justify-content: center; padding: var(--space-sm) 0 var(--space-md); }
.SelectDragIndicator, .ActionsheetDragIndicator, .BottomSheetDragIndicator { width: 40px; height: 4px; border-radius: var(--radius-pill); background: rgb(var(--jim-surface-3)); }
.SelectScrollView, .SelectFlatList, .SelectVirtualizedList, .SelectSectionList,
.ActionsheetScrollView, .ActionsheetFlatList, .ActionsheetVirtualizedList, .ActionsheetSectionList {
  display: block; max-height: 280px; overflow-y: auto;
}
.SelectSectionHeaderText, .ActionsheetSectionHeaderText {
  display: block; padding: var(--space-md) var(--space-lg) var(--space-xs);
  font-family: var(--font-mono); font-size: var(--fs-caption);
  letter-spacing: 0.08em; text-transform: uppercase;
  color: rgb(var(--muted-foreground));
}
.SelectItem, .ActionsheetItem, .BottomSheetItem, .MenuItem {
  display: flex; align-items: center; gap: var(--space-md);
  width: 100%; min-height: var(--tap-min);
  padding: var(--space-md) var(--space-lg);
  background: transparent; border: none; text-align: left; cursor: pointer;
  color: rgb(var(--popover-foreground));
  font-family: var(--font-body); font-size: var(--fs-body-md); line-height: var(--lh-body-md);
  transition: background-color var(--dur-fast) var(--ease-standard);
}
.SelectItem[data-state~="hover"], .ActionsheetItem[data-state~="hover"],
.BottomSheetItem[data-state~="hover"], .MenuItem[data-state~="hover"] { background: rgb(var(--accent)); color: rgb(var(--accent-foreground)); }
.SelectItem[data-state~="pressed"], .ActionsheetItem[data-state~="pressed"],
.BottomSheetItem[data-state~="pressed"], .MenuItem[data-state~="pressed"] { background: rgb(var(--jim-surface-3)); color: rgb(var(--foreground)); }
.SelectItem[data-state~="focus-visible"], .ActionsheetItem[data-state~="focus-visible"], .MenuItem[data-state~="focus-visible"] { box-shadow: var(--focus-ring); outline: none; }
.SelectItem[data-state~="checked"] { font-weight: var(--fw-semibold); color: rgb(var(--jim-primary-on-tint)); }
.SelectItem[data-state~="checked"]::after { content: ""; margin-inline-start: auto; width: 8px; height: 8px; border-radius: var(--radius-pill); background: rgb(var(--primary)); }
/* weight 10: disabled. The [data-action] form matches the specificity of the
   negative-action hover rule below, and the icon rule matches the hover icon
   rule, so a disabled destructive item can never render a tinted hover. */
.SelectItem[data-state~="disabled"], .ActionsheetItem[data-state~="disabled"],
.BottomSheetItem[data-state~="disabled"], .MenuItem[data-state~="disabled"],
.SelectItem[data-action][data-state~="disabled"], .ActionsheetItem[data-action][data-state~="disabled"],
.BottomSheetItem[data-action][data-state~="disabled"], .MenuItem[data-action][data-state~="disabled"] {
  color: rgb(var(--jim-fg-muted)); cursor: not-allowed; background: transparent; box-shadow: none;
}
.ActionsheetItemText, .MenuItemLabel { flex: 1; min-width: 0; font: inherit; color: inherit; }
.ActionsheetIcon, .MenuItemIcon { width: 16px; height: 16px; flex: none; display: block; color: rgb(var(--muted-foreground)); }
.ActionsheetItem[data-state~="hover"] .ActionsheetIcon, .MenuItem[data-state~="hover"] .MenuItemIcon { color: rgb(var(--accent-foreground)); }
.ActionsheetItem[data-action="negative"], .MenuItem[data-action="negative"] { color: rgb(var(--jim-destructive-text)); }
.ActionsheetItem[data-action="negative"][data-state~="hover"], .MenuItem[data-action="negative"][data-state~="hover"] { background: rgb(var(--jim-destructive-tint)); color: rgb(var(--jim-destructive-text)); }
.ActionsheetItem[data-action="negative"] .ActionsheetIcon, .MenuItem[data-action="negative"] .MenuItemIcon { color: currentColor; }
/* Declared last, so disabled wins on order as well as on specificity. */
.ActionsheetItem[data-state~="disabled"] .ActionsheetIcon,
.MenuItem[data-state~="disabled"] .MenuItemIcon,
.ActionsheetItem[data-action][data-state~="disabled"] .ActionsheetIcon,
.MenuItem[data-action][data-state~="disabled"] .MenuItemIcon { color: rgb(var(--jim-fg-muted)); }

/* =============================================================================
   MENU — menu: Menu, MenuContext, MenuItem, MenuItemLabel, MenuItemStately,
   Separator (6 parts). Hooks: useMenu, useMenuItem, useMenuSection,
   useMenuTrigger, and their .web variants.
   ============================================================================= */
.Menu {
  min-width: 220px; padding: var(--space-xs) 0;
  background: rgb(var(--popover)); color: rgb(var(--popover-foreground));
  border: 1px solid rgb(var(--border)); border-radius: var(--radius-md);
}
.Menu .Separator, .Separator { height: 1px; margin: var(--space-xs) 0; background: rgb(var(--border)); border: none; }
.MenuItemStately { display: block; }
.MenuSectionHeader { display: block; padding: var(--space-md) var(--space-lg) var(--space-xs); font-family: var(--font-mono); font-size: var(--fs-caption); letter-spacing: 0.08em; text-transform: uppercase; color: rgb(var(--muted-foreground)); }

/* =============================================================================
   ACTIONSHEET — actionsheet: Actionsheet, ActionsheetBackdrop,
   ActionsheetContent, ActionsheetContentContext, ActionsheetDragIndicator,
   ActionsheetDragIndicatorWrapper, ActionsheetFlatList, ActionsheetIcon,
   ActionsheetItem, ActionsheetItemText, ActionsheetScrollView,
   ActionsheetSectionHeaderText, ActionsheetSectionList,
   ActionsheetVirtualizedList, OverlayAnimatePresence (15 parts).
   Styling shared with Select above; only the container differs.
   ============================================================================= */
.Actionsheet, .BottomSheet, .Modal, .AlertDialog, .Popover {
  position: relative; overflow: hidden;
  border: 1px solid rgb(var(--border)); border-radius: var(--radius-md);
  background: rgb(var(--card));
}
.Actionsheet, .BottomSheet { display: flex; flex-direction: column; justify-content: flex-end; min-height: 340px; }
.Modal, .AlertDialog { display: grid; place-items: center; min-height: 300px; padding: var(--space-lg); }

/* =============================================================================
   BOTTOMSHEET — bottomsheet: BottomSheet, BottomSheetBackdrop,
   BottomSheetContent, BottomSheetContentContext, BottomSheetDragIndicator,
   BottomSheetDragIndicatorWrapper, BottomSheetItem (7 parts).
   ============================================================================= */
/* container and item styling shared above; nothing further is needed */

/* =============================================================================
   MODAL — modal: Context, Modal, ModalBackdrop, ModalBody, ModalCloseButton,
   ModalContent, ModalFooter, ModalHeader, OverlayAnimatePresence (9 parts).
   ============================================================================= */
.ModalContent, .AlertDialogContent, .PopoverContent {
  position: relative; width: 100%; max-width: 400px;
  background: rgb(var(--popover)); color: rgb(var(--popover-foreground));
  border: 1px solid rgb(var(--border)); border-radius: var(--radius-md);
  overflow: hidden;
}
.ModalHeader, .AlertDialogHeader, .PopoverHeader {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-md);
  padding: var(--space-lg) var(--space-lg) var(--space-md);
}
.ModalHeader h3, .AlertDialogHeader h3, .PopoverHeader h3 { margin: 0; font-size: var(--fs-heading-sm); line-height: var(--lh-heading-sm); font-weight: var(--fw-semibold); color: rgb(var(--popover-foreground)); }
.ModalBody, .AlertDialogBody, .PopoverBody { padding: 0 var(--space-lg) var(--space-lg); font-size: var(--fs-body-md); line-height: var(--lh-body-lg); color: rgb(var(--jim-fg-2)); }
.ModalBody > :last-child, .AlertDialogBody > :last-child, .PopoverBody > :last-child { margin-bottom: 0; }
.ModalFooter, .AlertDialogFooter, .PopoverFooter {
  display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-md);
  padding: var(--space-md) var(--space-lg) var(--space-lg);
  border-top: 1px solid rgb(var(--jim-border-faint));
}
/* DESIGN.md: the primary (the filled button) sits on the trailing edge, so it
   is written LAST in the DOM. Below the tablet rung (--bp-two, 800) the row
   stacks full width with the primary on top, which column-reverse gives from
   the same DOM order. Applies to every footer and to an ActionRow. */
.ActionRow { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-md); }
@media (max-width: 799.98px) {
  .ModalFooter, .AlertDialogFooter, .PopoverFooter, .ActionRow { flex-direction: column-reverse; align-items: stretch; }
  .ModalFooter > .Button, .AlertDialogFooter > .Button, .PopoverFooter > .Button, .ActionRow > .Button { width: 100%; }
}
.ModalCloseButton, .AlertDialogCloseButton, .PopoverCloseButton {
  flex: none; width: var(--tap-min); height: var(--tap-min);
  margin: calc(var(--space-md) * -1) calc(var(--space-md) * -1) 0 0;
  display: grid; place-items: center;
  background: transparent; border: none; border-radius: var(--radius-sm);
  color: rgb(var(--muted-foreground)); cursor: pointer;
}
.ModalCloseButton[data-state~="hover"], .AlertDialogCloseButton[data-state~="hover"], .PopoverCloseButton[data-state~="hover"] { background: rgb(var(--secondary)); color: rgb(var(--foreground)); }
.ModalCloseButton:focus-visible, .AlertDialogCloseButton:focus-visible, .PopoverCloseButton:focus-visible { box-shadow: var(--focus-ring); outline: none; }

/* =============================================================================
   POPOVER — popover: OverlayAnimatePresence, Popover, PopoverArrow,
   PopoverBackdrop, PopoverBody, PopoverCloseButton, PopoverContent,
   PopoverContext, PopoverFooter, PopoverHeader (10 parts).
   ============================================================================= */
.Popover { display: grid; place-items: center; min-height: 260px; padding: var(--space-lg); }
.PopoverContent { max-width: 300px; overflow: visible; }  /* the arrow sits 7px outside the box; the shared overflow: hidden above clipped it to nothing */
.PopoverArrow {
  position: absolute; width: 12px; height: 12px; transform: rotate(45deg);
  background: rgb(var(--popover));
  border-left: 1px solid rgb(var(--border)); border-top: 1px solid rgb(var(--border));
  top: -7px; inset-inline-start: 24px;
}

/* =============================================================================
   TOOLTIP — tooltip: OverlayAnimatePresence, Tooltip, TooltipArrow,
   TooltipContent, TooltipText (5 parts).
   Inverted, because a tooltip is transient and must not read as a surface.
   ============================================================================= */
.Tooltip { position: relative; display: inline-block; }
.TooltipContent {
  display: inline-block; padding: var(--space-sm) var(--space-md);
  background: rgb(var(--jim-fg-1)); border-radius: var(--radius-sm);
  max-width: 240px;
}
.TooltipText { font-size: var(--fs-label-md); line-height: var(--lh-label-md); color: rgb(var(--jim-fg-inverse)); }
.TooltipArrow { width: 10px; height: 10px; transform: rotate(45deg); background: rgb(var(--jim-fg-1)); margin: -5px auto 0; }

/* =============================================================================
   ALERT — alert: Alert, AlertIcon, AlertText (3 parts).

   This is v2's ob-banner, the messaging component, 45 usages. Quoting it:
     .ob-banner    display:flex; align-items:flex-start; gap:10px;
                   padding:11px 13px; border-radius:var(--radius-md);
                   font-size:12.5px; line-height:1.5
     .ob-banner svg  width:16px; height:16px; flex-shrink:0; margin-top:1px
     .ob-banner b    font-weight:600
     .ob-banner-ok   background:var(--success-bg); color:var(--success)
   and the note that ships with it: "The plain banner carries tint and text
   colour from the same status token pair and draws NO border at all."

   So the tint IS the boundary here. Nothing is drawn around it. --radius-md is
   also v2's most-used radius, 197 occurrences. Text keeps the on-tint role, so
   every variant still holds at least 4.53:1.
   ============================================================================= */
.Alert {
  display: flex; align-items: flex-start; gap: var(--space-md);
  padding: var(--space-md) var(--space-lg);
  border: none; border-radius: var(--radius-md);
}
.AlertIcon { width: 16px; height: 16px; flex: none; margin-top: 1px; display: block; }
.AlertText { font-size: var(--fs-body-sm); line-height: var(--lh-body-lg); }
.AlertText b { font-weight: var(--fw-semibold); }
/* The neutral banner is v2's wf-scope-note: a surface tier, no border, no hue.
   --jim-fg-2 rather than --muted-foreground, which measures 3.90:1 on
   --jim-surface-3 and fails. */
.Alert[data-action="muted"] { background: rgb(var(--jim-surface-3)); }
.Alert[data-action="muted"] .AlertText { color: rgb(var(--jim-fg-2)); }
.Alert[data-action="muted"] .AlertIcon { color: rgb(var(--jim-fg-2)); }
.Alert[data-action="info"] { background: rgb(var(--jim-link-tint)); }
.Alert[data-action="info"] .AlertText, .Alert[data-action="info"] .AlertIcon { color: rgb(var(--jim-link-text)); }
.Alert[data-action="success"] { background: rgb(var(--jim-success-tint)); }
.Alert[data-action="success"] .AlertText, .Alert[data-action="success"] .AlertIcon { color: rgb(var(--jim-success-text)); }
.Alert[data-action="warning"] { background: rgb(var(--jim-warn-tint)); }
.Alert[data-action="warning"] .AlertText, .Alert[data-action="warning"] .AlertIcon { color: rgb(var(--jim-warn-text)); }
.Alert[data-action="error"] { background: rgb(var(--jim-destructive-tint)); }
.Alert[data-action="error"] .AlertText, .Alert[data-action="error"] .AlertIcon { color: rgb(var(--jim-destructive-text)); }

/* =============================================================================
   TOAST — toast: OverlayAnimatePresence, Toast, ToastComponent, ToastContext,
   ToastDescription, ToastList, ToastTitle (7 parts).
   ============================================================================= */
.ToastList { display: flex; flex-direction: column; gap: var(--space-md); width: 100%; }
.Toast, .ToastComponent {
  display: block; padding: var(--space-md) var(--space-lg);
  background: rgb(var(--secondary)); color: rgb(var(--secondary-foreground));
  border: 1px solid rgb(var(--border)); border-radius: var(--radius-md);
}
.ToastTitle { display: block; font-size: var(--fs-label-md); line-height: var(--lh-label-md); font-weight: var(--fw-semibold); color: rgb(var(--foreground)); }
.ToastDescription { display: block; margin-top: 2px; font-size: var(--fs-label-sm); line-height: var(--lh-body-lg); color: rgb(var(--jim-fg-2)); }
/* A toast floats over arbitrary content, so unlike the Alert it does need an
   edge to detach from whatever is underneath. That is the second legal form in
   the v2 rule: derive it, mixing the status colour toward --border. Never the
   raw status colour at partial alpha. */
.Toast[data-action="success"] { background: rgb(var(--jim-success-tint)); border-color: var(--jim-success-line); }
.Toast[data-action="success"] .ToastTitle, .Toast[data-action="success"] .ToastDescription { color: rgb(var(--jim-success-text)); }
.Toast[data-action="error"] { background: rgb(var(--jim-destructive-tint)); border-color: var(--jim-destructive-line); }
.Toast[data-action="error"] .ToastTitle, .Toast[data-action="error"] .ToastDescription { color: rgb(var(--jim-destructive-text)); }
.Toast[data-action="warning"] { background: rgb(var(--jim-warn-tint)); border-color: var(--jim-warn-line); }
.Toast[data-action="warning"] .ToastTitle, .Toast[data-action="warning"] .ToastDescription { color: rgb(var(--jim-warn-text)); }

/* =============================================================================
   ACCORDION — accordion: Accordion, AccordionContent, AccordionContentText,
   AccordionHeader, AccordionIcon, AccordionItem, AccordionTitleText,
   AccordionTrigger, AnimatedHeight, Context (10 parts).
   ============================================================================= */
.Accordion { border: 1px solid rgb(var(--border)); border-radius: var(--radius-md); overflow: hidden; background: rgb(var(--background)); }
.AccordionItem + .AccordionItem { border-top: 1px solid rgb(var(--border)); }
.AccordionHeader { margin: 0; }
.AccordionTrigger {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-md);
  width: 100%; min-height: var(--tap-min);
  padding: var(--space-md) var(--space-lg);
  background: transparent; border: none; text-align: left; cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-standard);
}
.AccordionTitleText { font-size: var(--fs-body-md); line-height: var(--lh-body-md); font-weight: var(--fw-medium); color: rgb(var(--jim-fg-1)); }
.AccordionIcon { width: 16px; height: 16px; flex: none; display: block; color: rgb(var(--muted-foreground)); transition: transform var(--dur-base) var(--ease-standard); }
.AnimatedHeight { display: grid; grid-template-rows: 0fr; transition: grid-template-rows var(--dur-mid) var(--ease-out-quint); }
.AnimatedHeight > * { overflow: hidden; }
.AccordionContent { padding: 0 var(--space-lg) var(--space-lg); }
.AccordionContentText { font-size: var(--fs-body-sm); line-height: var(--lh-body-lg); color: rgb(var(--jim-fg-2)); }
.AccordionTrigger[data-state~="hover"] { background: rgb(var(--card)); }
.AccordionTrigger[data-state~="hover"] .AccordionTitleText { color: rgb(var(--foreground)); }
.AccordionTrigger[data-state~="pressed"] { background: rgb(var(--secondary)); }
.AccordionTrigger[data-state~="focus-visible"], .AccordionTrigger:focus-visible { box-shadow: var(--focus-ring); outline: none; }
/* weight 1: flip — expanded */
.AccordionItem[data-state~="flip"] .AccordionIcon,
.AccordionTrigger[data-state~="flip"] .AccordionIcon { transform: rotate(180deg); }
.AccordionItem[data-state~="flip"] .AnimatedHeight { grid-template-rows: 1fr; }
.AccordionTrigger[data-state~="disabled"] { cursor: not-allowed; background: transparent; }
.AccordionTrigger[data-state~="disabled"] .AccordionTitleText,
.AccordionTrigger[data-state~="disabled"] .AccordionIcon { color: rgb(var(--jim-fg-muted)); }

/* =============================================================================
   TABS — tabs: Context, Tabs, TabsContent, TabsContentWrapper, TabsIndicator,
   TabsList, TabsTrigger, TabsTriggerIcon, TabsTriggerText (9 parts).
   ============================================================================= */
.Tabs { display: block; }
.TabsList { position: relative; display: flex; gap: var(--space-xs); border-bottom: 1px solid rgb(var(--border)); overflow-x: auto; }
.TabsTrigger {
  position: relative; display: inline-flex; align-items: center; gap: var(--space-sm);
  /* Stays at --tap-min at every width. The prototype copy took --control-h
     here; it is reverted because .TabsList scrolls, a scroll container clips
     any hit area outside its box, and so the slop that saves a 36px Button
     cannot save a 36px tab. DESIGN.md's 48dp floor wins. */
  min-height: var(--tap-min); padding: 0 var(--space-lg);
  background: transparent; border: none; cursor: pointer; white-space: nowrap;
  transition: color var(--dur-fast) var(--ease-standard), background-color var(--dur-fast) var(--ease-standard);
}
.TabsTriggerText { font-size: var(--fs-label-md); line-height: var(--lh-label-md); font-weight: var(--fw-medium); color: rgb(var(--jim-fg-2)); }
.TabsTriggerIcon { width: 16px; height: 16px; flex: none; display: block; color: rgb(var(--muted-foreground)); }
.TabsIndicator { position: absolute; bottom: -1px; height: 2px; background: rgb(var(--primary)); border-radius: var(--radius-pill); transition: transform var(--dur-base) var(--ease-out-quint), width var(--dur-base) var(--ease-out-quint); }
.TabsTrigger[data-state~="hover"] { background: rgb(var(--card)); }
.TabsTrigger[data-state~="hover"] .TabsTriggerText { color: rgb(var(--foreground)); }
.TabsTrigger[data-state~="hover"] .TabsTriggerIcon { color: rgb(var(--foreground)); }
.TabsTrigger[data-state~="focus-visible"], .TabsTrigger:focus-visible {
  /* TabsList sets overflow-x: auto so the labels can scroll rather than shrink
     below the 48dp target. That establishes a clipping context, and an outset
     ring gets its top and bottom sliced off, leaving two vertical brackets
     around the label. An inset ring draws inside the trigger's own box, so it
     survives the scroll container and still reads as a ring on all four sides. */
  box-shadow: inset 0 0 0 2px rgb(var(--ring));
  outline: none; border-radius: var(--radius-sm);
}
/* weight 6: active — the selected tab */
.TabsTrigger[data-state~="active"] .TabsTriggerText { color: rgb(var(--foreground)); font-weight: var(--fw-semibold); }
.TabsTrigger[data-state~="active"] .TabsTriggerIcon { color: rgb(var(--primary)); }
.TabsTrigger[data-state~="disabled"] { cursor: not-allowed; background: transparent; }
.TabsTrigger[data-state~="disabled"] .TabsTriggerText, .TabsTrigger[data-state~="disabled"] .TabsTriggerIcon { color: rgb(var(--jim-fg-muted)); }
.TabsContentWrapper { display: block; }
.TabsContent { padding: var(--space-lg) 0 0; font-size: var(--fs-body-md); line-height: var(--lh-body-lg); color: rgb(var(--jim-fg-2)); }

/* =============================================================================
   AVATAR — avatar: Avatar, AvatarBadge, AvatarFallbackText, AvatarGroup,
   AvatarImage (5 parts).
   ============================================================================= */
.Avatar {
  position: relative; width: 40px; height: 40px; flex: none;
  display: grid; place-items: center; border-radius: var(--radius-pill);
  background: rgb(var(--secondary)); overflow: visible;
}
.Avatar[data-size="sm"] { width: 32px; height: 32px; }
.Avatar[data-size="lg"] { width: 56px; height: 56px; }
.AvatarImage { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: var(--radius-pill); object-fit: cover; }
.AvatarFallbackText { font-family: var(--font-body); font-size: var(--fs-label-md); font-weight: var(--fw-semibold); color: rgb(var(--secondary-foreground)); letter-spacing: 0.02em; }
.AvatarBadge {
  position: absolute; inset-block-end: -1px; inset-inline-end: -1px;
  width: 12px; height: 12px; border-radius: var(--radius-pill);
  background: rgb(var(--jim-success)); border: 2px solid rgb(var(--background));
}
.AvatarBadge[data-status="busy"] { background: rgb(var(--destructive)); }
.AvatarBadge[data-status="away"] { background: rgb(var(--jim-warn)); }
.AvatarBadge[data-status="offline"] { background: rgb(var(--muted-foreground)); }
.AvatarGroup { display: flex; align-items: center; }
.AvatarGroup .Avatar + .Avatar { margin-inline-start: -12px; }
.AvatarGroup .Avatar { box-shadow: 0 0 0 2px rgb(var(--background)); }

/* =============================================================================
   IMAGE — image: Image (1 part).
   ============================================================================= */
.Image { display: block; width: 100%; height: auto; border-radius: var(--radius-md); background: rgb(var(--secondary)); object-fit: cover; }

/* =============================================================================
   ICON — icon root. No exported parts under creator/; the root is the API and
   size comes from the class, not a prop.
   ============================================================================= */
.Icon { display: block; flex: none; width: 16px; height: 16px; color: currentColor; }
.Icon[data-size="xs"] { width: 12px; height: 12px; }
.Icon[data-size="sm"] { width: 14px; height: 14px; }
.Icon[data-size="lg"] { width: 20px; height: 20px; }
.Icon[data-size="xl"] { width: 24px; height: 24px; }

/* =============================================================================
   CALENDAR — calendar: Calendar, CalendarBody, CalendarContext, CalendarDay,
   CalendarDayIndicator, CalendarDayText, CalendarFooter, CalendarGrid,
   CalendarHeader, CalendarHeaderMonthSelect, CalendarHeaderNextButton,
   CalendarHeaderPrevButton, CalendarHeaderTitle, CalendarHeaderYearSelect,
   CalendarWeek, CalendarWeekDay, CalendarWeekDaysHeader, CalendarWeekNumber
   (18 parts).
   Every CalendarDay is a 44px cell inside a row that is at least 48dp tall, so
   the tap target clears the floor while the grid still fits a 360dp column.
   ============================================================================= */
.Calendar { background: rgb(var(--background)); border: 1px solid rgb(var(--border)); border-radius: var(--radius-md); padding: var(--space-md); max-width: 328px; }
/* Six controls do not fit one 328dp row. Forcing them onto one row either
   wraps the title ("August" / "2026") or clips it to "August 202", and
   clipping is the worse of the two. So the header is a two-row grid:
   arrows and title on top, the month and year selects beneath. Both selects
   get room for a full label, both arrows keep a 48dp target, and nothing is
   truncated or hidden. */
.CalendarHeader {
  display: grid;
  grid-template-columns: var(--tap-min) minmax(0, 1fr) minmax(0, 1fr) var(--tap-min);
  align-items: center; gap: var(--space-xs) var(--space-sm);
  margin-bottom: var(--space-md);
}
.CalendarHeaderTitle {
  grid-row: 1; grid-column: 2 / 4; min-width: 0; text-align: center;
  font-size: var(--fs-heading-sm); line-height: var(--lh-heading-sm);
  font-weight: var(--fw-semibold); color: rgb(var(--foreground));
}
.CalendarHeaderPrevButton, .CalendarHeaderNextButton {
  width: var(--tap-min); height: var(--tap-min); flex: none;
  display: grid; place-items: center; border-radius: var(--radius-sm);
  background: transparent; border: none; cursor: pointer; color: rgb(var(--jim-fg-2));
}
.CalendarHeaderPrevButton { grid-row: 1; grid-column: 1; }
.CalendarHeaderNextButton { grid-row: 1; grid-column: 4; }
.CalendarHeaderPrevButton[data-state~="hover"], .CalendarHeaderNextButton[data-state~="hover"] { background: rgb(var(--secondary)); color: rgb(var(--foreground)); }
.CalendarHeaderPrevButton:focus-visible, .CalendarHeaderNextButton:focus-visible { box-shadow: var(--focus-ring); outline: none; }
.CalendarHeaderPrevButton[data-state~="disabled"], .CalendarHeaderNextButton[data-state~="disabled"] { color: rgb(var(--jim-fg-muted)); cursor: not-allowed; background: transparent; }
.CalendarHeaderMonthSelect, .CalendarHeaderYearSelect {
  grid-row: 2; min-width: 0;
  min-height: 40px; padding: 0 var(--space-sm);
  background: rgb(var(--background)); color: rgb(var(--jim-fg-1));
  border: 1px solid rgb(var(--input)); border-radius: var(--radius-sm);
  font-family: var(--font-body); font-size: var(--fs-label-md); cursor: pointer;
}
.CalendarHeaderMonthSelect { grid-column: 1 / 3; }
.CalendarHeaderYearSelect { grid-column: 3 / 5; }
.CalendarHeaderMonthSelect:focus-visible, .CalendarHeaderYearSelect:focus-visible { box-shadow: var(--focus-ring); outline: none; }
.CalendarWeekDaysHeader { display: grid; grid-template-columns: 28px repeat(7, 1fr); gap: 2px; margin-bottom: var(--space-xs); }
.CalendarWeekDay { text-align: center; font-family: var(--font-mono); font-size: var(--fs-caption); line-height: var(--lh-caption); color: rgb(var(--muted-foreground)); padding: var(--space-xs) 0; }
.CalendarBody { display: block; }
.CalendarGrid { display: flex; flex-direction: column; gap: 2px; }
.CalendarWeek { display: grid; grid-template-columns: 28px repeat(7, 1fr); gap: 2px; min-height: var(--tap-min); align-items: center; }
.CalendarWeekNumber { text-align: center; font-family: var(--font-mono); font-size: var(--fs-caption); color: rgb(var(--muted-foreground)); }
.CalendarDay {
  position: relative; display: grid; place-items: center;
  height: 44px; border-radius: var(--radius-sm);
  background: transparent; border: none; cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-standard);
}
.CalendarDayText { font-family: var(--font-body); font-size: var(--fs-body-sm); line-height: 1; color: rgb(var(--jim-fg-1)); }
.CalendarDayIndicator { position: absolute; bottom: 6px; width: 4px; height: 4px; border-radius: var(--radius-pill); background: rgb(var(--primary)); }
.CalendarDay[data-outside="true"] .CalendarDayText { color: rgb(var(--muted-foreground)); }
.CalendarDay[data-state~="hover"] { background: rgb(var(--secondary)); }
.CalendarDay[data-state~="hover"] .CalendarDayText { color: rgb(var(--foreground)); }
.CalendarDay[data-state~="focus-visible"], .CalendarDay:focus-visible { box-shadow: var(--focus-ring); outline: none; }
.CalendarDay[data-today="true"] { box-shadow: inset 0 0 0 1px rgb(var(--jim-border-strong)); }
.CalendarDay[data-state~="checked"] { background: rgb(var(--primary)); }
.CalendarDay[data-state~="checked"] .CalendarDayText { color: rgb(var(--primary-foreground)); font-weight: var(--fw-semibold); }
.CalendarDay[data-state~="checked"] .CalendarDayIndicator { background: rgb(var(--primary-foreground)); }
.CalendarDay[data-state~="disabled"] { cursor: not-allowed; background: transparent; box-shadow: none; }
.CalendarDay[data-state~="disabled"] .CalendarDayText { color: rgb(var(--jim-fg-muted)); }
.CalendarFooter { display: flex; justify-content: space-between; align-items: center; gap: var(--space-md); margin-top: var(--space-md); padding-top: var(--space-md); border-top: 1px solid rgb(var(--jim-border-faint)); }

/* =============================================================================
   DATE TIME PICKER — date-time-picker: DateTimePicker, DateTimePickerContext,
   DateTimePickerIcon, DateTimePickerInput, DateTimePickerTrigger (5 parts).
   ============================================================================= */
.DateTimePicker { display: block; }
.DateTimePickerTrigger {
  display: flex; align-items: center; gap: var(--space-sm); width: 100%;
  position: relative;
  min-height: var(--control-h); padding: 0 var(--space-md);
  background: rgb(var(--background)); border: 1px solid rgb(var(--input));
  border-radius: var(--radius-sm); cursor: pointer; text-align: left;
}
.DateTimePickerInput { flex: 1; min-width: 0; border: none; background: transparent; outline: none; color: rgb(var(--foreground)); font-family: var(--font-mono); font-size: var(--fs-mono); line-height: var(--lh-mono); padding: var(--space-sm) 0; cursor: pointer; }
.DateTimePickerInput::placeholder { color: rgb(var(--muted-foreground)); font-family: var(--font-body); }
.DateTimePickerIcon { width: 16px; height: 16px; flex: none; display: block; color: rgb(var(--muted-foreground)); }
.DateTimePickerTrigger[data-state~="hover"] { border-color: rgb(var(--muted-foreground)); }
.DateTimePickerTrigger[data-state~="focus"], .DateTimePickerTrigger:focus-visible { border-color: rgb(var(--ring)); box-shadow: var(--focus-ring); outline: none; }
.DateTimePickerTrigger[data-state~="invalid"] { border-color: rgb(var(--destructive)); }
.DateTimePickerTrigger[data-state~="read-only"] { background: rgb(var(--card)); }
.DateTimePickerTrigger[data-state~="disabled"] { background: rgb(var(--card)); border-color: rgb(var(--border)); cursor: not-allowed; box-shadow: none; }
.DateTimePickerTrigger[data-state~="disabled"] .DateTimePickerInput,
.DateTimePickerTrigger[data-state~="disabled"] .DateTimePickerIcon { color: rgb(var(--jim-fg-muted)); }

/* =============================================================================
   CHAT AI — chat-ai root. No exported parts under creator/; it composes the
   primitives below. Jim's agent stream is built from it.
   ============================================================================= */
.ChatAi { display: flex; flex-direction: column; gap: var(--space-md); }
.ChatBubble { max-width: 88%; padding: var(--space-md) var(--space-lg); border-radius: var(--radius-md); font-size: var(--fs-body-md); line-height: var(--lh-body-lg); }
.ChatBubble[data-role="user"] { align-self: flex-end; background: rgb(var(--primary)); color: rgb(var(--primary-foreground)); border-end-end-radius: var(--radius-xs); }
.ChatBubble[data-role="agent"] { align-self: flex-start; background: rgb(var(--card)); color: rgb(var(--jim-fg-1)); border: 1px solid rgb(var(--border)); border-end-start-radius: var(--radius-xs); }
.ChatBubble[data-role="tool"] { align-self: stretch; background: rgb(var(--background)); border: 1px solid rgb(var(--border)); font-family: var(--font-mono); font-size: var(--fs-mono); line-height: var(--lh-mono); color: rgb(var(--jim-fg-2)); }
.ChatMeta { font-family: var(--font-mono); font-size: var(--fs-caption); color: rgb(var(--muted-foreground)); }
.ChatTyping { display: inline-flex; gap: 4px; align-items: center; }
.ChatTyping span { width: 5px; height: 5px; border-radius: var(--radius-pill); background: rgb(var(--muted-foreground)); animation: gs-blink 1.2s infinite; }
.ChatTyping span:nth-child(2) { animation-delay: 0.2s; }
.ChatTyping span:nth-child(3) { animation-delay: 0.4s; }
@keyframes gs-blink { 0%, 60%, 100% { opacity: 0.3; } 30% { opacity: 1; } }

/* =============================================================================
   STEPPER — Jim composite, not a Gluestack root. Gluestack v5 ships no stepper,
   so this composes VStack/HStack/Icon/Text the way ChatAi does, and its class
   names are Jim's, prefixed Stepper so no future Gluestack part can collide.
   Parts: Stepper (ol), StepperItem (li), StepperMark, StepperIcon, StepperBody,
   StepperLabel, StepperNote, StepperState (screen-reader word).

   Built for a list of agent runs: where a run is in its workflow. State reads
   WITHOUT colour, from shape alone. Every mark sits in the same 20dp box:
     upcoming   empty 1px ring              --input          3.54 L  3.44 D
     current    2px ring + 8dp centre dot   --foreground    21.00 L 16.82 D
     checked    filled disc + tick          --muted-foreground 6.10 L 6.81 D
                  tick in --background on the disc             6.10 L 6.81 D
     invalid    filled disc + cross         --destructive    4.83 L  6.23 D
                  cross --primary-foreground on it              4.83 L  6.23 D
     disabled   dashed 1px ring + bar       --input          3.54 L  3.44 D
   (contrast on --background; on --card the lowest, upcoming, is 3.25 / 3.31.)
   Done is deliberately the lighter fill: the current step is the one to find,
   so it carries the most contrast and the done discs recede.
   Labels: current and failed --foreground semibold (21.00 / 16.82), done
   --jim-fg-2 (10.05 / 10.99), upcoming and skipped --muted-foreground
   (6.10 / 6.81). The connector is one rail: travelled (after a done or
   skipped step) is 2px --muted-foreground, ahead is 1px --jim-border-strong.
   No accent anywhere: a stepper is status, and the accent is for actions.
   The current item carries aria-current="step", and every item carries a
   StepperState word for a screen reader. Not interactive by itself; to make a
   step tappable, wrap its body in a Pressable, which owns the 48dp target.
   ============================================================================= */
.Stepper { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; }
.StepperItem {
  position: relative; display: grid; grid-template-columns: 20px minmax(0, 1fr);
  column-gap: var(--space-md); padding-bottom: var(--space-lg);
}
.StepperItem:last-child { padding-bottom: 0; }
/* The rail runs from just under this mark to just above the next one, so its
   length is the gap whatever the note length: never a stub. */
.StepperItem:not(:last-child)::before {
  content: ""; position: absolute;
  inset-inline-start: 9.5px; top: 21px; bottom: 1px;
  border-inline-start: 1px solid rgb(var(--jim-border-strong));
}
.StepperItem:is([data-state~="checked"], [data-state~="disabled"]):not(:last-child)::before {
  inset-inline-start: 9px; border-inline-start: 2px solid rgb(var(--muted-foreground));
}
.StepperMark {
  position: relative; width: 20px; height: 20px; box-sizing: border-box;
  display: grid; place-items: center; border-radius: var(--radius-pill);
  border: 1px solid rgb(var(--input)); color: rgb(var(--background));
}
.StepperIcon { width: 12px; height: 12px; display: block; }
.StepperBody { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.StepperLabel { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-sm); min-height: 20px; font-size: var(--fs-body-sm); line-height: var(--lh-body-sm); color: rgb(var(--muted-foreground)); }
.StepperNote { font-size: var(--fs-label-md); line-height: var(--lh-label-md); color: rgb(var(--jim-fg-2)); text-wrap: pretty; }
.StepperState { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
/* weight 1: checked — done */
.StepperItem[data-state~="checked"] .StepperMark { background: rgb(var(--muted-foreground)); border-color: rgb(var(--muted-foreground)); }
.StepperItem[data-state~="checked"] .StepperLabel { color: rgb(var(--jim-fg-2)); }
/* weight 2: invalid — failed here */
.StepperItem[data-state~="invalid"] .StepperMark { background: rgb(var(--destructive)); border-color: rgb(var(--destructive)); color: rgb(var(--primary-foreground)); }
.StepperItem[data-state~="invalid"] .StepperLabel { color: rgb(var(--foreground)); font-weight: var(--fw-semibold); }
/* weight 6: active — current */
.StepperItem[data-state~="active"] .StepperMark { border: 2px solid rgb(var(--foreground)); }
.StepperItem[data-state~="active"] .StepperMark::after { content: ""; width: 8px; height: 8px; border-radius: var(--radius-pill); background: rgb(var(--foreground)); }
.StepperItem[data-state~="active"] .StepperLabel { color: rgb(var(--foreground)); font-weight: var(--fw-semibold); }
/* weight 10: disabled — skipped. A dashed ring alone is too close to an empty
   ring at 20dp, so it also carries a bar through the centre. */
.StepperItem[data-state~="disabled"] .StepperMark { border-style: dashed; background: transparent; }
.StepperItem[data-state~="disabled"] .StepperMark::after { content: ""; width: 12px; height: 2px; border-radius: 1px; background: rgb(var(--input)); }
.StepperItem[data-state~="disabled"] .StepperLabel { text-decoration: line-through; text-decoration-color: rgb(var(--muted-foreground)); }

/* Compact, horizontal: one row, marks only. For a list row that has room for
   the shape of a run but not its step names. The labels stay in the DOM for a
   screen reader and leave the layout. Give the row a fixed lead column (the
   run key) so the marks line up from row to row. */
.Stepper[data-orientation="horizontal"] { flex-direction: row; align-items: center; flex: 1 1 auto; inline-size: 100%; min-inline-size: 0; }
.Stepper[data-orientation="horizontal"] .StepperItem { display: flex; flex: 1 1 0; min-width: 20px; padding-bottom: 0; }
.Stepper[data-orientation="horizontal"] .StepperItem:last-child { flex: none; }
.Stepper[data-orientation="horizontal"] .StepperItem:not(:last-child)::before {
  top: 9.5px; bottom: auto; inset-inline-start: 22px; inset-inline-end: 2px;
  border-inline-start: none; border-top: 1px solid rgb(var(--jim-border-strong));
}
.Stepper[data-orientation="horizontal"] .StepperItem:is([data-state~="checked"], [data-state~="disabled"]):not(:last-child)::before {
  top: 9px; inset-inline-start: 22px; border-inline-start: none; border-top: 2px solid rgb(var(--muted-foreground));
}
.Stepper[data-orientation="horizontal"] .StepperBody { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* =============================================================================
   OVERLAY — overlay root. Eight hooks, no visual parts. It positions every
   overlay above: useOverlay, useOverlayPosition, useOverlayTrigger,
   usePreventScroll, and their .web variants.
   OverlayAnimatePresence is re-exported by actionsheet, alert-dialog, modal,
   popover, toast and tooltip.
   ============================================================================= */
.OverlayAnimatePresence { display: contents; }

/* =============================================================================
   CLI-ONLY PRIMITIVES.
   59 CLI components, 29 of which have no creator/ directory because they are
   layout or RN passthroughs rather than headless components. Jim styles the
   ones that carry visual weight.
   ============================================================================= */
.Card { padding: var(--space-lg); background: rgb(var(--card)); border: 1px solid rgb(var(--border)); border-radius: var(--radius-md); }
.Badge { display: inline-flex; align-items: center; gap: var(--space-xs); padding: 2px var(--space-sm); border-radius: var(--radius-pill); font-family: var(--font-mono); font-size: var(--fs-caption); line-height: 1.5; background: rgb(var(--secondary)); color: rgb(var(--secondary-foreground)); border: 1px solid rgb(var(--border)); }
/* Badge is v2's wf-chip. Its tinted variant is quoted exactly:
     .wf-chip-info  background: var(--blue-50); color: var(--blue-700);
                    border-color: transparent;
   The border collapses to transparent rather than picking up the hue, which
   keeps the chip's box metrics identical to the neutral chip while letting the
   tint carry the whole signal. v2's other tinted pill, .wf-status-success,
   declares no border at all — same result, same reasoning. */
.Badge[data-action="success"] { background: rgb(var(--jim-success-tint)); color: rgb(var(--jim-success-text)); border-color: transparent; }
.Badge[data-action="warning"] { background: rgb(var(--jim-warn-tint)); color: rgb(var(--jim-warn-text)); border-color: transparent; }
.Badge[data-action="error"] { background: rgb(var(--jim-destructive-tint)); color: rgb(var(--jim-destructive-text)); border-color: transparent; }
.Badge[data-action="accent"] { background: rgb(var(--jim-primary-tint)); color: rgb(var(--jim-primary-on-tint)); border-color: transparent; }
.Divider { height: 1px; width: 100%; background: rgb(var(--border)); border: none; margin: 0; }
.Divider[data-orientation="vertical"] { width: 1px; height: auto; align-self: stretch; }
.Heading { font-family: var(--font-display); font-weight: var(--fw-semibold); color: rgb(var(--foreground)); margin: 0; letter-spacing: var(--ls-display-sm); }
.Text { font-family: var(--font-body); font-size: var(--fs-body-md); line-height: var(--lh-body-md); color: rgb(var(--jim-fg-1)); margin: 0; }
.Spinner { width: 20px; height: 20px; border-radius: var(--radius-pill); border: 2px solid rgb(var(--jim-surface-3)); border-top-color: rgb(var(--primary)); animation: gs-spin 700ms linear infinite; }
.Skeleton { display: block; height: 14px; border-radius: var(--radius-xs); background: rgb(var(--secondary)); animation: gs-pulse 1.6s var(--ease-standard) infinite; }
@keyframes gs-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
.Table { width: 100%; border-collapse: collapse; font-size: var(--fs-body-sm); }
.Table th { padding: var(--space-sm) var(--space-md); text-align: left; background: rgb(var(--secondary)); color: rgb(var(--secondary-foreground)); font-family: var(--font-mono); font-size: var(--fs-caption); letter-spacing: 0.07em; text-transform: uppercase; font-weight: var(--fw-medium); }
.Table td { padding: var(--space-sm) var(--space-md); border-top: 1px solid rgb(var(--jim-border-faint)); color: rgb(var(--jim-fg-2)); }
.HStack { display: flex; flex-direction: row; align-items: center; }
.VStack { display: flex; flex-direction: column; }
.Box { display: block; }
.Center { display: grid; place-items: center; }
.Grid { display: grid; }
.LiquidGlass { background: rgb(var(--card) / 0.72); backdrop-filter: blur(12px); border: 1px solid rgb(var(--border)); border-radius: var(--radius-md); padding: var(--space-lg); }
.StatusBar { display: flex; align-items: center; justify-content: space-between; height: 24px; padding: 0 var(--space-lg); font-family: var(--font-mono); font-size: 10px; color: rgb(var(--muted-foreground)); background: rgb(var(--card)); }
.RefreshControl { display: grid; place-items: center; padding: var(--space-md); }
.InputAccessoryView { display: flex; align-items: center; gap: var(--space-sm); padding: var(--space-sm) var(--space-md); background: rgb(var(--secondary)); border-top: 1px solid rgb(var(--border)); }
.ImageViewer { position: relative; background: rgb(0 0 0 / 0.9); border-radius: var(--radius-md); display: grid; place-items: center; padding: var(--space-lg); min-height: 160px; }
.ImageBackground { position: relative; border-radius: var(--radius-md); overflow: hidden; background: rgb(var(--secondary)); }

/* =============================================================================
   Utility for the specimen pages only.
   ============================================================================= */
.stack-sm > * + * { margin-top: var(--space-sm); }
.stack-md > * + * { margin-top: var(--space-md); }
.stack-lg > * + * { margin-top: var(--space-lg); }
.w-full { width: 100%; }
.muted-note { font-family: var(--font-mono); font-size: var(--fs-caption); color: rgb(var(--muted-foreground)); }
