/* ============================================================================
   VRYNO CARD GRID
   ============================================================================
   One way for cards to sit on a page, for every page.

   ---- what was wrong -------------------------------------------------------

   A sweep of the dashboards found three different spacings in use at once:
   a 1.5rem Bootstrap gutter between cards across, a 22px margin under each
   card down, and a g-3 (1rem) gutter on the newer pages -- so the space
   between two cards was 24px one way and 22px the other, and 16px on some
   pages and not others. Heights drifted too: 9 of 48 multi-card rows had one
   card 40-400px taller than the card beside it, because equal height depended
   on the page remembering to write d-flex on the column and flex-fill or
   h-100 on the card, and many pages did not.

   ---- what this does -------------------------------------------------------

   Any row that holds cards gets:

     * ONE gap, --vr-card-gap, in both directions, slightly tighter than the
       old 24px;
     * columns that stretch, so every card in a line ends at the same bottom
       edge whether or not the page wrote the flex classes;
     * natural wrapping -- a thirteenth column added to an existing row drops
       onto the next line already aligned and already spaced, so adding a card
       no longer means opening a new <div class="row">.

   All of it keys off :has(), so no page markup changes and it reaches every
   page at once. Bootstrap's column widths are left exactly as they are: this
   only touches spacing and height, so col-xl-8 / col-xl-4 still means 8 and 4.
============================================================================ */

:root {
    /* The single spacing between cards, across and down. 1rem rather than the
       old 24px: the ask was for it to be slightly tighter and more even. */
    --vr-card-gap: 1rem;
}

/* The rows this file governs: a row whose columns hold cards. Written out
   once per rule because CSS has no way to name a matched selector. Rows that
   hold form fields, table cells or anything else are not touched. */

.content .row:is(:has(> [class*="col"] > .card), :has(> [class*="col"] > .vrd-card)) {
    --bs-gutter-x: var(--vr-card-gap);
    /* Vertical space is carried by the card's own margin instead, so that the
       space below the LAST line matches the space between lines. Bootstrap's
       gutter-y would leave the final line flush against whatever follows. */
    --bs-gutter-y: 0;
    margin-bottom: 0 !important;
    align-items: stretch;
}

/* The column: a stretched box, so its card can fill it. Columns already
   written as d-flex keep working -- this only adds the direction. */
.content .row:is(:has(> [class*="col"] > .card), :has(> [class*="col"] > .vrd-card)) > [class*="col"] {
    display: flex;
    flex-direction: column;
}

.content .row:is(:has(> [class*="col"] > .card), :has(> [class*="col"] > .vrd-card)) > [class*="col"] > :is(.card, .vrd-card) {
    width: 100%;
    /* Beats .card { margin-bottom: 22px } on specificity, so it holds
       whichever order the stylesheets end up loading in. */
    margin-bottom: var(--vr-card-gap);
}

/* The card fills its column, and every column in a line is the same height,
   so the cards end level. A column holding a stack of cards is left alone --
   sharing the height between them would squash the small one. */
.content .row:is(:has(> [class*="col"] > .card), :has(> [class*="col"] > .vrd-card)) > [class*="col"] > :is(.card, .vrd-card):only-child {
    flex: 1 1 auto;
}

/* h-100 was the old way of asking for the same thing, and it means height:100%
   of the column -- which, with a margin under the card, overflows the line by
   exactly that margin and laps onto the next row. The stretch above already
   does the job, so the fixed height is handed back. */
.content .row:is(:has(> [class*="col"] > .card), :has(> [class*="col"] > .vrd-card)) > [class*="col"] > :is(.card, .vrd-card).h-100 {
    height: auto !important;
}

/* A card carrying its own spacing utility -- mb-2, mb-3, mb-4 -- is asking
   for a gap, just a different one. Those are brought to the single value.
   mb-0 is left alone: a card that says it wants no margin at all is usually
   one whose column is doing the spacing instead, and forcing a gap under it
   would double the spacing rather than even it out. */
