/* Integra Workbench — design tokens
 *
 * Two tiers:
 *   1. Primitives — raw ramps. Never referenced by component CSS.
 *   2. Semantic   — role-named tokens. The only tier style.css may use.
 *
 * All hex literals in the web app live in this file (enforced by
 * tools/css_gate.sh). Theme switching overrides the semantic tier only,
 * via :root[data-theme="dark"].
 *
 * Brand palette (extracted from the Integrel logo):
 *   primary dark charcoal #303838 (desaturated dark slate, slight teal cast)
 *   brand accent magenta  #e73389 / #e84090
 */

:root {
  /* ── Primitives: charcoal/slate ramp (tinted toward #303838) ── */
  --charcoal-50:  #f4f6f6;
  --charcoal-100: #e8ecec;
  --charcoal-200: #d3dada;
  --charcoal-300: #b3bdbd;
  --charcoal-400: #93a0a0;
  --charcoal-500: #687474;
  --charcoal-600: #515c5c;
  --charcoal-700: #414a4a;
  --charcoal-800: #303838; /* brand primary */
  --charcoal-850: #232929;
  --charcoal-900: #1a2020;
  --charcoal-950: #121717;

  /* ── Primitives: magenta ramp (brand accent #e73389) ── */
  --magenta-50:  #fdf2f7;
  --magenta-100: #fce5f0;
  --magenta-200: #f9c5de;
  --magenta-300: #f49cc6;
  --magenta-400: #ee64a4;
  --magenta-500: #e73389; /* brand accent */
  --magenta-600: #cc2374;
  --magenta-700: #a91c60;
  --magenta-800: #8b1a50;
  --magenta-900: #6d1740;

  /* ── Primitives: gray-blue ramp (waiting) ── */
  --grayblue-50:  #f5f7fa;
  --grayblue-100: #e9edf3;
  --grayblue-200: #d4dce6;
  --grayblue-300: #b4c1d2;
  --grayblue-400: #9badc4;
  --grayblue-500: #6c7f99;
  --grayblue-600: #56677e;
  --grayblue-700: #475568;
  --grayblue-800: #343f4e;
  --grayblue-900: #242c38;

  /* ── Primitives: red ramp (fault) ── */
  --red-50:  #fdf3f2;
  --red-100: #fbe2e0;
  --red-200: #f6c4c1;
  --red-300: #e8938d;
  --red-400: #e36c65;
  --red-500: #d34a42;
  --red-600: #b73730;
  --red-700: #962c27;
  --red-800: #5c2f2c;
  --red-900: #3a2422;

  /* ── Primitives: amber ramp (warning) ── */
  --amber-50:  #fdf8ec;
  --amber-100: #faefd2;
  --amber-200: #f4dda4;
  --amber-300: #d9b25e;
  --amber-400: #dca93c;
  --amber-500: #c08a1d;
  --amber-600: #9d6f14;
  --amber-700: #7d5811;
  --amber-800: #54431c;
  --amber-900: #382e18;

  /* ── Primitives: green ramp (resolved / positive) ── */
  --green-50:  #f0f7f0;
  --green-100: #e6f2e6;
  --green-200: #c8e2c8;
  --green-300: #8fbf8f;
  --green-400: #6aa66a;
  --green-500: #4d8a4d;
  --green-600: #3d7a3d;
  --green-700: #356b35;
  --green-800: #294029;
  --green-900: #1f2e1f;

  /* ── Primitives: rust ramp (low confidence) ──
     Warmer and browner than the red ramp above, which is the fault hue. A grade the
     operator should not lean on must not read as a fault the system found.
     Two steps rather than a full ramp: only the light and the dark text tone are needed,
     and an unused step is a value nobody has looked at against a background. */
  --rust-300: #dda87c;
  --rust-700: #8a4a18;

  /* ── Primitives: teal ramp (high confidence) ──
     Cooler than the green ramp above, which is the resolved hue, and pulled toward the
     teal cast in the brand charcoal. A confident hypothesis is still a hypothesis, so it
     must not read as a case already put to bed. */
  --teal-300: #7fbfb7;
  --teal-700: #276760;

  /* ── Primitives: the four registry family hues (IW-529) ──
     A registry proposal card is coloured by the kind of change it is: a fact about the
     boat, a link, a controller, a lifecycle change. That is a classification, not a
     status, so none of these may read as one. Each hue sits in a gap the ramps above
     leave free: sea between the teal of high confidence and the gray-blue of waiting,
     cobalt and violet in the open stretch between that gray-blue and the brand magenta,
     moss between the amber of warning and the green of resolved. They are cut to one
     recipe so they read as a set: the lightness of the 700 and 300 steps above, and
     enough strength that cobalt is plainly a blue beside the gray-blue. Two steps each,
     like rust and teal, the tone for text on a light surface and the tone for text on a
     dark one. Sea and moss each have a status tone on either side, so each sits where
     its two neighbours are equally far off. Measured as chip text: every 700 step clears
     5.9 to 1 on the light page and 6.4 to 1 on a white card, every 300 step 7.2 to 1 on
     the dark surface. */
  --sea-300:    #6dbddc;
  --sea-700:    #066683;
  --cobalt-300: #8daaf2;
  --cobalt-700: #324faa;
  --violet-300: #c99de0;
  --violet-700: #793d94;
  --moss-300:   #adba65;
  --moss-700:   #5c6204;

  /* ── Non-color primitives ── */
  /* IBM Plex (vendored, @font-face in style.css) gives the workbench an engineered,
     instrument-panel character; system stacks remain as the offline fallback. */
  --font-sans: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
               system-ui, Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", SFMono-Regular, Menlo,
               Consolas, "Liberation Mono", monospace;

  --space-xs: 4px;
  --space-sm: 8px;
  --space-md: 12px;
  --space-lg: 16px;
  --space-xl: 24px;

  --font-size-xs: 12px;
  --font-size-sm: 13px;
  --font-size-md: 14px;
  /* Reading scale (IW-102): assistant prose is the one surface an operator reads for
     minutes at a time, so it sits a step above the chrome around it and takes a looser
     leading. The measure caps the line length independently of the pane width; a full
     1600px line is unreadable no matter how good the leading is. */
  --font-size-prose: 15px;
  /* The brief's hypothesis claim (IW-332): one clear step above prose, so the card's
     whole argument is the largest text on it and the eye lands there before the header
     and status lines above it. The grade beside it stays at label size, because an
     oversized number reads as a measurement and this number is a judgement. */
  --font-size-claim: 18px;
  /* The ticket header's title line (IW-606): the boat's name, the one place the
     header spends emphasis. Its own role, though it measures what the claim does:
     the two answer different questions, and one may move without the other. */
  --font-size-title: 18px;
  --line-height-prose: 1.65;
  --measure-prose: 68ch;
  /* Code samples and data tables need more room than running text but still a bound: a
     fenced block spanning a 1600px pane makes the prose above it look like a column in
     someone else's layout. */
  --measure-wide: 92ch;

  /* Motion (IW-102 U6): one duration and one curve for the whole chat surface, so
     entrances and state cross-fades read as the same gesture rather than a collection
     of separately tuned effects. */
  --motion-enter: 140ms;
  --ease-out: cubic-bezier(0.2, 0.6, 0.2, 1);

  --radius-sm: 4px;
  --radius-md: 6px;

  /* Shared height for form controls that must line up in one row (IW-291):
     the registry lookup row and the candidate promote row. Matches the
     rendered height inputs and buttons already get from their own padding,
     so it settles their small mismatch without resizing either. */
  --control-height: 32px;

  /* Shell layout (redesign U3) */
  --rail-width: 280px;
  --rail-width-collapsed: 56px;
  /* The bounds the operator can drag the rail between (IW-390). rail.js reads
     the default, the minimum and the maximum from here, so the three numbers
     have one home. The minimum still seats a row's glyph, number, age and
     unread dot with a sliver of name; the maximum is also capped at half the
     window by rail.js, so the case pane keeps a usable width on any screen. */
  --rail-width-min: 180px;
  --rail-width-max: 480px;
  /* The narrowest case pane the screens inside it are designed for (IW-391 built
     them down to this). rail.js reads it (IW-467): on a window where the pane
     beside the open rail would fall under it, the rail opens over the pane
     instead of pushing it. The pane's own narrow steps are container queries
     in style.css; this is the floor beneath them, not a third step. */
  --pane-width-min: 440px;
  --header-height: 48px;
  /* The spine of main pages (IW-624): its column on a desktop, and the height of
     the bar it becomes along the bottom of a phone. The same 56px as the
     collapsed rail strip beside it, so the two read as one measure. */
  --spine-width: 56px;
  /* Where the spine sits, read by everything placed against the rail's edge
     and by rail.js: the width it takes from the window's left and the height
     it takes from the bottom. Nothing on a page with no spine; style.css sets
     both on a shell that draws one, and swaps them on a phone. */
  --spine-column: 0px;
  --spine-row: 0px;
}

