﻿/* ============================================================================
   Cordis Design System — legacy compatibility shim  (--cordis-* -> --cordis-*)
   ----------------------------------------------------------------------------
   WHAT THIS IS
   The Cordis IDE ("Studio", Cordis.IDE.UI/wwwroot/app.css) declares its own
   token block under the legacy `--cordis-*` prefix. The canonical prefix of
   this design system is `--cordis-*`. This file aliases every legacy token onto
   its canonical counterpart so that existing IDE CSS keeps working unchanged
   while already resolving to the new canonical values wherever the two systems
   agree.

   THIS FILE IS TEMPORARY.
   It exists only to make the IDE migration incremental. It is deleted once the
   last `--cordis-*` / `--cdg-*` reference is gone from application code.
   NEW CODE MUST USE `--cordis-*` DIRECTLY. Never add a token here to serve new
   code; promote it into tokens.css instead.

   LOAD ORDER (this file always last)
     1. css/tokens.css              — canonical --cordis-* tokens
     2. css/cordis.css              — components
     3. css/cordis-studio.css       — Studio/IDE layer
     4. css/compat/cordis-legacy.css — this shim

   The IDE must then DELETE its own `:root` + `.cordis-shell.cordis-dark` token
   blocks from app.css. Leaving them in place would win by source order and the
   shim would have no effect.

   DARK MODE
   Canonical dark is the ATTRIBUTE `[data-theme="dark"]`, set on <html>. The IDE
   drives dark through the CLASS `.cordis-shell.cordis-dark`. Both mechanisms are
   bridged below, so either one works. The page's theme goes on <html>. A scoped
   theme (`data-theme` on an element inside the page, see tokens.css rule 5) works
   because the alias block below is declared on `[data-theme]` as well as `:root`:
   a var() inside a custom property resolves where it is DECLARED, so aliases
   declared on `:root` only would keep the page's values inside that subtree.

   BRAND DECISIONS D1-D5 — ALL DECIDED (2026-08)
   Five values used to differ between the two systems, and each kept its LEGACY
   LITERAL here while the decision was open. None does now: D1/D2/D3 went to the
   canonical palette (the hexes reference/index.html shows), D4 became a
   per-profile token, and D5 was deleted because nothing read it. There is no
   `PENDING D#` marker left in this file. If you are adding one, you are adding a
   held brand value, and it needs a page in the showcase saying so.

   ST SYNTAX TOKENS — HARD CONSTRAINT
   Every `--cordis-st-*` token MUST resolve to a literal 6-digit #rrggbb hex.
   The Monaco shim (cordisMonaco._stTokenColors) parses the COMPUTED value as a
   string and silently drops anything it cannot read as a hex — a `var()` there
   breaks Structured-Text syntax highlighting. They are therefore written as
   literals, never as aliases.
   ========================================================================== */