.content .row:is(:has(> [class*="col"] > .card), :has(> [class*="col"] > .vrd-card)) > [class*="col"] > :is(.card, .vrd-card):is(.mb-1, .mb-2, .mb-3, .mb-4, .mb-5) {
    margin-bottom: var(--vr-card-gap) !important;
}

/* A row nested inside a card is that card's own content -- a set of fields, a
   split panel -- and is not a place for this spacing. */
.content .card .row,
.content .vrd-card .row {
    --bs-gutter-x: 1.5rem;
}

/* ---------------------------------------------------------- KPI tile strips

   The newer pages lay their KPI tiles out as a flex strip rather than a row.
   Same gap, so the two generations line up with each other. */

.content .d-flex[class*="gap-"]:has(> .vrd-kpi) {
    gap: var(--vr-card-gap) !important;
    margin-bottom: var(--vr-card-gap) !important;
}

/* ============================================================================
   THE EMPTY CARD
   ============================================================================
   A card with nothing to show says so, and offers the two ways to fix it,
   rather than presenting an empty box that reads as a loading failure.
   assets/js/vryno-cards.js decides which cards are empty; this is the look.
============================================================================ */

.vr-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    min-height: 150px;
    padding: 24px 16px;
    text-align: center;
}

.vr-empty-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 14px;
    background: var(--light);
    color: var(--gray-400);
    font-size: 22px;
    line-height: 1;
}

.vr-empty-title {
    margin: 0;
    font-size: 14px;
    font-weight: 600;
    color: var(--heading-color);
    line-height: 1.2;
}

.vr-empty-text {
    margin: 0;
    max-width: 280px;
    font-size: 12.5px;
    color: var(--gray-500);
    line-height: 1.45;
}

.vr-empty-actions {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 2px;
}

/* Sized to the toolbar buttons set in vryno-toolbar.css, so an empty card's
   buttons are the same size as every other button in the product. */
.vr-empty-actions .btn {
    height: var(--vr-tb-h, 30px);
    min-height: var(--vr-tb-h, 30px);
    padding: 0 12px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12.5px;
    line-height: 1;
    border-radius: 8px;
}

.vr-empty-actions .btn i {
    font-size: var(--vr-tb-icon, 14px);
}

/* A short card -- a KPI tile, a single figure -- gets the message without the
   padding that would make it taller than the card beside it. */
.vr-empty.vr-empty-sm {
    min-height: 0;
    padding: 14px 12px;
    gap: 6px;
}

.vr-empty.vr-empty-sm .vr-empty-icon {
    width: 32px;
    height: 32px;
    font-size: 17px;
    border-radius: 10px;
}

/* ============================================================================
   ONE ARROW, EVERY CARD
   ============================================================================
   A card that shows records leads somewhere, and every card said so in its own
   words: "View all", "View All", "See all", "All meetings", "View more" -- five
   spellings of one affordance, at five different sizes, in five different
   button styles.

   The heading directly above already says what you are opening, so the words
   were being printed twice. They are now the tooltip, and the control is a
   right arrow the same size wherever it appears. vryno-cardlinks.js puts this
   class on the links it adds AND rewrites the ones the pages wrote themselves,
   so both end up here.

   Sized to the toolbar icon buttons it sits beside, and built from tokens, so
   the dark theme needs no rule of its own.
   ========================================================================== */

.vp-cardlink {
    width: 28px;
    height: 28px;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--white);
    color: var(--gray-600);
    font-size: 15px;
    line-height: 1;
    text-decoration: none;
    cursor: pointer;
    transition: border-color .15s ease, color .15s ease, background .15s ease;
}

.vp-cardlink:hover,
.vp-cardlink:focus-visible {
    border-color: var(--primary);
    color: var(--primary);
    background: var(--primary-transparent);
    text-decoration: none;
}

