/* ============================================================================
   khamo-ui.css  --  KHAMO MERIDIAN GRID
   ----------------------------------------------------------------------------
   Additive theme layer for the Khamo Certification admin app.
   Bootstrap 5 + FontAwesome 6 + jQuery are already loaded. This sheet LAYERS
   ON TOP of them. No existing class is renamed or removed; every legacy
   selector is restyled in place so all 25 views inherit the theme with zero
   markup changes.

   THIS IS A PLAIN .css FILE. Every at-rule below is a SINGLE @ (@media,
   @supports, @keyframes). Only a copy pasted into a .cshtml would need @@.

   LOAD POSITION IS LOAD-BEARING
   -----------------------------
   Link this file in Views/Shared/_Layout.cshtml AFTER the inline </style>
   (currently L135) and BEFORE </head> (currently L136):

       </style>
       <link rel="stylesheet" href="~/css/khamo-ui.css" asp-append-version="true" />
       </head>

   An inline <style> ELEMENT gets no specificity boost but wins on document
   order. Linked at the obvious spot (L11, next to bootstrap) this sheet would
   lose every equal-specificity tie to the layout's own block for .sidebar,
   .main-content, .nav-link, .top-bar, .card-custom, .stat-card, .stat-icon,
   body AND, fatally, the :root custom properties at L12-L18 -- the theme would
   silently do nothing.

   The webfont also has to be linked in the layout (this sheet deliberately
   contains no @import -- an @import of an external sheet is a render-blocking
   second round trip). Add ABOVE the bootstrap link:

       <link rel="preconnect" href="https://fonts.googleapis.com">
       <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
       <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">

   'Outfit' has been named in the layout since day one and has NEVER been
   loaded; the app silently falls back to Segoe UI.

   TWO THINGS STILL OUTRANK THIS SHEET EVEN AT L136, AND BOTH ARE HANDLED HERE
   --------------------------------------------------------------------------
   (a) !important in site.css on .btn-primary / .btn-warning (L20-L29),
       .bg-dark (L31), .text-primary / .text-warning (L35) and .nav-link.active
       (L43-L47), plus the layout's own at L82, L89-L92, L97, L101, L117.
       Importance beats document order, so these are matched with !important.
       Every such use below carries a comment naming what it beats.
   (b) The body-level <style> at L297-L331 and the 12 view-local <style> blocks
       that sit after @RenderBody() (L289). Those are still inside <body>, so
       they win on order at equal specificity. They are beaten with the `body `
       prefix, which raises (0,1,0) to (0,1,1) and needs no !important.

   SECTIONS
     01 Tokens                    11 Tables
     02 Degradation gates         12 Forms
     03 Keyframes                 13 Focus
     04 Base + ghost lattice      14 Tabs
     05 Raw typography            15 Badges, status pills, shims
     06 The rail (sidebar)        16 Chips + pagination
     07 Workspace + top bar       17 Masthead, KPI pills, branch row
     08 Data plates + trust seam  18 Small parts (code, avatar, flags)
     09 Stat cards                19 Members (rm-*) retarget
     10 Buttons + utilities       20 Overlays, alerts, reveal, shims
                                  21 Idle governor
                                  22 Reduced motion
   ============================================================================ */


/* ============================================================================
   01. TOKENS
   ============================================================================ */

