/* ==========================================================================
   METANOVA — design tokens
   --------------------------------------------------------------------------
   Single source of truth for the UI theme.

   THEMEABILITY CONTRACT
   Every colour below derives from a small set of *channel* variables
   (`--*-rgb`, space-separated R G B). Components must never hardcode a
   colour — always reference a semantic token. Changing accent, or swapping
   the dark block for the light block, must be sufficient to retheme the
   entire product with no component edits.

   Channels are stored unwrapped so alpha can be applied at point of use:
       background: rgb(var(--accent-rgb) / 0.44);
   ========================================================================== */

:root {
  /* ---- brand channels -------------------------------------------------- */
  --accent-rgb:        225 29 46;    /* #E11D2E  brand red — identity only  */
  --accent-glow-rgb:   196 24 31;    /* #C4181F  slightly deeper, for glows  */

  /* ---- accent ramp (gradients, charts) --------------------------------- */
  --accent-hi-rgb:     255 74 87;    /* #FF4A57  bar-gradient top            */
  --accent-mid-rgb:    255 85 97;    /* #FF5561  donut arc start             */
  --accent-lo-rgb:     126 12 21;    /* #7E0C15  bar-gradient bottom         */
  --accent-deep-rgb:   142 16 25;    /* #8E1019  donut arc end               */

  /* ---- signal channels (NEVER reuse accent for these) ------------------ */
  --signal-danger-rgb:  229 72 77;   /* #E5484D  alerts. distinct from brand */
  --signal-warning-rgb: 232 145 43;  /* #E8912B  amber. PM ruling 2026-08-10:
                                        was #E5C04D, a dark YELLOW, which
                                        collided with connecting (#EFE94A) at
                                        6px on the status dot. Orange separates
                                        them; connecting stays yellow because
                                        it is transitional, not a warning. */
  --signal-success-rgb:  63 185 80;  /* #3FB950  also "online" status        */
  --signal-info-rgb:     59 125 216; /* #3B7DD8                              */
  --scrim-rgb:            0 0 0;     /* modal/overlay scrim, used at 0.5a   */
  --signal-connecting-rgb: 239 233 74; /* #EFE94A  connecting — a distinct,
                                        brighter hue than amber. Slice 4.2
                                        Step B. Must NOT equal warning.     */
  --on-signal-rgb:      255 255 255; /* text/glyph sitting ON a signal fill   */

  /* ---- canvas component tiers -----------------------------------------
     One family at one PERCEIVED brightness (relative luminance 0.157 each),
     not one HSL lightness — equal L would leave purple ~6.5x darker than
     teal and it would read as near-black. Matched by luminance instead.

     None of the three is green: green belongs to STATUS (online) and FLOW
     (traffic). A tier tint sharing that hue put category, status and flow
     on one pixel value on a single card. Category is the arbitrary claim,
     so category moved. */
  --tier-source-rgb:    25 106 221;  /* #196ADD  sources                     */
  --tier-broker-rgb:   125  77 235;  /* #7D4DEB  metabrokers                 */
  --tier-tool-rgb:      14 124 115;  /* #0E7C73  tools / receivers           */
  --flow-active-rgb:    63 185  80;  /* #3FB950  active flow — stays green   */

  /* ---- HTTP method chips (API Reference) -------------------------------
     Their own tokens. Method chips must NEVER ride tier or signal tokens:
     an HTTP verb has nothing to do with component tiers or system health,
     and the coupling meant PUT silently retinted when broker purple moved.
     Values match today's render; PUT restores the original 4.5 purple. */
  --data-method-get-rgb:     63 185  80;  /* #3FB950 */
  --data-method-post-rgb:    59 125 216;  /* #3B7DD8 */
  --data-method-put-rgb:    139  92 246;  /* #8B5CF6 — pre-swap original    */
  --data-method-delete-rgb: 229  72  77;  /* #E5484D */
  --data-method-patch-rgb:  229 192  77;  /* #E5C04D */

  /* ---- quantitative fill ----------------------------------------------
     Progress bars and similar. NEUTRAL by design — a quantity is not a
     category and must not read as tier identity. Blue is unavailable now
     that --tier-source-rgb is #196ADD. */
  --data-progress-rgb:      195 195 195;  /* #C3C3C3 */

  /* ---- chart / data neutrals ------------------------------------------- */
  --data-neutral-hi-rgb: 201 206 212; /* #C9CED4  metadata bar top           */
  --data-neutral-lo-rgb:  75  80  87; /* #4B5057  metadata bar bottom        */
  --data-track-rgb:       29  32  37; /* #1D2025  unfilled bar track         */
  --axis-rgb:             42  46  51; /* #2A2E33  chart axis line            */

  /* ---- typography ------------------------------------------------------ */
  --font-display: 'METANOVA Display', sans-serif;  /* wordmarks only        */
  --font-ui:      system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono:    ui-monospace, 'SF Mono', Menlo, monospace;

  /* ---- geometry -------------------------------------------------------- */
  --rail-w:        64px;
  --topbar-h:      66px;
  --content-x:     97px;   /* content column left edge                      */
  --rail-slot:     68px;   /* icon / rail-letter pitch                      */
  --radius-card:   10px;
  --radius-ctl:     7px;
  --hairline:       1px;
  --statusbar-h:   41px;

  /* ---- button ladder — brightness, never colour -----------------------
     Reuses the existing surface/border/text tokens; only the pending border
     is new. Verified across every dark surface: READY border holds 1.47-1.88
     even on --surface-inset, PENDING holds 8.8-11.3. */
  --btn-border-pending:  #C3C3C3;   /* light border — the ONLY thing that lifts on   */
                                    /* PENDING, since READY already carries the     */
                                    /* brightest label token available.             */

  /* ---- corner-M lockup geometry ----------------------------------------
     The M is shared: METANOVA reads DOWN the rail, the product name reads
     ACROSS the top bar. These position the shared glyph and the wordmark
     that continues from it. Collapsed values are in the [data-rail] block. */
  --rail-w-collapsed: 40px;
  --lockup-m-x:       14px;
  --lockup-m-h:       30px;
  --lockup-wm-x:      69px;
}

