/* ============================================================================
 * Canopy · Figtree webfont
 * NOTE: the Canopy source ships self-hosted Figtree woff2 (400/500/600/700),
 * but no binaries were included with the codebase, so this design system
 * pulls Figtree from Google Fonts. Swap this @import for self-hosted
 * @font-face rules when the woff2 files are available.
 * ==========================================================================*/
@import url('https://fonts.googleapis.com/css2?family=Figtree:wght@400;500;600;700&display=swap');
/* ============================================================================
 * Canopy · Color tokens — CultureMonkey Platform (namespace cm-)
 * Primitive ramps (green-tinted neutral, brand green, status, data-viz) +
 * the SEMANTIC layer. Components read SEMANTIC vars only, never primitives.
 * All colors measured vs #ffffff for WCAG 2.2 AA per pairing.
 * ==========================================================================*/
:root {
  /* primitive · neutral (green-tinted, never blue-black) */
  --cm-neutral-0:   #ffffff;  /* app base */
  --cm-neutral-25:  #fbfcfb;  /* sidebar */
  --cm-neutral-50:  #f7f9f8;  /* wells, table header */
  --cm-neutral-100: #eef1ef;  /* chips, hover wash */
  --cm-neutral-200: #e3e8e4;  /* border default */
  --cm-neutral-300: #d3d9d4;  /* border strong, input border */
  --cm-neutral-400: #b6c0b8;  /* radio/checkbox rim */
  --cm-neutral-500: #8f998f;  /* placeholder / disabled only (never running text) */
  --cm-neutral-600: #67726b;  /* muted text — 5.0 AA — NOT #6f7a73 */
  --cm-neutral-700: #4b554f;  /* body text — 7.8 */
  --cm-neutral-800: #38413b;  /* strong body — 10.6 */
  --cm-neutral-900: #19211c;  /* headings — 16.5 */

  /* primitive · green / accent (brand-anchored) */
  --cm-green-50:  #eef5ee;  /* soft wash */
  --cm-green-100: #d9eedd;  /* selected wash, success soft */
  --cm-green-500: #0eb969;  /* brand mark, progress fills (non-text) */
  --cm-green-600: #0a9a56;  /* large icons, >=24px text — 3.6 */
  --cm-green-700: #0c7a43;  /* action.primary, solid buttons, links — 5.4 */
  --cm-green-800: #0a5c36;  /* accent text, active nav, focus ring — 8.1 */
  --cm-green-900: #074d2a;  /* key-line / pressed */

  /* primitive · status (color + label/icon, never color alone) */
  --cm-warning-icon: #b8851f;
  --cm-warning-text: #7a4f0e;  /* 7.1 */
  --cm-warning-soft: #faf2dd;
  --cm-danger-solid: #b42318;  /* 6.6 */
  --cm-danger-text:  #99231a;
  --cm-danger-soft:  #fbeae8;
  --cm-danger-soft-strong: #fdeee8;  /* high-risk fill */
  --cm-danger-text-strong: #93421f;
  --cm-info-solid:   #1a51b8;  /* 7.2 */
  --cm-info-text:    #1a51b8;
  --cm-info-soft:    #e9f0fc;
  --cm-violet:       #6b5fc9;  /* AI OUTPUT ONLY — never elsewhere */
  --cm-violet-soft:  #efedf9;
  --cm-violet-text:  #4f4399;
  --cm-teal:         #3f93a3;  /* case stage: concluding */
  --cm-teal-soft:    #e8f2f4;
  --cm-teal-text:    #2a6470;

  /* primitive · data-viz */
  --cm-viz-diverge-neg2: #b85036;
  --cm-viz-diverge-neg1: #f0d8c0;
  --cm-viz-diverge-zero: #eef1ef;
  --cm-viz-diverge-pos1: #cfe6d6;
  --cm-viz-diverge-pos2: #0a7a4a;
  --cm-viz-cat-1: #0a7a4a;
  --cm-viz-cat-2: #3565c0;
  --cm-viz-cat-3: #b8771f;
  --cm-viz-cat-4: #6b5fc9;
  --cm-viz-cat-5: #3f93a3;
  --cm-viz-cat-6: #a84e6e;

  /* SEMANTIC — the only layer components should read */
  --cm-bg-app:     var(--cm-neutral-0);
  --cm-bg-sidebar: var(--cm-neutral-25);
  --cm-bg-well:    var(--cm-neutral-50);
  --cm-bg-hover:   var(--cm-neutral-100);

  --cm-text-primary:  var(--cm-neutral-900);
  --cm-text-strong:   var(--cm-neutral-800);
  --cm-text-body:     var(--cm-neutral-700);
  --cm-text-muted:    var(--cm-neutral-600);  /* 5.0 AA — never #6f7a73 */
  --cm-text-disabled: var(--cm-neutral-500);
  --cm-text-accent:   var(--cm-green-800);
  --cm-text-on-accent:#ffffff;

  --cm-border-default: var(--cm-neutral-200);
  --cm-border-strong:  var(--cm-neutral-300);
  --cm-border-control: var(--cm-neutral-300);
  --cm-rim:            var(--cm-neutral-400);

  /* tenant theming (white-label) overrides ONLY these ~6 vars */
  --cm-action-primary:       var(--cm-green-700);
  --cm-action-primary-hover: #0a6b3b;
  --cm-action-keyline:       var(--cm-green-900);
  --cm-action-pressed:       var(--cm-green-900);
  --cm-accent-wash:          var(--cm-green-50);
  --cm-accent-wash-selected: #f2f9f4;

  /* success ALIASES the accent ramp (always pair with checkmark + copy) */
  --cm-success-solid: var(--cm-green-700);
  --cm-success-text:  var(--cm-green-800);
  --cm-success-soft:  var(--cm-green-100);

  /* focus ring — 2.5px green.800 + mandatory 2px offset gap, never suppressed */
  --cm-focus-ring:        var(--cm-green-800);
  --cm-focus-ring-width:  2.5px;
  --cm-focus-ring-offset: 2px;
}
/* ============================================================================
 * Canopy · Typography tokens — Figtree only (400/500/600/700)
 * No em-dash. No ALL-CAPS (tracked sentence-case eyebrows allowed).
 * No monospace: IDs stay in Figtree with tabular-nums.
 * Type scale exposed as size / line / weight / tracking triplets per role.
 * ==========================================================================*/
:root {
  --cm-font-family: 'Figtree', system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* weight system: 400 body · 500 nav/inactive · 600 headings/labels/buttons · 700 active */
  --cm-weight-regular:  400;
  --cm-weight-medium:   500;
  --cm-weight-semibold: 600;
  --cm-weight-bold:     700;

  /* type scale — page heroes (rare) */
  --cm-display-size: 31px;  --cm-display-line: 38px;  --cm-display-weight: 600;  --cm-display-tracking: -0.018em;
  /* employee page titles */
  --cm-display-sm-size: 25px;  --cm-display-sm-line: 32px;  --cm-display-sm-weight: 600;  --cm-display-sm-tracking: -0.015em;
  /* admin page titles, case ID */
  --cm-heading-lg-size: 21px;  --cm-heading-lg-line: 28px;  --cm-heading-lg-weight: 600;  --cm-heading-lg-tracking: -0.01em;
  /* card / modal titles */
  --cm-heading-size: 17px;  --cm-heading-line: 24px;  --cm-heading-weight: 600;
  /* employee reading text */
  --cm-body-lg-size: 16px;  --cm-body-lg-line: 24px;  --cm-body-lg-weight: 400;
  /* admin default, card descriptions */
  --cm-body-size: 14px;  --cm-body-line: 20px;  --cm-body-weight: 400;
  /* meta rows, compact tables */
  --cm-body-sm-size: 13px;  --cm-body-sm-line: 18px;  --cm-body-sm-weight: 400;
  /* field labels (sentence case) */
  --cm-label-size: 13px;  --cm-label-line: 16px;  --cm-label-weight: 600;
  /* numerals in tables / KPIs (tabular) */
  --cm-data-size: 13px;  --cm-data-line: 18px;  --cm-data-weight: 500;
  /* tracked eyebrow (group labels, sub-nav headers) — sentence case, never ALL-CAPS */
  --cm-eyebrow-size: 11px;  --cm-eyebrow-weight: 700;  --cm-eyebrow-tracking: 0.06em;
}
/* ============================================================================
 * Canopy · Spacing · Radius · Elevation tokens
 * Spacing on a 4px base. Radius: no pill-everything. Elevation is border-first:
 * a shadow means "floats above the page", never decoration on an in-flow card.
 * ==========================================================================*/
:root {
  /* spacing (4px base) */
  --cm-space-1:  4px;
  --cm-space-2:  8px;
  --cm-space-3:  12px;
  --cm-space-4:  16px;   /* card pad compact */
  --cm-space-6:  24px;   /* card pad comfortable, section gaps */
  --cm-space-8:  32px;
  --cm-space-12: 48px;

  /* radius */
  --cm-radius-sm:   6px;    /* badges, chips, kbd */
  --cm-radius-md:   9px;    /* buttons, inputs, selects */
  --cm-radius-lg:   12px;   /* cards, radio-cards, wells */
  --cm-radius-xl:   16px;   /* modals, drawers, page frames */
  --cm-radius-full: 999px;  /* avatars, radio dots only */

  /* elevation (border-first) */
  --cm-elevation-1: 0 1px 2px rgba(25, 33, 28, 0.06);    /* raised: cards lifting slightly */
  --cm-elevation-2: 0 4px 16px rgba(25, 33, 28, 0.12);   /* overlay: dropdowns, toasts, tooltips */
  --cm-elevation-3: 0 12px 32px rgba(25, 33, 28, 0.18);  /* modal: modals, drawers, palette */

  /* density: control + table-row heights per register */
  --cm-control-comfortable: 48px;  /* employee */
  --cm-row-comfortable:     48px;
  --cm-control-compact:     38px;  /* admin */
  --cm-row-compact:         36px;
}
/* ============================================================================
 * Canopy · Motion tokens
 * Motion is functional: state feedback only, 120-240ms. No entrance
 * choreography or parallax. prefers-reduced-motion collapses durations to 0.
 * ==========================================================================*/
:root {
  --cm-duration-fast: 120ms; /* @kind other */
  --cm-duration-base: 180ms; /* @kind other */
  --cm-duration-slow: 240ms; /* @kind other */
  --cm-ease-standard: cubic-bezier(0.2, 0.6, 0.2, 1); /* @kind other */
  --cm-ease-exit:     cubic-bezier(0.4, 0, 1, 1); /* @kind other */
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --cm-duration-fast: 0ms; /* @kind other */
    --cm-duration-base: 0ms; /* @kind other */
    --cm-duration-slow: 0ms; /* @kind other */
  }
}
/* ============================================================================
 * Canopy · Icon glyph tokens
 * CSS-mask glyphs: recolor via background-color (no inline SVG per instance).
 * These cover the chrome glyphs the system draws itself (chevron, check).
 * Product iconography is a stroked line-icon set — see readme ICONOGRAPHY.
 * ==========================================================================*/
:root {
  --cm-icon-chevron: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>"); /* @kind other */
  --cm-icon-chevron-muted: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2367726b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>"); /* @kind other */
  --cm-icon-check: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'><path d='M5 13l5 5L20 7'/></svg>"); /* @kind other */
}
/* ============================================================================
 * Canopy — CultureMonkey Platform design system (namespace cm-)
 * Vendored from the design-system source into this app's asset pipeline so
 * the app is self-contained at runtime (no link to the design-system
 * checkout). Token files below are copied verbatim from `tokens/`.
 *
 * Font substitution flag (per the source's own SKILL.md): the design system
 * self-hosts Figtree woff2 in its original codebase, but shipped no font
 * binaries, so tokens/fonts.css pulls Figtree from Google Fonts instead.
 * That is intentionally preserved as-is here — swap in self-hosted
 * @font-face rules if/when offline operation is required.
 *
 * Sprockets (not browser @import) concatenates these at asset-compile time.
 * ==========================================================================*/

/*






 */
