/* Steid's theme.
   Started from Topcoat's `neutral` theme and retuned; see plans/ui.md.

   The theme is a small set of design tokens. Components refer to tokens only,
   never to raw colors, so the whole product restyles by editing `:root` and
   `.dark` below. A component that hardcodes a color is a bug — it will not
   follow a palette change and it will not adapt to the color scheme.

     --background              the page background
     --surface                 raised panels: cards, menus, flash messages
     --foreground              text and iconography on the background
     --muted-foreground        secondary text: captions, descriptions, placeholders
     --primary                 the emphasis color: primary actions, selection, links
     --primary-foreground      text on a primary-filled surface
     --success                 confirmations, and git additions
     --success-foreground      text on a success-filled surface
     --warning                 caution, and git modifications
     --warning-foreground      text on a warning-filled surface
     --destructive             destructive actions, errors, and git deletions
     --destructive-foreground  text on a destructive-filled surface
     --border                  hairline borders and dividers
     --ring                    the focus ring
     --shadow-xs               a subtle shadow for controls: buttons, inputs
     --shadow-sm               a shadow for raised surfaces: cards, menus

   Syntax highlighting adds a --syntax-* family, derived from the same palette and
   mapped onto the highlighter's classes at the bottom of this file.

   Interactive states (hover, press) have no tokens of their own: components
   derive them by applying the fill or foreground color at reduced opacity,
   which adapts to both color schemes automatically.

   Steid is dark-first — the layout sets `class="dark"` on <html>. Light mode
   is supported and secondary. */

@import "tailwindcss";

/* Scan the project's Rust sources for the Tailwind classes they use. This
   file is installed at the project root, so `./src` is the crate's source. */
@source "./src/**/*.rs";

/* Dark mode is opted into by putting the `dark` class on an ancestor,
   typically <html>. */
@custom-variant dark (&:is(.dark *));

/* Expose the tokens as Tailwind utilities (`bg-background`, `text-primary`,
   `border-border`, ...). The indirection through plain variables on `:root`
   and `.dark` is what lets the values swap when the color scheme changes. */
@theme inline {
  --font-sans: "Geist", ui-sans-serif, system-ui, sans-serif;
  /* Paths, commit hashes, branch names, and code. */
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", monospace;
  --color-background: var(--background);
  --color-surface: var(--surface);
  --color-foreground: var(--foreground);
  --color-muted-foreground: var(--muted-foreground);
  --color-primary: var(--primary);
  --color-primary-foreground: var(--primary-foreground);
  --color-success: var(--success);
  --color-success-foreground: var(--success-foreground);
  --color-warning: var(--warning);
  --color-warning-foreground: var(--warning-foreground);
  --color-destructive: var(--destructive);
  --color-destructive-foreground: var(--destructive-foreground);
  --color-border: var(--border);
  --color-ring: var(--ring);
  --shadow-xs: var(--shadow-xs);
  --shadow-sm: var(--shadow-sm);
}

/* Light mode. Secondary, but it should not look like an afterthought. */
:root {
  --background: oklch(0.99 0.003 260);
  --surface: oklch(1 0 0);
  --foreground: oklch(0.24 0.012 260);
  --muted-foreground: oklch(0.51 0.014 260);
  --primary: oklch(0.5 0.18 250);
  --primary-foreground: oklch(0.99 0.003 260);
  --success: oklch(0.52 0.15 145);
  --success-foreground: oklch(0.99 0.01 145);
  --warning: oklch(0.62 0.14 85);
  --warning-foreground: oklch(0.99 0.01 85);
  --destructive: oklch(0.55 0.2 27);
  --destructive-foreground: oklch(0.99 0.012 27);
  --border: oklch(0.9 0.008 260);
  --ring: oklch(0.5 0.18 250);
  --shadow-xs: 0 1px 2px oklch(0.24 0.02 260 / 12%);
  --shadow-sm:
    0 1px 2px oklch(0.24 0.02 260 / 10%),
    0 2px 8px -2px oklch(0.24 0.02 260 / 9%);

  --syntax-comment: oklch(0.55 0.015 260);
  --syntax-punctuation: oklch(0.46 0.015 260);
  --syntax-variable: oklch(0.3 0.014 260);
  --syntax-type: oklch(0.45 0.09 195);
  --syntax-function: oklch(0.48 0.15 250);
  --syntax-constant: oklch(0.5 0.12 62);
  --syntax-string: oklch(0.45 0.12 150);
  --syntax-keyword: oklch(0.45 0.17 300);
  --syntax-heading: oklch(0.42 0.16 250);
}