:root{

  /* ---- 1. BRAND RAMP -------------------------------------------------------
     Legacy stops are pinned BYTE-IDENTICAL: 12 view-local <style> blocks and
     ~70 inline style attributes read these values directly. Changing them
     shifts 25 views unpredictably. Add stops, never move them.               */
  --kh-brand-50 : #F1F9F3;
  --kh-brand-100: #E6F8E8;
  --kh-brand-200: #D2ECDA;
  --kh-brand-300: #A7D7C5;   /* == legacy --accent-color                      */
  --kh-brand-400: #8AC7AE;
  --kh-brand-500: #74B49B;   /* == legacy --primary-green. 2.40:1 vs #fff.
                                RAIL / TINT / BORDER ONLY. Never a fill under
                                white text. Never body text.                  */
  --kh-brand-600: #66A96B;   /* == legacy gradient stop. 2.82:1 vs #fff.
                                Decorative, tints, rail gradients only.       */
  --kh-brand-700: #46794E;   /* AA BUTTON STOP: #fff on this = 5.12:1         */
  --kh-brand-750: #35583C;
  --kh-brand-800: #3B5F41;   /* == legacy --dark-green. 7.9:1                 */
  --kh-brand-850: #2C4A33;   /* == --bs-primary. #fff = 9.1:1                 */
  --kh-brand-900: #0F5132;   /* deep green of the Word policy documents       */
  --kh-brand-950: #08301E;

  --kh-brand-500-rgb: 116,180,155;
  --kh-brand-800-rgb: 59,95,65;
  --kh-brand-850-rgb: 44,74,51;

  /* ---- 2. THE RAIL -- dark chassis, board quadrant 1 ---------------------- */
  --kh-rail-top:      #1E2E26;
  --kh-rail-bot:      #141F1A;
  --kh-rail-deep:     #101A15;
  --kh-rail-edge:     rgba(167,215,197,.14);
  --kh-rail-ink:      #E7F2EB;   /* 13.1:1 on #1A2620                         */
  --kh-rail-ink-idle: #A6C2B2;   /*  7.4:1                                    */
  --kh-rail-ink-dim:  #89A697;   /*  5.3:1 -- the floor on the rail            */
  --kh-rail-hover:    rgba(167,215,197,.07);
  --kh-rail-active:   rgba(116,180,155,.16);
  --kh-rail-glass:    rgba(255,255,255,.06);
  --kh-rail-danger:   #FF9E96;   /* the .text-danger Suspension link on dark   */

  /* ---- 3. LUMINOUS ACCENTS ------------------------------------------------
     HARD RULE: --kh-mint and every --kh-glow-* token may ONLY be used on a
     ground at or darker than #2A3B31 (i.e. the rail, the modal scrim, the
     login chassis). On any light surface "live" is --kh-flow as a SOLID fill
     plus a 1px --kh-edge-live ring. A 0.3-alpha bloom over #F4F9F4 is a few
     percent of luminance delta -- it photographs as a grey-green fringe.      */
  --kh-mint:        #8CF2C8;   /* rail-only bloom colour                      */
  --kh-mint-dim:    rgba(140,242,200,.55);
  --kh-cyan:        #5FD7D0;
  --kh-flow:        #2FCF97;   /* light-surface "live" FILL (never text)      */
  --kh-flow-bright: #5FE3B8;
  --kh-flow-deep:   #12A97A;
  --kh-live-ink:    #0F5132;   /* the text colour that accompanies a live fill*/
  --kh-glow-rail:   0 0 18px -6px rgba(140,242,200,.65);   /* DARK GROUND ONLY */
  --kh-glow-rail-hi:0 0 26px -4px rgba(140,242,200,.85);   /* DARK GROUND ONLY */
  --kh-live-ring:   0 0 0 1px var(--kh-edge-live);         /* light-ground sub */

  /* ---- 4. SURFACES --------------------------------------------------------
     Three tiers, and the tier decides whether blur is legal:
       opaque  -> anything holding a table, a form, or a Bootstrap modal
       veil    -> alpha only, NO backdrop-filter, light non-data panels
       frost   -> alpha + backdrop-filter, ONLY over a dark/saturated ground   */
  --kh-bg:            #F1F7F2;
  --kh-surface:       #FFFFFF;               /* data plates. OPAQUE by rule.  */
  --kh-surface-2:     #FAFDFA;
  --kh-surface-sunk:  #F4F9F4;
  --kh-surface-veil:  rgba(255,255,255,.82); /* .kh-veil -- no blur, no layer  */
  --kh-surface-frost: rgba(255,255,255,.72); /* .kh-frost / .top-bar          */
  --kh-surface-raised:rgba(255,255,255,.97); /* modals, dropdowns, popovers   */
  --kh-scrim:         rgba(11,26,19,.52);    /* .modal-backdrop               */

  /* ---- 5. EDGES + THE TRUST SEAM ---------------------------------------- */
  --kh-edge:        rgba(59,95,65,.14);
  --kh-edge-strong: rgba(59,95,65,.22);
  --kh-edge-lum:    rgba(116,180,155,.55);
  --kh-edge-live:   rgba(47,207,151,.70);
  --kh-edge-inner:  rgba(255,255,255,.72);
  --kh-seam: linear-gradient(140deg,
                rgba(255,255,255,.95)  0%,
                rgba(167,215,197,.60) 42%,
                rgba(95,215,208,.34)  72%,
                rgba(255,255,255,.88) 100%);
  --kh-seam-live: linear-gradient(140deg,
                rgba(255,255,255,.98)  0%,
                rgba(95,227,184,.80)  45%,
                rgba(47,207,151,.62)  78%,
                rgba(255,255,255,.95) 100%);

  /* ---- 6. RAILS -- the signature primitive, four scales ------------------ */
  --kh-rail-idle:  rgba(167,215,197,.55);
  --kh-rail-solid: linear-gradient(90deg,#66A96B 0%, #2FCF97 55%, #46794E 100%);
  --kh-rail-y:     linear-gradient(180deg,
                     rgba(116,180,155,0)   0%,
                     var(--kh-brand-500)  16%,
                     var(--kh-mint)       50%,
                     var(--kh-brand-600)  84%,
                     rgba(116,180,155,0) 100%);
  --kh-rail-w: 3px;

  /* ---- 7. FILLS -----------------------------------------------------------
     Contrast-locked: the LIGHTEST stop is #46794E = 5.12:1 under white.      */
  --kh-btn-fill:       linear-gradient(135deg,#46794E 0%,#35583C 58%,#0F5132 100%);
  --kh-btn-fill-hover: linear-gradient(135deg,#4F8759 0%,#3B6243 58%,#14603C 100%);
  --kh-btn-sheen:      linear-gradient(100deg,
                         rgba(140,242,200,0)   30%,
                         rgba(140,242,200,.30) 50%,
                         rgba(140,242,200,0)   70%);
  --kh-tint:        rgba(167,215,197,.16);
  --kh-tint-strong: rgba(102,169,107,.22);
  --kh-avatar:      linear-gradient(135deg,#E6F8E8 0%,#A7D7C5 100%);

  /* ---- 8. INK -- every value measured against --kh-bg #F1F7F2 ------------ */
  --kh-ink:        #1C2A20;   /* 13.9:1  body, cell values, headings          */
  --kh-ink-soft:   #33463A;   /*  8.0:1  secondary body                       */
  --kh-ink-muted:  #5C7263;   /*  4.87:1 AA FLOOR -- labels, th, meta, hints   */
  --kh-ink-faint:  #8FA394;   /*  2.5:1  DECORATION ONLY. Never a word.       */
  --kh-ink-invert: #FFFFFF;
  --kh-link:       #1B5E45;   /*  7.4:1                                       */

  /* ---- 9. SEMANTICS -- restored, and every pair measured ------------------ */
  --kh-ok:          #2E7D46;  --kh-ok-tint:     rgba(46,125,70,.12);
  --kh-warn-ink:    #7A4C05;  --kh-warn-tint:   rgba(232,163,43,.16);
  --kh-warn-solid:  #E8A32B;  --kh-warn-on:     #3B2A05;  /* 6.39:1 pairing   */
  --kh-danger:      #B3261E;  --kh-danger-tint: rgba(179,38,30,.10);
  --kh-danger-ink:  #9F1D1D;
  --kh-info:        #1F7F6B;  --kh-info-tint:   rgba(31,127,107,.12);
  --kh-neutral:     #5C7263;  --kh-neutral-tint:rgba(92,114,99,.10);

  /* ---- 10. THE GHOST LATTICE -- board quadrant 1's polygonal wireframe.
        +/-30 degree triangulated struts + a node dot at each cell centre.
        Total ink <= 5.5%: invisible under content, resolves in the gutters.  */
  --kh-grid-ink:      rgba(59,95,65,.055);
  --kh-grid-ink-rail: rgba(167,215,197,.10);
  --kh-grid-node:     rgba(116,180,155,.09);
  --kh-grid-cell:     64px;
  --kh-grid-strut:    74px;
  --kh-wash:
     radial-gradient(120% 80% at 50% -10%, rgba(167,215,197,.20), transparent 62%),
     radial-gradient(90rem 60rem at -6% 108%, rgba(102,169,107,.12), transparent 60%);

  /* ---- 11. RADII (the app's existing 8/10/12/14/20/30 ladder, rationalised)*/
  --kh-r-xs:  6px;  --kh-r-sm:  8px;  --kh-r-md: 12px;
  --kh-r-lg: 18px;  --kh-r-xl: 22px;  --kh-r-pill: 999px;

  /* ---- 12. ELEVATION -- exactly three steps, ever ------------------------ */
  --kh-e0: 0 0 0 1px var(--kh-edge);
  --kh-e1: 0 0 0 1px var(--kh-edge),
           0 1px 2px rgba(20,40,28,.04),
           0 6px 16px -10px rgba(20,40,28,.18);
  --kh-e2: 0 0 0 1px var(--kh-edge-strong),
           0 2px 4px rgba(20,40,28,.05),
           0 14px 28px -14px rgba(20,40,28,.22);
  --kh-e3: 0 8px 24px -8px rgba(11,26,19,.18),
           0 32px 64px -24px rgba(11,26,19,.26);
  --kh-e-rail: inset -1px 0 0 0 var(--kh-rail-edge),
               18px 0 40px -30px rgba(10,24,18,.55);
  --kh-e-spec: inset 0 1px 0 var(--kh-edge-inner);

  /* ---- 13. FOCUS -- 5.99:1 on white, and it survives tinted and dark
        grounds because of the inner white/ink spacer. This token replaces
        every previous focus treatment in the app.                           */
  --kh-focus-ring:      0 0 0 2px #FFFFFF, 0 0 0 4px rgba(27,94,69,.90);
  --kh-focus-ring-dark: 0 0 0 2px var(--kh-rail-deep), 0 0 0 4px var(--kh-mint);
  --kh-focus-outline:   2px solid #1B5E45;

  /* ---- 14. BLUR -- legal in three places only: .top-bar, .modal-backdrop,
        and .kh-frost (which itself is legal only over a dark ground).       */
  --kh-blur-chrome: 14px;
  --kh-blur-rail:    8px;
  --kh-blur-scrim:   4px;
  --kh-sat:         1.30;

  /* ---- 15. MOTION -------------------------------------------------------- */
  --kh-t-press:   110ms;
  --kh-t-fast:    170ms;
  --kh-t-base:    240ms;
  --kh-t-slow:    360ms;
  --kh-t-max:     420ms;      /* nothing in this theme exceeds this           */
  --kh-ease-out:    cubic-bezier(.22,1,.36,1);
  --kh-ease-in-out: cubic-bezier(.65,0,.35,1);
  --kh-ease-spring: cubic-bezier(.20,.90,.25,1.02);  /* <=2% overshoot        */
  --kh-cycle-pulse: 2400ms;   /* the ONE permitted ambient loop, singleton    */
  --kh-cycle-sweep: 1100ms;   /* transient busy rail only                     */

  /* ---- 16. TYPE ---------------------------------------------------------- */
  --kh-font: 'Outfit','Segoe UI',system-ui,-apple-system,sans-serif;
  --kh-font-mono: 'JetBrains Mono',Consolas,'SF Mono',Menlo,monospace;
  --kh-fs-micro: .72rem; --kh-fs-xs: .78rem; --kh-fs-sm: .875rem;
  --kh-fs-md:    .95rem; --kh-fs-lg: 1.15rem; --kh-fs-xl: 1.45rem;
  --kh-fs-display: 2rem;
  --kh-tracking-label: .08em;
  --kh-tracking-tight: -.012em;
  --kh-row-h: 44px;

  /* ---- 17. Z-LADDER -- documented against what already exists.
        #global-notif = 10000 (inline), #custom-toast-container = 10005
        (inline). NOTHING in this theme may approach either.                  */
  --kh-z-topbar:  1020;
  --kh-z-sidebar: 1030;

  /* ---- 18. BOOTSTRAP 5.3 BRIDGE ------------------------------------------
     Retheme through Bootstrap's OWN variables first: no selector fights, no
     !important, and it reaches components we never wrote a rule for. This is
     what retunes every badge, every bg-opacity tint and every semantic text
     utility across 18+ views without a single new selector.                  */
  --bs-body-font-family: var(--kh-font);
  --bs-body-color:       var(--kh-ink);
  --bs-body-bg:          var(--kh-bg);
  --bs-emphasis-color:   var(--kh-ink);
  --bs-secondary-color:      var(--kh-ink-muted);
  --bs-secondary-color-rgb:  92,114,99;
  --bs-tertiary-color:   var(--kh-ink-muted);
  --bs-border-color:             var(--kh-edge-strong);
  --bs-border-color-translucent: var(--kh-edge);
  --bs-border-radius:    var(--kh-r-sm);
  --bs-border-radius-sm: var(--kh-r-xs);
  --bs-border-radius-lg: var(--kh-r-md);
  --bs-border-radius-xl: var(--kh-r-lg);
  --bs-border-radius-pill: var(--kh-r-pill);
  --bs-link-color:       var(--kh-link);
  --bs-link-color-rgb:   27,94,69;
  --bs-link-hover-color: var(--kh-brand-900);
  --bs-primary: #2C4A33;   --bs-primary-rgb: 44,74,51;
  --bs-success: #2E7D46;   --bs-success-rgb: 46,125,70;
  --bs-info:    #1F7F6B;   --bs-info-rgb:    31,127,107;  /* kills BS cyan    */
  --bs-warning: #E8A32B;   --bs-warning-rgb: 232,163,43;
  --bs-danger:  #B3261E;   --bs-danger-rgb:  179,38,30;
  --bs-focus-ring-color: rgba(27,94,69,.35);
  --bs-focus-ring-width: .25rem;
  --bs-table-bg:            transparent;
  --bs-table-color:         var(--kh-ink);
  --bs-table-border-color:  var(--kh-edge);
  --bs-table-hover-bg:      rgba(102,169,107,.07);
  --bs-table-hover-color:   var(--kh-ink);
  --bs-table-striped-bg:    rgba(167,215,197,.09);
  --bs-table-striped-color: var(--kh-ink);
  --bs-table-active-bg:     var(--kh-tint-strong);

  /* ---- 19. LEGACY ALIAS REMAP ---------------------------------------------
     Retires dead and wrong values across the views without touching a single
     .cshtml. This sheet loads last, so it beats BOTH existing :root blocks
     (site.css L1 and _Layout L12). --accent-color / --primary-green /
     --dark-green are pinned to their CURRENT values on purpose: 12 view-local
     blocks read them and would shift unpredictably otherwise.                */
  --bg-color:      var(--kh-bg);
  --accent-color:  #A7D7C5;
  --primary-green: #74B49B;
  --dark-green:    #3B5F41;
  --primary-color: #74B49B;
  --dark-color:    #2C4A33;   /* RETIRES the #5C8D89 teal that site.css pushes
                                 into .table thead th and .bg-dark            */
  --white:         #FFFFFF;
  --sidebar-color: var(--kh-rail-bot);
  --light-bg:      transparent;  /* _Layout L97 references var(--light-bg),
                                    defined NOWHERE today, so that declaration
                                    has always been invalid. Defining it
                                    deliberately as transparent resolves it to
                                    a no-op and seats #memberTabs on the plate.*/
}


/* ============================================================================
   02. DEGRADATION GATES -- token-level only, zero selector risk
   ============================================================================ */

/* No backdrop-filter support: raise the alphas so frosted surfaces stay
   legible instead of showing page content straight through them. */
@supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))){
  :root{
    --kh-surface-frost: rgba(255,255,255,.96);
    --kh-surface-veil:  rgba(255,255,255,.94);
    --kh-blur-chrome: 0px; --kh-blur-rail: 0px; --kh-blur-scrim: 0px;
  }
}

/* Collapsing --kh-blur-* to 0px here is what neutralises the layout's own
   inline `backdrop-filter: blur(10px)` on .top-bar: our higher-specificity
   `body .top-bar` rule re-declares the property as blur(0px). */
@media (prefers-reduced-transparency: reduce){
  :root{
    --kh-surface-frost: #FFFFFF;
    --kh-surface-veil:  #FFFFFF;
    --kh-surface-raised:#FFFFFF;
    --kh-scrim: rgba(11,26,19,.72);
    --kh-blur-chrome: 0px; --kh-blur-rail: 0px; --kh-blur-scrim: 0px;
    --kh-grid-ink: transparent; --kh-grid-node: transparent;
  }
}

@media (prefers-contrast: more){
  :root{
    --kh-ink-muted:   #3F5648;
    --kh-ink-faint:   #3F5648;
    --kh-edge:        rgba(44,74,51,.55);
    --kh-edge-strong: rgba(44,74,51,.80);
    --kh-edge-lum:    rgba(44,74,51,.80);
    --kh-surface-frost: #FFFFFF;
    --kh-surface-veil:  #FFFFFF;
    --kh-rail-ink-dim:  #C3D8CB;
  }
}

@media (prefers-reduced-motion: reduce){
  :root{
    --kh-t-press: 1ms; --kh-t-fast: 1ms; --kh-t-base: 1ms;
    --kh-t-slow:  1ms; --kh-t-max:  1ms;
    --kh-cycle-pulse: 0s; --kh-cycle-sweep: 0s;
  }
}


/* ============================================================================
   03. KEYFRAMES
   Only transform, opacity, background-position and (one-shot) box-shadow are
   ever animated. Nothing exceeds 420ms except the two transient/singleton
   loops. @keyframes slideIn is DELIBERATELY ABSENT -- it lives in the
   body-level <style> at _Layout L321 and its only consumer is the bare string
   'slideIn' inside element.style.cssText at L361, invisible to every linter.
   Defining it here would silently hijack the toast system.
   ============================================================================ */

@keyframes kh-reveal{
  from{ opacity:0; transform: translate3d(0,8px,0); }
  to  { opacity:1; transform: none; }
}
@keyframes kh-ignite{
  0%  { box-shadow: 0 0 0 0 rgba(140,242,200,0); }
  45% { box-shadow: 0 0 26px -4px rgba(140,242,200,.85); }
  100%{ box-shadow: 0 0 18px -6px rgba(140,242,200,.65); }
}
@keyframes kh-underline{
  from{ background-size: 0% 100%; }
  to  { background-size: 100% 100%; }
}
@keyframes kh-sheen{
  from{ background-position:   0% 50%; }
  to  { background-position: 200% 50%; }
}
@keyframes kh-sweep{
  from{ background-position:   0% 50%; }
  to  { background-position: 220% 50%; }
}
@keyframes kh-pulse{
  0%,100%{ box-shadow: 0 0 0 3px rgba(47,207,151,.28); }
  55%    { box-shadow: 0 0 0 8px rgba(47,207,151,0); }
}


/* ============================================================================
   04. BASE + THE GHOST LATTICE
   ============================================================================ */

body{
  font-family: var(--kh-font);
  color: var(--kh-ink);
  background-color: var(--kh-bg);
  letter-spacing: var(--kh-tracking-tight);
  /* every column of dates, counts, fees and membership numbers stops
     jittering as digit widths change */
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  min-height: 100vh;
}

/* THE GHOST LATTICE. A fixed-position pseudo-element, NOT
   background-attachment:fixed on body -- same image, no scroll repaint cost in
   Chromium. Node dot at each 64px cell centre, +30deg and -30deg triangulated
   struts at 74px pitch, all over the wash. Total ink <= 5.5%: invisible under
   content, resolves only in the gutters between plates and at the page edges.
   STATIC by contract -- see the vetoed crawling lattice. */
body::before{
  content:'';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-color: transparent;
  background-image:
    radial-gradient(circle at 50% 50%,
      var(--kh-grid-node) 0 1.2px, transparent 1.4px),
    repeating-linear-gradient(30deg,
      var(--kh-grid-ink) 0 1px, transparent 1px var(--kh-grid-strut)),
    repeating-linear-gradient(-30deg,
      var(--kh-grid-ink) 0 1px, transparent 1px var(--kh-grid-strut)),
    var(--kh-wash);
  /* --kh-wash is TWO gradients, so this element carries FIVE layers. All five
     sizes/repeats are listed explicitly: a shorter list cycles, and the wash
     would inherit the 64px tile. */
  background-size: var(--kh-grid-cell) var(--kh-grid-cell), auto, auto, auto, auto;
  background-repeat: repeat, repeat, repeat, no-repeat, no-repeat;
  background-position: 0 0, 0 0, 0 0, 0 0, 0 0;
}

::selection{ background-color: rgba(116,180,155,.34); color: var(--kh-ink); }

/* Page-level scrollbar, light side. */
body::-webkit-scrollbar{ width: 12px; height: 12px; }
body::-webkit-scrollbar-track{ background-color: transparent; }
body::-webkit-scrollbar-thumb{
  background-color: rgba(59,95,65,.22);
  border: 3px solid transparent;
  background-clip: content-box;
  border-radius: var(--kh-r-pill);
}
body::-webkit-scrollbar-thumb:hover{ background-color: rgba(59,95,65,.34); }


/* ============================================================================
   05. RAW TYPOGRAPHY
   Home/Privacy.cshtml and Shared/Error.cshtml have no card wrapper and no
   custom class at all, so they get nothing unless the bare elements are styled.
   ============================================================================ */

.main-content h1, .main-content h2, .main-content h3,
.main-content h4, .main-content h5{
  color: var(--kh-brand-900);
  font-weight: 700;
  letter-spacing: var(--kh-tracking-tight);
  line-height: 1.25;
}
.main-content h1{ font-size: var(--kh-fs-display); }
.main-content h2{ font-size: var(--kh-fs-xl); }
.main-content h3{ font-size: 1.3rem; }
.main-content h4{ font-size: var(--kh-fs-lg); }
.main-content h5{ font-size: 1.02rem; }

.main-content p{
  color: var(--kh-ink-soft);
  line-height: 1.6;
  max-width: 68ch;
}
.main-content code{
  font-family: var(--kh-font-mono);
  font-size: var(--kh-fs-xs);
  background-color: var(--kh-brand-100);
  color: var(--kh-brand-900);
  border-radius: var(--kh-r-xs);
  padding: 2px 6px;
}
hr{ border-color: var(--kh-edge); opacity: 1; }

a{ text-decoration-thickness: 1px; text-underline-offset: 2px; }

small, .small{ color: inherit; }


/* ============================================================================
   06. THE RAIL -- the 250px sidebar as the board's dark charcoal-green chassis
   ----------------------------------------------------------------------------
   STAYS display:block. It is NOT converted to flex-column: that would activate
   the currently-inert .mt-auto at _Layout L228 and snap the user chip to the
   viewport bottom, and with height:100% + overflow-y:auto + 22 nav links it
   would turn the nav into its own inner scroll region on short viewports.
   ============================================================================ */

body .sidebar{
  /* geometry preserved exactly: width/position/height/overflow are load-bearing
     for .main-content's matching 250px margin */
  width: 250px;
  position: fixed;
  top: 0;
  left: 0;
  height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
  z-index: var(--kh-z-sidebar);   /* it has none today and survives on paint
                                     order alone */
  color: var(--kh-rail-ink);
  background-color: var(--kh-rail-bot);
  /* struts first (they paint on top), chassis gradient last */
  background-image:
    repeating-linear-gradient(30deg,
      var(--kh-grid-ink-rail) 0 1px, transparent 1px var(--kh-grid-strut)),
    repeating-linear-gradient(-30deg,
      var(--kh-grid-ink-rail) 0 1px, transparent 1px var(--kh-grid-strut)),
    linear-gradient(180deg,
      var(--kh-rail-top) 0%, var(--kh-rail-bot) 62%, var(--kh-rail-deep) 100%);
  background-repeat: repeat, repeat, no-repeat;
  border-radius: 0 var(--kh-r-xl) var(--kh-r-xl) 0;
  box-shadow: var(--kh-e-rail);
  scrollbar-width: thin;
  scrollbar-color: rgba(167,215,197,.18) transparent;
}
body .sidebar::-webkit-scrollbar{ width: 10px; }
body .sidebar::-webkit-scrollbar-track{ background-color: transparent; }
body .sidebar::-webkit-scrollbar-thumb{
  background-color: rgba(167,215,197,.18);
  border: 3px solid transparent;
  background-clip: content-box;
  border-radius: var(--kh-r-pill);
}

/* The wordmark and the truncated username read light on the chassis with zero
   markup edits. */
body .sidebar h5,
body .sidebar .fw-bold{ color: var(--kh-rail-ink); letter-spacing: .01em; }

/* !important: Bootstrap 5.3 writes .text-secondary as
   `color: rgba(var(--bs-secondary-color-rgb), var(--bs-text-opacity)) !important`.
   Covers the 'CERTIFICATION' subtitle (L148) and the 'Administrator' role
   label (L235). */
body .sidebar .text-secondary{
  color: var(--kh-rail-ink-dim) !important;
  letter-spacing: var(--kh-tracking-label);
}

/* The two `hr.text-black-50` dividers at L199/L211 are invisible on dark:
   Bootstrap's hr is currentColor at opacity .25, and .text-black-50 forces a
   near-black currentColor with !important. */
body .sidebar hr{
  border-color: var(--kh-rail-edge) !important;
  opacity: 1 !important;
}

/* Replaces the inline style attribute on _Layout L144 once that edit lands.
   Stays near-white deliberately: the Khamo mark is a dark logo and needs a
   light tile on the dark chassis. */
.kh-logo-tile{
  width: 52px;
  height: 52px;
  margin: 0 auto 10px;
  padding: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(255,255,255,.90);
  border-radius: var(--kh-r-md);
  box-shadow: 0 0 0 1px rgba(167,215,197,.45), var(--kh-e1);
}

/* ---- The meridian spine ------------------------------------------------- */
body .sidebar .nav{ position: relative; }

/* One continuous track running the full height of the nav, fading at both
   ends. STATIC -- never animated. */
body .sidebar .nav::before{
  content:'';
  position: absolute;
  left: 14px;
  top: 10px;
  bottom: 10px;
  width: 2px;
  border-radius: 2px;
  pointer-events: none;
  background-image: linear-gradient(180deg,
    transparent 0%,
    var(--kh-rail-edge) 10%,
    var(--kh-rail-edge) 90%,
    transparent 100%);
}

/* ---- Nav links ----------------------------------------------------------
   This SCOPING is what stops the layout's unscoped .nav-link (L39-L58) leaking
   15px/20px padding, display:flex and border-left:4px into every Bootstrap tab
   strip in 5 views.
   !important on colour/background/border-left is unavoidable: site.css L43-L47
   sets .nav-link.active background-color and color with !important, and
   importance beats document order no matter where this sheet is linked. */
body .sidebar .nav-link{
  position: relative;
  display: flex;
  align-items: center;
  padding: 11px 18px 11px 34px;   /* left padding clears the spine + node */
  margin: 2px 10px 2px 0;
  border-radius: 0 var(--kh-r-md) var(--kh-r-md) 0;
  font-weight: 500;
  font-size: .92rem;
  color: var(--kh-rail-ink-idle) !important;
  background-color: transparent !important;
  background-image: none !important;
  border-left: 0 !important;
  box-shadow: none;
  transition:
    color var(--kh-t-fast) var(--kh-ease-out),
    background-color var(--kh-t-fast) var(--kh-ease-out),
    box-shadow var(--kh-t-base) var(--kh-ease-out);
}

/* The :not(.text-danger) guard is STRUCTURAL, not incidental: it protects the
   red Suspension link at _Layout L189 from being recoloured by a
   higher-specificity rule. */
body .sidebar .nav-link:not(.text-danger):hover{
  color: var(--kh-rail-ink) !important;
  background-color: var(--kh-rail-hover) !important;
}

body .sidebar .nav-link i{
  color: var(--kh-rail-ink-dim) !important;   /* beats the layout's
                                                 `.nav-link i { color:#66A96B }` */
  width: 20px;
  margin-right: 14px;
  text-align: center;
  transition: color var(--kh-t-fast) var(--kh-ease-out);
}
body .sidebar .nav-link:hover i{ color: var(--kh-brand-300) !important; }
body .sidebar .nav-link.active i{ color: var(--kh-mint) !important; }

/* THE STATION NODE. */
body .sidebar .nav-link.active:not(.text-danger){
  color: #EAFBEF !important;
  background-color: transparent !important;
  background-image: linear-gradient(90deg,
    var(--kh-rail-active) 0%, transparent 72%) !important;
  font-weight: 600;
  box-shadow: inset 3px 0 0 var(--kh-mint);
}

/* A real bloom -- this is the one place in the app with a ground dark enough
   to spend one on (#141F1A is far below the #2A3B31 glow floor). */
body .sidebar .nav-link.active:not(.text-danger)::before{
  content:'';
  position: absolute;
  left: 10px;
  top: 50%;
  width: 10px;
  height: 10px;
  margin-top: -5px;
  border-radius: 50%;
  background-color: var(--kh-flow-bright);
  box-shadow: var(--kh-glow-rail);
  pointer-events: none;
}

/* One-shot ignite at page load: glow spread travels 0 -> 26px -> 18px so the
   eye lands on 'where am I' before anything else. Class is added and removed
   by khamo-ui.js; skipped entirely under prefers-reduced-motion. */
body .sidebar .nav-link.active.kh-ignite::before{
  animation: kh-ignite var(--kh-t-max) var(--kh-ease-out) 1;
}

/* Bootstrap's .text-danger #dc3545 is 2.1:1 on the dark rail -- unreadable.
   #FF9E96 on #1A2620 is 7.6:1. Placed AFTER the .nav-link rule so it wins the
   equal-specificity tie on document order, and !important because
   .text-danger is itself an !important utility. Covers BOTH the Suspension
   nav link (L189) and the logout glyph in the user chip (L237). */
body .sidebar .text-danger{ color: var(--kh-rail-danger) !important; }
body .sidebar .text-danger:hover{ color: #FFC4BE !important; }

/* !important is exactly what beats the non-important inline
   style="color:#66A96B" on the Audit Portal and Lodgement Portal glyphs at
   L193/L196 -- a style attribute loses to an !important declaration, so no
   markup edit is needed. */
body .sidebar .fa-external-link-alt{
  color: var(--kh-mint) !important;
  opacity: .8;
}

/* The KA avatar chip at L230. */
body .sidebar .bg-primary{
  background-color: transparent !important;
  background-image: linear-gradient(135deg,#8CF2C8,#3E9E7A) !important;
  color: #10241C !important;
  font-weight: 700;
  border-radius: var(--kh-r-sm);
  box-shadow: 0 0 0 1px rgba(140,242,200,.35), var(--kh-glow-rail);
}

/* The four sidebar count pills seat on the dark rail. NO display declaration
   of any kind and NO animation: their hidden state is Bootstrap's .d-none
   (display:none !important) and the four pollers at _Layout L437-L484 depend
   on it. A display rule here would pin them permanently visible. */
#leads-badge, #support-badge, #enquiries-badge, #insurance-badge{
  box-shadow: 0 0 0 1px rgba(255,255,255,.14);
}


/* ============================================================================
   07. WORKSPACE + TOP BAR
   ============================================================================ */

/* max-width + min-width:0 clamp the PRE-EXISTING overflow caused by `w-100`
   and `margin-left:250px` landing on the same element (w-100 sets width, not
   max-width). Wide tables stop pushing 250px of horizontal page scroll on
   every list view. No markup change. */
body .main-content{
  margin-left: 250px;
  max-width: calc(100% - 250px);
  min-width: 0;
  padding: 20px 26px 48px;
}

body .top-bar{
  position: sticky;      /* it scrolls away today */
  top: 12px;
  z-index: var(--kh-z-topbar);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 20px;
  margin-bottom: 22px;
  border: 1px solid var(--kh-edge);
  border-radius: var(--kh-r-lg);
  background-color: var(--kh-surface-frost);
  box-shadow: var(--kh-e1), var(--kh-e-spec);
  transition:
    background-color var(--kh-t-base) var(--kh-ease-out),
    box-shadow var(--kh-t-base) var(--kh-ease-out);
  /* NO overflow:hidden -- it would clip any future dropdown. The busy rail is
     inset instead. */
}
/* `position: sticky` needs a positioned context for ::after; sticky IS
   positioned, so no extra declaration is required. */

/* THE ONE PERMITTED CHROME BLUR (the other two are the modal scrim and
   .kh-frost). Guarded so unsupported browsers keep the raised-alpha opaque
   fallback from section 02 and never show page content through the bar. */
@supports ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))){
  body .top-bar{
    -webkit-backdrop-filter: blur(var(--kh-blur-chrome)) saturate(var(--kh-sat));
    backdrop-filter: blur(var(--kh-blur-chrome)) saturate(var(--kh-sat));
  }
}