/*
 * Adoption Engine — restyled onto Canopy, the CultureMonkey Platform design
 * system. Canopy tokens are vendored under canopy/ and required first;
 * everything below reads the SEMANTIC layer only (--cm-text-muted,
 * --cm-action-primary, --cm-border-default, ...), never a primitive ramp
 * step or a raw hex value. Register: admin — compact desktop, 13-14px type,
 * 36-40px controls, a 56px dark top nav (see "App shell" below) with an
 * optional 48px breadcrumb sub-bar, full-width content beneath.
 *



 */

/* ---------------------------------------------------------------------
   Light re-skin (2026-08) — "make the background to white, the dark is
   not good" (user, verbatim). Reverses the dark reskin two commits back
   (d35fa93 tokens, 36a6777 charts, b5b7d0d sign-in) onto Canopy's light
   semantic layer. This is the SAME override point those commits used for
   the accent/dark surface stack, just pointed back at light values — the
   app bar/menus/dialog/palette/tabs architecture is untouched, only what
   its tokens resolve to changes again.

   Brand hue is still #1CA3DE. It cannot itself carry text or bound a
   control — 2.86:1 on white, under both the 4.5:1 text floor and the
   3.0:1 UI-component floor — so it's used only where a large filled area
   carries the meaning (chart series, meter fills, the busiest heatmap
   cell); text, actions, focus and key-lines take the darkened steps:
     500  #1ca3de  brand, large fills only     2.86:1  (never text)
     700  #1475a0  actions, white label on it  5.14:1
     800  #126c93  accent text, focus ring     5.85:1
     900  #0f5a7a  key-lines, pressed          7.60:1

   The three-tier dark surface stack (canvas/raised/elevated) collapses
   back to two: a tinted canvas behind the content, and one flat white for
   everything that sits on it — cards, tables AND chrome alike. --cm-bg-
   elevated stays defined only because navigation.css's app bar/menu/
   dialog/palette rules already read it (untouched, per the brief); on
   light it's just an alias for the same white every card uses — the
   dark build's "chrome one step lighter than cards" distinction doesn't
   exist here, Canopy never had it. Warning/danger/info tokens are no
   longer overridden at all: Canopy's own vendored ones
   (canopy/tokens/colors.css) are already calibrated for a white ground
   and were only ever shadowed by the dark reskin's lightened copies.

   Every pairing below is COMPUTED, not eyeballed — WCAG relative-
   luminance contrast ratio, script at
   /private/tmp/claude-501/-Users-siva-work-git-culturemonkey/
   276a5372-16da-4aea-9a19-11b647f8fd3c/scratchpad/contrast.js. Full
   report re-run against every surface a token actually appears on:
     text-primary  #19211c on white              16.46:1
     text-primary  #19211c on canvas #f1f7fa      15.23:1
     text-strong   #38413b on white               10.57:1
     text-body     #4b554f on white/canvas         7.74 /  7.16 : 1
     text-muted    #67726b on white/canvas         5.00 /  4.63 : 1
     text-accent/focus-ring  #126c93 on white/canvas/accent-wash
                                                    5.85 /  5.41 /  5.41 : 1
     white on action-primary/-hover/-pressed (700/800/900)
                                                    5.14 /  5.85 /  7.60 : 1
     warning-text #7a4f0e on white/warning-soft    7.11 /  6.37 : 1
     danger-text  #99231a on white/danger-soft     8.05 /  6.91 : 1
     danger-text-strong #93421f on danger-soft-strong              6.11:1
     white on danger-solid #b42318                                 6.57:1
     info-text #1a51b8 on info-soft/white          6.29 /  7.21 : 1
     border-default #e3e8e4 on white (decorative, hairline)        1.24:1
   Decorative-only pairings (hairlines, disabled text) are deliberately
   sub-AA, same "borders don't need to pop" logic that's always applied
   here — never a text/UI pairing. */
:root {
  --cm-brand-500: #1ca3de;
  --cm-brand-700: #1475a0;
  --cm-brand-800: #126c93;
  --cm-brand-900: #0f5a7a;

  --cm-action-primary:       var(--cm-brand-700);
  --cm-action-primary-hover: var(--cm-brand-800);
  --cm-action-keyline:       var(--cm-brand-900);
  --cm-action-pressed:       var(--cm-brand-900);
  --cm-text-accent:          var(--cm-brand-800);
  --cm-focus-ring:           var(--cm-brand-800);
  --cm-accent-wash:          #edf8fc;
  --cm-accent-wash-selected: #e4f4fb;

  /* Deliberate deviation from Canopy's own hard rule ("success = green").
     The user was explicit: "not green should be there. The whole theme is
     Blue." Canopy's success tokens (--cm-success-solid/-text/-soft) are
     ALIASES of the green ramp at the source (canopy/tokens/colors.css) —
     overriding them here, the same override point tenant theming already
     uses for --cm-action-*, is what turns every consumer of "success"
     (status-chip--active, flash--notice, health-badge--healthy, the good
     step of the score meter) blue instead of touching each component
     individually. Warning stays amber and critical stays red — those come
     straight from Canopy's own vendored tokens now (already light-
     calibrated, see the file-header contrast table) and are untouched. */
  --cm-success-solid: var(--cm-brand-700);
  --cm-success-text:  var(--cm-brand-800);
  --cm-success-soft:  var(--cm-accent-wash);

  /* Surface hierarchy — "lot of whites are there" (user, from the original
     brief; still true). --cm-bg-app stays Canopy's white (cards, tiles and
     tables keep it, so their text keeps every documented AA margin), but
     the page CANVAS behind those cards, the sidebar rail and every well/
     table-header sit on a tinted blue rather than blending into the same
     white as the content floating on them. Checked against --cm-text-muted
     (the tightest-margin text color in the app, 5.0:1 on pure white) and
     keeps >=4.6:1: bg-canvas/-well/-sidebar #f1f7fa vs muted 4.63:1. */
  --cm-bg-canvas:  #f1f7fa;
  --cm-bg-sidebar: #f1f7fa;
  --cm-bg-well:    #f1f7fa;

  /* The dark reskin's three-tier stack added this token so chrome (app
     bar/menus/dialog/palette) could sit one step lighter than ordinary
     cards. On light there's no such distinction — Canopy's kit never had
     one — so this is just an alias for the same white --cm-bg-app
     resolves to (Canopy's own --cm-neutral-0). Kept defined, not removed,
     because navigation.css's chrome rules read it directly and that
     structure is untouched by this re-skin. */
  --cm-bg-elevated: var(--cm-neutral-0);

  /* A floating chip (the slide-over-trigger tooltip) reads best darker
     than any surface it sits over, the same convention most UIs use for a
     tooltip regardless of the app's own theme — this was true before the
     dark reskin too (it borrowed the same near-black chip), just under a
     token name that no longer implies a whole dark surface stack. */
  --cm-tooltip-bg:   #0c1216;
  --cm-tooltip-text: #eef4f7;

  /* Sequential heatmap scale, re-hued to the accent. Canopy ships a
     terracotta -> green DIVERGING ramp for signed benchmarks; a heatmap of
     raw event counts has no negative half, so this is a single-hue
     sequential scale from "no activity" to "busiest day". */
  --cm-viz-seq-100: #eef1f4;
  --cm-viz-seq-150: #e3eef4;
  --cm-viz-seq-200: #d7eaf3;
  --cm-viz-seq-250: #cce7f3;
  --cm-viz-seq-300: #c0e3f2;
  --cm-viz-seq-350: #b5e0f2;
  --cm-viz-seq-400: #a9dcf1;
  --cm-viz-seq-450: #90c9e1;
  --cm-viz-seq-500: #77b7d2;
  --cm-viz-seq-550: #5ea4c2;
  --cm-viz-seq-600: #4491b2;
  --cm-viz-seq-650: #2b7fa3;
  --cm-viz-seq-700: #126c93;
}

/* ---------------------------------------------------------------------
   Base
   --------------------------------------------------------------------- */
* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--cm-bg-canvas);
  color: var(--cm-text-body);
  font-family: var(--cm-font-family);
  font-size: var(--cm-body-size);
  line-height: var(--cm-body-line);
}

/* `color-scheme` tells the browser this page is light, so native controls
   (checkboxes, radios, scrollbars, the date-input picker chrome) draw
   from its light built-in palette rather than guessing from the OS
   setting; `accent-color` then re-hues the checked/selected state to the
   theme's own accent instead of the browser default blue. */
html { color-scheme: light; }
input[type="checkbox"], input[type="radio"] { accent-color: var(--cm-action-primary); }