/* Registered so the collapse toggle (IW-259) can transition the width itself
   rather than snapping; an unregistered custom property cannot be animated. */
@property --rail-width {
  syntax: "<length>";
  inherits: true;
  initial-value: 280px;
}

/* ════════════════════════════════════════════════════════════════════
 * Semantic tier — light theme (default)
 * ════════════════════════════════════════════════════════════════════ */
:root {
  color-scheme: light;

  /* Backgrounds */
  --color-bg-page:     var(--charcoal-50);
  --color-bg-surface:  #ffffff;
  --color-bg-raised:   #ffffff;
  --color-bg-hover:    var(--charcoal-100);
  --color-bg-selected: var(--magenta-50);
  --color-bg-code:     var(--charcoal-100);
  --color-bg-inverse:  var(--charcoal-800);

  /* Text */
  --color-text-primary:   var(--charcoal-850);
  --color-text-secondary: var(--charcoal-700);
  --color-text-muted:     var(--charcoal-600);
  --color-text-inverse:   #ffffff;
  --color-text-on-accent: #ffffff;
  --color-text-on-status: #ffffff;

  /* Borders */
  --color-border-subtle: var(--charcoal-200);

  /* Ledger (IW-102): the hairline running down an assistant turn, and the tick that
     marks each block on it. The tick is the one place the brand accent appears inside
     the transcript, and it means "the agent acted" — never decoration. It is a separate
     role from the accent because it must stay quieter than an interactive element. */
  --color-ledger-rail: var(--charcoal-300);
  --color-ledger-tick: var(--magenta-400);

  /* Elevation (raised surfaces: floating panels, popovers) */
  --shadow-raised: 0 4px 14px rgba(20, 22, 26, 0.14);

  /* Scrim (IW-435): the one layer that covers the whole page, under the photo
     viewer. Dark in both themes, because a photograph is read against dark and
     the page beneath must fall away without vanishing; the brand charcoal at
     high alpha rather than black, so the scrim reads as the workbench dimmed
     and not as a different product. Text on it takes --color-text-inverse. */
  --color-scrim: rgba(26, 32, 32, 0.84);

  /* Accent (interactive / selected only) */
  --color-accent:       var(--magenta-600);
  --color-accent-hover: var(--magenta-700);

  /* Status (color + tint pair) */
  --color-status-fault:       var(--red-600);
  --color-status-fault-bg:    var(--red-100);
  --color-status-warning:     var(--amber-700);
  --color-status-warning-bg:  var(--amber-100);
  --color-status-waiting:     var(--grayblue-600);
  --color-status-waiting-bg:  var(--grayblue-100);
  --color-status-resolved:    var(--green-700);
  --color-status-resolved-bg: var(--green-100);

  /* Hypothesis confidence (IW-332): the three bands a grade renders in, low, middle and
     high. Their own roles by settled decision, not the status tones above: an unproven
     claim must never wear the fault hue or the resolved one, whatever its grade. Low is
     the rust ramp, middle the neutral charcoal, high the teal. Text tones only, so the
     grade takes its band's colour while the block keeps one tint.
     The middle band has to differ from --color-text-secondary as well as from the status
     roles. That is the colour .hyp-label already sets on the very line the grade sits in,
     so the neutral step nearest it left grades 5 to 7 with no separation at all. Middle
     steps to the primary text tone instead, away from the label rather than into it. */
  --color-confidence-low:    var(--rust-700);
  --color-confidence-middle: var(--charcoal-850);
  --color-confidence-high:   var(--teal-700);

  /* Registry families (IW-529): the colour a registry proposal card's chip takes from
     the kind of change it proposes. Boat is a fact about the boat itself, link is a
     ticket or an RMA joined to it, controller is the controller on board, lifecycle is a
     record made, parked, folded or split. Text tones, like the confidence roles: the
     chip's words and its outline take the colour and nothing is filled with it, so a
     family chip never reads as a status pill. The card's left stripe is not theirs; it
     stays the warning tone while pending and the border tone once settled. */
  --color-family-boat:       var(--sea-700);
  --color-family-link:       var(--cobalt-700);
  --color-family-controller: var(--violet-700);
  --color-family-lifecycle:  var(--moss-700);

  /* What the operator asked for (IW-665): the edge, the tint and the "You asked" lead of
     the answer block on the brief card. Cobalt, so the block is plainly not the magenta
     hypothesis callout it sits under, and not a status tone, because an answer is not a
     finding. Its own role: --color-family-link shares the step today and means a kind of
     registry change, so the two must be free to move apart. */
  --color-asked: var(--cobalt-700);

  /* Header controls (IW-530): the top bar's own tones, scoped to the inverse
     surface it sits on. Resting link text is a step below the inverse text so
     the current page and a hovered control can rise to it. Every control in the
     bar, page link, theme toggle and user menu, hovers to the same fill, and the
     page links are parted by a hairline so each reads as its own destination
     with nothing hovered. The count pill is neutral, a step lighter than the
     hover fill so it still shows on a hovered link; only the stuck fold badge
     takes the accent, so it is the one loud thing in the bar. */
  --color-header-text-rest:     var(--charcoal-200);
  --color-header-control-hover: var(--charcoal-700);
  --color-header-divider:       var(--charcoal-600);
  --color-header-badge-bg:      var(--charcoal-600);
}

