/*
 * Grouped list cells (.nvg-*)
 *
 * Shared primitives for list/table screens on the Metronic layout.
 * A grouped cell collapses several related fields into one column: the
 * dominant field reads first at full size, the supporting fields stack
 * beneath it at a smaller — but still readable — size.
 *
 * The point of grouping is that the table fits the page. A .nvg-table is
 * laid out fixed at 100% width, so column widths are shares of the page
 * and never a floor pushing the table wider than its container: content
 * wraps or clamps inside its cell instead of scrolling the row sideways.
 *
 * Markup:
 *   <td>
 *     <div class="nvg">
 *       <a href="..." class="nvg-lead">TO-26-0418</a>
 *       <span class="nvg-sub"><span class="nvg-k">Fresa</span>FRS/NBO/26/1188</span>
 *       <span class="nvg-sub"><span class="nvg-k">Rate</span><span class="nvg-num">KES 210,000.00</span></span>
 *     </div>
 *   </td>
 */

/* ---------- table: fits the container, always ---------- */
.nvg-table {
    width: 100%;
    table-layout: fixed;
}

/* Cells carry stacked fields rather than a single value, so they sit wider apart
   than plain table cells. The narrower overrides below still win where they
   apply. */
.nvg-table th,
.nvg-table td {
    vertical-align: top;
    overflow-wrap: break-word;
    padding-left: 1.1rem;
    padding-right: 1.1rem;
}

/* headers name a column — they wrap between words, never inside one */
.nvg-table th {
    overflow-wrap: normal;
    word-break: keep-all;
    hyphens: none;
}

.nvg-table td.nvg-cell {
    padding-top: 1.4rem;
    padding-bottom: 1.4rem;
}

/* A right-aligned figure sits hard against the next column otherwise. */
.nvg-table th.nvg-col-money,
.nvg-table td.nvg-cell.text-end {
    padding-right: 1.35rem;
}

.nvg-table th.nvg-col-status,
.nvg-table td.nvg-cell.nvg-status-cell {
    padding-left: 1.25rem;
}

/* A short header ("Type") in a narrow column would otherwise spend most of its
   share on gutters and spill into the header beside it. */
.nvg-table th.nvg-col-narrow {
    padding-left: 0.6rem;
    padding-right: 0.6rem;
}

/* the pill keeps its own shape rather than filling the cell edge to edge. Its
   label wraps rather than nowrapping — a long one ("Approved by Finance") would
   otherwise run out over the column beside it. */
.nvg-table .status-chip {
    display: inline-flex;
    line-height: 1.25;
}

/* An abbreviated value carries the full term for hover and assistive tech; the
   browser's dotted underline reads as an error next to the other cells. */
.nvg-table abbr {
    text-decoration: none;
    cursor: help;
}

/* A reference code cell overrides the table's break-anywhere wrapping: the code
   stays whole on one line, which is the only way it is readable. */
.nvg-table td.nvg-code-cell {
    white-space: nowrap;
    overflow-wrap: normal;
}

/* Column widths are percentage shares. Keep a table's shares near 100: a
   fixed layout scales them all down proportionally when they overshoot, so an
   over-subscribed header quietly starves the columns that need the room. */
.nvg-col-group-xl { width: 34%; }  /* the leading reference column */
.nvg-col-group-lg { width: 30%; }  /* grouped cell in a table with few columns */
.nvg-col-group-md { width: 24%; }
.nvg-col-group { width: 18%; }
.nvg-col-group-sm { width: 12%; }
.nvg-col-plain { width: 9%; }
.nvg-col-narrow { width: 6%; }
.nvg-col-actions { width: 5%; }  /* icon-only trigger, label on hover */

/* A reference code reads as one token, so its column is sized to hold the whole
   code on a single line rather than breaking it mid-code ("FPI/ NB O/2 ..."). */
.nvg-col-code { width: 17%; }

/* A money cell never wraps its figure and a status pill carries a two-word
   label, so both get a share wide enough to hold them outright. */
.nvg-col-money { width: 15%; }
.nvg-col-status { width: 13%; }

/* A bulk-select column holds a 16px control. Left unsized it absorbs the
   leftover share and opens a gap beside the column next to it. */
.nvg-table .bulk-checkbox-cell {
    width: 3rem;
    padding-left: 0.5rem;
    padding-right: 0.5rem;
}

/* ---------- the grouped cell ---------- */
.nvg {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    min-width: 0;
}

/* dominant field — the one the row is scanned by. Usually the row's reference,
   so it follows the same one-line rule as the values beneath it. */
.nvg-lead {
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1.3;
    color: var(--bs-gray-800);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

a.nvg-lead:hover {
    color: var(--bs-primary);
}

.nvg-lead.nvg-num {
    font-variant-numeric: tabular-nums;
}

/* supporting fields — smaller, still readable */
.nvg-sub {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.35rem;
    font-size: 0.82rem;
    font-weight: 500;
    line-height: 1.35;
    color: var(--bs-gray-700);
    min-width: 0;
}

.nvg-sub > a {
    color: inherit;
    text-decoration: none;
    min-width: 0;
}

.nvg-sub > a:hover {
    color: var(--bs-primary);
}

/* Field name inside a supporting line. Labels align on a common gutter, but a
   longer one ("Shipment", "Cust refs") takes the room it needs instead of being
   clipped — a fixed width would either cut the label or starve the value beside
   it in the narrower columns. */
.nvg-k {
    flex: 0 0 auto;
    min-width: 3.6rem;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--bs-gray-500);
    white-space: nowrap;
}