/* Dark mode. The primary surface for this product. */
.dark {
  --background: oklch(0.16 0.02 260);
  --surface: oklch(0.2 0.02 260);
  --foreground: oklch(0.9 0.01 260);
  --muted-foreground: oklch(0.66 0.014 260);
  --primary: oklch(0.65 0.15 250);
  --primary-foreground: oklch(0.16 0.02 260);
  --success: oklch(0.7 0.17 145);
  --success-foreground: oklch(0.16 0.02 145);
  --warning: oklch(0.8 0.15 85);
  --warning-foreground: oklch(0.16 0.02 85);
  --destructive: oklch(0.65 0.2 25);
  --destructive-foreground: oklch(0.14 0.02 25);
  --border: oklch(0.3 0.012 260);
  --ring: oklch(0.65 0.15 250);
  /* Light-mode shadows disappear on a dark background, so these are deeper. */
  --shadow-xs: 0 1px 2px oklch(0 0 0 / 35%);
  --shadow-sm: 0 1px 2px oklch(0 0 0 / 35%), 0 2px 8px -2px oklch(0 0 0 / 30%);

  --syntax-comment: oklch(0.6 0.014 260);
  --syntax-punctuation: oklch(0.72 0.014 260);
  --syntax-variable: oklch(0.86 0.02 260);
  --syntax-type: oklch(0.82 0.08 195);
  --syntax-function: oklch(0.78 0.11 240);
  --syntax-constant: oklch(0.82 0.11 70);
  --syntax-string: oklch(0.78 0.12 150);
  --syntax-keyword: oklch(0.75 0.12 300);
  --syntax-heading: oklch(0.75 0.13 250);
}

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

/* Syntax highlighting.
   `infrastructure/highlight.rs` emits classes, never inline colors, so the theme
   lives here with everything else and follows the color scheme. Tailwind never sees
   these class names — the markup is generated, not written in `src/` — so this is
   plain CSS against the tokens above, as ui.md requires.

   The classes are the *atoms* of a TextMate scope, flattened and prefixed: the scope
   `storage.type.function.rust` becomes `class="hl-storage hl-type hl-function hl-rust"`.
   Atoms are therefore not positional — `hl-function` is on `meta.function`, which
   wraps a whole function body, as well as on the name itself — so a single-atom
   selector is only safe for an atom that leads its scope. The rest are spelled out as
   the compound they really are.

   Order is load-bearing. Spans nest, so an inner span with two matching rules of equal
   specificity takes the later one; `punctuation.definition.string` carries both
   `hl-punctuation` and `hl-string`, and a quote should read as its string. Weakest
   first, strongest last. */

.hl-punctuation,
.hl-keyword.hl-operator {
  color: var(--syntax-punctuation);
}

.hl-variable,
.hl-entity.hl-other.hl-attribute-name {
  color: var(--syntax-variable);
}

.hl-entity.hl-name,
.hl-support.hl-function {
  color: var(--syntax-function);
}

.hl-entity.hl-name.hl-type,
.hl-entity.hl-name.hl-class,
.hl-entity.hl-name.hl-struct,
.hl-entity.hl-name.hl-enum,
.hl-entity.hl-name.hl-trait,
.hl-entity.hl-name.hl-namespace,
.hl-support.hl-type,
.hl-support.hl-class {
  color: var(--syntax-type);
}

.hl-constant,
.hl-support.hl-constant {
  color: var(--syntax-constant);
}

.hl-storage,
.hl-keyword,
.hl-entity.hl-name.hl-tag {
  color: var(--syntax-keyword);
}

.hl-string {
  color: var(--syntax-string);
}

/* Markdown and other markup: the source is read as prose, so structure carries the
   color and the body stays at foreground. */
.hl-markup.hl-heading {
  color: var(--syntax-heading);
  font-weight: 600;
}

.hl-markup.hl-raw {
  color: var(--syntax-string);
}

.hl-markup.hl-underline.hl-link {
  color: var(--syntax-function);
}

.hl-markup.hl-bold {
  font-weight: 600;
}

.hl-markup.hl-italic {
  font-style: italic;
}

/* Last, so a comment is a comment whatever it contains. */
.hl-comment {
  color: var(--syntax-comment);
}

.hl-invalid {
  color: var(--destructive);
}

/* Unified diff rows.

   Plain CSS rather than Tailwind utilities because these are theme tokens at
   low alpha, and `color-mix` against a custom property is not something a
   utility class can express. The alpha is the point: a tint has to sit under
   text that stays readable in both color schemes, which a solid `--success`
   or `--destructive` would not.

   Never a raw color here — every value is a token mixed with transparency, so
   the diff follows a palette change like everything else. The gutters take a
   stronger mix than the line so the numbers stay legible against it. */
.diff-line-add {
  background-color: color-mix(in oklab, var(--success) 12%, transparent);
}

.diff-line-del {
  background-color: color-mix(in oklab, var(--destructive) 12%, transparent);
}

.diff-gutter-add {
  background-color: color-mix(in oklab, var(--success) 20%, transparent);
}

.diff-gutter-del {
  background-color: color-mix(in oklab, var(--destructive) 20%, transparent);
}

/* A hunk header separates two parts of a file, so it reads as a rule rather
   than as a change: no tint, a hairline above it, and muted text. */
.diff-line-hunk td {
  border-top: 1px solid var(--border);
  padding-top: 0.25rem;
  padding-bottom: 0.25rem;
}

.diff-line-hunk:first-child td {
  border-top: 0;
}