/* One rAF-throttled class flip at scrollY > 8 -- not a scroll-linked
   interpolation. */
body .top-bar.is-stuck{
  background-color: rgba(255,255,255,.88);
  box-shadow: var(--kh-e2), var(--kh-e-spec);
}

/* THE BUSY RAIL. Transient progress indication with real informational
   payload -- not ambient decoration. Visible only while html.kh-busy. */
body .top-bar::after{
  content:'';
  position: absolute;
  left: 16px;
  right: 16px;
  bottom: 6px;
  height: 2px;
  border-radius: 2px;
  background-image: var(--kh-rail-solid);
  background-size: 220% 100%;
  opacity: 0;
  transform: scaleX(0);
  transform-origin: left;
  pointer-events: none;
  transition:
    opacity var(--kh-t-fast) linear,
    transform var(--kh-t-slow) var(--kh-ease-out);
}
html.kh-busy .top-bar::after{
  opacity: 1;
  transform: scaleX(1);
  animation: kh-sweep var(--kh-cycle-sweep) linear infinite;
}

/* The 'Search for certificates, members...' control at L277-L280 is a static
   <div> + <span> with no input, no form, no id and no handler. It gets NO
   caret, NO focus ring, NO hover-expand and NO pointer cursor -- an affordance
   that lies costs a keystroke and a moment of doubt every time. Inert chrome
   until someone makes it real. */
body .top-bar .fa-search{ color: var(--kh-brand-700); }
body .top-bar span{ color: var(--kh-ink-muted); font-size: var(--kh-fs-sm); }

.btn-link{ color: var(--kh-link); text-decoration: none; }
.btn-link:hover{ color: var(--kh-brand-900); text-decoration: underline; }


/* ============================================================================
   08. DATA PLATES + THE TRUST SEAM
   ----------------------------------------------------------------------------
   NO backdrop-filter on .card-custom or .card at ANY alpha. Two independent
   failures: (1) a backdrop-filtered element becomes the containing block for
   position:fixed descendants and a new stacking context, which would reparent
   and clip the #rejectModal nested inside `<div class="card-custom ...">` at
   Views/Assessor/Create.cshtml L20/L541 -- the compliance refusal workflow
   would break silently, and only when somebody clicks Reject; (2) on
   Windows/Chromium the promoted layer drops text from subpixel to grayscale
   antialiasing, measurably degrading 11-13px uppercase column headers.
   Depth comes from the Trust Seam plus the three-step shadow ladder.
   ============================================================================ */

/* `body ` prefix raises (0,1,0) to (0,1,1) and beats the two .card-custom
   redefinitions that sit inside @section Scripts at the END of <body> in
   Assessor/Edit and Insurance/Index -- restoring the 25px padding those two
   pages silently lose today. */