:root, [data-theme] {
  /* ------------------------------------------------------------------
     Brand palette
     ------------------------------------------------------------------ */
  --cordis-blue: var(--cordis-blue-500);        /* #1F9CD8 — exact match */
  --cordis-green: var(--cordis-green-500);      /* #3BAA35 — exact match */
  --cordis-red: var(--cordis-red-500);          /* #E20717 — exact match */
  --cordis-violet: var(--cordis-type-violet);   /* #8B5CF6 — exact match. User-defined
                                                data types (enumerations, complex types). */

  /* D1, D2, D3 — DECIDED 2026-08: the canonical palette wins, in all three cases.
     The brand is what the specification document (reference/index.html) shows, and
     it shows exactly these hexes; a legacy literal one step away from the brand is
     a value that drifted, not a value anyone chose. Studio therefore moves:
     blue-dark #1A83B8 → #0F6A97 (visible), blue-light #90D3F5 → #8FD3F5 (one step
     in the green channel, invisible), amber #D8941F → #C97A0E (visible, and the
     canonical one is the one that clears 4.5:1 as text). */
  --cordis-blue-dark: var(--cordis-blue-700);
  --cordis-blue-light: var(--cordis-blue-300);
  --cordis-amber: var(--cordis-amber-500);

  /* D5 — DECIDED 2026-08: deleted, not resolved. --cordis-grey #575756 was a warm
     grey with no rung in the cool --cordis-n-* ramp, and the question "which rung
     should it map to" had no answer because NOTHING READ IT. It is declared in
     app.css and in this shim and referenced nowhere in either repository; the one
     place in cordis-ide that considered it — StateNodeWidget.razor.css — rejected
     it in a comment as a near-invisible fixed dark grey and used a theme-aware one
     instead. A token no rule consumes is not a colour decision, it is a leftover.
     Anything that wants a neutral grey takes --cordis-text-muted or a --cordis-n-* rung. */

  /* ------------------------------------------------------------------
     State colours (diagram box accent + tree/palette/SPECIFY glyph)
     IDE-specific — not promoted to the design system.
     ------------------------------------------------------------------ */
  --cordis-state-normal: #98A1AD;
  --cordis-state-flat: #565F6B;

  /* ------------------------------------------------------------------
     Structured-Text syntax tokens — LITERAL HEX ONLY (see header)
     Values mirror the brand palette by hand: keyword = brand blue,
     call/true = brand green, type = type violet, false = brand red,
     number/string = canonical amber (D3 decided), variable/comment = dimmed text.
     If a brand value changes, update these literals in the same commit.
     ------------------------------------------------------------------ */
  --cordis-st-keyword: #1F9CD8;   /* = --cordis-blue-500 */
  --cordis-st-call: #3BAA35;      /* = --cordis-green-500 */
  --cordis-st-type: #8B5CF6;      /* = --cordis-type-violet */
  --cordis-st-true: #3BAA35;      /* = --cordis-green-500 */
  --cordis-st-false: #E20717;     /* = --cordis-red-500 */
  --cordis-st-number: #C97A0E;    /* = --cordis-amber-500 (D3 decided) */
  --cordis-st-string: #C97A0E;    /* = --cordis-amber-500 (D3 decided) */
  /* Variables carry the line and the punctuation around them recedes (issue #183): a macro's target
     path and its argument are what a reader is after, so they take the full body text and the
     delimiters take the dim. Shipped the other way round at first, which made the dots and brackets
     out-read the names on both themes. */
  --cordis-st-variable: #212B36;  /* = light --cordis-text; re-declared per theme below */
  --cordis-st-punctuation: #6B7280; /* light dimmed text; re-declared per theme below */
  --cordis-st-comment: #6B7280;   /* light dimmed text; re-declared per theme below */

  /* ------------------------------------------------------------------
     IDE chrome (deliberately dark in BOTH themes — VS Code style)
     IDE-specific, not promoted to the design system. These must stay
     literal: aliasing them to a semantic --cordis-* surface would make the
     chrome follow the body theme and turn the title bar white in light
     mode. Note --cordis-rail-bg equals the dark --cordis-surface-sunken
     (#171716) but must NOT alias it, because in light mode that token
     resolves to #F7F9FB.
     ------------------------------------------------------------------ */
  --cordis-chrome-bg: #1F1F1E;
  --cordis-rail-bg: #171716;
  --cordis-chrome-fg: #CFCDC8;
  --cordis-chrome-fg-dim: #85837E;
  --cordis-chrome-active: #FFFFFF;
  --cordis-chrome-border: #2C2C2A;
  /* The rules that separate GROUPS INSIDE the chrome, as opposed to the chrome's own outline. Not the
     same job, and they cannot share a value: --cordis-chrome-border draws the seam between two chrome
     surfaces that already differ, so it is deliberately almost invisible, while a divider has to be seen
     against ONE surface with nothing else marking it. At --cordis-chrome-border the activity rail's
     cluster hairlines sat at 1.3:1 on --cordis-rail-bg and could not be made out. The body's
     --cordis-border is not the answer either: it steps with the theme (#E5EAF0 in light) and the chrome
     stays dark in both, so in light mode it would draw a white line across the rail.
     A white FILM rather than a literal, matching --cordis-chrome-hover's idiom just below: the chrome has
     two grounds (--cordis-chrome-bg and the darker --cordis-rail-bg) and a film lands at the same weight
     on each - 1.79:1 and 1.76:1 - where one fixed colour drifts apart. */
  --cordis-chrome-divider: rgba(255, 255, 255, 0.18);
  --cordis-chrome-hover: rgba(255, 255, 255, 0.07);

  /* ------------------------------------------------------------------
     Custom tooltip chip — PROMOTED to css/tokens.css by D10 family merge #6,
     so it is no longer declared here. It was never IDE-specific: nothing
     about a dark chip over a `title` attribute is Blazor's or Studio's, and
     while the four tokens lived here an HMI panel loading only tokens.css +
     cordis.css got the class and never the colours. Token ownership is
     exactly one file per token (TokenOwnershipTests), so promoting them
     meant deleting them here rather than aliasing them.
     ------------------------------------------------------------------ */

  /* ------------------------------------------------------------------
     Status bar
     ------------------------------------------------------------------ */
  /* D4 — DECIDED 2026-08, and the legacy value turned out to be the right one FOR
     STUDIO: white on brand blue, 3.1:1, because Studio's bar is IDE window chrome
     that is glanced at rather than read. This alias is therefore no longer a held
     literal — cordis-studio.css sets --cordis-statusbar-text to white, and Shell keeps
     the dark blue-950 (5.3:1) for a bar that carries information to be parsed. One
     token, two profiles, and this shim just follows it. */
  --cordis-statusbar-fg: var(--cordis-statusbar-text);

  /* ------------------------------------------------------------------
     Work area surfaces (follow the body theme)
     ------------------------------------------------------------------ */
  --cordis-body-bg: var(--cordis-surface);    /* #FFFFFF — exact match in light */
  --cordis-panel-bg: var(--cordis-surface);   /* #FFFFFF — exact match in light */
  /* The workbench chrome surface (explorer / inspector / bottom & terminal pane),
     promoted to tokens.css as --cordis-surface-chrome (cordis-studio #1889). */
  --cordis-sidebar-bg: var(--cordis-surface-chrome);
  --cordis-panel-header-fg: #6B7280;  /* IDE-specific */

  /* Renames per MIGRATION.md ("Studio and MachineControlServer"). The legacy
     literals were #1f2430 / #6b7280 / #e6e8eb; the canonical tokens are the
     norm and carry the (sub-perceptual) numeric drift. */
  --cordis-text-dim: var(--cordis-text-muted);

  /* The focus ring, aliased so a .cordis-* sheet can hang the suite's one ring on
     the element the user perceives as the control. Needed because the universal
     :focus-visible rule in cordis.css can only ring whatever holds DOM focus, and a
     composite control (CordisFilterBox = bordered <label> + borderless <input>) puts
     that on the inner box. */

  /* IDE-specific interaction washes. Translucent so a hover reads on BOTH the
     white editor surfaces and the grey sidebar. No canonical equivalent:
     --cordis-nav-hover is a white wash for dark navigation only. */
  --cordis-hover: rgba(17, 24, 39, 0.05);
  --cordis-selected: rgba(31, 156, 216, 0.12);
  --cordis-selected-fg: #156A96;

  /* Shared document highlighter palette (#30). Amber is reserved for saved bookmarks;
     the reader's native text selection remains blue. Both HTML marks and PDF multiply
     overlays use these opaque paper colours, with dark ink in either shell theme. */
  --cordis-bookmark-mark: var(--cordis-amber-100);
  --cordis-bookmark-mark-hover: color-mix(in srgb, var(--cordis-amber-500) 25%, var(--cordis-amber-100));
  --cordis-bookmark-mark-active: color-mix(in srgb, var(--cordis-amber-500) 55%, var(--cordis-amber-100));
  --cordis-bookmark-mark-fg: var(--cordis-n-900);
  --cordis-bookmark-mark-active-fg: var(--cordis-bookmark-mark-fg);

  /* Diagram tokens (--cdg-*) — promoted to css/tokens.css in 2026-09, when the canvas look became
     shared with the Cordis Server's HMI editor. Only the IDE's class-driven dark restatement is left
     here (in the dark block below). */

  /* ------------------------------------------------------------------
     Scrollbars — theme-neutral grey. IDE-specific, not promoted.
     ------------------------------------------------------------------ */
  --cordis-scrollbar: rgba(128, 128, 128, 0.35);
  --cordis-scrollbar-hover: rgba(128, 128, 128, 0.6);

  /* ------------------------------------------------------------------
     Geometry
     ------------------------------------------------------------------ */
  /* The chrome metrics (titlebar-h, statusbar-h, rail-w) used to be re-declared
     here with a fallback to their own literal. Under one token family that is a
     CYCLE — `--cordis-titlebar-h: var(--cordis-titlebar-h, 40px)` refers to itself,
     which makes the property invalid at computed-value time and the title bar
     height nothing at all. cordis-studio.css is their single owner, which is right
     on the merits too: they are window chrome, and only Studio draws it. */
  /* IDE-specific: width reserved on the right of the title bar for the Windows
     caption buttons when the app owns the native chrome. Not promoted. */
  --cordis-caption-inset: 140px;

  /* Control metrics. These are what make the profile switch mean anything to a
     Blazor component. Two profiles, and since D11 retired density that is the whole
     table:

                   control-h   control-px   control-fs   row-h
       Shell          36px        16px         14px       44px
       Studio         26px         8px         12.5px     26px

     Studio's come from a .cordis-studio block in cordis-studio.css and Shell's from
     tokens.css, so a component that reads these follows the profile for free. Before this family existed every component sheet hardcoded the Studio
     numbers, which is why the profile switch changed the tokens, changed the
     .cds-* primitives, and left every actual component exactly as it was.

     --cordis-tree-row-h now has its Shell value in tokens.css (a tree row IS a
     list row until Studio tightens it) and its Studio value in cordis-studio.css,
     so it is not declared here at all — it is a profile metric, not a legacy name.
     What stays is the small-control step: one definition of "one notch down",
     mirroring the .cordis-btn--sm rule in cordis.css so the two cannot drift. */
  --cordis-control-h-sm: calc(var(--cordis-control-h) - 4px);

  --cordis-radius: var(--cordis-radius-md);     /* 8px — exact match */

  /* Deliberate change per MIGRATION.md: the interface font becomes IBM Plex Sans. */
  /* Was a literal Cascadia Code stack, on the reasoning that a code font is a
     working tool rather than a brand choice (MIGRATION.md). D6 shipped IBM Plex
     Mono, which turns that reasoning inside out: the four readers of this token
     are a copy field, a member row, a numeric input and a type label — none of
     them is code being EDITED, they are values being read, and a value in a form
     should be set in the suite's own mono. The one genuine code surface keeps
     Cascadia and says so where it is declared: .cordis-code in cordis-studio.css. */
  --cordis-mono: var(--cordis-font-mono);
}

