/* ──────────────────────────────────────────────
   Legacy Color Token Bridge
   Maps old --color-* vars to AI CodeOps --cos-* design system
   so existing public pages render correctly in the dark theme.
   ────────────────────────────────────────────── */

:root {
  /* ── Background ── */
  --color-bg: var(--cos-bg-base, #0a0a0c);
  --color-bg-surface: var(--cos-glass-bg, rgba(27, 27, 27, 0.72));
  --color-bg-elevated: var(--cos-bg-subtle-hover, rgba(255, 255, 255, 0.06));

  /* ── Text ── */
  --color-text: var(--cos-text-primary, #f4f4f5);
  --color-text-secondary: var(--cos-text-secondary, #a1a1aa);
  --color-text-muted: var(--cos-text-secondary, #a1a1aa);
  --color-text-weak: var(--cos-text-tertiary, #8b8b93);
  --color-text-disabled: var(--cos-text-tertiary, #8b8b93);
  --color-text-strong: var(--cos-text-primary, #f4f4f5);

  /* ── Accent ── */
  --color-accent: var(--cos-accent-400, #818cf8);
  --color-accent-hover: var(--cos-accent-500, #6366f1);
  --color-accent-active: var(--cos-accent-600);
  --color-accent-alpha: rgb(var(--cos-accent-rgb) / 0.15);

  /* ── Status ── */
  --color-success: #32c878;
  --color-warning: var(--cos-warning, #f59e0b);
  --color-danger: #ff6060;

  /* ── Borders ── */
  --color-border: var(--cos-border, rgba(255, 255, 255, 0.06));
  --color-border-muted: var(--cos-border, rgba(255, 255, 255, 0.06));

  /* ── Buttons ── */
  /* Primary actions are a light button with dark text, as in OpenCode; the
     soft-blue accent is kept for focus, links and the active item. */
  --color-primary: #ececec;
  --color-primary-hover: #ffffff;
  --color-primary-active: #d4d4d4;
  --color-primary-text: #161616;
  --color-primary-alpha-20: rgb(var(--cos-accent-rgb) / 0.2);

  --color-danger-hover: #e04545;
  --color-danger-active: #cc3333;
  --color-danger-text: #ffffff;

  --color-warning-hover: #d97706;
  --color-warning-active: #b45309;
  --color-warning-text: #000000;

  /* ── Surfaces ── */
  --color-surface: var(--cos-glass-bg, rgba(27, 27, 27, 0.72));
  --color-surface-hover: var(--cos-bg-subtle-hover, rgba(255, 255, 255, 0.06));
  --color-surface-border: var(--cos-border, rgba(255, 255, 255, 0.06));

  /* ── Legacy compat ── */
  --color-white: #ffffff;
  --color-black: #000000;
  --color-background: var(--cos-bg-base, #0a0a0c);
  --color-background-weak: var(--cos-bg-subtle, rgba(255, 255, 255, 0.03));
  --color-background-weak-hover: var(--cos-bg-subtle-hover, rgba(255, 255, 255, 0.06));
}
body {
  --font-size-2xs: 0.75rem;
  --font-size-xs: 0.75rem;
  --font-size-sm: 0.8125rem;
  --font-size-md: 0.9375rem;
  --font-size-lg: 1.125rem;
  --font-size-xl: 1.25rem;
  --font-size-2xl: 1.5rem;
  --font-size-3xl: 1.875rem;
  --font-size-4xl: 2.25rem;
  --font-size-5xl: 3rem;
  --font-size-6xl: 3.75rem;
  --font-size-7xl: 4.5rem;
  --font-size-8xl: 6rem;
  --font-size-9xl: 8rem;

  --font-mono: var(--cos-font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
  /* Was var(--font-mono): every component on this token (buttons, dropdowns,
     the workspace picker, the key/member/model/provider/usage sections)
     rendered in monospace instead of the console's sans. */
  --font-sans: var(--cos-font-sans, Inter, -apple-system, "Segoe UI", sans-serif);
}
body {
  --space-0: 0;
  --space-px: 1px;
  --space-0-5: 0.125rem;
  --space-0-75: 0.1875rem;
  --space-1: 0.25rem;
  --space-1-5: 0.375rem;
  --space-2: 0.5rem;
  --space-2-5: 0.625rem;
  --space-3: 0.75rem;
  --space-3-5: 0.875rem;
  --space-4: 1rem;
  --space-4-5: 1.125rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-7: 1.75rem;
  --space-8: 2rem;
  --space-9: 2.25rem;
  --space-10: 2.5rem;
  --space-11: 2.75rem;
  --space-12: 3rem;
  --space-14: 3.5rem;
  --space-16: 4rem;
  --space-17: 4.25rem;
  --space-18: 4.5rem;
  --space-19: 4.75rem;
  --space-20: 5rem;
  --space-24: 6rem;
  --space-28: 7rem;
  --space-32: 8rem;
  --space-36: 9rem;
  --space-40: 10rem;
  --space-44: 11rem;
  --space-48: 12rem;
  --space-52: 13rem;
  --space-56: 14rem;
  --space-60: 15rem;
  --space-64: 16rem;
  --space-72: 18rem;
  --space-80: 20rem;
  --space-96: 24rem;

  --border-radius-sm: 0.1875rem;
  --border-radius-md: 0.3125rem;
  --border-radius-lg: 0.5rem;
}

[data-component="button"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  border: 1px solid transparent;
  border-radius: var(--cos-radius-md, 10px);
  font-family: var(--font-sans);
  font-size: var(--font-size-md);
  font-weight: 500;
  line-height: 1.25;
  cursor: pointer;
  transition: all 0.2s ease-in-out;
  text-decoration: none;
  user-select: none;

  &:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }

  &:focus {
    outline: none;
    box-shadow: 0 0 0 2px var(--color-primary);
  }

  &[data-color="primary"] {
    background-color: var(--color-primary);
    color: var(--color-primary-text);
    border-color: var(--color-primary);

    &:hover:not(:disabled) {
      background-color: var(--color-primary-hover);
      border-color: var(--color-primary-hover);
    }

    &:active:not(:disabled) {
      background-color: var(--color-primary-active);
      border-color: var(--color-primary-active);
    }
  }

  &[data-color="ghost"] {
    background-color: transparent;
    color: var(--cos-text-secondary);
    border-color: var(--cos-border-hover);

    &:hover:not(:disabled) {
      color: var(--cos-text-primary);
      border-color: var(--cos-border-strong);
      background-color: var(--cos-bg-subtle-hover);
    }
  }

  &[data-color="danger"] {
    background-color: var(--color-danger);
    color: var(--color-danger-text);
    border-color: var(--color-danger);

    &:hover:not(:disabled) {
      background-color: var(--color-danger-hover);
      border-color: var(--color-danger-hover);
    }

    &:active:not(:disabled) {
      background-color: var(--color-danger-active);
      border-color: var(--color-danger-active);
    }

    &:focus {
      box-shadow: 0 0 0 2px var(--color-danger);
    }
  }

  &[data-color="warning"] {
    background-color: var(--color-warning);
    color: var(--color-warning-text);
    border-color: var(--color-warning);

    &:hover:not(:disabled) {
      background-color: var(--color-warning-hover);
      border-color: var(--color-warning-hover);
    }

    &:active:not(:disabled) {
      background-color: var(--color-warning-active);
      border-color: var(--color-warning-active);
    }

    &:focus {
      box-shadow: 0 0 0 2px var(--color-warning);
    }
  }

  &[data-size="small"] {
    padding: var(--space-2) var(--space-3);
    font-size: var(--font-size-sm);
    gap: var(--space-1-5);
  }

  &[data-size="large"] {
    padding: var(--space-4) var(--space-6);
    font-size: var(--font-size-lg);
    gap: var(--space-3);
  }

  [data-slot="icon"] {
    display: flex;
    align-items: center;
    width: 1em;
    height: 1em;
  }
}

/* 1. Use a more-intuitive box-sizing model */
*,
*::before,
*::after {
  box-sizing: border-box;
}

/* 2. Remove default margin */
* {
  margin: 0;
}

/* 3. Enable keyword animations */
@media (prefers-reduced-motion: no-preference) {
  html {
    interpolate-size: allow-keywords;
  }
}

body {
  /* 4. Add accessible line-height */
  line-height: 1.5;
  /* 5. Improve text rendering */
  -webkit-font-smoothing: antialiased;
}

/* 6. Improve media defaults */
img,
picture,
video,
canvas,
svg {
  display: block;
  max-width: 100%;
}

/* 7. Inherit fonts for form controls */
input,
button,
textarea,
select {
  font: inherit;
}

/* 8. Avoid text overflows */
p,
h1,
h2,
h3,
h4,
h5,
h6 {
  overflow-wrap: break-word;
}

/* 9. Improve line wrapping */
p {
  text-wrap: pretty;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  text-wrap: balance;
}

/*
  10. Create a root stacking context.
  The app mounts into `#app` (see entry-server.tsx) — the `#root` / `#__next`
  ids this rule shipped with are React-template leftovers that never match.
*/
#app {
  isolation: isolate;
}
html {
  line-height: 1;
  background-color: var(--cos-bg-base, #0a0a0c);
  color: var(--cos-text-primary, #f4f4f5);
}

body {
  font-family: var(--cos-font-sans, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif);
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

/* AI CodeOps Design System */
/* ═══════════════════════════════════════════════════════════════════
   AI CodeOps Design System — Design Tokens
   ═══════════════════════════════════════════════════════════════════
   Neutral greys · white text · one soft-blue accent · Inter / IBM Plex Mono

   Modelled on the OpenCode desktop app (sampled 2026-10-05): page #161616,
   chips #242424, borders #2e2e2e, text #fafafa / #808080, a grey send button,
   and almost no colour: a soft blue (#a2bcff) for paths and links, green/red
   for diffs. The previous warm/orange pass was "too much orange, bad for the
   eyes". Tints go through --cos-accent-rgb (now neutral white), so emphasis
   is a lighter grey, not a hue. Colour is kept for meaning: status, diffs,
   SDLC stages. */

/* Inter (sans, variable) for the UI and IBM Plex Mono for code, as in the
   OpenCode app: prose is sans, only code and identifiers are monospace.

   The stylesheet is requested from `<link>`s in entry-server.tsx, not with an
   `@import` here. A CSS `@import` cannot start until this file has itself been
   fetched and parsed, so the font CSS, and then the font files, land three
   serialized round trips deep — the whole app renders in the fallback stack and
   reflows when Inter finally arrives. The `<link>`s sit in the initial HTML
   with a `preconnect`, so the request starts during document parse. */

:root {
  /* ── Background Scale (neutral grey, as OpenCode) ── */
  --cos-bg-base: #161616;
  --cos-bg-raised: #1b1b1b;
  --cos-bg-surface: #212121;
  --cos-bg-overlay: #282828;
  --cos-bg-elevated: #2e2e2e;
  --cos-bg-subtle: rgba(255, 255, 255, 0.03);
  --cos-bg-subtle-hover: rgba(255, 255, 255, 0.06);

  /* ── Glass System ── */
  --cos-glass-bg: rgba(27, 27, 27, 0.78);
  --cos-glass-bg-dense: rgba(22, 22, 22, 0.92);
  --cos-glass-blur: 20px;
  --cos-glass-border: rgba(255, 255, 255, 0.08);
  --cos-glass-border-hover: rgba(255, 255, 255, 0.14);
  --cos-glass-shine: linear-gradient(135deg, rgba(255, 255, 255, 0.06) 0%, rgba(255, 255, 255, 0) 60%);

  /* ── Accent ──
     Text tiers 400/300 are OpenCode's soft blue (links, paths, active item:
     9.6 / 11.6 on the base). Fills 500-700 are neutral greys like its send
     button (white text 10.9:1). Every tint goes through --cos-accent-rgb,
     which is neutral white: emphasis is a lighter grey, not a colour. */
  --cos-accent-rgb: 255 255 255;
  --cos-accent-2-rgb: 255 255 255;
  --cos-accent-50: #f5f8ff;
  --cos-accent-100: #e6edff;
  --cos-accent-200: #cbd8ff;
  --cos-accent-300: #bccfff;
  --cos-accent-400: #a2bcff;
  --cos-accent-500: #3d3d3d;
  --cos-accent-600: #333333;
  --cos-accent-700: #2a2a2a;

  --cos-accent-primary: var(--cos-accent-500);
  --cos-accent-hover: var(--cos-accent-400);
  --cos-accent-active: var(--cos-accent-600);
  --cos-accent-gradient: linear-gradient(180deg, #454545, #383838);
  --cos-accent-gradient-vivid: linear-gradient(180deg, #4a4a4a, #383838);
  --cos-accent-glow: rgb(162 188 255 / 0.18);
  --cos-accent-glow-strong: rgb(162 188 255 / 0.3);

  /* Violet — a categorical hue now (merged PRs, the release stage), no longer
     the second brand colour. */
  --cos-violet-rgb: 139 92 246;
  --cos-violet-400: #a78bfa;
  --cos-violet-500: #8b5cf6;
  /* White on violet-500 is 4.23:1 — under the 4.5 AA floor for body-sized text,
     which is what the release-gate action button renders at. This is the
     darkest step that clears it (5.72:1). */
  --cos-violet-600: #7c3aed;

  /* ── Semantic Colors ── */
  --cos-success: #22c55e;
  --cos-success-bg: rgba(34, 197, 94, 0.1);
  --cos-success-border: rgba(34, 197, 94, 0.2);

  --cos-warning: #f59e0b;
  --cos-warning-bg: rgba(245, 158, 11, 0.1);
  --cos-warning-border: rgba(245, 158, 11, 0.2);

  --cos-danger: #ef4444;
  --cos-danger-bg: rgba(239, 68, 68, 0.1);
  --cos-danger-border: rgba(239, 68, 68, 0.2);

  --cos-info: #3b82f6;
  --cos-info-bg: rgba(59, 130, 246, 0.1);
  --cos-info-border: rgba(59, 130, 246, 0.2);

  /* Bright semantic variants — for small text/icons on near-black, where the
     base success/warning/danger above read too dim. (Tailwind *-400 shades.) */
  --cos-emerald-400: #34d399;
  --cos-amber-400: #fbbf24;
  --cos-rose-400: #fb7185;

  /* ── Text Scale (neutral zinc; brighter than the old blue-grays for
        dark-mode readability — light text reads optically thinner, so the
        secondary/tertiary tiers are bumped up a step) ── */
  --cos-text-primary: #fafafa;
  --cos-text-soft: #e2e2e2; /* brighter body copy / values */
  --cos-text-secondary: #bdbdbd;
  --cos-text-tertiary: #a6a6a6;
  /* Faint meta / captions. Raised in the 2026-10 readability pass (with
     secondary and tertiary): metadata read as too dim at small sizes. Now
     base 6.35, raised 6.05, surface 5.65 — and tertiary clears AA on every
     surface (5.58 on elevated). The rule that faint stays off
     --cos-bg-overlay / --cos-bg-elevated is kept so the tiers keep their
     order; test/contrast.test.ts enforces it. */
  --cos-text-faint: #999999;
  --cos-text-disabled: #5a5a5a;
  --cos-text-inverse: #161616;
  --cos-text-accent: var(--cos-accent-400);
  --cos-text-link: var(--cos-accent-400);
  --cos-text-link-hover: var(--cos-accent-300);

  /* ── Border ── */
  --cos-border: rgba(255, 255, 255, 0.08);
  --cos-border-hover: rgba(255, 255, 255, 0.14);
  --cos-border-focus: rgb(162 188 255 / 0.6);
  --cos-border-strong: rgba(255, 255, 255, 0.22);

  /* ── Typography ── */
  --cos-font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --cos-font-mono: "IBM Plex Mono", "JetBrains Mono", "Cascadia Code", ui-monospace, monospace;
  /* Headings are sans, as in the OpenCode app (its website is all-mono, the
     app is not). Kept as a token so headings can change in one place. */
  --cos-font-heading: var(--cos-font-sans);

  --cos-text-xs: 0.75rem; /* 12px */
  --cos-text-sm: 0.8125rem; /* 13px */
  --cos-text-base: 0.875rem; /* 14px */
  --cos-text-md: 0.9375rem; /* 15px */
  --cos-text-lg: 1rem; /* 16px */
  --cos-text-xl: 1.125rem; /* 18px */
  --cos-text-2xl: 1.375rem; /* 22px */
  --cos-text-3xl: 1.75rem; /* 28px */
  --cos-text-4xl: 2.25rem; /* 36px */

  --cos-leading-tight: 1.2;
  --cos-leading-normal: 1.5;
  --cos-leading-relaxed: 1.7;

  /* ── Spacing ── */
  --cos-space-1: 0.25rem; /* 4px */
  --cos-space-2: 0.5rem; /* 8px */
  --cos-space-3: 0.75rem; /* 12px */
  --cos-space-4: 1rem; /* 16px */
  --cos-space-5: 1.25rem; /* 20px */
  --cos-space-6: 1.5rem; /* 24px */
  --cos-space-8: 2rem; /* 32px */
  --cos-space-10: 2.5rem; /* 40px */
  --cos-space-12: 3rem; /* 48px */
  --cos-space-16: 4rem; /* 64px */

  /* ── Radii ── */
  --cos-radius-xs: 4px;
  --cos-radius-sm: 6px;
  --cos-radius-md: 10px;
  --cos-radius-lg: 14px;
  --cos-radius-xl: 18px;
  --cos-radius-2xl: 24px;
  --cos-radius-full: 9999px;

  /* ── Shadows ── */
  --cos-shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.3);
  --cos-shadow-sm: 0 2px 6px rgba(0, 0, 0, 0.35);
  --cos-shadow-md: 0 4px 16px rgba(0, 0, 0, 0.4);
  --cos-shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.45);
  --cos-shadow-xl: 0 16px 48px rgba(0, 0, 0, 0.5);
  --cos-shadow-glow: 0 0 20px var(--cos-accent-glow);
  --cos-shadow-glow-strong: 0 0 40px var(--cos-accent-glow-strong);

  /* ── Transitions ── */
  --cos-ease-default: cubic-bezier(0.4, 0, 0.2, 1);
  --cos-ease-in: cubic-bezier(0.4, 0, 1, 1);
  --cos-ease-out: cubic-bezier(0, 0, 0.2, 1);
  --cos-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);

  --cos-duration-fast: 120ms;
  --cos-duration-normal: 200ms;
  --cos-duration-slow: 350ms;
  --cos-duration-slower: 500ms;

  /* ── Z-Index Scale ──
     The app chrome sits BELOW the interactive layers: a dropdown opened inside
     the sidebar has to paint over the sidebar, and a tooltip has to clear the
     toast stack it may be triggered next to. */
  --cos-z-base: 0;
  --cos-z-header: 30;
  --cos-z-sidebar: 40;
  --cos-z-dropdown: 100;
  --cos-z-sticky: 200;
  --cos-z-overlay: 300;
  --cos-z-modal: 400;
  --cos-z-toast: 500;
  --cos-z-tooltip: 600;

  /* ── Sidebar ── */
  --cos-sidebar-width: 260px;
  --cos-sidebar-collapsed: 64px;

  /* ── Compatibility aliases ──
     Names that pages already reference. They were previously undefined, so the
     declarations using them were invalid at computed-value time and silently
     dropped (borderless tables on /status + /trust, square corners and
     full-strength "muted" text on the landing page, missing input surfaces on
     the release gate). Defined as aliases, not new literals, so each colour
     still has exactly one source of truth. `test/design-tokens.test.ts` fails
     the build if a new `--cos-*` reference goes undefined again. */
  --cos-accent: var(--cos-accent-primary);
  --cos-accent-secondary: var(--cos-accent-400);

  --cos-surface-1: var(--cos-bg-raised);
  --cos-surface-2: var(--cos-bg-surface);
  --cos-bg-surface-hover: #2a2a2a;

  --cos-text-muted: var(--cos-text-tertiary);
  --cos-text-dimmed: var(--cos-text-faint);

  --cos-emerald-500: #10b981;
  --cos-cyan-400: #22d3ee;
  --cos-violet-300: #c4b5fd;
  /* Tailwind-style names used by the public status/trust pages — mapped onto
     the existing bright semantic tier instead of adding near-duplicate hexes. */
  --cos-green-400: var(--cos-emerald-400);
  --cos-yellow-400: var(--cos-amber-400);
  --cos-red-400: var(--cos-rose-400);
  /* Bare hue names. Status and severity badges across the workspace pages build
     `var(--cos-${hue}, #818cf8)` from helpers that return "rose", "amber", …
     Nothing defined those names, so every badge fell back to the indigo default
     and a critical incident looked like a running one.
     test/css-hue-tokens.test.ts keeps helpers and tokens in step. */
  --cos-amber: var(--cos-amber-400);
  --cos-cyan: var(--cos-cyan-400);
  --cos-emerald: var(--cos-emerald-400);
  /* Status helpers use it for "running". */
  --cos-indigo: #8b9cf9;
  --cos-rose: var(--cos-rose-400);
  --cos-violet: var(--cos-violet-400);
  /* Decorative neutral — inactive status dots, the free-plan gradient. This is
     the value --cos-text-faint used to have; it is fine as a FILL but fails AA
     as text at any size the console uses, which is why the text tier moved off
     it. Not for `color`; test/retired-palette.test.ts enforces that. */
  --cos-gray-500: #787878;
  --cos-gray-600: #555555;
  --cos-gray-800: #2a2a2a;

  --cos-radius: var(--cos-radius-md);
  --cos-glow: var(--cos-accent-glow);
}
/* ═══════════════════════════════════════════════════════════════════
   AI CodeOps — Micro-Animations Library
   ═══════════════════════════════════════════════════════════════════ */

/* ── Entrance Animations ── */

@keyframes cos-fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes cos-fade-in-up {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes cos-fade-in-down {
  from {
    opacity: 0;
    transform: translateY(-12px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes cos-fade-in-left {
  from {
    opacity: 0;
    transform: translateX(-16px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

@keyframes cos-fade-in-right {
  from {
    opacity: 0;
    transform: translateX(16px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

@keyframes cos-scale-in {
  from {
    opacity: 0;
    transform: scale(0.92);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

@keyframes cos-glass-reveal {
  from {
    opacity: 0;
    transform: translateY(8px) scale(0.98);
    backdrop-filter: blur(0px);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
    backdrop-filter: blur(var(--cos-glass-blur));
  }
}

/* ── Loading Animations ── */

@keyframes cos-shimmer {
  0% {
    background-position: -200% 0;
  }
  100% {
    background-position: 200% 0;
  }
}

@keyframes cos-pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
}

@keyframes cos-pulse-glow {
  0%,
  100% {
    box-shadow: 0 0 0 0 var(--cos-accent-glow);
  }
  50% {
    box-shadow: 0 0 16px 4px var(--cos-accent-glow);
  }
}

@keyframes cos-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

@keyframes cos-bounce {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-6px);
  }
}

/* ── Status Dot ── */

@keyframes cos-status-pulse {
  0%,
  100% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(1.6);
    opacity: 0;
  }
}

/* ── Progress ── */

@keyframes cos-indeterminate {
  0% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(300%);
  }
}

/* ── Gradient Shift (for accent borders/backgrounds) ── */

@keyframes cos-gradient-shift {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}

/* ── Utility Classes ── */

.cos-animate-fade-in {
  animation: cos-fade-in var(--cos-duration-normal) var(--cos-ease-out) both;
}

.cos-animate-fade-in-up {
  animation: cos-fade-in-up var(--cos-duration-slow) var(--cos-ease-out) both;
}

.cos-animate-scale-in {
  animation: cos-scale-in var(--cos-duration-slow) var(--cos-ease-spring) both;
}

.cos-animate-glass-reveal {
  animation: cos-glass-reveal var(--cos-duration-slower) var(--cos-ease-out) both;
}

.cos-shimmer {
  background: linear-gradient(90deg, var(--cos-bg-subtle) 0%, rgba(255, 255, 255, 0.06) 50%, var(--cos-bg-subtle) 100%);
  background-size: 200% 100%;
  animation: cos-shimmer 1.5s var(--cos-ease-default) infinite;
}

.cos-pulse {
  animation: cos-pulse 2s var(--cos-ease-default) infinite;
}

.cos-spin {
  animation: cos-spin 1s linear infinite;
}

/* ── Staggered Children ── */

.cos-stagger > * {
  animation: cos-fade-in-up var(--cos-duration-slow) var(--cos-ease-out) both;
}

.cos-stagger > *:nth-child(1) {
  animation-delay: 0ms;
}
.cos-stagger > *:nth-child(2) {
  animation-delay: 50ms;
}
.cos-stagger > *:nth-child(3) {
  animation-delay: 100ms;
}
.cos-stagger > *:nth-child(4) {
  animation-delay: 150ms;
}
.cos-stagger > *:nth-child(5) {
  animation-delay: 200ms;
}
.cos-stagger > *:nth-child(6) {
  animation-delay: 250ms;
}
.cos-stagger > *:nth-child(7) {
  animation-delay: 300ms;
}
.cos-stagger > *:nth-child(8) {
  animation-delay: 350ms;
}
.cos-stagger > *:nth-child(9) {
  animation-delay: 400ms;
}
.cos-stagger > *:nth-child(10) {
  animation-delay: 450ms;
}

/* ── Hover Lift (reusable) ── */

.cos-hover-lift {
  transition:
    transform var(--cos-duration-normal) var(--cos-ease-out),
    box-shadow var(--cos-duration-normal) var(--cos-ease-out);
}

.cos-hover-lift:hover {
  transform: translateY(-2px);
  box-shadow: var(--cos-shadow-md);
}

/* ── Hover Glow (reusable) ── */

.cos-hover-glow {
  transition: box-shadow var(--cos-duration-normal) var(--cos-ease-out);
}

.cos-hover-glow:hover {
  box-shadow: var(--cos-shadow-glow);
}

/* ── Reduced motion (WCAG 2.3.3) ──
   Honour the OS "reduce motion" setting: collapse animations/transitions to a
   near-instant tick so motion-sensitive users don't get shimmer/scale/spin. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
/* ═══════════════════════════════════════════════════════════════════
   AI CodeOps — Base Component Styles
   ═══════════════════════════════════════════════════════════════════
   Composable building blocks using design tokens.
   Apply via data-component, data-color, and data-variant attributes.
   ═══════════════════════════════════════════════════════════════════ */

/* ── Reset & Base ── */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  /* Root size bump (16→17px ≈ +6%). The app sizes text in rem — inline 0.78rem
     labels, 0.85rem inputs, used 100s of times — which rendered at 12–14px, too
     small to read comfortably. Scaling the root is the one lever that enlarges
     ALL of it (token- AND inline-sized) without touching every element. 17.5px
     read a touch large / less dense; 17px keeps the readability win + density. */
  font-size: 17px;
}

body {
  font-family: var(--cos-font-sans);
  /* 440 (uses the Inter variable font — see design-tokens.css): a hair heavier
     than 400 so small text reads crisp on the dark base instead of thin/wispy. */
  font-weight: 440;
  font-size: var(--cos-text-base);
  line-height: var(--cos-leading-normal);
  color: var(--cos-text-primary);
  background: var(--cos-bg-base);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Dark-mode type polish (2026 dev-platform convention): light text reads
     optically thinner on a dark base, so a touch of positive tracking on body
     copy keeps it crisp + legible; optimizeLegibility turns on kerning/ligatures
     for Inter. */
  letter-spacing: 0.01em;
  text-rendering: optimizeLegibility;
}

/* Headings: Inter looks sharper / more "product-grade" with slightly NEGATIVE
   tracking at display sizes (the Linear/Vercel look) — counters the body's
   positive tracking. Applies to inline-styled headings too (they don't set
   letter-spacing). */
h1,
h2,
h3 {
  letter-spacing: -0.013em;
}

/* Keyboard focus ring for ALL interactive elements. Many buttons/links across
   the app are inline-styled (not the cos-btn/cos-input components), so without
   this they'd have NO visible focus state — a real keyboard-navigation gap for a
   developer tool. `:focus-visible` shows the ring only for keyboard focus, never
   on mouse click, so it doesn't add visual noise for pointer users. */
a:focus-visible,
button:focus-visible,
[role="button"]:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--cos-accent-400, #818cf8);
  outline-offset: 2px;
  border-radius: var(--cos-radius-sm, 6px);
}

/* ── Glass Card ── */

[data-component="cos-card"] {
  background: var(--cos-glass-bg);
  backdrop-filter: blur(var(--cos-glass-blur));
  -webkit-backdrop-filter: blur(var(--cos-glass-blur));
  border: 1px solid var(--cos-glass-border);
  border-radius: var(--cos-radius-lg);
  padding: var(--cos-space-6);
  position: relative;
  overflow: hidden;
  transition:
    border-color var(--cos-duration-normal) var(--cos-ease-default),
    box-shadow var(--cos-duration-normal) var(--cos-ease-default);
}

[data-component="cos-card"]::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--cos-glass-shine);
  pointer-events: none;
  border-radius: inherit;
}

[data-component="cos-card"]:hover {
  border-color: var(--cos-glass-border-hover);
  box-shadow: var(--cos-shadow-sm);
}

[data-component="cos-card"][data-glow] {
  box-shadow: var(--cos-shadow-glow);
}

[data-component="cos-card"][data-glow]:hover {
  box-shadow: var(--cos-shadow-glow-strong);
}

/* ── Buttons ── */

[data-component="cos-btn"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--cos-space-2);
  padding: var(--cos-space-2) var(--cos-space-4);
  border: 1px solid transparent;
  border-radius: var(--cos-radius-md);
  font-family: var(--cos-font-sans);
  font-size: var(--cos-text-sm);
  font-weight: 500;
  line-height: 1;
  cursor: pointer;
  transition: all var(--cos-duration-fast) var(--cos-ease-default);
  white-space: nowrap;
  user-select: none;
  outline: none;
  min-height: 36px;
}

[data-component="cos-btn"]:focus-visible {
  outline: 2px solid var(--cos-accent-primary);
  outline-offset: 2px;
}

[data-component="cos-btn"]:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none !important;
  box-shadow: none !important;
}

/* Primary */
[data-component="cos-btn"][data-color="primary"] {
  background: var(--cos-accent-gradient);
  color: white;
  border: none;
  box-shadow: var(--cos-shadow-sm);
}

[data-component="cos-btn"][data-color="primary"]:hover:not(:disabled) {
  transform: translateY(-1px);
  box-shadow: 0 4px 20px var(--cos-accent-glow-strong);
  filter: brightness(1.08);
}

[data-component="cos-btn"][data-color="primary"]:active:not(:disabled) {
  transform: translateY(0);
}

/* Secondary */
[data-component="cos-btn"][data-color="secondary"] {
  background: var(--cos-bg-subtle);
  color: var(--cos-text-primary);
  border-color: var(--cos-border);
}

[data-component="cos-btn"][data-color="secondary"]:hover:not(:disabled) {
  background: var(--cos-bg-subtle-hover);
  border-color: var(--cos-border-hover);
}

/* Ghost */
[data-component="cos-btn"][data-color="ghost"] {
  background: transparent;
  color: var(--cos-text-secondary);
}

[data-component="cos-btn"][data-color="ghost"]:hover:not(:disabled) {
  background: var(--cos-bg-subtle);
  color: var(--cos-text-primary);
}

/* Danger */
[data-component="cos-btn"][data-color="danger"] {
  background: var(--cos-danger-bg);
  color: var(--cos-danger);
  border-color: var(--cos-danger-border);
}

[data-component="cos-btn"][data-color="danger"]:hover:not(:disabled) {
  background: rgba(239, 68, 68, 0.18);
  border-color: rgba(239, 68, 68, 0.35);
}

/* Success */
[data-component="cos-btn"][data-color="success"] {
  background: var(--cos-success-bg);
  color: var(--cos-success);
  border-color: var(--cos-success-border);
}

/* Icon-only button */
[data-component="cos-btn"][data-variant="icon"] {
  width: 36px;
  height: 36px;
  padding: 0;
  border-radius: var(--cos-radius-sm);
}

/* Small */
[data-component="cos-btn"][data-size="sm"] {
  padding: var(--cos-space-1) var(--cos-space-3);
  font-size: var(--cos-text-xs);
  min-height: 28px;
  border-radius: var(--cos-radius-sm);
}

/* Large */
[data-component="cos-btn"][data-size="lg"] {
  padding: var(--cos-space-3) var(--cos-space-6);
  font-size: var(--cos-text-md);
  min-height: 44px;
  border-radius: var(--cos-radius-lg);
}

/* ── Inputs ── */

[data-component="cos-input"] {
  width: 100%;
  padding: var(--cos-space-2) var(--cos-space-3);
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--cos-border);
  border-radius: var(--cos-radius-md);
  color: var(--cos-text-primary);
  font-family: var(--cos-font-sans);
  font-size: var(--cos-text-sm);
  outline: none;
  transition:
    border-color var(--cos-duration-fast) var(--cos-ease-default),
    box-shadow var(--cos-duration-fast) var(--cos-ease-default);
  min-height: 38px;
}

[data-component="cos-input"]::placeholder {
  color: var(--cos-text-tertiary);
}

[data-component="cos-input"]:hover {
  border-color: var(--cos-border-hover);
}

[data-component="cos-input"]:focus {
  border-color: var(--cos-border-focus);
  box-shadow: 0 0 0 3px rgb(var(--cos-accent-rgb) / 0.12);
}

[data-component="cos-input"][data-error] {
  border-color: var(--cos-danger-border);
}

[data-component="cos-input"][data-variant="mono"] {
  font-family: var(--cos-font-mono);
  font-size: var(--cos-text-xs);
}

/* Textarea */
textarea[data-component="cos-input"] {
  resize: vertical;
  min-height: 80px;
  line-height: var(--cos-leading-relaxed);
}

/* Select */
select[data-component="cos-input"] {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%239194b3' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 32px;
}

/* ── Badge ── */

[data-component="cos-badge"] {
  display: inline-flex;
  align-items: center;
  gap: var(--cos-space-1);
  padding: 2px 10px;
  border-radius: var(--cos-radius-full);
  font-size: var(--cos-text-xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

[data-component="cos-badge"][data-color="primary"] {
  background: rgb(var(--cos-accent-rgb) / 0.12);
  color: var(--cos-accent-400);
}

[data-component="cos-badge"][data-color="success"] {
  background: var(--cos-success-bg);
  color: var(--cos-success);
}

[data-component="cos-badge"][data-color="warning"] {
  background: var(--cos-warning-bg);
  color: var(--cos-warning);
}

[data-component="cos-badge"][data-color="danger"] {
  background: var(--cos-danger-bg);
  color: var(--cos-danger);
}

[data-component="cos-badge"][data-color="info"] {
  background: var(--cos-info-bg);
  color: var(--cos-info);
}

[data-component="cos-badge"][data-color="neutral"] {
  background: var(--cos-bg-subtle);
  color: var(--cos-text-secondary);
}

/* ── Status Dot ── */

[data-component="cos-status-dot"] {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
  position: relative;
}

[data-component="cos-status-dot"][data-status="online"],
[data-component="cos-status-dot"][data-status="active"] {
  background: var(--cos-success);
}

[data-component="cos-status-dot"][data-status="warning"],
[data-component="cos-status-dot"][data-status="testing"] {
  background: var(--cos-warning);
  animation: cos-pulse 2s var(--cos-ease-default) infinite;
}

[data-component="cos-status-dot"][data-status="offline"],
[data-component="cos-status-dot"][data-status="inactive"] {
  background: var(--cos-text-tertiary);
}

[data-component="cos-status-dot"][data-status="error"] {
  background: var(--cos-danger);
}

/* ── Section Header ── */

[data-component="cos-section-header"] {
  margin-bottom: var(--cos-space-6);
}

[data-component="cos-section-header"] h2 {
  font-size: var(--cos-text-xl);
  font-weight: 700;
  color: var(--cos-text-primary);
  margin-bottom: var(--cos-space-1);
}

[data-component="cos-section-header"] p {
  font-size: var(--cos-text-sm);
  color: var(--cos-text-secondary);
  line-height: var(--cos-leading-relaxed);
}

/* ── Avatar ── */

[data-component="cos-avatar"] {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--cos-text-sm);
  font-weight: 600;
  color: white;
  background: var(--cos-accent-gradient);
  flex-shrink: 0;
  overflow: hidden;
}

[data-component="cos-avatar"] img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

[data-component="cos-avatar"][data-size="sm"] {
  width: 28px;
  height: 28px;
  font-size: var(--cos-text-xs);
}

[data-component="cos-avatar"][data-size="lg"] {
  width: 48px;
  height: 48px;
  font-size: var(--cos-text-lg);
}

/* ── Divider ── */

[data-component="cos-divider"] {
  height: 1px;
  background: var(--cos-border);
  border: none;
  margin: var(--cos-space-6) 0;
}

/* ── Empty State ── */

[data-component="cos-empty"] {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--cos-space-12) var(--cos-space-6);
  text-align: center;
  color: var(--cos-text-secondary);
}

[data-component="cos-empty"] [data-slot="icon"] {
  font-size: 2rem;
  margin-bottom: var(--cos-space-4);
  opacity: 0.4;
}

[data-component="cos-empty"] [data-slot="title"] {
  font-size: var(--cos-text-md);
  font-weight: 600;
  color: var(--cos-text-primary);
  margin-bottom: var(--cos-space-2);
}

[data-component="cos-empty"] [data-slot="description"] {
  font-size: var(--cos-text-sm);
  max-width: 320px;
  margin-bottom: var(--cos-space-6);
}

/* ── Skeleton Loader ── */

[data-component="cos-skeleton"] {
  border-radius: var(--cos-radius-sm);
  background: linear-gradient(90deg, var(--cos-bg-subtle) 0%, rgba(255, 255, 255, 0.06) 50%, var(--cos-bg-subtle) 100%);
  background-size: 200% 100%;
  animation: cos-shimmer 1.5s var(--cos-ease-default) infinite;
}

[data-component="cos-skeleton"][data-variant="text"] {
  height: 14px;
  width: 100%;
}

[data-component="cos-skeleton"][data-variant="circle"] {
  width: 36px;
  height: 36px;
  border-radius: 50%;
}

[data-component="cos-skeleton"][data-variant="card"] {
  height: 120px;
  width: 100%;
  border-radius: var(--cos-radius-lg);
}

/* ── Toast / Notification ── */

[data-component="cos-toast"] {
  position: fixed;
  bottom: var(--cos-space-6);
  right: var(--cos-space-6);
  z-index: var(--cos-z-toast);
  background: var(--cos-glass-bg-dense);
  backdrop-filter: blur(var(--cos-glass-blur));
  border: 1px solid var(--cos-glass-border);
  border-radius: var(--cos-radius-lg);
  padding: var(--cos-space-3) var(--cos-space-5);
  box-shadow: var(--cos-shadow-lg);
  animation: cos-fade-in-up var(--cos-duration-slow) var(--cos-ease-spring) both;
  display: flex;
  align-items: center;
  gap: var(--cos-space-3);
  max-width: 400px;
  font-size: var(--cos-text-sm);
}

/* ── Table ── */

[data-component="cos-table"] {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--cos-text-sm);
}

[data-component="cos-table"] th {
  text-align: left;
  padding: var(--cos-space-3) var(--cos-space-4);
  font-weight: 600;
  color: var(--cos-text-secondary);
  font-size: var(--cos-text-xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  border-bottom: 1px solid var(--cos-border);
}

[data-component="cos-table"] td {
  padding: var(--cos-space-3) var(--cos-space-4);
  color: var(--cos-text-primary);
  border-bottom: 1px solid var(--cos-border);
}

[data-component="cos-table"] tbody tr {
  transition: background var(--cos-duration-fast) var(--cos-ease-default);
}

[data-component="cos-table"] tbody tr:hover {
  background: var(--cos-bg-subtle);
}

/* ── Progress Bar ── */

[data-component="cos-progress"] {
  height: 4px;
  background: var(--cos-bg-subtle);
  border-radius: var(--cos-radius-full);
  overflow: hidden;
}

[data-component="cos-progress"] [data-slot="fill"] {
  height: 100%;
  border-radius: var(--cos-radius-full);
  background: var(--cos-accent-gradient);
  transition: width var(--cos-duration-slower) var(--cos-ease-out);
}

[data-component="cos-progress"] [data-slot="fill"][data-warning] {
  background: linear-gradient(90deg, var(--cos-warning), var(--cos-danger));
}

/* ── Tooltip (CSS-only) ── */

[data-tooltip] {
  position: relative;
}

[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  padding: 4px 10px;
  background: var(--cos-bg-elevated);
  border: 1px solid var(--cos-border);
  border-radius: var(--cos-radius-sm);
  font-size: var(--cos-text-xs);
  color: var(--cos-text-primary);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition:
    opacity var(--cos-duration-fast) var(--cos-ease-default),
    transform var(--cos-duration-fast) var(--cos-ease-default);
  z-index: var(--cos-z-tooltip, 600);
}

[data-tooltip]:hover::after {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* ── Scrollbar ── */

::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: var(--cos-bg-elevated);
  border-radius: var(--cos-radius-full);
}

::-webkit-scrollbar-thumb:hover {
  background: var(--cos-text-tertiary);
}

/* ─── Empty-state action ──────────────────────────────────────────────────
 * An empty state that only DESCRIBES the way forward makes the reader go and
 * find it. This carries the action itself.
 *
 * Defined globally rather than per module ON PURPOSE: `.emptyPanel` is declared
 * independently in four separate CSS modules (dashboard, lifecycle, pipelines,
 * sessions), so a rule placed in any one of them styles only that page's
 * panels — which is exactly the trap this hit first time round.
 *
 * Named `empty-action`, not `action`, because routes/[...404].css already
 * styles a `[data-slot="action"]` of its own.
 *
 * Applies to both <button> and <A>, hence the explicit text-decoration reset,
 * and clears the 24px WCAG 2.5.8 target floor.
 */
[data-slot="empty-action"] {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 16px;
  min-height: 32px;
  padding: 6px 16px;
  border-radius: var(--cos-radius-md, 10px);
  border: 1px solid var(--cos-border-strong, rgba(255, 255, 255, 0.14));
  background: var(--cos-bg-raised, #141418);
  color: var(--cos-text-primary, #f4f4f5);
  font-size: 0.82rem;
  font-weight: 500;
  font-family: inherit;
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color 0.15s ease,
    border-color 0.15s ease;
}

[data-slot="empty-action"]:hover {
  background: var(--cos-bg-surface, #1a1a1f);
  border-color: var(--cos-accent-500, #6366f1);
}

[data-slot="empty-action"]:focus-visible {
  outline: 2px solid var(--cos-accent-400, #818cf8);
  outline-offset: 2px;
}