a { color: var(--cm-text-accent); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3, h4 { font-weight: var(--cm-weight-semibold); margin: 0 0 0.4em; color: var(--cm-text-primary); }
h1 { font-size: var(--cm-heading-lg-size); line-height: var(--cm-heading-lg-line); letter-spacing: var(--cm-heading-lg-tracking); }
h2 { font-size: var(--cm-heading-size); line-height: var(--cm-heading-line); }
h3 { font-size: var(--cm-heading-size); line-height: var(--cm-heading-line); color: var(--cm-text-primary); }
h4 { font-size: var(--cm-body-size); line-height: var(--cm-body-line); color: var(--cm-text-strong); }

p { margin: 0 0 0.75em; color: var(--cm-text-body); }

table { font-variant-numeric: tabular-nums; }

code { font-family: var(--cm-font-family); font-variant-numeric: tabular-nums; background: var(--cm-bg-well); border: 1px solid var(--cm-border-default); border-radius: var(--cm-radius-sm); padding: 1px 6px; font-size: 0.92em; }

/* Sentence-case tracked eyebrow — the ONE permitted exception to "never
   ALL-CAPS". Authored per-string in sentence case; letter-spacing (not
   text-transform) gives it the "label" weight so we never risk
   accidentally capitalising "and". */
.eyebrow {
  font-size: var(--cm-eyebrow-size);
  font-weight: var(--cm-eyebrow-weight);
  letter-spacing: var(--cm-eyebrow-tracking);
  color: var(--cm-text-muted);
}

/* Focus ring — signature, never suppressed. 2.5px solid + mandatory 2px
   offset gap so the ring never touches an accent control or selected card. */
:focus-visible {
  outline: var(--cm-focus-ring-width) solid var(--cm-focus-ring);
  outline-offset: var(--cm-focus-ring-offset);
  border-radius: var(--cm-radius-sm);
}

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* Inline stroked icon — recolors via currentColor, sized by context. */
.cm-icon { display: inline-block; vertical-align: -3px; flex-shrink: 0; }
.cm-icon--sm { width: 14px; height: 14px; }
.cm-icon--md { width: 16px; height: 16px; }
.cm-icon--lg { width: 20px; height: 20px; }
.cm-icon--flip { transform: scaleX(-1); }

/* No left rail left to share width with — the content column now runs the
   full viewport width (minus side padding), so the wide tenant table and
   other data-dense pages get real breathing room instead of being capped
   at the old 1400px meant to sit beside a 248px sidebar. 1600px still caps
   line length on ultra-wide monitors for the handful of prose blocks
   (auth screen aside, empty states) that aren't tables/grids. */
.main__content {
  padding: 24px 28px 60px;
  max-width: 1600px;
  width: 100%;
}

.page-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}
.page-header__meta { color: var(--cm-text-muted); font-size: 13px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
/* Item 1's "one-click way to include the rest" — a plain, always-visible
   text link (not hidden behind the filter bar) sitting right next to the
   count it explains. */
.inline-clear-link { color: var(--cm-text-accent); font-weight: var(--cm-weight-medium); }

/* Tenant list's prominent "needs attention" toggle — see
   tenants_controller#index and tenants/index.html.erb. Warning-amber, same
   pairing the risk badges already use, so it reads as a severity signal
   rather than an ordinary filter chip; `.is-active` (the filter is on)
   switches to a solid fill, the same "pressed" treatment the view-toggle
   segmented control uses elsewhere on this page. */
.attention-toggle {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 14px; border-radius: 999px;
  border: 1px solid var(--cm-warning-icon); background: var(--cm-warning-soft); color: var(--cm-warning-text);
  font-size: 13px; font-weight: var(--cm-weight-medium); text-decoration: none; white-space: nowrap;
}
.attention-toggle:hover { border-color: var(--cm-warning-text); }
/* is-active fill uses --cm-warning-text (7.1:1 white-on-fill, page-
   independent — Canopy's own vendored value, not overridden here). */
.attention-toggle.is-active { background: var(--cm-warning-text); color: #fff; border-color: var(--cm-warning-text); }
.attention-toggle .cm-icon { flex-shrink: 0; }

/* ---------------------------------------------------------------------
   Flash banners — Alert pattern, always icon + copy
   --------------------------------------------------------------------- */
.flash {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 16px;
  border-radius: var(--cm-radius-md);
  margin: 0 0 18px;
  font-size: 13.5px;
  line-height: 1.5;
  border: 1px solid;
}
/* Border colors are hand-picked, not tokens — a hairline one step more
   saturated than each banner's own soft fill. --cm-success-soft's border
   used to be a hardcoded leftover from Canopy's green ramp (#d9eedd) — the
   one stray green pixel in the whole app; this is a blue-tinted hairline
   instead, matching the "success is blue here" override above it. */
.flash--notice { background: var(--cm-success-soft); border-color: #c8e6f2; color: var(--cm-success-text); }
.flash--alert  { background: var(--cm-danger-soft); border-color: #f0cdc8; color: var(--cm-danger-text); }
.flash .cm-icon { margin-top: 1px; }

/* ---------------------------------------------------------------------
   Cards — border-first elevation. 1px border, radius-lg, NO shadow.
   --------------------------------------------------------------------- */
.card {
  background: var(--cm-bg-app);
  border: 1px solid var(--cm-border-default);
  border-radius: var(--cm-radius-lg);
  padding: var(--cm-space-6);
  margin-bottom: var(--cm-space-6);
}
.card__title { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: var(--cm-space-4); flex-wrap: wrap; }
.card__title h3 { margin: 0; }

.grid { display: grid; gap: var(--cm-space-6); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(360px, 1fr)); }
.grid--kpi { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }

/* ---------------------------------------------------------------------
   Stat tiles — label / value / delta / sparkline. Elevation-1 ("raised":
   a card lifting slightly, per Canopy) distinguishes a KPI tile from a
   flat in-flow table — it's a distinct, glanceable surface, not decor.
   The value is set well above the label (30px vs. an 11px tracked
   eyebrow) so the number dominates on sight, per the dataviz stat-tile
   contract ("the number should dominate its label by a wide margin").
   --------------------------------------------------------------------- */
.stat-tile {
  background: var(--cm-bg-app);
  border: 1px solid var(--cm-border-default);
  border-radius: var(--cm-radius-lg);
  padding: 16px 18px 18px;
  box-shadow: var(--cm-elevation-1);
}
.stat-tile__label {
  font-size: var(--cm-eyebrow-size);
  font-weight: var(--cm-eyebrow-weight);
  letter-spacing: var(--cm-eyebrow-tracking);
  color: var(--cm-text-muted);
  margin-bottom: 9px;
}
.stat-tile__value { font-size: 30px; font-weight: var(--cm-weight-semibold); color: var(--cm-text-primary); line-height: 1.1; letter-spacing: -0.015em; font-variant-numeric: tabular-nums; }
/* Pre-existing overflow, surfaced while checking every tile on a dark
   surface: a route-path identifier ("engines/candidates/..._managers#index")
   is one unbroken string with no spaces, so it can't wrap at all without
   this and instead blows out of the tile and the KPI grid. Not a color
   fix, but this pass is the one that noticed it. */
.stat-tile__value--sm { font-size: 18px; letter-spacing: -0.005em; overflow-wrap: anywhere; }
.stat-tile { min-width: 0; }
/* Item 9's "Never adopted" KPI — same warning-amber basis as the risk
   badges, used sparingly: only when the count is actually positive (see
   menus/index.html.erb), never a permanent color. */
.stat-tile__value--warning { color: var(--cm-warning-text); }
/* The dropped-events counter on /ops (item 2 of the throughput fix) — same
   danger text token used for the churn/bus-factor callouts. Only applied
   when the count is actually positive; see ops/show.html.erb. */
.stat-tile__value--danger { color: var(--cm-danger-text); }
.stat-tile__unit { font-size: 14px; color: var(--cm-text-muted); font-weight: var(--cm-weight-medium); letter-spacing: normal; }
.stat-tile__sparkline { margin-top: 8px; height: 36px; }

/* ---------------------------------------------------------------------
   Meter — adoption score track
   --------------------------------------------------------------------- */
.meter { height: 8px; border-radius: 4px; background: var(--cm-neutral-200); overflow: hidden; }
/* Breadth column's inline meter, sized to sit beside the "83%" text rather
   than under it — moved out of a per-row inline style into a class so it's
   one declaration to maintain, not one per <tr>. */
.score-cell__meter { width: 56px; display: inline-block; vertical-align: middle; margin-left: 8px; }
.meter__fill { height: 100%; background: var(--cm-action-primary); border-radius: 4px 0 0 4px; }
/* "good" reads blue, not green — --cm-success-solid is overridden to
   --cm-brand-700 above (the theme's deliberate green -> blue deviation),
   never a raw --cm-green-* primitive. */
.meter__fill--good     { background: var(--cm-success-solid); }
.meter__fill--warning  { background: var(--cm-warning-icon); }
.meter__fill--critical { background: var(--cm-danger-solid); }

/* ---------------------------------------------------------------------
   Badges / chips — critical is the only solid fill; everything else
   escalates through border-only -> soft -> soft-strong.
   --------------------------------------------------------------------- */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 22px;
  padding: 0 9px;
  border-radius: var(--cm-radius-sm);
  font-size: 12.5px;
  font-weight: var(--cm-weight-semibold);
  border: 1px solid var(--cm-border-strong);
  color: var(--cm-text-body);
  background: var(--cm-bg-app);
  white-space: nowrap;
}
.chip--neutral { background: var(--cm-neutral-100); border-color: transparent; color: var(--cm-text-body); }

.status-chip { display: inline-flex; align-items: center; gap: 5px; height: 22px; padding: 0 9px; border-radius: var(--cm-radius-sm); font-size: 12.5px; font-weight: var(--cm-weight-semibold); white-space: nowrap; }
.status-chip--active  { background: var(--cm-success-soft); color: var(--cm-success-text); }
.status-chip--trial   { background: var(--cm-info-soft); color: var(--cm-info-text); }
.status-chip--churned { background: var(--cm-danger-solid); color: #fff; }
.status-chip--unknown { background: var(--cm-neutral-100); color: var(--cm-text-muted); }

/* Risk badges — escalating severity: no_core (border) < bus_factor (soft
   warning) < declining (strong danger soft) < churned (the one solid). */
.risk-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 22px;
  padding: 0 9px;
  border-radius: var(--cm-radius-sm);
  font-size: 12.5px;
  font-weight: var(--cm-weight-bold);
  margin: 0 4px 4px 0;
  white-space: nowrap;
}
.risk-badge__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex-shrink: 0; }
.risk-badge--no-core      { border: 1px solid var(--cm-border-strong); color: var(--cm-text-body); background: transparent; }
.risk-badge--low-adoption { border: 1px solid var(--cm-warning-icon); color: var(--cm-warning-text); background: transparent; }
.risk-badge--bus-factor   { background: var(--cm-warning-soft); color: var(--cm-warning-text); }
.risk-badge--declining    { background: var(--cm-danger-soft-strong); color: var(--cm-danger-text-strong); }
.risk-badge--churned      { background: var(--cm-danger-solid); color: #fff; }

.health-badge { display: inline-flex; align-items: center; gap: 6px; height: 22px; padding: 0 9px; border-radius: var(--cm-radius-sm); font-size: 12.5px; font-weight: var(--cm-weight-bold); }
.health-badge--healthy { background: var(--cm-success-soft); color: var(--cm-success-text); }
.health-badge--stale   { background: var(--cm-danger-solid); color: #fff; }
.health-badge--unknown { background: var(--cm-warning-soft); color: var(--cm-warning-text); }

/* ---------------------------------------------------------------------
   Tables — real <table>, hairline rows, sticky header, interactive at
   rest (accent id + trailing chevron), sortable column links.
   --------------------------------------------------------------------- */
.table-wrap { overflow-x: auto; border: 1px solid var(--cm-border-default); border-radius: var(--cm-radius-lg); }
/* One deliberate point of emphasis, now living on .portfolio-hero (see
   below) instead of here. The tenant list's entry point moved from "skim a
   strip, then land on the table" to "read the hero's one headline number,
   then land on the table/grid" — so the hero, not the table, is the surface
   that gets --cm-elevation-1. The table/grid stay plain-bordered, same as
   every other flat surface. (--cm-elevation-1 lifted from here in the
   Adoption Engine landing page rebuild — kept off .table-wrap itself so it
   stays opt-in per page, not a blanket elevation for every table.) */
table.data-table { width: 100%; border-collapse: collapse; background: var(--cm-bg-app); font-size: 13px; }
table.data-table thead th {
  position: sticky;
  top: 0;
  background: var(--cm-bg-well);
  text-align: left;
  padding: 9px 14px;
  font-size: 13px;
  font-weight: var(--cm-weight-bold);
  color: var(--cm-text-body);
  border-bottom: 1px solid var(--cm-border-default);
  white-space: nowrap;
}
table.data-table thead th a { color: var(--cm-text-muted); }
table.data-table thead th a:hover { color: var(--cm-text-primary); }
table.data-table thead th a.active { color: var(--cm-text-accent); }
table.data-table tbody td {
  padding: 10px 14px;
  border-bottom: 1px solid var(--cm-neutral-100);
  border-left: 3px solid transparent;
  vertical-align: middle;
  color: var(--cm-text-body);
  transition: background var(--cm-duration-fast) var(--cm-ease-standard), border-color var(--cm-duration-fast) var(--cm-ease-standard);
}
table.data-table tbody tr:last-child td { border-bottom: none; }
/* Row affordance on hover: wash + a thin accent rail on the leading edge,
   so a row with something to open reads as reachable, not just a table
   line — restrained (no shadow; Canopy is border-first for in-flow rows).
   Rail is 3px (was 2px) to match the app bar's own active-tab rail
   (.appbar__tab.active::after, navigation.css) — one consistent
   "leading-edge accent" weight across the app instead of two slightly
   different ones. */
table.data-table tbody tr:hover td { background: var(--cm-bg-well); }
/* --cm-brand-700, not the raw 500: the hard rule is "large fills only,
   never bounds a control or thin line" for the 2.86:1 raw brand hex. */
table.data-table tbody tr:hover td:first-child { border-left-color: var(--cm-brand-700); }
/* Keyboard-focus parity: a mouse hovering the row and a keyboard tabbing
   into the row's own link (the identifier, a sort header) are the same
   "I'm looking at this row" moment and should look the same, not just the
   focused control's own outline with a bare row underneath it. */
table.data-table tbody tr:focus-within td { background: var(--cm-bg-well); }
table.data-table tbody tr:focus-within td:first-child { border-left-color: var(--cm-brand-700); }
table.data-table .num { text-align: right; font-variant-numeric: tabular-nums; }
table.data-table .num span[title] { cursor: help; border-bottom: 1px dotted var(--cm-text-muted); }
table.data-table caption { text-align: left; padding: 9px 14px; color: var(--cm-text-muted); font-size: 13px; caption-side: top; }

/* Row identifier: accent-colored link + trailing chevron, visible at
   rest — not a hover-only affordance. */
.id-link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--cm-text-accent);
  font-weight: var(--cm-weight-semibold);
}
.id-link:hover { text-decoration: underline; }
.id-link .cm-icon { color: var(--cm-neutral-400); transition: transform var(--cm-duration-fast) var(--cm-ease-standard); }
.id-link:hover .cm-icon { transform: translateX(2px); color: var(--cm-text-accent); }

.name-cell { display: flex; align-items: center; gap: 8px; }
.name-cell small { color: var(--cm-text-muted); display: block; font-size: 12px; font-weight: var(--cm-weight-regular); }

/* ---------------------------------------------------------------------
   Heatmap grid - accent sequential scale (see tenant accent tokens above).
   Cells are sized up from an original 20px so the grid carries real visual
   weight instead of floating, tiny, in a full-width card; a compact stats
   rail fills the remaining width with numbers already computed for the
   legend caption (busiest day, total events) rather than leaving it bare.
   --------------------------------------------------------------------- */
.heatmap-layout { display: flex; align-items: flex-start; gap: var(--cm-space-8); flex-wrap: wrap; }
.heatmap-layout .table-wrap { border: none; overflow: visible; flex: 0 0 auto; }
.heatmap { border-collapse: separate; border-spacing: 3px; font-size: 12px; }
.heatmap th { color: var(--cm-text-muted); font-weight: var(--cm-weight-medium); text-align: center; padding: 2px 4px; }
.heatmap th.heatmap__row-label, .heatmap td.heatmap__row-label { text-align: right; padding-right: 10px; color: var(--cm-text-body); font-variant-numeric: tabular-nums; }
.heatmap td.heatmap__cell {
  width: 26px; height: 26px; border-radius: 5px;
  background-clip: padding-box;
  transition: transform var(--cm-duration-fast) var(--cm-ease-standard);
}
.heatmap td.heatmap__cell:hover { transform: scale(1.12); }
.heatmap-legend { display: flex; align-items: center; gap: 4px; margin-top: 14px; font-size: 12px; color: var(--cm-text-muted); }
.heatmap-legend__swatch { width: 12px; height: 12px; border-radius: 2px; display: inline-block; }

.heatmap-stats { display: flex; flex-direction: column; gap: var(--cm-space-4); flex: 0 0 160px; padding-top: 4px; }
.heatmap-stats__item { border-left: 2px solid var(--cm-border-default); padding-left: 12px; }
.heatmap-stats__value { font-size: 22px; font-weight: var(--cm-weight-semibold); color: var(--cm-text-primary); line-height: 1.15; font-variant-numeric: tabular-nums; }
.heatmap-stats__label { font-size: 12px; color: var(--cm-text-muted); margin-top: 2px; }

/* ---------------------------------------------------------------------
   Forms — auth screen + filter controls

   Split-screen sign-in: a tinted brand panel (bg-well, same tone as the
   page canvas — no seam, one continuous surface) beside the form on white
   (bg-app). The card holding the actual form sits one visible step above
   both, on white with a border, a soft elevation-2 shadow and a single
   brand-700 top hairline ("one hairline of brand, never a filled band" —
   the same restraint the portfolio hero uses) — so the one thing you're
   here to do reads as the most important surface on the page, not a form
   dropped onto a colored panel.
   --------------------------------------------------------------------- */
.auth-shell { min-height: 100vh; display: flex; background: var(--cm-bg-canvas); }
.auth-shell__brand-panel {
  flex: 1 1 46%;
  background: var(--cm-bg-well);
  border-right: 1px solid var(--cm-border-default);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 48px;
}
.auth-shell__brand-inner { max-width: 380px; }
.auth-shell__logo { display: block; width: 184px; height: auto; margin-bottom: 40px; }
.auth-shell__headline { font-size: var(--cm-display-size); line-height: var(--cm-display-line); letter-spacing: var(--cm-display-tracking); color: var(--cm-text-primary); margin-bottom: 12px; }
.auth-shell__tagline { font-size: 14.5px; line-height: 1.6; color: var(--cm-text-body); margin-bottom: 32px; }
.auth-shell__points { list-style: none; margin: 0 0 28px; padding: 0; display: flex; flex-direction: column; gap: 16px; }
.auth-shell__points li { display: flex; align-items: center; gap: 12px; font-size: 13.5px; color: var(--cm-text-strong); font-weight: var(--cm-weight-medium); }
.auth-shell__points .cm-icon { color: var(--cm-text-accent); flex-shrink: 0; }

/* Live proof — a real number (Feature.in_catalogue_scope.count, read fresh
   on every render, see SessionsController) given stat-tile-scale
   treatment instead of buried as a third bullet: the one thing on this
   page that's actually querying the database in front of you earns more
   weight than a claim in a sentence. Raised one step off the brand
   panel's base-canvas tone so it reads as its own surface, same
   "distinguishable by value" rule the rest of the reskin uses. */
.auth-shell__proof {
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding: 16px 18px;
  background: var(--cm-bg-app);
  border: 1px solid var(--cm-border-default);
  border-radius: var(--cm-radius-lg);
}
.auth-shell__proof-value {
  font-size: 32px;
  font-weight: var(--cm-weight-semibold);
  color: var(--cm-text-primary);
  line-height: 1;
  letter-spacing: -0.015em;
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.auth-shell__proof-label { font-size: 12.5px; line-height: 1.5; color: var(--cm-text-muted); }

.auth-shell__form-panel { flex: 1 1 54%; display: flex; align-items: center; justify-content: center; padding: 32px; background: var(--cm-bg-app); }
.auth-card {
  width: 360px;
  padding: 32px 30px;
  background: var(--cm-bg-elevated);
  border: 1px solid var(--cm-border-default);
  border-top: 2px solid var(--cm-brand-700);
  border-radius: var(--cm-radius-xl);
  box-shadow: var(--cm-elevation-2);
}
.auth-card h2 { font-size: var(--cm-heading-lg-size); margin-bottom: 4px; }
.auth-card p.sub { margin-bottom: 22px; font-size: 13.5px; }

@media (max-width: 860px) {
  .auth-shell { flex-direction: column; }
  .auth-shell__brand-panel { border-right: none; border-bottom: 1px solid var(--cm-border-default); padding: 32px; }
  .auth-shell__points { display: none; }
  .auth-shell__proof { display: none; }
}

.field { margin-bottom: 14px; }
.field label { display: block; font-size: var(--cm-label-size); font-weight: var(--cm-label-weight); color: var(--cm-text-strong); margin-bottom: 5px; }
.field input, .field select {
  width: 100%;
  height: 38px;
  padding: 0 12px;
  border-radius: var(--cm-radius-md);
  border: 1px solid var(--cm-border-control);
  background: var(--cm-bg-app);
  color: var(--cm-text-primary);
  font-family: var(--cm-font-family);
  font-size: 14px;
}
.field input:focus-visible, .field select:focus-visible { outline: var(--cm-focus-ring-width) solid var(--cm-focus-ring); outline-offset: var(--cm-focus-ring-offset); }

/* ---------------------------------------------------------------------
   Buttons — key-line is a 2px inner border-bottom on the solid variant,
   never a drop shadow; thins to 1px + presses in on :active.
   --------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 36px;
  padding: 0 16px;
  border-radius: var(--cm-radius-md);
  font-family: var(--cm-font-family);
  font-size: 13.5px;
  font-weight: var(--cm-weight-semibold);
  cursor: pointer;
  border: none;
  transition: background var(--cm-duration-fast) var(--cm-ease-standard);
}
.btn--primary {
  background: var(--cm-action-primary);
  color: var(--cm-text-on-accent);
  border-bottom: 2px solid var(--cm-action-keyline);
}
.btn--primary:hover { background: var(--cm-action-primary-hover); text-decoration: none; }
.btn--primary:active { background: var(--cm-action-pressed); border-bottom-width: 1px; transform: translateY(1px); }
.btn--secondary { background: var(--cm-bg-app); color: var(--cm-text-primary); border: 1px solid var(--cm-border-strong); }
.btn--secondary:hover { background: var(--cm-bg-well); text-decoration: none; }
.btn--ghost { background: transparent; color: var(--cm-text-accent); }
.btn--ghost:hover { background: var(--cm-accent-wash); text-decoration: none; }
.btn--full { width: 100%; }

/* ---------------------------------------------------------------------
   Select controls — styled with Canopy's chevron mask token so every
   dropdown in the product reads as a designed control, never a bare
   browser default. appearance:none strips the native arrow; the token's
   own baked-in stroke color (--cm-neutral-600) supplies the replacement,
   recolored slightly darker + shifted 1px on hover/focus for feedback.
   --------------------------------------------------------------------- */
.field select,
.filters select,
.filter-bar__field select {
  appearance: none;
  -webkit-appearance: none;
  background-image: var(--cm-icon-chevron-muted);
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 15px;
  padding-right: 36px;
  cursor: pointer;
  transition: border-color var(--cm-duration-fast) var(--cm-ease-standard), background-color var(--cm-duration-fast) var(--cm-ease-standard);
}
.field select:hover,
.filters select:hover,
.filter-bar__field select:hover {
  border-color: var(--cm-border-strong);
  background-color: var(--cm-bg-well);
}

/* ---------------------------------------------------------------------
   Filters row
   --------------------------------------------------------------------- */
.filters { display: flex; gap: 10px; align-items: center; margin-bottom: 18px; flex-wrap: wrap; }
.filters select, .filters input[type="search"] {
  height: 36px; padding: 0 12px; border-radius: var(--cm-radius-md); border: 1px solid var(--cm-border-control);
  /* background-color, not `background` — see the identical fix + comment
     on .filter-bar__field select: the shorthand here would wipe the
     chevron-mask background-image set by the rule above. */
  background-color: var(--cm-bg-app); color: var(--cm-text-primary); font-family: var(--cm-font-family); font-size: 13.5px;
}
.filters input[type="search"] { min-width: 220px; }
.filters select:focus-visible, .filters input:focus-visible { outline: var(--cm-focus-ring-width) solid var(--cm-focus-ring); outline-offset: var(--cm-focus-ring-offset); }

/* ---------------------------------------------------------------------
   View toggle — Canopy's Segmented control (level-2 nav): active option is
   a white pill + elevation-1, not just a color change, so "which view am I
   on" reads at a glance instead of only via link color.
   --------------------------------------------------------------------- */
.view-toggle {
  display: inline-flex;
  gap: 4px;
  padding: 4px;
  background: var(--cm-bg-well);
  border: 1px solid var(--cm-border-default);
  border-radius: var(--cm-radius-md);
  margin-bottom: 16px;
}
/* FIX 5 — these are real <button> elements (see tenants/index.html.erb and
   menus/show's Hierarchy/Flat toggle), and without an explicit reset a
   <button> keeps the browser's native chrome (an inset border + grey
   buttonface background) wherever this class's own declarations don't
   already override it — which, before this fix, was everywhere except the
   .is-active state. The result was two flat grey boxes with a border,
   not Canopy's Segmented control. `border: none` + `background: transparent`
   + `cursor: pointer` + inheriting the page's font is the same reset every
   other button-styled control in this file already carries
   (.btn, .info-affordance, .attention-toggle's icon...); this component
   was simply missing it. */
.view-toggle__option {
  display: inline-flex;
  align-items: center;
  height: 34px;
  padding: 0 16px;
  border: none;
  border-radius: 7px;
  background: transparent;
  font-family: inherit;
  font-size: 13.5px;
  font-weight: var(--cm-weight-semibold);
  color: var(--cm-text-body);
  cursor: pointer;
}
.view-toggle__option:hover { text-decoration: none; color: var(--cm-text-primary); }
.view-toggle__option.is-active {
  background: var(--cm-bg-app);
  color: var(--cm-text-accent);
  box-shadow: var(--cm-elevation-1);
}
.view-toggle__option.is-active:hover { color: var(--cm-text-accent); }

/* ---------------------------------------------------------------------
   Pagination
   --------------------------------------------------------------------- */
/* FIX 7 — "bring pagination up": the same nav renders both above and below
   a paged table/grid (see shared/_pagination.html.erb's `location:` param)
   so a reader who has scrolled through a full page of rows never has to
   scroll back up just to reach "next". `--top` swaps the spacing from
   "after the content" to "before it". */
.pagination { display: flex; gap: 8px; align-items: center; margin-top: 16px; font-size: 13px; color: var(--cm-text-muted); }
.pagination--top { margin-top: 0; margin-bottom: 14px; }
.pagination a, .pagination span.current, .pagination span.disabled {
  display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 12px; border-radius: var(--cm-radius-md); border: 1px solid var(--cm-border-strong);
}
.pagination a { color: var(--cm-text-body); }
.pagination a:hover { background: var(--cm-bg-well); text-decoration: none; }
.pagination span.current { background: var(--cm-action-primary); color: #fff; border-color: var(--cm-action-primary); font-weight: var(--cm-weight-semibold); }
.pagination span.disabled { border-color: var(--cm-border-default); opacity: 0.5; }

/* ---------------------------------------------------------------------
   Callouts — in-flow banners for tenant risk copy (Alert pattern)
   --------------------------------------------------------------------- */
.callout {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  border: 1px solid #ecdfc0;
  background: var(--cm-warning-soft);
  color: var(--cm-warning-text);
  padding: 12px 16px;
  border-radius: var(--cm-radius-md);
  margin-bottom: var(--cm-space-4);
  font-size: 13.5px;
  line-height: 1.5;
}
.callout--critical { border-color: #f0cdc8; background: var(--cm-danger-soft); color: var(--cm-danger-text); }
.callout .cm-icon { margin-top: 1px; flex-shrink: 0; }

/* ---------------------------------------------------------------------
   Misc
   --------------------------------------------------------------------- */
/* button_to's default form_class ("button_to") renders block — this keeps
   an inline action (e.g. the Team page's per-row Deactivate/Reactivate)
   sitting beside another button rather than dropping to its own line. */
.inline-form { display: inline; }

.muted { color: var(--cm-text-muted); }
.text-strong { color: var(--cm-text-strong); font-weight: var(--cm-weight-semibold); }

/* Designed empty/zero-data state — icon in a muted well + message,
   centered, so "nothing here yet" reads as intentional rather than a
   broken render. See application_helper#empty_state. */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 44px 20px;
  text-align: center;
  color: var(--cm-text-muted);
  font-size: 13.5px;
}
.empty-state__icon {
  display: flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--cm-bg-well); color: var(--cm-neutral-400);
}
.empty-state__icon .cm-icon--lg { width: 22px; height: 22px; }
.empty-state__text { margin: 0; max-width: 360px; }
/* Nested / low-emphasis empty state (inside an already-open disclosure
   row, a sub-table) — smaller, no icon well, so it doesn't out-weigh the
   content it's nested inside. */
.empty-state--compact { flex-direction: row; padding: 12px 4px; gap: 8px; }
.empty-state--compact .empty-state__icon { width: 20px; height: 20px; background: none; }
.empty-state--compact .empty-state__icon .cm-icon--lg { width: 16px; height: 16px; }

details.reveal > summary {
  cursor: pointer;
  color: var(--cm-text-accent);
  font-size: 13.5px;
  margin: 10px 0;
  font-weight: var(--cm-weight-semibold);
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
details.reveal > summary::-webkit-details-marker { display: none; }
details.reveal > summary .cm-icon { transition: transform var(--cm-duration-fast) var(--cm-ease-standard); }
details.reveal[open] > summary .cm-icon { transform: rotate(90deg); }

/* Nested feature-hierarchy <details> (section -> menu -> sub-features) */
.hierarchy-section { margin-bottom: var(--cm-space-6); }
.hierarchy-section:last-child { margin-bottom: 0; }
.hierarchy-section__head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.hierarchy-section__head h4 { margin: 0; }

.menu-disclosure > summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 6px;
}
.menu-disclosure > summary::-webkit-details-marker { display: none; }
.menu-disclosure > summary .cm-icon { color: var(--cm-neutral-400); transition: transform var(--cm-duration-fast) var(--cm-ease-standard); flex-shrink: 0; }
.menu-disclosure[open] > summary .cm-icon { transform: rotate(90deg); }
.menu-disclosure .sub-table-wrap { margin: 10px 0 4px 22px; }

/* The sub-feature table sits in its own full-width row (see
   _feature_hierarchy.html.erb) so it never influences the parent table's
   column widths. It stays hidden until the previous row's <details> is
   open — no JS, just :has() reading the disclosure's own [open] state. */
.menu-subrow { display: none; }
.menu-subrow > td { padding: 0 14px 14px; }
tr.menu-row:has(details[open]) + tr.menu-subrow { display: table-row; }

/* FIX 3 — zero-usage tail. The toggle row uses the same `details.reveal`
   pattern as the flat view's "Show N features with no usage" reveal;
   `tr.menu-row--zero` rows start hidden and only become table rows once
   THAT row's own details is open — same :has()-on-a-sibling technique as
   the sub-feature row above, just one level higher, so no JS is needed to
   open a whole tail of rows at once. Once visible, the muted color still
   keeps them reading as "the tail", never mistaken for a real signal. */
tr.menu-row--zero { display: none; }
tr.menu-row--toggle:has(details[open]) ~ tr.menu-row--zero { display: table-row; }
/* FIX 3 (revised) — color alone made the tail readable only on inspection:
   a Director had to actually read a row's text/color to learn it was
   noise. Dropping both size (13px -> 12px, the same step already used for
   .name-cell small and risk-badge text elsewhere) and weight (the id-link's
   semibold -> regular, forfeiting the one bit of emphasis every other row's
   identifier carries) means the tail is *felt* as lighter before it's ever
   read — while --cm-text-muted still holds 4.6:1+ against both the row's
   resting white and its hover wash, so it stays legible the moment someone
   deliberately looks. */
tr.menu-row--zero, tr.menu-row--zero td { color: var(--cm-text-muted); font-size: 12px; }
tr.menu-row--zero .id-link { color: var(--cm-text-muted); font-weight: var(--cm-weight-regular); }
tr.menu-row--zero .id-link .cm-icon { color: var(--cm-neutral-400); }

/* Same muted treatment for an individual zero-usage row inside an
   already-expanded sub-feature table (that table is small and hidden
   behind its own parent disclosure already, so it doesn't need a second
   collapse — just enough contrast that a real sub-feature still stands
   out from the untouched ones sitting beside it), and for the Feature
   Catalogue's unclassified tail (see features/index.html.erb). */
tr.row-zero, tr.row-zero td { color: var(--cm-text-muted); font-size: 12px; }
tr.row-zero .id-link { color: var(--cm-text-muted); font-weight: var(--cm-weight-regular); }
tr.row-zero .id-link .cm-icon { color: var(--cm-neutral-400); }

canvas { max-width: 100%; }

.spark-cell { width: 130px; }

/* Inline-SVG sparkline (see ApplicationHelper#sparkline_svg) — replaces a
   per-row Chartkick canvas on the tenant list, which measured at 400
   Chart.js canvases for 200 tenants (one per row in each of the table and
   card views). No JS initialization, no canvas: just a styled polyline. */
.sparkline { display: block; overflow: visible; }
.sparkline__line { fill: none; stroke: var(--cm-brand-700); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.sparkline__flat { stroke: var(--cm-border-strong); stroke-width: 1.5; stroke-dasharray: 2 3; }

/* ---------------------------------------------------------------------
   Metric tile definitions — the plain-English line every KPI tile carries
   directly under its value (Director-legibility requirement: no metric
   should require asking what it means).
   --------------------------------------------------------------------- */
.stat-tile__definition { font-size: 11.5px; color: var(--cm-text-muted); margin-top: 6px; line-height: 1.4; }
.stat-tile__reference { font-size: 11.5px; color: var(--cm-text-muted); margin-top: 3px; line-height: 1.4; }
.stat-tile__reference strong { color: var(--cm-text-body); font-weight: var(--cm-weight-medium); }

/* ---------------------------------------------------------------------
   Portfolio hero — the tenant list's entry point (landing-page rebuild:
   "make it better like launch_engine"). launch_engine's tier1-hero answers
   "how's the whole book doing" with ONE dominant number (overall ARR) plus
   a handful of supporting side stats, ahead of its table — a clear place
   for the eye to land before the per-row detail. This is that shape,
   expressed in Canopy tokens rather than launch_engine's raw hex/dark
   gradient: a bordered white card (Canopy has no decorative gradients) at
   --cm-elevation-1, the ONE deliberate emphasis point on this page (see the
   comment on .table-wrap above — the table/grid below stay plain-bordered).

   The old 3-pass "Portfolio Health" strip (healthy/at-risk/dormant figures
   + a mix bar, its own separate .card above the table) is folded in here
   rather than kept alongside: its exact counts now live in the mix legend
   and two of the four side stats (Tenants at risk / Dormant), so the page
   never repeats hero + summary strip + table — exactly the density mistake
   a prior pass of this page already had to recover from once.

   Headline number: portfolio-wide composite adoption (breadth + stickiness
   + seat coverage ÷ 3, TenantsController#portfolio_hero), weighted by each
   tenant's active-admin count so one very small account can't swing it —
   stated in the sub-label and spelled out in the info-affordance tooltip,
   never left as an unexplained bare number (Director-legibility
   requirement carried over from the KPI tiles elsewhere in this app). Side
   stats are the four figures a Director checks first: at risk, dormant,
   median breadth (the typical account, unlike the weighted mean which
   skews toward the biggest ones), total active admins (portfolio scale).

   The hero stands out from the ordinary cards below it by a single brand
   hairline across its top edge, not by being a different surface — same
   white, same border, one extra 2px accent rule. This is this page's one
   deliberate brand moment, restrained to a hairline rather than a filled
   band. */
.portfolio-hero {
  display: flex;
  justify-content: space-between;
  align-items: stretch;
  gap: var(--cm-space-8);
  flex-wrap: wrap;
  margin-bottom: var(--cm-space-6);
  padding: 26px 28px;
  background: var(--cm-bg-elevated);
  border: 1px solid var(--cm-border-default);
  border-top: 2px solid var(--cm-brand-700);
  border-radius: var(--cm-radius-xl);
  box-shadow: var(--cm-elevation-2);
}
.portfolio-hero__main { flex: 1 1 320px; min-width: 260px; }
/* The hero's own eyebrow overrides the shared .eyebrow color — the light
   accent step, not amber/gold: this headline is the portfolio's normal
   state, not a warning, so it stays on-brand rather than borrowing the
   risk-side stats' amber/red. */
.portfolio-hero .eyebrow { color: var(--cm-text-accent); }
.portfolio-hero__num {
  margin: 4px 0 0;
  font-size: var(--cm-display-size);
  line-height: var(--cm-display-line);
  letter-spacing: var(--cm-display-tracking);
  font-weight: var(--cm-display-weight);
  color: var(--cm-text-primary);
  font-variant-numeric: tabular-nums;
}
.portfolio-hero__num span { font-size: 20px; color: var(--cm-text-muted); font-weight: var(--cm-weight-semibold); margin-left: 1px; }
.portfolio-hero__sub { margin: 6px 0 0; font-size: 13.5px; color: var(--cm-text-muted); display: inline-flex; align-items: center; gap: 4px; }
.portfolio-hero__sub strong { color: var(--cm-text-primary); font-weight: var(--cm-weight-semibold); }

.portfolio-hero__mix { margin-top: 18px; max-width: 420px; }
.portfolio-hero__mix-legend { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 8px; font-size: 12.5px; color: var(--cm-text-muted); }
.portfolio-hero__dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin-right: 6px; vertical-align: middle; }
.portfolio-hero__dot--healthy { background: var(--cm-brand-500); }
.portfolio-hero__dot--at-risk { background: var(--cm-warning-text); }
.portfolio-hero__dot--dormant { background: var(--cm-danger-text); }

.portfolio-hero__side { display: flex; align-items: stretch; gap: 12px; flex-wrap: wrap; justify-content: flex-end; }
.portfolio-hero__stat {
  min-width: 118px;
  padding: 12px 16px;
  background: var(--cm-bg-app);
  border: 1px solid var(--cm-border-default);
  border-radius: var(--cm-radius-md);
}
.portfolio-hero__stat-num { margin: 0; font-size: 21px; font-weight: var(--cm-weight-semibold); color: var(--cm-text-primary); line-height: 1.1; font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.portfolio-hero__stat-num span { font-size: 14px; color: var(--cm-text-muted); font-weight: var(--cm-weight-medium); }
.portfolio-hero__stat-num--warning { color: var(--cm-warning-text); }
.portfolio-hero__stat-num--danger { color: var(--cm-danger-text); }
/* Sentence-case tracked label, same construction as .eyebrow (letter-
   spacing carries the "label" weight, never text-transform — Canopy's
   never-ALL-CAPS rule has no exemption for small chrome labels). */
.portfolio-hero__stat-label { margin: 4px 0 0; font-size: var(--cm-eyebrow-size); font-weight: var(--cm-eyebrow-weight); letter-spacing: var(--cm-eyebrow-tracking); color: var(--cm-text-muted); }
.portfolio-hero .info-affordance { color: var(--cm-text-muted); }
.portfolio-hero .info-affordance:hover { background: var(--cm-bg-hover); color: var(--cm-text-primary); }

/* Info affordance — a tooltip trigger for chrome explainer copy that
   doesn't deserve a permanent line of body text (Canopy has no dedicated
   tooltip-trigger component to reuse; this mirrors the disclosure/help
   affordances it does ship — round, muted, `cursor: help`, native
   title + aria-label rather than a JS-built popover). */
.info-affordance {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; padding: 0; border: none; border-radius: 50%;
  background: transparent; color: var(--cm-text-muted); cursor: help;
}
.info-affordance:hover { background: var(--cm-bg-well); color: var(--cm-text-body); }

.proportion-bar { display: flex; height: 10px; border-radius: 5px; overflow: hidden; background: var(--cm-neutral-200); }
.proportion-bar__segment--healthy { background: var(--cm-success-solid); }
.proportion-bar__segment--at-risk { background: var(--cm-warning-icon); }
.proportion-bar__segment--dormant { background: var(--cm-danger-solid); }

.health-badge--at-risk { background: var(--cm-warning-soft); color: var(--cm-warning-text); }

/* ---------------------------------------------------------------------
   Tenant card grid — the view-toggle alternative to the table (landing
   page rebuild). Same information as the table's row, rearranged as one
   rich per-tenant summary rather than a column-by-column comparison:
   plan/status, breadth with its meter, the 12-week sparkline, active
   admins, seat coverage, last active, and any risk badges.
   --------------------------------------------------------------------- */
.tenant-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
  gap: var(--cm-space-4);
}
/* display:grid would otherwise override [hidden] — see view_toggle_controller.js. */
.tenant-grid[hidden] { display: none; }

/* FIX 6 — "Open tenant" used to be a small link stranded at the card foot,
   disconnected from the rest of a card that otherwise did nothing when
   clicked. The whole card is now the click target (position: relative +
   a single "stretched link" overlay anchored to the title — see
   .tenant-card__link below), with the chevron affordance living on the
   title itself, matching how every OTHER identifier in this app already
   signals "this row/name opens something" (.id-link). */
.tenant-card {
  position: relative;
  background: var(--cm-bg-app);
  border: 1px solid var(--cm-border-default);
  border-radius: var(--cm-radius-lg);
  padding: 18px 20px;
  transition: border-color var(--cm-duration-fast) var(--cm-ease-standard), background var(--cm-duration-fast) var(--cm-ease-standard);
}
.tenant-card:hover { border-color: var(--cm-brand-700); cursor: pointer; }
/* Keyboard-focus parity with the mouse-hover state above: the visible
   anchor's own outline is suppressed (see .tenant-card__link:focus-visible
   below) in favor of a ring on the whole card, since the whole card is the
   real click target. */
.tenant-card:has(.tenant-card__link:focus-visible) {
  border-color: var(--cm-brand-700);
  outline: var(--cm-focus-ring-width) solid var(--cm-focus-ring);
  outline-offset: var(--cm-focus-ring-offset);
}

.tenant-card__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.tenant-card__name { margin: 0; font-size: 15.5px; }
/* The single real, visible anchor for the whole card (everything else in
   the card is plain text/chips — no nested interactive elements). The
   ::after pseudo-element stretches it over the entire card so a click
   anywhere on the card activates it, while focus/hover still visually
   center on the title + chevron where the affordance actually reads. */
.tenant-card__link { display: inline-flex; align-items: center; gap: 4px; color: var(--cm-text-primary); font-weight: var(--cm-weight-semibold); }
.tenant-card__link:hover { text-decoration: none; color: var(--cm-text-accent); }
.tenant-card__link::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.tenant-card__link:focus-visible { outline: none; }
.tenant-card__link .cm-icon { color: var(--cm-neutral-400); transition: transform var(--cm-duration-fast) var(--cm-ease-standard); }
.tenant-card:hover .tenant-card__link .cm-icon,
.tenant-card:has(.tenant-card__link:focus-visible) .tenant-card__link .cm-icon { transform: translateX(2px); color: var(--cm-text-accent); }
.tenant-card__meta { margin: 3px 0 0; font-size: 12px; color: var(--cm-text-muted); }
.tenant-card__chips { display: flex; flex-direction: column; align-items: flex-end; gap: 5px; flex-shrink: 0; }

.tenant-card__score { margin-bottom: 12px; }
.tenant-card__score-row { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 6px; }
.tenant-card__score-value { font-size: 22px; font-weight: var(--cm-weight-semibold); color: var(--cm-text-primary); font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.tenant-card__score-label { font-size: 11px; font-weight: var(--cm-weight-medium); color: var(--cm-text-muted); }

.tenant-card__spark { height: 40px; margin-bottom: 12px; }
.tenant-card__spark .sparkline { width: 100%; height: 40px; }

.tenant-card__stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  padding: 12px 0;
  border-top: 1px solid var(--cm-border-default);
  border-bottom: 1px solid var(--cm-border-default);
  margin-bottom: 12px;
}
.tenant-card__stat-num { margin: 0; font-size: 15px; font-weight: var(--cm-weight-semibold); color: var(--cm-text-primary); line-height: 1.2; font-variant-numeric: tabular-nums; }
.tenant-card__stat-label { margin: 3px 0 0; font-size: 10.5px; font-weight: var(--cm-weight-medium); color: var(--cm-text-muted); }

.tenant-card__risks { display: flex; flex-wrap: wrap; gap: 4px; }

/* ---------------------------------------------------------------------
   Segment/filter bar (plan, industry, size, status) — what makes "vs your
   other accounts" comparisons meaningful (research brief §3).
   --------------------------------------------------------------------- */
.filter-bar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; margin-bottom: var(--cm-space-4); }
.filter-bar__field { display: flex; flex-direction: column; gap: 4px; }
.filter-bar__field label { font-size: 11.5px; font-weight: var(--cm-weight-medium); color: var(--cm-text-muted); }
/* background-color, NOT the `background` shorthand: this rule cascades
   after the chevron-mask rule above (same specificity, later in the file),
   and the shorthand form resets background-image/-repeat/-position/-size
   to their initial values, silently erasing the chevron that rule set.
   This was the exact cause of the FIX 2 regression: selects rendered as
   plain text inputs because their arrow was wiped by this line. */
.filter-bar__field select { height: 34px; padding: 0 10px; border-radius: var(--cm-radius-md); border: 1px solid var(--cm-border-control); background-color: var(--cm-bg-app); color: var(--cm-text-primary); font-family: var(--cm-font-family); font-size: 13px; min-width: 150px; }
.filter-bar__field select:focus-visible { outline: var(--cm-focus-ring-width) solid var(--cm-focus-ring); outline-offset: var(--cm-focus-ring-offset); }
.filter-bar__field input[type="search"] { height: 34px; padding: 0 10px; border-radius: var(--cm-radius-md); border: 1px solid var(--cm-border-control); background-color: var(--cm-bg-app); color: var(--cm-text-primary); font-family: var(--cm-font-family); font-size: 13px; min-width: 200px; }
.filter-bar__field input[type="search"]:focus-visible { outline: var(--cm-focus-ring-width) solid var(--cm-focus-ring); outline-offset: var(--cm-focus-ring-offset); }

/* The tenant list's "needs attention only" checkbox — sits at input
   height so it lines up with the selects/search box beside it. */
.filter-bar__checkbox { display: flex; align-items: center; gap: 6px; height: 34px; font-size: 13px; color: var(--cm-text-body); white-space: nowrap; }

/* ---------------------------------------------------------------------
   Inline-SVG distribution / funnel / scatter charts — used where Chartkick
   doesn't fit (exact per-bar coloring, a labeled funnel, a quadrant
   overlay). Every chart in this family carries its own caption stating
   what question it answers.
   --------------------------------------------------------------------- */
.svg-chart { display: block; width: 100%; height: auto; }
.svg-chart text { font-family: var(--cm-font-family); fill: var(--cm-text-body); }
.svg-chart .svg-chart__axis-label { fill: var(--cm-text-muted); font-size: 11px; }
.svg-chart .svg-chart__value-label { fill: var(--cm-text-strong); font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; }
.chart-caption { font-size: 12.5px; color: var(--cm-text-muted); margin-top: 8px; line-height: 1.5; }

/* Breadth/depth quadrant guide lines — thin, muted, never mistaken for
   data. */
.svg-chart .quadrant-line { stroke: var(--cm-border-default); stroke-width: 1; }
.svg-chart .quadrant-point--peer { fill: var(--cm-neutral-400); }
.svg-chart .quadrant-point--self { fill: var(--cm-brand-700); stroke: var(--cm-brand-900); stroke-width: 1.5; }

.two-col-charts { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: var(--cm-space-6); }

/* ---------------------------------------------------------------------
   Role breakdown (item 10) — Super Admin / Sub Admin / Manager usage
   split, shared between the tenant detail page (30-day window) and the
   menu detail page (all-time, cross-tenant). One row per role: a label,
   an active/eligible meter (the same .meter component the rest of the
   app uses for a rate, not a bespoke bar), then the raw counts.
   --------------------------------------------------------------------- */
.role-breakdown { display: flex; flex-direction: column; gap: 14px; }
.role-breakdown__row { display: grid; grid-template-columns: 110px 1fr 170px; align-items: center; gap: 14px; }
.role-breakdown__label { font-size: 13.5px; font-weight: var(--cm-weight-semibold); color: var(--cm-text-strong); }
.role-breakdown__meter { margin: 0; }
.role-breakdown__stats { display: flex; justify-content: space-between; gap: 10px; font-size: 12.5px; color: var(--cm-text-muted); white-space: nowrap; }
.role-breakdown__empty { grid-column: 2 / span 2; font-size: 12.5px; color: var(--cm-text-muted); font-style: italic; }
@media (max-width: 640px) {
  .role-breakdown__row { grid-template-columns: 1fr; gap: 6px; }
}

/* Composite score card — the components ALWAYS render beside the number
   (research brief §5: never a single opaque composite). The score is this
   page's hero figure (dataviz contract: the single number a dashboard
   leads with, >=48px, exactly one per view) — set apart with a right
   keyline rather than competing with the KPI strip above it. */
.composite-card { display: flex; align-items: center; gap: 32px; flex-wrap: wrap; }
.composite-card__score { text-align: center; flex-shrink: 0; padding-right: 32px; border-right: 1px solid var(--cm-border-default); }
.composite-card__score-value { font-size: 48px; font-weight: var(--cm-weight-semibold); color: var(--cm-text-primary); line-height: 1; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.composite-card__score-label { font-size: 12px; color: var(--cm-text-muted); margin-top: 6px; }
.composite-card__formula { display: flex; gap: 22px; flex-wrap: wrap; flex: 1; min-width: 240px; align-items: center; }
.composite-card__component { min-width: 100px; }
.composite-card__component-value { font-size: 20px; font-weight: var(--cm-weight-semibold); color: var(--cm-text-accent); font-variant-numeric: tabular-nums; }
.composite-card__component-label { font-size: 12px; color: var(--cm-text-muted); margin-top: 3px; }

/* ---------------------------------------------------------------------
   Right-pane slide-over — a generic accelerator over the full pages
   (tenant/menu/feature quick-view) panels share this
   shell shape. `[hidden]` fully removes it from layout/tab order; opening
   adds `.is-open`, which is what actually animates the panel in — see
   slide_over_controller.js for the open/close/focus
   sequencing this timing depends on.
   --------------------------------------------------------------------- */
.slide-over { position: fixed; inset: 0; z-index: 70; }
.slide-over[hidden] { display: none; }
.slide-over__backdrop {
  position: absolute; inset: 0;
  background: rgba(12, 18, 22, 0.44);
  opacity: 0;
  transition: opacity var(--cm-duration-fast) var(--cm-ease-standard);
}
.slide-over.is-open .slide-over__backdrop { opacity: 1; }
.slide-over__panel {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: min(480px, 100vw);
  display: flex; flex-direction: column;
  background: var(--cm-bg-app);
  border-left: 1px solid var(--cm-border-default);
  box-shadow: var(--cm-elevation-2);
  padding: 28px 24px 24px;
  overflow-y: auto;
  transform: translateX(100%);
  transition: transform var(--cm-duration-base, var(--cm-duration-fast)) var(--cm-ease-standard);
}
.slide-over.is-open .slide-over__panel { transform: translateX(0); }
.slide-over__close {
  position: absolute; top: 16px; right: 16px;
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border: none; border-radius: 50%;
  background: var(--cm-bg-well); color: var(--cm-text-muted); cursor: pointer;
}
.slide-over__close:hover { background: var(--cm-neutral-100); color: var(--cm-text-primary); }
.slide-over__loading { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 80px 20px; color: var(--cm-text-muted); }
.slide-over__header .eyebrow { margin: 0 0 4px; }
.slide-over__header h2 { margin: 0 0 6px; font-size: 19px; }

/* A narrow-width alternative to .data-table for the slide-over panels —
   two real table columns get cramped at the panel's ~430px content
   width, so the menu/feature quick views use a flowing name+value row
   list instead. */
.panel-list { list-style: none; margin: 0; padding: 0; }
.panel-list li {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 9px 0; border-bottom: 1px solid var(--cm-neutral-100); font-size: 13px;
}
.panel-list li:last-child { border-bottom: none; }
.panel-list__name { color: var(--cm-text-body); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.panel-list__value { color: var(--cm-text-strong); font-weight: var(--cm-weight-semibold); font-variant-numeric: tabular-nums; flex-shrink: 0; }

/* Quick-view trigger — sits beside an existing .id-link, never replaces
   it (the full page stays the primary destination). Icon-only with a
   real aria-label + a CSS-only tooltip on hover/focus-visible. */
.slide-over-trigger {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; margin-left: 4px; border-radius: 50%;
  color: var(--cm-text-muted); vertical-align: middle;
}
.slide-over-trigger:hover { background: var(--cm-bg-well); color: var(--cm-text-accent); text-decoration: none; }
.slide-over-trigger::after {
  content: attr(data-tooltip);
  position: absolute; bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%);
  padding: 5px 9px; border-radius: var(--cm-radius-sm);
  background: var(--cm-tooltip-bg); color: var(--cm-tooltip-text);
  font-size: 11px; font-weight: var(--cm-weight-medium); white-space: nowrap;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity var(--cm-duration-fast) var(--cm-ease-standard);
}
.slide-over-trigger:hover::after, .slide-over-trigger:focus-visible::after { opacity: 1; visibility: visible; }

/* ---------------------------------------------------------------------
   Explore — the guided metric/breakdown/filter/visualization builder.
   The 4 step selectors read as one connected sentence ("Breadth, broken
   down by Plan, filtered to Enterprise, as a Bar chart") rather than an
   unrelated stack of <select>s.
   --------------------------------------------------------------------- */
.explore-builder { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 14px; margin-bottom: var(--cm-space-4); }
.explore-builder__field { display: flex; flex-direction: column; gap: 4px; }
.explore-builder__field label { font-size: 11.5px; font-weight: var(--cm-weight-medium); color: var(--cm-text-muted); }
.explore-builder__field select { height: 36px; padding: 0 12px; border-radius: var(--cm-radius-md); border: 1px solid var(--cm-border-control); background-color: var(--cm-bg-app); color: var(--cm-text-primary); font-family: var(--cm-font-family); font-size: 13.5px; min-width: 170px; }
.explore-builder__field select:focus-visible { outline: var(--cm-focus-ring-width) solid var(--cm-focus-ring); outline-offset: var(--cm-focus-ring-offset); }

.starting-points { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--cm-space-4); margin-bottom: var(--cm-space-6); }
.starting-point {
  display: block; padding: 16px 18px; border: 1px solid var(--cm-border-default); border-radius: var(--cm-radius-lg);
  background: var(--cm-bg-app); color: var(--cm-text-primary);
  transition: border-color var(--cm-duration-fast) var(--cm-ease-standard), background var(--cm-duration-fast) var(--cm-ease-standard);
}
.starting-point:hover { border-color: var(--cm-brand-700); text-decoration: none; background: var(--cm-bg-well); }
.starting-point__audience { font-size: var(--cm-eyebrow-size); font-weight: var(--cm-eyebrow-weight); letter-spacing: var(--cm-eyebrow-tracking); color: var(--cm-text-accent); margin-bottom: 6px; }
.starting-point__question { font-size: 14.5px; font-weight: var(--cm-weight-semibold); margin-bottom: 4px; }
.starting-point__detail { font-size: 12.5px; color: var(--cm-text-muted); line-height: 1.5; }

.explore-share { display: flex; align-items: center; gap: 8px; margin: 4px 0 var(--cm-space-4); font-size: 12.5px; color: var(--cm-text-muted); }
.explore-share code { flex: 1; overflow-x: auto; white-space: nowrap; }
/* ---------------------------------------------------------------------
   Redesigned app chrome — drop-in replacement for the "App shell",
   ".topnav*" and ".subbar*" blocks in app/assets/stylesheets/application.css.
   Semantic Canopy tokens only. The chrome sits at the ELEVATED tier
   (--cm-bg-elevated) — one step lighter than the raised cards/tables it
   sits above (--cm-bg-app), which in turn sit one step above the page
   canvas — so the app bar, contextbar-adjacent menus and overlays read as
   the topmost plane by value, not just by z-index.
   --------------------------------------------------------------------- */
.app-shell { display: flex; flex-direction: column; min-height: 100vh; }

/* App bar — the chrome's elevated surface, 56px, sticky. */
.appbar {
  height: 56px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 0 20px;
  background: var(--cm-bg-elevated);
  border-bottom: 1px solid var(--cm-border-default);
  position: sticky;
  top: 0;
  z-index: 40;
}

.appbar__brand {
  display: flex; align-items: center; gap: 10px; height: 100%;
  padding-right: 16px; margin-right: 10px;
  border-right: 1px solid var(--cm-border-default);
  flex-shrink: 0;
}
.appbar__brand:hover { text-decoration: none; }
.appbar__brand-logo { display: block; height: 24px; width: auto; }
.appbar__brand-app { font-size: 13px; font-weight: var(--cm-weight-semibold); color: var(--cm-text-primary); white-space: nowrap; }

.appbar__nav { display: flex; align-items: center; gap: 2px; height: 100%; }
.appbar__tab {
  display: flex; align-items: center; gap: 8px;
  height: 34px; padding: 0 12px;
  border-radius: var(--cm-radius-md);
  color: var(--cm-text-body);
  font-size: 13.5px; font-weight: var(--cm-weight-medium);
  position: relative; white-space: nowrap;
}
.appbar__tab .cm-icon { color: var(--cm-text-muted); }
.appbar__tab:hover { background: var(--cm-bg-hover); color: var(--cm-text-primary); text-decoration: none; }
.appbar__tab:hover .cm-icon { color: currentColor; }
.appbar__tab.active {
  background: var(--cm-accent-wash);
  color: var(--cm-text-accent);
  font-weight: var(--cm-weight-bold);
}
.appbar__tab.active .cm-icon { color: currentColor; }
/* Same 3px leading-edge accent the table rows use, rotated to the bar's
   bottom edge. --cm-brand-700, never the raw 500. */
.appbar__tab.active::after {
  content: "";
  position: absolute; left: 10px; right: 10px; bottom: -11px;
  height: 3px; border-radius: 3px 3px 0 0;
  background: var(--cm-brand-700);
}

.appbar__spacer { flex: 1; }
.appbar__actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }

