/* ============================================================================
   Envor design tokens.

   The single source for colour, type, tracking and form across every Envor
   surface: envor.io, the console, the wake page, and provisioning. Nothing
   downstream declares a colour or a size of its own.

   Two densities share one set of named steps. Marketing surfaces take the
   defaults; a console-density subtree adds .dense.
   ============================================================================ */

:root {
  /* -- Ground -------------------------------------------------------------
     Soft blacks. The ramp descends from the page ground into panels, so a
     raised surface is lighter than the plane it sits on, never darker. */
  --ink-000: #0a0a0a; /* app shell, the ground behind panels */
  --ink-050: #0f0f0f; /* page ground, header, footer */
  --ink-100: #141517; /* sunken: tracks, inputs, code */
  --ink-150: #17181a; /* surface: panels, cards, rows */
  --ink-200: #1d1f22; /* raised: hover, active row, selected */

  --line: #2c3034;    /* border */
  --line-hi: #3a4046; /* a divider that must read */

  /* -- Text ---------------------------------------------------------------
     Contrast ratios are against --ink-150, the surface most text sits on. */
  --fg-000: #ffffff;  /* display figures, the mark      19.8:1 */
  --fg-100: #e8eaed;  /* primary                       16.4:1 */
  --fg-200: #d1d5db;  /* prose                         13.4:1 */
  --fg-300: #9ca3af;  /* dim: labels, captions          7.8:1 */
  --fg-400: #828b98;  /* faint: ticks, metadata         5.3:1 */

  /* -- Brand --------------------------------------------------------------
     The mark's green. It carries the brand and the converged state alike:
     the product's promise and its best status are the same idea. */
  --brand: #34d74a;
  --brand-hi: #5ee46f;
  --brand-dim: rgba(52, 215, 74, 0.12); /* focus rings and quiet fills, never a state marker */

  /* -- State --------------------------------------------------------------
     In flight sits on the blue axis so it is never told from converged or
     failed by hue alone, and so a progress bar does not read as a warning.
     The warm range is a severity ramp, held to degraded to failed, and it
     descends in lightness as it worsens: severity survives a reader who
     cannot separate the hues at all.

     Held is an overlay, not a peer of the others: a service is converged and
     held, or degraded and held. Idle means no demand is being made, which the
     console calls a bystander; it never takes a filled bar. */
  --live: #22d3ee;     /* in flight: work happening now  9.8:1 */
  --live-dim: rgba(34, 211, 238, 0.13);
  --live-glow: rgba(34, 211, 238, 0.45);

  --degraded: #e2683a; /* partial, needs attention       5.9:1 */
  --held: #fbbf24;     /* a deferral holds this         10.6:1 */
  --fail: #de536d;     /* failed, unreachable            4.7:1 */
  --idle: #828b98;     /* nothing is being asked         5.2:1 */

  /* -- Tone ---------------------------------------------------------------
     The ramp a customer's own state name is drawn in, and the counterpart to
     the state colours above: those are envor's reading of a unit, this is the
     customer's vocabulary. State names are arbitrary strings (On, Off, Running,
     Stopped, Full, ReducedCapacity, ApiReady) and hold no verdict, so they take
     a tone and never a hue. A strip of them reads as texture, and every mark
     beside it keeps all the colour.

     Four steps, ordered so a colourer walking them in first-seen order puts the
     lightest next to the darkest and consecutive assignments contrast most.
     Ratios are against --ink-100, the sunken track a tone lies in, and that
     floor is the point of them: a fill that does not clear its own groove is
     not a fill. The closest pair is tone-2 against tone-4 at 1.36:1, which is a
     texture difference rather than a legibility guarantee, so tone is never the
     only channel. Every block is named beside it, in a column or a legend, and
     a fifth state reuses the ramp rather than earning a fifth step. */
  --tone-1: #777c87;   /* lightest                       4.37:1 */
  --tone-2: #303540;   /* darkest                        1.49:1 */
  --tone-3: #5b606b;   /*                                2.90:1 */
  --tone-4: #444954;   /*                                2.02:1 */

  /* -- Type ---------------------------------------------------------------
     Two faces. The mono is the structural voice and carries everything with
     a shape to it: headings, nav, labels, buttons, tables, code, every
     identifier and every figure. The sans carries running prose and nothing
     else. Display is not a third family, it is the mono set large, heavy and
     closed up.

     JetBrains Mono is self hosted wherever the surface must work air-gapped;
     the stack falls back to the platform mono in order. */
  --mono: 'JetBrains Mono', ui-monospace, 'SF Mono', 'Cascadia Code', Menlo, Consolas, monospace;
  --sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, 'Helvetica Neue', Arial, sans-serif;
  --font-display: var(--mono);

  /* -- Scale: marketing density ------------------------------------------ */
  --fs-nano: 11px;   /* eyebrows, legends, ticks, badges       */
  --fs-meta: 12px;   /* timestamps, counts, footnotes          */
  --fs-body: 14px;   /* rows, cells, controls, prose           */
  --fs-head: 15px;   /* names, panel titles                    */
  --fs-lead: 18px;   /* section heads, sub display             */
  --fs-d-sm: 28px;   /* card figures                           */
  --fs-d: 40px;      /* hero line, primary KPI                 */
  --fs-d-lg: 56px;   /* the countdown                          */

  /* -- Tracking -----------------------------------------------------------
     Three values, one job each. Every uppercase label takes the same track:
     differing by a hair reads as drift rather than as distinction. Below
     20px there is no negative tracking at all, where it is imperceptible. */
  --tr-label: .14em;    /* uppercase labels: eyebrows, table heads, buttons */
  --tr-display: -.02em; /* display lines */
  --tr-figure: -.045em; /* display figures: monospaced, so set loose by default */

  /* -- Form ---------------------------------------------------------------
     Corners are square. Bars and tracks take the hairline radius; only true
     dots take a full one. One control height per density, so inputs, selects
     and buttons align by construction. */
  --r-0: 0;
  --r-1: 2px;
  --r-full: 999px;
  --ctl: 32px;
  --t: 150ms ease;
}