.vp-cardlink i {
    font-size: inherit;
    line-height: 1;
}

/* The row the chart switcher builds for a card whose heading was loose in the
   body. It has to match the title rows the pages already write, or the two
   kinds of chart card would sit at different heights side by side. */
.vr-chart-head {
    min-height: 30px;
}

/* ============================================================================
   THE IN-CARD PANEL  (assets/js/vryno-card-panel.js)
   ============================================================================
   Notes, Email, Call, Task and Meeting open inside a Grid or Kanban card, at
   the bottom, the way they open under a row in the list view.

   The panel's contents are NOT a smaller copy of the list's: they are the same
   VrynoActivityTable, rendered into a card. So everything below is about one
   thing only -- making that table work in a 280px kanban column:

     * the toolbar wraps and its secondary buttons become icons
     * the composer is one column, not a grid
     * the item table stacks: each row becomes a block, each cell a labelled
       line, with the label taken from the cell's own data-col
     * the controls are BIGGER, not smaller -- the first version squeezed them
       to 5px of padding and the text was clipped mid-word

   Built from tokens, so the dark theme needs no rule of its own.
   ========================================================================== */

.vr-cp {
    margin: 10px -12px -12px;
    border-top: 1px solid var(--border-color);
    background: var(--light);
    border-radius: 0 0 10px 10px;
    overflow: hidden;
    cursor: default;
    text-align: left;
    animation: vr-cp-in .16s ease-out;
}

/* The grid card has 1rem of padding, the kanban card 12px; pulling the panel
   out to the card's own edge keeps it flush in both. */
.lead-grid-card > .vr-cp {
    margin: 12px -1rem -1rem;
    border-radius: 0 0 14px 14px;
}

@keyframes vr-cp-in {
    from {
        opacity: 0;
        transform: translateY(-4px);
    }
}

.vr-cp-open {
    border-color: var(--primary) !important;
    box-shadow: 0 0 0 1px var(--primary-transparent);
}

/* ---- head ---- */

.vr-cp-head {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px 10px;
    background: var(--white);
    border-bottom: 1px solid var(--border-color);
}

.vr-cp-title {
    font-size: 12px;
    font-weight: 600;
    color: var(--gray-900);
    min-width: 0;
    flex: 1 1 auto;
}

.vr-cp-close {
    border: 0;
    background: transparent;
    color: var(--gray-500);
    font-size: 15px;
    line-height: 1;
    padding: 3px 4px;
    cursor: pointer;
    flex-shrink: 0;
}

