#main-navbar-tools a.dropdown-toggle{text-decoration:none;color:#fff}.navbar .dropdown-submenu{position:relative}.navbar .dropdown-menu{margin:0;padding:0}.navbar .dropdown-menu a{font-size:.9em;padding:10px 15px;display:block;min-width:210px;text-align:left;border-radius:.25rem;min-height:44px}.navbar .dropdown-submenu a::after{transform:rotate(-90deg);position:absolute;right:16px;top:18px}.navbar .dropdown-submenu .dropdown-menu{top:0;left:100%}.card-header .btn{padding:2px 6px}.card-header h5{margin:0}.container>.card{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}@media screen and (min-width:768px){.navbar .dropdown:hover>.dropdown-menu{display:block}.navbar .dropdown-submenu:hover>.dropdown-menu{display:block}}.input-validation-error{border-color:#dc3545}.field-validation-error{font-size:.8em}.dataTables_scrollBody{min-height:248px}div.dataTables_wrapper div.dataTables_info{padding-top:11px;white-space:nowrap}div.dataTables_wrapper div.dataTables_length label{padding-top:10px;margin-bottom:0}.rtl .dropdown-menu-right{right:auto;left:0}.rtl .dropdown-menu-right a{text-align:right}.rtl .navbar .dropdown-menu a{text-align:right}.rtl .navbar .dropdown-submenu .dropdown-menu{top:0;left:auto;right:100%}.rtl div.dataTables_wrapper div.dataTables_filter input{margin-left:auto;margin-right:.5em}.rtl div.dataTables_wrapper div.dataTables_filter{text-align:left}.rtl table.dataTable thead th,table.dataTable thead td,table.dataTable tfoot th,table.dataTable tfoot td{text-align:right}.brand-container{text-align:center;margin-top:8rem}.brand-logo{height:50px}.brand-text{color:#292d33;font-family:Lexend;font-size:30px;font-style:normal;font-weight:500;line-height:34px;margin-top:5px;margin-bottom:15px}.ts-control{border:1px solid #d0d0d0;border-radius:3px;box-shadow:none;box-sizing:border-box;display:flex;flex-wrap:wrap;overflow:hidden;padding:8px;position:relative;width:100%;z-index:1}.ts-wrapper.multi.has-items .ts-control{padding:6px 8px 3px}.full .ts-control{background-color:#fff}.disabled .ts-control,.disabled .ts-control *{cursor:default!important}.focus .ts-control{box-shadow:none}.ts-control>*{display:inline-block;vertical-align:initial}.ts-wrapper.multi .ts-control>div{background:#f2f2f2;border:0 solid #d0d0d0;color:#303030;cursor:pointer;margin:0 3px 3px 0;overflow:auto;padding:2px 6px}.ts-wrapper.multi .ts-control>div.active{background:#e8e8e8;border:0 solid #cacaca;color:#303030}.ts-wrapper.multi.disabled .ts-control>div,.ts-wrapper.multi.disabled .ts-control>div.active{background:#fff;border:0 solid #fff;color:#7d7d7d}.ts-control>input{background:none!important;border:0!important;box-shadow:none!important;display:inline-block!important;flex:1 1 auto;line-height:inherit!important;margin:0!important;max-height:none!important;max-width:100%!important;min-height:0!important;min-width:7rem;padding:0!important;text-indent:0!important;-webkit-user-select:auto!important;-moz-user-select:auto!important;-ms-user-select:auto!important;user-select:auto!important}.ts-control>input::-ms-clear{display:none}.ts-control>input:focus{outline:none!important}.has-items .ts-control>input{margin:0 4px!important}.ts-control.rtl{text-align:right}.ts-control.rtl.single .ts-control:after{left:15px;right:auto}.ts-control.rtl .ts-control>input{margin:0 4px 0 -2px!important}.disabled .ts-control{background-color:#fafafa;opacity:.5}.input-hidden .ts-control>input{left:-10000px;opacity:0;position:absolute}.ts-dropdown{background:#fff;border:1px solid #d0d0d0;border-radius:0 0 3px 3px;border-top:0;box-shadow:0 1px 3px rgba(0,0,0,.1);box-sizing:border-box;left:0;margin:.25rem 0 0;position:absolute;top:100%;width:100%;z-index:10}.ts-dropdown [data-selectable]{cursor:pointer;overflow:hidden}.ts-dropdown [data-selectable] .highlight{background:rgba(125,168,208,.2);border-radius:1px}.ts-dropdown .create,.ts-dropdown .no-results,.ts-dropdown .optgroup-header,.ts-dropdown .option{padding:5px 8px}.ts-dropdown .option,.ts-dropdown [data-disabled],.ts-dropdown [data-disabled] [data-selectable].option{cursor:inherit;opacity:.5}.ts-dropdown [data-selectable].option{cursor:pointer;opacity:1}.ts-dropdown .optgroup:first-child .optgroup-header{border-top:0}.ts-dropdown .optgroup-header{background:#fff;color:#303030;cursor:default}.ts-dropdown .active{background-color:#f5fafd;color:#495c68}.ts-dropdown .active.create{color:#495c68}.ts-dropdown .create{color:rgba(48,48,48,.5)}.ts-dropdown .spinner{display:inline-block;height:30px;margin:5px 8px;width:30px}.ts-dropdown .spinner:after{animation:lds-dual-ring 1.2s linear infinite;border-color:#d0d0d0 transparent;border-radius:50%;border-style:solid;border-width:5px;content:" ";display:block;height:24px;margin:3px;width:24px}@keyframes lds-dual-ring{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.ts-dropdown-content{max-height:200px;overflow:hidden auto;scroll-behavior:smooth}.ts-wrapper.plugin-drag_drop .ts-dragging{color:transparent!important}.ts-wrapper.plugin-drag_drop .ts-dragging>*{visibility:hidden!important}.plugin-checkbox_options:not(.rtl) .option input{margin-right:.5rem}.plugin-checkbox_options.rtl .option input{margin-left:.5rem}.plugin-clear_button{--ts-pr-clear-button:1em}.plugin-clear_button .clear-button{background:transparent!important;cursor:pointer;margin-right:0!important;opacity:0;position:absolute;right:2px;top:50%;transform:translateY(-50%);transition:opacity .5s}.plugin-clear_button.form-select .clear-button,.plugin-clear_button.single .clear-button{right:max(var(--ts-pr-caret),8px)}.plugin-clear_button.focus.has-items .clear-button,.plugin-clear_button:not(.disabled):hover.has-items .clear-button{opacity:1}.ts-wrapper .dropdown-header{background:color-mix(#fff,#d0d0d0,85%);border-bottom:1px solid #d0d0d0;border-radius:3px 3px 0 0;padding:10px 8px;position:relative}.ts-wrapper .dropdown-header-close{color:#303030;font-size:20px!important;line-height:20px;margin-top:-12px;opacity:.4;position:absolute;right:8px;top:50%}.ts-wrapper .dropdown-header-close:hover{color:#000}.plugin-dropdown_input.focus.dropdown-active .ts-control{border:1px solid #d0d0d0;box-shadow:none}.plugin-dropdown_input .dropdown-input{background:transparent;border:solid #d0d0d0;border-width:0 0 1px;box-shadow:none;display:block;padding:8px;width:100%}.plugin-dropdown_input .items-placeholder{border:0!important;box-shadow:none!important;width:100%}.plugin-dropdown_input.dropdown-active .items-placeholder,.plugin-dropdown_input.has-items .items-placeholder{display:none!important}.ts-wrapper.plugin-input_autogrow.has-items .ts-control>input{min-width:0}.ts-wrapper.plugin-input_autogrow.has-items.focus .ts-control>input{flex:none;min-width:4px}.ts-wrapper.plugin-input_autogrow.has-items.focus .ts-control>input::-ms-input-placeholder{color:transparent}.ts-wrapper.plugin-input_autogrow.has-items.focus .ts-control>input::placeholder{color:transparent}.ts-dropdown.plugin-optgroup_columns .ts-dropdown-content{display:flex}.ts-dropdown.plugin-optgroup_columns .optgroup{border-right:1px solid #f2f2f2;border-top:0;flex-basis:0;flex-grow:1;min-width:0}.ts-dropdown.plugin-optgroup_columns .optgroup:last-child{border-right:0}.ts-dropdown.plugin-optgroup_columns .optgroup:before{display:none}.ts-dropdown.plugin-optgroup_columns .optgroup-header{border-top:0}.ts-wrapper.plugin-remove_button .item{align-items:center;display:inline-flex}.ts-wrapper.plugin-remove_button .item .remove{border-radius:0 2px 2px 0;box-sizing:border-box;color:inherit;display:inline-block;padding:0 6px;text-decoration:none;vertical-align:middle}.ts-wrapper.plugin-remove_button .item .remove:hover{background:rgba(0,0,0,.05)}.ts-wrapper.plugin-remove_button.disabled .item .remove:hover{background:none}.ts-wrapper.plugin-remove_button .remove-single{font-size:23px;position:absolute;right:0;top:0}.ts-wrapper.plugin-remove_button:not(.rtl) .item{padding-right:0!important}.ts-wrapper.plugin-remove_button:not(.rtl) .item .remove{border-left:1px solid #d0d0d0;margin-left:6px}.ts-wrapper.plugin-remove_button:not(.rtl) .item.active .remove{border-left-color:#cacaca}.ts-wrapper.plugin-remove_button:not(.rtl).disabled .item .remove{border-left-color:#fff}.ts-wrapper.plugin-remove_button.rtl .item{padding-left:0!important}.ts-wrapper.plugin-remove_button.rtl .item .remove{border-right:1px solid #d0d0d0;margin-right:6px}.ts-wrapper.plugin-remove_button.rtl .item.active .remove{border-right-color:#cacaca}.ts-wrapper.plugin-remove_button.rtl.disabled .item .remove{border-right-color:#fff}:root{--ts-pr-clear-button:0px;--ts-pr-caret:0px;--ts-pr-min:.75rem}.ts-wrapper.single .ts-control,.ts-wrapper.single .ts-control input{cursor:pointer}.ts-control:not(.rtl){padding-right:max(var(--ts-pr-min),var(--ts-pr-clear-button) + var(--ts-pr-caret))!important}.ts-control.rtl{padding-left:max(var(--ts-pr-min),var(--ts-pr-clear-button) + var(--ts-pr-caret))!important}.ts-wrapper{position:relative}.ts-control,.ts-control input,.ts-dropdown{color:#303030;font-family:inherit;font-size:13px;line-height:18px}.ts-control,.ts-wrapper.single.input-active .ts-control{background:#fff;cursor:text}.ts-hidden-accessible{border:0!important;clip:rect(0 0 0 0)!important;-webkit-clip-path:inset(50%)!important;clip-path:inset(50%)!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}
/*# sourceMappingURL=tom-select.min.css.map *//*
 * radinik-theme.css
 * RightTrak ES by Radinik
 * ABP Framework v10.3
 * Generated from RADINIK_UI_STYLE.md
 * DO NOT EDIT MANUALLY — regenerate from the style guide
 */

/* Self-hosted type ---------------------------------------------------
   DM Sans and DM Mono are served from wwwroot/fonts rather than the Google
   Fonts CDN. RightTrak installs on plant PCs where outbound internet is
   routinely blocked by policy; when the CDN request failed, the whole type
   ladder collapsed to browser defaults on every screen. It also removes an
   outbound call from a validated system. DM Sans is a variable font, so one
   file per subset covers 300-700.
   SIL Open Font License 1.1 - see wwwroot/fonts/README.md. */

