/*
 * The design tokens, and the only file to edit to change how Kanso looks.
 *
 * One token system lives in this document: shadcn's, named as shadcn names them so
 * a component copied from the documentation works unmodified. Kanso's original
 * `--k-*` palette is gone — every surface reads from here now. `data-theme` narrows
 * the legacy `color-scheme`, and `.dark` selects the block below; both are driven
 * from the same preference, so they cannot disagree. See lib/theme.ts.
 *
 * One copy of the values below lives outside this repository's CSS:
 * `apps/api/.../oauth/ConsentPage.kt` inlines the `:root` and dark blocks, because that
 * page is served by the API on another origin and has no stylesheet to link. It is the
 * screen a member reads before handing an agent their work, so a palette edited here and
 * not there is a consent screen that stops looking like Kanso — and `ConsentPageTest`
 * checks that it renders in both themes, not that it matches this file.
 */

/* Dark mode by class, the shadcn standard. */
@custom-variant dark (&:is(.dark *));

:root {
  /* Ground and ink. Neutrals carry a trace of hue 262 at chroma 0.002–0.012:
     an order of magnitude below where a tint reads as a colour decision, and
     what puts the ground under the accent rather than beside it. */
  --background: oklch(0.988 0.002 262);
  --foreground: oklch(0.22 0.012 262);
  --muted-foreground: oklch(0.52 0.011 262);
  --faint: oklch(0.68 0.010 262);          /* third ink: labels, ids, meta */

  --card: #ffffff;
  --card-foreground: var(--foreground);
  --popover: #ffffff;
  --popover-foreground: var(--foreground);
  --secondary: oklch(0.965 0.004 262);
  --secondary-foreground: var(--foreground);
  --muted: oklch(0.965 0.004 262);

  /* shadcn's --accent is the hover fill, not the brand colour. */
  --accent: oklch(0.965 0.004 262);
  --accent-foreground: var(--foreground);

  --border: oklch(0.925 0.005 262);        /* a contour */
  --input: oklch(0.925 0.005 262);
  --rule: oklch(0.86 0.006 262);           /* a stated divider */

  /* Statuses: five drawn hues on one lightness plane, so none outweighs
     another at a glance. Move all five or none. Canceled sits above the
     plane on purpose — a canceled ticket should recede. */
  --status-backlog: oklch(0.68 0.010 262);
  --status-todo: oklch(0.52 0.011 262);
  --status-progress: oklch(0.62 0.13 78);
  --status-review: oklch(0.58 0.12 232);
  --status-done: oklch(0.56 0.13 158);
  --status-canceled: oklch(0.75 0.008 262);

  /* Priority. Not statuses: a separate axis, read as a glyph.
     --urgent is next to --destructive in hue and stays its own token:
     an urgent ticket is not a failed one. */
  --urgent: oklch(0.55 0.19 22);
  --priority-high: oklch(0.58 0.14 52);
  --priority-medium: oklch(0.58 0.12 232);
  --priority-low: oklch(0.68 0.010 262);
  --priority-none: oklch(0.75 0.008 262);

  /* Not in the design system, and load-bearing. globals.css records why amber
     is not red: a dependency broken but still repairable is not an error. */
  --destructive: oklch(0.577 0.245 27.325);
  --destructive-foreground: oklch(0.985 0 0);

  /* L lowered from 0.60 to 0.50 (hue and chroma unchanged): at 0.60 the white label
     sat at a 3.57:1 contrast, under WCAG AA's 4.5:1 and under this same palette's own
     --destructive (4.56:1). 0.50 clears 5.4:1 — read at the swatch and the badge in
     src/app/design-system, not computed first and assumed. */
  --success: oklch(0.50 0.13 150);
  --success-foreground: oklch(0.985 0 0);
  --warning: oklch(0.70 0.15 75);
  --warning-foreground: oklch(0.205 0 0);

  /* Density. Compact removes space, never legibility: the body stays 13px. */
  --radius: 6px;                            /* the row corner */
  --panel-radius: 10px;
  --row-h: 36px;
  --row-pad-x: 12px;
  --row-gap: 2px;
  --group-gap: 18px;
  --touch-min: 44px;

  /* Elevation. Raw tokens are --elev-*: --shadow-* is a Tailwind namespace,
     and a raw token mapped to a theme key of the same name resolves to itself. */
  --elev-flat: 0 1px 2px rgb(20 20 30 / 8%);
  --elev-panel: 0 1px 2px rgb(20 20 30 / 8%), 0 18px 44px rgb(20 20 30 / 10%);
  --elev-float: 0 1px 2px rgb(20 20 30 / 10%), 0 20px 44px rgb(20 20 30 / 22%);

  --font-sans: var(--font-public-sans), system-ui, -apple-system, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  --font-seal: var(--font-noto-sans-jp), "Hiragino Sans", "Yu Gothic", sans-serif;
}