.vr-cp-close:hover {
    color: var(--danger, #e11d48);
}

/* ---- the tab strip: scrolls sideways, so a sixth kind just works ---- */

.vr-cp-tabs {
    display: flex;
    align-items: stretch;
    gap: 2px;
    padding: 0 6px;
    background: var(--white);
    border-bottom: 1px solid var(--border-color);
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}

.vr-cp-tabs::-webkit-scrollbar {
    height: 0;
}

.vr-cp-tab {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex: 0 0 auto;
    border: 0;
    background: transparent;
    padding: 8px 8px 7px;
    margin-bottom: -1px;
    border-bottom: 2px solid transparent;
    font-size: 11.5px;
    font-weight: 600;
    line-height: 1.2;
    color: var(--gray-500);
    cursor: pointer;
    white-space: nowrap;
}

.vr-cp-tab i {
    font-size: 14px;
}

/* Five labels do not fit across 280px, and shrinking them gives "N…",
   "Creat…". Only the tab you are on names itself; the rest are icon + count,
   with the name on hover. */
.vr-cp-tab-label {
    display: none;
}

.vr-cp-tab.active .vr-cp-tab-label {
    display: inline;
}

.vr-cp-tab.active {
    color: var(--primary);
    border-bottom-color: var(--primary);
}

.vr-cp-tab:hover {
    color: var(--gray-900);
}

.vr-cp-tab-count {
    font-size: 9.5px;
    font-weight: 700;
    line-height: 1;
    padding: 2px 5px;
    border-radius: 999px;
    background: var(--gray-100);
    color: var(--gray-600);
}

.vr-cp-tab.active .vr-cp-tab-count {
    background: var(--primary-transparent);
    color: var(--primary);
}

/* ---- the body ---- */

.vr-cp-body {
    max-height: 420px;
    overflow-y: auto;
    overflow-x: hidden;
    /* The card is 280px wide; 10px a side was taking 7% of it for nothing. */
    padding: 8px 7px 9px;
}

.vr-cp-body::-webkit-scrollbar {
    width: 6px;
}

.vr-cp-body::-webkit-scrollbar-thumb {
    background: var(--border-color);
    border-radius: 99px;
}

.vr-cp-fallback {
    font-size: 12px;
    color: var(--gray-500);
    margin: 0;
}

/* ==========================================================================
   The activity table, at card width
   ==========================================================================
   Three things go wrong when the list's panel is put in a 280px column, and
   all three are fixed here rather than in the engine:

     1. the toolbar's four buttons and a search field do not fit on one line
     2. a seven-column table does not fit at all
     3. everything the engine spaces for a full-width row is suddenly too big

   The rule throughout: take the padding out, not the legibility. Type stays
   readable and controls stay tappable; what shrinks is the empty space.
   ========================================================================== */

/* ---- toolbar: Add on the left, the two tool icons on the right ---- */

.vr-cp .vr-at-toolbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 5px;
    margin-bottom: 7px;
}

/* The spacer is what pushes Filter and Customize to the right-hand end. The
   first version hid it, which left them stranded on the left. */
.vr-cp .vr-at-toolbar-spacer {
    display: block;
    flex: 1 1 auto;
    order: 2;
}

.vr-cp .vr-at-toolbar > .vr-at-btn-primary {
    order: 1;
}

.vr-cp .vr-at-toolbar > .vr-at-pop-anchor {
    order: 3;
}

/* Search gets its own line, full width. */
.vr-cp .vr-at-search {
    order: 4;
    flex: 1 1 100%;
    min-width: 0;
}

.vr-cp .vr-at-search input {
    width: 100%;
    font-size: 12px;
    min-height: 30px;
    padding-block: 0;
}

/* Filter and Customize are icons only -- their labels cost a whole line and
   the icon already says it. */
.vr-cp .vr-at-toolbar .vr-at-btn:not(.vr-at-btn-primary) span:not(.vr-at-btn-badge) {
    display: none;
}

.vr-cp .vr-at-toolbar .vr-at-btn:not(.vr-at-btn-primary) {
    width: 28px;
    min-width: 28px;
    height: 28px;
    min-height: 28px;
    padding: 0;
    justify-content: center;
}

.vr-cp .vr-at-btn {
    min-height: 28px;
    padding: 0 10px;
    font-size: 12px;
    border-radius: 7px;
}

/* ---- composer ---- */

.vr-cp .vr-at-composer {
    padding: 8px;
    border-radius: 9px;
    margin-bottom: 8px;
}

