/* Written by Richard Christopher, Copyright 2026 Mindfull */
/*
 * Design tokens and element defaults ONLY.
 *
 * Every component style lives in that component's own scoped <style> block.
 * The previous file carried a parallel utility system (.glass-card, .btn-*,
 * .badge-*) that duplicated what components already styled locally and drifted
 * from it; none of that is coming back.
 */

/*
 * TOKENS. One source, six scales: color, space, type, radius, elevation,
 * motion. The CloudCanvas surface and every widget it draws read these and
 * define no scale of their own, which is what stops six panels each
 * re-declaring `.mt-4` and then drifting apart.
 *
 * Dark is the default because the product is dark. Light is an explicit
 * override on [data-theme='light'], and following the system is an explicit
 * opt-in on [data-theme='auto'] - an unset document is dark, never whatever the
 * desktop happens to prefer. Nothing below is duplicated per theme except the
 * colour scale itself; space, type, radius and motion are theme-independent.
 */
:root {
  color-scheme: dark;

  /* --- colour: surfaces ------------------------------------------------ */
  --bg: #0b0f14;
  --bg-raised: #11161d;
  --bg-sunken: #070a0e;
  --bg-overlay: rgba(7, 10, 14, 0.72);
  /* The wash a surface takes for each step it stands behind another (a folder tab's layers). Translucent,
   * so two steps back is twice as shaded as one. */
  --layer-shade: rgba(0, 0, 0, 0.22);
  --border: #232b36;
  --border-strong: #3a4553;

  /* --- colour: text ---------------------------------------------------- */
  --text: #dfe6ee;
  --text-dim: #94a3b3;
  --text-faint: #647082;
  --text-inverse: #0b0f14;

  /* The boundary of a field. It is what says a field is there, so it holds 3 : 1
   * against every surface (WCAG 1.4.11), which neither hairline above does. The
   * faintest text does, in both themes, and this is that colour by name: one
   * value, restated by no theme block. `tests/contrast-tokens.test.js` measures it. */
  --border-field: var(--text-faint);

  /* --- colour: signal --------------------------------------------------- */
  --ok: #4ade80;
  --fail: #f87171;
  --warn: #fbbf24;
  --info: #60a5fa;
  --accent: #818cf8;

  /* Tints, for the wash behind a warning and behind the accent. Derived from
   * the colours above so a theme change moves both together. */
  --warn-wash: rgba(251, 191, 36, 0.1);
  --accent-wash: rgba(129, 140, 248, 0.12);

  /* --- colour: categorical --------------------------------------------- */
  /* Eight hues that tell categories apart and say nothing else: a number here
   * carries no meaning, which is what separates these from the signal colours.
   * Each is a fill --text-inverse reads on, as --accent is. */
  --cat-1: #38bdf8;
  --cat-2: #fb923c;
  --cat-3: #34d399;
  --cat-4: #fb7185;
  --cat-5: #a78bfa;
  --cat-6: #facc15;
  --cat-7: #2dd4bf;
  --cat-8: #e879f9;

  /* --- colour: fixed --------------------------------------------------- */
  /* The paper behind a QR code. White in both themes, and stated in both: a
   * camera reads the code against it, so it is the one surface a theme must
   * not repaint. */
  --qr-paper: #ffffff;
  /* The light and the shade drawn on a flag marker, and the shadow it casts.
   * They model light falling on the marker, not a surface of the theme, so one
   * value serves both themes and no theme block restates them. */
  --flag-light: #ffffff;
  --flag-shade: #020617;
  --flag-shadow: rgba(2, 6, 23, 0.4);

  /* --- type ------------------------------------------------------------- */
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --font-sans: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;

  --text-xs: 10px;
  --text-sm: 11px;
  --text-base: 13px;
  --text-lg: 15px;
  --text-xl: 19px;

  --leading-tight: 1.25;
  --leading-normal: 1.5;

  --weight-normal: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  /* --- space: a 4px ratio scale, not ad-hoc rem values ------------------ */
  --space-0: 0;
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;

  /* --- radius ----------------------------------------------------------- */
  --radius-none: 0;
  --radius-sm: 2px;
  --radius: 4px;
  --radius-lg: 8px;
  --radius-full: 999px;

  /* --- elevation --------------------------------------------------------- */
  --elevation-0: none;
  --elevation-1: 0 1px 2px rgba(0, 0, 0, 0.35);
  --elevation-2: 0 2px 8px rgba(0, 0, 0, 0.45);
  --elevation-3: 0 8px 24px rgba(0, 0, 0, 0.55);

  /* --- motion ------------------------------------------------------------ */
  --motion-fast: 90ms;
  --motion-base: 160ms;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}

/*
 * Light theme. Explicit opt-in via `data-theme="light"` on <html>, so the
 * appearance preference (phase-4 settings) is one attribute and nothing has to
 * be recompiled. Only the colour scale is restated.
 */
