/* =========================================================================
   NV — shared component styles
   =========================================================================
   Loaded BEFORE css/main.css so page-specific rules can still override.
   Everything here is prefixed .nv* and is page-agnostic.

   Global traps from master.css this file must work around:
     * { border: 0 }           → every border below is explicit
     a:hover { background: var(--G01) } → .nvLink resets it
     section { line-height: 0 } → components mount inside .appContent, which resets it

   ⚠ Never add transform / filter / contain / will-change to
     main, .appShell or .appMain — the drawer and every popover are
     position:fixed and rely on escaping main{overflow:hidden}.
   ========================================================================= */

/* --------------------------------------------------------- select arrow */
/* Chrome paints the native <select> arrow hard against the right edge and
   ignores padding-right, so it sits ~4px in while the text is inset 12px.
   Every select in the app replaces it with this chevron instead.
   Declared as a token because each rule sets its own background colour with
   the shorthand, which would otherwise wipe a separately-declared image. */
:root {
    --nvSelectArrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='rgba(0,0,0,0.45)' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* ------------------------------------------------------------ page header */
.nvPageHeader {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    margin-top: 4px;
}

.nvPageTitle {
    font-size: 26px;
    font-weight: 800;
    color: var(--Main);
}

.nvPageMeta {
    font-size: 12px;
    color: rgba(0, 0, 0, .45);
}

/* Primary page action, top-right of the page header (+ Add ...) */
.nvPrimaryBtn {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: none;
    padding: 10px 18px;
    border-radius: 12px;
    background: var(--Main);
    color: #fff;
    font-size: 13px;
    font-weight: 600;
    font-family: inherit;
    line-height: normal;
    white-space: nowrap;
    cursor: pointer;
    transition: background .2s ease;
}

.nvPrimaryBtn:hover {
    background: var(--Secondary);
}

/* -------------------------------------------------------------- grid shell */
.nvGrid {
    scroll-margin-top: 16px;
}

.nvGrid-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 14px;
}

.nvGrid-scope {
    margin-top: 4px;
    font-size: 12px;
    color: rgba(0, 0, 0, .5);
}

.nvGrid-scope:empty {
    margin-top: 0;
}

.nvGrid-tools {
    position: relative;
    display: flex;
    align-items: center;
    gap: 10px;
    flex: none;
}

.nvToolBtn {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    border-radius: 10px;
    border: 1px solid rgba(84, 55, 143, .2);
    background: #fff;
    color: var(--Main);
    font-size: 12px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    white-space: nowrap;
    transition: background .15s ease;
}

.nvToolBtn:hover,
.nvToolBtn.is-open {
    background: rgba(141, 74, 242, .1);
}

/*Refresh spins while it works, so pressing it always looks like it did
  something even when the data is unchanged*/
.nvRefreshBtn.is-spinning i {
    animation: nvSpin .6s linear;
}

@keyframes nvSpin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

/* ------------------------------------------------------------ filter chips */
.nvChipBar {
    display: none;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: 14px;
    padding: 12px 14px;
    border-radius: 12px;
    background: rgba(141, 74, 242, .06);
}

.nvChipBar.is-visible {
    display: flex;
}

.nvChipBar-label {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: rgba(0, 0, 0, .45);
}

.nvChip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 5px 8px 5px 12px;
    border-radius: 999px;
    background: #fff;
    border: 1px solid rgba(84, 55, 143, .2);
    font-size: 12px;
    color: var(--Black);
}

.nvChip-key {
    color: rgba(0, 0, 0, .5);
}

.nvChip-remove {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    color: rgba(0, 0, 0, .45);
    background: rgba(0, 0, 0, .06);
    font-size: 9px;
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
}

.nvChip-remove:hover {
    background: var(--Main);
    color: #fff;
}

.nvChipClear {
    margin-left: auto;
    font-size: 12px;
    font-weight: 600;
    color: var(--Main);
    text-decoration: underline;
    cursor: pointer;
}

/* ------------------------------------------------------------------ table */
.nvTableWrap {
    overflow-x: auto;
    border-radius: 12px;
    border: 1px solid rgba(0, 0, 0, .07);
}

.nvTable {
    width: 100%;
    min-width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    font-size: 13px;
}

.nvTable th,
.nvTable td {
    text-align: left;
    padding: 12px 14px;
    white-space: nowrap;
    border-bottom: 1px solid rgba(0, 0, 0, .06);
}

.nvTable th.is-right,
.nvTable td.is-right {
    text-align: right;
}

.nvTable th.is-center,
.nvTable td.is-center {
    text-align: center;
}

/* .nvColHead is a flex container, so text-align on the th does nothing to
   it — the label would sit left while its numbers sat right, which is what
   makes a wide numeric column hard to read. Align the flex line instead. */
.nvTable th.is-right .nvColHead {
    justify-content: flex-end;
}

.nvTable th.is-center .nvColHead {
    justify-content: center;
}

.nvTable thead th {
    background: rgba(141, 74, 242, .06);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: rgba(0, 0, 0, .55);
}