@font-face {
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/dm-mono-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/dm-mono-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/dm-mono-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/dm-mono-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'DM Sans';
  font-style: italic;
  font-weight: 300 700;
  font-display: swap;
  src: url('../fonts/dm-sans-italic-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'DM Sans';
  font-style: italic;
  font-weight: 300 700;
  font-display: swap;
  src: url('../fonts/dm-sans-italic-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'DM Sans';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('../fonts/dm-sans-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'DM Sans';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('../fonts/dm-sans-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ═══════════════════════════════════════════════════════════
   1. Color Tokens
════════════════════════════════════════════════════════════ */

/* wwwroot/css/radinik-theme.css */
:root {
  /* ── Primary Accent (Blue) ── */
  --rad-blue:         #1A4FA0;   /* Buttons, active nav, card bars, links     */
  --rad-blue-hover:   #2563C4;   /* Hover on primary elements                 */
  --rad-blue-muted:   rgba(26,79,160,0.10); /* Focus ring, subtle highlight   */
  --rad-blue-tint:    #F0F5FF;   /* Sub-header backgrounds, tag fills         */
  --rad-blue-tag:     #EFF4FF;   /* Tag/badge background for "No" state       */

  /* ── Logo Dot Palette ── */
  --rad-dot-dark: #2D1B4E;  /* Deep purple — code field text, deep accents   */
  --rad-dot-mid:  #7B3F6E;  /* Mid purple — avatar gradients, pair accents   */

  /* ── Sidebar ── */
  --rad-navy:       #1A1F3C;  /* Sidebar background                           */
  --rad-navy-mid:   #232847;  /* Sidebar mid tone                             */
  --rad-navy-hover: #2C3357;  /* Sidebar item hover                           */

  /* ── Surface & Layout ── */
  --rad-surface:   #F5F6FA;  /* Page background                               */
  --rad-white:     #FFFFFF;  /* Card / panel background                       */
  --rad-border:    #E4E7F0;  /* All dividers and input borders                */
  --rad-input-bg:  #F8F9FC;  /* Input / select / textarea background          */
  --rad-code-bg:   #EFF1F8;  /* Read-only code field background               */
  --rad-row-hover: #FAFBFE;  /* Table row hover, panel headers                */
  --rad-thead-bg:  #F0F2F8;  /* Table thead background                        */
  --rad-skeleton-mid: #ECEEF5; /* Skeleton shimmer mid-colour                 */

  /* ── Typography ── */
  --rad-text:         #1A1F3C;  /* Primary body text                          */
  --rad-text-rgb:     26, 31, 60; /* --rad-text as a triplet, for Bootstrap's *-rgb vars */
  --rad-text-2:       #5C6080;  /* Secondary / form labels                    */
  --rad-text-muted:   #9298B0;  /* Placeholders, helper text, footer          */
  --rad-sidebar-text: #CDD2E8;  /* Inactive sidebar item text (AA-compliant)  */

  /* ── Status ── */
  --rad-success:      #27AE60;
  --rad-success-tint: #E8F7EE;
  --rad-warning:      #F0A500;
  --rad-warning-tint: #FFF8E6;
  --rad-error:        #DC2626;  /* Validation errors, destructive buttons     */
  --rad-error-tint:   #FEF2F2;
  --rad-error-border: #FECACA;

  /* ── Overlay ── */
  --rad-overlay: rgba(26,31,60,0.45);  /* Modal backdrop                      */

  /* ── Inline accent text ── */
  --rad-accent-text: var(--rad-blue);  /* Section labels, results labels       */

  /* ── Deployment environment (licensing plan §F) ── */
  --rad-env-val:      #7C3AED;  /* Validation environment                    */
  --rad-env-val-tint: #F3E8FF;

  /* ── Fonts ── */
  --font: 'DM Sans', sans-serif;
  --mono: 'DM Mono', monospace;
}

/* Bootstrap's text colours, mapped to ours. `body` names --rad-text, but
   Bootstrap components set their own colour from these variables rather than
   inheriting it: .card from --bs-body-color (#212529), so every card's text,
   and .table from --bs-emphasis-color (#000), so every DataTable cell, drew in
   Bootstrap's colours. --bs-card-color is left empty on purpose, so .card-body
   inherits from .card. Declared here, after Bootstrap's own :root, so these
   win. */
:root {
  --bs-body-color:         var(--rad-text);
  --bs-body-color-rgb:     var(--rad-text-rgb);
  --bs-emphasis-color:     var(--rad-text);
  --bs-emphasis-color-rgb: var(--rad-text-rgb);
}

/* ═══════════════════════════════════════════════════════════
   4.1 Sidebar
════════════════════════════════════════════════════════════ */

.sidebar {
  width: 220px;
  min-width: 220px;
  background: var(--rad-navy);
  display: flex;
  flex-direction: column;

  /* The shell scrolls with the page, so a sidebar that is only 100vh tall
     scrolls away with it and leaves bare surface beside a long table. Pinned
     the way the topbar already is (13.1) it stays a full viewport tall for the
     whole scroll. align-self stops the flex container stretching it to the
     document height, which is what would defeat the stick. */
  position: sticky;
  top: 0;
  align-self: flex-start;
  height: 100vh;
  z-index: var(--z-sticky);

  overflow-y: auto;
  scrollbar-width: none;
  transition: width .2s ease;
}
.sidebar::-webkit-scrollbar { display: none; }

/* Collapsed state */
.sidebar.collapsed { width: 60px; min-width: 60px; }
.sidebar.collapsed .logo-name,
.sidebar.collapsed .logo-sub,
.sidebar.collapsed .s-label,
.sidebar.collapsed .s-item-text,
.sidebar.collapsed .caret { display: none; }
.sidebar.collapsed .s-item { justify-content: center; padding: 10px; }
.sidebar.collapsed .sidebar-footer { display: none; }

/* Logo area. Column, not row: the brand lockup is a wordmark that already
   carries the product name, so the attribution line sits under it rather than
   beside a mark. */
.sidebar-logo {
  padding: 22px 18px 16px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}
.logo-name { font-size: 19px; font-weight: 700; color: #fff; letter-spacing: -0.3px; }
.logo-name em { color: var(--rad-blue-hover); font-style: normal; } /* "nik" in blue */
.logo-sub { font-size: 9px; color: var(--rad-text-muted); letter-spacing: .1em; text-transform: uppercase; }

/* Section groups */
.s-section { padding: 16px 10px 4px; }
.s-label {
  font-size: 9.5px; font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; color: var(--rad-text-muted);
  padding: 0 8px; margin-bottom: 5px;
}

/* Nav items */
.s-item {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 10px; border-radius: 7px;
  font-size: 13px; font-weight: 500;
  color: var(--rad-sidebar-text);   /* #CDD2E8 — AA-compliant on navy */
  transition: background .15s, color .15s;
  margin-bottom: 1px;
  cursor: pointer;
  text-decoration: none;   /* a nav row, not an inline link — Bootstrap underlines every <a> */
}
.s-item:hover   { background: var(--rad-navy-hover); color: #fff; }
.s-item.active  { background: var(--rad-blue); color: #fff; }
.s-item[aria-current="page"] { background: var(--rad-blue); color: #fff; }
.s-item .caret  { margin-left: auto; font-size: 10px; opacity: .5; }

/* Standalone top-level nav links (Home, Batches, Shipments — leaf items with no children).
   Slightly bolder than sub-items; icon at 87% opacity to match group-child items. */
.s-item-top { font-weight: 600; }
.s-item-top i { opacity: .87; }

/* Collapsed tooltip on hover */
.sidebar.collapsed .s-item { position: relative; }
.sidebar.collapsed .s-item:hover::after {
  content: attr(data-label);
  position: absolute; left: 56px; top: 50%; transform: translateY(-50%);
  background: var(--rad-navy-hover); color: #fff;
  padding: 5px 10px; border-radius: 6px;
  font-size: 12px; font-weight: 500; white-space: nowrap;
  pointer-events: none; z-index: 100;
}

/* Sub-menu */
.s-sub {
  margin-left: 10px; padding-left: 12px;
  border-left: 1px solid rgba(255,255,255,.07);
}
.s-sub .s-item { font-size: 12.5px; font-weight: 400; padding: 6px 10px; }

/* Footer */
.sidebar-footer {
  margin-top: auto; padding: 12px;
  border-top: 1px solid rgba(255,255,255,.06);
  font-size: 10.5px; color: var(--rad-text-muted); text-align: center;
}

/* ═══════════════════════════════════════════════════════════
   4.2 Topbar
════════════════════════════════════════════════════════════ */

/* Page content area */
.content {
  flex: 1;
  padding: 26px 28px;
  background: var(--rad-surface);
  overflow-y: auto;
}

/* Topbar divider / spacer */
.tb-div { flex: 1; }

.topbar {
  background: var(--rad-white);
  border-bottom: 1px solid var(--rad-border);
  padding: 0 28px; height: 54px;
  display: flex; align-items: center; gap: 14px;
  box-shadow: 0 1px 4px rgba(26,31,60,.06);
}
.topbar-title { font-size: 14px; font-weight: 600; color: var(--rad-text); flex: 1; }

/* Network selector */
.net-select {
  background: var(--rad-surface); border: 1px solid var(--rad-border);
  border-radius: 7px; padding: 5px 28px 5px 10px;
  font-size: 12.5px; font-family: var(--font); color: var(--rad-text);
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%235C6080' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 8px center;
}

/* User pill */
.user-pill {
  display: flex; align-items: center; gap: 7px;
  padding: 3px 10px 3px 3px; border-radius: 50px;
  border: 1px solid var(--rad-border); background: var(--rad-surface);
  cursor: pointer;
}
.user-pill:hover { border-color: var(--rad-blue); }
.user-av {
  width: 26px; height: 26px; border-radius: 50%;
  background: linear-gradient(135deg, var(--rad-blue) 0%, var(--rad-dot-mid) 100%);
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 10px; font-weight: 700;
}

/* ═══════════════════════════════════════════════════════════
   4.3 Card
════════════════════════════════════════════════════════════ */

.card {
  background: var(--rad-white);
  border-radius: 12px;
  border: 1px solid var(--rad-border);
  box-shadow: 0 1px 3px rgba(26,31,60,.07);
  overflow: hidden;
  margin-bottom: 18px;
}
.card-hdr {
  padding: 14px 22px;
  border-bottom: 1px solid var(--rad-border);
  display: flex; align-items: center; justify-content: space-between;
}

/* Blue left-bar accent — applied to every card title */
.card-hdr-title {
  font-size: 12.5px; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase;
  color: var(--rad-text);
  display: flex; align-items: center; gap: 8px;
}
.card-hdr-title::before {
  content: ''; display: block;
  width: 3px; height: 15px; border-radius: 2px;
  background: var(--rad-blue);
}

/* Card header action link (e.g. "— Collapse") */
.card-hdr-action {
  font-size: 12px; font-weight: 500;
  color: var(--rad-blue); cursor: pointer;
  transition: opacity .15s;
}
.card-hdr-action:hover { opacity: .7; }

.card-body { padding: 22px; }

/* Colored sub-headers inside cards (e.g. "Items Added") */
.card-sub-hdr {
  padding: 10px 22px;
  border-bottom: 1px solid var(--rad-border);
  background: var(--rad-blue-tint);
  font-size: 12px; font-weight: 600; color: var(--rad-blue);
}
.card-panel-hdr {
  padding: 10px 22px;
  border-bottom: 1px solid var(--rad-border);
  background: var(--rad-row-hover);
  font-size: 11.5px; font-weight: 700; color: var(--rad-text-2);
}

/* Action bar at card bottom (add links) */
.card-action-bar {
  border-top: 1px solid var(--rad-border);
  background: var(--rad-row-hover);
}

/* ═══════════════════════════════════════════════════════════
   4.4 Buttons
════════════════════════════════════════════════════════════ */

.btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 17px; border-radius: 8px;
  font-size: 13px; font-weight: 600; font-family: var(--font);
  cursor: pointer; border: none; transition: all .15s;
}

/* Primary — blue fill */
.btn-primary {
  background: var(--rad-blue); color: #fff;
  box-shadow: 0 2px 8px rgba(26,79,160,.28);
}
.btn-primary:hover {
  background: var(--rad-blue-hover);
  transform: translateY(-1px);
  box-shadow: 0 4px 14px rgba(26,79,160,.36);
}

/* Ghost / Secondary */
.btn-ghost {
  background: var(--rad-surface); color: var(--rad-text-2);
  border: 1px solid var(--rad-border);
}
.btn-ghost:hover { border-color: var(--rad-blue); color: var(--rad-blue); }

/* Danger (destructive actions only) */
.btn-danger { background: var(--rad-error); color: #fff; }
.btn-danger:hover { background: #B91C1C; }

/* Small variant */
.btn-sm { padding: 5px 12px; font-size: 12px; }

/* Keyboard focus — buttons carried no ring at all, so a keyboard user tabbing
   to a filled action saw nothing. Filled variants take a white halo plus a
   solid ring, since a 10%-alpha blue ring is invisible on a blue fill. */
.btn:focus-visible {
  outline: none;
  border-color: var(--rad-blue);
  box-shadow: 0 0 0 3px var(--rad-blue-muted);
}
.btn-primary:focus-visible {
  box-shadow: 0 2px 8px rgba(26,79,160,.28),
              0 0 0 2px var(--rad-white),
              0 0 0 4px var(--rad-blue);
}
.btn-danger:focus-visible {
  box-shadow: 0 0 0 2px var(--rad-white), 0 0 0 4px var(--rad-error);
}
.btn:focus:not(:focus-visible) { outline: none; box-shadow: none; }
.btn-primary:focus:not(:focus-visible) { box-shadow: 0 2px 8px rgba(26,79,160,.28); }

/* Disabled state — applies to all variants */
.btn:disabled,
.btn[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
  transform: none !important;
  box-shadow: none !important;
}

/* Loading state — shown while async action is in-flight */
.btn-loading {
  pointer-events: none;
  opacity: 0.8;
}
.btn-loading .btn-spinner {
  width: 13px; height: 13px;
  border: 2px solid rgba(255,255,255,0.4);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin .65s linear infinite;
  flex-shrink: 0;
}
.btn-ghost.btn-loading .btn-spinner {
  border-color: rgba(26,79,160,0.3);
  border-top-color: var(--rad-blue);
}

/* ═══════════════════════════════════════════════════════════
   4.4a Base Typography
════════════════════════════════════════════════════════════ */

/* Bootstrap sets `body { font-family: var(--bs-body-font-family) }`, its system
   stack, and nothing here ever overrode it. Only the ~35 rules that name
   font-family explicitly (.form-control, .btn, the mono elements) were getting
   DM Sans; every heading, label, card title and table cell in the product was
   rendering in Segoe UI. The type ladder in DESIGN.md assumes DM Sans's metrics,
   so this is what makes the documented hierarchy actually apply. */
body {
  font-family: var(--font);
  background: var(--rad-surface);
  color: var(--rad-text);
  margin: 0;
}

/* ═══════════════════════════════════════════════════════════
   4.4b Browser Surfaces
════════════════════════════════════════════════════════════ */

/* The parts the browser draws still belong to the system. Selection and the
   caret ship as OS blue otherwise, which is the one colour this palette does
   not contain. */
::selection {
  background: rgba(26,79,160,0.18);
  color: var(--rad-text);
}
.sidebar ::selection,
.auth-shell > ::selection {
  background: rgba(255,255,255,0.22);
  color: #fff;
}
input, textarea, select, [contenteditable] { caret-color: var(--rad-blue); }

/* ═══════════════════════════════════════════════════════════
   4.5 Form Fields
════════════════════════════════════════════════════════════ */

/* Shared base for input, select, textarea */
.form-control {
  background: var(--rad-input-bg);
  border: 1px solid var(--rad-border);
  border-radius: 8px; padding: 8px 12px;
  font-size: 13px; font-family: var(--font); color: var(--rad-text);
  width: 100%;
  transition: border-color .15s, box-shadow .15s;
}
/* Use :focus-visible so keyboard users see the ring; mouse clicks do not */
.form-control:focus-visible {
  outline: none;
  border-color: var(--rad-blue);
  box-shadow: 0 0 0 3px var(--rad-blue-muted);
}
/* Bootstrap's .form-control:focus flips the fill to --bs-body-bg, which drops
   an editable field to white the moment it is focused and takes the input-fill
   affordance with it. Hold the documented fill through focus. */
.form-control:focus { background-color: var(--rad-input-bg); }
/* Fallback for browsers that don't support :focus-visible */
.form-control:focus:not(:focus-visible) { outline: none; }

/* Read-only auto-generated code / ID fields */
.form-control.code-field {
  font-family: var(--mono); font-size: 12px;
  background: var(--rad-code-bg); color: var(--rad-dot-dark);
  font-weight: 500; cursor: default;
}

/* Select chevron — applied to both .form-control selects and .form-select */
select.form-control,
.form-select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%235C6080' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 11px center;
  padding-right: 32px;
}

/* Bootstrap uses .form-select for <select> — apply the same base styles as .form-control */
.form-select {
  background-color: var(--rad-input-bg);
  border: 1px solid var(--rad-border);
  border-radius: 8px;
  padding: 8px 32px 8px 12px;
  font-size: 13px;
  font-family: var(--font);
  color: var(--rad-text);
  width: 100%;
  transition: border-color .15s, box-shadow .15s;
  cursor: pointer;
}
.form-select:focus,
.form-select:focus-visible {
  outline: none;
  border-color: var(--rad-blue);
  box-shadow: 0 0 0 3px var(--rad-blue-muted);
}
.form-select:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

textarea.form-control { resize: vertical; min-height: 82px; line-height: 1.55; }

/* Disabled fields */
.form-control:disabled,
.form-control[readonly]:not(.code-field) {
  opacity: 0.55;
  cursor: not-allowed;
  background: var(--rad-surface);
}

/* Validation — invalid state */
.form-control.is-invalid,
.form-select.is-invalid {
  border-color: var(--rad-error);
  box-shadow: none;
}
.form-control.is-invalid:focus-visible,
.form-select.is-invalid:focus-visible {
  border-color: var(--rad-error);
  box-shadow: 0 0 0 3px rgba(220,38,38,0.10);
}
/* Bootstrap widens an invalid select for a status icon our chevron does not carry,
   and resizes the chevron with it. Same selector, so the later rule wins. */
.form-select.is-invalid:not([multiple]):not([size]) {
  padding-right: 32px;
  background-position: right 11px center;
  background-size: auto;
}

/* Validation error message */
.field-error {
  font-size: 11.5px; color: var(--rad-error);
  margin-top: 4px;
  display: flex; align-items: center; gap: 4px;
}
.field-error::before {
  content: '!';
  display: inline-flex; align-items: center; justify-content: center;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--rad-error); color: #fff;
  font-size: 9px; font-weight: 700; flex-shrink: 0;
}

/* An error span that JS fills in is empty until something goes wrong, and ::before
   would otherwise draw a bare "!" bubble under a perfectly valid field. The tag
   helper's spans are covered by .field-validation-valid; hand-written ones are not. */
.field-error:empty { display: none; }

/* Advisory message — the value is legal but probably not what was meant.
   Same shape as .field-error so the two read as one family, in the warning
   colour so it is clearly not blocking the save. */
.field-warning {
  font-size: 11.5px; color: var(--rad-warning);
  margin-top: 4px;
  display: flex; align-items: center; gap: 4px;
}
.field-warning::before {
  content: 'i';
  display: inline-flex; align-items: center; justify-content: center;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--rad-warning); color: #fff;
  font-size: 9px; font-weight: 700; flex-shrink: 0;
}

/* ABP Blazor validation — maps to same style as .field-error */
.validation-message {
  font-size: 11.5px; color: var(--rad-error);
  margin-top: 4px;
}

/* Helper text below non-error fields. margin-bottom is stated because a hint is
   often a <p>, which would otherwise inherit the browser's 1rem and space itself
   away from the field it describes — every such hint used to carry Bootstrap's
   mb-0 to cancel it. */
.field-hint {
  font-size: 11px; color: var(--rad-text-muted);
  margin-top: 4px; margin-bottom: 0;
}

/* A file picker sitting above the field it fills: the native input is hidden behind
   .sr-only and its label is the button, so it matches every other button on the form
   instead of rendering as the browser's own grey "Choose file". */
.key-file-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}
.key-file-row .field-hint { margin-top: 0; }

/* A value the form shows but does not take — derived elsewhere, stated here. */
.form-static {
  font-size: 13px; color: var(--rad-text);
  min-height: 36px; display: flex; align-items: center;
}

/* A column of labelled checkboxes; the hint rides on the option's line. */
.check-list { display: flex; flex-direction: column; gap: 2px; }
.check-option {
  display: flex; align-items: center; gap: 8px;
  min-height: 32px; font-size: 13px; cursor: pointer;
}
/* A lone option standing in a form field's slot is as tall as the input beside it,
   so the two rows of a .form-grid line up. */
.form-group > .check-option { min-height: 36px; }
/* On the option's line the hint is centred with it; its usual top margin would
   drop it below the text. */
.check-option .field-hint { margin-left: 4px; margin-top: 0; }
/* When the row runs short the hint wraps, not the option's own name. */
.check-option > span:has(+ .field-hint) { flex-shrink: 0; }
.check-input { accent-color: var(--rad-blue); cursor: pointer; }
.check-input:disabled { cursor: not-allowed; }
.check-input:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--rad-blue-muted); }

/* Labels */
.form-label {
  font-size: 11px; font-weight: 600;
  color: var(--rad-text-2);
  letter-spacing: .03em; text-transform: uppercase;
}
/* Use a single canonical class for the required asterisk. Inline tables mark a
   required column in its header, so the asterisk reads the same there. */
.form-label .required,
th .required,
.inline-tbl-col-label .required { color: var(--rad-blue); }

/* Two-column form grid */
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.form-grid.form-grid-3 { grid-template-columns: 1fr 1fr 1fr; }
.form-grid.form-grid-4 { grid-template-columns: 1fr 1fr 1fr 1fr; }
.form-group { display: flex; flex-direction: column; gap: 5px; }
.form-group.span-2 { grid-column: span 2; }

/* ═══════════════════════════════════════════════════════════
   4.6 Data Table
════════════════════════════════════════════════════════════ */

table { width: 100%; border-collapse: collapse; }

thead tr { background: var(--rad-thead-bg); }
th {
  padding: 9px 14px; text-align: left;
  font-size: 10px; font-weight: 700;
  letter-spacing: .07em; text-transform: uppercase;
  color: var(--rad-text-2);
  border-bottom: 1px solid var(--rad-border);
  white-space: nowrap;
}
td {
  padding: 10px 14px; font-size: 12.5px;
  border-bottom: 1px solid var(--rad-border);
}
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover td { background: var(--rad-row-hover); }

/* Sortable column headers */
th.sortable { cursor: pointer; user-select: none; }
th.sortable::after { content: ' ↕'; opacity: 0.3; font-size: 9px; }
th.sort-asc::after  { content: ' ↑'; opacity: 1; color: var(--rad-blue); }
th.sort-desc::after { content: ' ↓'; opacity: 1; color: var(--rad-blue); }

/* Three-dot row action menu */
.dot-menu {
  display: inline-flex; gap: 2px; cursor: pointer;
  padding: 4px 8px; border-radius: 6px;
  border: 1px solid transparent;
  position: relative;
}
.dot-menu:hover { border-color: var(--rad-border); background: var(--rad-surface); }
.dot-menu span { width: 3.5px; height: 3.5px; border-radius: 50%; background: var(--rad-text-muted); display: block; }

/* Dot-menu dropdown */
.dot-menu-dropdown {
  display: none;
  position: absolute; right: 0; top: calc(100% + 4px);
  background: var(--rad-white);
  border: 1px solid var(--rad-border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(26,31,60,.12);
  min-width: 140px; z-index: 50;
  overflow: hidden;
}
.dot-menu.open .dot-menu-dropdown { display: block; }
.dot-menu-item {
  padding: 9px 14px;
  font-size: 13px; font-weight: 500;
  color: var(--rad-text); cursor: pointer;
  display: flex; align-items: center; gap: 8px;
  transition: background .1s;
}
.dot-menu-item:hover { background: var(--rad-row-hover); }
.dot-menu-item.danger { color: var(--rad-error); }
.dot-menu-item.danger:hover { background: var(--rad-error-tint); }

/* ── btn-dot-menu: the Bootstrap-dropdown trigger used in DataTable cells ──
   Renders as "•••" with Radinik ghost styling; the dropdown list is
   styled below to match .dot-menu-dropdown / .dot-menu-item. */
.btn-dot-menu {
  background: none;
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 4px 10px;
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  letter-spacing: 1px;
  color: var(--rad-text-muted);
  font-family: inherit;
  transition: background .15s, border-color .15s, color .15s;
}
.btn-dot-menu:hover,
.btn-dot-menu[aria-expanded="true"] {
  background: var(--rad-surface);
  border-color: var(--rad-border);
  color: var(--rad-text);
}
/* ── Global Bootstrap dropdown override ─────────────────────
   Bootstrap/Popper.js may reattach .dropdown-menu to <body>,
   so never use a parent-dependent selector like "td .dropdown-menu".
   These rules apply to every dropdown in the app.              ── */
.dropdown-menu {
  font-family: var(--font) !important;
  font-size: 13px !important;
  border: 1px solid var(--rad-border) !important;
  border-radius: 10px !important;
  box-shadow: 0 8px 24px rgba(26,31,60,.12) !important;
  padding: 6px 0 !important;
  min-width: 150px !important;
  background: var(--rad-white) !important;
}
.dropdown-menu .dropdown-item {
  padding: 9px 14px !important;
  font-size: 13px !important;
  font-weight: 500 !important;
  font-family: var(--font) !important;
  color: var(--rad-text-2) !important;
  display: flex !important;
  align-items: center !important;
  gap: 8px !important;
  border-radius: 0 !important;
  text-decoration: none !important;
  transition: background .1s !important;
}
.dropdown-menu .dropdown-item:hover,
.dropdown-menu .dropdown-item:focus {
  background: var(--rad-row-hover) !important;
  color: var(--rad-text) !important;
}
.dropdown-menu .dropdown-item.text-danger {
  color: var(--rad-error) !important;
}
.dropdown-menu .dropdown-item.text-danger:hover,
.dropdown-menu .dropdown-item.text-danger:focus {
  background: var(--rad-error-tint) !important;
  color: var(--rad-error) !important;
}
.dropdown-menu .dropdown-item i { margin-right: 0 !important; }
.dropdown-menu .dropdown-divider {
  border-color: var(--rad-border) !important;
  margin: 4px 0 !important;
}

/* ═══════════════════════════════════════════════════════════
   4.7 Tags / Badges
════════════════════════════════════════════════════════════ */

.tag { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; }
.tag-no      { background: var(--rad-blue-tag);     color: var(--rad-blue); }
.tag-yes     { background: var(--rad-success-tint); color: var(--rad-success); }
.tag-warning { background: var(--rad-warning-tint); color: var(--rad-warning); }
.tag-error   { background: var(--rad-error-tint);   color: var(--rad-error); }

/* Inline text utilities (used by DataTables cell renderers) */
.mono        { font-family: var(--mono); }
.text-muted  { color: var(--rad-text-muted); }

/* Audit trail report — property change detail list inside a results cell */
.audit-detail-list { font-size: 10.5px; line-height: 1.6; }
.audit-detail-list .audit-detail-toggle { padding: 0; font-size: inherit; }
.audit-object-id   { font-size: 10.5px; }

/* ═══════════════════════════════════════════════════════════
   4.8 Breadcrumb & Page Header
════════════════════════════════════════════════════════════ */

.breadcrumb { display: flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--rad-text-muted); margin-bottom: 6px; }
.breadcrumb .active { color: var(--rad-blue); font-weight: 500; }

.page-header { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 22px; }
.page-title { font-size: 20px; font-weight: 700; letter-spacing: -.3px; color: var(--rad-text); }
.page-sub { font-size: 12.5px; color: var(--rad-text-2); margin-top: 3px; }
.btn-group { display: flex; gap: 10px; align-items: center; }

/* Inline add-item link (bottom of card sections) */
.add-link {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12.5px; font-weight: 600;
  color: var(--rad-accent-text); cursor: pointer;
  padding: 10px 22px;
  transition: opacity .15s;
}
.add-link:hover { opacity: .75; }

/* ═══════════════════════════════════════════════════════════
   4.9 Modal / Dialog
════════════════════════════════════════════════════════════ */

/* Backdrop */
.rad-modal-overlay {
  position: fixed; inset: 0;
  background: var(--rad-overlay);
  backdrop-filter: blur(2px);
  z-index: 1000;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}

/* Dialog container */
.rad-modal {
  background: var(--rad-white);
  border-radius: 14px;
  border: 1px solid var(--rad-border);
  box-shadow: 0 20px 60px rgba(26,31,60,.22);
  width: 100%;
  max-width: 560px;
  max-height: 90vh;
  display: flex; flex-direction: column;
  overflow: hidden;
}
.rad-modal.modal-lg { max-width: 780px; }
.rad-modal.modal-sm { max-width: 400px; }

/* Modal header */
.rad-modal-hdr {
  padding: 18px 24px 16px;
  border-bottom: 1px solid var(--rad-border);
  display: flex; align-items: center; justify-content: space-between;
  flex-shrink: 0;
}
.rad-modal-title {
  font-size: 15px; font-weight: 700;
  letter-spacing: -0.2px; color: var(--rad-text);
  display: flex; align-items: center; gap: 8px;
}
.rad-modal-title::before {
  content: ''; display: block;
  width: 3px; height: 16px; border-radius: 2px;
  background: var(--rad-blue);
}
.rad-modal-close {
  width: 28px; height: 28px; border-radius: 7px;
  border: 1px solid var(--rad-border);
  background: var(--rad-surface);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; color: var(--rad-text-muted);
  font-size: 14px; transition: all .15s;
}
.rad-modal-close:hover { border-color: var(--rad-blue); color: var(--rad-blue); }

/* Modal body */
.rad-modal-body {
  padding: 22px 24px;
  overflow-y: auto; flex: 1;
  scrollbar-width: thin; scrollbar-color: var(--rad-border) transparent;
}

/* Modal footer — left-aligned, same order as form footer */
.rad-modal-ftr {
  padding: 14px 24px;
  border-top: 1px solid var(--rad-border);
  background: var(--rad-surface);
  display: flex; justify-content: flex-start; gap: 10px;
  flex-shrink: 0;
}

/* ═══════════════════════════════════════════════════════════
   4.10 Notifications & Toasts
════════════════════════════════════════════════════════════ */

/* Toast container — bottom-right, stacks upward */
#abp-notification-container,
.abp-toast-container {
  position: fixed;
  bottom: 24px; right: 24px;
  z-index: 9999;
  display: flex; flex-direction: column; gap: 10px;
  max-width: 360px;
}

/* Base toast */
.rad-toast {
  background: var(--rad-white);
  border-radius: 10px; border: 1px solid var(--rad-border);
  box-shadow: 0 8px 24px rgba(26,31,60,.14);
  padding: 13px 16px;
  display: flex; align-items: flex-start; gap: 11px;
  font-size: 13px; font-weight: 500; color: var(--rad-text);
  animation: toastIn .2s ease;
}
@keyframes toastIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes toastOut {
  from { opacity: 1; transform: translateY(0); max-height: 100px; }
  to   { opacity: 0; transform: translateY(8px); max-height: 0; padding: 0; }
}
.rad-toast.dismissing { animation: toastOut .25s ease forwards; }

/* Left accent bar */
.rad-toast::before {
  content: ''; display: block; flex-shrink: 0;
  width: 3px; border-radius: 2px; align-self: stretch;
}
.rad-toast.toast-success::before { background: var(--rad-success); }
.rad-toast.toast-warning::before { background: var(--rad-warning); }
.rad-toast.toast-error::before   { background: var(--rad-error); }
.rad-toast.toast-info::before    { background: var(--rad-blue); }

.rad-toast-body { flex: 1; }
.rad-toast-title { font-weight: 700; font-size: 13px; margin-bottom: 2px; }
.rad-toast-msg   { font-size: 12.5px; color: var(--rad-text-2); line-height: 1.4; }

/* Dismiss button */
.rad-toast-close {
  flex-shrink: 0; background: none; border: none;
  color: var(--rad-text-muted); cursor: pointer;
  font-size: 14px; padding: 0; line-height: 1;
  transition: color .15s;
}
.rad-toast-close:hover { color: var(--rad-text); }

/* ═══════════════════════════════════════════════════════════
   4.11 Empty States
════════════════════════════════════════════════════════════ */

.empty-state {
  padding: 48px 22px;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  text-align: center; gap: 10px;
}
.empty-state-icon {
  width: 44px; height: 44px; border-radius: 12px;
  background: var(--rad-blue-tint);
  display: flex; align-items: center; justify-content: center;
  color: var(--rad-blue); margin-bottom: 4px;
}
.empty-state-title { font-size: 14px; font-weight: 600; color: var(--rad-text); }
.empty-state-body  { font-size: 13px; color: var(--rad-text-muted); max-width: 300px; line-height: 1.5; }

/* ═══════════════════════════════════════════════════════════
   4.12 Loading & Skeleton States
════════════════════════════════════════════════════════════ */

/* Full-card spinner overlay — spinner is a real child element, not ::after */
.card-loading { position: relative; pointer-events: none; }
.card-loading-veil {
  position: absolute; inset: 0;
  background: rgba(255,255,255,0.75);
  border-radius: inherit;
  display: flex; align-items: center; justify-content: center;
  z-index: 10;
}

/* Spinner */
.rad-spinner {
  border: 2.5px solid var(--rad-border);
  border-top-color: var(--rad-blue);
  border-radius: 50%;
  animation: spin .65s linear infinite;
}
.rad-spinner        { width: 22px; height: 22px; }
.rad-spinner.spinner-sm { width: 14px; height: 14px; border-width: 2px; }
.rad-spinner.spinner-lg { width: 34px; height: 34px; border-width: 3px; }
@keyframes spin { to { transform: rotate(360deg); } }

/* Skeleton shimmer */
.skeleton {
  background: linear-gradient(90deg,
    var(--rad-surface) 25%,
    var(--rad-skeleton-mid) 50%,
    var(--rad-surface) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.4s infinite;
  border-radius: 5px;
}
@keyframes shimmer {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}

.sk-line      { height: 12px; margin-bottom: 8px; }
.sk-line-w100 { width: 100%; }
.sk-line-w75  { width: 75%; }
.sk-line-w50  { width: 50%; }
.sk-cell      { height: 38px; border-radius: 6px; }

/* ═══════════════════════════════════════════════════════════
   4.13 Pagination
════════════════════════════════════════════════════════════ */

.pagination {
  display: flex; align-items: center; gap: 4px;
  padding: 14px 22px;
  border-top: 1px solid var(--rad-border);
}
.page-item {
  min-width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 7px; font-size: 13px; font-weight: 500;
  color: var(--rad-text-2); cursor: pointer;
  border: 1px solid transparent; transition: all .15s; padding: 0 8px;
}
.page-item:hover   { background: var(--rad-surface); border-color: var(--rad-border); }
.page-item.active  { background: var(--rad-blue); color: #fff; border-color: var(--rad-blue); }
.page-item[aria-current="page"] { background: var(--rad-blue); color: #fff; border-color: var(--rad-blue); }
.page-item.ellipsis  { cursor: default; color: var(--rad-text-muted); }
.page-item.disabled  { opacity: 0.4; cursor: not-allowed; pointer-events: none; }

/* Radinik renderer state classes (pg-* prefix avoids Bootstrap collision) */
.page-item.pg-active        { background: var(--rad-blue); color: #fff; border-color: var(--rad-blue); }
.page-item.pg-active:hover  { background: var(--rad-blue); border-color: var(--rad-blue); color: #fff; }
.page-item.pg-disabled      { opacity: 0.38; cursor: default; pointer-events: none; }
.page-item.pg-ellipsis      { cursor: default; color: var(--rad-text-muted); pointer-events: none; }

/* Rows-per-page control rendered by radinik-datatables.js */
.page-size-wrap {
  margin-left: auto;
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--rad-text-muted);
}
.page-size-wrap select {
  background: var(--rad-surface); border: 1px solid var(--rad-border);
  border-radius: 7px; padding: 4px 24px 4px 8px;
  font-size: 12.5px; font-family: var(--font); color: var(--rad-text);
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%235C6080' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 6px center; cursor: pointer;
}

.page-size-select {
  margin-left: auto;
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--rad-text-muted);
}
.page-size-select select {
  background: var(--rad-surface); border: 1px solid var(--rad-border);
  border-radius: 7px; padding: 4px 24px 4px 8px;
  font-size: 12.5px; font-family: var(--font); color: var(--rad-text);
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%235C6080' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 6px center; cursor: pointer;
}

/* ═══════════════════════════════════════════════════════════
   4.13a Idle Session Warning Modal  (§16)
════════════════════════════════════════════════════════════ */

.idle-modal-overlay {
  position: fixed; inset: 0;
  background: var(--rad-overlay);
  backdrop-filter: blur(3px);
  z-index: var(--z-idle);
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}

.idle-modal {
  background: var(--rad-white);
  border-radius: 14px;
  border: 1px solid var(--rad-border);
  box-shadow: 0 20px 60px rgba(26,31,60,.28);
  max-width: 400px;
  width: 100%;
  overflow: hidden;
}

.idle-modal-hdr {
  background: var(--rad-warning-tint);
  border-bottom: 1px solid #F0D080;
  padding: 16px 22px;
  display: flex; align-items: center; gap: 10px;
}
.idle-modal-hdr-icon  { color: var(--rad-warning); flex-shrink: 0; }
.idle-modal-hdr-title { font-size: 14px; font-weight: 700; color: var(--rad-text); }

.idle-modal-body { padding: 22px 24px; text-align: center; }

/* Countdown ring */
.idle-countdown-wrap {
  width: 80px; height: 80px;
  margin: 0 auto 16px;
  position: relative;
}
.idle-countdown-ring {
  width: 80px; height: 80px;
  transform: rotate(-90deg);
}
.idle-countdown-ring circle {
  fill: none;
  stroke: var(--rad-border);
  stroke-width: 5;
}
.idle-countdown-ring .progress {
  stroke: var(--rad-warning);
  stroke-linecap: round;
  stroke-dasharray: 220;
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 1s linear, stroke .5s;
}
.idle-countdown-ring .progress.urgent { stroke: var(--rad-error); }

.idle-countdown-number {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 22px; font-weight: 700;
  color: var(--rad-text);
  font-family: var(--mono);
}

.idle-message {
  font-size: 13.5px;
  color: var(--rad-text-2);
  line-height: 1.6;
  margin-bottom: 6px;
}
.idle-message strong { color: var(--rad-text); }

.idle-modal-ftr {
  padding: 14px 24px;
  border-top: 1px solid var(--rad-border);
  background: var(--rad-surface);
  display: flex; gap: 10px;
  justify-content: flex-start;
}

/* ═══════════════════════════════════════════════════════════
   4.14 Back Navigation Link
════════════════════════════════════════════════════════════ */

/* Use .btn.btn-ghost for the back button — not a bare link */
/* Example: <button class="btn btn-ghost">‹ Back</button> */

/* ═══════════════════════════════════════════════════════════
   4.15 Date Picker Input
════════════════════════════════════════════════════════════ */

.date-input-wrap {
  position: relative; width: 100%;
}
.date-input-wrap .form-control { padding-right: 38px; }
.date-input-icon {
  position: absolute; right: 11px; top: 50%; transform: translateY(-50%);
  color: var(--rad-text-muted); pointer-events: none;
  display: flex; align-items: center;
}
.date-input-wrap .form-control:focus-visible ~ .date-input-icon {
  color: var(--rad-blue);
}

/* ═══════════════════════════════════════════════════════════
   4.16 Two-Column Page Layout
════════════════════════════════════════════════════════════ */

.page-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; align-items: start; margin-bottom: 18px; }
.page-cols.cols-6-4 { grid-template-columns: 3fr 2fr; }
.page-cols.cols-4-6 { grid-template-columns: 2fr 3fr; }
.page-cols .card { margin-bottom: 0; }

/* ═══════════════════════════════════════════════════════════
   4.17 Inline Section Label (within card body)
════════════════════════════════════════════════════════════ */

.section-label {
  font-size: 13px; font-weight: 700;
  color: var(--rad-accent-text);   /* use token, not raw var(--rad-blue) */
  margin-bottom: 14px; margin-top: 6px;
  letter-spacing: 0.01em;
}
.section-label.with-divider {
  padding-top: 18px;
  border-top: 1px solid var(--rad-border);
  margin-top: 20px;
}

/* ═══════════════════════════════════════════════════════════
   4.18 Inline Matrix Input Table
════════════════════════════════════════════════════════════ */

.fee-grid { width: 100%; border-collapse: collapse; }
.fee-grid thead th {
  padding: 8px 10px; font-size: 10px; font-weight: 700;
  letter-spacing: .07em; text-transform: uppercase;
  color: var(--rad-text-2); background: var(--rad-thead-bg);
  border-bottom: 1px solid var(--rad-border);
  text-align: left; white-space: nowrap;
}
.fee-grid thead th:first-child { width: 160px; }
.fee-grid tbody td.fee-row-label {
  font-size: 13px; font-weight: 500; color: var(--rad-text);
  padding: 10px 10px 10px 0; vertical-align: middle; white-space: nowrap;
}
.fee-grid tbody td.fee-cell { padding: 5px 6px; vertical-align: middle; }
.fee-grid tbody td.fee-cell .form-control { min-width: 90px; }
.fee-grid tbody tr:hover td { background: inherit; }

/* ═══════════════════════════════════════════════════════════
   4.19 Search / Filter Page Pattern
════════════════════════════════════════════════════════════ */

.search-btn-row { display: flex; align-items: center; gap: 10px; margin: 4px 0 18px; }
.results-label {
  font-size: 13px; font-weight: 700;
  color: var(--rad-accent-text);
  padding: 14px 22px 10px;
}

/* Which zone the record times below are in (§56.3, _ServerTimeNote). Under a results
   label it lines up with the label; at the top of a card body it sits above the first
   block. Printed with the page. */
.time-zone-note {
  font-size: 11px; color: var(--rad-text-muted);
  margin: 0;
}
.results-label + .time-zone-note { padding: 0 22px 10px; margin-top: -6px; }
.card-body > .time-zone-note:first-child { margin-bottom: -6px; }

/* ═══════════════════════════════════════════════════════════
   4.20 Table Cell Link (Row-level Navigation)
════════════════════════════════════════════════════════════ */

.tbl-link {
  color: var(--rad-blue); font-weight: 600;
  text-decoration: underline;
  text-decoration-color: rgba(26,79,160,0.30);
  text-underline-offset: 2px; cursor: pointer;
  transition: color .15s, text-decoration-color .15s;
}
.tbl-link:hover {
  color: var(--rad-blue-hover);
  text-decoration-color: var(--rad-blue-hover);
}

/* A signer named in a table cell, opening the signature's details (21 CFR 11.50).
   A button, since it opens a dialog rather than going anywhere — dressed as a
   .tbl-link so the cell still reads as text. */
.sig-detail-link {
  background: none; border: 0; padding: 0;
  font: inherit; text-align: left;
  color: var(--rad-blue); font-weight: 600;
  text-decoration: underline;
  text-decoration-color: rgba(26,79,160,0.30);
  text-underline-offset: 2px; cursor: pointer;
  border-radius: 3px;
  transition: color .15s, text-decoration-color .15s;
}
.sig-detail-link:hover {
  color: var(--rad-blue-hover);
  text-decoration-color: var(--rad-blue-hover);
}
.sig-detail-link:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--rad-blue-muted);
}
.sig-detail-link .text-muted { font-weight: 400; }

/* ═══════════════════════════════════════════════════════════
   4.21 Tab Strip (within card body)
════════════════════════════════════════════════════════════ */

.tab-strip {
  display: flex; border-bottom: 1px solid var(--rad-border);
  margin: 0 -22px; padding: 0 22px;
}
.tab-item {
  /* button element resets */
  background: none;
  border: none;
  border-radius: 0;
  font-family: inherit;
  line-height: inherit;
  /* tab styling */
  font-size: 13px; font-weight: 500; color: var(--rad-text-muted);
  padding: 10px 16px; cursor: pointer;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  transition: color .15s, border-color .15s;
}
.tab-item:hover { color: var(--rad-text-2); }
.tab-item.active { color: var(--rad-blue); border-bottom-color: var(--rad-blue); font-weight: 600; }
.tab-item:focus-visible { outline: 2px solid var(--rad-blue-muted); outline-offset: -2px; border-radius: 4px; }
.tab-panel { padding-top: 18px; display: none; }
.tab-panel.show { display: block; }

/* A tab strip bleeds to the edge of whatever pads it, and the negative margin above
   is the card body's 22px. A modal body pads 24px (§4.9), so inside one the strip
   stopped 2px short on each side and its underline did not meet the dialog wall. */
.modal-dialog .modal-body .tab-strip { margin: 0 -24px; padding: 0 24px; }

/* ═══════════════════════════════════════════════════════════
   4.22 Inline Editable Table (Add / Delete rows)
════════════════════════════════════════════════════════════ */

.inline-tbl-hdr {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 0 8px; border-bottom: 2px solid var(--rad-border); margin-bottom: 4px;
}

/* The rule above describes the div-based grid below it, but every editable table in
   the app puts the class on a real <thead>. `display: flex` there takes the header
   row out of the table's column algorithm, so header cells size themselves and stop
   lining up with the body — and the widened row pushes its action buttons behind a
   horizontal scrollbar. Restore the row-group display and drop the box properties
   that only meant something to the flex container; §4.6's base `th` already carries
   the padding and the label typography, so only the heavier 2px rule moves onto the
   cells, where a collapsed table paints it. */
thead.inline-tbl-hdr {
  display: table-header-group;
  padding: 0; margin-bottom: 0; border-bottom: none;
}
thead.inline-tbl-hdr > tr > th { border-bottom: 2px solid var(--rad-border); }
.inline-tbl-hdr-cols {
  display: grid; grid-template-columns: 1fr 1fr 80px;
  gap: 12px; flex: 1; align-items: center;
}
.inline-tbl-col-label {
  font-size: 10px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--rad-text-2);
}
.inline-row {
  display: grid; grid-template-columns: 1fr 1fr 80px;
  gap: 12px; align-items: center;
  padding: 6px 0; border-bottom: 1px solid var(--rad-border);
}
.inline-row:last-child { border-bottom: none; }
.inline-row:only-child .btn-danger { visibility: hidden; }

/* ═══════════════════════════════════════════════════════════
   4.23 Form Footer (End-of-Form Actions)
════════════════════════════════════════════════════════════ */

.form-footer {
  display: flex;
  justify-content: flex-start;   /* left-aligned */
  align-items: center;
  gap: 10px;
  padding: 20px 0 8px;
}

/* ═══════════════════════════════════════════════════════════
   4.24 Assignment List (multi-select checkbox list)
═══════════════════════════════════════════════════════════ */

.assign-list-hdr {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 8px;
}
.assign-list-count { font-size: 12px; font-weight: 600; color: var(--rad-text-2); }
.assign-list-actions { display: flex; gap: 14px; }
.assign-list-action {
  background: none; border: none; padding: 0;
  font-family: inherit; font-size: 12px; font-weight: 600;
  color: var(--rad-accent-text); cursor: pointer;
}
.assign-list-action:hover { opacity: .75; }
.assign-list-action:focus-visible {
  outline: 2px solid var(--rad-blue-muted); outline-offset: 2px; border-radius: 4px;
}

.assign-list {
  max-height: 280px; overflow-y: auto;
  border: 1px solid var(--rad-border); border-radius: 8px;
  background: var(--rad-white);
}
.assign-row {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px; margin: 0; cursor: pointer;
  border-bottom: 1px solid var(--rad-border);
  transition: background .1s;
}
.assign-row:last-child { border-bottom: none; }
.assign-row:hover { background: var(--rad-row-hover); }
/* The 15px box is the only thing a keyboard lands on, and its own focus ring is
   easy to miss inside a scrolling list — so the row it belongs to says so too. */
.assign-row:has(input:focus-visible) {
  background: var(--rad-blue-tint);
  box-shadow: inset 3px 0 0 var(--rad-blue);
}
.assign-row input[type="checkbox"] { flex-shrink: 0; margin: 0; }
.assign-row-body { flex: 1; min-width: 0; }
/* Blocks, but spans: a <label> may only contain phrasing content, and the row is
   the label — that is what makes the whole row a hit target for the checkbox. */
.assign-row-body,
.assign-row-name,
.assign-row-meta { display: block; }
.assign-row-name { font-size: 13px; font-weight: 600; color: var(--rad-text); }
.assign-row-meta { font-size: 11.5px; color: var(--rad-text-muted); margin-top: 1px; }
.assign-row-code {
  flex-shrink: 0;
  font-family: var(--mono); font-size: 11px; font-weight: 500;
  color: var(--rad-blue); background: var(--rad-blue-tint);
  border-radius: 4px; padding: 2px 6px;
}

/* Chips or status badges in a table cell — the gap keeps them apart when they wrap */
.tag-list { display: inline-flex; flex-wrap: wrap; gap: 4px; }
td.text-center .tag-list { justify-content: center; }

/* ═══════════════════════════════════════════════════════════
   4.25 Read-only Permission List
═══════════════════════════════════════════════════════════ */

.perm-view-group { margin-bottom: 18px; }
.perm-view-group:last-child { margin-bottom: 0; }
.perm-view-group-hdr {
  font-size: 11px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
  color: var(--rad-text-2);
  padding-bottom: 6px; margin-bottom: 6px;
  border-bottom: 1px solid var(--rad-border);
}
.perm-view-list { list-style: none; margin: 0; padding: 0; }
.perm-view-item {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 0;
  font-size: 13px; color: var(--rad-text);
}
/* Children keep the tree the permission definition declares — a list that flattens
   it reads as 250 peers rather than a dozen areas with actions under them. */
.perm-view-item.is-child {
  margin-inline-start: 18px;
  padding-inline-start: 12px;
  border-inline-start: 2px solid var(--rad-border);
}
.perm-view-tick { color: var(--rad-success); font-size: 11px; flex-shrink: 0; }
.perm-view-name { flex: 1; min-width: 0; }
/* The role the grant came from. Muted and trailing: it is provenance, not the label. */
.perm-view-source {
  flex-shrink: 0;
  font-size: 11px; font-weight: 600;
  color: var(--rad-text-muted);
  background: var(--rad-surface);
  border-radius: 4px; padding: 2px 7px;
}

/* ═══════════════════════════════════════════════════════════
   DataTables overrides (Razor Pages)
════════════════════════════════════════════════════════════ */

/* ── Wrapper & layout ── */
.dataTables_wrapper {
  font-family: var(--font);
  font-size: 13px;
  color: var(--rad-text);
}

/* ── Table itself ── */
table.dataTable {
  width: 100% !important;
  border-collapse: collapse !important;
  margin: 0 !important;
}
table.dataTable thead tr { background: var(--rad-thead-bg); }
table.dataTable thead th,
table.dataTable thead td {
  padding: 9px 14px !important;
  font-size: 10px !important; font-weight: 700 !important;
  letter-spacing: .07em !important; text-transform: uppercase !important;
  color: var(--rad-text-2) !important;
  border-bottom: 1px solid var(--rad-border) !important;
  border-top: none !important;
  white-space: nowrap;
}
table.dataTable tbody td {
  padding: 10px 14px !important;
  font-size: 12.5px !important;
  border-bottom: 1px solid var(--rad-border) !important;
  border-top: none !important;
  vertical-align: middle;
}
table.dataTable tbody tr:last-child td { border-bottom: none !important; }
table.dataTable tbody tr:hover td     { background: var(--rad-row-hover) !important; }

/* Kill DataTables default striping */
table.dataTable.stripe tbody tr.odd,
table.dataTable.display tbody tr.odd { background: inherit !important; }

/* ── Sort arrows ── */
table.dataTable thead .sorting::after,
table.dataTable thead .sorting_asc::after,
table.dataTable thead .sorting_desc::after {
  font-size: 9px; opacity: 0.3;
}
table.dataTable thead .sorting::after      { content: ' ↕' !important; }
table.dataTable thead .sorting_asc::after  { content: ' ↑' !important; opacity: 1; color: var(--rad-blue); }
table.dataTable thead .sorting_desc::after { content: ' ↓' !important; opacity: 1; color: var(--rad-blue); }
table.dataTable thead .sorting,
table.dataTable thead .sorting_asc,
table.dataTable thead .sorting_desc { cursor: pointer; background-image: none !important; }

/* ── Search box ── */
.dataTables_filter label {
  font-size: 11px; font-weight: 600;
  color: var(--rad-text-2); letter-spacing: .03em; text-transform: uppercase;
  display: flex; align-items: center; gap: 8px;
}
.dataTables_filter input {
  background: var(--rad-input-bg) !important;
  border: 1px solid var(--rad-border) !important;
  border-radius: 8px !important; padding: 7px 12px !important;
  font-size: 13px !important; font-family: var(--font) !important;
  color: var(--rad-text) !important;
  transition: border-color .15s, box-shadow .15s;
  outline: none;
  margin-left: 6px;
}
.dataTables_filter input:focus-visible {
  border-color: var(--rad-blue) !important;
  box-shadow: 0 0 0 3px var(--rad-blue-muted) !important;
}

/* ── Length selector (rows per page) ── */
.dataTables_length label {
  font-size: 12px; color: var(--rad-text-muted);
  display: flex; align-items: center; gap: 6px;
}
.dataTables_length select {
  background: var(--rad-surface) !important;
  border: 1px solid var(--rad-border) !important;
  border-radius: 7px !important; padding: 4px 24px 4px 8px !important;
  font-size: 12.5px !important; font-family: var(--font) !important;
  color: var(--rad-text) !important; appearance: none !important;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%235C6080' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") !important;
  background-repeat: no-repeat !important; background-position: right 6px center !important;
  cursor: pointer;
}

/* ── Info text ("Showing 1 to 10 of 57 entries") ── */
.dataTables_info {
  font-size: 12px; color: var(--rad-text-muted);
  padding: 14px 0 !important;
}

/* ── Pagination — ABP uses datatables.net-bs5 which renders:
     <ul class="pagination">
       <li class="paginate_button page-item [active|disabled]">
         <a class="page-link">…</a>
       </li>
     </ul>
   Strategy: style the <li> as the visual button (per §9.1 spec),
   strip all Bootstrap chrome from the inner <a>. ── */

/* Reset Bootstrap's <ul class="pagination"> */
.dataTables_paginate { padding: 10px 0 !important; }
.dataTables_paginate .pagination {
  display: inline-flex !important;
  align-items: center !important;
  gap: 3px !important;
  margin: 0 !important;
  padding: 0 !important;
  list-style: none !important;
  flex-wrap: wrap;
}

/* ── The <li> IS the visual button ── */
.dataTables_paginate .paginate_button {
  min-width: 32px; height: 32px;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  border-radius: 7px !important;
  font-size: 13px !important; font-weight: 500 !important;
  font-family: var(--font) !important;
  color: var(--rad-text-2) !important;
  border: 1px solid transparent !important;
  background: none !important;
  cursor: pointer !important;
  transition: background .15s, border-color .15s, color .15s !important;
  padding: 0 8px !important;
  box-shadow: none !important;
}
.dataTables_paginate .paginate_button:hover {
  background: var(--rad-surface) !important;
  border-color: var(--rad-border) !important;
  color: var(--rad-text) !important;
}
/* Active / current page */
.dataTables_paginate .paginate_button.active,
.dataTables_paginate .paginate_button.current,
.dataTables_paginate .paginate_button.active:hover,
.dataTables_paginate .paginate_button.current:hover {
  background: var(--rad-blue) !important;
  border-color: var(--rad-blue) !important;
  color: #fff !important;
}
/* Disabled buttons (at first/last page boundaries) */
.dataTables_paginate .paginate_button.disabled,
.dataTables_paginate .paginate_button.disabled:hover {
  opacity: 0.38 !important;
  cursor: default !important;
  background: none !important;
  border-color: transparent !important;
  color: var(--rad-text-muted) !important;
  pointer-events: none !important;
}

/* ── Strip ALL Bootstrap chrome from the inner <a class="page-link"> ──
   It must be invisible and fill its parent <li>. ── */
.dataTables_paginate .paginate_button > a.page-link,
.dataTables_paginate .paginate_button > span.page-link {
  all: unset !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  width: 100% !important;
  height: 100% !important;
  color: inherit !important;
  text-decoration: none !important;
  cursor: inherit !important;
  line-height: 1 !important;
}

.dataTables_paginate .ellipsis { color: var(--rad-text-muted) !important; }

/* ── Processing overlay ── */
.dataTables_processing {
  background: rgba(255,255,255,0.85) !important;
  border: none !important; border-radius: 8px !important;
  box-shadow: 0 4px 16px rgba(26,31,60,.12) !important;
  font-size: 13px !important; font-family: var(--font) !important;
  color: var(--rad-text-2) !important;
  padding: 14px 22px !important;
}

/* ── Selected row ── */
table.dataTable tbody tr.selected td {
  background: var(--rad-blue-tint) !important;
  color: var(--rad-text) !important;
}

/* ── Responsive extension (dt-responsive) ── */
td.dtr-control::before {
  border-color: var(--rad-blue) !important;
  background-color: var(--rad-blue) !important;
}

/* ═══════════════════════════════════════════════════════════
   Telerik Grid overrides (Blazor)
════════════════════════════════════════════════════════════ */

.k-grid                   { border: 1px solid var(--rad-border) !important; border-radius: 0 0 12px 12px; }
.k-grid-header            { background: var(--rad-thead-bg) !important; }
.k-grid-header th,
.k-header                 { font-size: 10px !important; font-weight: 700 !important; letter-spacing: .07em !important;
                            text-transform: uppercase !important; color: var(--rad-text-2) !important;
                            border-color: var(--rad-border) !important; padding: 9px 14px !important; }
.k-grid td                { font-size: 12.5px !important; padding: 10px 14px !important;
                            border-color: var(--rad-border) !important; }
.k-grid tr:hover td       { background: var(--rad-row-hover) !important; }
.k-alt                    { background: inherit !important; }
.k-pager-wrap             { background: var(--rad-surface) !important; border-color: var(--rad-border) !important; }
.k-state-selected td      { background: var(--rad-blue-tint) !important; color: var(--rad-text) !important; }
.k-sort-icon              { color: var(--rad-blue) !important; }

/* ═══════════════════════════════════════════════════════════
   8.5 `abp-dynamic-form` Grid Override
════════════════════════════════════════════════════════════ */

/* ── abp-dynamic-form → Radinik form-grid ── */

/* Remove Bootstrap row/col wrappers visually */
.dynamic-form .row   { display: contents; }
.dynamic-form .col,
.dynamic-form [class*="col-"] {
  display: contents;
}

/* The form itself becomes the grid container */
.dynamic-form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

/* Each generated form-group maps to .form-group */
.dynamic-form .form-group {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin-bottom: 0;   /* kill Bootstrap's margin-bottom */
}

/* ABP generated labels → Radinik form-label */
.dynamic-form .form-group label {
  font-size: 11px;
  font-weight: 600;
  color: var(--rad-text-2);
  letter-spacing: .03em;
  text-transform: uppercase;
  margin-bottom: 0;
}

/* ABP generated inputs/selects/textareas → Radinik form-control */
.dynamic-form .form-group .form-control {
  background: var(--rad-input-bg);
  border: 1px solid var(--rad-border);
  border-radius: 8px;
  padding: 8px 12px;
  font-size: 13px;
  font-family: var(--font);
  color: var(--rad-text);
  transition: border-color .15s, box-shadow .15s;
}
.dynamic-form .form-group .form-control:focus-visible {
  outline: none;
  border-color: var(--rad-blue);
  box-shadow: 0 0 0 3px var(--rad-blue-muted);
}

/* ABP validation spans → Radinik field-error */
.dynamic-form .field-validation-error,
.dynamic-form .text-danger {
  font-size: 11.5px;
  color: var(--rad-error);
  margin-top: 4px;
}

/* Full-width fields — add .span-2 to the abp-form-content wrapper */
.dynamic-form .form-group.span-2 { grid-column: span 2; }

/* ═══════════════════════════════════════════════════════════
   8.7 Responsive Breakpoints
════════════════════════════════════════════════════════════ */

/* ── Tablet (≤ 1024px) ── */
@media (max-width: 1024px) {

  /* Collapse sidebar to icon-only */
  .sidebar {
    width: 60px;
    min-width: 60px;
  }
  .sidebar .logo-name,
  .sidebar .logo-sub,
  .sidebar .s-label,
  .sidebar .s-item-text,
  .sidebar .caret { display: none; }
  .sidebar .s-item { justify-content: center; padding: 10px; }
  .sidebar .sidebar-footer { display: none; }

  /* Same wordmark-to-mark swap the .collapsed class makes (13.4) - this
     breakpoint narrows the rail without setting that class. */
  .sidebar .sidebar-logo-img  { display: none; }
  .sidebar .sidebar-logo-mark { display: block; }
  .sidebar .sidebar-logo { align-items: center; padding: 18px 8px 14px; }

  /* Two-column page layout becomes single column */
  .page-cols,
  .page-cols.cols-6-4,
  .page-cols.cols-4-6 { grid-template-columns: 1fr; }

  /* Form grid becomes single column */
  .form-grid,
  .form-grid.form-grid-3,
  .form-grid.form-grid-4 { grid-template-columns: 1fr; }
  .form-group.span-2 { grid-column: span 1; }
  .dynamic-form { grid-template-columns: 1fr; }
  .dynamic-form .form-group.span-2 { grid-column: span 1; }
}

/* ── Mobile (≤ 640px) ── */
@media (max-width: 640px) {

  /* Hide sidebar entirely — use a drawer/hamburger instead */
  .sidebar { display: none; }
  .sidebar.mobile-open { display: flex; position: fixed; z-index: 200; height: 100vh; width: 220px; }

  /* Topbar — tighter padding */
  .topbar { padding: 0 16px; gap: 10px; }
  .topbar-title { font-size: 13px; }

  /* Page content — tighter padding */
  .content { padding: 18px 16px; }

  /* Cards — tighter body padding */
  .card-body { padding: 16px; }
  .card-hdr  { padding: 12px 16px; }

  /* Fee grid — allow horizontal scroll */
  .fee-grid-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

  /* Topbar controls — hide network selector label on mobile */
  .net-label { display: none; }

  /* Modal — full-width on mobile */
  .rad-modal { max-width: 100%; border-radius: 14px 14px 0 0; }
  .rad-modal-overlay { align-items: flex-end; padding: 0; }

  /* Toast — full width */
  #abp-notification-container,
  .abp-toast-container { left: 12px; right: 12px; max-width: none; }
}

/* ═══════════════════════════════════════════════════════════
   9.1 DataTables Renderer Plugin (Approach 3 — Full HTML Control)
════════════════════════════════════════════════════════════ */

/* Wrapper output by the dom string */
.rad-dt-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-top: 1px solid var(--rad-border);
  padding: 0 22px;
}
/* DT 2.x uses .dt-info; keep .dataTables_info as fallback */
.rad-dt-footer .dt-info,
.rad-dt-footer .dataTables_info {
  font-size: 12px;
  color: var(--rad-text-muted);
  padding: 14px 0;
}
/* DT 2.x paging host: .dt-paging (was .dataTables_paginate) */
.rad-dt-footer .dt-paging,
.rad-dt-footer .dataTables_paginate {
  display: flex;
  align-items: center;
}
.rad-dt-footer .pagination {
  border-top: none;
  padding: 10px 0;
}

/* ═══════════════════════════════════════════════════════════
   9.2 Native Radinik Table (Approach 4 — No DataTables)
════════════════════════════════════════════════════════════ */

/* Native table sort links */
a.sort-link {
  color: var(--rad-text-2);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 3px;
}
a.sort-link::after        { content: ' ↕'; opacity: 0.3; font-size: 9px; }
a.sort-link.sort-asc::after  { content: ' ↑'; opacity: 1; color: var(--rad-blue); }
a.sort-link.sort-desc::after { content: ' ↓'; opacity: 1; color: var(--rad-blue); }
a.sort-link:hover         { color: var(--rad-blue); }

/* ═══════════════════════════════════════════════════════════
   10.5 Modal Size Decision in CSS
════════════════════════════════════════════════════════════ */

.rad-modal          { max-width: 560px; }   /* default — up to ~6 fields */
.rad-modal.modal-lg { max-width: 780px; }   /* up to ~10 fields or 1 tab strip */
.rad-modal.modal-sm { max-width: 400px; }   /* delete confirmation, single field */

/* ═══════════════════════════════════════════════════════════
   11.2 Tree Menu CSS
════════════════════════════════════════════════════════════ */

/* ── Tree: expandable parent item ───────────────────────────── */
.s-item.has-children {
  position: relative;
}

/* Chevron — rotates on expand */
.s-item.has-children .s-chevron {
  margin-left: auto;
  flex-shrink: 0;
  width: 14px; height: 14px;
  display: flex; align-items: center; justify-content: center;
  color: var(--rad-sidebar-text);
  transition: transform .2s ease, color .15s;
}
.s-item.has-children:hover .s-chevron,
.s-item.has-children.open   .s-chevron { color: #fff; }
.s-item.has-children.open   .s-chevron { transform: rotate(90deg); }

/* ── Tree: sub-menu container ───────────────────────────────── */
.s-sub {
  overflow: hidden;
  max-height: 0;
  transition: max-height .25s ease;
  margin-left: 10px;
  padding-left: 12px;
  border-left: 1px solid rgba(255,255,255,.07);
}
.s-sub.open {
  /* max-height set dynamically by JS to scrollHeight */
  max-height: 600px;   /* fallback — JS overrides this */
}
.s-sub .s-item {
  font-size: 12.5px;
  font-weight: 400;
  padding: 6px 10px;
}

/* ── Level 3: nested sub-menu ───────────────────────────────── */
.s-sub .s-sub {
  margin-left: 8px;
  padding-left: 10px;
  border-left: 1px solid rgba(255,255,255,.05);
}
.s-sub .s-sub .s-item {
  font-size: 12px;
  padding: 5px 8px;
}

/* ── Active ancestor: parent stays highlighted when child is
   the current page ─────────────────────────────────────────── */
.s-item.has-children.ancestor {
  color: #fff;
  background: var(--rad-navy-hover);
}
.s-item.has-children.ancestor .s-chevron { color: #fff; }

/* ── Icon rail (collapsed, or ≤ 1024px): a group opens in place ──
   The sections are folded, so a group's pages have to be reachable
   from its icon. They open beneath it as icons of their own, set on
   a faint panel so it reads which group they belong to; the indent
   and guide line a 60px rail has no room for are dropped. */
.sidebar.collapsed .s-item.has-children .s-chevron { display: none; }
.sidebar.collapsed .s-sub {
  margin-left: 0;
  padding-left: 0;
  border-left: 0;
}
.sidebar.collapsed .s-sub.open {
  background: rgba(255,255,255,.04);
  border-radius: 7px;
}
@media (max-width: 1024px) {
  .sidebar .s-item.has-children .s-chevron { display: none; }
  .sidebar .s-sub {
    margin-left: 0;
    padding-left: 0;
    border-left: 0;
  }
  .sidebar .s-sub.open {
    background: rgba(255,255,255,.04);
    border-radius: 7px;
  }
  .sidebar .s-sub .s-item { justify-content: center; padding: 10px; }
}

/* ═══════════════════════════════════════════════════════════
   12.2 jQuery Validation → Radinik CSS Bridge
════════════════════════════════════════════════════════════ */

/* ── Bridge jQuery Validation classes → Radinik tokens ── */

/* Invalid input */
input.input-validation-error,
select.input-validation-error,
textarea.input-validation-error {
  border-color: var(--rad-error) !important;
  box-shadow: none;
}
input.input-validation-error:focus-visible,
select.input-validation-error:focus-visible,
textarea.input-validation-error:focus-visible {
  border-color: var(--rad-error) !important;
  box-shadow: 0 0 0 3px rgba(220,38,38,0.10) !important;
}

/* Valid input (after correction) */
input.input-validation-valid,
select.input-validation-valid,
textarea.input-validation-valid {
  border-color: var(--rad-border);
}

/* Error message span. The validation tag helper also stamps Bootstrap's
   .text-danger, whose colour is !important — without matching it here the
   message renders Bootstrap red (#DC3545) beside a Radinik red (#DC2626)
   badge, two reds in one line. */
span.field-validation-error {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 11.5px;
  color: var(--rad-error) !important;
  margin-top: 4px;
}
span.field-validation-error::before {
  content: '!';
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--rad-error);
  color: #fff;
  font-size: 9px;
  font-weight: 700;
  flex-shrink: 0;
}

/* Hide the span when valid (jQuery Validation adds .field-validation-valid) */
span.field-validation-valid { display: none; }

/* Validation summary — sits at the top of the form, above the first card, so a
   failed POST (which re-renders at scroll-top) shows it without scrolling. It
   was carrying .field-error, which is the single-line inline idiom: that gave it
   a flex row with a badge floating mid-block and a stray 4px margin-top. This is
   a block banner, so it follows .page-banner instead — status colour in the fill,
   border and badge, message text at full contrast. */
div.validation-summary-errors {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  background: var(--rad-error-tint);
  border: 1px solid var(--rad-error-border);
  border-radius: 10px;
  padding: 13px 16px;
  margin-bottom: 18px;
  font-size: 13px;
  color: var(--rad-text);
}
/* Same badge as .field-error and the page-alert bridge, but pinned to the first
   line rather than centred, so it still reads as a marker when the list is long. */
div.validation-summary-errors::before {
  content: '!';
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  width: 16px; height: 16px; margin-top: 1px;
  border-radius: 50%;
  background: var(--rad-error); color: #fff;
  font-size: 10px; font-weight: 700; line-height: 1;
}
div.validation-summary-errors ul {
  flex: 1; min-width: 0;
  margin: 0; padding: 0;
  list-style: none;
}
div.validation-summary-errors ul li {
  font-size: 12.5px;
  line-height: 1.45;
}
div.validation-summary-errors ul li + li { margin-top: 4px; }
div.validation-summary-valid { display: none; }

/* ABP abp-validation-summary tag helper */
.abp-validation-summary {
  /* inherits div.validation-summary-errors styles above */
}

/* ═══════════════════════════════════════════════════════════
   12.5 `[Remote]` Validation (Async Server Check)
════════════════════════════════════════════════════════════ */

/* Remote validation in-flight indicator */
input.input-validation-pending {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%239298B0' stroke-width='2'%3E%3Ccircle cx='12' cy='12' r='10' stroke-dasharray='32' stroke-dashoffset='10'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='0.8s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 11px center;
  padding-right: 36px;
}

/* ═══════════════════════════════════════════════════════════
   12.7 Blazor `EditContext` → Radinik CSS Integration
════════════════════════════════════════════════════════════ */

/* Blazor EditForm invalid state — mirrors jQuery Validation bridge */
.modified.invalid  { border-color: var(--rad-error) !important; }
.modified.valid    { border-color: var(--rad-border); }

/* ═══════════════════════════════════════════════════════════
   13.1 Full Topbar CSS
════════════════════════════════════════════════════════════ */

/* ── Topbar layout ─────────────────────────────────────────────── */
.topbar {
  background: var(--rad-white);
  border-bottom: 1px solid var(--rad-border);
  padding: 0 24px;
  height: 54px;
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
  box-shadow: 0 1px 4px rgba(26,31,60,.06);
  position: sticky;
  top: 0;
  z-index: 100;
}

/* ── Environment badge ─────────────────────────────────────────── */
.env-badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  border-radius: 5px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  flex-shrink: 0;
}
.env-badge.env-prod { background: var(--rad-success-tint); color: var(--rad-success); }
.env-badge.env-uat  { background: var(--rad-warning-tint); color: var(--rad-warning); }
.env-badge.env-dev  { background: var(--rad-blue-tint);    color: var(--rad-blue); }
.env-badge.env-val  { background: var(--rad-env-val-tint); color: var(--rad-env-val); } /* Validation env */

/* ── Spacer ────────────────────────────────────────────────────── */
.topbar-spacer { flex: 1; }

/* ── Global search ─────────────────────────────────────────────── */
.topbar-search {
  position: relative;
  width: 220px;
  transition: width .2s ease;
}
.topbar-search:focus-within { width: 320px; }
.topbar-search input {
  width: 100%;
  background: var(--rad-surface);
  border: 1px solid var(--rad-border);
  border-radius: 8px;
  padding: 6px 12px 6px 32px;
  font-size: 13px;
  font-family: var(--font);
  color: var(--rad-text);
  transition: border-color .15s, box-shadow .15s;
}
.topbar-search input:focus-visible {
  outline: none;
  border-color: var(--rad-blue);
  box-shadow: 0 0 0 3px var(--rad-blue-muted);
}
.topbar-search .search-icon {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--rad-text-muted);
  pointer-events: none;
}