/* Search trigger — looks like the field it opens, behaves like a button.
   Sits one tier BELOW the appbar's own elevated surface (--cm-bg-app, the
   same raised tone as an ordinary card) so it reads as a recessed field
   set into the bar, not a flat rectangle floating on top of it. */
.appbar__search {
  display: flex; align-items: center; gap: 8px;
  width: 266px; height: 34px; padding: 0 8px 0 10px;
  border: 1px solid var(--cm-border-strong); border-radius: var(--cm-radius-md);
  background: var(--cm-bg-app); color: var(--cm-text-muted);
  font-family: var(--cm-font-family); font-size: 13px; cursor: pointer;
}
.appbar__search span { flex: 1; text-align: left; }
.appbar__search:hover { background: var(--cm-bg-well); border-color: var(--cm-rim); }
.appbar__search kbd,
.menu__kbd {
  font-family: var(--cm-font-family); font-size: 11px; font-weight: var(--cm-weight-semibold);
  color: var(--cm-text-muted); background: var(--cm-bg-well);
  border: 1px solid var(--cm-border-default); border-radius: var(--cm-radius-sm); padding: 1px 5px;
}

.appbar__btn {
  display: flex; align-items: center; gap: 6px;
  height: 34px; padding: 0 10px; border: none; background: transparent;
  border-radius: var(--cm-radius-md); color: var(--cm-text-body);
  font-family: var(--cm-font-family); font-size: 13.5px; font-weight: var(--cm-weight-medium);
  cursor: pointer;
}
.appbar__btn:hover,
.appbar__btn[aria-expanded="true"] { background: var(--cm-bg-hover); color: var(--cm-text-primary); }
.appbar__btn--icon { width: 34px; padding: 0; justify-content: center; color: var(--cm-text-muted); }
.appbar__btn--avatar { gap: 4px; padding: 0 6px 0 4px; }