.nvTable tbody tr {
    transition: background .15s ease;
}

.nvTable tbody tr[data-nv-row] {
    cursor: pointer;
}

.nvTable tbody tr:hover {
    background: rgba(141, 74, 242, .06);
}

.nvTable tbody tr:last-child td {
    border-bottom: 0;
}

/* frozen column — opt-in per column via col.sticky, not :first-child */
.nvTable th.is-sticky,
.nvTable td.is-sticky {
    position: sticky;
    left: 0;
    z-index: 2;
    background: #fff;
    box-shadow: 1px 0 0 rgba(0, 0, 0, .07);
}

.nvTable thead th.is-sticky {
    z-index: 3;
    background: #f2ecfd;
}

.nvTable tbody tr:hover td.is-sticky {
    background: #f7f2ff;
}

/* Pinned to the right edge — keeps an Action column reachable on a table
   that is wider than the viewport, instead of hiding it behind a scroll. */
.nvTable th.is-sticky-right,
.nvTable td.is-sticky-right {
    position: sticky;
    right: 0;
    z-index: 2;
    background: #fff;
    box-shadow: -1px 0 0 rgba(0, 0, 0, .07);
}

.nvTable thead th.is-sticky-right {
    z-index: 3;
    background: #f2ecfd;
}

.nvTable tbody tr:hover td.is-sticky-right {
    background: #f7f2ff;
}

.nvTable-check {
    width: 44px;
}

.nvTable-check input {
    width: 15px;
    height: 15px;
    accent-color: var(--Main);
    cursor: pointer;
}

.nvTable-empty {
    padding: 40px 16px;
    text-align: center;
    color: rgba(0, 0, 0, .45);
    font-size: 13px;
    white-space: normal;
}

/* ------------------------------------------------------------ column head */
.nvColHead {
    display: flex;
    align-items: center;
    gap: 8px;
}

.nvColHead-sort,
.nvColHead-filter {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border-radius: 5px;
    color: rgba(0, 0, 0, .3);
    font-size: 10px;
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
}

.nvColHead-sort:hover,
.nvColHead-filter:hover {
    background: rgba(141, 74, 242, .16);
    color: var(--Main);
}

.nvColHead-sort.is-active,
.nvColHead-filter.is-active,
.nvColHead-filter.is-open {
    color: var(--Main);
    background: rgba(141, 74, 242, .16);
}

/* ------------------------------------------------------------- cell atoms */
.nvMono {
    font-family: ui-monospace, Menlo, monospace;
    font-size: 12.5px;
}

.nvBadge {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 6px;
    font-size: 11.5px;
    font-weight: 700;
    color: #fff;
}