/* Global search results dropdown */
.topbar-search-results {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  left: 0; right: 0;
  background: var(--rad-white);
  border: 1px solid var(--rad-border);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(26,31,60,.14);
  z-index: 200;
  overflow: hidden;
  max-height: 360px;
  overflow-y: auto;
}
.topbar-search:focus-within .topbar-search-results { display: block; }
.search-result-group-label {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--rad-text-muted);
  padding: 10px 14px 4px;
}
.search-result-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  cursor: pointer;
  font-size: 13px;
  color: var(--rad-text);
  transition: background .1s;
}
.search-result-item:hover { background: var(--rad-row-hover); }
.search-result-item mark {
  background: var(--rad-blue-tint);
  color: var(--rad-blue);
  border-radius: 2px;
  padding: 0 2px;
  font-style: normal;
}
.search-result-meta {
  font-size: 11.5px;
  color: var(--rad-text-muted);
  margin-left: auto;
}

/* ── Help link ─────────────────────────────────────────────────── */
.topbar-icon-btn {
  width: 34px; height: 34px;
  border-radius: 8px;
  border: 1px solid var(--rad-border);
  background: var(--rad-surface);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  color: var(--rad-text-muted);
  transition: all .15s;
  flex-shrink: 0;
  text-decoration: none;
}
.topbar-icon-btn:hover {
  border-color: var(--rad-blue);
  color: var(--rad-blue);
  background: var(--rad-blue-tint);
}