/* Console density: the same named steps, one notch tighter. */
.dense {
  --fs-nano: 10px;
  --fs-meta: 11px;
  --fs-body: 12.5px;
  --fs-head: 13.5px;
  --fs-lead: 17px;
  --fs-d-sm: 24px;
  --fs-d: 34px;
  --fs-d-lg: 40px;
  --ctl: 30px;
}

/* ----------------------------------------------------------------------------
   Two primitives that every surface shares.
   ---------------------------------------------------------------------------- */

/* The display figure. Weight and tracking are tuned for a monospaced face,
   which is wide and set loose at size. Tabular by construction, so columns of
   figures align and a counting display does not jitter as its digits change. */
.num {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: var(--tr-figure);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

/* The state marker: a dot carries the colour, the word carries the meaning.
   No capsule and no tint. Colour is never the only channel, so the word is
   always present beside the dot.

   These express envor's judgment about convergence, and nothing else. A
   customer's own state names are arbitrary (On, Off, Running, Stopped, Full,
   Reduced, ApiReady) and carry no verdict: Reduced may be exactly where an
   environment is meant to stand. Never colour a customer's state name. Where a
   surface shows what a thing stands in and what it is bound for, both are set
   neutrally, and colour appears only when convergence has something to say. */
.marker {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  white-space: nowrap;
  font-family: var(--mono);
  font-size: var(--fs-nano);
  font-weight: 600;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
}
.marker::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: var(--r-full);
  background: currentColor;
  flex-shrink: 0;
}
.marker.ok       { color: var(--brand); }
.marker.live     { color: var(--live); }
.marker.degraded { color: var(--degraded); }
.marker.held     { color: var(--held); }
.marker.fail     { color: var(--fail); }
.marker.idle     { color: var(--idle); }

/* Slashed zero, so 0 and O never trade places in an id or a timestamp. The
   sans has no such feature and ignores it. */
body {
  font-feature-settings: 'zero' 1;
}