/* ==========================================================================
   DARK  (default)
   ========================================================================== */
:root,
[data-theme='dark'] {
  /* Tells the browser to paint native widget chrome dark: number-input
     spinners, date/colour pickers, select dropdown lists, scrollbars.
     Those parts are drawn by the browser, not by CSS — without this they
     render light on a dark surface no matter what the surrounding rules
     say. This is the fix for that whole category; do not chase individual
     ::-webkit-* pseudo-elements. */
  color-scheme: dark;

  --surface-page:    #08090B;
  --surface-rail:    #0F1115;
  --surface-topbar:  #0E1013;
  --surface-card:    #121417;
  --surface-raised:  #1C1F24;
  --surface-active:  #17191E;   /* selected rail slot                       */
  --surface-inset:   #212429;   /* donut track, inset wells                 */

  --border-hairline: #232629;
  --border-strong:   #3A3F45;

  --text-primary:    #E9EDF2;
  --text-secondary:  #C0C2C4;
  --text-muted:      #7E858C;
  --text-disabled:   #565C63;
  --icon-idle:       #6B7178;   /* unselected rail icon                     */

  --rail-letter:     var(--text-secondary);   /* #C0C2C4 rail stack        */
  --wordmark-silver: #D5D9E0;                 /* wordmark letters, BRAND-SPEC */
}

/* ==========================================================================
   LIGHT
   Complete second value set (0.4.18, PM direction). DARK stays the default
   and the product identity; light is the per-user opt-in. Signal, tier and
   accent channels are NOT overridden — a signal stays the same signal in
   both palettes. Only surfaces, borders, text, and the dark-tuned data
   neutrals take light values.
   ========================================================================== */
[data-theme='light'] {
  color-scheme: light;

  --surface-page:    #F4F5F7;
  --surface-rail:    #FFFFFF;
  --surface-topbar:  #FFFFFF;
  --surface-card:    #FFFFFF;
  --surface-raised:  #F0F1F3;
  --surface-active:  #E9EBEE;   /* selected rail slot                       */
  --surface-inset:   #E4E6EA;   /* donut track, inset wells, form fields    */

  --border-hairline: #E2E4E8;
  --border-strong:   #C6CAD0;

  --text-primary:    #16181C;
  --text-secondary:  #3F454C;
  --text-muted:      #6B7178;
  --text-disabled:   #A1A7AE;
  --icon-idle:       #8A9098;   /* unselected rail icon                     */

  --rail-letter:     var(--text-secondary);
  --wordmark-silver: #3F454C;
  --scrim-rgb:       15 17 21;   /* light theme scrims from graphite, not black */

  /* dark-tuned data tokens take light counterparts */
  --data-track-rgb:      223 225 229;  /* #DFE1E5  unfilled bar track       */
  --axis-rgb:            208 211 216;  /* #D0D3D8  chart axis line          */
  --data-neutral-hi-rgb:  63  69  76;  /* #3F454C  metadata bar top         */
  --data-neutral-lo-rgb: 158 164 171;  /* #9EA4AB  metadata bar bottom      */
  --data-progress-rgb:    90  96 104;  /* #5A6068  quantitative fill        */

  /* PENDING lifts DARK on a light surface — the ladder is brightness
     DISTANCE from the resting border, not a fixed direction */
  --btn-border-pending:  #16181C;
}