/* ── Notification bell ─────────────────────────────────────────── */
.topbar-bell {
  position: relative;
}
.topbar-bell .bell-badge {
  position: absolute;
  top: -4px; right: -4px;
  min-width: 16px; height: 16px;
  background: var(--rad-error);
  color: #fff;
  border-radius: 8px;
  font-size: 9.5px;
  font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  padding: 0 4px;
  border: 2px solid var(--rad-white);
}

/* Notification dropdown */
.notif-dropdown {
  display: none;
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  width: 340px;
  background: var(--rad-white);
  border: 1px solid var(--rad-border);
  border-radius: 12px;
  box-shadow: 0 8px 32px rgba(26,31,60,.16);
  z-index: 200;
  overflow: hidden;
}
.topbar-bell.open .notif-dropdown { display: block; }
.notif-header {
  padding: 14px 16px 10px;
  border-bottom: 1px solid var(--rad-border);
  display: flex; align-items: center; justify-content: space-between;
}
.notif-header-title {
  font-size: 13px; font-weight: 700; color: var(--rad-text);
}
.notif-mark-all {
  font-size: 11.5px; font-weight: 500;
  color: var(--rad-blue); cursor: pointer;
}
.notif-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--rad-border);
  cursor: pointer;
  transition: background .1s;
}
.notif-item:last-child { border-bottom: none; }
.notif-item:hover { background: var(--rad-row-hover); }
.notif-item.unread { background: var(--rad-blue-tint); }
.notif-item.unread:hover { background: #E8EFFE; }
.notif-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--rad-blue);
  flex-shrink: 0;
  margin-top: 5px;
}
.notif-item:not(.unread) .notif-dot { background: transparent; }
.notif-text { font-size: 12.5px; color: var(--rad-text); line-height: 1.4; flex: 1; }
.notif-time { font-size: 11px; color: var(--rad-text-muted); white-space: nowrap; }
.notif-footer {
  padding: 10px 16px;
  border-top: 1px solid var(--rad-border);
  background: var(--rad-surface);
  text-align: center;
  font-size: 12.5px; font-weight: 500; color: var(--rad-blue);
  cursor: pointer;
}

/* ── Organisation name ─────────────────────────────────────────── */
.topbar-org {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--rad-text-2);
  max-width: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex-shrink: 0;
}

/* ── App version ───────────────────────────────────────────────── */
.topbar-version {
  font-size: 10.5px;
  font-family: var(--mono);
  color: var(--rad-text-muted);
  flex-shrink: 0;
  padding: 3px 7px;
  background: var(--rad-surface);
  border: 1px solid var(--rad-border);
  border-radius: 5px;
}

/* ═══════════════════════════════════════════════════════════
   13.4 Sidebar Branding
════════════════════════════════════════════════════════════ */

/* Sidebar wordmark. The supplied artwork is dark blue and red on transparent,
   which is unreadable against the navy rail, so it is knocked out to white here.
   The login card is white and uses the same file with no filter. */
.sidebar-logo-img {
  display: block;
  width: 100%;
  max-width: 168px;
  height: auto;
  filter: brightness(0) invert(1);
}

/* The 60px rail has no room for a wordmark, so the geometric mark stands in for
   it there. Hidden the rest of the time; the swap is driven from both the
   .collapsed class and the tablet breakpoint, which collapses on its own. */
.sidebar-logo-mark { display: none; }
.sidebar.collapsed .sidebar-logo-img,
.sidebar.collapsed .logo-sub      { display: none; }
.sidebar.collapsed .sidebar-logo-mark { display: block; }
.sidebar.collapsed .sidebar-logo {
  align-items: center;
  padding: 18px 8px 14px;
}

/* ═══════════════════════════════════════════════════════════
   13.5 User Pill Dropdown
════════════════════════════════════════════════════════════ */

.user-nm { font-size: 13px; font-weight: 500; color: var(--rad-text); }

.user-pill-wrap { position: relative; }
.user-dropdown {
  display: none;
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  width: 220px;
  background: var(--rad-white);
  border: 1px solid var(--rad-border);
  border-radius: 12px;
  box-shadow: 0 8px 32px rgba(26,31,60,.16);
  z-index: var(--z-overlay, 400);
  overflow: hidden;
}
.user-pill-wrap.open .user-dropdown { display: block; }

.user-dropdown-header {
  padding: 14px 16px;
  border-bottom: 1px solid var(--rad-border);
}
.user-dropdown-name { font-size: 13.5px; font-weight: 700; color: var(--rad-text); margin-bottom: 2px; }
.user-dropdown-email { font-size: 11.5px; color: var(--rad-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-dropdown-role { font-size: 11px; font-weight: 600; color: var(--rad-blue); margin-top: 3px; letter-spacing: .02em; }
.user-dropdown-item {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 16px;
  font-size: 13px; font-weight: 500; color: var(--rad-text-2);
  cursor: pointer; transition: background .1s; text-decoration: none;
}
.user-dropdown-item:hover { background: var(--rad-row-hover); color: var(--rad-text); }
.user-dropdown-item.danger { color: var(--rad-error); }
.user-dropdown-item.danger:hover { background: var(--rad-error-tint); }
.user-dropdown-divider { height: 1px; background: var(--rad-border); margin: 4px 0; }

/* ═══════════════════════════════════════════════════════════
   14.1 Auth Page Layout Shell
════════════════════════════════════════════════════════════ */

/* ── Auth layout — no sidebar, centred card ─── */
.auth-shell {
  min-height: 100vh;
  background: var(--rad-navy);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  position: relative;
  overflow: hidden;
}

/* Measured dot grid — the ruled ground the card sits on. Light ink rather than
   blue, because blue at 18% on navy resolved to nothing; masked to a soft
   ellipse so the texture pools around the card and dissolves toward the edges
   instead of tiling flat into the corners. */
.auth-shell::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: radial-gradient(
    circle, rgba(205,210,232,0.11) 1px, transparent 1px
  );
  background-size: 28px 28px;
  -webkit-mask-image: radial-gradient(ellipse 78% 68% at 50% 48%, #000 15%, transparent 100%);
          mask-image: radial-gradient(ellipse 78% 68% at 50% 48%, #000 15%, transparent 100%);
  pointer-events: none;
}

.auth-card {
  background: var(--rad-white);
  border-radius: 14px;   /* modal step — this card is the dialog plane (§7) */
  border: 1px solid var(--rad-border);
  /* Overlay step, navy ink. Carried at a higher alpha than the on-paper
     overlay because the ground here is navy rather than cool paper; pure
     black would read as a different material (§5 Navy Ink Rule). */
  box-shadow: 0 20px 60px rgba(26,31,60,0.55);
  width: 100%;
  max-width: 420px;
  padding: 40px;
  position: relative;
  z-index: 1;
}

.auth-logo {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  margin-bottom: 28px;
}
/* Sized well below the card heading so the wordmark identifies the system
   without outranking the task the page is actually for. Full colour: the card
   is white, which is what the artwork was drawn for. */
.auth-logo-img {
  display: block;
  width: 100%;
  max-width: 190px;
  height: auto;
}
.auth-logo-sub {
  font-size: 11px;
  font-weight: 600;
  /* Was --rad-text-muted at 10px: 2.86:1, the only AA contrast failure on the
     page, and the smallest text on it. Both faults sat on one element. This is
     the 11px form-label rung of the uppercase ladder (SS3) at 6.10:1. */
  color: var(--rad-text-2);
  letter-spacing: .03em;
  text-transform: uppercase;
}

/* Display step, with the signature blue bar hanging into the card's padding so
   the title, subtitle and form all share one left edge. */
.auth-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 6px -11px;
  font-size: 20px;
  font-weight: 700;
  color: var(--rad-text);
  letter-spacing: -.3px;
  line-height: 1.3;
}
.auth-title::before {
  content: ''; display: block; flex-shrink: 0;
  width: 3px; height: 16px; border-radius: 2px;
  background: var(--rad-blue);
}
.auth-subtitle {
  font-size: 13px;
  color: var(--rad-text-2);
  margin-bottom: 24px;
  line-height: 1.5;
}

.auth-footer {
  margin-top: 22px;
  text-align: center;
  font-size: 12.5px;
  color: var(--rad-text-2);
}
.auth-footer a {
  color: var(--rad-blue);
  font-weight: 500;
  text-decoration: none;
  border-radius: 4px;
}
.auth-footer a:hover { text-decoration: underline; }
.auth-footer a:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--rad-blue-muted);
}

/* Version + copyright footer */
.auth-version-footer {
  margin-top: 24px;
  padding-top: 14px;
  border-top: 1px solid var(--rad-border);
  text-align: center;
  font-size: 11px;
  color: var(--rad-text-2);
  letter-spacing: .01em;
  line-height: 1.7;
}
.auth-version-tag {
  display: inline-block;
  font-family: var(--mono);
  font-size: 10.5px;
  background: var(--rad-surface);
  color: var(--rad-blue);
  padding: 1px 7px;
  border-radius: 4px;
  border: 1px solid var(--rad-border);
  margin-right: 5px;
  vertical-align: middle;
  position: relative;
  top: -1px;
}

/* Centre button text inside auth card (full-width flex column stretches the button) */
.auth-card .btn { justify-content: center; }

/* Screen-reader-only. Used for the post-load login-failure announcement: a
   role="alert" that is already in the server HTML at parse time is not reliably
   announced, so the message has to be inserted into a live region after load. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Auth submit row — stacked full-width actions, primary first */
.auth-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.auth-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 20px 0;
  font-size: 11.5px;
  color: var(--rad-text-2);
}
.auth-divider::before,
.auth-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--rad-border);
}

/* ── 21 CFR Part 11 compliance notice on auth pages ── */
.auth-cfr-notice {
  background: var(--rad-blue-tint);
  border: 1px solid var(--rad-border);
  border-radius: 8px;
  padding: 10px 14px;
  margin-bottom: 20px;
  font-size: 11.5px;
  color: var(--rad-text-2);
  line-height: 1.5;
}
.auth-cfr-notice strong { color: var(--rad-blue); }

/* Wrapper only, so an empty page-alert region contributes no box. */
.auth-alert { display: contents; }

/* The route out when the credentials are not the problem. */
.auth-help {
  margin: 16px 0 0;
  text-align: center;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--rad-text-2);
}

/* ── Auth page form helpers ── */
.auth-form-group {
  margin-bottom: 16px;
}

/* Password field with toggle button */
.auth-pw-wrap {
  display: flex;
  align-items: stretch;
}
.auth-pw-wrap .form-control {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
  border-right: none;
  flex: 1;
  min-width: 0;
}
.auth-pw-wrap .auth-pw-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 12px;
  background: var(--rad-input-bg);
  border: 1px solid var(--rad-border);
  border-left: none;
  border-top-right-radius: 8px;
  border-bottom-right-radius: 8px;
  color: var(--rad-text-2);
  cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}
.auth-pw-wrap .auth-pw-toggle:hover { background: var(--rad-row-hover); color: var(--rad-blue); }
.auth-pw-wrap .auth-pw-toggle:focus-visible {
  outline: none;
  color: var(--rad-blue);
  border-color: var(--rad-blue);
  box-shadow: 0 0 0 3px var(--rad-blue-muted);
  position: relative;
}
/* Keep the seam between field and toggle honest while the field is focused or
   invalid — the toggle borrows the field's border colour. */
.auth-pw-wrap .form-control:focus-visible + .auth-pw-toggle { border-color: var(--rad-blue); }
.auth-pw-wrap .form-control.input-validation-error + .auth-pw-toggle { border-color: var(--rad-error); }

/* Remember me + forgot-password row */
.auth-check-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
}
/* With no "remember me" beside it, the lone link would sit flush left under the
   password field and read as a validation message. Push it to the field's end. */
.auth-check-row > :only-child { margin-left: auto; }
.auth-check-label {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  color: var(--rad-text-2);
  cursor: pointer;
}
.auth-check-label input[type="checkbox"] {
  accent-color: var(--rad-blue);
  width: 14px; height: 14px;
  cursor: pointer;
  flex-shrink: 0;
}
.auth-link {
  font-size: 12.5px;
  color: var(--rad-text-2);   /* muted is 2.9:1 on white — too low for a control */
  text-decoration: none;
  border-radius: 4px;
  transition: color .15s;
}
.auth-link:hover { color: var(--rad-blue); text-decoration: underline; }
.auth-link:focus-visible {
  outline: none;
  color: var(--rad-blue);
  box-shadow: 0 0 0 3px var(--rad-blue-muted);
}

/* Provider button (external OAuth) */
.auth-ext-btn {
  display: block;
  width: 100%;
  text-align: center;
  background: var(--rad-surface);
  border: 1px solid var(--rad-border);
  border-radius: 8px;
  padding: 9px 16px;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--rad-text);
  cursor: pointer;
  transition: border-color .15s, background .15s;
  margin-bottom: 8px;
}
.auth-ext-btn:hover { border-color: var(--rad-blue); background: var(--rad-blue-tint); color: var(--rad-blue); }
.auth-ext-btn:focus-visible {
  outline: none;
  border-color: var(--rad-blue);
  box-shadow: 0 0 0 3px var(--rad-blue-muted);
}

/* Narrow viewports — the card keeps its shape, the padding gives ground */
@media (max-width: 640px) {
  .auth-shell { padding: 16px; }
  .auth-card  { padding: 28px 22px; }
}

/* ═══════════════════════════════════════════════════════════
   15.2 Signature Modal CSS
════════════════════════════════════════════════════════════ */

/* ── E-signature modal — extends .rad-modal ── */
.sig-modal { max-width: 480px; }

.sig-modal .rad-modal-hdr {
  background: var(--rad-navy);
  border-bottom-color: rgba(255,255,255,.1);
}
.sig-modal .rad-modal-title { color: #fff; }
.sig-modal .rad-modal-title::before { background: var(--rad-blue-hover); }
.sig-modal .rad-modal-close { background: rgba(255,255,255,.1); border-color: transparent; color: #fff; }
.sig-modal .rad-modal-close:hover { background: rgba(255,255,255,.2); }

/* Action being signed — shown in the modal body */
.sig-action-banner {
  background: var(--rad-blue-tint);
  border: 1px solid var(--rad-border);
  border-radius: 8px;
  padding: 12px 14px;
  margin-bottom: 18px;
  display: flex;
  align-items: flex-start;
  gap: 10px;
}
.sig-action-icon { color: var(--rad-blue); flex-shrink: 0; margin-top: 1px; }
.sig-action-text { font-size: 13px; color: var(--rad-text); line-height: 1.5; }
.sig-action-text strong { color: var(--rad-blue); }

/* Where the signed change will be written — its own line in the banner, so the
   location is read with the action rather than after the password. */
.sig-location {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
  font-size: 12.5px;
  color: var(--rad-text);
}
.sig-location > .fa-location-dot { color: var(--rad-blue); font-size: 12px; }

/* Consequence of the action being signed — amber rather than blue, because this is
   what the action description could not say on its own. Sits between the banner and
   the fields, so it is read before the password. */
.sig-consequences {
  background: var(--rad-warning-tint);
  border: 1px solid rgba(240,165,0,.3);
  border-left: 3px solid var(--rad-warning);
  border-radius: 8px;
  padding: 11px 14px;
  margin-bottom: 18px;
}
.sig-consequences-title {
  display: block;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--rad-text);
  line-height: 1.5;
}
.sig-consequences-list {
  margin: 7px 0 0;
  padding-left: 18px;
  /* A long hierarchy should scroll inside the block rather than push the password
     field off a laptop screen. */
  max-height: 132px;
  overflow-y: auto;
}
.sig-consequences-list li {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--rad-text);
  line-height: 1.7;
}

/* Meaning of signature */
.sig-meaning {
  font-size: 11.5px;
  color: var(--rad-text-muted);
  font-style: italic;
  margin-top: 14px;
  line-height: 1.5;
}

/* Signed-by display (read-only after capture) */
.sig-captured {
  background: var(--rad-success-tint);
  border: 1px solid var(--rad-success);
  border-radius: 8px;
  padding: 12px 14px;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--rad-success);
  font-weight: 600;
}

/* ═══════════════════════════════════════════════════════════
   16.1 Idle Warning CSS
════════════════════════════════════════════════════════════ */

/* ── Idle warning modal — extends .rad-modal ── */
.idle-modal-overlay {
  position: fixed; inset: 0;
  background: var(--rad-overlay);
  backdrop-filter: blur(3px);
  z-index: 2000;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}

.idle-modal {
  background: var(--rad-white);
  border-radius: 14px;
  border: 1px solid var(--rad-border);
  box-shadow: 0 20px 60px rgba(26,31,60,.28);
  max-width: 400px;
  width: 100%;
  overflow: hidden;
}

.idle-modal-hdr {
  background: var(--rad-warning-tint);
  border-bottom: 1px solid #F0D080;
  padding: 16px 22px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.idle-modal-hdr-icon { color: var(--rad-warning); flex-shrink: 0; }
.idle-modal-hdr-title {
  font-size: 14px; font-weight: 700;
  color: var(--rad-text);
}

.idle-modal-body { padding: 22px 24px; text-align: center; }

/* Countdown ring */
.idle-countdown-wrap {
  width: 80px; height: 80px;
  margin: 0 auto 16px;
  position: relative;
}
.idle-countdown-ring {
  width: 80px; height: 80px;
  transform: rotate(-90deg);
}
.idle-countdown-ring circle {
  fill: none;
  stroke: var(--rad-border);
  stroke-width: 5;
}
.idle-countdown-ring .progress {
  stroke: var(--rad-warning);
  stroke-linecap: round;
  stroke-dasharray: 220;
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 1s linear, stroke .5s;
}
.idle-countdown-ring .progress.urgent { stroke: var(--rad-error); }
.idle-countdown-number {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  font-weight: 700;
  color: var(--rad-text);
  font-family: var(--mono);
}

.idle-message {
  font-size: 13.5px;
  color: var(--rad-text-2);
  line-height: 1.6;
  margin-bottom: 6px;
}
.idle-message strong { color: var(--rad-text); }

.idle-modal-ftr {
  padding: 14px 24px;
  border-top: 1px solid var(--rad-border);
  background: var(--rad-surface);
  display: flex;
  gap: 10px;
  justify-content: flex-start;
}

/* ═══════════════════════════════════════════════════════════
   17.2 PDF Viewer CSS
════════════════════════════════════════════════════════════ */

/* ── PDF viewer card ─────────────────────────────────────────── */
.pdf-viewer-card {
  background: var(--rad-white);
  border-radius: 12px;
  border: 1px solid var(--rad-border);
  box-shadow: 0 1px 3px rgba(26,31,60,.07);
  overflow: hidden;
  margin-bottom: 18px;
}

.pdf-viewer-toolbar {
  padding: 10px 18px;
  border-bottom: 1px solid var(--rad-border);
  background: var(--rad-surface);
  display: flex;
  align-items: center;
  gap: 10px;
}
.pdf-viewer-title {
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--rad-text);
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
}
.pdf-viewer-title::before {
  content: '';
  display: block;
  width: 3px; height: 15px;
  border-radius: 2px;
  background: var(--rad-blue);
}
.pdf-viewer-actions { display: flex; gap: 8px; align-items: center; }

.pdf-frame-wrap {
  position: relative;
  background: #525659;
  /* 16:9 ratio placeholder — adjust to A4 or letter aspect ratio */
  /* A4 at 96 DPI ≈ 794 × 1123 px → ratio = 1123/794 ≈ 1.415 */
}
.pdf-frame-wrap iframe {
  display: block;
  width: 100%;
  height: 800px;   /* fixed height — let the iframe scroll internally */
  border: none;
}

/* Loading state while PDF generates */
.pdf-frame-wrap .pdf-loading {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: #525659;
  gap: 14px;
}
.pdf-loading-text {
  font-size: 13px;
  color: rgba(255,255,255,0.7);
  font-family: var(--font);
}

/* ═══════════════════════════════════════════════════════════
   17.4 Print Stylesheet
════════════════════════════════════════════════════════════ */

@media print {
  /* Hide navigation chrome */
  .sidebar, .topbar, .form-footer,
  .search-btn-row, .pagination,
  .pdf-viewer-toolbar { display: none !important; }

  /* Remove shadows and borders */
  .card {
    box-shadow: none !important;
    border: 1px solid #ccc !important;
    break-inside: avoid;
  }

  /* Full width — no sidebar offset */
  .main, .content { width: 100% !important; padding: 0 !important; }
  body { background: #fff !important; }

  /* Show the PDF viewer frame full page */
  .pdf-frame-wrap iframe {
    height: 100vh !important;
    width: 100% !important;
  }

  /* Ensure table rows don't break across pages */
  .rtbl tbody tr { break-inside: avoid; }

  /* Print-visible URL footnote */
  a[href]::after {
    content: none; /* suppress URL printing — report speaks for itself */
  }
}

/* ═══════════════════════════════════════════════════════════
   18.1 ABP Identity Modal Override
════════════════════════════════════════════════════════════ */

/* ── ABP Identity modals (Create/Edit User, Role, etc.) ── */

/* Modal wrapper — ABP uses .modal-dialog */
.modal-dialog .modal-content {
  border-radius: 14px !important;
  border: 1px solid var(--rad-border) !important;
  box-shadow: 0 20px 60px rgba(26,31,60,.22) !important;
  overflow: hidden;
}

/* Modal header */
.modal-dialog .modal-header {
  background: var(--rad-white) !important;
  border-bottom: 1px solid var(--rad-border) !important;
  padding: 18px 24px 16px !important;
  display: flex;
  align-items: center;
}
.modal-dialog .modal-title {
  font-size: 15px !important;
  font-weight: 700 !important;
  letter-spacing: -0.2px !important;
  color: var(--rad-text) !important;
  font-family: var(--font) !important;
  display: flex;
  align-items: center;
  gap: 8px;
}
.modal-dialog .modal-title::before {
  content: '';
  display: block;
  width: 3px; height: 16px;
  border-radius: 2px;
  background: var(--rad-blue);
}
.modal-dialog .btn-close {
  width: 28px; height: 28px;
  border-radius: 7px !important;
  border: 1px solid var(--rad-border) !important;
  background: var(--rad-surface) !important;
  opacity: 1 !important;
  padding: 0 !important;
  transition: all .15s;
  /* Bootstrap draws the × as a background image; the chip fill above replaces
     it, so the mark has to be drawn back in — as .alert .btn-close already does. */
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--rad-text-2);
}
.modal-dialog .btn-close::before {
  content: '✕';
  font-size: 12px;
  line-height: 1;
}
.modal-dialog .btn-close:hover {
  border-color: var(--rad-blue) !important;
  background: var(--rad-blue-tint) !important;
}

/* Modal body */
.modal-dialog .modal-body {
  padding: 22px 24px !important;
  font-family: var(--font) !important;
}

/* Modal footer */
.modal-dialog .modal-footer {
  padding: 14px 24px !important;
  border-top: 1px solid var(--rad-border) !important;
  background: var(--rad-surface) !important;
  justify-content: flex-start !important;
}

/* §12.4: a form footer is left-aligned with the primary action first and the ghost
   second. <abp-modal-footer> emits them the other way round and there is no ordering
   parameter on the tag helper, so the order is corrected here — for ABP's own dialogs
   as much as ours, since a modal is a form footer like any other. */
.modal-dialog .modal-footer .btn-primary { order: 1; }
.modal-dialog .modal-footer .btn-outline-secondary { order: 2; }

/* ABP's <abp-modal-footer> renders Cancel as .btn-outline-secondary — Bootstrap
   grey, no border — beside a Radinik primary. Every modal in the app uses that
   tag helper, so mapping the class here is what keeps the ghost button one
   shape whether it sits on a page or in a dialog. */
.modal-dialog .modal-footer .btn-outline-secondary {
  background: var(--rad-surface) !important;
  color: var(--rad-text-2) !important;
  border: 1px solid var(--rad-border) !important;
}
.modal-dialog .modal-footer .btn-outline-secondary:hover {
  border-color: var(--rad-blue) !important;
  color: var(--rad-blue) !important;
  background: var(--rad-surface) !important;
}

/* ── ABP Bootstrap form → Radinik form ── */
.modal-dialog .form-control,
.modal-dialog .form-select {
  background: var(--rad-input-bg) !important;
  border: 1px solid var(--rad-border) !important;
  border-radius: 8px !important;
  font-size: 13px !important;
  font-family: var(--font) !important;
  color: var(--rad-text) !important;
}
.modal-dialog .form-control { padding: 8px 12px !important; }
/* Preserve room for the chevron arrow in select elements */
.modal-dialog .form-select  { padding: 8px 32px 8px 12px !important; }
.modal-dialog .form-control:focus,
.modal-dialog .form-select:focus {
  border-color: var(--rad-blue) !important;
  box-shadow: 0 0 0 3px var(--rad-blue-muted) !important;
}
.modal-dialog .form-label {
  font-size: 11px !important;
  font-weight: 600 !important;
  color: var(--rad-text-2) !important;
  letter-spacing: .03em !important;
  text-transform: uppercase !important;
  margin-bottom: 5px !important;
  font-family: var(--font) !important;
}

/* ── ABP Bootstrap buttons → Radinik buttons ── */
.modal-dialog .btn-primary {
  background: var(--rad-blue) !important;
  border-color: var(--rad-blue) !important;
  border-radius: 8px !important;
  font-size: 13px !important;
  font-weight: 600 !important;
  font-family: var(--font) !important;
  box-shadow: 0 2px 8px rgba(26,79,160,.28) !important;
  padding: 8px 17px !important;
}
.modal-dialog .btn-primary:hover {
  background: var(--rad-blue-hover) !important;
  border-color: var(--rad-blue-hover) !important;
}
.modal-dialog .btn-secondary,
.modal-dialog .btn-default {
  background: var(--rad-surface) !important;
  border: 1px solid var(--rad-border) !important;
  color: var(--rad-text-2) !important;
  border-radius: 8px !important;
  font-size: 13px !important;
  font-weight: 600 !important;
  font-family: var(--font) !important;
  padding: 8px 17px !important;
  box-shadow: none !important;
}
.modal-dialog .btn-secondary:hover,
.modal-dialog .btn-default:hover {
  border-color: var(--rad-blue) !important;
  color: var(--rad-blue) !important;
}