body .card-custom{
  position: relative;
  background-color: var(--kh-surface);   /* OPAQUE #FFFFFF by rule */
  background-image: none;
  border: 0;
  border-radius: var(--kh-r-lg);
  padding: 25px;         /* UNCHANGED -- load-bearing for 21 views' rhythm */
  margin-bottom: 25px;   /* UNCHANGED */
  box-shadow: var(--kh-e1);
  transition: box-shadow var(--kh-t-base) var(--kh-ease-out);
  /* NO overflow:hidden -- it would clip Bootstrap dropdowns and tooltips in
     21 views. */
}

/* THE TRUST SEAM -- a masked 1px gradient hairline, white -> mint -> cyan ->
   white on a 140deg diagonal. A masked pseudo-element and NOT border-image,
   because border-image cannot follow an 18px radius.
   BASE = a plain 1px edge, so a browser without mask-composite still gets a
   correctly ringed plate rather than a solid gradient slab over the card. */
body .card-custom::before{
  content:'';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  border: 1px solid var(--kh-edge);
}
@supports ((-webkit-mask-composite: xor) or (mask-composite: exclude)){
  body .card-custom::before{
    border: 0;
    padding: 1px;
    background-image: var(--kh-seam);
    -webkit-mask: linear-gradient(#000 0 0) content-box,
                  linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
            mask: linear-gradient(#000 0 0) content-box,
                  linear-gradient(#000 0 0);
            mask-composite: exclude;
  }
}

/* The surface itself signals that the record is verified / insured /
   certified. Server-rendered additive class; no markup renames. */
body .card-custom.is-live::before,
body .card-custom.is-certified::before{
  background-image: var(--kh-seam-live);
  border-color: var(--kh-edge-live);
}
body .card-custom.is-live,
body .card-custom.is-certified{ box-shadow: var(--kh-e1), var(--kh-live-ring); }

/* Shadow step only -- NO transform. Plates hold dense text and must not
   resample it on hover. */
body .card-custom:hover{ box-shadow: var(--kh-e2); }

/* The parallel surface system (14 views) is brought into line so the app stops
   looking like two apps. Beats site.css L15-L18's mint border on document
   order -- no !important needed. */
body .card{
  background-color: var(--kh-surface);
  border: 1px solid var(--kh-edge);
  border-radius: var(--kh-r-lg);
  box-shadow: var(--kh-e1);
}
.card-header{
  background-color: var(--kh-surface-2);
  border-bottom: 1px solid var(--kh-edge);
  font-weight: 600;
  color: var(--kh-ink);
}
/* .bg-white is an !important utility, so matching it is unavoidable here. */
.card-header.bg-white{ background-color: var(--kh-surface-2) !important; }
.card-footer{
  background-color: var(--kh-surface-2);
  border-top: 1px solid var(--kh-edge);
}
/* `body ` prefix beats the Company/Create and Company/Edit redefinitions. */
body .card-title{ font-weight: 700; color: var(--kh-ink); }
body .card-subtitle{ color: var(--kh-ink-muted); }

/* TRANSLUCENCY WITHOUT BLUR -- alpha only, so no compositing layer and no
   containing block for fixed descendants. The lattice reads faintly through
   it at zero legibility cost. Light NON-DATA panels only. */
.kh-veil{
  background-color: var(--kh-surface-veil);
  border-radius: var(--kh-r-lg);
  box-shadow: var(--kh-e1);
}

/* REAL FROSTED GLASS. LEGAL ONLY on a dark or saturated ground: descendants of
   .sidebar, the modal scrim, and the login shell. NEVER on an element that
   contains a table, a form, or a Bootstrap modal. */
.kh-frost{
  background-color: var(--kh-surface-frost);
  border: 1px solid var(--kh-edge-inner);
  border-radius: var(--kh-r-md);
  box-shadow: var(--kh-e-spec);
}
@supports ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))){
  .kh-frost{
    -webkit-backdrop-filter: blur(var(--kh-blur-rail)) saturate(var(--kh-sat));
    backdrop-filter: blur(var(--kh-blur-rail)) saturate(var(--kh-sat));
  }
}
/* On the rail the glass is a light film on dark, not a white sheet. The
   markup's inline `background: rgba(255,255,255,0.05)` at L229 is a style
   attribute and wins over this declaration -- which is fine, it is the same
   intent; this rule supplies the border, blur and specular that the inline
   style does not. */
body .sidebar .kh-frost{
  background-color: var(--kh-rail-glass);
  border-color: var(--kh-rail-edge);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.06);
}


/* ============================================================================
   09. STAT CARDS
   ============================================================================ */

body .stat-card{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
}
body .stat-card h2{
  font-size: var(--kh-fs-display);
  font-weight: 800;
  letter-spacing: -.02em;
  color: var(--kh-brand-900);
  font-variant-numeric: tabular-nums;
  margin: 0;
  line-height: 1.1;
}
body .stat-card h6{
  font-size: var(--kh-fs-micro);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--kh-tracking-label);
  color: var(--kh-ink-muted);
  margin: 0 0 6px;
}

/* Sets background-IMAGE (a white specular wash) and deliberately NOT
   background-color, so the markup's `bg-primary bg-opacity-10` / `bg-success`
   / `bg-info` / `bg-danger` utility still supplies the semantic tint and
   stays semantic. */
body .stat-icon{
  width: 46px;
  height: 46px;
  border-radius: var(--kh-r-md);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  font-size: 20px;
  background-image: linear-gradient(160deg,
    rgba(255,255,255,.45) 0%, rgba(255,255,255,0) 62%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.7), var(--kh-e1);
}


/* ============================================================================
   10. BUTTONS + COLOUR UTILITIES
   ============================================================================ */

.btn{
  font-family: var(--kh-font);
  font-weight: 600;
  letter-spacing: .005em;
  border-radius: var(--kh-r-pill);
  /* transform MUST be listed explicitly: Bootstrap's own .btn transition omits
     it, which is why the existing -2px primary-button lift SNAPS on every
     button in the app today. */
  transition:
    color var(--kh-t-fast) var(--kh-ease-out),
    background-color var(--kh-t-fast) var(--kh-ease-out),
    border-color var(--kh-t-fast) var(--kh-ease-out),
    box-shadow var(--kh-t-fast) var(--kh-ease-out),
    transform var(--kh-t-fast) var(--kh-ease-out);
}
.btn:active{ transform: translateY(0) scale(.985); transition-duration: var(--kh-t-press); }

/* !important is mandatory on background/border/colour: site.css L20-L24 sets
   all three with !important and importance beats document order.
   The lightest gradient stop is #46794E = 5.12:1 under white; the current
   #66A96B start is 2.82:1 and fails AA. */
.btn-primary{
  position: relative;
  isolation: isolate;
  background-color: var(--kh-brand-750) !important;
  background-image: var(--kh-btn-fill) !important;
  border: 1px solid rgba(15,81,50,.20) !important;
  color: #fff !important;
  padding: .55rem 1.35rem;
  box-shadow: var(--kh-e1), inset 0 1px 0 rgba(140,242,200,.32);
}

/* THE MINT SHEEN. Inside isolation:isolate a z-index:-1 child paints above the
   button's own background but below its text -- so the brand's luminous green
   survives on the most-clicked surface in the app without white-on-mint ever
   happening. */
.btn-primary::after{
  content:'';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  background-image: var(--kh-btn-sheen);
  background-size: 260% 100%;
  background-position: 0% 50%;
  transition: opacity var(--kh-t-fast) linear;
}
.btn-primary:hover{
  background-image: var(--kh-btn-fill-hover) !important;
  color: #fff !important;
  transform: translateY(-1px);
  box-shadow: var(--kh-e2), inset 0 1px 0 rgba(140,242,200,.45);
}
.btn-primary:hover::after{
  opacity: 1;
  animation: kh-sheen var(--kh-t-slow) var(--kh-ease-out) 1;
}
.btn-primary:active{ transform: translateY(0) scale(.985); }
.btn-primary:focus-visible{
  box-shadow: var(--kh-focus-ring) !important;   /* beats site.css's !important
                                                    background/border stack */
  outline: 0;
}

/* RESTORES SEMANTIC AMBER. site.css L20-L29 repaints .btn-warning AND
   .text-warning to the scheme green with !important, so 'Email failed',
   'COI Not Declared' and 'Unassigned tutor' currently render as success green
   in 7 views. Dark ink #3B2A05 on #E8A32B = 6.39:1 -- never white on dark amber
   (that composite is 4.06:1 and fails).
   FLAGGED CHANGE: ships with before/after screenshots. */
.btn-warning{
  background-color: var(--kh-warn-solid) !important;
  background-image: none !important;
  border-color: transparent !important;
  color: var(--kh-warn-on) !important;
}
.btn-warning:hover{
  background-color: #D9941F !important;
  border-color: transparent !important;
  color: var(--kh-warn-on) !important;
}
.text-warning{ color: var(--kh-warn-ink) !important; }   /* 6.4:1 */

/* OUTLINE VARIANTS -- nothing in the app has ever overridden these, so every
   'Edit' button in 11 views, every secondary in 13 and every danger in 4
   renders stock Bootstrap blue/grey inside a sage-green scheme. Fixed purely
   through Bootstrap's own --bs-btn-* custom properties: no !important, no
   specificity fight. Widest single win in the theme -- 22 views, one block. */
.btn-outline-primary{
  --bs-btn-color: var(--kh-brand-850);
  --bs-btn-border-color: var(--kh-edge-lum);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--kh-brand-850);
  --bs-btn-hover-border-color: var(--kh-brand-850);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--kh-brand-900);
  --bs-btn-active-border-color: var(--kh-brand-900);
  --bs-btn-disabled-color: var(--kh-ink-faint);
  --bs-btn-disabled-border-color: var(--kh-edge);
  --bs-btn-focus-shadow-rgb: 116,180,155;
}
.btn-outline-secondary{
  --bs-btn-color: var(--kh-ink-muted);
  --bs-btn-border-color: var(--kh-edge-strong);
  --bs-btn-hover-color: var(--kh-ink);
  --bs-btn-hover-bg: var(--kh-brand-100);
  --bs-btn-hover-border-color: var(--kh-edge-lum);
  --bs-btn-active-color: var(--kh-ink);
  --bs-btn-active-bg: var(--kh-brand-200);
  --bs-btn-active-border-color: var(--kh-edge-lum);
  --bs-btn-disabled-color: var(--kh-ink-faint);
  --bs-btn-disabled-border-color: var(--kh-edge);
  --bs-btn-focus-shadow-rgb: 116,180,155;
}
.btn-outline-danger{
  --bs-btn-color: var(--kh-danger);
  --bs-btn-border-color: rgba(179,38,30,.45);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--kh-danger);
  --bs-btn-hover-border-color: var(--kh-danger);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: #8F1E17;
  --bs-btn-active-border-color: #8F1E17;
  --bs-btn-focus-shadow-rgb: 179,38,30;
}
.btn-outline-success{
  --bs-btn-color: var(--kh-ok);
  --bs-btn-border-color: rgba(46,125,70,.45);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--kh-ok);
  --bs-btn-hover-border-color: var(--kh-ok);
  --bs-btn-focus-shadow-rgb: 46,125,70;
}

/* RESTORES Bootstrap's bg-opacity mechanism, which the layout's flat
   `background-color: var(--primary-green) !important` at L116-L118 currently
   destroys, AND moves the solid value to #2C4A33 (9.1:1 under white) from
   #74B49B (2.40:1). `bg-primary bg-opacity-10` on the dashboard stat icons
   keeps working and becomes a correct soft tint. */
.bg-primary{
  background-color: rgba(var(--bs-primary-rgb), var(--bs-bg-opacity, 1)) !important;
}
/* Two conflicting definitions (site.css #74B49B, layout #3B5F41) collapse into
   one, and text-opacity support comes back. Used in 23 views. */
.text-primary{
  color: rgba(var(--bs-primary-rgb), var(--bs-text-opacity, 1)) !important;
}
/* Retires site.css's #5C8D89 teal on the Price/Index thead and the
   Support/Index stat card. */
.bg-dark{ background-color: var(--kh-brand-950) !important; }

/* STAYS GENUINELY OPAQUE. Support/Index L143 knocks 'DEV ACTIONS' out of an
   absolutely-positioned rule using `bg-white pe-3`; the trick dies the instant
   this utility goes translucent. Also load-bearing for .strand-card in
   Suspension/Index and the bg-white panels in Register, Leads and Training. */