.avatar {
  width: 26px; height: 26px; border-radius: var(--cm-radius-full);
  background: var(--cm-accent-wash); color: var(--cm-text-accent);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: var(--cm-weight-bold);
}
.avatar--lg { width: 34px; height: 34px; font-size: 12.5px; }

/* ---------------------------------------------------------------------
   Menus — one pattern for every dropdown in the app (Admin, Help,
   account, recent, saved views, sort, table row actions), driven by
   controllers/menu_controller.js. Overlay elevation, never a border-only
   panel: --cm-elevation-2 is Canopy's overlay step.
   --------------------------------------------------------------------- */
.menu { position: relative; display: flex; }
.menu__panel {
  position: absolute; top: calc(100% + 8px); left: 0;
  min-width: 240px;
  background: var(--cm-bg-elevated);
  border: 1px solid var(--cm-border-default);
  border-radius: var(--cm-radius-lg);
  box-shadow: var(--cm-elevation-2);
  padding: 6px; z-index: 60;
}
.menu__panel--right { left: auto; right: 0; }
.menu__panel--wide { width: 300px; }
/* Row-action menus sit inside .table-wrap, which declares overflow-x: auto
   — and per spec a `visible` value on the other axis computes to `auto`,
   so an absolutely-positioned panel is clipped on BOTH axes and the bottom
   rows' menus are unusable. These panels are positioned against the
   viewport by menu_controller.js (data-menu-fixed) instead. */