/* value helpers */
.nvg-num {
    font-variant-numeric: tabular-nums;
    color: var(--bs-gray-800);
    min-width: 0;
    white-space: nowrap;
}

/* A value stays on one line. A reference is a single token and breaking it
   ("AIR- 2024- 015") makes it unreadable, so the line clips with an ellipsis
   instead and every one of these carries a title with the value in full. */
.nvg-trunc {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

/* A label and its value share one line, but only while the value still has room
   to read. Squeezed into what is left of a narrow column, min-width:0 lets the
   value shrink until it breaks one character per line ("A I R - 2 0 2 4"). The
   basis below is the width a value asks for: when the leftover space beside the
   label is smaller than that, the value wraps to its own full-width line
   instead — same rule the code columns follow, never break a value mid-token. */
.nvg-sub > .nvg-trunc,
.nvg-sub > .nvg-num,
.nvg-sub > .nvg-empty {
    flex: 1 1 7rem;
}

/* ---------- row disclosure ----------
 * Supporting fields marked .nvg-x are in the DOM but hidden until the row is
 * opened. The control is a chevron sitting at the left edge of the first cell,
 * not a column of its own.
 */
.nvg-disclose {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    min-width: 0;
}

/* The control has to be findable before it can be used, so it carries its own
   surface rather than sitting as a bare glyph on the row, and is large enough
   to be an easy target on a touch screen. */
.nvg-tog {
    flex: 0 0 auto;
    width: 1.6rem;
    height: 1.6rem;
    margin-top: 0.05rem;
    padding: 0;
    border: 1px solid var(--bs-gray-300);
    border-radius: 6px;
    background: var(--bs-gray-100);
    color: var(--bs-gray-700);
    cursor: pointer;
    display: grid;
    place-items: center;
    line-height: 1;
    font-size: 0.8rem;
    transition: transform 0.15s ease, background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.nvg-tog:hover {
    background: var(--bs-gray-200);
    border-color: var(--bs-gray-400);
    color: var(--bs-gray-900);
}

.nvg-tog:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: 1px;
}

.nvg-table tr[data-open] .nvg-tog {
    transform: rotate(90deg);
    color: var(--bs-gray-800);
}

.nvg-table tr[data-open] > td {
    background: var(--bs-gray-100);
}

/* Opening and closing is a slide: the supporting lines grow out of the row and
   fade in together instead of snapping into place.
 *
 * max-height carries the motion because these lines have no fixed height. The
 * bound sits just above a two-line field — the tallest one of these gets once a
 * squeezed value wraps onto its own line — so the travel stays close to the real
 * height and the slide reads at its true speed.
 *
 * The negative margin swallows the parent's flex gap while collapsed, so a
 * closed row keeps exactly the height it had before. Visibility flips only after
 * the close finishes, which keeps the hidden lines out of the tab order and out
 * of find-in-page rather than merely transparent. */
.nvg-x {
    display: flex;
    overflow: hidden;
    max-height: 0;
    margin-top: -0.3rem;
    opacity: 0;
    visibility: hidden;
    transition:
        max-height 0.26s ease,
        margin-top 0.26s ease,
        opacity 0.18s ease,
        visibility 0s linear 0.26s;
}

.nvg-table tr[data-open] .nvg-x {
    max-height: 3rem;
    margin-top: 0;
    opacity: 1;
    visibility: visible;
    transition:
        max-height 0.26s ease,
        margin-top 0.26s ease,
        opacity 0.22s ease 0.04s,
        visibility 0s;
}

@media (prefers-reduced-motion: reduce) {
    .nvg-tog,
    .nvg-x,
    .nvg-table tr[data-open] .nvg-x {
        transition: none;
    }
}

/* a field with nothing in it — never rendered as a badge or a fake value */
.nvg-empty {
    color: var(--bs-gray-500);
    font-weight: 400;
}

/* route: origin over destination, arrow carries the direction */
.nvg-route-to::before {
    content: "\2192";
    margin-right: 0.3rem;
    color: var(--bs-gray-500);
}

/* status accent on the first cell of a row */
.nvg-spine { box-shadow: inset 3px 0 0 var(--bs-gray-300); }
.nvg-spine-primary { box-shadow: inset 3px 0 0 var(--bs-primary); }
.nvg-spine-info { box-shadow: inset 3px 0 0 var(--bs-info); }
.nvg-spine-success { box-shadow: inset 3px 0 0 var(--bs-success); }
.nvg-spine-warning { box-shadow: inset 3px 0 0 var(--bs-warning); }
.nvg-spine-danger { box-shadow: inset 3px 0 0 var(--bs-danger); }

/* pills read as one label; they wrap between words at most */
.nvg-table .badge,
.nvg-table .status-chip,
.nvg-table .type-chip {
    white-space: normal;
    overflow-wrap: normal;
    word-break: keep-all;
}

/* ---------- narrow screens ---------- */
/* Below the tablet breakpoint the label column costs more than it earns,
   so supporting fields stack their name above the value. */
@media (max-width: 991.98px) {
    .nvg-sub {
        flex-direction: column;
        gap: 0;
    }

    .nvg-k {
        width: auto;
        max-width: none;
    }

    /* stacked, every supporting line is at least two rows tall — the open bound
       has to clear that or the slide would clip the value it just revealed */
    .nvg-table tr[data-open] .nvg-x {
        max-height: 5rem;
    }
}
