/*
 * Executor's design tokens, as Tailwind theme SOURCE.
 *
 * Split out of `globals.css` because this file has two consumers:
 *
 *  1. The shell's own build, which `@import`s it and compiles it ahead of time.
 *  2. The sandboxed inner frame, which embeds it VERBATIM in a
 *     `<style type="text/tailwindcss">` so the in-frame Tailwind compiler can
 *     generate whatever utilities the model's code actually uses, against these
 *     tokens. Without the theme source there, `text-muted-foreground` compiles
 *     to nothing and `md:grid-cols-4` never exists — see `buildRendererSrcDoc`.
 *
 * It therefore contains ONLY tokens and variants: no `@font-face` (whose
 * `url()` must be build-resolved into a `data:` URL), no `@source`, and no
 * component CSS. Anything with a build-time dependency stays in `globals.css`.
 *
 * The semantic values are copied from `packages/react/src/styles/globals.css`
 * and pinned against it by `theme-tokens.pin.test.ts`.
 */

@custom-variant dark (&:is(.dark *));

@theme inline {
  /* Geist sets UI and prose; Geist Mono sets code, slugs, IDs, counts and
     section labels. The faces themselves are declared in `globals.css`, which
     is where the build can inline them. */
  --font-sans: "Geist", ui-sans-serif, system-ui, sans-serif;
  --font-mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --font-display: "Geist", ui-sans-serif, system-ui, sans-serif;

  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-card: var(--card);
  --color-card-foreground: var(--card-foreground);
  --color-primary: var(--primary);
  --color-primary-foreground: var(--primary-foreground);
  --color-secondary: var(--secondary);
  --color-secondary-foreground: var(--secondary-foreground);
  --color-muted: var(--muted);
  --color-muted-foreground: var(--muted-foreground);
  --color-accent: var(--accent);
  --color-accent-foreground: var(--accent-foreground);
  --color-destructive: var(--destructive);
  --color-popover: var(--popover);
  --color-popover-foreground: var(--popover-foreground);
  --color-border: var(--border);
  --color-input: var(--input);
  --color-ring: var(--ring);

  --color-chart-1: var(--chart-1);
  --color-chart-2: var(--chart-2);
  --color-chart-3: var(--chart-3);
  --color-chart-4: var(--chart-4);
  --color-chart-5: var(--chart-5);
  --color-chart-6: var(--chart-6);
  --color-chart-7: var(--chart-7);
  --color-chart-8: var(--chart-8);

  --color-positive: var(--positive);
  --color-caution: var(--caution);
  --color-negative: var(--negative);

  --radius-sm: calc(var(--radius) * 0.6);
  --radius-md: calc(var(--radius) * 0.8);
  --radius-lg: var(--radius);
  --radius-xl: calc(var(--radius) * 1.4);
}

/* Light theme.
   Grayscale, registry-grade minimal: white surfaces, a near-neutral gray ramp,
   hairline borders, and color held back to one role (destructive). Hierarchy
   comes from tone and borders, not hue. */
:root {
  color-scheme: light dark;
  --radius: 0.5rem;

  --background: #ffffff;
  --foreground: #111111;
  --card: #ffffff;
  --card-foreground: #111111;
  --popover: #ffffff;
  --popover-foreground: #111111;
  --primary: #0a0a0a;
  --primary-foreground: #ffffff;
  --secondary: #fafafa;
  --secondary-foreground: #0a0a0a;
  --muted: #fafafa;
  --muted-foreground: #666666;
  --accent: #f5f5f5;
  --accent-foreground: #0a0a0a;
  --destructive: #b4261a;
  --border: #eaeaea;
  --input: #d4d4d4;
  --ring: #888888;

  /* Data-visualization palette.

     The one place the system admits hue, because a chart with four grayscale
     series is unreadable. It is held to the same restraint as everything else:
     desaturated, mid-tone, no neon, and NOT a rainbow. Every entry is muted
     enough to sit under `foreground` text on a white card without pulling the
     eye off the numbers.

     Ordered. Slot 1 is the near-neutral slate a single-series chart gets, so
     the common case stays grayscale; hue only appears once a second series
     needs distinguishing. Color follows the entity, never its rank — slot 3 is
     "the third series in this chart", not "the third-biggest value". */
  --chart-1: #545454; /* slate — the default single series */
  --chart-2: #3d6ea8; /* muted blue */
  --chart-3: #9a6b3f; /* clay */
  --chart-4: #4a7f70; /* muted teal */
  --chart-5: #7b6099; /* muted violet */
  --chart-6: #a8654f; /* terracotta */
  --chart-7: #5b7a4a; /* moss */
  --chart-8: #8e5f78; /* mauve */

  /* Status. Reserved, never used as series colors: a chart that spends its
     palette on these loses the ability to say "this one is bad". Always paired
     with a word or an icon — never color alone. `negative` is `destructive`. */
  --positive: #2f7d52;
  --caution: #9a6b1f;
  --negative: #b4261a;
}

/* Dark theme.
   The gray ramp inverts: near-black surfaces, a white primary, hairlines at low
   contrast. Depth comes from a one-step-lighter surface, not a heavier shadow.
   The chart palette lightens rather than saturating — the same hues, raised to
   clear a near-black background. */