/* ==========================================================================
   COLLAPSED RAIL
   Narrows to icons only. The corner M STAYS and the top-bar wordmark STAYS —
   both readings of the shared M survive collapse, simply translated left.
   The stacked METANOVA letters hide: at this width a stacked wordmark stops
   reading as a word and becomes texture; the M alone carries identity.
   Hiding the letter column is a PRODUCT-LOCAL selector, not a brand rule.
   ========================================================================== */
[data-rail='collapsed'] {
  --rail-w:      var(--rail-w-collapsed);
  --lockup-m-x:   9px;
  --lockup-m-h:  22px;
  --lockup-wm-x: 45px;
}
[data-rail='collapsed'] .mn-rail-item svg { width: 18px; height: 18px; }

/* ==========================================================================
   FOCUS
   Keyboard focus must be visible on every interactive chrome control.
   2px minimum per WCAG 2.2 focus appearance, and offset so the ring reads
   as distinct from the accent BORDER that marks an actionable control.
   ========================================================================== */
.mn-rail-item:focus-visible,
.mn-nav-item:focus-visible,
.mn-btn:focus-visible,
.mn-lockup:focus-visible {
  outline: 2px solid rgb(var(--accent-rgb));
  outline-offset: 2px;
  border-radius: var(--radius-ctl);
}
/* rail slots are edge-to-edge — inset the ring so it is not clipped */
.mn-rail-item:focus-visible { outline-offset: -2px; }

/* ==========================================================================
   CARD EDGE HIGHLIGHT
   Reads as a single light source above the card: bright across the top,
   spilling a little down both sides, nothing at the bottom.
   Pure gradients — no filters, no box-shadow, no blur.
   ========================================================================== */
.mn-card {
  position: relative;
  background: var(--surface-card);
  border: var(--hairline) solid var(--border-hairline);
  border-radius: var(--radius-card);
  overflow: hidden;
}

/* top edge — horizontal, fades to nothing at both corners */
.mn-card::before {
  content: '';
  position: absolute;
  inset: 0 10px auto 10px;
  height: 3px;
  pointer-events: none;
  background: linear-gradient(
    90deg,
    transparent,
    rgb(var(--accent-glow-rgb) / 0.20) 18%,
    rgb(var(--accent-glow-rgb) / 0.44) 50%,
    rgb(var(--accent-glow-rgb) / 0.20) 82%,
    transparent);
}

/* both sides — vertical, decays over ~50% of card height */
.mn-card::after {
  content: '';
  position: absolute;
  inset: 8px 0 auto 0;
  height: 50%;
  max-height: 175px;
  pointer-events: none;
  background:
    linear-gradient(180deg,
      rgb(var(--accent-glow-rgb) / 0.165),
      rgb(var(--accent-glow-rgb) / 0.085) 45%,
      transparent) left  / 1.6px 100% no-repeat,
    linear-gradient(180deg,
      rgb(var(--accent-glow-rgb) / 0.165),
      rgb(var(--accent-glow-rgb) / 0.085) 45%,
      transparent) right / 1.6px 100% no-repeat;
}