.bg-white{ background-color: #FFFFFF !important; }

/* .text-info / .text-success / .text-danger / .text-secondary / .bg-success /
   .bg-info / .bg-danger / .bg-warning are DELIBERATELY NOT REDECLARED.
   Bootstrap 5.3 computes all of them from --bs-*-rgb, which section 18 remaps
   -- including the Bootstrap cyan #0dcaf0 heading on Company/Index and the cyan
   'New Companies' KPI on the dashboard. */


/* ============================================================================
   11. TABLES
   ----------------------------------------------------------------------------
   Restyled ONLY through Bootstrap's own --bs-table-* custom properties. This
   sheet NEVER writes `.table > :not(caption) > * > * { box-shadow: none }`
   and never writes cell-level background rules on that selector: that inset
   9999px box-shadow IS Bootstrap 5.3's striping and hover mechanism, and a
   rule matching it at equal specificity but later in the cascade silently
   de-stripes WebEnquiries/Index and removes hover from all 27 tables.
   ============================================================================ */

body .table{
  --bs-table-bg: transparent;
  --bs-table-color: var(--kh-ink);
  --bs-table-border-color: var(--kh-edge);
  --bs-table-hover-bg: rgba(102,169,107,.07);
  --bs-table-hover-color: var(--kh-ink);
  --bs-table-striped-bg: rgba(167,215,197,.09);
  --bs-table-striped-color: var(--kh-ink);
  --bs-table-active-bg: var(--kh-tint-strong);
  font-size: var(--kh-fs-sm);
  margin-bottom: 0;
}

/* KILLS THE DARK-TEAL BAND. site.css L49-L52 paints every header cell #5C8D89
   with white text, silently defeating the `<thead class="bg-light">` markup in
   ~20 views. Specificity here is (0,1,4) and (0,1,3), both above site.css's
   (0,1,2) and above the Assessor/Index view-local copy.
   The box-shadow is the lattice datum line. */
body .table > thead > tr > th,
body .table thead th,
body .rm-table thead th{
  background-color: transparent;
  background-image: linear-gradient(180deg,
    rgba(167,215,197,.18), rgba(167,215,197,.05));
  color: var(--kh-ink-muted);
  font-size: var(--kh-fs-micro);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--kh-tracking-label);
  padding: 12px 14px;
  white-space: nowrap;
  vertical-align: middle;
  border-bottom: 1px solid var(--kh-edge-strong);
  box-shadow: inset 0 -2px 0 -1px rgba(167,215,197,.45);
}
body .table > thead > tr > th a,
body .table thead th a{ color: inherit; text-decoration: none; }
body .table > thead > tr > th a:hover,
body .table thead th a:hover{ color: var(--kh-brand-900); }
/* NOTE: the inline `style="background-color:#f8fafc !important"` on
   Views/Assessor/Index.cshtml L69 is a style-attribute !important and is
   unbeatable from any stylesheet. It must be deleted in markup. */

/* Rows stay at 44px -- not 56, not 64. NO position:relative on every td and NO
   pseudo-elements on td (see the row rail below). */
body .table > tbody > tr > td,
body .table tbody td,
body .rm-table tbody td{
  padding: .7rem 14px;
  min-height: var(--kh-row-h);
  vertical-align: middle;
  color: var(--kh-ink);
  border-color: var(--kh-edge);
}

/* Transition list is background-color and box-shadow AND NOTHING ELSE. No
   transform, no lift, no scale, ever: a 200-row list must never repaint
   geometry or resample subpixel antialiasing while somebody scans it. This
   deliberately removes the existing -1px hover lift on .rm-table. */
body .table tbody tr,
body .rm-table tbody tr{
  transition:
    background-color var(--kh-t-fast) var(--kh-ease-out),
    box-shadow var(--kh-t-fast) var(--kh-ease-out);
}

/* .rm-table is UNIFIED, not preserved. The floating row-card mechanic
   (border-spacing: 0 8px + per-row shadows) costs ~200px of vertical scan per
   25-row screen, fights Bootstrap's accent-bg inset-shadow painting, and
   inside the 27 .table-responsive wrappers (overflow-x:auto computes
   overflow-y to auto) transformed rows contribute to scrollable overflow and
   flicker a scrollbar. `body ` prefix beats the 153-line view-local <style>
   block, which sits in <body> after @RenderBody(). */
body .rm-table{
  border-collapse: collapse;
  border-spacing: 0;
  width: 100%;
}
body .rm-table tbody tr{
  background-color: transparent !important;   /* the view-local block sets a
                                                 per-row white card fill */
  box-shadow: none;
  transform: none !important;                 /* kills the -1px lift */
}
body .rm-table tbody tr td:first-child,
body .rm-table tbody tr td:last-child{ border-radius: 0; }

/* THE ROW RAIL -- hover state. Drawn as a composed inset box-shadow and NEVER
   as a td::before: Insurance/Index L111 puts a select-row checkbox in the
   first cell, and a pseudo-element there would need pointer-events:none plus
   position:relative on every <td> in the app.
   The second shadow layer replicates Bootstrap 5.3's own accent painting
   underneath our rail, so striping and hover tint survive on the first cell
   instead of being wiped by our declaration. */
body .table-hover > tbody > tr:hover > td:first-child,
body .rm-table tbody tr:hover > td:first-child{
  box-shadow:
    inset var(--kh-rail-w) 0 0 0 var(--kh-brand-600),
    inset 0 0 0 9999px var(--bs-table-bg-state,
                        var(--bs-table-bg-type,
                        var(--bs-table-accent-bg, transparent)));
}

/* THE LIT ROW -- a state channel at the far-left edge, so a 200-row list
   becomes scannable by state before a single word is read. Additive
   server-rendered classes; no existing name touched.
   On these LIGHT grounds 'live' is a SOLID fill plus a 1px ring -- never a
   bloom. There is no dark ground here to spend a glow on. */
body tr.is-live > td:first-child{
  box-shadow:
    inset var(--kh-rail-w) 0 0 0 var(--kh-flow),
    inset 0 0 0 9999px var(--bs-table-bg-state,
                        var(--bs-table-bg-type,
                        var(--bs-table-accent-bg, transparent)));
}
body tr.is-live > td:last-child{ box-shadow: var(--kh-live-ring); }
body tr.is-done > td:first-child{
  box-shadow:
    inset var(--kh-rail-w) 0 0 0 var(--kh-brand-900),
    inset 0 0 0 9999px var(--bs-table-bg-state,
                        var(--bs-table-bg-type,
                        var(--bs-table-accent-bg, transparent)));
}
body tr.is-blocked > td:first-child{
  box-shadow:
    inset var(--kh-rail-w) 0 0 0 var(--kh-danger),
    inset 0 0 0 9999px var(--bs-table-bg-state,
                        var(--bs-table-bg-type,
                        var(--bs-table-accent-bg, transparent)));
}
/* :focus-within only fires on Members/Index once khamo-ui.js adds tabindex to
   its `<tr onclick>` rows -- that is the app's only route to keyboarding a
   list today. */
body tr.is-lit > td,
body tr:focus-within > td{
  box-shadow:
    inset 0 -2px 0 -1px var(--kh-brand-500),
    inset 0 0 0 9999px rgba(102,169,107,.09);
}
body tr.is-lit > td:first-child,
body tr:focus-within > td:first-child{
  box-shadow:
    inset var(--kh-rail-w) 0 0 0 var(--kh-mint),
    inset 0 -2px 0 -1px var(--kh-brand-500),
    inset 0 0 0 9999px rgba(102,169,107,.09);
}

.table-responsive{ border-radius: var(--kh-r-md); }
/* NO max-height and NO sticky thead in v1: .table-responsive's overflow-x:auto
   computes overflow-y to auto, making it a scroll container that silently
   breaks page-level position:sticky on <th>. */


/* ============================================================================
   12. FORMS -- three competing input treatments collapse into one
   ============================================================================ */

body .form-control,
body .form-select{
  background-color: var(--kh-surface);
  color: var(--kh-ink);
  border: 1px solid var(--kh-edge-strong);
  border-radius: var(--kh-r-sm);
  padding: .6rem .85rem;
  font-family: var(--kh-font);
  font-size: var(--kh-fs-sm);
  box-shadow: inset 0 1px 2px rgba(20,40,28,.03);
  transition:
    border-color var(--kh-t-fast) var(--kh-ease-out),
    box-shadow var(--kh-t-fast) var(--kh-ease-out),
    background-color var(--kh-t-fast) var(--kh-ease-out);
}
body .form-control::placeholder{ color: var(--kh-ink-muted); opacity: 1; }
body .form-control:hover,
body .form-select:hover{ border-color: var(--kh-edge-lum); }
body .form-control:disabled,
body .form-control[readonly],
body .form-select:disabled{
  background-color: var(--kh-surface-sunk);
  color: var(--kh-ink-muted);
}

/* ONE focus ring for the whole app, at 5.99:1. Retires site.css's
   `0 0 0 .25rem rgba(116,180,155,.25)` and Members/Index's 4px/.15 twin, both
   of which composite to roughly 1.25:1 and are effectively invisible.
   The lit baseline is a box-shadow and NEVER a background-image, because
   .form-select carries its caret in background-image. */
body .form-control:focus,
body .form-select:focus,
body .rm-search:focus{
  border-color: var(--kh-flow-deep);
  outline: 0;
  box-shadow: var(--kh-focus-ring), inset 0 -2px 0 0 var(--kh-brand-600);
}

.form-label,
.col-form-label,
.kh-field-label{
  font-size: var(--kh-fs-micro);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--kh-tracking-label);
  color: var(--kh-ink-muted);
  margin-bottom: 6px;
}

/* `body ` prefix beats the Assessor/Edit end-of-body block. SIZING IS NOT
   TOUCHED -- Suspension/Index overrides .form-switch .form-check-input to
   3em x 1.5em page-globally and must not be fought. */
body .form-check-input:checked{
  background-color: var(--kh-brand-700);
  border-color: var(--kh-brand-700);
}
body .form-check-input:focus{ box-shadow: var(--kh-focus-ring); border-color: var(--kh-flow-deep); }

.input-group-text{
  background-color: var(--kh-surface-sunk);
  border-color: var(--kh-edge-strong);
  color: var(--kh-ink-muted);
}

/* Bootstrap's validation mechanics are otherwise untouched -- no green, no
   glow, no softening. */
.was-validated .form-control:invalid,
.form-control.is-invalid,
.was-validated .form-select:invalid,
.form-select.is-invalid{ border-color: var(--kh-danger); }
.invalid-feedback{ color: var(--kh-danger); font-size: var(--kh-fs-xs); }


/* ============================================================================
   13. FOCUS -- the app's first keyboard affordance
   :where() contributes ZERO specificity, so this rule cannot break any
   existing view and is trivially overridden where a component needs its own
   ring. The weak rings that were considered and rejected: 3px
   rgba(116,180,155,.28) composites to #D8EAE3 = 1.25:1 on white, and a 2px
   #66A96B outline is 2.82:1 -- both fail WCAG 2.2 SC 2.4.11's 3:1 floor.
   ============================================================================ */

:where(a, button, [tabindex], .nav-link, .page-link, [role="button"]):focus-visible{
  outline: var(--kh-focus-outline);
  outline-offset: 2px;
  border-radius: var(--kh-r-sm);
}
.sidebar :where(a, button, [tabindex], .nav-link, [role="button"]):focus-visible{
  outline-color: var(--kh-mint);
}


/* ============================================================================
   14. TABS -- five competing active-tab designs collapse into one underline
   ----------------------------------------------------------------------------
   (0,3,2) with the `body ` prefix beats the layout's unscoped .nav-link, the
   three `.nav-tabs .nav-link` blocks in Assessor/Edit, Insurance/Index and
   Register/Index (two of which sit at the end of <body>), and Support/Index's
   .nav-tabs-custom. !important on colour/background is still required because
   site.css L43-L47 sets .nav-link.active with !important.
   ============================================================================ */

.nav-tabs,
.nav-pills{ border-bottom: 1px solid var(--kh-edge-strong); gap: 2px; }

body .nav-tabs .nav-item .nav-link,
body .nav-pills .nav-item .nav-link{
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: .62rem 1rem !important;      /* undoes the sidebar rule's leaked
                                           15px/20px */
  border: 0 !important;
  border-left: 0 !important;
  margin: 0;
  border-radius: var(--kh-r-sm) var(--kh-r-sm) 0 0;
  background-color: transparent !important;
  background-image: none !important;
  color: var(--kh-ink-muted) !important;
  font-weight: 600;
  box-shadow: none;
  transition: color var(--kh-t-fast) var(--kh-ease-out);
}
/* Undoes the layout's `.nav-link i { margin-right:15px; width:20px;
   color:#66A96B }` leak inside tab strips. */
body .nav-tabs .nav-item .nav-link i,
body .nav-pills .nav-item .nav-link i{
  color: inherit !important;
  margin-right: 0 !important;
  width: auto !important;
}
body .nav-tabs .nav-item .nav-link:hover,
body .nav-pills .nav-item .nav-link:hover{ color: var(--kh-ink) !important; }

/* No more opaque white notch welded to the plate. Identity comes from the
   underline bar below -- the same rail primitive as the sidebar spine and the
   row rail, rotated 90 degrees. */
body .nav-tabs .nav-item .nav-link.active,
body .nav-pills .nav-item .nav-link.active{
  color: var(--kh-brand-900) !important;
  background-color: transparent !important;
  background-image: none !important;
}
body .nav-tabs .nav-item .nav-link.active::after,
body .nav-pills .nav-item .nav-link.active::after{
  content:'';
  position: absolute;
  left: 12%;
  right: 12%;
  bottom: -1px;
  height: 2px;
  border-radius: 2px;
  background-image: var(--kh-rail-solid);
  background-size: 100% 100%;
  background-repeat: no-repeat;
  animation: kh-underline var(--kh-t-fast) var(--kh-ease-out) 1;
  pointer-events: none;
}

/* #memberTabs needs matching ID weight PLUS !important to beat _Layout
   L80-L99, which uses an ID selector and !important on every declaration.
   --light-bg is now defined (section 19) as transparent, so L97's
   permanently-invalid declaration finally resolves -- deliberately to a no-op. */