@media (prefers-color-scheme: dark) {
  :root {
    --background: #0a0a0a;
    --foreground: #ededed;
    --card: #0f0f0f;
    --card-foreground: #ededed;
    --popover: #141414;
    --popover-foreground: #ededed;
    --primary: #ffffff;
    --primary-foreground: #0a0a0a;
    --secondary: #141414;
    --secondary-foreground: #ededed;
    --muted: #141414;
    --muted-foreground: #9a9a9a;
    --accent: #1a1a1a;
    --accent-foreground: #ededed;
    --destructive: #e0726a;
    --border: #1f1f1f;
    --input: #333333;
    --ring: #777777;

    --chart-1: #a1a1a1;
    --chart-2: #7a9cc9;
    --chart-3: #c99a6b;
    --chart-4: #6fb0a0;
    --chart-5: #a892c6;
    --chart-6: #d1917b;
    --chart-7: #8dab78;
    --chart-8: #bd8fa8;

    --positive: #5cb185;
    --caution: #c9a04a;
    --negative: #e0726a;
  }
}

.dark {
  --background: #0a0a0a;
  --foreground: #ededed;
  --card: #0f0f0f;
  --card-foreground: #ededed;
  --popover: #141414;
  --popover-foreground: #ededed;
  --primary: #ffffff;
  --primary-foreground: #0a0a0a;
  --secondary: #141414;
  --secondary-foreground: #ededed;
  --muted: #141414;
  --muted-foreground: #9a9a9a;
  --accent: #1a1a1a;
  --accent-foreground: #ededed;
  --destructive: #e0726a;
  --border: #1f1f1f;
  --input: #333333;
  --ring: #777777;

  --chart-1: #a1a1a1;
  --chart-2: #7a9cc9;
  --chart-3: #c99a6b;
  --chart-4: #6fb0a0;
  --chart-5: #a892c6;
  --chart-6: #d1917b;
  --chart-7: #8dab78;
  --chart-8: #bd8fa8;

  --positive: #5cb185;
  --caution: #c9a04a;
  --negative: #e0726a;
}

@layer base {
  * {
    @apply border-border;
  }

  html,
  body,
  #root {
    min-height: 100%;
    margin: 0;
    padding: 0;
  }

  /* Fill mode: the document is exactly its frame, not at least its frame.

     `min-height: 100%` above is the inline contract — grow with the content and
     let the host size the frame around it. It is also, precisely, why an
     artifact's own `h-full` used to do nothing: a percentage height resolves
     against a parent's DEFINITE height, and `min-height` never makes one. Every
     link in the chain was `auto`, so `h-full` collapsed to `h-auto` and there
     was no bounded region for `flex-1 min-h-0 overflow-auto` to scroll inside.

     Switching to a definite `height: 100%` here is what turns the host's
     measured viewport into a real constraint the whole way down: frame ->
     document -> body -> #root -> the artifact's root element. `min-height: 0`
     goes with it so the floor cannot re-inflate the box past its frame.

     This file is loaded by BOTH documents — compiled into the shell's own
     stylesheet and shipped as raw source to the inner srcdoc frame — so one rule
     covers both halves of the chain. It is class-scoped rather than
     unconditional because inline mode genuinely needs the opposite: there, body
     must be content-height, since that is the number the inner frame's
     ResizeObserver reports and the host sizes the frame from. */
  html.artifact-fill,
  html.artifact-fill body,
  html.artifact-fill #root {
    height: 100%;
    min-height: 0;
  }

  body {
    @apply bg-background font-sans text-foreground antialiased;
  }

  /* Numbers do not jitter. Every count, metric, axis tick and table figure in
     an artifact is a number in a column that updates, so tabular figures are
     the default rather than something the model has to remember to ask for. */
  body {
    font-variant-numeric: tabular-nums;
  }

  .proportional-nums {
    font-variant-numeric: normal;
  }

  ::-webkit-scrollbar {
    width: 6px;
    height: 6px;
  }
  ::-webkit-scrollbar-track {
    background: transparent;
  }
  ::-webkit-scrollbar-thumb {
    background: var(--input);
    border-radius: 3px;
  }
  ::-webkit-scrollbar-thumb:hover {
    background: var(--ring);
  }
}

/* The artifact container.

   The shell owns the artifact's outer padding and measure. Model-written code
   that also sets a page-level `p-6` doubles it; code that sets none renders
   flush to the frame edge. Neither is the model's problem to solve, so the
   answer is not a prompt rule but a container that is always right — the skill
   documents it so the model knows not to add its own.

   `max-width` keeps a table or a metric row from stretching to a 2000px
   viewport, where rows become unreadable ribbons. Content that genuinely wants
   the full width opts out with `w-full` on a child. */
.artifact-root {
  padding: 24px;
  max-width: 1100px;
  margin-inline: auto;
}

@media (max-width: 640px) {
  .artifact-root {
    padding: 16px;
  }
}

/* Fill mode: the artifact container is the viewport, and its child fills it.

   `height: 100%` completes the chain from the host's measured container down to
   the model's own root element. `display: flex` with a single stretched child is
   what makes `h-full` usable INSIDE the artifact — a percentage-height child of
   a plain block box resolves against the box's content height, which is circular,
   whereas a flex item stretches to the line. So an artifact written as
   `<div className="flex h-full flex-col">` gets a real bounded column, and its
   `flex-1 min-h-0 overflow-auto` region becomes a genuine scroll box.

   `box-sizing: border-box` keeps the 24px padding inside the 100%, rather than
   pushing the container 48px past its frame and reintroducing the outer
   scrollbar this whole mode exists to remove. */
html.artifact-fill .artifact-root {
  height: 100%;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
}

html.artifact-fill .artifact-root > * {
  min-height: 0;
  flex: 1;
}