[data-density="compact"] {
  --row-h: 27px;
  --row-pad-x: 10px;
  --row-gap: 1px;
  --group-gap: 11px;
  --radius: 5px;
}

.dark {
  --background: oklch(0.185 0.008 262);
  --foreground: oklch(0.935 0.006 262);
  --muted-foreground: oklch(0.715 0.011 262);
  --faint: oklch(0.565 0.011 262);

  --card: oklch(0.228 0.010 262);
  --card-foreground: var(--foreground);
  --popover: oklch(0.228 0.010 262);
  --popover-foreground: var(--foreground);
  --secondary: oklch(0.272 0.012 262);
  --secondary-foreground: var(--foreground);
  --muted: oklch(0.272 0.012 262);
  --accent: oklch(0.272 0.012 262);
  --accent-foreground: var(--foreground);

  --border: oklch(0.315 0.012 262);
  --input: oklch(0.315 0.012 262);
  --rule: oklch(0.315 0.012 262);

  --status-backlog: oklch(0.565 0.011 262);
  --status-todo: oklch(0.715 0.011 262);
  --status-progress: oklch(0.76 0.12 78);
  --status-review: oklch(0.72 0.11 232);
  --status-done: oklch(0.70 0.12 158);
  --status-canceled: oklch(0.50 0.009 262);

  --urgent: oklch(0.68 0.17 22);
  --priority-high: oklch(0.74 0.13 52);
  --priority-medium: oklch(0.72 0.11 232);
  --priority-low: oklch(0.565 0.011 262);
  --priority-none: oklch(0.50 0.009 262);

  --destructive: oklch(0.704 0.191 22.216);
  --destructive-foreground: oklch(0.145 0 0);
  --success: oklch(0.70 0.14 150);
  --success-foreground: oklch(0.145 0 0);
  --warning: oklch(0.78 0.14 75);
  --warning-foreground: oklch(0.145 0 0);

  --elev-flat: 0 1px 2px rgb(0 0 0 / 30%);
  --elev-panel: 0 1px 2px rgb(0 0 0 / 30%), 0 18px 44px rgb(10 10 16 / 30%);
  --elev-float: 0 1px 2px rgb(0 0 0 / 34%), 0 20px 44px rgb(8 8 14 / 40%);
}

/* Light: --primary is oklch(0.52 C h); dark is oklch(0.70 C-0.01 h).
   Chroma per hue: 262→0.14, 302→0.15, 12→0.15, 232→0.14, 158→0.13, 78→0.13.
   Only indigo is drawn in the bundle in both schemes; the other five dark
   values follow the transform it demonstrates, so they are read on
   /design-system before they ship, not trusted.
   --accent-soft is a tint of the ground, not of the accent: it sits behind
   body text, and a saturated fill would either bury the text or vibrate
   against the page. --accent-ink is the accent read as text — on
   --accent-soft, or wherever the hue has to speak without the weight of a
   filled --primary. */
[data-accent="indigo"] {
  --primary: oklch(0.52 0.14 262);
  --accent-soft: oklch(0.965 0.021 262);
  --accent-ink: oklch(0.42 0.13 262);
}
.dark [data-accent="indigo"],
[data-accent="indigo"].dark {
  --primary: oklch(0.70 0.13 262);
  --accent-soft: oklch(0.30 0.048 262);
  --accent-ink: oklch(0.80 0.11 262);
}

[data-accent="violet"] {
  --primary: oklch(0.52 0.15 302);
  --accent-soft: oklch(0.965 0.021 302);
  --accent-ink: oklch(0.42 0.13 302);
}
.dark [data-accent="violet"],
[data-accent="violet"].dark {
  --primary: oklch(0.70 0.14 302);
  --accent-soft: oklch(0.30 0.048 302);
  --accent-ink: oklch(0.80 0.11 302);
}

[data-accent="rose"] {
  --primary: oklch(0.52 0.15 12);
  --accent-soft: oklch(0.965 0.021 12);
  --accent-ink: oklch(0.42 0.13 12);
}
.dark [data-accent="rose"],
[data-accent="rose"].dark {
  --primary: oklch(0.70 0.14 12);
  --accent-soft: oklch(0.30 0.048 12);
  --accent-ink: oklch(0.80 0.11 12);
}

[data-accent="blue"] {
  --primary: oklch(0.52 0.14 232);
  --accent-soft: oklch(0.965 0.021 232);
  --accent-ink: oklch(0.42 0.13 232);
}
.dark [data-accent="blue"],
[data-accent="blue"].dark {
  --primary: oklch(0.70 0.13 232);
  --accent-soft: oklch(0.30 0.048 232);
  --accent-ink: oklch(0.80 0.11 232);
}

[data-accent="green"] {
  --primary: oklch(0.52 0.13 158);
  --accent-soft: oklch(0.965 0.021 158);
  --accent-ink: oklch(0.42 0.13 158);
}
.dark [data-accent="green"],
[data-accent="green"].dark {
  --primary: oklch(0.70 0.12 158);
  --accent-soft: oklch(0.30 0.048 158);
  --accent-ink: oklch(0.80 0.11 158);
}