#memberTabs{
  background-color: transparent !important;
  border-bottom: 1px solid var(--kh-edge-strong) !important;
}
#memberTabs .nav-link{
  padding: .62rem 1rem !important;
  background-color: transparent !important;
  color: var(--kh-ink-muted) !important;
  border: 0 !important;
  border-radius: var(--kh-r-sm) var(--kh-r-sm) 0 0 !important;
  box-shadow: none !important;
}
#memberTabs .nav-link.active{
  background-color: transparent !important;
  color: var(--kh-brand-900) !important;
  border: 0 !important;
  box-shadow: inset 0 -2px 0 0 var(--kh-brand-600) !important;
}

/* Support/Index's fifth tab idiom, folded into the same underline. */
.nav-tabs-custom .nav-link{ color: var(--kh-ink-muted); font-weight: 600; }
.nav-tabs-custom .nav-link.active{
  color: var(--kh-brand-900);
  border-bottom-color: var(--kh-brand-600) !important;
}


/* ============================================================================
   15. BADGES, THE ONE STATUS PILL, AND THE SOFT-BADGE SHIM
   ============================================================================ */

.badge{
  --bs-badge-font-weight: 700;
  --bs-badge-font-size: var(--kh-fs-micro);
  --bs-badge-padding-x: .7em;
  --bs-badge-padding-y: .4em;
  --bs-badge-border-radius: var(--kh-r-pill);
  letter-spacing: .02em;
}

/* THE ONE STATUS PILL, absorbing five competing families. */
.kh-state{
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 4px 12px;
  border-radius: var(--kh-r-pill);
  font-size: var(--kh-fs-micro);
  font-weight: 700;
  line-height: 1.5;
  white-space: nowrap;
  border: 1px solid transparent;
  background-color: var(--kh-neutral-tint);
  color: #3F5348;
}
.kh-state::before{
  content:'';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background-color: currentColor;
  flex: 0 0 auto;
  /* NO pulse here, ever: this selector can match inside a <tbody>, and a
     25-row list would become 25 halos breathing in the data area. */
}
.kh-state--prospect{ background-color: var(--kh-neutral-tint); color: #3F5348; }
.kh-state--active{
  background-color: rgba(47,207,151,.14);
  color: var(--kh-live-ink);
  border-color: var(--kh-edge-live);
}
.kh-state--certified{
  background-color: rgba(15,81,50,.10);
  color: var(--kh-live-ink);
  border-color: var(--kh-edge-live);
}
.kh-state--pending{ background-color: var(--kh-warn-tint); color: var(--kh-warn-ink); }
.kh-state--blocked{ background-color: var(--kh-danger-tint); color: var(--kh-danger-ink); }
.kh-state--info{ background-color: var(--kh-info-tint); color: var(--kh-info); }

/* THE POSITION MICRO-TRACK. Encodes pipeline position as LENGTH as well as
   hue -- the only colour-blind-safe status channel in the design. Set the fill
   with an inline `style="--seg:66%"`.
   RESTRICTED BY RULE to detail-view headers and single-record contexts. It
   must NOT be applied to list-view chips: a hundred micro-tracks per page
   turns the signature into wallpaper and devalues the one real stage
   indicator. That is why it is an opt-in modifier and not part of .kh-state. */
.kh-state--track::after{
  content:'';
  width: 18px;
  height: 2px;
  border-radius: 1px;
  flex: 0 0 auto;
  opacity: .62;
  background-image: linear-gradient(90deg,
    currentColor 0 var(--seg,33%), rgba(28,42,32,.14) var(--seg,33%) 100%);
}
.kh-state--blocked.kh-state--track::after{
  background-image: repeating-linear-gradient(90deg,
    currentColor 0 3px, transparent 3px 6px);
}

/* A standalone state dot for detail headers and the system-status indicator.
   Static by default. */
.kh-dot{
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: var(--kh-ink-faint);
  box-shadow: 0 0 0 3px rgba(92,114,99,.16);
}
.kh-dot.is-live{
  background-color: var(--kh-flow);
  box-shadow: 0 0 0 3px rgba(47,207,151,.28);
}

/* THE ONLY AMBIENT LOOP IN THE APP, and it is a SINGLETON BY CONTRACT: at most
   ONE element per page, and NEVER inside a <tbody>. */
.kh-pulse{ animation: kh-pulse var(--kh-cycle-pulse) var(--kh-ease-in-out) infinite; }

/* COMPATIBILITY SHIM -- converges the five divergent soft-badge families onto
   the .kh-state palette with ZERO markup edits. !important is required because
   three of the source blocks sit at the end of <body> and win on order.
   This ALSO defines .bg-warning-soft globally, which Assessor/Index L88
   applies but only Suspension/Index defines -- unregistered-person avatars
   silently render mint today. */
.bg-success-soft,
.badge.bg-success-soft,
.rm-status.on,
.status-pill.on{
  background-color: rgba(47,207,151,.14) !important;
  color: var(--kh-live-ink) !important;
}
.bg-danger-soft,
.badge.bg-danger-soft,
.rm-status.off,
.status-pill.off{
  background-color: var(--kh-danger-tint) !important;
  color: var(--kh-danger-ink) !important;
}
.bg-warning-soft,
.badge.bg-warning-soft{
  background-color: var(--kh-warn-tint) !important;
  color: var(--kh-warn-ink) !important;
}
.bg-soft-primary,
.bg-soft-success,
.bg-soft-info{
  background-color: var(--kh-tint) !important;
  color: var(--kh-brand-800) !important;
}
.rm-status,
.status-pill,
.scheme-badge{
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 4px 12px;
  border-radius: var(--kh-r-pill);
  font-size: var(--kh-fs-micro);
  font-weight: 700;
  line-height: 1.5;
  white-space: nowrap;
}
.rm-status .dot,
.status-pill .dot{
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background-color: currentColor;
  /* NO pulse -- see .kh-state::before. */
}


/* ============================================================================
   16. FILTER CHIPS + PAGINATION
   Active state on a chip is a FILL, not a glow -- and it is the same
   var(--kh-btn-fill) recipe as .btn-primary and .rm-page-btn.current, so
   'selected' means one thing across the whole app.
   ============================================================================ */

.kh-chip,
.rm-chip{
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--kh-edge-strong);
  background-color: var(--kh-surface);
  color: var(--kh-ink-soft);
  border-radius: var(--kh-r-pill);
  padding: 6px 16px;
  font-size: .82rem;
  font-weight: 600;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition:
    color var(--kh-t-fast) var(--kh-ease-out),
    background-color var(--kh-t-fast) var(--kh-ease-out),
    border-color var(--kh-t-fast) var(--kh-ease-out),
    box-shadow var(--kh-t-fast) var(--kh-ease-out),
    transform var(--kh-t-fast) var(--kh-ease-out);
}
.kh-chip:hover,
.rm-chip:hover{
  background-color: var(--kh-brand-100);
  border-color: var(--kh-edge-lum);
  color: var(--kh-ink);
  transform: translateY(-1px);
}
.kh-chip:active,
.rm-chip:active{ transform: translateY(0) scale(.985); transition-duration: var(--kh-t-press); }
.kh-chip.active,
.rm-chip.active,
.kh-chip.current,
.rm-chip.current{
  background-color: var(--kh-brand-750);
  background-image: var(--kh-btn-fill);
  border-color: transparent;
  color: #fff;
  box-shadow: 0 4px 12px -6px rgba(59,95,65,.6);
}

.pagination{ gap: 4px; }
.page-link,
.rm-page-btn{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 36px;
  height: 36px;
  border-radius: var(--kh-r-sm);
  border: 1px solid var(--kh-edge-strong);
  background-color: var(--kh-surface);
  color: var(--kh-ink-soft);
  font-weight: 600;
  font-size: var(--kh-fs-sm);
  text-decoration: none;
  transition:
    color var(--kh-t-fast) var(--kh-ease-out),
    background-color var(--kh-t-fast) var(--kh-ease-out),
    border-color var(--kh-t-fast) var(--kh-ease-out),
    transform var(--kh-t-fast) var(--kh-ease-out);
}
.page-link:hover,
.rm-page-btn:hover{ background-color: var(--kh-brand-100); color: var(--kh-ink); }
.page-link:active,
.rm-page-btn:active{ transform: translateY(0) scale(.985); transition-duration: var(--kh-t-press); }
.page-item.active .page-link,
.rm-page-btn.current{
  background-color: var(--kh-brand-750);
  background-image: var(--kh-btn-fill);
  border-color: transparent;
  color: #fff;
}
.page-item.disabled .page-link,
.rm-page-btn.disabled{
  opacity: .35;
  pointer-events: none;
  background-color: var(--kh-surface);
  color: var(--kh-ink-muted);
}
.rm-pagination{ display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }


/* ============================================================================
   17. MASTHEAD, KPI PILLS, AND THE BRANCH ROW
   ============================================================================ */

/* Promoted out of Members/Index and un-nested so .kh-page-icon is standalone.
   Home/Index has NO header at all today and Company/Index has a bare
   `<h4 class="text-info">`; this gives all 37 views one masthead. */
.kh-page-header,
.rm-header{
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 15px;
  margin-bottom: 22px;
}
.kh-page-header h1,
.kh-page-header h2,
.kh-page-header h3,
.kh-page-header h4{ margin: 0; }
.kh-page-header .kh-page-sub,
.rm-header .kh-page-sub{
  color: var(--kh-ink-muted);
  font-size: var(--kh-fs-sm);
  margin: 4px 0 0;
}
.kh-page-icon,
.rm-header .icon-badge{
  width: 46px;
  height: 46px;
  border-radius: var(--kh-r-md);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  font-size: 20px;
  background-image: linear-gradient(135deg,#74B49B,#3B5F41);
  color: #fff;
  box-shadow: 0 6px 18px -8px rgba(59,95,65,.5);
}

.kh-stat,
.rm-stat-pill{
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  background-color: var(--kh-surface);
  border: 1px solid var(--kh-edge);
  border-radius: var(--kh-r-md);
  padding: 8px 18px;
  min-width: 110px;
  box-shadow: var(--kh-e1);
  transition:
    box-shadow var(--kh-t-fast) var(--kh-ease-out),
    transform var(--kh-t-fast) var(--kh-ease-out);
}
.kh-stat:hover,
.rm-stat-pill:hover{ transform: translateY(-1px); box-shadow: var(--kh-e2); }
.kh-stat .num,
.rm-stat-pill .num{
  font-size: 1.35rem;
  font-weight: 700;
  color: var(--kh-brand-900);
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
}
.kh-stat .lbl,
.rm-stat-pill .lbl{
  font-size: var(--kh-fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--kh-tracking-label);
  color: var(--kh-ink-muted);
  font-weight: 700;
}
/* These three modifiers exist so the two inline hex colours on
   Members/Index L179 and L183 can be deleted. */
.kh-stat--ok .num{ color: var(--kh-ok); }
.kh-stat--info .num{ color: var(--kh-info); }
.kh-stat--danger .num{ color: var(--kh-danger); }

/* BOARD QUADRANT 2, the only part of it that ships. One additive wrapper class
   on the dashboard's existing .row -- no model change, no new Razor logic, no
   grid change to the .col-md-3 children. The four KPI tiles read as cards
   branching off a pipeline, at the cost of one class and zero data.
   The rail is STATIC -- no shimmer. */
.kh-branch-row{ position: relative; padding-top: 34px; }
.kh-branch-row::before{
  content:'';
  position: absolute;
  left: 6%;
  right: 6%;
  top: 14px;
  height: 2px;
  border-radius: 2px;
  background-image: var(--kh-rail-solid);
  pointer-events: none;
}
.kh-branch-row > [class*="col-"]{ position: relative; }
.kh-branch-row > [class*="col-"]::before{
  content:'';
  position: absolute;
  left: 50%;
  top: -20px;
  width: 1px;
  height: 20px;
  background-color: var(--kh-edge-lum);
  pointer-events: none;
}
.kh-branch-row > [class*="col-"]::after{
  content:'';
  position: absolute;
  box-sizing: border-box;
  left: 50%;
  top: -24px;
  width: 9px;
  height: 9px;
  margin-left: -4px;
  border-radius: 50%;
  background-color: var(--kh-surface);
  border: 2px solid var(--kh-brand-600);
  box-shadow: var(--kh-live-ring);
  pointer-events: none;
}


/* ============================================================================
   18. SMALL PARTS -- code chips, avatars, boolean flags
   ============================================================================ */

/* Generalises to certificate IDs, lodgement refs and invoice numbers. Its old
   #F4F9F4 background equalled the page background token and vanished. */
.kh-code,
.rm-memno{
  font-family: var(--kh-font-mono);
  font-size: var(--kh-fs-xs);
  font-weight: 700;
  background-color: var(--kh-brand-100);
  color: var(--kh-brand-900);
  border: 1px solid rgba(116,180,155,.30);
  border-radius: var(--kh-r-xs);
  padding: 3px 9px;
  display: inline-block;
  letter-spacing: 0;
}

/* Authored WITHOUT a body prefix and WITHOUT !important on background, so the
   two divergent .avatar-circle definitions (Assessor/Index mint 38px,
   Tutors/Index indigo 35px) converge on one look where they do not override,
   and keep their own geometry where they do. Both consume var(--accent-color)
   / var(--dark-green) / var(--primary-green), which the alias remap keeps
   alive. */
.kh-avatar,
.rm-avatar,
.avatar-circle{
  width: 40px;
  height: 40px;
  border-radius: var(--kh-r-md);   /* squircle */
  background-image: var(--kh-avatar);
  color: var(--kh-brand-800);
  font-weight: 700;
  font-size: .85rem;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Retires the #f2f2f2 / #cfcfcf greys -- the only neutral greys in the design. */
.rm-tick,
.rm-dash,
.kh-flag-on,
.kh-flag-off{
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--kh-fs-micro);
  flex: 0 0 auto;
}
.rm-tick,
.kh-flag-on{ background-color: rgba(47,207,151,.15); color: var(--kh-ok); }
.rm-dash,
.kh-flag-off{ background-color: var(--kh-surface-sunk); color: var(--kh-ink-faint); }


/* ============================================================================
   19. MEMBERS (rm-*) VOCABULARY -- retargeted onto tokens, not redesigned
   All body-prefixed so they beat the 152-line view-local <style> block, which
   sits in <body> after @RenderBody().
   ============================================================================ */

body .rm-search-wrap{ position: relative; display: flex; align-items: center; }
body .rm-search{
  border-radius: 30px;        /* the pill shape IS the page's search
                                 affordance -- kept deliberately */
  border: 1px solid var(--kh-edge-strong);
  background-color: var(--kh-surface);
  color: var(--kh-ink);
  padding: .55rem 1rem;
  font-size: var(--kh-fs-sm);
}
body .rm-search::placeholder{ color: var(--kh-ink-muted); opacity: 1; }
body .rm-clear{
  color: var(--kh-ink-muted);
  background: transparent;
  border: 0;
  line-height: 1;
}
body .rm-clear:hover{ color: var(--kh-ink); }
body .rm-hint{ color: var(--kh-ink-muted); font-size: var(--kh-fs-xs); }  /* was #a3b3a5, 2.7:1 */
body .rm-name{ color: var(--kh-ink); font-weight: 600; }
body .rm-email{ color: var(--kh-ink-muted); font-size: var(--kh-fs-xs); } /* was #9aa89c, 3.0:1 */

/* RETIREMENT MAP for the remaining inline hexes in Views/Members/Index.cshtml.
   The 152-line <style> block is deleted only AFTER these nine inline style
   attributes are stripped, not before:
       #8aa08d (3.3:1) -> var(--kh-ink-muted)
       #9aa89c (3.0:1) -> var(--kh-ink-muted)
       #a3b3a5 (2.7:1) -> var(--kh-ink-muted)
       #556E53          -> var(--kh-ink-soft)
       #2c3e2f          -> var(--kh-ink)
       #c9dccb / #d5e4d7 -> var(--kh-edge)
       #f2f2f2 / #cfcfcf -> var(--kh-surface-sunk) / var(--kh-ink-faint)      */


/* ============================================================================
   20. OVERLAYS, ALERTS, REVEAL, SHIMS
   ============================================================================ */

/* Forms live inside modals, so the content stays near-opaque and gets NO
   backdrop-filter. */
.modal-content{
  background-color: var(--kh-surface-raised);
  border: 0;
  border-radius: var(--kh-r-lg);
  box-shadow: var(--kh-e3);
}
.modal-header{ border-bottom: 1px solid var(--kh-edge); }
.modal-footer{ border-top: 1px solid var(--kh-edge); }
.modal-title{ font-weight: 700; color: var(--kh-ink); }

/* THE SECOND PERMITTED BLUR. Blurring the page BEHIND a dialog is the one
   place where blur costs no legibility. */
.modal-backdrop.show{
  background-color: var(--kh-scrim);
  opacity: 1;
}
@supports ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))){
  .modal-backdrop.show{
    -webkit-backdrop-filter: blur(var(--kh-blur-scrim));
    backdrop-filter: blur(var(--kh-blur-scrim));
  }
}