/* Badge colours mirror the donut segment colours exactly */
.nvBadge.is-critical { background: #E5348A; }
.nvBadge.is-high     { background: #B4419E; }
.nvBadge.is-medium   { background: #8D4AF2; }
.nvBadge.is-low      { background: #585CFD; }

.nvDot {
    display: inline-block;
    width: 8px;
    height: 8px;
    margin-right: 8px;
    border-radius: 50%;
    background: rgba(0, 0, 0, .25);
}

.nvDot.is-ok   { background: #22C55E; }
.nvDot.is-off  { background: #E5348A; }
.nvDot.is-idle { background: rgba(0, 0, 0, .25); }

.nvLink {
    color: var(--Main);
    text-decoration: underline;
}

/* master.css sets a:hover{background:var(--G01)} — cancel it here */
.nvLink:hover {
    background: none;
    color: var(--Secondary);
}

/* ----------------------------------------------------------------- toggle */
.nvToggle {
    position: relative;
    display: inline-block;
    width: 38px;
    height: 21px;
    padding: 0;
    border: 1px solid rgba(0, 0, 0, .12);
    border-radius: 999px;
    background: rgba(0, 0, 0, .12);
    cursor: pointer;
    vertical-align: middle;
    transition: background .2s ease, border-color .2s ease;
}

.nvToggle.is-on {
    background: var(--Main);
    border-color: var(--Main);
}

.nvToggle-knob {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 15px;
    height: 15px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
    transition: transform .2s ease;
}

.nvToggle.is-on .nvToggle-knob {
    transform: translateX(17px);
}

/* ----------------------------------------------------------- row actions */
.nvActions {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.nvActionBtn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    border: 1px solid rgba(84, 55, 143, .25);
    background: #fff;
    color: var(--Main);
    font-size: 11px;
    cursor: pointer;
    transition: background .15s ease, color .15s ease, border-color .15s ease;
}

.nvActionBtn:hover {
    background: var(--Main);
    color: #fff;
}

.nvActionBtn.is-danger {
    border-color: rgba(229, 52, 138, .35);
    color: #E5348A;
}

.nvActionBtn.is-danger:hover {
    background: #E5348A;
    border-color: #E5348A;
    color: #fff;
}

/* A count that opens the records behind it. Reads as a link (the reference
   UI styles it that way) but is a <button>, since it acts within the page
   rather than navigating. */
.nvCountBtn {
    padding: 0;
    background: none;
    color: var(--Third);
    font-size: inherit;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: color .15s ease;
}

.nvCountBtn:hover {
    color: var(--Main);
    text-decoration: underline;
}

/* --------------------------------------------- popover + column picker */
/* Above the modal (100): a popover is always opened *from* something, so it
   must sit on top of whatever opened it — a date picker inside a form was
   rendering behind the form. */
.nvPopover,
.nvColumnMenu {
    position: fixed;
    z-index: 120;
    width: 250px;
    padding: 12px;
    border-radius: 14px;
    background: #fff;
    border: 1px solid rgba(0, 0, 0, .1);
    box-shadow: 0 16px 36px rgba(0, 0, 0, .16);
}

.nvPopover-search {
    position: relative;
    margin-bottom: 10px;
}

.nvPopover-search input,
.nvPopover-text input {
    width: 100%;
    padding: 8px 10px;
    border-radius: 8px;
    border: 1px solid rgba(0, 0, 0, .12);
    background: rgba(0, 0, 0, .03);
    font-size: 12.5px;
    font-family: inherit;
    color: var(--Black);
}

.nvPopover-search input:focus,
.nvPopover-text input:focus {
    outline: none;
    border-color: var(--Main);
}

.nvPopover-text {
    margin-bottom: 10px;
    padding-bottom: 10px;
    border-bottom: 1px solid rgba(0, 0, 0, .08);
}

.nvPopover-hint {
    margin-bottom: 6px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: rgba(0, 0, 0, .4);
}

.nvPopover-list {
    max-height: 208px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.nvOption {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 7px 8px;
    border-radius: 8px;
    font-size: 12.5px;
    color: var(--Black);
    cursor: pointer;
    transition: background .15s ease;
}

.nvOption:hover {
    background: rgba(141, 74, 242, .1);
}

.nvOption input {
    width: 15px;
    height: 15px;
    flex: none;
    accent-color: var(--Main);
    cursor: pointer;
}

.nvOption-count {
    margin-left: auto;
    font-size: 11px;
    color: rgba(0, 0, 0, .4);
}

.nvOption.is-all {
    font-weight: 600;
    border-bottom: 1px solid rgba(0, 0, 0, .08);
    border-radius: 8px 8px 0 0;
    margin-bottom: 2px;
}

.nvPopover-foot {
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid rgba(0, 0, 0, .08);
    text-align: right;
}

.nvPopover-clear {
    font-size: 12px;
    font-weight: 600;
    color: var(--Main);
    cursor: pointer;
}

.nvPopover-clear:hover {
    text-decoration: underline;
}

/* ------------------------------------------------------------- pagination */
.nvPagination {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 14px;
    margin-top: 16px;
}

.nvPagination-info {
    font-size: 12px;
    color: rgba(0, 0, 0, .5);
}

.nvPagination-pages {
    display: flex;
    align-items: center;
    gap: 6px;
}

.nvPageBtn {
    min-width: 32px;
    height: 32px;
    padding: 0 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    border: 1px solid rgba(84, 55, 143, .18);
    background: #fff;
    color: var(--Main);
    font-size: 12.5px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: background .15s ease;
}

.nvPageBtn:hover:not(:disabled) {
    background: rgba(141, 74, 242, .12);
}

.nvPageBtn.is-active {
    background: var(--Main);
    border-color: var(--Main);
    color: #fff;
}

.nvPageBtn:disabled {
    opacity: .35;
    cursor: not-allowed;
}

.nvPageEllipsis {
    padding: 0 2px;
    color: rgba(0, 0, 0, .35);
    font-size: 12px;
}

.nvPagination-size {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    color: rgba(0, 0, 0, .5);
}

.nvPagination-size select {
    padding: 6px 10px;
    border-radius: 8px;
    border: 1px solid rgba(84, 55, 143, .18);
    background: #fff;
    color: var(--Main);
    font-size: 12.5px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
}

/* ----------------------------------------------------------- detail drawer */
.nvDrawer-backdrop {
    position: fixed;
    inset: 0;
    z-index: 88;
    background: rgba(20, 10, 40, .4);
    opacity: 0;
    visibility: hidden;
    transition: opacity .2s ease, visibility .2s ease;
}

.nvDrawer-backdrop.is-open {
    opacity: 1;
    visibility: visible;
}

.nvDrawer {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 90;
    width: 380px;
    max-width: 88vw;
    display: flex;
    flex-direction: column;
    background: #fff;
    box-shadow: -14px 0 44px rgba(0, 0, 0, .2);
    transform: translateX(100%);
    transition: transform .25s ease;
}

.nvDrawer.is-open {
    transform: translateX(0);
}

.nvDrawer-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    padding: 22px 24px;
    border-bottom: 1px solid rgba(0, 0, 0, .08);
}

.nvDrawer-title {
    font-size: 17px;
    font-weight: 700;
    color: var(--Black);
}

.nvDrawer-id {
    margin-top: 4px;
    font-family: ui-monospace, Menlo, monospace;
    font-size: 12px;
    color: rgba(0, 0, 0, .45);
}

.nvDrawer-close {
    width: 32px;
    height: 32px;
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    color: rgba(0, 0, 0, .5);
    background: rgba(0, 0, 0, .05);
    cursor: pointer;
    transition: background .2s ease;
}

.nvDrawer-close:hover {
    background: rgba(0, 0, 0, .1);
}

.nvDrawer-body {
    flex: 1;
    overflow-y: auto;
    padding: 12px 24px 24px;
}

.nvDrawerRow {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding: 13px 0;
    border-bottom: 1px solid rgba(0, 0, 0, .06);
}

.nvDrawerRow-key {
    flex: none;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: rgba(0, 0, 0, .45);
}

.nvDrawerRow-value {
    text-align: right;
    font-size: 13px;
    color: var(--Black);
    word-break: break-all;
}

.nvDrawer-foot {
    flex: none;
    display: flex;
    gap: 10px;
    padding: 16px 24px 22px;
    border-top: 1px solid rgba(0, 0, 0, .08);
}

.nvDrawerBtn {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 11px 12px;
    border-radius: 10px;
    background: var(--Main);
    color: #fff;
    font-size: 13px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: background .2s ease;
}

.nvDrawerBtn:hover {
    background: var(--Secondary);
}

/* ------------------------------------------------------------------- tabs */
.nvTabs {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-bottom: 20px;
    box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .1);
}

.nvTab {
    position: relative;
    padding: 12px 18px;
    background: none;
    border: 0;
    color: rgba(0, 0, 0, .5);
    font-size: 14px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: color .15s ease;
}

.nvTab:hover {
    color: var(--Main);
}

.nvTab.is-active {
    color: var(--Main);
    box-shadow: inset 0 -2px 0 var(--Main);
}

/* ------------------------------------------------------- segmented control */
.nvSegmented {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.nvSegment {
    padding: 6px 16px;
    border-radius: 999px;
    border: 1px solid rgba(84, 55, 143, .25);
    background: #fff;
    color: var(--Main);
    font-size: 12px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
}

.nvSegment:hover {
    background: rgba(141, 74, 242, .1);
}

.nvSegment.is-active {
    border-color: var(--Main);
    background: var(--Main);
    color: #fff;
}

/* -------------------------------------------------------------- query bar */
.nvQueryBar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 14px;
    margin-bottom: 20px;
}

/* Fields flex instead of holding a hard 190px floor. With a fixed minimum
   the bar demanded the same total width whatever space it had, so it went
   from one row to two the instant it was 1px short — and a query bar inside
   a card wrapped ~40px earlier than a bare one purely from card padding. */
.nvQueryField {
    flex: 1 1 150px;
    min-width: 0;
    max-width: 240px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

/* full-width break so the active-filter chips sit under the fixed fields */
.nvQueryChips {
    display: none;
    flex: 0 0 100%;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    padding: 12px 14px;
    border-radius: 12px;
    background: rgba(141, 74, 242, .06);
}

.nvQueryChips.is-visible {
    display: flex;
}

.nvQueryField > label {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: rgba(0, 0, 0, .45);
}

.nvQueryField select,
.nvQueryField input {
    width: 100%;
    min-width: 0;
    padding: 9px 12px;
    border-radius: 10px;
    border: 1px solid rgba(0, 0, 0, .12);
    background: #fff;
    font-size: 13px;
    font-family: inherit;
    color: var(--Black);
}

.nvQueryField select:focus,
.nvQueryField input:focus {
    outline: none;
    border-color: var(--Main);
    box-shadow: 0 0 0 3px rgba(84, 55, 143, .12);
}

/* Buttons keep their size — only the fields absorb the slack */
.nvQueryBtn {
    flex: none;
    padding: 10px 28px;
    border-radius: 10px;
    background: var(--Main);
    color: #fff;
    font-size: 13px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: background .2s ease;
}

.nvQueryBtn:hover {
    background: var(--Secondary);
}

.nvQueryAdd {
    flex: none;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 10px 4px;
    white-space: nowrap;
    background: none;
    color: var(--Main);
    font-size: 13px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
}

.nvQueryAdd:hover {
    text-decoration: underline;
}

/* ----------------------------------------------------------- multiSelect */
.nvMultiSelect-field {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 9px 12px;
    border-radius: 10px;
    border: 1px solid rgba(0, 0, 0, .14);
    background: #fff;
    color: var(--Black);
    font-size: 13px;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color .15s ease;
}

.nvMultiSelect-field:hover,
.nvMultiSelect-field.is-open {
    border-color: var(--Secondary);
}

.nvMultiSelect-field.is-empty .nvMultiSelect-label {
    color: rgba(0, 0, 0, .4);
}

.nvMultiSelect-label {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.nvMultiSelect-clear,
.nvMultiSelect-chevron {
    flex: none;
    font-size: 11px;
    color: rgba(0, 0, 0, .4);
}

.nvMultiSelect-clear:hover {
    color: #E5348A;
}

/* ---- Add Filter popover form ---- */
/* .nvPopover already supplies the shell (fixed, white, shadow, 250px);
   this widens it and lays the three rows out vertically. */
.nvQueryForm {
    width: 260px;
    display: flex;
    flex-direction: column;
    gap: 14px;
    /* belt-and-braces with popover repositioning: never taller than the
       viewport, whatever the operator adds */
    max-height: calc(100vh - 24px);
    overflow-y: auto;
}

.nvQueryForm-row {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.nvQueryForm-row > label {
    font-size: 12px;
    font-weight: 600;
    color: rgba(0, 0, 0, .6);
}

.nvQueryForm-row select,
.nvQueryForm-row input {
    width: 100%;
    padding: 8px 10px;
    border-radius: 8px;
    border: 1px solid rgba(0, 0, 0, .14);
    background: #fff;
    font-size: 13px;
    font-family: inherit;
    color: var(--Black);
}

.nvQueryForm-row select:focus,
.nvQueryForm-row input:focus {
    outline: none;
    border-color: var(--Secondary);
}

.nvQueryForm-range {
    display: none;
    align-items: center;
    gap: 8px;
}

.nvQueryForm-dash {
    flex: none;
    color: rgba(0, 0, 0, .4);
}

/* Errors are pre-rendered and revealed on submit, so the popover never
   changes height as you type. */
.nvQueryForm-err {
    display: none;
    font-size: 11.5px;
    font-weight: 600;
    color: #E5348A;
}

.nvQueryForm-err.is-visible {
    display: block;
}

.nvQueryForm-add {
    padding: 9px 14px;
    border-radius: 10px;
    background: var(--Main);
    color: #fff;
    font-size: 13px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: background .2s ease;
}

.nvQueryForm-add:hover {
    background: var(--Secondary);
}

/* ------------------------------------------------------------------ modal */
.nvModalOverlay {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: rgba(20, 10, 40, .55);
    backdrop-filter: blur(4px);
    opacity: 0;
    visibility: hidden;
    transition: opacity .2s ease, visibility .2s ease;
}

.nvModalOverlay.is-open {
    opacity: 1;
    visibility: visible;
}

.nvModal {
    width: 100%;
    max-width: 420px;
    max-height: calc(100vh - 48px);
    display: flex;
    flex-direction: column;
    background: #fff;
    border-radius: 24px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, .3);
    transform: translateY(-10px);
    transition: transform .2s ease;
}

.nvModalOverlay.is-open .nvModal {
    transform: translateY(0);
}

/* width comes from the modal config as an inline max-width */

.nvModal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 28px 30px 0;
}

.nvModal-title {
    font-size: 20px;
    font-weight: 700;
    color: var(--Black);
}

.nvModal-close {
    width: 32px;
    height: 32px;
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    color: rgba(0, 0, 0, .5);
    background: rgba(0, 0, 0, .05);
    cursor: pointer;
    transition: background .2s ease;
}

.nvModal-close:hover {
    background: rgba(0, 0, 0, .1);
}

/* Explanatory copy between the title and the form */
.nvModal-desc {
    padding: 18px 30px 0;
    font-size: 13px;
    line-height: 1.65;
    color: rgba(0, 0, 0, .55);
}

.nvModal-body {
    flex: 1;
    overflow-y: auto;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 18px;
    padding: 24px 30px;
}

.nvField {
    display: flex;
    flex-direction: column;
    gap: 8px;
    grid-column: span 2;
}

/* One rule for every switch in the app: label first, switch immediately
   after it. Pushing it to the far right of the row made the same control
   land in a different place on each form. */
.nvField.is-inline {
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    gap: 14px;
}

.nvField.is-inline > label {
    flex: none;
}

/* ---- file field: the button is the affordance, the name is the result ---- */
.nvDateTime {
    position: relative;
    display: block;
}

.nvDateTime-input {
    width: 100%;
    padding: 9px 34px 9px 12px;
    border-radius: 10px;
    border: 1px solid rgba(0, 0, 0, .14);
    background: #fff;
    font-size: 13px;
    font-family: inherit;
    color: var(--Black);
    cursor: pointer;
}

.nvDateTime-input:focus {
    outline: none;
    border-color: var(--Secondary);
}

.nvDateTime-icon {
    position: absolute;
    top: 50%;
    right: 12px;
    transform: translateY(-50%);
    font-size: 12px;
    color: rgba(0, 0, 0, .4);
    pointer-events: none;
}

.nvDateTime.is-disabled .nvDateTime-input {
    background: rgba(0, 0, 0, .04);
    color: rgba(0, 0, 0, .35);
    cursor: not-allowed;
}

.nvDateTimePop {
    width: auto;
    min-width: 260px;
}

.nvCal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
}

.nvCal-title {
    font-size: 13px;
    font-weight: 700;
    color: var(--Black);
}

.nvCal-nav {
    width: 26px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    background: none;
    color: var(--Main);
    font-size: 11px;
    cursor: pointer;
}

.nvCal-nav:hover {
    background: rgba(141, 74, 242, .1);
}

.nvCal-grid {
    display: grid;
    grid-template-columns: repeat(7, 32px);
    gap: 2px;
}

.nvCal-dow span {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 26px;
    font-size: 10.5px;
    font-weight: 700;
    color: rgba(0, 0, 0, .4);
}

.nvCal-day {
    height: 30px;
    border-radius: 8px;
    background: none;
    font-size: 12.5px;
    font-family: inherit;
    color: var(--Black);
    cursor: pointer;
    transition: background .12s ease;
}

.nvCal-day:hover:not(.is-out) {
    background: rgba(141, 74, 242, .12);
}

.nvCal-day.is-out {
    color: rgba(0, 0, 0, .2);
    cursor: default;
}

.nvCal-day.is-selected {
    background: var(--Main);
    color: #fff;
    font-weight: 700;
}

.nvTimeSpin {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid rgba(0, 0, 0, .07);
}

.nvTimeSpin-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
}

.nvTimeSpin-btn {
    width: 30px;
    height: 22px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
    background: none;
    color: rgba(0, 0, 0, .45);
    font-size: 10px;
    cursor: pointer;
}

.nvTimeSpin-btn:hover {
    background: rgba(141, 74, 242, .12);
    color: var(--Main);
}

.nvTimeSpin-value {
    font-family: ui-monospace, Menlo, monospace;
    font-size: 15px;
    font-weight: 700;
    color: var(--Black);
}

.nvTimeSpin-sep {
    font-size: 15px;
    font-weight: 700;
    color: rgba(0, 0, 0, .4);
}

.nvDateTimePop-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px solid rgba(0, 0, 0, .07);
}

.nvDateTimePop-now {
    background: none;
    color: var(--Secondary);
    font-size: 12px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
}

.nvDateTimePop-now:hover {
    text-decoration: underline;
}

.nvDateTimePop-done {
    padding: 6px 16px;
    border-radius: 8px;
    background: var(--Main);
    color: #fff;
    font-size: 12px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
}

.nvDateTimePop-done:hover {
    background: var(--Secondary);
}

.nvMenu {
    width: auto;
    min-width: 200px;
    padding: 6px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.nvMenu-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    border-radius: 8px;
    background: none;
    color: var(--Black);
    font-size: 13px;
    font-family: inherit;
    text-align: left;
    white-space: nowrap;
    cursor: pointer;
    transition: background .15s ease;
}

.nvMenu-item:hover {
    background: rgba(141, 74, 242, .1);
    color: var(--Main);
}

.nvFileField.is-dragover {
    outline: 2px dashed var(--Secondary);
    outline-offset: 3px;
    border-radius: 8px;
}

.nvFileField {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
}

.nvFileField-input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.nvFileBtn {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: none;
    padding: 9px 16px;
    border-radius: 10px;
    border: 1px solid rgba(84, 55, 143, .25);
    background: #fff;
    color: var(--Main);
    font-size: 13px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: background .15s ease;
}

.nvFileBtn:hover {
    background: rgba(141, 74, 242, .1);
}

.nvFileField-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 13px;
    color: rgba(0, 0, 0, .4);
}

.nvFileField-clear {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: rgba(0, 0, 0, .06);
    color: rgba(0, 0, 0, .45);
    font-size: 10px;
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
}

.nvFileField-clear:hover {
    background: #E5348A;
    color: #fff;
}

.nvFileField-name.is-set {
    font-family: ui-monospace, Menlo, monospace;
    font-size: 12.5px;
    color: var(--Black);
}

.nvField.is-half {
    grid-column: span 1;
}

.nvField > label {
    font-size: .85rem;
    font-weight: 600;
    color: var(--Black);
}

.nvField input[type="text"],
.nvField input[type="password"],
.nvField input[type="email"],
.nvField input[type="number"],
.nvField select,
.nvField textarea {
    width: 100%;
    padding: 10px 14px;
    border-radius: 10px;
    border: 1px solid rgba(0, 0, 0, .12);
    background: rgba(0, 0, 0, .03);
    color: var(--Black);
    font-size: .9rem;
    font-family: inherit;
}

.nvField textarea {
    min-height: 84px;
    resize: vertical;
}

.nvField input:focus,
.nvField select:focus,
.nvField textarea:focus {
    outline: none;
    border-color: var(--Main);
    box-shadow: 0 0 0 3px rgba(84, 55, 143, .15);
}

/*Per-field validation message, appended on submit*/
.nvField-error {
    font-size: 11.5px;
    font-weight: 600;
    line-height: normal;
    color: #E5348A;
}

.nvConfirm {
    max-width: 400px;
}

.nvConfirm-body {
    padding: 22px 30px 4px;
    font-size: .95rem;
    line-height: 1.6;
    color: var(--Black);
}

.nvModalSubmit.is-danger {
    background: #E5348A;
}

.nvModalSubmit.is-danger:hover {
    background: #C41F72;
}

.nvField-hint {
    font-size: 11px;
    color: rgba(0, 0, 0, .45);
}

/* Grid, not flex: with flex:1 a three-control row gave thirds and a
   two-control row gave halves, so the same control (an operator select)
   ended up a different width on each row. A field can pass `widths` to pin
   the shared columns and let only the value expand. */
.nvField-row {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    align-items: center;
    gap: 10px;
}

.nvField-row > * {
    min-width: 0;
}

.nvField-row .nvField-static {
    white-space: nowrap;
}

.nvField-static {
    font-size: 13px;
    color: rgba(0, 0, 0, .6);
}

.nvRadioGroup {
    display: flex;
    flex-wrap: wrap;
    gap: 18px;
}

.nvRadio {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    color: var(--Black);
    cursor: pointer;
}

.nvRadio input {
    width: 16px;
    height: 16px;
    accent-color: var(--Secondary);
    cursor: pointer;
}

/*Settings rows: one label, its control immediately after — same rule as
  every switch in the app*/
.nvSettingRow {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 0;
    border-bottom: 1px solid rgba(0, 0, 0, .06);
    flex-wrap: wrap;
    line-height: normal;
}

.nvSettingRow:last-child {
    border-bottom: 0;
}

.nvSettingRow > label,
.nvSettingRow > .nvSettingRow-label {
    font-size: 13px;
    color: var(--Black);
}

.nvSettingRow-master {
    padding-bottom: 18px;
    border-bottom: 1px solid rgba(0, 0, 0, .1);
}

.nvSettingRow-master .nvSettingRow-label {
    font-weight: 700;
}

.nvSettingRow-sub {
    padding-left: 34px;
}

.nvSettingNum {
    width: 110px;
    padding: 8px 12px;
    border-radius: 10px;
    border: 1px solid rgba(0, 0, 0, .14);
    background: #fff;
    font-size: 13px;
    font-family: inherit;
    color: var(--Black);
}

.nvSettingNum:focus {
    outline: none;
    border-color: var(--Secondary);
}

.nvSettingUnit {
    font-size: 12.5px;
    color: rgba(0, 0, 0, .5);
}

.nvCheckGroup {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
}

.nvCheckGroup label {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    cursor: pointer;
}

.nvCheckGroup input {
    width: 15px;
    height: 15px;
    accent-color: var(--Main);
    cursor: pointer;
}

.nvModal-foot {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 16px;
    padding: 0 30px 28px;
}

.nvModalCancel {
    background: none;
    font-size: .9rem;
    font-weight: 600;
    font-family: inherit;
    color: rgba(0, 0, 0, .5);
    cursor: pointer;
    transition: color .2s ease;
}

.nvModalCancel:hover {
    color: var(--Black);
}

.nvModalSubmit {
    padding: 10px 22px;
    border-radius: 10px;
    background: var(--Main);
    color: #fff;
    font-size: .9rem;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: background .2s ease;
}

.nvModalSubmit:hover {
    background: var(--Secondary);
}

/* ----------------------------------------------------------------- banner */
.nvBanner {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 20px;
    font-size: 13px;
    font-weight: 600;
    line-height: normal;
}

.nvBanner.is-danger {
    background: rgba(229, 52, 138, .12);
    color: #B5236C;
}

.nvBanner.is-warn {
    background: rgba(245, 165, 36, .16);
    color: #9A6100;
}

.nvBanner.is-info {
    background: rgba(88, 92, 253, .12);
    color: #4145CE;
}

.nvBanner-close {
    margin-left: auto;
    width: 24px;
    height: 24px;
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(0, 0, 0, .06);
    color: inherit;
    cursor: pointer;
    transition: background .15s ease;
}

.nvBanner-close:hover {
    background: rgba(0, 0, 0, .14);
}

/* -------------------------------------------------------- horizontal bars */
/* Shared "top N" list used by Alert Center charts and Log Explorer
   Quick Stats. Rows are only interactive when .is-clickable is set. */
.nvBarList {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.nvBarList-empty {
    padding: 24px 0;
    text-align: center;
    font-size: 12px;
    color: rgba(0, 0, 0, .35);
}

.nvBarRow {
    display: grid;
    grid-template-columns: 108px 1fr 52px;
    align-items: center;
    gap: 10px;
    padding: 4px 6px;
    border-radius: 8px;
    font-size: 12px;
    transition: background .15s ease;
}

.nvBarList.is-clickable .nvBarRow {
    cursor: pointer;
}

.nvBarList.is-clickable .nvBarRow:hover {
    background: rgba(141, 74, 242, .1);
}

.nvBarRow.is-active {
    background: rgba(141, 74, 242, .16);
}

.nvBarRow-label {
    font-family: ui-monospace, Menlo, monospace;
    font-size: 11.5px;
    color: rgba(0, 0, 0, .7);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.nvBarRow-track {
    display: block;
    height: 14px;
    border-radius: 6px;
    background: var(--Bg);
    overflow: hidden;
}

.nvBarRow-fill {
    display: block;
    height: 100%;
    border-radius: 6px;
    background: linear-gradient(90deg, var(--Secondary), var(--Third));
}

.nvBarRow-value {
    text-align: right;
    font-weight: 700;
    font-size: 11.5px;
    color: var(--Main);
}

/* ------------------------------------------------------------- stat cards */
.nvStatRow {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 16px;
    margin-bottom: 20px;
}

.nvStatCard {
    padding: 18px 20px;
    border-radius: 16px;
    background: #fff;
    border: 1px solid rgba(84, 55, 143, .1);
    line-height: normal;
}

.nvStatCard-label {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: rgba(0, 0, 0, .45);
}

.nvStatCard-value {
    margin-top: 8px;
    font-size: 26px;
    font-weight: 800;
    color: var(--Main);
}

.nvStatCard-sub {
    margin-top: 4px;
    font-size: 11.5px;
    color: rgba(0, 0, 0, .45);
}

.nvStack {
    display: flex;
    flex-direction: column;
    gap: 2px;
    line-height: normal;
}

.nvStack b {
    font-weight: 600;
}

.nvStack i {
    font-style: normal;
    font-size: 11.5px;
    color: rgba(0, 0, 0, .45);
}

/* ------------------------------------------- multi-value + expandable row */
.nvTags {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 5px;
}

.nvBadge.is-plain {
    background: rgba(84, 55, 143, .12);
    color: var(--Main);
}

.nvMuted {
    color: rgba(0, 0, 0, .3);
}

.nvExpandBtn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 4px 10px;
    border-radius: 999px;
    border: 1px solid rgba(84, 55, 143, .2);
    background: #fff;
    color: var(--Main);
    font-size: 12px;
    font-weight: 600;
    font-family: inherit;
    white-space: nowrap;
    cursor: pointer;
    transition: background .15s ease;
}

.nvExpandBtn:hover {
    background: rgba(141, 74, 242, .1);
}

.nvExpandBtn i {
    font-size: 9px;
    transition: transform .2s ease;
}

/* the open row's own button points up */
.nvTable tr:has(+ .nvRowDetail) .nvExpandBtn i {
    transform: rotate(180deg);
}

.nvRowDetail > td {
    padding: 0 !important;
    background: rgba(141, 74, 242, .05);
}

.nvRowDetail-inner {
    padding: 14px 18px;
    line-height: normal;
}

.nvRowDetail-title {
    margin-bottom: 10px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: rgba(0, 0, 0, .45);
}

.nvRowDetail-list {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.nvRowDetail-list span {
    padding: 5px 12px;
    border-radius: 999px;
    background: #fff;
    border: 1px solid rgba(84, 55, 143, .14);
    font-family: ui-monospace, Menlo, monospace;
    font-size: 11.5px;
    color: rgba(0, 0, 0, .7);
}

/* ------------------------------------------------------------ line chart */
.nvChart-svg {
    display: block;
    width: 100%;
    height: auto;
}

.nvChart-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    justify-content: center;
    margin-bottom: 6px;
}

.nvChart-legend span {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 11.5px;
    line-height: normal;
    color: rgba(0, 0, 0, .6);
}

.nvChart-legend i {
    width: 14px;
    height: 3px;
    border-radius: 2px;
}

.nvChart-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 160px;
    font-size: 12.5px;
    line-height: normal;
    color: rgba(0, 0, 0, .35);
}

/* -------------------------------------------------------- select chevron */
/* Placed after every rule above that sets `background: <colour>` — the
   shorthand resets background-image, so the chevron has to come last. */
.nvQueryField select,
.nvQueryForm-row select,
.nvField select,
.nvPagination-size select {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    padding-right: 34px;
    background-image: var(--nvSelectArrow);
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 11px;
}

/* The rows-per-page select is narrow, so it takes a tighter inset */
.nvPagination-size select {
    padding-right: 28px;
    background-position: right 9px center;
    background-size: 10px;
}

/* ================================================================== RWD == */
@media screen and (max-width:1280px) {
    .nvDrawer {
        width: 340px;
    }
}

@media screen and (max-width:1024px) {
    .nvGrid-head {
        flex-direction: column;
        align-items: stretch;
    }

    .nvQueryBar {
        flex-direction: column;
        align-items: stretch;
    }

    .nvQueryField select,
    .nvQueryField input {
        min-width: 0;
        width: 100%;
    }

    .nvModal-body {
        grid-template-columns: 1fr;
    }

    .nvField.is-half {
        grid-column: span 2;
    }
}

@media screen and (max-width:480px) {
    .nvDrawer {
        width: 100%;
        max-width: 100%;
    }

    .nvPagination {
        justify-content: center;
    }

    .nvPagination-info {
        display: none;
    }

    .nvPopover,
    .nvColumnMenu {
        width: min(250px, calc(100vw - 24px));
    }

    .nvTabs {
        overflow-x: auto;
    }
}