/* ============================================================================
   DARK — MECHANISM BRIDGE
   ----------------------------------------------------------------------------
   Canonical dark is `[data-theme="dark"]`; the IDE shell toggles the class
   `.cordis-shell.cordis-dark`. This block mirrors the dark semantic layer of
   tokens.css onto the class, so IDE markup that only sets the class still gets
   canonical dark values.

   MIRROR — keep in sync with the `[data-theme="dark"]` block in css/tokens.css.
   It exists only because this shim may not edit tokens.css to add the class to
   that selector list. Once the IDE sets `data-theme="dark"` on <html>, DELETE
   this block; it is pure duplication.
   ========================================================================= */
.cordis-shell.cordis-dark {
  --cordis-bg:             #1F1F1E;
  --cordis-surface:        #282826;
  --cordis-surface-sunken: #171716;
  --cordis-surface-raised: #3A3936;
  --cordis-surface-chrome: var(--cordis-surface);
  --cordis-border:         #3E3D3A;   /* mirror: see tokens.css for why it was lifted */
  --cordis-border-strong:  #4A4945;
  --cordis-overlay:        rgba(0, 0, 0, 0.60);

  --cordis-text:        #EEEDEA;   /* mirror: see tokens.css */
  --cordis-text-strong: #FFFFFF;
  --cordis-text-muted:  #B4B2AC;
  --cordis-text-faint:  #9D9B95;

  /* Mirrors tokens.css: one accent surface hue in both themes, and only accent
     TEXT steps. See the dark block there for why blue-400 was wrong here. */
  --cordis-primary:         var(--cordis-blue-500);
  --cordis-primary-hover:   var(--cordis-blue-400);
  --cordis-primary-active:  var(--cordis-blue-300);
  --cordis-accent:          var(--cordis-primary);
  --cordis-primary-soft:    #0A2E42;
  --cordis-primary-soft-bd: #135372;
  --cordis-primary-text:    var(--cordis-blue-300);
  /* Was `0 0 0 3px rgba(69, 177, 228, 0.35)` — the 35%-alpha ring that measured
     ~1.4:1 and that tokens.css fixed in 2026-08. This mirror had kept the broken
     version, so IDE markup toggling the class instead of the attribute still got
     an invisible ring. Now it is the same two-token expression as canonical dark. */
  --cordis-focus-color:     var(--cordis-primary);
  --cordis-focus-ring:      0 0 0 2px var(--cordis-focus-color);
  /* Mirrors canonical dark, which stopped stepping this token — see the note in
     css/tokens.css. A mirror that kept #06222F would put a different ink on the same
     blue depending only on which sheet an app happens to load. */
  --cordis-text-on-fill:    #FFFFFF;

  --cordis-nav-bg:      #171716;
  --cordis-nav-text:    #9D9B95;
  --cordis-nav-divider: rgba(255, 255, 255, 0.08);
  --cordis-nav-text-muted: #B4B2AC;
  --cordis-statusbar-bg:   var(--cordis-blue-500);
  --cordis-statusbar-text: var(--cordis-blue-950);

  --cordis-canvas-brand: linear-gradient(215deg, #16232C 0%, #0B4F71 55%, #06222F 100%);
  --cordis-canvas-brand-text: var(--cordis-blue-300);

  --cordis-success:      #5BC454;
  --cordis-success-soft: #12290F;
  --cordis-success-text: #9BE096;
  --cordis-warning:      #D8941F;
  --cordis-warning-soft: #3A3630;
  --cordis-warning-text: #F0C983;
  --cordis-danger:       #F4565C;
  --cordis-danger-soft:  #2E1113;
  --cordis-danger-text:  #FF9EA3;
  --cordis-info:         var(--cordis-blue-400);
  --cordis-info-soft:    #0A2E42;
  --cordis-info-text:    var(--cordis-blue-300);
  --cordis-neutral-soft: #2A2A28;
  --cordis-neutral-text: #A5A39D;

  --cordis-chart-1: var(--cordis-blue-300);
  --cordis-chart-2: var(--cordis-blue-400);
  --cordis-chart-3: var(--cordis-blue-500);
  --cordis-chart-4: var(--cordis-blue-700);
  --cordis-chart-5: #4A4945;
  /* MIRRORS tokens.css; change both. Not removable: this selector is not :root, and a
     var() inside a custom property is substituted where the property is DECLARED -- so
     the :root copy has already resolved to the light border by the time this element
     overrides --cordis-border. */
  --cordis-chart-track: var(--cordis-border);

  --cordis-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.40);
  --cordis-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.45);
  --cordis-shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.55);
}