.vr-cp .vr-at-composer-grid {
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.vr-cp .vr-at-field {
    width: 100%;
    min-width: 0;
}

.vr-cp .vr-at-field label {
    display: block;
    font-size: 10.5px;
    font-weight: 600;
    color: var(--gray-500);
    margin-bottom: 2px;
}

.vr-cp .vr-at-field input,
.vr-cp .vr-at-field select,
.vr-cp .vr-at-field textarea,
.vr-cp .vr-at-composer > textarea {
    width: 100%;
    box-sizing: border-box;
    min-height: 32px;
    padding: 6px 8px;
    font-size: 12.5px;
    line-height: 1.4;
    border-radius: 7px;
}

.vr-cp .vr-at-composer > textarea {
    min-height: 62px;
    resize: vertical;
}

.vr-cp .vr-at-composer-foot {
    flex-wrap: wrap;
    gap: 4px;
    margin-top: 7px;
}

/* ---- what is already on the record ----------------------------------------
   The table stacks: one block per item, one line per field, the field's name
   on the left and its value on the right. Every cell is still the engine's
   own cell, so click-to-edit works exactly as it does in the list. */

.vr-cp .vr-at-scroll {
    overflow: visible;
}

.vr-cp .vr-at-table {
    min-width: 0 !important;
    width: 100%;
    display: block;
}

.vr-cp .vr-at-table thead {
    display: none;
}

.vr-cp .vr-at-table tbody,
.vr-cp .vr-at-table tr,
.vr-cp .vr-at-table td {
    display: block;
    width: auto !important;
    max-width: none !important;
}

.vr-cp .vr-at-table tr {
    border: 1px solid var(--border-color);
    border-radius: 9px;
    background: var(--white);
    padding: 7px 8px;
    margin-bottom: 6px;
    position: relative;
    overflow: hidden;
}

/* An empty trailing cell still takes a line. */
.vr-cp .vr-at-table td:empty:not(.vr-at-col-select):not(.vr-at-col-actions) {
    display: none;
}

/* No grey wash on hover. A row that greys out as the pointer crosses it makes
   a list of six items flicker; the border is enough to say which one you are
   on. Same for the cells and the toolbar buttons. */
.vr-cp .vr-at-table tr:hover {
    background: var(--white);
    border-color: var(--primary);
}

.vr-cp .vr-at-table td:hover,
.vr-cp .vr-at-table td:focus-within {
    background: transparent;
}

.vr-cp .vr-at-btn:hover,
.vr-cp .vr-at-tool:hover {
    background: var(--primary-transparent);
    color: var(--primary);
}

/* Label left, value right, on one line. The first version put the label on a
   line of its own above the value, which turned a four-field note into eight
   lines of mostly nothing. */
/* The engine draws a rule under every cell -- right for a table, wrong for a
   stack, where it turns four facts into four boxes. !important because its
   own stylesheet loads after this one. */
.vr-cp .vr-at-table td {
    border: 0 !important;
    padding: 1px 0 !important;
    min-height: 0 !important;
    height: auto !important;
    font-size: 12px;
    line-height: 1.45;
    white-space: normal !important;
    display: flex;
    align-items: baseline;
    gap: 8px;
    color: var(--gray-800);
}

.vr-cp .vr-at-table td[data-label]::before {
    content: attr(data-label);
    flex: 0 0 auto;
    min-width: 66px;
    font-size: 10.5px;
    font-weight: 600;
    color: var(--gray-500);
    /* the engine's key would print as "relatedTo"; the label comes off the
       header row instead -- see labelCells() in vryno-card-panel.js */
    text-transform: none;
    letter-spacing: 0;
}

/* The first cell is the item itself -- it needs no label, and it wraps rather
   than truncating: "Chased the signe…" tells you nothing. */
.vr-cp .vr-at-table td.vr-at-prio-1 {
    display: block;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--gray-900);
    /* room on the right for the tick and the row actions */
    padding: 0 48px 5px 0 !important;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--border-color) !important;
    white-space: normal !important;
    overflow: visible !important;
    text-overflow: clip !important;
}

.vr-cp .vr-at-table td.vr-at-prio-1::before {
    display: none;
}

/* The value is wrapped in an element of the engine's own that clamps it to
   one line. Clearing the clamp has to reach every descendant, not just the
   direct child -- and -webkit-line-clamp needs clearing too, since a clamped
   box ellipsises whatever white-space says. */
.vr-cp .vr-at-table td.vr-at-prio-1,
.vr-cp .vr-at-table td.vr-at-prio-1 * {
    white-space: normal !important;
    overflow: visible !important;
    text-overflow: clip !important;
    max-width: none !important;
    width: auto !important;
    -webkit-line-clamp: none !important;
    line-clamp: none !important;
}