/* ── Bootstrap nav-tabs inside ABP modals → Radinik tab strip ──
   Targets the User create/edit modal which uses Bootstrap's nav-tabs
   for the User Info / Roles / Password tab groups.               */
.modal-dialog .nav-tabs {
  border-bottom: 1px solid var(--rad-border) !important;
  gap: 0 !important;
  margin-bottom: 18px !important;
}
.modal-dialog .nav-tabs .nav-link {
  font-size: 13px !important;
  font-weight: 500 !important;
  font-family: var(--font) !important;
  color: var(--rad-text-muted) !important;
  padding: 8px 16px !important;
  border: none !important;
  border-bottom: 2px solid transparent !important;
  border-radius: 0 !important;
  background: none !important;
  transition: color .15s, border-color .15s !important;
  margin-bottom: -1px !important;
}
.modal-dialog .nav-tabs .nav-link:hover {
  color: var(--rad-text) !important;
  border-bottom-color: var(--rad-border) !important;
}
.modal-dialog .nav-tabs .nav-link.active,
.modal-dialog .nav-tabs .nav-item.show .nav-link {
  color: var(--rad-blue) !important;
  font-weight: 600 !important;
  border-bottom-color: var(--rad-blue) !important;
  background: none !important;
}
.modal-dialog .tab-content > .tab-pane {
  font-family: var(--font) !important;
}
/* Role checkboxes inside tab pane */
.modal-dialog .form-check-input {
  width: 15px !important;
  height: 15px !important;
  border: 1.5px solid var(--rad-border) !important;
  border-radius: 4px !important;
  cursor: pointer !important;
}
.modal-dialog .form-check-input:checked {
  background-color: var(--rad-blue) !important;
  border-color: var(--rad-blue) !important;
}
.modal-dialog .form-check-input:focus {
  box-shadow: 0 0 0 3px var(--rad-blue-muted) !important;
  border-color: var(--rad-blue) !important;
}
.modal-dialog .form-check-label {
  font-size: 13px !important;
  font-family: var(--font) !important;
  color: var(--rad-text) !important;
  cursor: pointer !important;
}

/* ═══════════════════════════════════════════════════════════
   18.2 Permission Dialog Override
════════════════════════════════════════════════════════════ */

/* ABP renders this dialog as a vertical nav-pills list beside a scrolling
   column of .form-check rows — not the .permission-group-header /
   .permission-list / .child-permission classes this section used to name.
   Those selectors matched nothing, which is why the dialog came through in
   stock Bootstrap. The rules below follow the markup the modal actually
   emits: ul#PermissionsTabs.nav-pills for the group list, and one
   div[data-permission-name] per permission (children carry a non-empty
   data-parent-name and are indented by ABP's own inline margin). */

/* ── Filter row ──────────────────────────────────────────────
   The addon holds a Bootstrap Icons glyph (<i class="bi bi-search">) and
   this app ships Font Awesome, so the slot rendered as an empty box. Supply
   the equivalent Font Awesome glyph; the family list keeps it working across
   an FA major-version change. */
.modal-dialog .input-group > .input-group-text {
  background: var(--rad-surface) !important;
  border: 1px solid var(--rad-border) !important;
  border-right: none !important;
  border-radius: 8px 0 0 8px !important;
  color: var(--rad-text-2) !important;
  padding: 0 12px !important;
}
.modal-dialog .input-group > .input-group-text .bi-search::before {
  content: "\f002";
  font-family: "Font Awesome 7 Free", "Font Awesome 6 Free", "Font Awesome 5 Free", FontAwesome;
  font-weight: 900;
  font-size: 12px;
}
.modal-dialog .input-group > .form-control {
  border-left: none !important;
  border-radius: 0 8px 8px 0 !important;
}

/* ── The bordered well and its caption ───────────────────── */
.modal-dialog .modal-body fieldset.border {
  border: 1px solid var(--rad-border) !important;
  border-radius: 10px !important;
}
.modal-dialog .modal-body fieldset > legend {
  font-size: 11px !important;
  font-weight: 700 !important;
  letter-spacing: .06em !important;
  text-transform: uppercase !important;
  color: var(--rad-text-2) !important;
  font-family: var(--font) !important;
  width: auto !important;
  float: none !important;
  margin-bottom: 0 !important;
}

/* ── Group list (vertical pills) ─────────────────────────────
   Bootstrap's pill is a solid #0d6efd block. The active group instead reads
   as a tinted row with the 3px blue bar the cards use, so the dialog speaks
   the same language as the page behind it. */
.modal-dialog .nav-pills {
  gap: 2px !important;
}
.modal-dialog .nav-pills .nav-link {
  font-family: var(--font) !important;
  font-size: 13px !important;
  font-weight: 500 !important;
  color: var(--rad-text-2) !important;
  background: none !important;
  border-radius: 7px !important;
  padding: 8px 12px !important;
  text-align: start !important;
  transition: background .12s, color .12s;
}
.modal-dialog .nav-pills .nav-link:hover {
  background: var(--rad-row-hover) !important;
  color: var(--rad-text) !important;
}
.modal-dialog .nav-pills .nav-link.active {
  background: var(--rad-blue-tint) !important;
  color: var(--rad-blue) !important;
  font-weight: 600 !important;
  box-shadow: inset 3px 0 0 var(--rad-blue);
}
.modal-dialog .nav-pills .nav-link:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--rad-blue-muted);
}

/* ── Permission rows ─────────────────────────────────────── */
/* Only the block padding may be set here. Bootstrap's .form-check reserves
   padding-inline-start for the checkbox, which is drawn back into that gap with a
   negative margin — overriding the shorthand pulls every top-level checkbox out of
   the row and the scrolling column (overflow-y:auto makes the other axis clip too)
   shears it to a sliver. */
.modal-dialog [data-permission-name] {
  padding-top: 4px !important;
  padding-bottom: 4px !important;
  padding-inline-end: 8px !important;
  border-radius: 6px;
  transition: background .1s;
}
.modal-dialog [data-permission-name]:hover {
  background: var(--rad-row-hover);
}
/* A child permission reads one step quieter than the parent it hangs from.
   ABP already indents it inline, so this only carries the weight. */
.modal-dialog [data-parent-name]:not([data-parent-name=""]) .form-check-label {
  color: var(--rad-text-2) !important;
}

/* ── One group, so the chrome that exists to choose between groups goes ──
   The dialog is filtered to a single group (RightTrak_ESPermissionAppService), which
   leaves a one-item group list, a caption naming it, and a filter box for searching
   across groups — three controls with nothing to decide. Hidden rather than deleted
   from the markup: ABP's script binds to #permission-search and the tab elements on
   open, and a page override would put this app on the hook for their modal.

   The filter shares its row with "Grant all permissions", which with one group does
   exactly what "Select all" inside the list does — so the row goes whole, and the
   surviving toggle is the one that sits directly above the items it governs. */
.modal-dialog .modal-body .row:has(#permission-search) { display: none !important; }
.modal-dialog .lpx-scroll-pills-container:has(#PermissionsTabs) > .col-md-4 { display: none !important; }
.modal-dialog .lpx-scroll-pills-container:has(#PermissionsTabs) > .col-md-8 {
  flex: 0 0 100% !important;
  max-width: 100% !important;
  width: 100% !important;
}
.modal-dialog .modal-body fieldset:has(#PermissionsTabs) > legend { display: none !important; }

/* ── "Grant all permissions" / "Select all" ──────────────── */
.modal-dialog #SelectAllInAllTabs ~ .form-check-label,
.modal-dialog [id^="SelectAllInThisTab"] ~ .form-check-label {
  font-weight: 600 !important;
}

/* ═══════════════════════════════════════════════════════════
   18.3 ABP Identity Page Header Override
════════════════════════════════════════════════════════════ */

/* ── ABP Identity page wrapper ────────────────────────────────── */

/* Page toolbar — ABP renders .page-toolbar */
.page-toolbar {
  display: flex !important;
  align-items: flex-start !important;
  justify-content: space-between !important;
  margin-bottom: 22px !important;
  background: none !important;
  padding: 0 !important;
  border: none !important;
  box-shadow: none !important;
}

/* ABP page title */
.page-toolbar h1,
.page-toolbar .page-header {
  font-size: 20px !important;
  font-weight: 700 !important;
  letter-spacing: -.3px !important;
  color: var(--rad-text) !important;
  font-family: var(--font) !important;
  margin: 0 !important;
}

/* ABP toolbar Create button */
.page-toolbar .btn-primary {
  background: var(--rad-blue) !important;
  border-color: var(--rad-blue) !important;
  border-radius: 8px !important;
  font-family: var(--font) !important;
  font-size: 13px !important;
  font-weight: 600 !important;
  padding: 8px 17px !important;
  box-shadow: 0 2px 8px rgba(26,79,160,.28) !important;
}

/* ABP data table wrapper */
.abp-crud-page-wrapper {
  background: none !important;
  padding: 0 !important;
}

/* ABP card around the identity table */
.abp-crud-page-wrapper .card,
.identity-page-content .card {
  border-radius: 12px !important;
  border: 1px solid var(--rad-border) !important;
  box-shadow: 0 1px 3px rgba(26,31,60,.07) !important;
  overflow: hidden !important;
}

/* ═══════════════════════════════════════════════════════════
   19. Z-Index Scale
════════════════════════════════════════════════════════════ */

:root {
  /* existing tokens … */

  /* ── Z-index scale ─────────────────────────────────────────── */
  --z-base:       0;      /* Static content                        */
  --z-raised:     10;     /* Slightly elevated cards, hover states  */
  --z-dropdown:   50;     /* Dot-menu dropdowns, select options     */
  --z-sticky:     100;    /* Sticky topbar                          */
  --z-overlay:    200;    /* Search results, notification dropdown  */
  --z-modal:      1000;   /* Modals and modal overlays              */
  --z-lookup:     1050;   /* Lookup lists (§57) — opened into the page body, so above a modal */
  --z-field-popover: 1050; /* Field helper popovers (§35.3, §35.4) — same reason as --z-lookup */
  --z-signature:  1100;   /* E-signature modal (above regular modals) */
  --z-idle:       2000;   /* Idle session warning (above everything) */
  --z-toast:      9999;   /* Toasts (always on top)                 */
}

.topbar            { z-index: var(--z-sticky); }
.dot-menu-dropdown { z-index: var(--z-dropdown); }
.topbar-search-results,
.notif-dropdown    { z-index: var(--z-overlay); }
.rad-modal-overlay { z-index: var(--z-modal); }
.sig-modal         { z-index: var(--z-signature); }
.idle-modal-overlay{ z-index: var(--z-idle); }
#abp-notification-container,
.abp-toast-container { z-index: var(--z-toast); }

/* ═══════════════════════════════════════════════════════════
   20.2 Audit Trail CSS
════════════════════════════════════════════════════════════ */

/* ── Audit trail card ──────────────────────────────────────── */
.audit-card .card-hdr { background: var(--rad-surface); }

/* Timeline container */
.audit-timeline {
  padding: 6px 22px 4px;
  position: relative;
}
.audit-timeline::before {
  content: '';
  position: absolute;
  left: 42px;
  top: 0; bottom: 0;
  width: 1px;
  background: var(--rad-border);
}

/* Single event row */
.audit-event {
  display: grid;
  grid-template-columns: 20px 1fr;
  gap: 0 16px;
  padding: 14px 0;
  border-bottom: 1px solid var(--rad-border);
  position: relative;
}
.audit-event:last-child { border-bottom: none; }

/* Dot on the timeline */
.audit-dot {
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--rad-blue);
  border: 2px solid var(--rad-white);
  box-shadow: 0 0 0 1px var(--rad-border);
  margin-top: 4px;
  position: relative;
  z-index: 1;
  flex-shrink: 0;
}
.audit-dot.dot-create  { background: var(--rad-success); }
.audit-dot.dot-update  { background: var(--rad-blue); }
.audit-dot.dot-delete  { background: var(--rad-error); }
.audit-dot.dot-approve { background: #7C3AED; }
.audit-dot.dot-sign    { background: var(--rad-warning); }
.audit-dot.dot-lock    { background: var(--rad-text-muted); }

/* Event content */
.audit-content { min-width: 0; }
.audit-header {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 4px;
}
.audit-action {
  font-size: 13px;
  font-weight: 600;
  color: var(--rad-text);
}
.audit-user {
  font-size: 12.5px;
  color: var(--rad-blue);
  font-weight: 500;
}
.audit-time {
  font-size: 11.5px;
  color: var(--rad-text-muted);
  margin-left: auto;
  white-space: nowrap;
  font-family: var(--mono);
}

/* Changed fields list */
.audit-changes {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 6px;
}
.audit-change-row {
  display: grid;
  grid-template-columns: 160px 1fr 1fr;
  gap: 8px;
  font-size: 12px;
  align-items: baseline;
}
.audit-field-name {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .03em;
  text-transform: uppercase;
  color: var(--rad-text-muted);
}
.audit-old-val {
  color: var(--rad-error);
  text-decoration: line-through;
  font-family: var(--mono);
  font-size: 12px;
}
.audit-new-val {
  color: var(--rad-success);
  font-family: var(--mono);
  font-size: 12px;
}

/* Signature badge on signed events */
.audit-sig-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: #F3E8FF;
  color: #7C3AED;
  border-radius: 4px;
  padding: 2px 8px;
  font-size: 11px;
  font-weight: 600;
  margin-top: 6px;
}

/* Reason code badge */
.audit-reason {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--rad-blue-tint);
  color: var(--rad-blue);
  border-radius: 4px;
  padding: 2px 8px;
  font-size: 11px;
  font-weight: 600;
  margin-top: 6px;
  margin-left: 4px;
}

/* ═══════════════════════════════════════════════════════════
   21.2 Lock State CSS
════════════════════════════════════════════════════════════ */

/* ── Locked record banner ──────────────────────────────────── */
.record-lock-banner {
  background: var(--rad-surface);
  border: 1px solid var(--rad-border);
  border-left: 4px solid var(--rad-text-muted);
  border-radius: 10px;
  padding: 14px 18px;
  margin-bottom: 18px;
  display: flex;
  align-items: flex-start;
  gap: 14px;
}
.record-lock-banner.lock-approved {
  border-left-color: var(--rad-success);
  background: var(--rad-success-tint);
}
.record-lock-banner.lock-released {
  border-left-color: #7C3AED;
  background: #F3E8FF;
}
.record-lock-banner.lock-archived {
  border-left-color: var(--rad-text-muted);
  background: var(--rad-surface);
}
.lock-banner-icon { flex-shrink: 0; margin-top: 1px; }
.lock-banner-icon.approved { color: var(--rad-success); }
.lock-banner-icon.released { color: #7C3AED; }
.lock-banner-icon.archived { color: var(--rad-text-muted); }
.lock-banner-body { flex: 1; min-width: 0; }
.lock-banner-title {
  font-size: 13px;
  font-weight: 700;
  color: var(--rad-text);
  margin-bottom: 3px;
}
.lock-banner-meta {
  font-size: 12px;
  color: var(--rad-text-2);
  line-height: 1.5;
}
.lock-banner-meta strong { color: var(--rad-text); }
.lock-banner-actions { display: flex; gap: 8px; align-items: center; }

/* Locked fields — visually distinct from disabled. A value the record holds but
   this form may not change: read at full contrast, not faded like a control that is
   merely unavailable. Selects are drawn without their chevron, as nothing opens. */
.form-control.locked,
.form-select.locked {
  background: var(--rad-code-bg) !important;
  border-color: transparent !important;
  color: var(--rad-text) !important;
  cursor: default !important;
  opacity: 1 !important;
  font-weight: 500;
}
select.form-control.locked,
.form-select.locked,
textarea.form-control.locked {
  appearance: none;
  background-image: none !important;
  resize: none;
}

/* Locked card — subtle overlay on card header */
.card.card-locked .card-hdr {
  background: var(--rad-surface);
}
.card.card-locked .card-hdr-title::before {
  background: var(--rad-text-muted);
}

/* ═══════════════════════════════════════════════════════════
   22.2 Label-Value Pair CSS
════════════════════════════════════════════════════════════ */

/* ── Read-only label-value grid ─────────────────────────────── */
.view-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
}
.view-field {
  padding: 12px 0;
  border-bottom: 1px solid var(--rad-border);
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.view-field:nth-last-child(-n+2) { border-bottom: none; }  /* last row */
.view-field.span-2 { grid-column: span 2; }

.view-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--rad-text-muted);
}
.view-value {
  font-size: 13.5px;
  color: var(--rad-text);
  line-height: 1.4;
}
.view-value.code {
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--rad-dot-dark);
  font-weight: 500;
}
.view-value.empty {
  color: var(--rad-text-muted);
  font-style: italic;
}

/* ── View page action bar ─────────────────────────────────────── */
.view-page-actions {
  display: flex;
  gap: 10px;
  align-items: center;
}

/* ═══════════════════════════════════════════════════════════
   23.1 File Upload CSS
════════════════════════════════════════════════════════════ */

/* ── File upload — drop zone ────────────────────────────────── */
.file-drop-zone {
  border: 2px dashed var(--rad-border);
  border-radius: 10px;
  background: var(--rad-input-bg);
  padding: 28px 22px;
  text-align: center;
  cursor: pointer;
  transition: border-color .15s, background .15s;
  position: relative;
}
.file-drop-zone:hover,
.file-drop-zone.drag-over {
  border-color: var(--rad-blue);
  background: var(--rad-blue-tint);
}
.file-drop-zone input[type="file"] {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
  width: 100%;
  height: 100%;
}
.file-drop-icon {
  color: var(--rad-text-muted);
  margin-bottom: 10px;
  transition: color .15s;
}
.file-drop-zone:hover .file-drop-icon,
.file-drop-zone.drag-over .file-drop-icon { color: var(--rad-blue); }
.file-drop-title {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--rad-text);
  margin-bottom: 4px;
}
.file-drop-title span { color: var(--rad-blue); }
.file-drop-hint {
  font-size: 12px;
  color: var(--rad-text-muted);
}

/* ── Attached file list ────────────────────────────────────── */
.file-list { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }

.file-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: var(--rad-white);
  border: 1px solid var(--rad-border);
  border-radius: 8px;
  font-size: 13px;
}
.file-item-icon {
  width: 32px; height: 32px;
  border-radius: 7px;
  background: var(--rad-blue-tint);
  display: flex; align-items: center; justify-content: center;
  color: var(--rad-blue);
  flex-shrink: 0;
}
.file-item-icon.pdf-icon  { background: #FEF2F2; color: var(--rad-error); }
.file-item-icon.xlsx-icon { background: #E8F7EE; color: var(--rad-success); }
.file-item-icon.doc-icon  { background: var(--rad-blue-tint); color: var(--rad-blue); }
.file-item-name {
  flex: 1;
  font-weight: 500;
  color: var(--rad-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.file-item-size {
  font-size: 11.5px;
  color: var(--rad-text-muted);
  font-family: var(--mono);
  flex-shrink: 0;
}
.file-item-remove {
  width: 24px; height: 24px;
  border-radius: 6px;
  border: 1px solid transparent;
  background: none;
  cursor: pointer;
  color: var(--rad-text-muted);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  transition: all .15s;
}
.file-item-remove:hover {
  border-color: var(--rad-error-border);
  background: var(--rad-error-tint);
  color: var(--rad-error);
}

/* Upload progress bar */
.file-item-progress {
  width: 100%;
  height: 3px;
  background: var(--rad-border);
  border-radius: 2px;
  margin-top: 6px;
  overflow: hidden;
}
.file-item-progress-bar {
  height: 100%;
  background: var(--rad-blue);
  border-radius: 2px;
  transition: width .3s ease;
}

/* ═══════════════════════════════════════════════════════════
   24.2 Inline Alert CSS
════════════════════════════════════════════════════════════ */

/* ── Page-level banner ─────────────────────────────────────── */
.page-banner {
  border-radius: 10px;
  padding: 13px 16px;
  margin-bottom: 18px;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-size: 13px;
  line-height: 1.5;
}
.page-banner.banner-info {
  background: var(--rad-blue-tint);
  border: 1px solid rgba(26,79,160,.2);
  color: var(--rad-text);
}
.page-banner.banner-info .banner-icon { color: var(--rad-blue); }

.page-banner.banner-warning {
  background: var(--rad-warning-tint);
  border: 1px solid rgba(240,165,0,.3);
  color: var(--rad-text);
}
.page-banner.banner-warning .banner-icon { color: var(--rad-warning); }

.page-banner.banner-error {
  background: var(--rad-error-tint);
  border: 1px solid var(--rad-error-border);
  color: var(--rad-text);
}
.page-banner.banner-error .banner-icon { color: var(--rad-error); }

.page-banner.banner-success {
  background: var(--rad-success-tint);
  border: 1px solid rgba(39,174,96,.3);
  color: var(--rad-text);
}
.page-banner.banner-success .banner-icon { color: var(--rad-success); }

.banner-icon { flex-shrink: 0; margin-top: 1px; }
.banner-body { flex: 1; min-width: 0; }
.banner-title {
  font-weight: 700;
  color: var(--rad-text);
  margin-bottom: 2px;
}
.banner-text { color: var(--rad-text-2); }
.banner-actions { margin-top: 8px; display: flex; gap: 8px; }
.banner-dismiss {
  flex-shrink: 0;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--rad-text-muted);
  padding: 0;
  line-height: 1;
  font-size: 16px;
  transition: color .15s;
  margin-top: -1px;
}
.banner-dismiss:hover { color: var(--rad-text); }

/* ═══════════════════════════════════════════════════════════
   24.4 ABP Page Alert → Radinik Banner Bridge
════════════════════════════════════════════════════════════ */

/* ABP's PageAlertsViewComponent emits Bootstrap `.alert.alert-*` markup, so it
   arrives with Bootstrap's palette, 16px type and its own close button — the
   last untouched-Bootstrap surface in the app, and the one a user meets first
   on a failed login. Map it onto the .page-banner vocabulary here rather than
   re-templating the component, so both the auth card and the app shell get it. */
.alert {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  border-radius: 10px;
  padding: 13px 16px;
  margin-bottom: 18px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--rad-text);
}
.alert-danger  { background: var(--rad-error-tint);   border: 1px solid var(--rad-error-border); }
.alert-warning { background: var(--rad-warning-tint); border: 1px solid rgba(240,165,0,.3); }
.alert-success { background: var(--rad-success-tint); border: 1px solid rgba(39,174,96,.3); }
.alert-info,
.alert-primary,
.alert-secondary { background: var(--rad-blue-tint); border: 1px solid rgba(26,79,160,.2); }

/* The status colour lives in the badge, not in the message text, so the copy
   stays at full contrast. Same badge shape as .field-error / .field-warning. */
.alert::before {
  content: '!';
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  width: 16px; height: 16px; margin-top: 1px;
  border-radius: 50%;
  font-size: 10px; font-weight: 700; line-height: 1;
  color: #fff;
}
.alert-danger::before  { background: var(--rad-error); }
.alert-warning::before { background: var(--rad-warning); }
.alert-success::before { content: '✓'; background: var(--rad-success); }
.alert-info::before,
.alert-primary::before,
.alert-secondary::before { content: 'i'; background: var(--rad-blue); }

.alert > .alert-body { flex: 1; min-width: 0; }
.alert h4 {
  font-size: 13px; font-weight: 700;
  color: var(--rad-text);
  margin: 0 0 2px;
}
.alert p { margin: 0; color: var(--rad-text-2); }
.alert a { color: var(--rad-blue); font-weight: 500; }

/* Bootstrap absolutely positions .btn-close inside .alert-dismissible and pads
   the alert 3rem on the right to clear it. Put it back in the flow. */
.alert-dismissible { padding-right: 16px; }
.alert-dismissible .btn-close,
.alert .btn-close {
  position: static;
  flex-shrink: 0;
  margin-left: auto;
  width: auto; height: auto; padding: 0;
  background: none; border: none; opacity: 1;
  color: var(--rad-text-muted);
  font-size: 0; line-height: 1;
  border-radius: 4px;
  cursor: pointer;
  transition: color .15s;
}
.alert .btn-close::before { content: '✕'; font-size: 12px; line-height: 1; }
.alert .btn-close:hover { color: var(--rad-text); }
.alert .btn-close:focus-visible {
  outline: none;
  color: var(--rad-text);
  box-shadow: 0 0 0 3px var(--rad-blue-muted);
}

/* ═══════════════════════════════════════════════════════════
   25.2 KPI Tile CSS
════════════════════════════════════════════════════════════ */

/* ── KPI / Stat tiles ──────────────────────────────────────── */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  margin-bottom: 20px;
}

/* Three tiles, not four. The grid's default leaves an empty column, which reads as a
   tile that failed to load rather than as a deliberate row of three. */
.kpi-grid-3 { grid-template-columns: repeat(3, 1fr); }

.kpi-tile {
  background: var(--rad-white);
  border-radius: 12px;
  border: 1px solid var(--rad-border);
  box-shadow: 0 1px 3px rgba(26,31,60,.07);
  padding: 20px 22px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  position: relative;
  overflow: hidden;
}

/* Accent bar — top edge, coloured by type */
.kpi-tile::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  border-radius: 12px 12px 0 0;
}
.kpi-tile.kpi-blue::before    { background: var(--rad-blue); }
.kpi-tile.kpi-success::before { background: var(--rad-success); }
.kpi-tile.kpi-warning::before { background: var(--rad-warning); }
.kpi-tile.kpi-purple::before  { background: #7C3AED; }

.kpi-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
}
.kpi-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--rad-text-muted);
}
.kpi-icon {
  width: 34px; height: 34px;
  border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.kpi-tile.kpi-blue    .kpi-icon { background: var(--rad-blue-tint);    color: var(--rad-blue); }
.kpi-tile.kpi-success .kpi-icon { background: var(--rad-success-tint); color: var(--rad-success); }
.kpi-tile.kpi-warning .kpi-icon { background: var(--rad-warning-tint); color: var(--rad-warning); }
.kpi-tile.kpi-purple  .kpi-icon { background: #F3E8FF;                 color: #7C3AED; }

.kpi-value {
  font-size: 28px;
  font-weight: 700;
  color: var(--rad-text);
  letter-spacing: -.5px;
  line-height: 1;
  font-family: var(--mono);
}

.kpi-trend {
  font-size: 12px;
  font-weight: 500;
  display: flex;
  align-items: center;
  gap: 4px;
}
.kpi-trend.up   { color: var(--rad-success); }
.kpi-trend.down { color: var(--rad-error); }
.kpi-trend.flat { color: var(--rad-text-muted); }

.kpi-subtext {
  font-size: 12px;
  color: var(--rad-text-muted);
}

/* ── Pending actions list ──────────────────────────────────── */
.action-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid var(--rad-border);
}
.action-item:last-child { border-bottom: none; }
.action-priority {
  width: 8px; height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
  margin-top: 5px;
}
.action-priority.high   { background: var(--rad-error); }
.action-priority.medium { background: var(--rad-warning); }
.action-priority.low    { background: var(--rad-blue); }
.action-body { flex: 1; min-width: 0; }
.action-title {
  font-size: 13px;
  font-weight: 500;
  color: var(--rad-text);
  margin-bottom: 2px;
}
.action-meta {
  font-size: 11.5px;
  color: var(--rad-text-muted);
}
.action-due {
  font-size: 11.5px;
  font-family: var(--mono);
  color: var(--rad-text-muted);
  white-space: nowrap;
  flex-shrink: 0;
}
.action-due.overdue { color: var(--rad-error); font-weight: 600; }

/* ═══════════════════════════════════════════════════════════
   27.2 Plant Context & Data Scoping
════════════════════════════════════════════════════════════ */

/* ── Active location pill in the topbar ────────────────────────
   Sits beside the user pill and takes its shape, so the two read
   as one "who and where" cluster. A link (with a caret) only for a
   user holding several locations; a plain label otherwise. */
.loc-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  max-width: 220px;
  padding: 5px 12px;
  border-radius: 50px;
  border: 1px solid var(--rad-border);
  background: var(--rad-surface);
  color: var(--rad-text);
  font-size: 12.5px;
  font-weight: 600;
  text-decoration: none;
  flex-shrink: 0;
}
.loc-pill > .fa-location-dot { color: var(--rad-blue); font-size: 12px; }
.loc-pill-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.loc-pill-caret { font-size: 9px; color: var(--rad-text-muted); }