/* ============================================================================
   DARK — LEGACY TOKEN OVERRIDES
   ----------------------------------------------------------------------------
   Applied for BOTH dark mechanisms. Two reasons this block is unavoidable:
     1. The legacy tokens that keep a LITERAL value (chrome panels, hovers,
        state colours, ST variable/comment) have no theme awareness of their
        own and must be re-declared here.
     2. The legacy tokens that ALIAS a --cordis-* token are custom properties, and
        a var() inside a custom property resolves on the element where it is
        DECLARED. Declared on :root they resolve against :root — so under the
        class mechanism (where the dark --cordis-* values live on the shell, not on
        :root) they would keep their light values unless re-declared here. This
        is exactly why app.css re-declared --cordis-st-variable / -punctuation / -comment in
        its own dark block; that behaviour is preserved.
   The chrome tokens (title bar, activity rail, tooltips) are deliberately NOT
   here: they are dark in both themes.
   ========================================================================= */
[data-theme="dark"],
.cordis-shell.cordis-dark {
  /* The dark surface ladder. The ORDER matters and must be preserved: body-bg
     is not only the editor canvas, it is also the sunken surface of every form
     control and the tab-strip trough, so it stays the DARKEST rung. panel-bg is
     the floating rung (menus, dialogs, toasts, diagram cards) and is brightest. */
  --cordis-body-bg: var(--cordis-bg);        /* #1F1F1E — exact match */
  --cordis-sidebar-bg: var(--cordis-surface-chrome);/* #282826, the panel surface */
  /* IDE-specific: the floating rung, between the panel (#282826) and
     --cordis-surface-raised (#3A3936), which is a step too bright for a menu or a
     diagram card, so no alias. */
  --cordis-panel-bg: #31302E;
  --cordis-panel-header-fg: #A09E98;      /* IDE-specific */

  --cordis-text-dim: var(--cordis-text-muted);   /* canonical dark muted */

  /* IDE-specific interaction washes (one step up from 0.05: on the brighter
     dark panels a 5% white wash is almost imperceptible). */
  --cordis-hover: rgba(255, 255, 255, 0.07);
  --cordis-selected: rgba(31, 156, 216, 0.18);
  --cordis-selected-fg: var(--cordis-blue-light);  /* = --cordis-blue-300 (D2 decided) */

  /* IDE-specific: on dark, "heavier" reads as lighter — flat states brighten,
     normal states dim. */
  --cordis-state-normal: #77756F;
  --cordis-state-flat: #D0CEC8;

  /* ST tokens riding a theme-varying base MUST be re-substituted here, and
     still as LITERAL HEX for the Monaco shim. Value = the dark dimmed text
     (one step dimmer than canonical --cordis-text-muted #B4B2AC, so variables and
     comments recede behind the brand-coloured tokens). The brand-colour ST tokens (keyword/call/type/true/false/
     number/string) are theme-invariant and are not re-declared. */
  --cordis-st-variable: #EEEDEA;     /* = dark --cordis-text */
  --cordis-st-punctuation: #A09E98;
  --cordis-st-comment: #A09E98;

  /* The dark node surfaces are owned by tokens.css ([data-theme="dark"]). They are
     restated here, with the same values, only because this block also answers the
     IDE's CLASS-driven dark (.cordis-shell.cordis-dark), which tokens.css does not
     read. Change them in both places, or better, delete these two with the class. */
  --cdg-node-bg: #363532;
  --cdg-node-border: #6B6A64;
}