[data-accent="amber"] {
  --primary: oklch(0.52 0.13 78);
  --accent-soft: oklch(0.965 0.021 78);
  --accent-ink: oklch(0.42 0.13 78);
}
.dark [data-accent="amber"],
[data-accent="amber"].dark {
  --primary: oklch(0.70 0.12 78);
  --accent-soft: oklch(0.30 0.048 78);
  --accent-ink: oklch(0.80 0.11 78);
}

:root {
  --primary-foreground: #ffffff;
  --ring: var(--primary);
}
.dark {
  --primary-foreground: oklch(0.185 0.008 262);
}

/*
 * The bridge that turns the variables above into utilities: `bg-background`,
 * `text-muted-foreground`, `rounded-lg`, `border-border`. `inline` resolves the
 * var() at use, which is what lets .dark re-point the same utility.
 */
@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-card: var(--card);
  --color-card-foreground: var(--card-foreground);
  --color-popover: var(--popover);
  --color-popover-foreground: var(--popover-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-destructive-foreground: var(--destructive-foreground);
  --color-success: var(--success);
  --color-success-foreground: var(--success-foreground);
  --color-warning: var(--warning);
  --color-warning-foreground: var(--warning-foreground);
  --color-border: var(--border);
  --color-input: var(--input);
  --color-ring: var(--ring);

  --color-faint: var(--faint);
  --color-rule: var(--rule);
  --color-accent-soft: var(--accent-soft);
  --color-accent-ink: var(--accent-ink);
  --color-status-backlog: var(--status-backlog);
  --color-status-todo: var(--status-todo);
  --color-status-progress: var(--status-progress);
  --color-status-review: var(--status-review);
  --color-status-done: var(--status-done);
  --color-status-canceled: var(--status-canceled);
  --color-urgent: var(--urgent);
  --color-priority-high: var(--priority-high);
  --color-priority-medium: var(--priority-medium);
  --color-priority-low: var(--priority-low);
  --color-priority-none: var(--priority-none);

  --height-row: var(--row-h);
  --spacing-row-x: var(--row-pad-x);
  --spacing-row: var(--row-gap);
  --spacing-group: var(--group-gap);
  --spacing-touch: var(--touch-min);

  --radius-sm: calc(var(--radius) - 2px);
  --radius-md: var(--radius);
  --radius-lg: var(--radius);
  --radius-xl: calc(var(--radius) + 4px);
  --radius-panel: var(--panel-radius);

  --shadow-flat: var(--elev-flat);
  --shadow-panel: var(--elev-panel);
  --shadow-float: var(--elev-float);

  --text-11: 11px;
  --text-12: 12px;
  --text-13: 13px;
  --text-15: 15px;
  --text-21: 21px;
  --text-30: 30px;

  /*
   * Without this line `--font-sans` above is just a same-named custom property:
   * Tailwind's theme system only reads keys declared inside `@theme`, so the
   * `font-sans` utility and Tailwind v4 preflight's own `--default-font-family`
   * on `html`/`:host` kept resolving to Tailwind's built-in fallback instead of
   * Public Sans, no matter what `--font-sans` said. Neither of those reaches
   * rendered app text on its own — `globals.css`'s `body` rule sits below
   * `html` and already named `var(--font-sans)` directly, which was sufficient
   * for body text with or without this line, since `--font-sans`'s plain
   * `:root` declaration above is unlayered and always beats this line's
   * layered one. This line is what makes the `font-sans` utility (should
   * anything reach for it) and preflight's own default agree with the rest of
   * the app instead of quietly disagreeing with it. `inline` for the same
   * reason every other bridge line above is: the `var()` re-resolves at use,
   * so this doesn't have to duplicate the stack.
   */
  --font-sans: var(--font-sans);
}

/*
 * What a bare `border` utility is coloured with — and the third thing `shadcn init`
 * writes, which hand-authoring `components.json` and `cn()` accounted for and this did
 * not. Without it there is no default at all: Tailwind's `.border` emits only width and
 * style, preflight's `* { border: 0 solid }` resets `border-color` to its initial
 * `currentColor`, and every generated component that says `border` therefore drew its
 * border in its own text colour. In light mode that put a near-black 1px line around
 * every dropdown, card and dialog, where Kanso's own popover used a light grey.
 *
 * In `base` on purpose, which is what scopes it. The layer order is `theme, base,
 * components, kanso-reset, utilities` (see globals.css), so this loses to every
 * unlayered legacy rule — `.button`'s own `border: 1px solid var(--border)` and its
 * kin keep winning — and loses to `utilities`, so `border-destructive` still
 * overrides it. What it reaches is exactly the set nothing else colours: the
 * generated components.
 */
@layer base {
  *,
  ::before,
  ::after {
    border-color: var(--border);
  }
}