.loc-pill-switch { cursor: pointer; transition: border-color .15s; }
.loc-pill-switch:hover { border-color: var(--rad-blue); color: var(--rad-text); }
.loc-pill-switch:focus-visible {
  outline: none;
  border-color: var(--rad-blue);
  box-shadow: 0 0 0 3px var(--rad-blue-muted);
}

/* No location chosen, or none assigned — nothing can be written until
   that is put right, so it must not read as a normal state. */
.loc-pill.loc-pill-warn {
  background: var(--rad-warning-tint);
  border-color: var(--rad-warning);
  color: var(--rad-warning);
}
.loc-pill.loc-pill-warn > .fa-location-dot,
.loc-pill.loc-pill-warn .loc-pill-caret { color: var(--rad-warning); }

/* ═══════════════════════════════════════════════════════════
   28.2 Aggregation Tree CSS
════════════════════════════════════════════════════════════ */

/* ── Aggregation tree ───────────────────────────────────────── */
.agg-tree {
  font-family: var(--font);
  font-size: 13px;
}

/* Each node row */
.agg-node {
  display: flex;
  align-items: flex-start;
  gap: 0;
  position: relative;
}

/* Indentation lines */
.agg-indent {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 28px;
  flex-shrink: 0;
  position: relative;
}
.agg-indent-line {
  width: 1px;
  background: var(--rad-border);
  flex: 1;
  min-height: 100%;
  position: absolute;
  left: 14px;
  top: 0; bottom: 0;
}
.agg-indent-elbow {
  width: 14px;
  height: 20px;
  border-left: 1px solid var(--rad-border);
  border-bottom: 1px solid var(--rad-border);
  border-radius: 0 0 0 4px;
  flex-shrink: 0;
  margin-top: 10px;
}

/* Node content */
.agg-node-content {
  flex: 1;
  min-width: 0;
  border: 1px solid var(--rad-border);
  border-radius: 8px;
  margin: 3px 0;
  overflow: hidden;
  transition: box-shadow .15s;
}
.agg-node-content:hover {
  box-shadow: 0 2px 8px rgba(26,31,60,.1);
}

/* Node header bar */
.agg-node-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  background: var(--rad-white);
  cursor: pointer;
  user-select: none;
}
.agg-node-header:hover { background: var(--rad-row-hover); }

/* Level type badge */
.agg-level-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 7px;
  border-radius: 4px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  flex-shrink: 0;
}
.agg-level-pallet  { background: #F3E8FF; color: #7C3AED; }
.agg-level-case    { background: var(--rad-blue-tint); color: var(--rad-blue); }
.agg-level-carton  { background: var(--rad-warning-tint); color: var(--rad-warning); }
.agg-level-item    { background: var(--rad-success-tint); color: var(--rad-success); }

/* Serial number */
.agg-serial {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--rad-dot-dark);
  font-weight: 500;
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* GTIN + batch */
.agg-meta {
  font-size: 11.5px;
  color: var(--rad-text-muted);
  white-space: nowrap;
  flex-shrink: 0;
}

/* Plant origin tag — shown on cross-plant nodes */
.agg-plant-tag {
  font-size: 10.5px;
  font-weight: 600;
  color: var(--rad-text-2);
  background: var(--rad-surface);
  border: 1px solid var(--rad-border);
  border-radius: 4px;
  padding: 1px 6px;
  flex-shrink: 0;
}

/* Status indicator */
.agg-status {
  width: 8px; height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}
.agg-status.commissioned  { background: var(--rad-success); }
.agg-status.aggregated    { background: var(--rad-blue); }
.agg-status.shipped       { background: #7C3AED; }
.agg-status.decommissioned{ background: var(--rad-error); }
.agg-status.sampled       { background: var(--rad-warning); }

/* Expand/collapse chevron */
.agg-chevron {
  color: var(--rad-text-muted);
  transition: transform .2s;
  flex-shrink: 0;
}
.agg-node-content.open .agg-chevron { transform: rotate(90deg); }

/* Children container */
.agg-children {
  padding: 0 0 6px 28px;
  display: none;
}
.agg-node-content.open + .agg-children,
.agg-children.open { display: block; }

/* Child count badge */
.agg-count {
  font-size: 11px;
  color: var(--rad-text-muted);
  background: var(--rad-surface);
  border: 1px solid var(--rad-border);
  border-radius: 10px;
  padding: 1px 7px;
  flex-shrink: 0;
}

/* Truncated items indicator */
.agg-truncated {
  padding: 8px 14px;
  font-size: 12px;
  color: var(--rad-blue);
  cursor: pointer;
  font-weight: 500;
}
.agg-truncated:hover { text-decoration: underline; }

/* ═══════════════════════════════════════════════════════════
   29.2 EPCIS Timeline CSS
════════════════════════════════════════════════════════════ */

/* ── EPCIS timeline modal content ──────────────────────────── */
.epcis-timeline {
  display: flex;
  flex-direction: column;
  gap: 0;
}

/* Event row */
.epcis-event {
  border-bottom: 1px solid var(--rad-border);
  cursor: pointer;
  transition: background .1s;
}
.epcis-event:last-child { border-bottom: none; }
.epcis-event:hover .epcis-event-header { background: var(--rad-row-hover); }
.epcis-event.open .epcis-event-header  { background: var(--rad-blue-tint); }

.epcis-event-header {
  display: grid;
  grid-template-columns: 100px 140px 1fr 120px 80px;
  gap: 10px;
  align-items: center;
  padding: 11px 16px;
  transition: background .1s;
}

/* Event type badge */
.epcis-type {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: 4px;
}
.epcis-type.object      { background: var(--rad-blue-tint);    color: var(--rad-blue); }
.epcis-type.aggregation { background: #F3E8FF;                 color: #7C3AED; }
.epcis-type.transaction { background: var(--rad-success-tint); color: var(--rad-success); }
.epcis-type.transform   { background: var(--rad-warning-tint); color: var(--rad-warning); }

/* Business step */
.epcis-step {
  font-size: 12px;
  color: var(--rad-text-2);
  font-weight: 500;
}

/* Disposition */
.epcis-disposition {
  font-size: 12px;
  color: var(--rad-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Timestamp */
.epcis-time {
  font-size: 11.5px;
  font-family: var(--mono);
  color: var(--rad-text-muted);
  white-space: nowrap;
}

/* Submission status */
.epcis-sub-status {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  font-weight: 600;
}
.epcis-sub-status.sent      { color: var(--rad-success); }
.epcis-sub-status.pending   { color: var(--rad-warning); }
.epcis-sub-status.failed    { color: var(--rad-error); }
.epcis-sub-status.acked     { color: #7C3AED; }

/* Expand chevron */
.epcis-chevron {
  justify-self: end;
  color: var(--rad-text-muted);
  transition: transform .2s;
}
.epcis-event.open .epcis-chevron { transform: rotate(90deg); }

/* Expanded detail panel */
.epcis-detail {
  display: none;
  padding: 14px 16px;
  background: var(--rad-surface);
  border-top: 1px solid var(--rad-border);
}
.epcis-event.open .epcis-detail { display: block; }

/* Detail tabs: Readable | Raw XML/JSON */
.epcis-detail-tabs {
  display: flex;
  gap: 0;
  border-bottom: 1px solid var(--rad-border);
  margin-bottom: 14px;
}
.epcis-detail-tab {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--rad-text-muted);
  padding: 7px 14px;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color .15s, border-color .15s;
}
.epcis-detail-tab.active {
  color: var(--rad-blue);
  border-bottom-color: var(--rad-blue);
  font-weight: 600;
}

/* Raw event code block */
.epcis-raw {
  background: var(--rad-code-bg);
  border-radius: 8px;
  padding: 14px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--rad-dot-dark);
  overflow-x: auto;
  white-space: pre;
  max-height: 280px;
  overflow-y: auto;
}

/* Readable key-value pairs */
.epcis-readable {
  display: grid;
  grid-template-columns: 160px 1fr;
  gap: 8px 16px;
}
.epcis-readable-key {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--rad-text-muted);
  align-self: start;
  padding-top: 1px;
}
.epcis-readable-val {
  font-size: 13px;
  color: var(--rad-text);
  font-family: var(--mono);
  word-break: break-all;
}

/* ═══════════════════════════════════════════════════════════
   30.1 Inline Integration Status (on records)
════════════════════════════════════════════════════════════ */

/* ── Integration status bar ─────────────────────────────────── */
.integration-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  flex-wrap: wrap;
}
.int-status-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 10px;
  border-radius: 6px;
  font-size: 11.5px;
  font-weight: 600;
  border: 1px solid transparent;
}
/* SAP */
.int-status-pill.int-sap {
  background: var(--rad-surface);
  border-color: var(--rad-border);
  color: var(--rad-text-2);
}
/* TraceLink */
.int-status-pill.int-tracelink {
  background: var(--rad-surface);
  border-color: var(--rad-border);
  color: var(--rad-text-2);
}
/* States */
.int-dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}
.int-dot.synced  { background: var(--rad-success); }
.int-dot.pending { background: var(--rad-warning); }
.int-dot.failed  { background: var(--rad-error); }
.int-dot.na      { background: var(--rad-border); }

.int-status-pill.has-error {
  background: var(--rad-error-tint);
  border-color: var(--rad-error-border);
  color: var(--rad-error);
  cursor: pointer;
}
.int-status-pill.has-error:hover { opacity: .85; }

/* ═══════════════════════════════════════════════════════════
   30.2 Integration Monitor Page
════════════════════════════════════════════════════════════ */

/* ── Integration monitor ────────────────────────────────────── */
.int-monitor-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin-bottom: 20px;
}
.int-system-tile {
  background: var(--rad-white);
  border-radius: 12px;
  border: 1px solid var(--rad-border);
  box-shadow: 0 1px 3px rgba(26,31,60,.07);
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.int-system-header {
  display: flex;
  align-items: center;
  justify-content: space-between;

  /* space-between leaves nothing between them once the tile is narrow, and the
     provider type then runs straight into the connection status. */
  gap: 10px;
}
.int-system-name {
  font-size: 13px;
  font-weight: 700;
  color: var(--rad-text);
  display: flex;
  align-items: center;
  gap: 8px;

  /* A long connection name wraps inside the tile rather than pushing the status
     out of it. */
  flex-wrap: wrap;
  min-width: 0;
}
.int-system-type {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--rad-text-muted);
}
.int-conn-status {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  flex-shrink: 0;
}
.int-conn-status.connected    { color: var(--rad-success); }
.int-conn-status.disconnected { color: var(--rad-error); }
.int-conn-status.degraded     { color: var(--rad-warning); }

.int-stats {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 8px;
  padding-top: 10px;
  border-top: 1px solid var(--rad-border);
}
.int-stat-item { display: flex; flex-direction: column; gap: 2px; }
.int-stat-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--rad-text-muted);
}
.int-stat-value {
  font-size: 18px;
  font-weight: 700;
  font-family: var(--mono);
  color: var(--rad-text);
  letter-spacing: -.3px;
}
.int-stat-value.has-failures { color: var(--rad-error); }
.int-stat-value.all-good     { color: var(--rad-success); }

.int-last-sync {
  font-size: 11.5px;
  color: var(--rad-text-muted);
  font-family: var(--mono);
}

/* ═══════════════════════════════════════════════════════════
   33.1 CSS
════════════════════════════════════════════════════════════ */

/* ── ABP page progress bar ───────────────────────────────────── */
#nprogress .bar {
  background: var(--rad-blue) !important;
  height: 3px !important;
  box-shadow: none !important;
}
#nprogress .peg {
  box-shadow: 0 0 10px var(--rad-blue), 0 0 5px var(--rad-blue) !important;
}
#nprogress .spinner-icon {
  border-top-color:  var(--rad-blue) !important;
  border-left-color: var(--rad-blue) !important;
}

/* ABP setBusy overlay — shown over a card/element while loading */
.abp-busy-indicator {
  background: rgba(255,255,255,0.75) !important;
  border-radius: inherit;
}
.abp-busy-indicator .abp-busy-message {
  font-family: var(--font) !important;
  font-size: 13px !important;
  color: var(--rad-text-2) !important;
}
.abp-busy-indicator i {
  color: var(--rad-blue) !important;
}

/* ═══════════════════════════════════════════════════════════
   34.2 Settings Page Shell CSS
════════════════════════════════════════════════════════════ */

/* ── Settings page layout ────────────────────────────────────── */
.settings-layout {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 20px;
  align-items: start;
}

/* Left: category navigation */
.settings-nav {
  background: var(--rad-white);
  border: 1px solid var(--rad-border);
  border-radius: 12px;
  overflow: hidden;
  position: sticky;
  top: 80px;   /* topbar height + margin */
}
.settings-nav-section {
  padding: 12px 14px 6px;
  border-bottom: 1px solid var(--rad-border);
}
.settings-nav-section:last-child { border-bottom: none; }
.settings-nav-label {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--rad-text-muted);
  padding: 0 6px;
  margin-bottom: 4px;
}
.settings-nav-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 7px;
  font-size: 13px;
  font-weight: 500;
  color: var(--rad-text-2);
  cursor: pointer;
  transition: background .15s, color .15s;
  text-decoration: none;
  margin-bottom: 2px;
}
.settings-nav-item:hover  { background: var(--rad-surface); color: var(--rad-text); }
.settings-nav-item.active { background: var(--rad-blue-tint); color: var(--rad-blue); font-weight: 600; }

/* Right: settings content */
.settings-content { min-width: 0; }

/* Global / Per-plant scope indicator on a setting group */
.settings-scope-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: 4px;
  margin-left: 8px;
}
.settings-scope-badge.global    { background: var(--rad-blue-tint); color: var(--rad-blue); }
.settings-scope-badge.per-plant { background: var(--rad-warning-tint); color: var(--rad-warning); }

/* Plant override indicator — shown when a setting has a plant-level override */
.settings-overridden {
  font-size: 11px;
  color: var(--rad-warning);
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 4px;
}

/* ═══════════════════════════════════════════════════════════
   35.1 CSS
════════════════════════════════════════════════════════════ */

/* ── Serial range display ────────────────────────────────────── */
.serial-range-block {
  background: var(--rad-code-bg);
  border: 1px solid var(--rad-border);
  border-radius: 8px;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.serial-range-row {
  display: grid;
  grid-template-columns: 200px 200px 100px 1fr auto;
  gap: 10px;
  align-items: center;
  font-family: var(--mono);
  font-size: 12px;
}

.serial-range-label {
  font-family: var(--font);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--rad-text-muted);
  margin-bottom: 4px;
}

.serial-range-value {
  color: var(--rad-dot-dark);
  font-weight: 500;
}
.serial-range-separator {
  color: var(--rad-text-muted);
  font-weight: 400;
  text-align: center;
}
.serial-range-count {
  color: var(--rad-text-2);
  font-family: var(--font);
  font-size: 12px;
}
.serial-range-status {
  justify-self: end;
}

/* GS1 identifier formatting helpers */
.gtin-formatted {
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--rad-dot-dark);
  font-weight: 500;
  letter-spacing: .02em;
}
.sscc-formatted {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--rad-dot-dark);
}

/* ═══════════════════════════════════════════════════════════
   36.1 Exception Severity & Status Tokens
════════════════════════════════════════════════════════════ */

/* ── Exception severity badges ───────────────────────────────── */
.exc-severity {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.exc-severity.critical { background: #FEE2E2; color: #991B1B; }
.exc-severity.high     { background: var(--rad-error-tint); color: var(--rad-error); }
.exc-severity.medium   { background: var(--rad-warning-tint); color: var(--rad-warning); }
.exc-severity.low      { background: var(--rad-blue-tint); color: var(--rad-blue); }
.exc-severity.info     { background: var(--rad-surface); color: var(--rad-text-muted); }

/* Exception status */
.exc-status { /* uses standard .tag classes */ }

/* Exception resolution card */
.exc-resolution {
  background: var(--rad-success-tint);
  border: 1px solid rgba(39,174,96,.3);
  border-radius: 8px;
  padding: 12px 14px;
  margin-top: 12px;
  font-size: 12.5px;
  color: var(--rad-text-2);
}
.exc-resolution-title {
  font-weight: 700;
  color: var(--rad-success);
  margin-bottom: 4px;
}

/* The same card carrying a failure, not a resolution (a provisioning run's error). */
.exc-resolution.is-error {
  background: var(--rad-error-tint);
  border-color: var(--rad-error-border);
}
.exc-resolution.is-error .exc-resolution-title { color: var(--rad-error); }

/* ═══════════════════════════════════════════════════════════
   37.1 Scan Input CSS
════════════════════════════════════════════════════════════ */

/* ── Scanner input field ─────────────────────────────────────── */
.scan-input-wrap {
  position: relative;
  /* Stretches like the input it wraps would have, inside .form-group's column. */
  width: 100%;
  align-self: stretch;
}
.scan-input-wrap .form-control {
  padding-left: 38px;
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: .02em;
  border-width: 2px;
  transition: border-color .1s, box-shadow .1s, background .1s;
}

/* Scan icon */
.scan-input-icon {
  position: absolute;
  left: 11px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--rad-text-muted);
  pointer-events: none;
  transition: color .1s;
}

/* States */
.scan-input-wrap.scan-success .form-control {
  border-color: var(--rad-success) !important;
  background: var(--rad-success-tint) !important;
  box-shadow: 0 0 0 3px rgba(39,174,96,0.15) !important;
}
.scan-input-wrap.scan-success .scan-input-icon { color: var(--rad-success); }

.scan-input-wrap.scan-error .form-control {
  border-color: var(--rad-error) !important;
  background: var(--rad-error-tint) !important;
  box-shadow: 0 0 0 3px rgba(220,38,38,0.12) !important;
}
.scan-input-wrap.scan-error .scan-input-icon { color: var(--rad-error); }

.scan-input-wrap.scan-processing .form-control {
  border-color: var(--rad-warning) !important;
  background: var(--rad-warning-tint) !important;
}

/* Feedback message below the input */
.scan-feedback {
  font-size: 12px;
  font-family: var(--mono);
  margin-top: 6px;
  min-height: 18px;
  transition: color .1s;
}
.scan-feedback.success { color: var(--rad-success); font-weight: 600; }
.scan-feedback.error   { color: var(--rad-error);   font-weight: 600; }
.scan-feedback.info    { color: var(--rad-text-muted); }

/* ═══════════════════════════════════════════════════════════
   38.1 Stepper CSS
════════════════════════════════════════════════════════════ */

/* ── Batch status stepper ────────────────────────────────────── */
.status-stepper {
  display: flex;
  align-items: flex-start;
  padding: 20px 22px;
  overflow-x: auto;
  gap: 0;
}

.stepper-step {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 1;
  min-width: 110px;
  position: relative;
}

/* Connector line between steps */
.stepper-step:not(:last-child)::after {
  content: '';
  position: absolute;
  top: 14px;
  left: calc(50% + 16px);
  right: calc(-50% + 16px);
  height: 2px;
  background: var(--rad-border);
  z-index: 0;
}
.stepper-step.completed:not(:last-child)::after {
  background: var(--rad-blue);
}

/* Step circle */
.stepper-circle {
  width: 28px; height: 28px;
  border-radius: 50%;
  border: 2px solid var(--rad-border);
  background: var(--rad-white);
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700;
  color: var(--rad-text-muted);
  position: relative;
  z-index: 1;
  flex-shrink: 0;
  transition: all .2s;
}
.stepper-step.completed .stepper-circle {
  background: var(--rad-blue);
  border-color: var(--rad-blue);
  color: #fff;
}
.stepper-step.active .stepper-circle {
  background: var(--rad-white);
  border-color: var(--rad-blue);
  border-width: 3px;
  color: var(--rad-blue);
}
.stepper-step.error .stepper-circle {
  background: var(--rad-error);
  border-color: var(--rad-error);
  color: #fff;
}

/* Step label */
.stepper-label {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--rad-text-muted);
  margin-top: 8px;
  text-align: center;
  white-space: nowrap;
}
.stepper-step.completed .stepper-label { color: var(--rad-blue); }
.stepper-step.active    .stepper-label { color: var(--rad-text); }
.stepper-step.error     .stepper-label { color: var(--rad-error); }

/* Step meta — timestamp + signatory */
.stepper-meta {
  font-size: 10.5px;
  color: var(--rad-text-muted);
  text-align: center;
  margin-top: 4px;
  line-height: 1.4;
  font-family: var(--mono);
}

/* ═══════════════════════════════════════════════════════════
   39.1 Signature Block CSS
════════════════════════════════════════════════════════════ */

/* ── Printed signature block ─────────────────────────────────── */
.sig-print-block {
  border: 1px solid var(--rad-border);
  border-radius: 8px;
  padding: 14px 18px;
  margin-top: 20px;
  background: var(--rad-surface);
}
.sig-print-block-title {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--rad-text-muted);
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--rad-border);
}
.sig-print-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}
.sig-print-field { display: flex; flex-direction: column; gap: 3px; }
.sig-print-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--rad-text-muted);
}
.sig-print-value {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--rad-text);
  font-family: var(--mono);
}
.sig-print-meaning {
  grid-column: span 4;
  font-size: 11.5px;
  color: var(--rad-text-2);
  font-style: italic;
  line-height: 1.5;
  padding-top: 10px;
  border-top: 1px solid var(--rad-border);
  margin-top: 6px;
}

/* Print-only visibility */
@media screen { .sig-print-block { display: block; } }
@media print  {
  .sig-print-block {
    border: 1px solid #999 !important;
    background: none !important;
    break-inside: avoid;
    page-break-inside: avoid;
  }
  .sig-print-meaning { border-top-color: #999 !important; }
}

/* ═══════════════════════════════════════════════════════════
   40.1 CSS
════════════════════════════════════════════════════════════ */

/* ── Confirmation phrase input ───────────────────────────────── */
.confirm-phrase-wrap {
  margin-top: 14px;
}
.confirm-phrase-instruction {
  font-size: 13px;
  color: var(--rad-text-2);
  margin-bottom: 8px;
  line-height: 1.5;
}
.confirm-phrase-instruction code {
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 700;
  color: var(--rad-dot-dark);
  background: var(--rad-code-bg);
  padding: 1px 5px;
  border-radius: 4px;
}
.confirm-phrase-input {
  font-family: var(--mono) !important;
  font-size: 13px !important;
  letter-spacing: .02em;
}
.confirm-phrase-input.phrase-match {
  border-color: var(--rad-success) !important;
  background: var(--rad-success-tint) !important;
}

/* ═══════════════════════════════════════════════════════════
   41. ABP Feature Management Override
════════════════════════════════════════════════════════════ */

/* ── ABP Feature Management modal ────────────────────────────── */
/* Reuses §18.1 modal-dialog overrides — no additional CSS needed */

/* Feature group headers */
.feature-group-header,
abp-feature-group-header {
  font-size: 11px !important;
  font-weight: 700 !important;
  letter-spacing: .06em !important;
  text-transform: uppercase !important;
  color: var(--rad-text-2) !important;
  padding: 10px 0 6px !important;
  border-bottom: 1px solid var(--rad-border) !important;
  margin-bottom: 4px !important;
  font-family: var(--font) !important;
}

/* Feature items — reuse permission tree styles */
.feature-list .form-check           { padding: 5px 0 5px 24px !important; border-radius: 6px; transition: background .1s; }
.feature-list .form-check:hover     { background: var(--rad-row-hover); }
.feature-list .form-check-input     { accent-color: var(--rad-blue); width: 14px; height: 14px; cursor: pointer; }
.feature-list .form-check-label     { font-size: 13px !important; color: var(--rad-text) !important; font-family: var(--font) !important; cursor: pointer; }

/* Feature value input (text/number features) */
.feature-list .feature-value-input  { /* inherits .form-control via §18.1 */ }

/* ═══════════════════════════════════════════════════════════
   42. ABP `ObjectExtending` Extra Fields
════════════════════════════════════════════════════════════ */

/* ── Extra fields injected by ObjectExtensionManager ─────────── */

/* ABP wraps extra fields in .row > .col — flatten to Radinik form-group */
.modal-dialog .extra-properties .row  { display: contents; }
.modal-dialog .extra-properties [class*="col-"] { display: contents; }

.modal-dialog .extra-properties {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--rad-border);
}

/* Section label above the extra fields block */
.modal-dialog .extra-properties::before {
  content: attr(data-section-label);
  grid-column: span 2;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--rad-text-muted);
}

/* ═══════════════════════════════════════════════════════════
   43.1 Download Link CSS
════════════════════════════════════════════════════════════ */

/* ── Read-only attachment list (view mode) ───────────────────── */
.attachment-list { display: flex; flex-direction: column; gap: 8px; }