/* ==========================================================================
   CONTROLS  —  THE BUTTON STANDARD

   THREE STATES, distinguished by BRIGHTNESS. No accent, no colour, no solid
   fills. A button never carries red: red on a button reads as an error, and
   the accent budget is spent on identity and alerts.

   The FILL never changes. Only the BORDER and the LABEL move.

     IDLE      disabled.  hairline border  +  muted label
     READY     enabled, nothing staged.  strong border  +  bright label
     PENDING   enabled, work waiting.    LIGHT border   +  bright label

   IDLE -> READY lifts BOTH border and label. READY -> PENDING lifts the
   BORDER ONLY: READY already carries --text-primary, the brightest label
   available, so pending cannot out-brighten it and gains an EDGE instead.

   Verified on every dark surface. READY's border holds 1.47-1.88 contrast
   even on --surface-inset; PENDING holds 8.8-11.3. IDLE deliberately fades
   on lighter surfaces — a disabled control should recede, and its label
   still marks that something is there.

   The test is unchanged: IS THERE SOMETHING PENDING THAT PRESSING THIS
   WOULD COMMIT?

     Apply, 0 edits      -> READY        Apply, 3 edits  -> PENDING
     Update, 1 staged    -> PENDING      + Add Group     -> READY
     Change Project      -> READY        Cancel          -> READY always

   Because no button uses accent, THE SURFACE RULE NO LONGER APPLIES TO
   BUTTONS — brightness cannot collide with content the way a colour can.
   The rule still governs non-button affordances; see below.
   ========================================================================== */
.mn-btn {
  background: var(--surface-raised);
  border: 1.2px solid var(--border-strong);
  border-radius: var(--radius-ctl);
  color: var(--text-primary);
  font: 13.5px/1 var(--font-ui);
  padding: 11px 18px;
}
.mn-btn--pending  { border-color: var(--btn-border-pending); }
.mn-btn:disabled  { border-color: var(--border-hairline); color: var(--text-disabled); cursor: default; }

/* ---- THE SURFACE RULE — non-button affordances ------------------------
   A COLOUR CANNOT MARK A CONTROL ON A SURFACE WHERE THAT COLOUR IS THE
   CONTENT. Buttons are now exempt by construction (they use brightness, not
   colour). It still governs anything that DOES signal with colour — status
   chips, inline severity marks, indicator bars.

     Dashboard    red is ambient instrument colour, so in-dashboard alert
                  severities use AMBER; red would vanish into the surface.
     Alerts page  red IS the content, so nothing else on that surface may
                  claim red.

   Judge by what the colour already means on THAT surface, never by
   precedent from another page. Does NOT apply to form controls. */

/* ==========================================================================
   SELECTION  —  the third state, not a button appearance

   A selected toggle or segment reports STATE. It is neither PASSIVE nor
   PENDING, so it sits outside the two button appearances entirely — the
   same category as a checked box.

   Selection is NEUTRAL: raised fill + strong border. It does not take
   accent, because accent means "work waiting to commit" and a selection has
   committed nothing.

   EXCEPTION — selection that is NAVIGATION (segmented page switchers, sub-
   tabs) follows the nav grammar instead: bright label + accent INDICATOR
   (underline or bar), never accent fill or border. Same rule as .mn-nav-item
   and .mn-rail-item — the accent marks the indicator, never the control.
   ========================================================================== */
.mn-toggle                  { background: var(--surface-raised); border: 1px solid var(--border-hairline); color: var(--text-muted); }
.mn-toggle[aria-pressed='true'],
.mn-toggle[aria-selected='true'] {
  background: var(--surface-active);
  border-color: var(--border-strong);
  color: var(--text-primary);
}

/* ==========================================================================
   FORM CONTROLS
   Native checkbox / radio / range are tinted via accent-color rather than
   rebuilt as primitives: one property, fully tokenised, and it keeps the
   native keyboard and AT behaviour a custom primitive would have to
   re-implement.

   THE SURFACE RULE DOES NOT APPLY HERE. That rule governs colour used to
   mark a control as pending/actionable. A checked box reports STATE, not
   affordance, so accent is correct even on surfaces where accent is also
   content. Do not neutralise checkboxes on red-content pages.
   ========================================================================== */
input[type='checkbox'],
input[type='radio'],
input[type='range'] {
  accent-color: rgb(var(--accent-rgb));
}

/* A checkbox or radio WITH ITS LABEL is a form control, not a button.
   It takes NO button treatment — no border, no filled container,
   transparent background. Wrapping one in an accent border makes it read
   as an error or a validation failure. The accent belongs to the tick
   itself (above) and nowhere else in the control. */