.vr-cp .vr-at-table td.vr-at-prio-1 > * {
    display: inline;
}

/* The tick and the row actions ride in the corner rather than taking a line
   of their own. */
.vr-cp .vr-at-table td.vr-at-col-select {
    position: absolute;
    top: 7px;
    right: 30px;
    padding: 0;
    display: block;
}

.vr-cp .vr-at-table td.vr-at-col-actions {
    position: absolute;
    top: 5px;
    right: 6px;
    padding: 0;
    display: block;
}

.vr-cp .vr-at-table td.vr-at-col-actions .vr-at-btn,
.vr-cp .vr-at-table td.vr-at-col-actions button {
    width: 22px;
    min-width: 22px;
    height: 22px;
    min-height: 22px;
    padding: 0;
    font-size: 13px;
}

/* An edit started in a cell gets a control the same size as the composer's. */
.vr-cp .vr-at-table input:not([type="checkbox"]),
.vr-cp .vr-at-table select,
.vr-cp .vr-at-table textarea {
    width: 100%;
    box-sizing: border-box;
    min-height: 30px;
    padding: 5px 7px;
    font-size: 12.5px;
    border-radius: 6px;
}

/* ---- foot ---- */

.vr-cp .vr-at-foot {
    flex-wrap: wrap;
    gap: 5px;
    font-size: 11px;
    padding-top: 7px;
}

/* The plus a Grid card did not have, drawn like the Kanban card's own. */
.vr-cp-plus {
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 7px;
    color: var(--gray-500);
    font-size: 16px;
    line-height: 1;
    text-decoration: none;
}

.vr-cp-plus:hover {
    background: var(--primary-transparent);
    color: var(--primary);
}

/* ---- the Filter and Customize popups ----
   Each is absolutely positioned against its own anchor and sized for a
   full-width row, so in a 280px card it opened 46px off the left edge of the
   panel and was then clipped by the card's rounded overflow -- you could read
   "ound", "nd", "ping" and nothing else.

   It is not made to escape the card: the card clips on purpose, so the corners
   stay round. Instead the popup is anchored to the TOOLBAR and spans the
   panel, which is the only width available to it, and scrolls if its list is
   longer than the card is tall. */

.vr-cp .vr-at-toolbar {
    position: relative;
}

.vr-cp .vr-at-pop-anchor {
    position: static;
}

.vr-cp .vr-at-pop {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    width: auto !important;
    min-width: 0 !important;
    max-width: none !important;
    max-height: 232px;
    overflow-y: auto;
    z-index: 5;
    box-sizing: border-box;
}

.vr-cp .vr-at-pop-row,
.vr-cp .vr-at-pop-group,
.vr-cp .vr-at-pop-head {
    white-space: normal;
    font-size: 12px;
}

.vr-cp .vr-at-pop-row {
    padding-block: 5px;
}

/* ============================================================================
   THE PAGE FORM'S CARD  (built by vryno-platform.js -> ensureFormCard)
   ============================================================================
   The card body used to carry pb-0 so the last field's own mb-3 would not
   double up with the card's bottom padding. That removed the space entirely
   for any form ending in a control with no margin of its own -- Add Signer
   ends in a select2 -- leaving the last field flush against the card edge.

   The padding is back, and the doubling is handled here instead: whatever the
   form's last element is, its bottom margin is dropped, so every add form ends
   with the card's own padding and nothing more.
   ========================================================================== */

.vp-form-card > .card-body > :last-child {
    margin-bottom: 0 !important;
}

/* A form laid out in a grid ends in a row of columns, and each column carries
   its own field with its own margin -- so the whole last row is collapsed, not
   only its last column. */
/* .vp-form-card > .card-body > .row:last-child > [class*="col"] > :last-child,
.vp-form-card > .card-body > .row:last-child > [class*="col"]:last-child {
    margin-bottom: 0 !important;
} */