.attachment-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: var(--rad-white);
  border: 1px solid var(--rad-border);
  border-radius: 8px;
  text-decoration: none;
  color: inherit;
  transition: border-color .15s, box-shadow .15s;
}
.attachment-item:hover {
  border-color: var(--rad-blue);
  box-shadow: 0 2px 8px rgba(26,79,160,.1);
}
.attachment-item-icon {
  width: 32px; height: 32px;
  border-radius: 7px;
  background: var(--rad-blue-tint);
  display: flex; align-items: center; justify-content: center;
  color: var(--rad-blue);
  flex-shrink: 0;
}
.attachment-item-icon.pdf  { background: #FEF2F2; color: var(--rad-error); }
.attachment-item-icon.xlsx { background: #E8F7EE; color: var(--rad-success); }
.attachment-item-name {
  flex: 1;
  font-size: 13px;
  font-weight: 500;
  color: var(--rad-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.attachment-item-meta {
  font-size: 11.5px;
  color: var(--rad-text-muted);
  font-family: var(--mono);
  white-space: nowrap;
  flex-shrink: 0;
}
.attachment-download-icon {
  color: var(--rad-blue);
  flex-shrink: 0;
}

/* ═══════════════════════════════════════════════════════════
   44.1 Wizard CSS
════════════════════════════════════════════════════════════ */

/* ── Wizard step indicator ───────────────────────────────────── */
.wizard-header {
  background: var(--rad-white);
  border: 1px solid var(--rad-border);
  border-radius: 12px;
  padding: 20px 28px;
  margin-bottom: 20px;
  box-shadow: 0 1px 3px rgba(26,31,60,.07);
}
.wizard-steps {
  display: flex;
  align-items: center;
  gap: 0;
  position: relative;
}
.wizard-step {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 1;
  position: relative;
  gap: 8px;
}

/* Connector */
.wizard-step:not(:last-child)::after {
  content: '';
  position: absolute;
  top: 14px;
  left: calc(50% + 18px);
  right: calc(-50% + 18px);
  height: 2px;
  background: var(--rad-border);
  z-index: 0;
}
.wizard-step.completed:not(:last-child)::after { background: var(--rad-blue); }

/* Circle */
.wizard-circle {
  width: 28px; height: 28px;
  border-radius: 50%;
  border: 2px solid var(--rad-border);
  background: var(--rad-white);
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700;
  color: var(--rad-text-muted);
  position: relative; z-index: 1;
  flex-shrink: 0;
}
.wizard-step.completed .wizard-circle {
  background: var(--rad-blue);
  border-color: var(--rad-blue);
  color: #fff;
}
.wizard-step.active .wizard-circle {
  border-color: var(--rad-blue);
  border-width: 3px;
  color: var(--rad-blue);
  font-weight: 800;
}

.wizard-step-label {
  font-size: 12px;
  font-weight: 500;
  color: var(--rad-text-muted);
  text-align: center;
}
.wizard-step.completed .wizard-step-label { color: var(--rad-blue); }
.wizard-step.active    .wizard-step-label { color: var(--rad-text); font-weight: 600; }

/* Wizard content card */
.wizard-content { @* same as .card *@ }

/* Wizard navigation footer */
.wizard-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 18px 0 8px;
}
.wizard-footer-left  { display: flex; gap: 10px; }
.wizard-footer-right { display: flex; gap: 10px; }
.wizard-step-counter {
  font-size: 12.5px;
  color: var(--rad-text-muted);
  align-self: center;
}

/* ═══════════════════════════════════════════════════════════
   Batch report — key/value summary + table totals row
════════════════════════════════════════════════════════════ */

/* Borderless label/value spec sheet (batch information summary) */
.kv-table td.kv-label {
  width: 1%; white-space: nowrap;
  font-size: 12px; font-weight: 600;
  color: var(--rad-text-muted);
}
.kv-table td { font-weight: 600; }
.kv-table tbody tr:hover td { background: transparent; }

/* Emphasised totals row at the foot of a report table */
tr.kv-total td {
  font-weight: 700;
  background: var(--rad-thead-bg);
  border-top: 2px solid var(--rad-blue);
  border-bottom: none;
}
tr.kv-total:hover td { background: var(--rad-thead-bg); }

/* ═══════════════════════════════════════════════════════════
   Plan table — a plan line with its own rows underneath
═══════════════════════════════════════════════════════════ */

/* Two grains in one table, which only works if the eye can tell them apart without
   reading them. The plan line carries the weight and the divider above it; what ran
   against it sits indented and lighter underneath, the way a ledger entry sits under
   its account. A nested second table would lose the shared column edges, and those
   edges are the whole reason the numbers stay comparable down the page. */
.plan-table tbody tr.plan-row td {
  font-weight: 600;
  border-top: 1px solid var(--rad-border);
  background: var(--rad-thead-bg);
}
.plan-table tbody tr.plan-row:first-child td { border-top: none; }
.plan-table tbody tr.plan-row:hover td { background: var(--rad-thead-bg); }

.plan-table tbody tr.draw-row td {
  border-top: none;
  color: var(--rad-text-muted);
}

/* The indent is on the first cell only, so the numeric columns stay aligned with the
   plan line above them — an indented number column would not read as a subtotal of
   anything. */
.plan-table tbody tr.draw-row td:first-child { padding-left: 28px; }

.plan-table .draw-when {
  font-family: var(--mono);
  font-size: 12px;
}

/* ═══════════════════════════════════════════════════════════
   Serial pool status pill — two axes in one token
════════════════════════════════════════════════════════════ */

/* Administrative (inactive) and operational (running / paused / flushing /
   faulted) states collapse into a single pill, because an operator reading a
   pool list wants one answer: is this pool serving serials right now? */
.pool-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 9px;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}
.pool-status::before {
  content: '';
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}
.pool-status.running  { background: var(--rad-success-tint); color: var(--rad-success); }
.pool-status.paused   { background: var(--rad-warning-tint); color: var(--rad-warning); }
.pool-status.flushing { background: var(--rad-blue-tint);    color: var(--rad-blue); }
.pool-status.faulted  { background: var(--rad-error-tint);   color: var(--rad-error); }
.pool-status.inactive { background: var(--rad-surface);      color: var(--rad-text-muted); }

/* Print template lifecycle, on the same pill because it answers the same shape of
   question: can this record be used right now? Draft reads as "not yet" rather than
   as a fault, so it takes the muted surface rather than a warning tint. */
.pool-status.draft        { background: var(--rad-surface);       color: var(--rad-text-muted); }
.pool-status.approved     { background: var(--rad-success-tint);  color: var(--rad-success); }
.pool-status.discontinued { background: var(--rad-error-tint);    color: var(--rad-error); }

/* Code request lifecycle, on the same pill for the third time because it answers
   the same shape of question from the line's end: has this draw got where it was
   going? The colours follow what the operator has to do about it — nothing while
   the codes are moving (blue), nothing ever again once they arrived (green), wait
   while a draw is parked (amber), act when one failed (red). Cancelled is settled
   rather than wrong, so it takes the muted surface Draft uses. */
.pool-status.pending      { background: var(--rad-surface);       color: var(--rad-text-muted); }
.pool-status.awaitingpool { background: var(--rad-warning-tint);  color: var(--rad-warning); }
.pool-status.allocated    { background: var(--rad-blue-tint);     color: var(--rad-blue); }
.pool-status.sent         { background: var(--rad-blue-tint);     color: var(--rad-blue); }
.pool-status.completed    { background: var(--rad-success-tint);  color: var(--rad-success); }
.pool-status.failed       { background: var(--rad-error-tint);    color: var(--rad-error); }
.pool-status.cancelled    { background: var(--rad-surface);       color: var(--rad-text-muted); }

/* Batch and shipment lifecycle, on their lists and page and report headers, coloured
   on the same rule: not started is muted, work under way is blue, done is green,
   settled for good is muted again. Voided is red because it undoes a shipment that
   was confirmed. Shipped and Created serve both records; Cancelled is the
   code-request rule above. */
.pool-status.created      { background: var(--rad-surface);       color: var(--rad-text-muted); }
.pool-status.inproduction { background: var(--rad-blue-tint);     color: var(--rad-blue); }
.pool-status.serialized   { background: var(--rad-blue-tint);     color: var(--rad-blue); }
.pool-status.picking      { background: var(--rad-blue-tint);     color: var(--rad-blue); }
.pool-status.packed       { background: var(--rad-blue-tint);     color: var(--rad-blue); }
.pool-status.released     { background: var(--rad-success-tint);  color: var(--rad-success); }
.pool-status.shipped      { background: var(--rad-success-tint);  color: var(--rad-success); }
.pool-status.archived     { background: var(--rad-surface);       color: var(--rad-text-muted); }
.pool-status.voided       { background: var(--rad-error-tint);    color: var(--rad-error); }

/* Flushing is the one transient state, so its dot pulses — the row is telling
   the operator to wait rather than to act. */
.pool-status.flushing::before { animation: poolFlushPulse 1.2s ease-in-out infinite; }

@keyframes poolFlushPulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: .25; }
}

@media (prefers-reduced-motion: reduce) {
  .pool-status.flushing::before { animation: none; }
}

/* ── Reported Upstream card (§30.1 on a batch or shipment) ─────
   One row per event: its status pill and when it was sent and acknowledged, with the
   file and any refusal on a detail line beneath. The header tag is the worst row,
   coloured as the row dots are. */
.pool-status.reporting-state.synced  { background: var(--rad-success-tint); color: var(--rad-success); }
.pool-status.reporting-state.pending { background: var(--rad-warning-tint); color: var(--rad-warning); }
.pool-status.reporting-state.failed  { background: var(--rad-error-tint);   color: var(--rad-error); }

.reporting-table td { vertical-align: top; }
.reporting-table .reporting-time { white-space: nowrap; }
.reporting-table .int-status-pill { white-space: nowrap; text-decoration: none; }
.reporting-table .int-status-pill:not(.has-error) {
  background: var(--rad-surface);
  border-color: var(--rad-border);
  color: var(--rad-text-2);
}
.reporting-table .int-status-pill + .field-hint,
.reporting-table .field-hint + .field-hint { margin-top: 4px; }

.reporting-table tr.has-detail td { border-bottom: none; }
.reporting-table tr.reporting-detail td { padding-top: 0; }
.reporting-detail-label {
  font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--rad-text-muted); margin-right: 8px;
}
/* Wraps rather than truncates: the tail of the name is what tells two files apart */
.reporting-file {
  font-family: var(--mono); font-size: 11.5px; color: var(--rad-text-2);
  overflow-wrap: anywhere;
}
.reporting-reason { margin-top: 4px; font-size: 12px; color: var(--rad-error); }

/* ═══════════════════════════════════════════════════════════
   55. Serial pool stock bar — one allocation's level
════════════════════════════════════════════════════════════ */

/* Two facts in one strip: how much stock there is, and how much of it can
   actually be drawn. Available and Allocated are separate segments rather than
   one total because TotalQty is stock in the pool's custody — an allocation
   sitting at its ceiling entirely in reserved stock cannot serve a single
   request, and a single bar would show that as full. */
.stock-bar {
  position: relative;
  margin: 6px 0 26px;
}

.stock-bar-track {
  display: flex;
  height: 12px;
  border-radius: 6px;
  background: var(--rad-code-bg);
  border: 1px solid var(--rad-border);
  overflow: hidden;
}

.stock-bar-seg { height: 100%; }
.stock-bar-seg.available { background: var(--rad-blue); }

/* Grey, not a second accent: allocated stock is in custody but cannot be drawn,
   and colouring it as a variant of Available invites reading the two together. */
.stock-bar-seg.allocated { background: var(--rad-text-muted); }

/* At or below the minimum the allocation is due for replenishment. Amber says
   that without claiming anything has failed — the top-up may already be queued. */
.stock-bar-seg.available.below-min { background: var(--rad-warning); }

/* Markers ride above the track so they stay visible over a filled bar. */
.stock-bar-marker {
  position: absolute;
  top: -3px;
  width: 0;
  height: 18px;
  border-left: 2px solid var(--rad-text-2);
}
.stock-bar-marker.min { border-left-style: dashed; }

/* A minimum of zero puts the marker on the left edge, where a centred label hangs
   off the card. Applied by the page when the marker is within a label's reach of
   the start. */
.stock-bar-marker.at-start .stock-bar-marker-label { transform: none; }

.stock-bar-marker-label {
  position: absolute;
  top: 20px;
  left: 0;
  transform: translateX(-50%);
  white-space: nowrap;
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--rad-text-muted);
}

/* The ceiling marker sits at the right edge, so its label would overflow the
   card; it is anchored inward instead. */
.stock-bar-marker.max .stock-bar-marker-label { transform: translateX(-100%); }

.stock-bar-legend {
  display: flex;
  gap: 16px;
  margin-top: 4px;
  font-size: 11.5px;
  color: var(--rad-text-2);
}
.stock-bar-legend-item { display: inline-flex; align-items: center; gap: 6px; }
.stock-bar-swatch {
  width: 10px; height: 10px;
  border-radius: 2px;
  flex: none;
}
.stock-bar-swatch.available { background: var(--rad-blue); }
.stock-bar-swatch.available.below-min { background: var(--rad-warning); }
.stock-bar-swatch.allocated { background: var(--rad-text-muted); }

/* The §30.2 stat value below the bar takes the bar's own amber at the threshold.
   .has-failures would make it red, and red on this page means a faulted pool (§54)
   — an allocation due for a top-up has not failed at anything. */
.int-stat-value.below-min { color: var(--rad-warning); }

/* An allocation taken out of service keeps its stock and its history, so it is
   dimmed rather than hidden. */
.level-card-inactive { opacity: .6; }

/* ── Product form (§61) ─────────────────────────────────────────────────────
   The create and edit pages share _ProductFields. Tables sit flush in their card,
   under a .card-line that says what the card is for, and show only once they
   have a row. Remove is a quiet ×: a solid red button on every row out-shouted
   Save on a filled form. */
.form-group.span-all { grid-column: 1 / -1; }

.packing-type-band {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 4px 22px;
  padding: 12px 22px;
  border-bottom: 1px solid var(--rad-border);
}
.packing-type-band .field-validation-error { flex-basis: 100%; margin-top: 0; }

/* Choices laid along one line, where .check-list stacks them. */
.check-row { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 26px; }
.check-option.is-fixed { color: var(--rad-text-2); cursor: default; }
.card-line + .card-body { padding-top: 2px; }

.product-form-table { margin-bottom: 0; }
.product-form-table[hidden] { display: none; }
.card-line + .product-form-table { border-top: 1px solid var(--rad-border); }
.product-form-table > thead > tr > th,
.product-form-table > tbody > tr > td { padding: 9px 12px; }
.product-form-table > tbody > tr > td { vertical-align: top; background: none; }
.product-form-table > thead > tr > th:first-child,
.product-form-table > tbody > tr > td:first-child { padding-left: 22px; }
.product-form-table > thead > tr > th:last-child,
.product-form-table > tbody > tr > td:last-child { padding-right: 22px; }
.product-form-table > tbody > tr:hover > td { background: none; }
.product-form-table .row-remove-col { width: 64px; }
.product-form-table > tbody > tr > td.text-end > .check-input { margin-top: 8px; }

.product-identifier-type-col { width: 320px; }
.product-identifier-key-col { width: 170px; }
.product-identifier-key { margin-top: 5px; }
.metadata-key-col { width: 190px; }
.metadata-kind-col { width: 140px; }
.metadata-slot-col { width: 130px; }
.metadata-key { display: flex; align-items: center; gap: 6px; }

/* The quiet remove: muted at rest, red only under the pointer or the keyboard. */
.row-remove {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0;
  border: 1px solid transparent; border-radius: 7px;
  background: none; color: var(--rad-text-muted);
  font-size: 13px; cursor: pointer;
  transition: color .15s, background-color .15s, border-color .15s;
}
.row-remove:hover { color: var(--rad-error); background: var(--rad-error-tint); border-color: var(--rad-error-border); }
.row-remove:focus-visible { outline: none; color: var(--rad-error); box-shadow: 0 0 0 3px rgba(220,38,38,0.10); }

/* An add link at the foot of a card, where the next row goes. */
button.add-link { background: none; border: 0; font-family: var(--font); }
button.add-link:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--rad-blue-muted); border-radius: 6px; }
.card-add-row { border-top: 1px solid var(--rad-border); }
.card-add-row .field-validation-error,
.card > .field-validation-error { padding: 0 22px 12px; margin-top: 0; }
.card > .pack-levels-empty { padding: 12px 22px 0; }

/* ── Packaging levels: one row per level, what it prints on a strip beneath ─
   The level number is the row's position, drawn rather than typed. A level and
   its strip read as one unit, so the rule runs under the strip only. */
.pack-levels-table .pack-level-no-col { width: 64px; }
.pack-levels-table .pack-level-type-col { width: 172px; }
.pack-levels-table .pack-level-qty-col { width: 112px; }
.pack-levels-table .pack-level-identifier-col { width: 272px; }
.pack-levels-table .pack-level-reported-col { width: 80px; }
.pack-levels-table > tbody > tr.pack-level-row > td { border-bottom: 0; padding-bottom: 6px; }
.pack-levels-table > tbody > tr.pack-level-row > td.text-center { padding-top: 16px; }
.pack-levels-table > tbody > tr.pack-level-templates-row > td { padding-top: 0; padding-bottom: 14px; }

.pack-level-no {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 7px;
  background: var(--rad-code-bg); color: var(--rad-dot-dark);
  font-family: var(--mono); font-size: 13px; font-weight: 500;
}
.pack-level-units:empty { display: none; }

.pack-level-identifier-none { display: flex; align-items: center; min-height: 30px; color: var(--rad-text-muted); }
.pack-level-identifier-inputs { display: flex; gap: 6px; }
.pack-level-identifier-inputs > .form-select { width: 76px; flex: none; }
.pack-level-identifier-derived-value {
  display: flex; align-items: center; min-height: 30px;
  font-family: var(--mono); font-size: 12.5px; color: var(--rad-dot-dark);
}
.pack-level-identifier [hidden] { display: none; }

.pack-level-templates {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 8px 14px;
  padding: 8px 12px;
  border: 1px solid var(--rad-border); border-radius: 8px;
  background: var(--rad-row-hover);
}
.pack-level-templates-label {
  font-size: 10px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--rad-text-2);
}
.pack-level-templates-body { display: contents; }
.pack-level-template { display: inline-flex; align-items: flex-start; gap: 6px; }
.pack-level-template-usage { width: 140px; }
.pack-level-template-pick { width: 280px; }
.pack-level-template-advisory { margin-top: 4px; }
.pack-level-templates-empty { margin: 0; }
.pack-level-templates .add-link { padding: 4px 2px; }

/* ── Print template: print order (§4.3) ─────────────────────────────────────
   Two ordered lists side by side — what goes into the barcode, and what is printed
   as text. The position is the row's place in its list, so there is nothing to
   type and no number to skip. One column below tablet-landscape width, where two
   lists of field names would each be too narrow to read. */
.print-order-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px;
}
@media (max-width: 991.98px) {
  .print-order-grid { grid-template-columns: minmax(0, 1fr); }
}

.print-order-hdr {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--rad-text-muted);
  margin-bottom: 6px;
}

.print-order-table { margin-bottom: 8px; }
.print-order-table > tbody > tr > td { vertical-align: middle; }
.print-order-table > tbody > tr:last-child > td { border-bottom: none; }

/* The position is the point of the list, so it reads first and in the accent. Scoped
   under the table: Bootstrap's `.table > :not(caption) > * > *` sets every cell's
   colour and outranks a single class. */
.print-order-table .print-order-pos {
  width: 36px;
  font-family: var(--mono);
  font-weight: 600;
  color: var(--rad-blue);
}

.print-order-caption { display: block; margin-top: 0; }

.print-order-actions { width: 1%; white-space: nowrap; text-align: right; }
.print-order-actions .btn { padding: 2px 7px; }

/* The first row cannot move up nor the last down. Bootstrap's .btn:disabled resets the
   ghost fill and border to its own transparent/black, which reads as a *different*
   button rather than an unavailable one — so the ghost look is kept and only dimmed. */
.print-order-actions .btn-ghost:disabled {
  background: var(--rad-surface);
  border-color: var(--rad-border);
  color: var(--rad-text-muted);
  opacity: .45;
}

.print-order-empty { margin: 2px 0 8px; }
.print-order-add { max-width: 320px; }

/* The fields grid's summary of the same thing, one tag per list the field is in. */
.field-placement { white-space: nowrap; }
.field-placement-text { display: inline-flex; gap: 4px; flex-wrap: nowrap; }

/* ── Shipment view: contents by batch and pack level ─────────── */
/* The batch number and its "not listed" tag stay on one line each; the
   table scrolls inside .table-responsive rather than breaking them. */
.shipment-contents td,
.shipment-contents th { white-space: nowrap; }
.shipment-contents-batch .tag { margin-top: 4px; }

/* ── Batch view: release readiness checklist (P3 §6.2) ───────── */
.release-checklist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.release-checklist li { display: flex; align-items: flex-start; gap: 10px; font-size: 13.5px; color: var(--rad-text); }
.release-checklist li i { margin-top: 2px; }
.release-checklist li.ok i { color: var(--rad-success); }
.release-checklist li.fail i { color: var(--rad-error); }

/* ── Date fields (radinik-date-input.js, date format design §3.7) ─
   bootstrap-datepicker's calendar in Radinik tokens. Its z-index is computed
   by the library from the field's ancestors, so it clears a modal without a
   number here. */
.datepicker.dropdown-menu {
  font-family: var(--font);
  font-size: 13px;
  color: var(--rad-text);
  background: var(--rad-white);
  border: 1px solid var(--rad-border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(26,31,60,0.12);
  padding: 8px;
}
.datepicker table tr td,
.datepicker table tr th {
  border-radius: 6px;
  width: 32px;
  height: 30px;
}
.datepicker .datepicker-switch,
.datepicker .prev,
.datepicker .next { color: var(--rad-text); font-weight: 600; }
.datepicker .dow { color: var(--rad-text-muted); font-weight: 500; font-size: 11.5px; }
.datepicker table tr td.day:hover,
.datepicker table tr td.focused,
.datepicker .datepicker-switch:hover,
.datepicker .prev:hover,
.datepicker .next:hover,
.datepicker table tr td span:hover { background: var(--rad-blue-tint); }
.datepicker table tr td.old,
.datepicker table tr td.new { color: var(--rad-text-muted); }
.datepicker table tr td.today,
.datepicker table tr td.today:hover {
  background: var(--rad-blue-muted);
  color: var(--rad-blue);
}
.datepicker table tr td.active,
.datepicker table tr td.active:hover,
.datepicker table tr td.active.active,
.datepicker table tr td span.active,
.datepicker table tr td span.active:hover {
  background: var(--rad-blue);
  background-image: none;
  color: var(--rad-white);
  text-shadow: none;
}

/* ═══════════════════════════════════════════════════════════
   Licensing — About page, EULA and license setup (licensing plan)
════════════════════════════════════════════════════════════ */

/* The EULA and the third-party notices: the embedded text as written, in a box that
   scrolls on its own so a long agreement never pushes the form off the screen. */
.legal-text {
  font-family: var(--font);
  font-size: 13px;
  line-height: 1.6;
  color: var(--rad-text);
  background: var(--rad-input-bg);
  border: 1px solid var(--rad-border);
  border-radius: 8px;
  padding: 16px 18px;
  max-height: 60vh;
  overflow-y: auto;
}
.legal-text:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--rad-blue-muted); }
.legal-text p { margin: 0 0 10px; }
.legal-text p:last-child { margin-bottom: 0; }
.legal-text .legal-heading { font-weight: 700; margin-top: 4px; }
.legal-text .legal-rule { border: 0; border-top: 1px solid var(--rad-border); margin: 14px 0; }

/* The setup pages (EULA, license, not activated): the sign-in shell, wider. */
.auth-card.setup-card { max-width: 860px; }
.setup-topline {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 22px;
}
.setup-logo-img { height: 34px; width: auto; }
.setup-account { display: flex; align-items: center; gap: 12px; font-size: 12.5px; color: var(--rad-text-2); }
.setup-account-name { font-family: var(--mono); }

/* Where setup stands: the agreement, then the license. */
.setup-steps {
  display: flex;
  gap: 8px;
  list-style: none;
  padding: 0;
  margin: 0 0 20px;
  counter-reset: setup-step;
}
.setup-steps li {
  counter-increment: setup-step;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--rad-text-muted);
}
.setup-steps li::before {
  content: counter(setup-step);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1.5px solid var(--rad-border);
  font-size: 11px;
}
.setup-steps li + li::after { content: none; }
.setup-steps li.active { color: var(--rad-blue); }
.setup-steps li.active::before { border-color: var(--rad-blue); background: var(--rad-blue-tint); }
.setup-steps li.done { color: var(--rad-success); }
.setup-steps li.done::before { content: '\2713'; border-color: var(--rad-success); background: var(--rad-success-tint); }

/* A read-only value with its copy button beside it. */
.setup-inline-row { display: flex; gap: 8px; align-items: flex-start; }
.setup-inline-row .form-control { flex: 1; }

/* The deployment environment, across the top of every page that is not Production
   (licensing plan §F). A Test system that looks like Production is how test data ends
   up in a record, so the strip is loud and cannot be dismissed. */
.env-strip {
  display: block;
  width: 100%;
  padding: 5px 16px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-align: center;
}
.env-strip.env-strip-test { background: var(--rad-warning); color: var(--rad-navy); }
.env-strip.env-strip-val  { background: var(--rad-env-val); color: var(--rad-white); }
.env-strip.env-strip-dev  { background: var(--rad-blue); color: var(--rad-white); }
.env-strip.env-strip-none { background: var(--rad-error); color: var(--rad-white); }

/* On the sign-in and setup shells, which centre their card: the strip is pinned to the
   top edge instead of taking part in the centring. */
.env-strip.env-strip-overlay {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: var(--z-raised);
}

/* "2 of 3 licensed" under a list's title (licensing plan §6). */
.license-usage { font-size: 12px; color: var(--rad-text-2); margin: 4px 0 0; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.license-usage .fa { color: var(--rad-text-muted); }
.license-usage-sep { color: var(--rad-text-muted); }
.license-usage-full { color: var(--rad-warning); font-weight: 600; }

/* A view grid laid out as one row — a handful of short values side by side, as on the
   About page's product card. No row borders: there is only one row. */
.view-grid.view-grid-row { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); column-gap: 24px; }
.view-grid.view-grid-row .view-field { border-bottom: none; padding: 0; }

/* Two cards side by side at the same height, however much each holds. */
.page-cols.cols-stretch { align-items: stretch; }
.page-cols.cols-stretch .card { height: 100%; }

/* More than one thing on the right of a card header: a tag and a button. */
.card-hdr-tools { display: inline-flex; align-items: center; gap: 10px; }

/* ═══════════════════════════════════════════════════════════════════════════════
   57. Lookup Field (Tom Select)
   A searchable, paged picker for records that outgrow a dropdown — products,
   batches, serial pools, print templates, customers. radinik-lookup.js builds it
   on a <select data-rad-lookup>; the select stays in the form and posts the id.
   The control reads as a .form-select; the list opens into the page body.
   ═══════════════════════════════════════════════════════════════════════════════ */
/* Sized by its container, never by the label it holds: in a table a chosen value would
   otherwise widen its column and squeeze the others. A long label ends in an ellipsis. */
.rad-lookup.ts-wrapper { width: 100%; min-width: 10rem; contain: inline-size; }
.rad-lookup.ts-wrapper .ts-control {
  display: flex; align-items: center; flex-wrap: nowrap;
  min-height: 37px;
  padding: 8px 32px 8px 12px;
  background-color: var(--rad-input-bg);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%235C6080' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 11px center;
  border: 1px solid var(--rad-border);
  border-radius: 8px;
  box-shadow: none;
  font-family: var(--font); font-size: 13px; line-height: 19px;
  color: var(--rad-text);
  cursor: pointer;
  transition: border-color .15s, box-shadow .15s;
}
.rad-lookup.ts-wrapper .ts-control:has(:focus-visible) {
  border-color: var(--rad-blue);
  box-shadow: 0 0 0 3px var(--rad-blue-muted);
}
.rad-lookup.ts-wrapper .ts-control > .item {
  display: flex; align-items: center; gap: 8px;
  min-width: 0; overflow: hidden; white-space: nowrap;
}
.rad-lookup-item-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rad-lookup.ts-wrapper .ts-control > input {
  font: inherit; color: var(--rad-text);
  min-width: 4rem; margin: 0; padding: 0;
}
/* The empty option's text, drawn as a native select draws it — body text, not a faint
   hint — so an empty lookup reads the same as the dropdowns beside it. */
.rad-lookup.ts-wrapper .ts-control > input::placeholder { color: var(--rad-text); opacity: 1; }
/* While the user types over a chosen value, the value gives way to what they type —
   only while there is text: a value just chosen shows at once, focused or not. */
.rad-lookup.ts-wrapper.rad-lookup-typing.has-items .ts-control > .item { display: none; }

.rad-lookup.ts-wrapper .clear-button {
  right: 28px;
  color: var(--rad-text-muted);
  font-size: 16px;
  background: transparent;
}
.rad-lookup.ts-wrapper .clear-button:hover { color: var(--rad-text); }
.rad-lookup.ts-wrapper .clear-button:focus-visible {
  outline: none; border-radius: 4px;
  box-shadow: 0 0 0 3px var(--rad-blue-muted);
}

.rad-lookup.ts-wrapper.disabled .ts-control {
  opacity: .55; cursor: not-allowed;
  background-color: var(--rad-input-bg);
}

/* The §12.2 bridge marks the select; radinik-lookup.js mirrors it onto the control. */
.rad-lookup.ts-wrapper.rad-lookup-invalid .ts-control { border-color: var(--rad-error); }
.rad-lookup.ts-wrapper.rad-lookup-invalid .ts-control:has(:focus-visible) {
  border-color: var(--rad-error);
  box-shadow: 0 0 0 3px rgba(220,38,38,0.10);
}