/* NO backdrop-filter -- these are frequently opened from inside a .card-custom,
   and a promoted layer there would clip and reparent them. */
.dropdown-menu,
.offcanvas,
.popover{
  background-color: var(--kh-surface-raised);
  border: 1px solid var(--kh-edge);
  border-radius: var(--kh-r-md);
  box-shadow: var(--kh-e2);
}
.dropdown-item{ color: var(--kh-ink-soft); }
.dropdown-item:hover,
.dropdown-item:focus{ background-color: var(--kh-brand-100); color: var(--kh-ink); }
.dropdown-item.active,
.dropdown-item:active{ background-color: var(--kh-brand-850); color: #fff; }

.tooltip-inner{
  background-color: var(--kh-brand-950);
  color: #fff;
  border-radius: var(--kh-r-sm);
  font-size: var(--kh-fs-xs);
}

/* CRITICAL: never declare `transform` on .alert or on #global-notif. The
   dismiss script at _Layout L265 writes el.style.transform =
   'translate(-50%,-100%)', and a CSS transform here would fight Bootstrap's
   .translate-middle-x centring and break the exit animation. */
.alert{
  border: 1px solid var(--kh-edge);
  border-radius: var(--kh-r-md);
  box-shadow: var(--kh-e1);
}
.alert-success{ background-color: rgba(46,125,70,.10); color: var(--kh-brand-900); border-color: rgba(46,125,70,.28); }
.alert-danger{ background-color: var(--kh-danger-tint); color: #7A1913; border-color: rgba(179,38,30,.28); }
.alert-warning{ background-color: var(--kh-warn-tint); color: var(--kh-warn-ink); border-color: rgba(232,163,43,.35); }
.alert-info{ background-color: var(--kh-info-tint); color: var(--kh-info); border-color: rgba(31,127,107,.28); }

/* It is ALREADY rgba(255,255,255,.8) + blur(10px) and would otherwise
   double-blur. Its display:none / .active display:block tab mechanism is left
   completely alone -- see the note on bare .active at the end of this file. */
.settings-card{
  background-color: var(--kh-surface) !important;
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
  border: 1px solid var(--kh-edge);
  border-radius: var(--kh-r-lg);
  box-shadow: var(--kh-e1);
}

/* THE REVEAL. No animation-delay, no animation-fill-mode, no stagger. The
   resting state is FULLY VISIBLE, so a stylesheet error, a JS failure, or a
   suppressed animation all leave the finished page -- the invariant is 'never
   author a hidden resting state'. Gated on a JS-added html class purely so it
   cannot fire again on a soft/AJAX refresh. */
html.kh-ready .card-custom,
html.kh-ready .card,
html.kh-ready .top-bar,
html.kh-ready .kh-page-header{
  animation: kh-reveal var(--kh-t-base) var(--kh-ease-out);
}

/* Static loading placeholder. SHIMMER IS OPT-IN via .is-animated, permitted
   only while an actual request is in flight. Never ambient decoration. */
.kh-skeleton{
  background-image: linear-gradient(90deg,
    var(--kh-surface-sunk), var(--kh-brand-100), var(--kh-surface-sunk));
  border-radius: var(--kh-r-sm);
  min-height: 1em;
  color: transparent;
}
.kh-skeleton.is-animated{
  background-size: 220% 100%;
  animation: kh-sweep var(--kh-cycle-sweep) linear infinite;
}

/* THE ONLY TWO DEAD-CLASS SHIMS.
   Four headings in Training/Index and Training/ManageSlots are silently not
   bold today; two Settings/Index submit buttons stay full-width at every
   breakpoint. The other ten dead classes (text-gray-800, italic, fw-500,
   avatar-sm, btn-white, bg-indigo-subtle, text-indigo, text-slate-900,
   cursor-pointer, transition-all, x-small, pointer-events-none) stay dead ON
   PURPOSE -- defining them would change pages nobody asked to change. In
   particular .opacity-10 is NOT shimmed: it would make the Support/Index L143
   `bg-white pe-3` knockout divider label nearly invisible. */
.font-weight-bold{ font-weight: 700; }
@media (min-width: 768px){
  .w-md-auto{ width: auto !important; }   /* matches Bootstrap's own width
                                             utilities, which are !important */
}

/* NOT STYLED, NOT WRAPPED, NOT RENAMED -- behavioural hooks with no CSS, listed
   so a class audit does not delete them:
     .select-all, .select-row, .status-select, .perm-sync, .register-checkbox,
     .strand-active-cb, .strand-type-hdn, .card-checkbox, .insurance-panel,
     .custom-toast-close-btn, #insuranceStatusContainer
   In particular .card-checkbox's display:none plus the
   `:checked + .insurance-card-content` sibling chain IS the Company insurance
   toggle's entire visual state -- no rule may set display, appearance or a
   wrapper on it.

   The toast system is DELIBERATELY UNTOUCHED IN V1:
     .custom-toast-item, .custom-toast-drawer, .custom-toast-icon,
     .custom-drawer-link, #custom-toast-container, @keyframes slideIn
   Its visuals are written as element.style.cssText at _Layout L361/L368/L382
   and are unreachable from any stylesheet, and the animation name 'slideIn' is
   referenced only as a bare JS string. Retheming toasts is a separate,
   separately-tested commit.

   A BARE `.active` RULE IS NEVER WRITTEN IN THIS FILE, under any
   circumstances. Settings/Index (.settings-card.active) and Company/Create +
   Company/Edit (.wizard-content-section.active) use .active to control
   VISIBILITY via display:none / display:block. Any unscoped .active rule would
   show all panels at once or hide them all. Every .active selector above is
   prefixed by a component selector. */


/* ============================================================================
   21. THE IDLE GOVERNOR -- an explicit allowlist, never universal
   ----------------------------------------------------------------------------
   This must NEVER be written as
       html.kh-idle * { animation-play-state: paused !important }
   The universal form also freezes Bootstrap's .spinner-border and, fatally,
   parks an arriving error toast at translateX(100%) off-screen forever, where
   the admin never sees it. Only this theme's own animated selectors are
   listed.
   ============================================================================ */

html.kh-idle .kh-pulse,
html.kh-idle .top-bar::after,
html.kh-idle .kh-skeleton.is-animated{
  animation-play-state: paused;
}


/* ============================================================================
   22. REDUCED MOTION
   ----------------------------------------------------------------------------
   Because no resting state is ever hidden and every animated end-state is also
   expressed as a static declaration, collapsing durations produces the
   finished design with the travel removed: hover still recolours, the active
   rail still lights, the lit row still shows its mint bar, the busy rail still
   appears. Nothing that is communicated by motion is communicated ONLY by
   motion.
   ============================================================================ */

@media (prefers-reduced-motion: reduce){

  /* tokens are already collapsed in section 02: --kh-t-* to 1ms,
     --kh-cycle-* to 0s */

  *, *::before, *::after{
    animation-duration: .001ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  html.kh-ready .card-custom,
  html.kh-ready .card,
  html.kh-ready .top-bar,
  html.kh-ready .kh-page-header{
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }

  body .sidebar .nav-link.active::before,
  .kh-pulse,
  .top-bar::after,
  .btn-primary::after,
  .kh-skeleton.is-animated,
  body .nav-tabs .nav-item .nav-link.active::after,
  body .nav-pills .nav-item .nav-link.active::after{
    animation: none !important;
  }

  .btn-primary:hover,
  .kh-chip:hover,
  .rm-chip:hover,
  .kh-stat:hover,
  .rm-stat-pill:hover,
  .btn:active,
  .kh-chip:active,
  .rm-chip:active,
  .page-link:active,
  .rm-page-btn:active{
    transform: none !important;
  }

  /* STATE MUST STILL READ WITHOUT MOTION -- every effect has a static twin. */
  body .sidebar .nav-link.active:not(.text-danger)::before{
    box-shadow: var(--kh-glow-rail);
    opacity: 1;
  }
  .kh-pulse{ box-shadow: 0 0 0 3px rgba(47,207,151,.28); }
  html.kh-busy .top-bar::after{ opacity: 1; transform: scaleX(1); }
  .btn-primary::after{ opacity: 0; }
  body .nav-tabs .nav-item .nav-link.active::after,
  body .nav-pills .nav-item .nav-link.active::after{ background-size: 100% 100%; }
}

/* ============================================================================
   END khamo-ui.css
   ============================================================================ */

/* ============================================================================
   DASHBOARD — KPI tiles and server-rendered SVG charts
   Chart surface is the opaque white data plate (--kh-surface). Series colours
   are assigned in HomeController.SeriesSlots and validated as a set against
   that surface; text here always wears ink tokens, never a series colour.
   ============================================================================ */

.kh-dash { padding-bottom: 8px; }

/* ---- KPI tiles ---------------------------------------------------------- */
.kh-kpi-row { margin-bottom: 4px; }

.kh-kpi {
  position: relative;
  height: 100%;
  background: var(--kh-surface);
  border-radius: var(--kh-r-lg);
  padding: 18px 20px 16px;
  box-shadow: var(--kh-e1);
  overflow: hidden;
  transition: box-shadow var(--kh-t-fast) var(--kh-ease-out),
              transform var(--kh-t-fast) var(--kh-ease-out);
}
.kh-kpi:hover { box-shadow: var(--kh-e2); transform: translateY(-2px); }

.kh-kpi-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 10px; margin-bottom: 10px;
}
.kh-kpi-label {
  font-size: var(--kh-fs-micro);
  letter-spacing: var(--kh-tracking-label);
  text-transform: uppercase;
  font-weight: 700;
  color: var(--kh-ink-muted);
}
.kh-kpi-icon {
  flex: 0 0 auto;
  width: 34px; height: 34px;
  border-radius: var(--kh-r-sm);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 15px;
  background: var(--kh-tint);
  color: var(--kh-brand-800);
}
.kh-kpi-icon-alert { background: var(--kh-danger-tint); color: var(--kh-danger); }

.kh-kpi-value {
  font-size: var(--kh-fs-display);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: var(--kh-tracking-tight);
  color: var(--kh-ink);
  font-variant-numeric: tabular-nums;
}
.kh-kpi-foot {
  margin-top: 8px;
  font-size: var(--kh-fs-xs);
  color: var(--kh-ink-muted);
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}

/* The one accent tile — the headline number, on the dark chassis */
.kh-kpi-accent {
  background: linear-gradient(150deg, var(--kh-rail-top) 0%, var(--kh-rail-deep) 100%);
  box-shadow: var(--kh-e2);
}
.kh-kpi-accent .kh-kpi-label { color: var(--kh-rail-ink-dim); }
.kh-kpi-accent .kh-kpi-value { color: #FFFFFF; }
.kh-kpi-accent .kh-kpi-foot  { color: var(--kh-rail-ink-idle); }
.kh-kpi-accent .kh-kpi-icon  { background: var(--kh-rail-glass); color: var(--kh-mint); }

.kh-delta {
  display: inline-flex; align-items: center; gap: 4px;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: var(--kh-r-pill);
  font-size: var(--kh-fs-micro);
}
.kh-delta.up   { background: rgba(140,242,200,.16); color: var(--kh-mint); }
.kh-delta.down { background: rgba(255,158,150,.16); color: var(--kh-rail-danger); }

/* ---- Chart cards -------------------------------------------------------- */
.kh-chart-card { display: flex; flex-direction: column; }

.kh-chart-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; margin-bottom: 14px;
}
.kh-chart-title {
  margin: 0;
  font-size: var(--kh-fs-lg);
  font-weight: 700;
  color: var(--kh-ink);
  letter-spacing: var(--kh-tracking-tight);
}
.kh-chart-sub {
  margin: 3px 0 0;
  font-size: var(--kh-fs-xs);
  color: var(--kh-ink-muted);
}
.kh-chart-meta { text-align: right; flex: 0 0 auto; }
.kh-meta-value {
  display: block;
  font-size: var(--kh-fs-lg);
  font-weight: 800;
  color: var(--kh-ink);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.kh-meta-label {
  font-size: var(--kh-fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--kh-tracking-label);
  color: var(--kh-ink-muted);
  font-weight: 600;
}
.kh-flag {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 8px;
  border-radius: var(--kh-r-pill);
  background: var(--kh-warn-tint);
  color: var(--kh-warn-ink);
  font-size: var(--kh-fs-micro);
  font-weight: 700;
  cursor: help;
}

/* ---- Trend plot --------------------------------------------------------- */
.kh-plot { position: relative; }
.kh-svg  { width: 100%; height: auto; display: block; overflow: visible; }

.kh-grid   { stroke: var(--kh-edge); stroke-width: 1; shape-rendering: crispEdges; }
.kh-line   { fill: none; stroke: #12A97A; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.kh-axis   { fill: var(--kh-ink-muted); font-size: 11px; font-weight: 600; }
.kh-axis-y { text-anchor: end; }
.kh-axis-x { text-anchor: middle; }

.kh-peak-dot    { fill: #12A97A; stroke: var(--kh-surface); stroke-width: 2; }
.kh-point-label { fill: var(--kh-ink); font-size: 12px; font-weight: 800; text-anchor: middle; }

.kh-crosshair  { stroke: var(--kh-brand-500); stroke-width: 1; stroke-dasharray: 3 3; }
.kh-cursor-dot { fill: #12A97A; stroke: var(--kh-surface); stroke-width: 2.5; }
.kh-cursor     { transition: opacity var(--kh-t-fast) var(--kh-ease-out); pointer-events: none; }

.kh-hit { fill: transparent; cursor: crosshair; }
.kh-hit:focus-visible { outline: 2px solid var(--kh-link); outline-offset: -2px; }

.kh-tip {
  position: absolute;
  transform: translate(-50%, -100%);
  background: var(--kh-rail-deep);
  color: var(--kh-rail-ink);
  border-radius: var(--kh-r-sm);
  padding: 7px 11px;
  font-size: var(--kh-fs-xs);
  line-height: 1.35;
  white-space: nowrap;
  pointer-events: none;
  box-shadow: var(--kh-e3);
  z-index: 5;
}
.kh-tip strong {
  display: block;
  font-size: var(--kh-fs-md);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}
.kh-tip span { color: var(--kh-rail-ink-dim); }

/* ---- Donut -------------------------------------------------------------- */
.kh-donut-wrap { display: flex; justify-content: center; padding: 4px 0 10px; }
.kh-donut { width: 152px; height: 152px; }
.kh-donut-track { fill: none; stroke: var(--kh-surface-sunk); }
.kh-donut circle[stroke-dasharray] { transition: opacity var(--kh-t-fast) var(--kh-ease-out); }
.kh-donut:hover circle[stroke-dasharray] { opacity: .55; }
.kh-donut circle[stroke-dasharray]:hover { opacity: 1; }
.kh-donut-total {
  fill: var(--kh-ink); font-size: 21px; font-weight: 800;
  text-anchor: middle; font-variant-numeric: tabular-nums;
}
.kh-donut-cap {
  fill: var(--kh-ink-muted); font-size: 10px; font-weight: 600;
  text-anchor: middle; text-transform: uppercase; letter-spacing: .06em;
}

/* ---- Legend (identity is never colour-alone: swatch + name + value) ------ */
.kh-legend { list-style: none; margin: 0; padding: 0; }
.kh-legend li {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 2px;
  border-top: 1px solid var(--kh-edge);
  font-size: var(--kh-fs-sm);
}
.kh-legend li:first-child { border-top: none; }
.kh-swatch {
  flex: 0 0 auto; width: 11px; height: 11px; border-radius: 3px;
  box-shadow: 0 0 0 1px rgba(0,0,0,.06);
}
.kh-legend-name  { flex: 1 1 auto; color: var(--kh-ink-soft); font-weight: 600; }
.kh-legend-value { color: var(--kh-ink); font-weight: 800; font-variant-numeric: tabular-nums; }
.kh-legend-pct   { color: var(--kh-ink-muted); font-size: var(--kh-fs-xs); min-width: 44px; text-align: right; }

/* ---- Horizontal bars ---------------------------------------------------- */
.kh-bars { display: flex; flex-direction: column; gap: 14px; }
.kh-bar-row {
  display: grid;
  grid-template-columns: minmax(120px, 190px) 1fr auto auto;
  align-items: center;
  gap: 14px;
}
.kh-bar-name  { font-size: var(--kh-fs-sm); font-weight: 600; color: var(--kh-ink-soft); }
.kh-bar-track {
  height: 12px; border-radius: var(--kh-r-pill);
  background: var(--kh-surface-sunk);
  overflow: hidden;
}
.kh-bar-fill {
  display: block; height: 100%;
  border-radius: var(--kh-r-pill);
  transition: width var(--kh-t-slow) var(--kh-ease-out);
}
.kh-bar-value { font-weight: 800; color: var(--kh-ink); font-variant-numeric: tabular-nums; min-width: 66px; text-align: right; }
.kh-bar-pct   { font-size: var(--kh-fs-xs); color: var(--kh-ink-muted); min-width: 48px; text-align: right; }

/* ---- Table view (the relief rule) and empty states ---------------------- */
.kh-table-view { margin-top: 14px; border-top: 1px solid var(--kh-edge); padding-top: 10px; }
.kh-table-view summary {
  cursor: pointer;
  font-size: var(--kh-fs-xs);
  font-weight: 700;
  color: var(--kh-link);
  letter-spacing: .02em;
}
.kh-table-view summary:hover { color: var(--kh-brand-900); }
.kh-table-view table { margin-top: 10px; font-size: var(--kh-fs-xs); }

.kh-empty {
  padding: 44px 20px;
  text-align: center;
  color: var(--kh-ink-muted);
}
.kh-empty i { font-size: 30px; opacity: .28; display: block; margin-bottom: 12px; }
.kh-empty p { margin: 0; font-size: var(--kh-fs-sm); }

@media (max-width: 700px) {
  .kh-bar-row { grid-template-columns: 1fr auto; row-gap: 6px; }
  .kh-bar-track { grid-column: 1 / -1; order: 3; }
}

@media (prefers-reduced-motion: reduce) {
  .kh-kpi, .kh-bar-fill, .kh-cursor, .kh-donut circle[stroke-dasharray] { transition: none; }
  .kh-kpi:hover { transform: none; }
}

/* ---- State plates on a plain Bootstrap .card -----------------------------
   Views/Insurance/Review.cshtml and the Assessor register cards carry
   .is-live / .is-done / .is-blocked on a stock .card. The existing rules only
   reached .card-custom and <tr>, so those hooks rendered nothing. These give a
   .card the same reading as a table row: a solid state rail on the leading
   edge (replacing the old inline 4px border-left) plus the light-ground ring.
   Light ground, so: solid fill + 1px ring, never a bloom. */
body .card.is-live,
body .card.is-done,
body .card.is-blocked{
  border-left-width: 0;
  border-top-left-radius: var(--kh-r-sm);
  border-bottom-left-radius: var(--kh-r-sm);
}
body .card.is-live{
  box-shadow: inset var(--kh-rail-w) 0 0 0 var(--kh-flow), var(--kh-e1), var(--kh-live-ring);
}
body .card.is-done{
  box-shadow: inset var(--kh-rail-w) 0 0 0 var(--kh-brand-900), var(--kh-e1);
}
body .card.is-blocked{
  box-shadow: inset var(--kh-rail-w) 0 0 0 var(--kh-danger), var(--kh-e1);
}

/* Same three states on the app's own plate, for parity. */
body .card-custom.is-done{
  box-shadow: inset var(--kh-rail-w) 0 0 0 var(--kh-brand-900), var(--kh-e1);
}
body .card-custom.is-blocked{
  box-shadow: inset var(--kh-rail-w) 0 0 0 var(--kh-danger), var(--kh-e1);
}

/* ---- Member documents (Assessor > Documents tab) -------------------------
   One row per required document: the verification tick, the file that
   satisfies it, and its own upload/replace control. */
body .kh-doc-count{
  font-size: var(--kh-fs-xs); font-weight: 700; color: var(--kh-ink-muted);
  background: var(--kh-surface-sunk); border: 1px solid var(--kh-edge);
  border-radius: var(--kh-r-pill); padding: 5px 14px; white-space: nowrap;
}
body .kh-doc-list{ display: flex; flex-direction: column; gap: 8px; }
body .kh-doc-row{
  display: flex; align-items: flex-start; gap: 14px;
  padding: 14px 16px; background: var(--kh-surface);
  border-radius: var(--kh-r-md); box-shadow: var(--kh-e1);
  transition: box-shadow var(--kh-t-fast) var(--kh-ease-out);
}
body .kh-doc-row.has-file{ box-shadow: inset var(--kh-rail-w) 0 0 0 var(--kh-flow), var(--kh-e1); }
body .kh-doc-row.is-busy{ opacity: .72; }
body .kh-doc-check{ padding-top: 2px; }
body .kh-doc-main{ flex: 1 1 auto; min-width: 0; }
body .kh-doc-name{ font-weight: 700; color: var(--kh-ink); font-size: var(--kh-fs-md); }
body .kh-doc-tag{
  font-size: .64rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; color: var(--kh-warn-ink);
  background: var(--kh-warn-tint); border-radius: var(--kh-r-pill);
  padding: 2px 8px; margin-left: 8px; vertical-align: middle;
}
body .kh-doc-file{ margin-top: 4px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
body .kh-doc-link{ font-weight: 600; color: var(--kh-link); text-decoration: none; word-break: break-all; }
body .kh-doc-link:hover{ text-decoration: underline; }
body .kh-doc-meta{ font-size: var(--kh-fs-xs); color: var(--kh-ink-muted); }
body .kh-doc-empty{ font-size: var(--kh-fs-sm); color: var(--kh-ink-muted); font-style: italic; }
body .kh-doc-error{ font-size: var(--kh-fs-sm); color: var(--kh-danger); font-weight: 600; }
body .kh-doc-history{
  border: none; background: none; padding: 0; font-size: var(--kh-fs-xs);
  font-weight: 600; color: var(--kh-ink-muted); text-decoration: underline;
}
body .kh-doc-history:hover{ color: var(--kh-link); }
body .kh-doc-actions{ display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
body .kh-doc-versions{
  margin-top: 10px; padding: 10px 12px; border-radius: var(--kh-r-sm);
  background: var(--kh-surface-sunk); border: 1px solid var(--kh-edge);
  display: flex; flex-direction: column; gap: 6px;
}
body .kh-doc-version{ display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: var(--kh-fs-xs); }
body .kh-doc-version .v{
  font-weight: 700; color: var(--kh-ink-muted); background: var(--kh-surface);
  border: 1px solid var(--kh-edge); border-radius: var(--kh-r-xs); padding: 1px 7px;
}
body .kh-doc-version a{ color: var(--kh-link); font-weight: 600; text-decoration: none; }
body .kh-doc-foot{
  font-size: var(--kh-fs-xs); color: var(--kh-ink-muted);
  background: var(--kh-surface-sunk); border: 1px solid var(--kh-edge);
  border-radius: var(--kh-r-sm); padding: 10px 14px;
}
@media (max-width: 640px){
  body .kh-doc-row{ flex-wrap: wrap; }
  body .kh-doc-actions{ width: 100%; justify-content: flex-end; }
}