.mn-check {
  background: transparent;
  border: 0;
  color: var(--text-primary);
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

/* Native file inputs render with a WHITE button on every browser. Style the
   selector button to the passive control treatment and keep the field
   itself transparent, or it punches a white hole in a dark surface. */
input[type='file'] {
  background: transparent;
  color: var(--text-muted);
  font: 13px/1 var(--font-ui);
}
input[type='file']::file-selector-button {
  background: var(--surface-raised);
  border: 1.2px solid var(--border-strong);
  border-radius: var(--radius-ctl);
  color: var(--text-primary);
  font: 13px/1 var(--font-ui);
  padding: 8px 14px;
  margin-right: 12px;
  cursor: pointer;
}
input[type='file']::file-selector-button:hover { border-color: var(--text-muted); }

/* Any native control that ships a light default — file, date, colour,
   select — must be tokenised. A white box on a dark surface is always a
   defect, never a style choice. Widget SUB-PARTS the browser paints itself
   (spinners, pickers, dropdown lists) are handled by color-scheme above,
   not here. */
select, input, textarea { background: var(--surface-inset); color: var(--text-primary); }

/* ==========================================================================
   OVERLAY
   ========================================================================== */
.mn-scrim { background: rgb(var(--scrim-rgb) / 0.5); }

/* ==========================================================================
   CHROME
   ========================================================================== */
.mn-rail   { width: var(--rail-w); background: var(--surface-rail); }
.mn-topbar { height: var(--topbar-h); background: var(--surface-topbar); }

/* THE CORNER IS OPEN.
   The rail divider does NOT cross the top bar. It begins at the top bar's
   lower edge and runs down, continuous with the grey hairline that edges the
   bar. A line drawn through the top-bar band would cut the corner M off from
   the wordmark and destroy the horizontal reading.
   The hairline likewise does NOT cross the rail — it starts at the rail edge
   and runs right. Both bars meet at an open corner with the M sitting in it. */
.mn-rail-divider {
  position: absolute; top: var(--topbar-h); bottom: 0; left: var(--rail-w);
  width: var(--hairline); background: var(--border-hairline);
}

/* grey edge along the bottom of the top bar — from the rail edge rightward */
.mn-topbar { border-bottom: var(--hairline) solid var(--border-hairline); }

/* accent glow on the rail's right edge. Builds downward, brightest ~80%
   down. MUST start below the top bar — a red edge running past the corner
   M would cut between its two readings (METANOVA down, product across). */
.mn-rail-divider::after {
  content: '';
  position: absolute;
  top: 0; bottom: 0; left: 0;   /* parent already starts below the bar */
  width: 2px;    /* the GLOW is 2px; the divider beneath is 1px hairline */
  pointer-events: none;
  background: linear-gradient(180deg,
    transparent,
    rgb(var(--accent-glow-rgb) / 0.03) 12%,
    rgb(var(--accent-glow-rgb) / 0.13) 45%,
    rgb(var(--accent-glow-rgb) / 0.28) 62%,
    rgb(var(--accent-glow-rgb) / 0.50) 80%,
    rgb(var(--accent-glow-rgb) / 0.42) 93%,
    rgb(var(--accent-glow-rgb) / 0.30));
}

/* SELECTION RULE
   Selected = bright (--text-primary). Unselected = muted (--text-muted).
   Accent marks the INDICATOR ONLY — the underline or rail bar — never the
   label or icon itself. Colouring a selected item red makes accent carry two
   meanings at once and drowns the interface in red. */
/* ==========================================================================
   PAGE TITLE
   ONE treatment for the main section heading on every tab. Pages must render
   this class, never their own heading styles — consistency by construction,
   so a new page cannot drift.

   Standard is the System-tab heading (Tenants / Projects / Users), named by
   PM. This SUPERSEDES the letterspaced caps "DASHBOARD" in dashboard_v2.png;
   that render is no longer authoritative on title treatment.

   Section sub-headers (e.g. the CRITICAL band on Alerts) are deliberately
   distinct from page titles and do not use this class.
   ========================================================================== */
.mn-page-title {
  font: 500 13px/1.2 var(--font-ui);
  color: var(--text-primary);
  letter-spacing: 0;
  text-transform: none;
}

.mn-nav-item               { color: var(--text-muted); font: 15.4px/1 var(--font-ui); }
.mn-nav-item[aria-current] { color: var(--text-primary); }
.mn-nav-item[aria-current]::after {
  content: ''; display: block; height: 3px; margin-top: 21px;
  background: rgb(var(--accent-rgb));
}

/* rail items follow the same rule: bright icon + accent bar, never a red icon */
.mn-rail-item               { color: var(--icon-idle); }
.mn-rail-item[aria-current] { color: var(--text-primary); background: var(--surface-active); }
.mn-rail-item[aria-current]::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0;
  width: 3px; background: rgb(var(--accent-rgb));
}