/* ── The open list ── */
.rad-lookup-dropdown.ts-dropdown {
  z-index: var(--z-lookup);
  /* At least readable width, however narrow the field — a lookup in a table cell would
     otherwise wrap every label over three lines. radinik-lookup.js keeps it on screen. */
  min-width: 360px;
  max-width: calc(100vw - 32px);
  margin-top: 4px;
  background: var(--rad-white);
  border: 1px solid var(--rad-border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(26,31,60,.12);
  font-family: var(--font); font-size: 13px;
  color: var(--rad-text);
  overflow: hidden;
}
.rad-lookup-dropdown .ts-dropdown-content { max-height: 300px; padding: 4px 0; }
.rad-lookup-dropdown .option {
  display: flex; flex-direction: column; gap: 2px;
  padding: 8px 12px;
  cursor: pointer;
}
.rad-lookup-dropdown .option.active { background: var(--rad-blue-tint); color: var(--rad-text); }
.rad-lookup-dropdown .option.selected .rad-lookup-option-label { font-weight: 600; }
.rad-lookup-option-label { display: flex; align-items: center; gap: 8px; }
.rad-lookup-option-detail {
  font-family: var(--mono); font-size: 11.5px;
  color: var(--rad-text-muted);
}
.rad-lookup-dropdown .highlight {
  background: var(--rad-blue-tint);
  color: var(--rad-blue);
  border-radius: 2px;
}
.rad-lookup-dropdown .option.active .highlight { background: transparent; }
.rad-lookup-status,
.rad-lookup-dropdown .no-results {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px;
  font-size: 12px;
  color: var(--rad-text-muted);
}
.rad-lookup-tag { flex-shrink: 0; font-size: 10.5px; padding: 1px 6px; }

/* ═══════════════════════════════════════════════════════════
   37.3 Scanner indicator (scanning design §3.4)
   Beside the location pill; shown only on pages with a scan field.
════════════════════════════════════════════════════════════ */
.scanner-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 12px;
  border-radius: 50px;
  border: 1px solid var(--rad-border);
  background: var(--rad-surface);
  color: var(--rad-text-2);
  font-family: var(--font);
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color .15s;
}
.scanner-pill[hidden] { display: none; }
.scanner-pill > .fa-barcode { color: var(--rad-blue); font-size: 12px; }
.scanner-pill:hover:not(:disabled) { border-color: var(--rad-blue); color: var(--rad-text); }
.scanner-pill:focus-visible {
  outline: none;
  border-color: var(--rad-blue);
  box-shadow: 0 0 0 3px var(--rad-blue-muted);
}
.scanner-pill:disabled { cursor: default; opacity: 1; }
.scanner-pill-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--rad-text-muted);
}
.scanner-pill[data-state="on"] { color: var(--rad-text); }
.scanner-pill[data-state="on"] .scanner-pill-dot { background: var(--rad-success); }
.scanner-pill[data-state="busy"],
.scanner-pill[data-state="unplugged"] {
  background: var(--rad-warning-tint);
  border-color: var(--rad-warning);
  color: var(--rad-warning);
}
.scanner-pill[data-state="busy"] .scanner-pill-dot,
.scanner-pill[data-state="unplugged"] .scanner-pill-dot { background: var(--rad-warning); }
.scanner-pill[data-state="unsupported"] .scanner-pill-dot { background: var(--rad-error); }

/* Scanner Check (scanning design §8) */
.scan-check-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.scan-check-list li { display: flex; align-items: center; gap: 10px; font-size: 13px; }
.scan-check-strip {
  font-family: var(--mono);
  font-size: 13px;
  background: var(--rad-code-bg);
  border-radius: 6px;
  padding: 9px 12px;
  word-break: break-all;
  line-height: 1.9;
}
.scan-check-gs {
  display: inline-block;
  font-family: var(--font);
  font-size: 10.5px;
  font-weight: 700;
  padding: 0 5px;
  margin: 0 2px;
  border-radius: 4px;
  line-height: 1.6;
  background: var(--rad-dot-dark);
  color: var(--rad-white);
}
.scan-check-hex { font-family: var(--mono); font-size: 12px; color: var(--rad-text-2); word-break: break-all; line-height: 1.8; }
.scan-check-hex .gs { background: var(--rad-dot-dark); color: var(--rad-white); border-radius: 3px; padding: 0 2px; }

/* ═══════════════════════════════════════════════════════════
   8.8 Error Pages (404, 403, 401, 400, 500 …)
════════════════════════════════════════════════════════════ */

/* One panel, two settings: centred in the application shell for a signed-in
   user, left-aligned in the sign-in card (like the other auth pages) for a
   server error or anyone signed out. */
.error-panel {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.error-panel-shell {
  align-items: center;
  text-align: center;
  justify-content: center;
  min-height: 60vh;
  max-width: 520px;
  margin: 0 auto;
  padding: 48px 22px;
}
.error-panel-card { align-items: flex-start; }

/* The empty-state tile (§4.11), one step larger, toned to the status. */
.error-icon {
  width: 52px; height: 52px; border-radius: 14px;
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 10px;
}
.error-icon-info    { background: var(--rad-blue-tint);    color: var(--rad-blue); }
.error-icon-warning { background: var(--rad-warning-tint); color: var(--rad-warning); }
.error-icon-error   { background: var(--rad-error-tint);   color: var(--rad-error); }

/* "Error 404" — the eyebrow above the title, in the identifier face. */
.error-code {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--rad-text-2);
}

/* Display step, with the signature blue bar (as .auth-title). */
.error-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 20px;
  font-weight: 700;
  color: var(--rad-text);
  letter-spacing: -.3px;
  line-height: 1.3;
}
.error-title::before {
  content: ''; display: block; flex-shrink: 0;
  width: 3px; height: 16px; border-radius: 2px;
  background: var(--rad-blue);
}
.error-panel-card .error-title { margin-left: -11px; }

.error-body {
  margin: 0;
  font-size: 13px;
  color: var(--rad-text-2);
  line-height: 1.6;
  max-width: 440px;
}

/* A refusal's own message ("this location is read-only") under the body. */
.error-detail {
  margin: 10px 0 0;
  width: 100%;
  text-align: left;
}
.error-validation { margin: 4px 0 0; padding-left: 18px; color: var(--rad-text-2); }

/* Primary action first, Back ghost second (the form-footer order). */
.error-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 18px;
}
.error-panel-shell .error-actions { justify-content: center; }
.error-actions .btn { text-decoration: none; }

/* The correlation id of a failed request — what support looks up in the log. */
.error-reference {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 18px;
  font-size: 11.5px;
  color: var(--rad-text-2);
}
.error-reference-value {
  font-family: var(--mono);
  font-size: 11px;
  background: var(--rad-surface);
  border: 1px solid var(--rad-border);
  border-radius: 4px;
  padding: 2px 7px;
  color: var(--rad-text);
  user-select: all;
  word-break: break-all;
}


/* ═══════════════════════════════════════════════════════════
   35.3 GTIN Calculator (radinik-gtin-calculator.js)
════════════════════════════════════════════════════════════ */

/* A popover beside a GTIN field that turns an EAN-13 or NDC into the GTIN-14 of
   each packaging level, so nobody leaves the form for GS1's check digit page. */

/* The input keeps its full width; the trigger sits inside its right edge. */
.gtin-calc-field { position: relative; flex: 1; min-width: 0; }
.gtin-calc-field.has-gtin-calc > input { padding-right: 34px; }

.gtin-calc-trigger {
  position: absolute; top: 50%; right: 4px; transform: translateY(-50%);
  width: 26px; height: 26px; border-radius: 6px;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; background: transparent; color: var(--rad-text-muted);
  font-size: 13px; cursor: pointer; transition: background .15s, color .15s;
}
.gtin-calc-trigger:hover,
.gtin-calc-trigger[aria-expanded="true"] { background: var(--rad-blue-tint); color: var(--rad-blue); }
.gtin-calc-trigger:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--rad-blue-muted); color: var(--rad-blue); }
.gtin-calc-trigger[hidden] { display: none; }

.gtin-calc {
  position: absolute; z-index: var(--z-field-popover);
  width: 392px;
  background: var(--rad-white);
  border: 1px solid var(--rad-border); border-radius: 12px;
  box-shadow: 0 12px 32px rgba(26,31,60,.16), 0 2px 6px rgba(26,31,60,.06);
  font-family: var(--font); color: var(--rad-text);
}
.gtin-calc[hidden] { display: none; }

.gtin-calc-hdr {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 10px 8px 16px;
  border-bottom: 1px solid var(--rad-border);
}
.gtin-calc-title {
  position: relative; padding-left: 11px;
  font-size: 13px; font-weight: 700;
}
.gtin-calc-title::before {
  content: ''; position: absolute; left: 0; top: 2px; bottom: 2px;
  width: 3px; border-radius: 2px; background: var(--rad-blue);
}
.gtin-calc-close {
  width: 26px; height: 26px; border-radius: 6px; border: none;
  background: transparent; color: var(--rad-text-muted); cursor: pointer;
}
.gtin-calc-close:hover { background: var(--rad-surface); color: var(--rad-text); }
.gtin-calc-close:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--rad-blue-muted); }

.gtin-calc-body { padding: 12px 16px 14px; }

/* Two-way segmented switch. */
.gtin-calc-modes {
  display: inline-flex; padding: 3px; margin-bottom: 8px;
  background: var(--rad-surface); border: 1px solid var(--rad-border); border-radius: 8px;
}
.gtin-calc-modes button {
  border: none; background: transparent; border-radius: 6px;
  padding: 4px 14px; font: 600 12px var(--font); color: var(--rad-text-2); cursor: pointer;
}
.gtin-calc-modes button[aria-checked="true"] {
  background: var(--rad-white); color: var(--rad-blue);
  box-shadow: 0 1px 3px rgba(26,31,60,.12);
}
.gtin-calc-modes button:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--rad-blue-muted); }

.gtin-calc-input { font-family: var(--mono); font-size: 14px; letter-spacing: .02em; }
.gtin-calc-input[aria-invalid="true"] { border-color: var(--rad-error); }
.gtin-calc-hint { margin-top: 5px; }

.gtin-calc-msg { font-size: 12px; line-height: 1.45; }
.gtin-calc-msg:empty { display: none; }
.gtin-calc-msg.is-error,
.gtin-calc-msg.is-warning,
.gtin-calc-msg.is-note { margin-top: 10px; padding: 8px 10px; border-radius: 8px; }
.gtin-calc-msg.is-error   { background: var(--rad-error-tint);   color: var(--rad-error); border: 1px solid var(--rad-error-border); }
.gtin-calc-msg.is-warning { background: var(--rad-warning-tint); color: var(--rad-text); border: 1px solid var(--rad-warning); }
.gtin-calc-msg.is-note    { background: var(--rad-blue-tint);    color: var(--rad-text-2); }

.gtin-calc-levels { width: 100%; margin-top: 10px; border-collapse: collapse; font-size: 12px; }
.gtin-calc-levels[hidden] { display: none; }
.gtin-calc-levels th {
  padding: 4px 8px; text-align: left;
  background: var(--rad-thead-bg); color: var(--rad-text-2);
  font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
}
.gtin-calc-levels th:first-child { border-radius: 6px 0 0 6px; width: 64px; }
.gtin-calc-levels th:last-child  { border-radius: 0 6px 6px 0; }
.gtin-calc-levels td { padding: 2px 8px; border-bottom: 1px solid var(--rad-border); vertical-align: middle; }
.gtin-calc-levels tr:last-child td { border-bottom: none; }
.gtin-calc-levels tbody tr:hover td { background: var(--rad-row-hover); }
.gtin-calc-levels tr.is-current td { background: var(--rad-blue-tint); }

.gtin-calc-level { font-family: var(--mono); color: var(--rad-text-2); white-space: nowrap; }
.gtin-calc-value { font-family: var(--mono); font-size: 13px; color: var(--rad-dot-dark); white-space: nowrap; }

.gtin-calc-tag {
  display: inline-block; margin-left: 2px; padding: 1px 6px; border-radius: 4px;
  font: 600 10px var(--font); color: var(--rad-text-2); background: var(--rad-surface);
  vertical-align: 1px;
}
.gtin-calc-tag.is-current { color: var(--rad-blue); background: var(--rad-white); }

.gtin-calc-actions { text-align: right; white-space: nowrap; }
.gtin-calc-actions .btn-sm { padding: 1px 10px; font-size: 11.5px; }
.gtin-calc-copy {
  width: 24px; height: 24px; margin-left: 2px; border-radius: 6px; border: none;
  background: transparent; color: var(--rad-text-muted); cursor: pointer; vertical-align: middle;
}
.gtin-calc-copy:hover { background: var(--rad-surface); color: var(--rad-blue); }
.gtin-calc-copy.is-copied { color: var(--rad-success); }
.gtin-calc-copy:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--rad-blue-muted); }

.gtin-calc-copy-buffer { position: fixed; top: 0; left: 0; opacity: 0; pointer-events: none; }

/* ═══════════════════════════════════════════════════════════
   35.4 GLN and SGLN Helpers (radinik-party-identifiers.js)
════════════════════════════════════════════════════════════ */

/* The identifier tables' value inputs, wrapped by the script. The trigger and the
   popover borrow the GTIN calculator's classes above so the two read as one family. */
.party-id-field { position: relative; }
.party-id-field.has-party-calc > input { padding-right: 34px; }

.party-calc-sgln { margin-top: 10px; }
.party-calc-sgln[hidden],
.party-calc-result[hidden] { display: none; }
.party-calc-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

.party-calc-result {
  margin-top: 12px; padding: 9px 12px;
  background: var(--rad-blue-tint); border-radius: 8px;
}
.party-calc-result-label {
  margin-bottom: 4px;
  font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
  color: var(--rad-text-2);
}
.party-calc-result-row { display: flex; align-items: center; gap: 6px; }
.party-calc-value {
  flex: 1; min-width: 0;
  font-family: var(--mono); font-size: 13px; color: var(--rad-dot-dark);
  word-break: break-all;
}
.party-calc-result-row .btn-sm { padding: 1px 10px; font-size: 11.5px; }

/* Row buttons in a grid's action column: wrap onto a second line with even gaps
   instead of relying on the whitespace between inline buttons. */
.grid-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; }

/* ═══════════════════════════════════════════════════════════
   59. Expandable Row Detail
   A grid row that opens beneath itself to show what does not fit a
   column: a paragraph a destination sent back, a file name somebody
   will quote, and the actions that answer them. First used on the
   Reporting Monitor.
════════════════════════════════════════════════════════════ */

table.dataTable td.dt-toggle-col { padding-right: 0 !important; }
table.dataTable td.dt-nowrap { white-space: nowrap; }

/* One line of a long text, the rest in the row's details. max-width: 0 lets
   the cell take what the fixed columns leave instead of setting the width. */
table.dataTable td.dt-clip {
  max-width: 0; width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

tr.dt-expandable > td { cursor: pointer; }

/* A second line under a cell's value: the record an event was about. */
.dt-cell-sub { margin-top: 2px; color: var(--rad-text-2); }

.dt-row-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; padding: 0;
  background: none; border: 1px solid transparent; border-radius: 6px;
  color: var(--rad-text-muted); cursor: pointer;
  transition: background .15s, border-color .15s, color .15s;
}
.dt-row-toggle i { font-size: 10px; }
.dt-row-toggle:hover {
  background: var(--rad-surface); border-color: var(--rad-border); color: var(--rad-text);
}
.dt-row-toggle:focus:not(:focus-visible) { outline: none; }
.dt-row-toggle:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--rad-blue-muted); }
.dt-row-toggle[aria-expanded="true"] { color: var(--rad-blue); }
.dt-row-toggle[aria-expanded="true"] i { transform: rotate(90deg); }

/* The open row and its details read as one band. */
table.dataTable tbody tr.dt-row-open > td {
  background: var(--rad-row-hover) !important;
  border-bottom-color: transparent !important;
}
table.dataTable tbody tr.dt-detail-row > td,
table.dataTable tbody tr.dt-detail-row:hover > td {
  padding: 4px 22px 18px 50px !important;
  background: var(--rad-row-hover) !important;
  cursor: default;
}

/* A file name in a cell: DM Mono, since the system wrote it (§ Mono Means Machine). */
.dt-file-link,
.dt-file-name {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--mono); font-size: 12px;
  color: var(--rad-dot-dark);
}
.dt-file-link { color: var(--rad-blue); text-decoration: none; border-radius: 3px; }
.dt-file-link i { font-size: 11px; color: var(--rad-text-muted); }
.dt-file-link:hover span {
  text-decoration: underline; text-underline-offset: 2px;
  text-decoration-color: var(--rad-blue-hover);
}
.dt-file-link:hover i { color: var(--rad-blue); }
.dt-file-link:focus:not(:focus-visible) { outline: none; }
.dt-file-link:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--rad-blue-muted); }

/* ── The details: references left, what was said right, actions beneath ── */
.row-detail {
  display: grid;
  grid-template-columns: minmax(300px, 420px) minmax(0, 1fr);
  gap: 14px 32px;
  align-items: start;
  padding-top: 10px;
  border-top: 1px solid var(--rad-border);
}

.row-detail-refs {
  display: grid;
  grid-template-columns: 112px minmax(0, 1fr);
  gap: 8px 16px;
  margin: 0;
  font-size: 12.5px;
}
.row-detail-refs dt {
  padding-top: 1px;
  font-size: 11px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase;
  color: var(--rad-text-2);
}
.row-detail-refs dd { margin: 0; min-width: 0; color: var(--rad-text); }

/* The file, on its own line across both columns: the reference a person quotes. */
.row-detail-lead { grid-column: 1 / -1; }
.row-detail-lead .row-detail-mono { font-size: 12.5px; }

.row-detail-ref { display: flex; align-items: flex-start; gap: 4px; }
.row-detail-mono {
  flex: 0 1 auto; min-width: 0; margin-right: 4px;
  font-family: var(--mono); font-size: 12px; line-height: 1.5;
  color: var(--rad-dot-dark);
  overflow-wrap: anywhere;
  user-select: all;
}

.row-detail-icon {
  flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; margin-top: -3px; padding: 0;
  background: none; border: 1px solid transparent; border-radius: 6px;
  font-size: 11.5px; color: var(--rad-text-muted);
  cursor: pointer; text-decoration: none;
  transition: background .15s, border-color .15s, color .15s;
}
.row-detail-icon:hover {
  background: var(--rad-white); border-color: var(--rad-border); color: var(--rad-blue);
}
.row-detail-icon:focus:not(:focus-visible) { outline: none; }
.row-detail-icon:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--rad-blue-muted); }

.row-detail-notes { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.row-detail-note { margin-top: 0; }
.row-detail-text {
  max-width: 78ch;
  font-size: 13px; line-height: 1.6;
  color: var(--rad-text);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* A note that is neither a failure nor a settlement: a response still awaited, or
   a decision somebody signed for. */
.exc-resolution.is-neutral {
  background: var(--rad-white);
  border-color: var(--rad-border);
}
.exc-resolution.is-neutral .exc-resolution-title { color: var(--rad-text-2); }

.row-detail-actions {
  grid-column: 1 / -1;
  display: flex; flex-wrap: wrap; gap: 8px;
  padding-top: 12px;
  border-top: 1px solid var(--rad-border);
}

@media (max-width: 1024px) {
  .row-detail { grid-template-columns: minmax(0, 1fr); }
  table.dataTable tbody tr.dt-detail-row > td { padding-left: 22px !important; }
}

/* ═══════════════════════════════════════════════════════════
   60. Record Page Summary (batch view)
   A record page says each fact once: the title row carries the number and
   status, one summary card the facts nothing else says, over the stepper and
   whatever gates the next step.
════════════════════════════════════════════════════════════ */

.page-title-row { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; }
.page-actions { display: flex; align-items: center; justify-content: flex-end; flex-wrap: wrap; gap: 8px; }
.btn-icon { padding-left: 11px; padding-right: 11px; }
.btn-caret { font-size: 9px; margin-left: 2px; }

/* Label above value, one row, hairlines between. */
.fact-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  margin: 0; padding: 18px 22px;
  border-bottom: 1px solid var(--rad-border);
  row-gap: 14px;
}
.fact-strip .fact { padding: 0 16px; border-left: 1px solid var(--rad-border); min-width: 0; }
.fact-strip .fact:first-child { padding-left: 0; border-left: 0; }
.fact-strip dt {
  margin-bottom: 5px;
  font-size: 11px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase;
  color: var(--rad-text-2);
}
.fact-strip dd { margin: 0; font-size: 13.5px; font-weight: 600; color: var(--rad-text); overflow-wrap: anywhere; }

/* The release gates under the stepper (P3 §6.2): what fails first. */
.release-strip {
  display: flex; align-items: flex-start; gap: 18px; flex-wrap: wrap;
  padding: 13px 22px;
  border-top: 1px solid var(--rad-border);
  background: var(--rad-row-hover);
}
.release-strip-label {
  display: flex; align-items: center; gap: 8px; padding-top: 1px;
  font-size: 11px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase;
  color: var(--rad-text-2);
}
.release-strip-label .tag { text-transform: none; letter-spacing: 0; }
.release-strip .release-checklist { flex: 1; min-width: 280px; flex-direction: row; flex-wrap: wrap; gap: 6px 22px; }
.release-strip .release-checklist li { font-size: 12.5px; color: var(--rad-text-2); }
.release-strip .release-checklist li.fail { color: var(--rad-text); font-weight: 600; }

/* A card's one line of context under its header: where a batch reports, and the zone. */
.card-line {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 0;
  padding: 12px 22px;
  font-size: 12px; color: var(--rad-text-2);
}
.card-line > * + *::before { content: '·'; margin: 0 10px; color: var(--rad-text-muted); }
.card-line .time-zone-note { margin: 0; }

.reporting-file-cell { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.reporting-file-cell .row-detail-icon { margin-top: 0; }
.card-hdr .time-zone-note { margin: 0; }

/* Facts about a card's content, on a band at its foot. */
.card-foot {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px 16px;
  padding: 12px 22px;
  border-top: 1px solid var(--rad-border);
  background: var(--rad-row-hover);
}
.card-foot-facts { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; font-size: 12.5px; color: var(--rad-text-2); }
.card-foot-facts strong { font-weight: 600; color: var(--rad-text); }
.fact-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 2px 8px; border-radius: 4px;
  background: var(--rad-white); border: 1px solid var(--rad-border);
  font-size: 11.5px; color: var(--rad-text-2);
}
.fact-chip b { font-family: var(--mono); font-weight: 500; color: var(--rad-text); }

/* A destructive action in a page header (cancel, delete, void): red outline at rest,
   solid on hover, so it never outshouts the one filled button (§51). */
.btn-ghost-danger {
  background: var(--rad-surface); color: var(--rad-error);
  border: 1px solid var(--rad-error-border);
}
.btn-ghost-danger:hover { background: var(--rad-error); color: #fff; border-color: var(--rad-error); }
.btn-ghost-danger:focus:not(:focus-visible) { outline: none; }
.btn-ghost-danger:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(220,38,38,0.10); }

/* A fact with a second value beneath (a document's date under its number). */
.fact-strip dd small {
  display: block; margin-top: 2px;
  font-family: var(--mono); font-size: 11.5px; font-weight: 400; color: var(--rad-text-muted);
}
.fact-strip dd.fact-none { font-weight: 400; color: var(--rad-text-muted); font-size: 12.5px; }

/* More than a line of gates: one per line, however many there are. */
.release-strip .release-checklist.release-checklist-stacked { flex-direction: column; gap: 6px; }
.release-checklist li.wait i { color: var(--rad-warning); }
.release-checklist li.info i { color: var(--rad-blue); }

/* What happened to a record that ended early (a void): on the error tint, under the
   stepper whose last step it is. */
.void-strip {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px 22px;
  padding: 13px 22px;
  border-top: 1px solid var(--rad-error-border);
  background: var(--rad-error-tint);
  font-size: 12.5px; color: var(--rad-text-2);
}
.void-strip b { font-weight: 600; color: var(--rad-text); }
.void-strip b.mono { font-weight: 500; }
.void-strip-label {
  font-size: 11px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase;
  color: var(--rad-error);
}
.void-strip-reason { flex-basis: 100%; }

/* A list inside a card, collapsed behind its count. */
.card-disclosure { border-top: 1px solid var(--rad-border); }
.card-disclosure > summary {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 22px;
  list-style: none; cursor: pointer;
  background: var(--rad-row-hover);
  font-size: 12.5px; font-weight: 600; color: var(--rad-text);
}
.card-disclosure > summary::-webkit-details-marker { display: none; }
.card-disclosure > summary i { font-size: 10px; color: var(--rad-text-muted); }
.card-disclosure[open] > summary i { transform: rotate(90deg); }
.card-disclosure > summary:focus:not(:focus-visible) { outline: none; }
.card-disclosure > summary:focus-visible { outline: none; box-shadow: inset 0 0 0 3px var(--rad-blue-muted); }

.serial-chips { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; margin: 0; padding: 12px 22px 16px; }
.serial-chip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 3px 9px; border: 1px solid var(--rad-border); border-radius: 4px;
  background: var(--rad-white); font-size: 12px;
}
.serial-chip-state { font-size: 11px; color: var(--rad-text-muted); }

/* A draw's legacy request number, before its time (line agent §3). */
.plan-table .draw-when { white-space: nowrap; }
.plan-table .draw-no { margin-right: 8px; font-weight: 500; color: var(--rad-text-2); }

/* Why a draw failed, under its pill (validation fix A-34): what a person has to correct,
   so it reads as an error rather than as the row's muted detail. */
.plan-table .draw-failure {
  margin-top: 4px;
  max-width: 420px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--rad-error);
  white-space: normal;
}

/* ── Signatures on screen: one ledger row each (§39) ──
   The same fields as the printed block, which is what prints. */
.sig-ledger { list-style: none; margin: 0; padding: 0; }
.sig-ledger-row {
  display: grid;
  grid-template-columns: 190px minmax(0, 1fr) 170px 130px;
  gap: 4px 18px; align-items: baseline;
  padding: 12px 22px;
  border-bottom: 1px solid var(--rad-border);
}
.sig-ledger-row:last-child { border-bottom: 0; }
.sig-ledger-event {
  font-size: 10px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--rad-text-2);
}
.sig-ledger-who { font-size: 12.5px; font-weight: 600; }
.sig-ledger-user { margin-left: 6px; font-family: var(--mono); font-size: 12px; font-weight: 400; color: var(--rad-text-muted); }
.sig-ledger-when { font-family: var(--mono); font-size: 12px; }
.sig-ledger-meaning { font-size: 12.5px; color: var(--rad-text-2); }
.sig-ledger-statement { grid-column: 2 / -1; font-size: 11.5px; color: var(--rad-text-2); font-style: italic; }

@media screen { .sig-print-only { display: none; } }
@media print  { .sig-ledger { display: none; } .page-actions { display: none !important; } }

@media (max-width: 1024px) {
  .sig-ledger-row { grid-template-columns: 150px minmax(0, 1fr) 150px; }
  .sig-ledger-meaning { grid-column: 3; grid-row: 2; }
  .sig-ledger-statement { grid-column: 2 / 3; grid-row: 2; }
}

/* ── The serial view (§60.1) ──
   The same record page: one summary card, each fact once. */

/* A fact's second value that is not an identifier (a level, a parent's state, a count). */
.fact-strip dd small.fact-plain { font-family: inherit; font-size: 11.5px; }
.fact-strip dd small.fact-plain .tag { margin-right: 4px; }
.fact-strip dd a.tbl-link { font-weight: 500; }
.fact-strip dd.mono { font-weight: 500; }

/* Identifiers a person copies rather than reads: two wide columns, mono. */
.fact-strip.fact-strip-codes { grid-template-columns: repeat(2, minmax(0, 1fr)); padding-top: 14px; padding-bottom: 14px; }
.fact-strip-codes dd:not(.fact-none) {
  display: flex; align-items: center; gap: 6px;
  font-family: var(--mono); font-size: 12px; font-weight: 500;
}
.fact-strip-codes dd > span { min-width: 0; overflow-wrap: anywhere; }
.fact-strip-codes .row-detail-icon { margin-top: 0; }

/* A fact strip under a card line rather than a header. */
.fact-strip.fact-strip-topped { border-top: 1px solid var(--rad-border); border-bottom: 0; }

/* A lifecycle that ended early: amber for stock that left deliberately, red for stock
   that is gone. The label stays in ink; the circle says which. */
.stepper-step.warning .stepper-circle { background: var(--rad-warning); border-color: var(--rad-warning); color: #fff; }
.stepper-step.warning .stepper-label,
#serialStepper .stepper-step.error .stepper-label { color: var(--rad-text); }

/* How the record ended, or why it can no longer be worked: a band under the stepper. */
.outcome-strip {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px 18px;
  padding: 13px 22px;
  border-top: 1px solid var(--rad-border);
  background: var(--rad-row-hover);
  font-size: 12.5px; color: var(--rad-text-2);
}
.outcome-strip-label {
  font-size: 11px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase;
  color: var(--rad-text-2);
}
.outcome-strip b { font-weight: 600; color: var(--rad-text); }
.outcome-strip .sep { color: var(--rad-text-muted); }
.outcome-strip .fa { margin-right: 4px; color: var(--rad-text-muted); }

/* A second line in a table cell: the state change under an event, System or Operator under the user. */
.cell-sub { display: block; margin-top: 2px; font-size: 11.5px; color: var(--rad-text-muted); }
.serial-history td { vertical-align: top; }
.serial-history td.mono { white-space: nowrap; }