.menu__panel--fixed { position: fixed; top: auto; left: auto; right: auto; min-width: 0; width: 214px; }

.menu__label {
  margin: 0; padding: 8px 10px 4px;
  font-size: var(--cm-eyebrow-size); font-weight: var(--cm-eyebrow-weight);
  letter-spacing: var(--cm-eyebrow-tracking); color: var(--cm-text-muted);
}
.menu__item {
  display: flex; align-items: center; gap: 10px;
  width: 100%; height: 36px; padding: 0 10px;
  border: none; background: transparent; border-radius: var(--cm-radius-sm);
  color: var(--cm-text-body); font-family: var(--cm-font-family); font-size: 13.5px;
  text-align: left; cursor: pointer;
}
.menu__item:hover { background: var(--cm-bg-hover); text-decoration: none; }
.menu__item .cm-icon { color: var(--cm-text-muted); }
.menu__item[aria-current="true"] { background: var(--cm-accent-wash); color: var(--cm-text-accent); font-weight: var(--cm-weight-semibold); }
.menu__item-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.menu__item-meta { font-size: 12px; color: var(--cm-text-muted); }
.menu__item-meta--ok { display: inline-flex; align-items: center; gap: 5px; color: var(--cm-success-text); }
.menu__dot { width: 6px; height: 6px; border-radius: var(--cm-radius-full); background: var(--cm-success-solid); }
.menu__rule { height: 1px; border: 0; background: var(--cm-border-default); margin: 6px 0; }