:root[data-theme='light'] {
  color-scheme: light;

  --bg: #f6f7f9;
  --bg-raised: #ffffff;
  --bg-sunken: #eceff3;
  --bg-overlay: rgba(246, 247, 249, 0.75);
  --layer-shade: rgba(22, 32, 43, 0.06);
  --border: #d7dce3;
  --border-strong: #b3bcc8;

  --text: #16202b;
  --text-dim: #4d5a68;
  --text-faint: #788593;
  --text-inverse: #ffffff;

  --ok: #15803d;
  --fail: #b91c1c;
  --warn: #a16207;
  --info: #1d4ed8;
  --accent: #4338ca;

  --warn-wash: rgba(161, 98, 7, 0.09);
  --accent-wash: rgba(67, 56, 202, 0.1);

  --cat-1: #0369a1;
  --cat-2: #c2410c;
  --cat-3: #047857;
  --cat-4: #be123c;
  --cat-5: #6d28d9;
  --cat-6: #a16207;
  --cat-7: #0f766e;
  --cat-8: #a21caf;

  --qr-paper: #ffffff;

  --elevation-1: 0 1px 2px rgba(22, 32, 43, 0.08);
  --elevation-2: 0 2px 8px rgba(22, 32, 43, 0.12);
  --elevation-3: 0 8px 24px rgba(22, 32, 43, 0.16);
}

/*
 * Auto. OPT-IN, via data-theme="auto", not the default.
 *
 * Dark is the product's appearance, so an unset document is dark regardless of
 * what the operating system prefers. Making `prefers-color-scheme` the default
 * would silently flip every screen to light for
 * anyone whose desktop is light, which is a decision the product has not made.
 * The appearance preference (phase-4 settings) can therefore express three
 * states: dark, light, and follow-the-system.
 */
@media (prefers-color-scheme: light) {
  :root[data-theme='auto'] {
    color-scheme: light;

    --bg: #f6f7f9;
    --bg-raised: #ffffff;
    --bg-sunken: #eceff3;
    --bg-overlay: rgba(246, 247, 249, 0.75);
    --layer-shade: rgba(22, 32, 43, 0.06);
    --border: #d7dce3;
    --border-strong: #b3bcc8;

    --text: #16202b;
    --text-dim: #4d5a68;
    --text-faint: #788593;
    --text-inverse: #ffffff;

    --ok: #15803d;
    --fail: #b91c1c;
    --warn: #a16207;
    --info: #1d4ed8;
    --accent: #4338ca;

    --warn-wash: rgba(161, 98, 7, 0.09);
    --accent-wash: rgba(67, 56, 202, 0.1);

    --cat-1: #0369a1;
    --cat-2: #c2410c;
    --cat-3: #047857;
    --cat-4: #be123c;
    --cat-5: #6d28d9;
    --cat-6: #a16207;
    --cat-7: #0f766e;
    --cat-8: #a21caf;

    --qr-paper: #ffffff;

    --elevation-1: 0 1px 2px rgba(22, 32, 43, 0.08);
    --elevation-2: 0 2px 8px rgba(22, 32, 43, 0.12);
    --elevation-3: 0 8px 24px rgba(22, 32, 43, 0.16);
  }
}

/* Motion tokens collapse to zero rather than each component writing its own
 * reduced-motion query. One place, and nothing can forget. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --motion-fast: 0ms;
    --motion-base: 0ms;
  }
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  -webkit-font-smoothing: antialiased;
}

a {
  color: var(--info);
}

/* Bare element defaults. These are the elements themselves, not a utility
 * class system: no component needs to opt in and nothing here can drift out of
 * step with a component that forgot to apply a class. */
button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
  background: var(--bg-sunken);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.2rem 0.4rem;
}

button {
  border-color: var(--border-strong);
  padding: 0.2rem 0.6rem;
  cursor: pointer;
}

button:hover:not(:disabled) {
  border-color: var(--accent);
  color: var(--accent);
}

button:disabled {
  opacity: 0.45;
  cursor: default;
}

/* A field is known by its boundary: it takes the one that can be seen (`--border-field`). */
input,
select,
textarea {
  border-color: var(--border-field);
}

input:focus,
select:focus,
textarea:focus {
  outline: 1px solid var(--accent);
  outline-offset: -1px;
}

/* A placeholder is read, so it is a text colour of the palette and not the
 * browser's own grey, which no theme reaches; and it is not dimmed twice. */
::placeholder {
  color: var(--text-dim);
  opacity: 1;
}

/*
 * DENSITY. An opt-in on `data-density="compact"` on <html>, set by the
 * appearance section of /screens/settings and stored in that browser only.
 *
 * It re-declares the SPACE SCALE and nothing else. No component defines its own
 * spacing, so tightening the scale tightens every screen at once, and there is
 * no per-component compact variant that could drift from the comfortable one.
 * Type, colour, radius and motion are untouched: compact means less air, not
 * smaller text, and shrinking the type would be a legibility decision nobody
 * asked for.
 */
:root[data-density='compact'] {
  --space-1: 0.15rem;
  --space-2: 0.3rem;
  --space-3: 0.45rem;
  --space-4: 0.6rem;
  --space-5: 0.9rem;
  --space-6: 1.2rem;
  --space-7: 1.8rem;
}