/* ════════════════════════════════════════════════════════════════════
 * Semantic tier — dark theme overrides (semantic tokens only)
 * Lightness elevation: page < surface < raised. Off-white text,
 * desaturated accent and status hues.
 * ════════════════════════════════════════════════════════════════════ */
:root[data-theme="dark"] {
  color-scheme: dark;

  /* Backgrounds */
  --color-bg-page:     var(--charcoal-950);
  --color-bg-surface:  var(--charcoal-900);
  --color-bg-raised:   var(--charcoal-850);
  --color-bg-hover:    var(--charcoal-800);
  --color-bg-selected: #3b2233;
  --color-bg-code:     var(--charcoal-850);
  --color-bg-inverse:  var(--charcoal-900);

  /* Text */
  --color-text-primary:   #e8eaed;
  --color-text-secondary: var(--charcoal-300);
  --color-text-muted:     var(--charcoal-400);
  --color-text-inverse:   #e8eaed;
  --color-text-on-accent: var(--charcoal-950);
  --color-text-on-status: var(--charcoal-950);

  /* Borders */
  --color-border-subtle: var(--charcoal-800);

  /* Ledger (IW-102) */
  --color-ledger-rail: var(--charcoal-700);
  --color-ledger-tick: var(--magenta-500);

  /* Elevation (deeper shadow reads against dark surfaces) */
  --shadow-raised: 0 4px 14px rgba(0, 0, 0, 0.5);

  /* Scrim (IW-435): deeper than the page so the viewer still reads as a layer
     over a surface that is already dark. */
  --color-scrim: rgba(0, 0, 0, 0.82);

  /* Accent (desaturated a step in dark) */
  --color-accent:       #e87fb0;
  --color-accent-hover: #f0a1c6;

  /* Status (lighter, desaturated; tints are dark) */
  --color-status-fault:       var(--red-300);
  --color-status-fault-bg:    var(--red-900);
  --color-status-warning:     var(--amber-300);
  --color-status-warning-bg:  var(--amber-900);
  --color-status-waiting:     var(--grayblue-400);
  --color-status-waiting-bg:  var(--grayblue-900);
  --color-status-resolved:    var(--green-300);
  --color-status-resolved-bg: var(--green-900);

  /* Hypothesis confidence (IW-332): lighter steps of the same three roles, so every band
     keeps its separation from the fault and resolved tones in this theme too, and middle
     keeps its separation from --color-text-secondary, which is --charcoal-300 here. */
  --color-confidence-low:    var(--rust-300);
  --color-confidence-middle: var(--charcoal-100);
  --color-confidence-high:   var(--teal-300);

  /* Registry families (IW-529): the light step of the same four hues. */
  --color-family-boat:       var(--sea-300);
  --color-family-link:       var(--cobalt-300);
  --color-family-controller: var(--violet-300);
  --color-family-lifecycle:  var(--moss-300);

  /* What the operator asked for (IW-665): the light step of the same hue. */
  --color-asked: var(--cobalt-300);

  /* Header controls (IW-530): the same four roles one step down the ramp, over
     the darker inverse surface. */
  --color-header-text-rest:     var(--charcoal-300);
  --color-header-control-hover: var(--charcoal-800);
  --color-header-divider:       var(--charcoal-700);
  --color-header-badge-bg:      var(--charcoal-700);
}