.menu__head { padding: 10px 10px 8px; border-bottom: 1px solid var(--cm-border-default); margin-bottom: 6px; }
.menu__head-title { margin: 0 0 3px; font-size: 13px; font-weight: var(--cm-weight-semibold); color: var(--cm-text-primary); }
.menu__head-body { margin: 0; font-size: 12.5px; line-height: 18px; color: var(--cm-text-muted); }

.menu__identity { display: flex; align-items: center; gap: 10px; padding: 10px; }
.menu__identity-text { display: flex; flex-direction: column; min-width: 0; }
.menu__identity-text strong { font-size: 13.5px; font-weight: var(--cm-weight-semibold); color: var(--cm-text-primary); }
.menu__identity-text span { font-size: 12px; color: var(--cm-text-muted); overflow: hidden; text-overflow: ellipsis; }
.menu__role {
  display: inline-block; margin: 0 10px 8px; padding: 2px 8px;
  border-radius: var(--cm-radius-sm); background: var(--cm-bg-well);
  font-size: 11.5px; font-weight: var(--cm-weight-semibold); color: var(--cm-text-muted);
}

/* ---------------------------------------------------------------------
   Context bar — always present (no more 48px layout jump between an
   index and a detail page) and now carries the list controls.
   --------------------------------------------------------------------- */
.contextbar {
  height: 48px; flex-shrink: 0;
  display: flex; align-items: center; gap: 12px;
  padding: 0 28px;
  background: var(--cm-bg-canvas);
  border-bottom: 1px solid var(--cm-border-default);
  position: sticky; top: 56px; z-index: 30;
}
.contextbar__crumbs { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--cm-text-muted); min-width: 0; white-space: nowrap; }
.contextbar__crumbs a { color: var(--cm-text-muted); }
.contextbar__crumbs a:hover { color: var(--cm-text-accent); }
.contextbar__crumbs .cm-icon { color: var(--cm-rim); }
.contextbar__crumbs .current { color: var(--cm-text-strong); font-weight: var(--cm-weight-medium); }
.contextbar__spacer { flex: 1; }
.contextbar__btn {
  display: flex; align-items: center; gap: 6px;
  height: 30px; padding: 0 10px;
  border: 1px solid var(--cm-border-default); border-radius: var(--cm-radius-md);
  background: var(--cm-bg-app); color: var(--cm-text-body);
  font-family: var(--cm-font-family); font-size: 13px; font-weight: var(--cm-weight-medium);
  cursor: pointer; white-space: nowrap;
}
.contextbar__btn:hover { background: var(--cm-bg-well); border-color: var(--cm-border-strong); }
.contextbar__btn .cm-icon { color: var(--cm-text-muted); }

/* ---------------------------------------------------------------------
   Date range — the app's one time control, in the context bar so every
   page reads from the same range instead of each page inventing its own.
   Presets on the left, an explicit custom range on the right; the label
   always states the resolved range, never just "Custom".
   --------------------------------------------------------------------- */
.daterange__panel { width: 460px; display: flex; padding: 0; overflow: hidden; }
/* `display: flex` above is an author rule, so it beats the UA stylesheet's
   `[hidden] { display: none }` at equal specificity regardless of source
   order (author always outranks user-agent) — without this, the date
   range panel rendered open on every single page load, `hidden` attribute
   notwithstanding. menu_controller.js still owns the actual open/close;
   this only lets the `hidden` attribute's `display: none` win again. */
.daterange__panel[hidden] { display: none; }
.daterange__presets { width: 190px; padding: 6px; border-right: 1px solid var(--cm-border-default); background: var(--cm-bg-elevated); }
.daterange__custom { flex: 1; padding: 12px; background: var(--cm-bg-app); }
.daterange__custom-row { display: flex; gap: 8px; margin-bottom: 10px; }
.daterange__field { flex: 1; display: flex; flex-direction: column; gap: 4px; }
.daterange__field label { font-size: var(--cm-label-size); font-weight: var(--cm-label-weight); color: var(--cm-text-strong); }
.daterange__field input {
  height: 34px; padding: 0 8px; font-family: var(--cm-font-family); font-size: 13px;
  color: var(--cm-text-primary); background: var(--cm-bg-app);
  border: 1px solid var(--cm-border-control); border-radius: var(--cm-radius-md);
}
.daterange__compare { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--cm-text-body); margin-bottom: 12px; }
.daterange__actions { display: flex; justify-content: flex-end; gap: 8px; }
.daterange__note { font-size: 12px; color: var(--cm-text-muted); margin: 0 0 10px; line-height: 17px; }

/* Filter bar — the tenant/feature filter selects become the same menu
   pattern as the rest of the chrome, so a filter reads as a control with
   a value rather than a native select in a form row. */
.filterbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 16px; }
.filterbar__search {
  display: flex; align-items: center; gap: 8px; height: 34px; width: 260px; padding: 0 10px;
  border: 1px solid var(--cm-border-control); border-radius: var(--cm-radius-md); background: var(--cm-bg-app);
}
.filterbar__search input { flex: 1; border: none; outline: none; background: transparent; font-family: var(--cm-font-family); font-size: 13px; color: var(--cm-text-primary); }
.filterbar__search .cm-icon { color: var(--cm-text-muted); }
.filterbar__btn {
  display: flex; align-items: center; gap: 6px; height: 34px; padding: 0 10px;
  border: 1px solid var(--cm-border-control); border-radius: var(--cm-radius-md);
  background: var(--cm-bg-app); color: var(--cm-text-body);
  font-family: var(--cm-font-family); font-size: 13px; font-weight: var(--cm-weight-medium);
  cursor: pointer; white-space: nowrap;
}
.filterbar__btn:hover { background: var(--cm-bg-well); }
.filterbar__btn.is-set { border-color: var(--cm-action-primary); color: var(--cm-text-accent); background: var(--cm-accent-wash); }
.filterbar__spacer { flex: 1; }
.menu__check { width: 16px; height: 16px; flex-shrink: 0; color: var(--cm-text-accent); }

/* Tabs — tenant/menu/feature detail pages get one tab row instead of a
   single 374-line scroll. */
.tabs { display: flex; align-items: center; gap: 2px; border-bottom: 1px solid var(--cm-border-default); margin-bottom: 20px; }
.tabs__tab {
  height: 38px; padding: 0 12px; border: none; background: transparent;
  color: var(--cm-text-muted); font-family: var(--cm-font-family); font-size: 13.5px;
  font-weight: var(--cm-weight-medium); cursor: pointer; position: relative;
}
.tabs__tab:hover { color: var(--cm-text-primary); }
.tabs__tab.is-active { color: var(--cm-text-accent); font-weight: var(--cm-weight-bold); }
.tabs__tab.is-active::after {
  content: ""; position: absolute; left: 6px; right: 6px; bottom: -1px; height: 3px;
  border-radius: 3px 3px 0 0; background: var(--cm-brand-700);
}

/* Dialog — deactivate/confirm and the new-agent form, at modal elevation.
   Replaces data-turbo-confirm's browser dialog for destructive actions. */
.dialog__backdrop { position: fixed; inset: 0; background: rgba(25, 33, 28, 0.32); z-index: 80; }
.dialog {
  position: fixed; top: 120px; left: 50%; transform: translateX(-50%);
  width: min(440px, 92vw); background: var(--cm-bg-elevated);
  border: 1px solid var(--cm-border-default); border-radius: var(--cm-radius-xl);
  box-shadow: var(--cm-elevation-3); z-index: 90; padding: 20px;
}
.dialog__title { margin: 0 0 8px; font-size: var(--cm-heading-size); line-height: var(--cm-heading-line); font-weight: var(--cm-weight-semibold); color: var(--cm-text-primary); }
.dialog__body { margin: 0 0 18px; font-size: 13.5px; line-height: 20px; color: var(--cm-text-body); }
.dialog__actions { display: flex; justify-content: flex-end; gap: 8px; }
.btn--danger { background: var(--cm-danger-solid); color: #fff; border-bottom: 2px solid #8f1c13; }

/* Slide-over quick view — unchanged behaviour, restated here so the
   redesigned chrome and the panel share one elevation language. */
.quickview__backdrop { position: fixed; inset: 0; background: rgba(25, 33, 28, 0.32); z-index: 80; }
.quickview {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(440px, 94vw);
  background: var(--cm-bg-app); border-left: 1px solid var(--cm-border-default);
  box-shadow: var(--cm-elevation-3); z-index: 90; padding: 20px 22px; overflow-y: auto;
}
.quickview__close { position: absolute; top: 14px; right: 14px; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; border: none; background: transparent; border-radius: var(--cm-radius-sm); color: var(--cm-text-muted); cursor: pointer; }
.quickview__close:hover { background: var(--cm-bg-hover); }

/* The light portfolio-hero override that used to live here (item 12 of
   integration/README.md) is gone: the user asked for the app "richer,
   darker" and that's a newer instruction than the kit's light hero. The
   hero's real definition is back in application.css's own .portfolio-hero
   rule, now re-skinned for the app-wide dark surface (--cm-bg-elevated +
   a brand-700 top hairline) instead of restored verbatim — see that
   file's comment for why it no longer needs a second invented surface to
   stand out on. */

/* ---------------------------------------------------------------------
   Command palette (⌘K) — modal elevation over the page.
   --------------------------------------------------------------------- */
.palette__backdrop { position: fixed; inset: 0; background: rgba(25, 33, 28, 0.32); z-index: 80; }
.palette {
  position: fixed; top: 88px; left: 50%; transform: translateX(-50%);
  width: min(640px, 92vw);
  background: var(--cm-bg-elevated);
  border: 1px solid var(--cm-border-default);
  border-radius: var(--cm-radius-xl);
  box-shadow: var(--cm-elevation-3);
  overflow: hidden; z-index: 90;
}
.palette__field { display: flex; align-items: center; gap: 10px; height: 52px; padding: 0 16px; border-bottom: 1px solid var(--cm-border-default); }
.palette__field .cm-icon { color: var(--cm-text-muted); }
.palette__input { flex: 1; border: none; outline: none; background: transparent; font-family: var(--cm-font-family); font-size: 15px; color: var(--cm-text-primary); }
.palette__results { max-height: min(420px, 60vh); overflow-y: auto; padding: 6px; }
.palette__result { display: flex; align-items: center; gap: 10px; height: 40px; padding: 0 10px; border-radius: var(--cm-radius-sm); color: var(--cm-text-body); font-size: 13.5px; }
.palette__result .cm-icon { color: var(--cm-text-muted); }
.palette__result[aria-selected="true"] { background: var(--cm-accent-wash); color: var(--cm-text-accent); font-weight: var(--cm-weight-semibold); }
.palette__result[aria-selected="true"] .cm-icon { color: currentColor; }
.palette__result-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.palette__result-meta { font-size: 12px; font-weight: var(--cm-weight-regular); color: var(--cm-text-muted); }
.palette__footer { display: flex; align-items: center; gap: 14px; height: 38px; padding: 0 16px; background: var(--cm-bg-well); border-top: 1px solid var(--cm-border-default); font-size: 12px; color: var(--cm-text-muted); }
