/* The hidden attribute always hides. Bootstrap's display utilities (.d-flex,
   .d-block...) are !important too and load later, so an element carrying both
   was shown - a strength meter on an empty password, a note meant for one
   role. This sheet loads after Bootstrap, so here [hidden] wins. */
[hidden] {
    display: none !important;
}

/*
   For screens below 576px (xs):
   - Make the button full-width, display:block
*/
@media (max-width: 575.98px) {
  .btn-responsive {
    display: block;
    width: 100%;
  }
}

/*
   For screens 576px (sm) and above:
   - Revert to an inline style
*/
@media (min-width: 576px) {
  .btn-responsive {
    display: inline-block;
    width: auto;
  }
}

.drag-handle {
    cursor: grab !important;
}

.drag-handle:active {
    cursor: grabbing !important;
}

.star-toggle input {
    display: none;
}

.star-toggle i {
    cursor: pointer;
    font-size: 1.2rem;
    color: #adb5bd;
}

.star-toggle input:checked + i {
    color: #f1c40f;
    font-weight: 900;
}

.checkbox-column {
    width: 40px;
    min-width: 40px;
    text-align: center;
}

.checkbox-column .form-check {
    padding-left: 0;
    margin-bottom: 0;
}

.checkbox-column .form-check-input {
    /* BS5 uses float:left here where BS4 used position:absolute - without
       float:none the box ignores the cell's text-align and pins to the left */
    float: none;
    position: static;
    margin: 0;
    vertical-align: middle;
}

/* ---------------------------------------------------------------
   AdminLTE 4 compatibility.
   v4 dropped .text-sm and the accent-* / navbar-* / sidebar-dark-*
   trio that ITFlow's 16 theme choices were built on. In v3 the theme
   colour drove the TOP NAVBAR, link colours and the active sidebar
   item - the sidebar itself was always dark. That is reproduced here.
   --------------------------------------------------------------- */
/* Font stack. v3 led with "Source Sans Pro" then -apple-system; v4/BS5 leads
   with "Source Sans 3" then system-ui. ITFlow loads neither webfont, so the
   two stacks fall through to different system fonts. Pinned to v3's. */
:root {
    --bs-font-sans-serif: "Source Sans Pro", -apple-system, BlinkMacSystemFont,
        "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif,
        "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}

/* The full .text-sm cascade. AdminLTE 3 shipped ~100 rules for this; these are
   the ones that actually set sizing, and without them the app renders a step
   larger everywhere than it used to. */
.text-sm {
    font-size: .875rem;
}
.text-sm .form-control,
.text-sm .form-select,
.text-sm .input-group-text,
.text-sm table {
    font-size: .875rem;
}
.text-sm .btn,
.text-sm .dropdown-menu {
    font-size: .875rem !important;
}
.text-sm .card-title {
    font-size: 1rem;
}
.text-sm .content-header h1,
.text-sm .app-content-header h1 {
    font-size: 1.5rem;
}
.text-sm .brand-link {
    font-size: inherit;
}

/* Sidebar density. v3 tightened nav-link padding under .text-sm to .4rem .8rem;
   BS5's default is .5rem 1rem, which is what made the menu items taller. */
.text-sm .nav-link {
    padding: .4rem .8rem;
}
/* v3 nav-icon metrics - v4 switched these to a 1.5rem flex box */
.sidebar-menu .nav-icon {
    min-width: 1.6rem;
    max-width: 1.6rem;
    margin-left: .05rem;
    margin-right: .2rem;
    font-size: 1.2rem;
}

/* one accent per theme - v3 used the same hex for navbar, links and
   the active sidebar item */
/* black has no upstream token - AdminLTE calls its darkest neutral
   gray-dark (#343a40), which is a different colour */
.theme-black { --itflow-accent: #000000; }
.theme-blue { --itflow-accent: var(--bs-blue, #007bff); }
.theme-cyan { --itflow-accent: var(--bs-cyan, #17a2b8); }
.theme-fuchsia { --itflow-accent: var(--bs-fuchsia, #f012be); }
.theme-gray { --itflow-accent: var(--bs-gray, #6c757d); }
.theme-green { --itflow-accent: var(--bs-green, #28a745); }
.theme-indigo { --itflow-accent: var(--bs-indigo, #6610f2); }
.theme-lightblue { --itflow-accent: var(--bs-lightblue, #3c8dbc); }
.theme-maroon { --itflow-accent: var(--bs-maroon, #d81b60); }
.theme-navy { --itflow-accent: var(--bs-navy, #001f3f); }
.theme-olive { --itflow-accent: var(--bs-olive, #3d9970); }
.theme-orange { --itflow-accent: var(--bs-orange, #fd7e14); }
.theme-pink { --itflow-accent: var(--bs-pink, #e83e8c); }
.theme-purple { --itflow-accent: var(--bs-purple, #6f42c1); }
.theme-red { --itflow-accent: var(--bs-red, #dc3545); }
.theme-teal { --itflow-accent: var(--bs-teal, #20c997); }
.theme-yellow { --itflow-accent: var(--bs-yellow, #ffc107); }

/* top navbar takes the theme colour */
.app-header.navbar {
    background-color: var(--itflow-accent, #007bff) !important;
}

/* Navbar height. v4 pairs .app-header{max-height:2.75rem} with 0.5rem of
   navbar padding, but the tallest children want 47-48px and overflow that
   44px cap. Everything below is sized so it fits inside a 3rem bar - the
   .navbar-search field is ~33px and clears it without help.
   NOTE: .sidebar-brand is the matching half of this pair and is set to the
   same height further down - change both or they stop lining up. */
.app-header.navbar {
    --bs-navbar-padding-y: .4rem;
    min-height: 3rem;
    max-height: 3rem;
}
/* Every item stretches the full bar and centres its own contents, so icons,
   the avatar and the search box all sit on the same optical line regardless of
   their individual heights. */
.app-header .navbar-nav {
    align-items: stretch;
}
.app-header .navbar-nav > .nav-item {
    display: flex;
    align-items: center;
}
.app-header .navbar-nav .nav-link {
    display: flex;
    align-items: center;
    height: 100%;
    max-height: none;
    padding-top: 0;
    padding-bottom: 0;
}
/* v4 sizes the avatar 2rem with a -2px nudge, which is too tall for this bar */
.app-header .navbar-nav > .user-menu .user-image {
    width: 1.6rem;
    height: 1.6rem;
    margin-top: 0;
}
/* .navbar-badge positions itself (top:9px/right:5px) for a taller bar. Pinned
   to the link's edge, it slid over the icon whenever the link got narrower -
   on phones the link is 28px wide and the badge covered the bell completely.
   The icon is centred in the link, so anchoring to the centre puts the badge
   on the icon's top-right corner at every width. */
.app-header .navbar-badge {
    top: 50%;
    right: auto;
    left: calc(50% + .2rem);
    margin-top: -.9rem;
    font-size: .65rem;
}

/* sidebar stays dark; only the ACTIVE item picks up the theme.

   The :hover and :focus variants are load-bearing, not decoration. A bare
   `.nav-link.active` scores exactly the same specificity as the grey hover
   rule further down this file (both 0,5,0), and that rule comes later - so
   pointing at the current page's menu item repainted its accent grey.
   AdminLTE 3 won this same tie on source order alone: its per-theme
   `.sidebar-dark-<colour> ... .nav-link.active` rule was emitted AFTER the
   `[class*=sidebar-dark-] ... .nav-item:hover > .nav-link` block, so the
   accent held on hover. Spelling the states out here wins on specificity
   instead, which survives any future reordering of this sheet.

   v3 also pinned its treeview active item the same way
   (`.nav-link.active, .nav-link.active:hover, .nav-link.active:focus`), so
   both levels are covered. Deliberately NO separate hover shade for the
   active item: v3 had none, and the current item is already the loudest
   thing in the sidebar. */
.app-sidebar .sidebar-menu > .nav-item > .nav-link.active,
.app-sidebar .sidebar-menu > .nav-item:hover > .nav-link.active,
.app-sidebar .sidebar-menu > .nav-item > .nav-link.active:focus,
.app-sidebar .nav-treeview > .nav-item > .nav-link.active,
.app-sidebar .nav-treeview > .nav-item > .nav-link.active:hover,
.app-sidebar .nav-treeview > .nav-item > .nav-link.active:focus {
    background-color: var(--itflow-accent, #007bff);
    color: #fff;
}

/* Bootstrap 5's reboot underlines every link; Bootstrap 4 did not, and
   AdminLTE 3 additionally suppressed the hover underline. Restored so links
   read the way they did before the migration. */
a,
a:hover,
a:focus {
    text-decoration: none;
}

/* links and accented controls */
/* Tabs and pills. Bootstrap points inactive nav links at --bs-link-color and
   hardcodes --bs-nav-pills-link-active-bg to #0d6efd, so both states came out
   blue regardless of theme. Scoped to .nav-tabs/.nav-pills rather than .nav:
   .navbar-nav redefines these same variables for the top bar, and the sidebar
   is protected by its own higher-specificity rules. */
.nav-tabs,
.nav-pills {
    /* inactive sits at 70% so the active state still reads as the highlight */
    --bs-nav-link-color: color-mix(in srgb, var(--itflow-accent, #007bff) 70%, transparent);
    --bs-nav-link-hover-color: var(--itflow-accent, #007bff);
}
.nav-tabs {
    --bs-nav-tabs-link-active-color: var(--itflow-accent, #007bff);
    /* accent rule along the top edge marks the selected tab */
    --bs-nav-tabs-link-active-border-color: var(--itflow-accent, #007bff) var(--bs-border-color) var(--bs-body-bg);
}
.nav-tabs .nav-link.active {
    font-weight: 600;
}
/* Pagination. Driving Bootstrap's own variables rather than overriding
   .page-link directly: a flat `.page-item .page-link{color:...}` ties with
   BS5's `.active>.page-link` and `.disabled>.page-link` on specificity and,
   because this sheet loads last, silently won both - so the active number was
   accent-on-accent (invisible) and disabled Prev/Next lost their muted grey. */
/* Bootstrap's generic focus ring (buttons, links, .btn-check labels) */
.form-check-input:checked {
    background-color: var(--itflow-accent, #007bff);
    border-color: var(--itflow-accent, #007bff);
}

/* sidebar is ALWAYS dark - v4 gives .app-sidebar no background at all.
   These are AdminLTE 3.2.0's [class*=sidebar-dark-] values verbatim. */
.app-sidebar {
    background-color: #343a40;
}
/* Sidebar header. v4 scopes its brand rules under .sidebar-brand, and its own
   defaults centre the brand in a fixed 2.75rem box. v3's .brand-link was a
   left-aligned block, and several of these headers carry a "Back | ..." line
   that is taller than that, so height is relaxed and alignment restored. */
.app-sidebar .sidebar-brand {
    /* v4 deliberately pairs .sidebar-brand{height:2.75rem} with
       .app-header{max-height:2.75rem} so the sidebar header lines up with the
       top bar. Both are set to 3rem above - change them together or
       they stop lining up. v4's .8125rem padding leaves too little room for
       the heading, so it is cut right down. */
    height: 3rem;
    padding: .3rem .5rem;
    justify-content: flex-start;
    background-color: #343a40;
    border-bottom: 1px solid #4b545c;
}
.app-sidebar .sidebar-brand .brand-link {
    width: 100%;
    color: #fff;
}
.app-sidebar .sidebar-brand .brand-text {
    color: #fff;
    line-height: 1.2;
}
/* Bootstrap sizes .h1-.h4 responsively (e.g. .h4 is calc(1.275rem + .3vw)), so
   on a wide screen they outgrow the bar and v4's .sidebar-brand{overflow:hidden}
   clips them. Cap ONLY those - .h5 (1.25rem) and .h6 (1rem) are fixed and must
   keep their own size, or the "Back | ..." headers get blown up to h4. */
.app-sidebar .sidebar-brand .brand-text.h1,
.app-sidebar .sidebar-brand .brand-text.h2,
.app-sidebar .sidebar-brand .brand-text.h3,
.app-sidebar .sidebar-brand .brand-text.h4,
.app-sidebar .sidebar-brand h1.brand-text,
.app-sidebar .sidebar-brand h2.brand-text,
.app-sidebar .sidebar-brand h3.brand-text,
.app-sidebar .sidebar-brand h4.brand-text {
    font-size: min(1.6rem, calc(1.275rem + .3vw));
}

/* Company brand - agent/includes/side_nav.php (main nav only; the client,
   admin and reports navs keep their "Back | ..." headers above).

   The logo or initials tile with the company name beside it, the whole row one
   rounded hover target like a workspace switcher. Sized to sit inside the 3rem
   header that lines up with the top bar. */
.app-sidebar .itflow-brand-link {
    gap: .6rem;
    height: 100%;
    padding: .2rem .4rem;
    border-radius: var(--bs-border-radius);
    color: #fff;
    transition: background-color .15s ease-in-out;
}
.app-sidebar .itflow-brand-link:hover {
    background-color: rgba(255, 255, 255, .07);
    color: #fff;
}
.app-sidebar .itflow-brand-link:focus-visible {
    outline: 2px solid var(--itflow-accent, var(--bs-primary));
    outline-offset: -2px;
}
.itflow-brand-mark {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    height: 2rem;
    border-radius: var(--bs-border-radius);
    overflow: hidden;
}
/* Logos are drawn for a light page, so they get a light tile. A wide logo
   widens the tile (up to a point) instead of shrinking to fit a square. */
.itflow-brand-mark-logo {
    min-width: 2rem;
    max-width: 5.5rem;
    padding: .2rem .3rem;
    background-color: #fff;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .35);
}
.itflow-brand-mark-logo img {
    display: block;
    width: auto;
    height: 100%;
    max-width: 100%;
    object-fit: contain;
}
/* No logo: the company's initials on the theme colour. The inner ring keeps
   the tile visible when the theme colour is close to the sidebar's (black,
   navy, gray). */
.itflow-brand-mark-initials {
    width: 2rem;
    font-size: .7rem;
    font-weight: 700;
    letter-spacing: .03em;
    color: #fff;
    background-color: var(--itflow-accent, #007bff);
    background-image: linear-gradient(135deg, rgba(255, 255, 255, .18), rgba(0, 0, 0, .18));
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .18), 0 1px 2px rgba(0, 0, 0, .35);
}
.theme-yellow .itflow-brand-mark-initials {
    color: #1f2d3d;
}
/* Two lines, then an ellipsis. v4's .sidebar-brand is nowrap, so wrapping
   has to be switched back on here. */
.itflow-brand-name {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    min-width: 0;
    overflow: hidden;
    font-size: .95rem;
    font-weight: 600;
    line-height: 1.15;
    letter-spacing: -.01em;
    white-space: normal;
    overflow-wrap: anywhere;
}
.app-sidebar .sidebar-menu .nav-link,
.app-sidebar .nav-header {
    color: #c2c7d0;
}
.app-sidebar .sidebar-menu > .nav-item > .nav-link:focus,
.app-sidebar .sidebar-menu > .nav-item:hover > .nav-link,
.app-sidebar .sidebar-menu > .nav-item.menu-open > .nav-link {
    background-color: rgba(255, 255, 255, .1);
    color: #fff;
}
.app-sidebar .sidebar-menu > .nav-item > .nav-link.active {
    color: #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24);
}
.app-sidebar .nav-treeview {
    background-color: transparent;
}


/* --- Bootstrap 5 unpaired background utilities -------------------------
   BS4 + AdminLTE 3 shipped `.bg-dark,.card.bg-dark .card-body{color:#fff}`.
   BS5 split the pair: .bg-* sets ONLY a background and you are expected to
   use .text-bg-* for the pairing. ITFlow uses bg-dark 303 times (every modal
   header, most card headers), so without this the header text is dark on
   dark and effectively invisible. Contrast choices below mirror Bootstrap's
   own .text-bg-* decisions. */
.bg-dark, .bg-primary, .bg-secondary, .bg-success, .bg-danger, .bg-purple {
    color: #fff;
}
.bg-info, .bg-warning, .bg-light, .bg-olive, .bg-pink {
    color: #000;
}
.card.bg-dark .card-body {
    color: #fff;
}
/* keep close buttons visible on the dark headers they sit in */
.bg-dark > .btn-close, .modal-header.bg-dark .btn-close {
    filter: var(--bs-btn-close-white-filter, invert(1) grayscale(100%) brightness(200%));
}

/* --- dashboard small-box ------------------------------------------------
   AdminLTE 4 dropped v3's watermark icon. 4.8.5 restored it, but under a new
   class name (.small-box-icon) that ITFlow's markup does not use - the boxes
   still carry v3's <div class="icon"> wrapper - so these rules stay.
   The inner padding and the p > small rule ARE back upstream at identical
   values and have been dropped from here. */
.small-box .icon {
    color: rgba(0, 0, 0, .15);
    z-index: 0;
}
.small-box .icon > i,
.small-box .icon > svg {
    position: absolute;
    top: 15px;
    right: 15px;
    font-size: 90px;
    transition: transform .3s linear;
}
.small-box:hover .icon > i,
.small-box:hover .icon > svg {
    transform: scale(1.1);
}
/* Upstream sets z-index:5 on these but no `position`, which leaves it inert -
   the icon is absolutely positioned at z-index 0, so the text needs a
   stacking context of its own to stay above it. */
.small-box h3,
.small-box .h3,
.small-box p {
    position: relative;
}
/* 4.8.5 sets this same 1rem, but also shrinks it to 12px below 576px. This
   file loads last at equal specificity, so keeping the line deliberately
   holds the desktop size on phones too; delete it to take their mobile
   treatment instead. */
.small-box p {
    font-size: 1rem;
}
.small-box hr {
    opacity: .25;
}
.small-box > .small-box-footer {
    color: rgba(255, 255, 255, .8);
}
.small-box > .small-box-footer:hover {
    color: #fff;
}

/* --- utility classes AdminLTE 4 dropped -------------------------------- */
.text-bold, .text-bold.table td, .text-bold.table th {
    font-weight: 700;
}
.text-xs {
    font-size: .75rem !important;
}
.btn-default {
    color: #6c757d;
    background-color: #f8f9fa;
    border-color: #ced4da;
}
.btn-default:hover {
    color: #495057;
    background-color: #e2e6ea;
    border-color: #adb5bd;
}
.btn-flat {
    border-radius: 0;
    border-width: 1px;
    box-shadow: none;
}
/* sidebar count badges - v3 positioned these absolutely */
.sidebar-menu .nav-link > .right,
.sidebar-menu .nav-link > p > .right {
    position: absolute;
    right: 1rem;
    top: .7rem;
}
/* v3's softened box colours, kept for the three small-boxes that still use
   them on the dashboard. The other fourteen were dropped - nothing in the
   tree carries those classes, and the only class names PHP interpolates are
   Bootstrap's seven contextual ones, so they were unreachable. adminlte-
   colors-v3 defines all of them anyway if a page ever wants one back. */
.bg-olive { background-color: rgba(116,200,163,.9) !important; }
.bg-pink { background-color: rgba(232,62,140,.9) !important; }
.bg-purple { background-color: rgba(111,66,193,.9) !important; }

/* --- Flatpickr date-filter preset panel ---------------------------------
   Flatpickr has no preset-ranges feature; js/date_filter.js injects this
   panel to reproduce the nine ranges daterangepicker used to provide. */
/* The panel sits in a second column to the right of the month grid. This has to
   be a GRID rather than flex: .flatpickr-calendar's own children are the month
   nav and the day grid STACKED, so flexing the container would put those two
   side by side as well. Two explicit columns keep flatpickr's own stacking in
   column 1 and give the panel column 2, spanning both rows.

   width:auto is safe in this layout but was NOT when the panel ran along the
   bottom. The calendar is position:absolute, so auto means shrink-to-fit, which
   resolves to max-content - and max-content for a horizontal row of nine nowrap
   buttons is one long line that flex-wrap never breaks, while .flatpickr-days
   keeps its own fixed 307.875px. Everything past the month grid then rendered as
   an empty second pane. Stacked in a column the panel's max-content is just the
   widest single label, so the container comes out calendar + panel wide.

   The `> *` rule catches anything flatpickr adds later - an unplaced child would
   otherwise auto-flow into column 2 and land on top of the panel. */
.flatpickr-calendar.itflow-fp-with-ranges.open {
    display: grid;
    grid-template-columns: max-content max-content;
    grid-template-rows: auto auto;
    align-items: start;
    width: auto;
}
.flatpickr-calendar.itflow-fp-with-ranges > * {
    grid-column: 1;
}
.flatpickr-calendar.itflow-fp-with-ranges > .itflow-fp-ranges {
    grid-column: 2;
    grid-row: 1 / span 2;
    /* stretch so the divider runs the calendar's full height, not just the
       height of the nine buttons */
    align-self: stretch;
}
.itflow-fp-ranges {
    display: flex;
    flex-direction: column;
    gap: .125rem;
    padding: .5rem;
    border-left: 1px solid var(--bs-border-color, #dee2e6);
}
.itflow-fp-range {
    padding: .2rem .5rem;
    font-size: .8125rem;
    /* .flatpickr-calendar sets line-height:24px and it inherits. Nine buttons at
       that height overshoot the calendar's own ~296px; 1.4 brings the column back
       under it so the two sides finish level. */
    line-height: 1.4;
    text-align: left;
    color: var(--itflow-accent, #007bff);
    white-space: nowrap;
    background: none;
    border: 1px solid transparent;
    border-radius: .25rem;
}
.itflow-fp-range:hover,
.itflow-fp-range:focus,
.itflow-fp-range.active {
    color: #fff;
    background-color: var(--itflow-accent, #007bff);
    border-color: var(--itflow-accent, #007bff);
}
/* The preset currently in effect - without this there is nothing on screen
   telling you which range you are looking at once the calendar is open. */
.itflow-fp-range.active {
    font-weight: 600;
}

/* --- Flash toast ---------------------------------------------------------
   Restores the four things toastr did that a plain Bootstrap toast does not:
   sits top-right rather than centred over what you are reading, carries an
   icon for its type, counts its own timer down, and dismisses on a click
   anywhere instead of only on the small x.

   It also appears on the FIRST PAINT. includes/inc_alert_feedback.php renders
   the element with .show already set and every state change here is an
   animation, so nothing waits on bootstrap.Toast - which used to mean waiting
   for DOMContentLoaded, and therefore for every parser-blocking script in the
   document. The inline script in that file only handles the click and removes
   the node; neither gates the appearance.

   Durations are toastr's own: 300ms in, 5s on screen, 1s out. */
.itflow-toast {
    position: relative;
    overflow: hidden;
    cursor: pointer;
    animation:
        itflow-toast-in 300ms ease-out both,
        itflow-toast-out 1s ease-in 5s both;
}

/* Hovering holds it open, so a long message cannot disappear mid-sentence.
   The progress bar needs its own rule - animation-play-state does not
   cascade to a child's separate animation. */
.itflow-toast:hover,
.itflow-toast:hover .itflow-toast-progress {
    animation-play-state: paused;
}

/* currentColor, so the bar inherits whichever contrast text-bg-* already
   picked - white on success and danger, dark on warning and info - rather
   than needing a rule per type. */
.itflow-toast-progress {
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    height: 3px;
    background: currentColor;
    opacity: .4;
    transform-origin: left;
    animation: itflow-toast-progress 5s linear both;
}

@keyframes itflow-toast-in {
    from {
        opacity: 0;
        transform: translateX(100%);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}

/* visibility flips on the last one percent rather than at the end, because a
   discrete property switches at the MIDPOINT of its keyframe interval - put
   it only on the 100% stop and the toast would vanish halfway through its own
   fade. This is the fallback that matters if the inline remover never runs:
   without it an invisible toast keeps sitting over the user menu, eating
   clicks. */
@keyframes itflow-toast-out {
    0% {
        opacity: 1;
        visibility: visible;
    }
    99% {
        opacity: 0;
        visibility: visible;
    }
    100% {
        opacity: 0;
        visibility: hidden;
    }
}

@keyframes itflow-toast-progress {
    from {
        transform: scaleX(1);
    }
    to {
        transform: scaleX(0);
    }
}

/* Reduced motion drops the slide and the moving bar but keeps the timed
   dismissal - that is a timeout, not an animation the user is watching. */
@media (prefers-reduced-motion: reduce) {
    .itflow-toast {
        animation: itflow-toast-out 1s linear 5s both;
    }
    .itflow-toast-progress {
        animation: none;
        transform: scaleX(0);
    }
}

/* The JS-raised toasts from itflowToast() still go through bootstrap.Toast,
   so they keep the slower fade. */
.itflow-toast-js .toast.fade {
    transition: opacity .5s linear;
}

/* --- Filter footer -------------------------------------------------------
   The pagination row wants a touch more breathing room than .py-2 gives, but
   .py-3 is a 16px jump that makes the bar noticeably chunky. Bootstrap has no
   step between the two, hence the named rule. */
.card-footer.itflow-filter-footer {
    padding-top: .5rem;
    padding-bottom: .5rem;
}

/* --- Primary button follows the theme -----------------------------------
   Bootstrap 5 buttons are entirely variable driven, so these set --bs-btn-*
   rather than overriding background-color. That keeps hover, active,
   disabled and the focus ring consistent instead of only recolouring the
   resting state.

   The shade steps are Bootstrap's own: hover is shade 15%, active shade 20%,
   and shade(c, n%) is literally mix(black, c, n%) - which color-mix
   reproduces exactly. */

/* Focus ring has to be an RGB triplet, so it is per theme. */

/* Text colour on a solid primary button. Threshold derived from Bootstrap's
   own palette (white up to L=0.183, black from L=0.486), so only these two
   themes are light enough to need dark text - the rest keep white. */

/* Same L>0.335 contrast cut as the primary button. */
.theme-orange .nav-pills,
.theme-teal .nav-pills,
.theme-yellow .nav-pills {
    --bs-nav-pills-link-active-color: #000;
}


/* --- Theme picker (admin/settings_theme.php) -----------------------------
   Each choice is a miniature of the app rather than a colour circle, so you
   can see where the colour actually lands before committing to it. Structure
   and proportions are lifted from AdminLTE 4's own theme generator
   (dist/generate/theme.html) - note those .lte-skin-preview-* rules live in
   that page's inline <style> and are NOT in adminlte.min.css, so they are
   reproduced here under ITFlow-owned names to avoid colliding with anything
   upstream may ship later.

   The mini-app reflects how ITFlow actually applies a theme, not AdminLTE's
   presets: the sidebar is always dark with the accent on its active item, the
   top bar takes the accent, and the content area shows an accent widget
   beside a neutral one.

   The preview carries .theme-<name>, so --itflow-accent is re-scoped for that
   subtree and every swatch paints itself from the same variable the theme
   will apply - add a theme to the stylesheet and its preview is correct with
   no extra rule.

   The radio is a visually hidden .btn-check and the label is the control.
   Selection reads as a ring around the preview plus a bolder name. */
.itflow-theme-swatch {
    display: block;
    padding: .5rem .25rem;
    text-align: center;
    cursor: pointer;
    border-radius: .5rem;
    transition: background-color .15s ease;
}
.itflow-theme-swatch:hover {
    background-color: var(--bs-secondary-bg);
}
.itflow-theme-preview {
    display: inline-flex;
    width: 6rem;
    height: 3.75rem;
    overflow: hidden;
    vertical-align: middle;
    background-color: var(--bs-tertiary-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    transition: border-color .15s ease, box-shadow .15s ease;
}
/* the sidebar is always dark in ITFlow, whatever the theme */
.itflow-theme-preview-sidebar {
    display: flex;
    flex: 0 0 30%;
    flex-direction: column;
    gap: 9%;
    padding: 10% 12%;
    color: #fff;
    background-color: #343a40;
}
.itflow-theme-preview-brand,
.itflow-theme-preview-item {
    display: block;
    flex: none;
    height: 7%;
    min-height: 2px;
    background: currentColor;
    border-radius: 99px;
    opacity: .45;
}
.itflow-theme-preview-brand {
    width: 70%;
    height: 11%;
    min-height: 3px;
    margin-bottom: 6%;
    opacity: .9;
}
/* only the active sidebar item takes the accent - same as the real sidebar */
.itflow-theme-preview-active {
    background: var(--itflow-accent, #007bff);
    opacity: 1;
}
.itflow-theme-preview-main {
    display: flex;
    flex: auto;
    flex-direction: column;
    min-width: 0;
}
.itflow-theme-preview-header {
    display: flex;
    flex: 0 0 24%;
    gap: 6%;
    align-items: center;
    padding: 0 8%;
    color: #fff;
    background-color: var(--itflow-accent, #007bff);
}
.itflow-theme-preview-header .itflow-theme-preview-item {
    width: 24%;
    height: 22%;
    opacity: .55;
}
.itflow-theme-preview-avatar {
    display: block;
    width: 14%;
    margin-left: auto;
    aspect-ratio: 1;
    background: currentColor;
    border-radius: 50%;
    opacity: .55;
}
.itflow-theme-preview-body {
    display: grid;
    flex: auto;
    grid-template-rows: 1fr 1fr;
    grid-template-columns: 1fr 1fr;
    gap: 8%;
    padding: 10%;
}
.itflow-theme-preview-box {
    display: block;
    background-color: var(--itflow-accent, #007bff);
    border-radius: 2px;
}
.itflow-theme-preview-box-muted {
    background-color: var(--bs-secondary-bg);
}
.itflow-theme-preview-card {
    display: block;
    grid-column: 1 / -1;
    background-color: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: 2px;
}
.itflow-theme-name {
    display: block;
    margin-top: .4rem;
    font-size: .8125rem;
    text-transform: capitalize;
}
.btn-check:checked + .itflow-theme-swatch .itflow-theme-preview {
    border-color: var(--bs-body-color);
    box-shadow: 0 0 0 1px var(--bs-body-color);
}
.btn-check:checked + .itflow-theme-swatch .itflow-theme-name {
    font-weight: 600;
}
.btn-check:focus-visible + .itflow-theme-swatch {
    outline: 2px solid var(--itflow-accent, #007bff);
    outline-offset: 2px;
}

/* --- Dark mode ------------------------------------------------------------
   Bootstrap treats .bg-light / .text-dark / .bg-white as ABSOLUTE colours, so
   none of them flip under [data-bs-theme=dark] - 69 bg-light and 425 text-dark
   usages stayed bright. Overriding the utilities rather than the underlying
   --bs-light-rgb / --bs-dark-rgb variables, because those same two variables
   also drive .text-light and .bg-dark, which must NOT flip. */
[data-bs-theme=dark] .bg-light {
    background-color: var(--bs-secondary-bg) !important;
}
[data-bs-theme=dark] .bg-white {
    background-color: var(--bs-body-bg) !important;
}
[data-bs-theme=dark] .text-dark {
    color: var(--bs-body-color) !important;
}
/* .table-light hardcodes #f8f9fa and #000 outright */
[data-bs-theme=dark] .table-light {
    --bs-table-bg: var(--bs-secondary-bg);
    --bs-table-color: var(--bs-body-color);
    --bs-table-border-color: var(--bs-border-color);
    --bs-table-striped-bg: var(--bs-tertiary-bg);
    --bs-table-striped-color: var(--bs-body-color);
    --bs-table-hover-bg: var(--bs-tertiary-bg);
    --bs-table-hover-color: var(--bs-body-color);
}

/* Secondary and light buttons are fixed greys - #6c757d and #f8f9fa - so in
   dark mode one goes muddy and the other glares. 260 btn-light and 185
   btn-secondary uses, so these matter more than most. */
[data-bs-theme=dark] .btn-secondary {
    --bs-btn-color: #dee2e6;
    --bs-btn-bg: #3d4349;
    --bs-btn-border-color: #495057;
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: #495057;
    --bs-btn-hover-border-color: #565e64;
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: #565e64;
    --bs-btn-active-border-color: #6c757d;
    --bs-btn-disabled-color: #adb5bd;
    --bs-btn-disabled-bg: #3d4349;
    --bs-btn-disabled-border-color: #495057;
}
[data-bs-theme=dark] .btn-light {
    --bs-btn-color: #dee2e6;
    --bs-btn-bg: #343a40;
    --bs-btn-border-color: #454d55;
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: #454d55;
    --bs-btn-hover-border-color: #565e64;
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: #565e64;
    --bs-btn-active-border-color: #6c757d;
    --bs-btn-disabled-color: #6c757d;
    --bs-btn-disabled-bg: #343a40;
    --bs-btn-disabled-border-color: #454d55;
}
/* .btn-dark is #212529 - EXACTLY --bs-body-bg in dark mode, so the button was
   the same colour as the page. Its main use is the search button welded to an
   input group, so it needs to read as a control next to a .form-control rather
   than invert to a bright button. Sits a step above the input, and above the
   other two neutrals, mirroring its light-mode role as the strongest of them:
   btn-light #343a40 < btn-secondary #3d4349 < btn-dark #495057 */
[data-bs-theme=dark] .btn-dark {
    --bs-btn-color: #dee2e6;
    --bs-btn-bg: #495057;
    --bs-btn-border-color: #545b62;
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: #545b62;
    --bs-btn-hover-border-color: #6c757d;
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: #6c757d;
    --bs-btn-active-border-color: #7d858c;
    --bs-btn-disabled-color: #adb5bd;
    --bs-btn-disabled-bg: #495057;
    --bs-btn-disabled-border-color: #545b62;
}
[data-bs-theme=dark] .btn-outline-dark {
    --bs-btn-color: #dee2e6;
    --bs-btn-border-color: #6c757d;
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: #495057;
    --bs-btn-hover-border-color: #6c757d;
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: #545b62;
    --bs-btn-active-border-color: #6c757d;
}
[data-bs-theme=dark] .btn-outline-secondary {
    --bs-btn-color: #adb5bd;
    --bs-btn-border-color: #6c757d;
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: #6c757d;
    --bs-btn-hover-border-color: #6c757d;
}
/* .btn-default is my own AdminLTE 3 shim and hardcodes a light grey, so it
   glares in dark mode like the Bootstrap greys above. */
[data-bs-theme=dark] .btn-default {
    color: #dee2e6;
    background-color: #343a40;
    border-color: #454d55;
}
[data-bs-theme=dark] .btn-default:hover {
    color: #fff;
    background-color: #454d55;
    border-color: #565e64;
}

/* --- TinyMCE chrome ------------------------------------------------------
   TinyMCE's oxide skins ship their own palette - a blue-slate #222f3e with
   #161f29 borders in dark - which sits next to the app's neutral #212529 and
   #495057 and reads as a mismatch rather than a choice. The toolbar and
   frame live in the main document (only the editing area is iframed), so
   they can be driven from the same --bs-* variables as every other control,
   which also means light and dark are handled by one set of rules.

   The frame is matched to .form-control: same border, radius and focus ring. */
.tox.tox-tinymce {
    border: var(--bs-border-width) solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
}
.tox .tox-editor-header,
.tox .tox-toolbar,
.tox .tox-toolbar__primary,
.tox .tox-toolbar-overlord,
.tox .tox-menubar,
.tox .tox-statusbar {
    background-color: var(--bs-tertiary-bg) !important;
    border-color: var(--bs-border-color) !important;
}
.tox .tox-editor-header {
    box-shadow: none;
}
.tox .tox-statusbar {
    border-top: var(--bs-border-width) solid var(--bs-border-color);
    color: var(--bs-secondary-color);
}
.tox .tox-edit-area__iframe {
    background-color: var(--bs-body-bg) !important;
}
/* Toolbar buttons.
   The skin gives every .tox-tbtn its own background:#222f3e, which sits as a
   visible blue-slate box on the retinted toolbar - they need to be transparent
   so the toolbar surface shows through, the way oxide looks in light mode.

   Colour is set via `color`, never `fill`: the skin already declares
   `.tox .tox-tbtn svg{fill:currentColor!important}`, so setting fill directly
   fights its own model and, worse, overrides the forecolor swatch that is
   supposed to show the currently selected text colour. */
.tox .tox-tbtn,
.tox .tox-mbtn,
.tox .tox-split-button {
    background: transparent !important;
    color: var(--bs-body-color) !important;
}
.tox .tox-tbtn:hover,
.tox .tox-mbtn:hover,
.tox .tox-tbtn:focus,
.tox .tox-split-button:hover {
    background: var(--bs-secondary-bg) !important;
    color: var(--bs-emphasis-color) !important;
}
.tox .tox-tbtn--enabled,
.tox .tox-tbtn--enabled:hover,
.tox .tox-tbtn.tox-tbtn--active {
    background: var(--itflow-accent, #007bff) !important;
    color: #fff !important;
}
/* light accents need a dark glyph - same L>0.335 cut as the buttons */
.theme-yellow .tox .tox-tbtn--enabled,
.theme-orange .tox .tox-tbtn--enabled,
.theme-teal .tox .tox-tbtn--enabled,
.theme-yellow .tox .tox-tbtn.tox-tbtn--active,
.theme-orange .tox .tox-tbtn.tox-tbtn--active,
.theme-teal .tox .tox-tbtn.tox-tbtn--active {
    color: #000 !important;
}
.theme-yellow .tox .tox-mbtn--active,
.theme-orange .tox .tox-mbtn--active,
.theme-teal .tox .tox-mbtn--active {
    color: #000 !important;
}
.theme-yellow .tox .tox-collection__item--active,
.theme-orange .tox .tox-collection__item--active,
.theme-teal .tox .tox-collection__item--active,
.theme-yellow .tox .tox-collection__item--enabled,
.theme-orange .tox .tox-collection__item--enabled,
.theme-teal .tox .tox-collection__item--enabled {
    color: #000 !important;
}
/* Form controls that live IN the toolbar - the Styles listbox is the obvious
   one - keep their own #2b3b4e fill and #161f29 border. Matched to .form-select
   / .form-control instead so they read as the same kind of control as the rest
   of the app. */
.tox .tox-listboxfield .tox-listbox--select,
.tox .tox-textfield,
.tox .tox-toolbar-textfield,
.tox .tox-textarea {
    background-color: var(--bs-body-bg) !important;
    border-color: var(--bs-border-color) !important;
    border-radius: var(--bs-border-radius) !important;
    color: var(--bs-body-color) !important;
}
.tox .tox-listboxfield .tox-listbox--select:focus,
.tox .tox-textfield:focus,
.tox .tox-toolbar-textfield:focus,
.tox .tox-textarea:focus {
    border-color: var(--itflow-accent, #007bff) !important;
    box-shadow: 0 0 0 .25rem color-mix(in srgb, var(--itflow-accent, #007bff) 25%, transparent) !important;
}
/* the caret and label inside those controls */
.tox .tox-listboxfield .tox-listbox--select,
.tox .tox-tbtn__select-chevron {
    color: var(--bs-body-color) !important;
}
.tox .tox-label,
.tox .tox-toolbar-label {
    color: var(--bs-secondary-color) !important;
}
/* the Styles button face - 'styles' is in every ITFlow toolbar */
.tox .tox-tbtn--bespoke {
    background: var(--bs-body-bg) !important;
    border: var(--bs-border-width) solid var(--bs-border-color) !important;
    border-radius: var(--bs-border-radius) !important;
}
.tox .tox-tbtn--bespoke:hover {
    background: var(--bs-secondary-bg) !important;
}
.tox .tox-tbtn__select-label {
    color: var(--bs-body-color) !important;
}
/* menubar active state was a fixed #599fef blue */
.tox .tox-mbtn--active,
.tox .tox-mbtn:not(:disabled).tox-mbtn--active:focus {
    background: var(--itflow-accent, #007bff) !important;
    color: #fff !important;
}
/* split buttons (forecolor, backcolor) - the focus fill was a fixed #222f3e */
.tox .tox-split-button:hover,
.tox .tox-split-button__main:focus,
.tox .tox-split-button__chevron:focus {
    background: var(--bs-secondary-bg) !important;
    color: var(--bs-body-color) !important;
}
/* disabled toolbar items */
.tox .tox-tbtn--disabled,
.tox .tox-tbtn:disabled {
    color: var(--bs-secondary-color) !important;
}

/* focus ring, so the editor matches every other focused input */
.tox.tox-tinymce.tox-edit-focus,
.tox.tox-tinymce:focus-within {
    border-color: var(--itflow-accent, #007bff);
    box-shadow: 0 0 0 .25rem color-mix(in srgb, var(--itflow-accent, #007bff) 25%, transparent);
}
/* TinyMCE also draws its own focus box inside the editor - a fixed blue
   (#006ce7) border on .tox-edit-area::before - so on any other theme a blue
   box sat inside the theme-coloured ring. The ring above is the one every
   input gets, so the inner box goes. */
.tox:not(.tox-tinymce-inline) .tox-edit-area::before {
    display: none;
}
/* menus and dropdowns the toolbar opens */
.tox .tox-menu,
.tox .tox-collection--list .tox-collection__group {
    background-color: var(--bs-body-bg) !important;
    border-color: var(--bs-border-color) !important;
}
.tox .tox-collection__item {
    color: var(--bs-body-color) !important;
}
.tox .tox-collection__item--active,
.tox .tox-collection__item--enabled {
    background-color: var(--itflow-accent, #007bff) !important;
    color: #fff !important;
}

/* --- Select picker - js/itflow_select.js ---------------------------------
   Every <select class="select2">. The field is a .form-select, so height,
   border, chevron, focus ring and dark mode all come from Bootstrap; this
   adds what goes inside it and the panel that opens under it.

   Before the script runs the browser paints the raw <select>. A single select
   looks the same either way, but a multiple one renders as a four-row listbox
   (~100px) that would collapse to a one-line field and yank the form up. So
   it is held at field height with its text hidden until the picker takes
   over (.itflow-select-native). If the script never runs, the delayed reveal
   brings the plain control back after 3s so the form stays usable. */
select.select2[multiple]:not(.itflow-select-native) {
    height: calc(1.5em + .75rem + calc(var(--bs-border-width) * 2));
    overflow-y: auto;
    visibility: hidden;
    animation: itflowRevealUninitSelect 1ms linear 3s forwards;
}
@keyframes itflowRevealUninitSelect {
    to { visibility: visible; }
}

.itflow-select {
    position: relative;
    display: block;
    width: 100%;
    min-width: 0;
}
/* The real <select> stays in the form, under the field, for posting and for
   the browser's "please select an item" bubble - just not seen or clicked */
.itflow-select > select.itflow-select-native {
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 1px;
    min-height: 0;
    padding: 0;
    border: 0;
    opacity: 0;
    pointer-events: none;
}
.itflow-select-control {
    display: flex;
    align-items: center;
    gap: .375rem;
    min-height: calc(1.5em + .75rem + calc(var(--bs-border-width) * 2));
    cursor: pointer;
    user-select: none;
    text-align: start;
}
.itflow-select-control:focus,
.itflow-select.is-open > .itflow-select-control {
    border-color: var(--itflow-accent, #86b7fe);
    outline: 0;
    box-shadow: 0 0 0 .25rem color-mix(in srgb, var(--itflow-accent, #0d6efd) 25%, transparent);
}
.itflow-select.is-disabled > .itflow-select-control {
    cursor: default;
    color: var(--bs-secondary-color);
    background-color: var(--bs-secondary-bg);
}
.itflow-select.is-invalid > .itflow-select-control,
.itflow-select.is-invalid-class > .itflow-select-control,
.was-validated .itflow-select:has(> select:invalid) > .itflow-select-control {
    border-color: var(--bs-form-invalid-border-color);
}
.itflow-select-value {
    display: flex;
    align-items: center;
    gap: .5rem;
    min-width: 0;
    flex: 1 1 auto;
}
.itflow-select-value .itflow-select-label {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.itflow-select-placeholder,
.itflow-select-label.is-none {
    color: var(--bs-secondary-color);
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
/* × to put the field back to its "nothing" option - only on optional fields */
.itflow-select.is-clearable > .itflow-select-control {
    padding-right: 3.5rem;
}
.itflow-select-clear {
    position: absolute;
    top: 50%;
    right: 2.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.25rem;
    height: 1.25rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    font-size: .7rem;
    color: var(--bs-secondary-color);
    background: transparent;
    transform: translateY(-50%);
    opacity: 0;
}
.itflow-select:hover .itflow-select-clear,
.itflow-select-control:focus .itflow-select-clear,
.itflow-select.is-open .itflow-select-clear {
    opacity: 1;
}
.itflow-select-clear:hover {
    color: var(--bs-body-color);
    background: var(--bs-secondary-bg);
}

/* Multiple: chips in the field */
.itflow-select.is-multiple > .itflow-select-control {
    flex-wrap: wrap;
    gap: .25rem;
    padding-top: .25rem;
    padding-bottom: .25rem;
    padding-left: .375rem;
}
.itflow-select.is-multiple .itflow-select-placeholder {
    padding-left: .375rem;
}
.itflow-select-chip {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    max-width: 100%;
    height: 1.625rem;
    padding: 0 .25rem 0 .55rem;
    border: 1px solid var(--bs-border-color-translucent);
    border-radius: 2rem;
    font-size: .8125rem;
    color: var(--bs-body-color);
    background: var(--bs-tertiary-bg);
}
.itflow-select-chip.has-lead {
    padding-left: .2rem;
}
.itflow-select-chip.is-more {
    padding-right: .55rem;
    color: var(--bs-secondary-color);
}
.itflow-select-chip-label {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.itflow-select-chip .itflow-select-avatar,
.itflow-select-chip .itflow-select-badge {
    width: 1.25rem;
    height: 1.25rem;
    font-size: .55rem;
}
.itflow-select-chip .itflow-select-dot {
    margin: 0 .15rem 0 .3rem;
}
.itflow-select-chip-remove {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 1.125rem;
    height: 1.125rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    font-size: .6rem;
    color: var(--bs-secondary-color);
    background: transparent;
}
.itflow-select-chip-remove:hover {
    color: var(--bs-body-color);
    background: var(--bs-secondary-bg);
}

/* In an .input-group the picker is the flexible middle piece */
.input-group > .itflow-select {
    flex: 1 1 auto;
    width: 1%;
}
.input-group > .itflow-select:focus-within,
.input-group > .itflow-select.is-open {
    z-index: 5;
}
.input-group > .itflow-select:not(:first-child) > .itflow-select-control {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
}
.input-group > .itflow-select:not(:last-child) > .itflow-select-control {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}

/* Pictures, tiles, dots and icons in front of a label */
.itflow-select-avatar {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 50%;
    font-size: .6rem;
    font-weight: 600;
    letter-spacing: .02em;
    object-fit: cover;
}
.itflow-select-avatar.is-tile {
    border-radius: var(--bs-border-radius-sm);
}
.itflow-select-control .itflow-select-avatar,
.itflow-select-control .itflow-select-badge {
    width: 1.375rem;
    height: 1.375rem;
}
.itflow-select-dot {
    flex: 0 0 auto;
    width: .625rem;
    height: .625rem;
    margin: 0 .3125rem;
    border-radius: 50%;
    background-color: var(--itflow-select-color, var(--bs-secondary));
    box-shadow: 0 0 0 1px rgba(0, 0, 0, .08);
}
.itflow-select-badge {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: var(--bs-border-radius);
    font-size: .65rem;
    color: #fff;
    background-color: var(--itflow-select-color, var(--bs-secondary));
}
/* A tag's - its icon in its colour on a wash of it, as its pill looks (tagOptionLook()) */
.itflow-select-badge.is-soft {
    color: var(--itflow-select-color, var(--bs-secondary));
    color: color-mix(in oklab, var(--itflow-select-color, var(--bs-secondary)) var(--itflow-tag-ink, 75%), var(--bs-emphasis-color));
    background-color: var(--bs-tertiary-bg);
    background-color: color-mix(in srgb, var(--itflow-select-color, var(--bs-secondary)) 14%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--itflow-select-color, var(--bs-secondary)) 40%, var(--bs-border-color));
}
.itflow-select-icon {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 1.25rem;
    color: var(--bs-secondary-color);
}

/* The panel */
.itflow-select-panel {
    position: fixed;
    z-index: 1075;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    font-size: .9375rem;
    color: var(--bs-body-color);
    background: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color-translucent);
    border-radius: var(--bs-border-radius-lg);
    box-shadow: 0 .75rem 2rem rgba(0, 0, 0, .14), 0 .125rem .375rem rgba(0, 0, 0, .06);
    animation: itflowSelectIn .12s ease-out;
}
[data-bs-theme="dark"] .itflow-select-panel {
    background: var(--bs-tertiary-bg);
    box-shadow: 0 .75rem 2rem rgba(0, 0, 0, .5);
}
.itflow-select-panel.is-above {
    animation-name: itflowSelectInAbove;
}
@keyframes itflowSelectIn {
    from { opacity: 0; transform: translateY(-4px); }
}
@keyframes itflowSelectInAbove {
    from { opacity: 0; transform: translateY(4px); }
}
/* Above the list: what it is for, and Cancel (Done where several are ticked) to close it */
.itflow-select-sheet-head {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    padding: .25rem .375rem .25rem .875rem;
    border-bottom: 1px solid var(--bs-border-color-translucent);
    font-size: .8125rem;
    color: var(--bs-secondary-color);
}
.itflow-select-sheet-title {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.itflow-select-sheet-head + .itflow-select-search {
    border-top: 0;
}
/* The tag picker's Done is in its footer, beside what it tagged */
.itflow-tag-panel:not(.is-sheet) .itflow-select-sheet-head {
    display: none;
}
.itflow-select-search {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .5rem .75rem;
    border-bottom: 1px solid var(--bs-border-color-translucent);
    color: var(--bs-secondary-color);
    font-size: .875rem;
}
.itflow-select-search[hidden] {
    display: none;
}
.itflow-select-search input {
    flex: 1 1 auto;
    min-width: 0;
    padding: .125rem 0;
    border: 0;
    outline: 0;
    font-size: .9375rem;
    color: var(--bs-body-color);
    background: transparent;
}
.itflow-select-search input::placeholder {
    color: var(--bs-secondary-color);
}
.itflow-select-list {
    max-height: 18rem;
    padding: .25rem;
    overflow-y: auto;
    overscroll-behavior: contain;
}
.itflow-select-option {
    display: flex;
    align-items: center;
    gap: .625rem;
    min-height: 2.25rem;
    padding: .375rem .625rem;
    border-radius: var(--bs-border-radius);
    cursor: pointer;
    user-select: none;
}
.itflow-select-option.is-active {
    background: var(--bs-secondary-bg);
}
.itflow-select-option.is-disabled {
    cursor: default;
    opacity: .5;
}
.itflow-select-option.is-none .itflow-select-label {
    color: var(--bs-secondary-color);
}
.itflow-select-text {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    min-width: 0;
    line-height: 1.3;
}
.itflow-select-text .itflow-select-label {
    overflow-wrap: anywhere;
}
.itflow-select-description {
    font-size: .8125rem;
    color: var(--bs-secondary-color);
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.itflow-select-option mark {
    padding: 0;
    color: inherit;
    font-weight: 600;
    background: color-mix(in srgb, var(--itflow-accent, #0d6efd) 16%, transparent);
    border-radius: 2px;
}
.itflow-select-option.is-selected .itflow-select-label {
    font-weight: 600;
}
.itflow-select-tick {
    flex: 0 0 auto;
    font-size: .8rem;
    color: var(--itflow-accent, var(--bs-primary));
    visibility: hidden;
}
.itflow-select-option.is-selected .itflow-select-tick {
    visibility: visible;
}
/* Multiple: a checklist */
.itflow-select-checkbox {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 1rem;
    height: 1rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .3rem;
    font-size: .6rem;
    color: transparent;
    background: var(--bs-body-bg);
}
.itflow-select-option.is-selected .itflow-select-checkbox {
    border-color: var(--itflow-accent, var(--bs-primary));
    color: #fff;
    background: var(--itflow-accent, var(--bs-primary));
}
.theme-yellow .itflow-select-option.is-selected .itflow-select-checkbox,
.theme-orange .itflow-select-option.is-selected .itflow-select-checkbox,
.theme-teal .itflow-select-option.is-selected .itflow-select-checkbox {
    color: #000;
}
.itflow-select-create .itflow-select-icon {
    color: var(--itflow-accent, var(--bs-primary));
}
.itflow-select-group {
    padding: .5rem .625rem .25rem;
    font-size: .75rem;
    font-weight: 600;
    color: var(--bs-secondary-color);
}
.itflow-select-empty,
.itflow-select-more {
    padding: .75rem .625rem;
    font-size: .875rem;
    color: var(--bs-secondary-color);
}
.itflow-select-more {
    padding-top: .375rem;
    font-size: .8125rem;
}
.itflow-select-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: .25rem .375rem .25rem .875rem;
    border-top: 1px solid var(--bs-border-color-translucent);
    font-size: .8125rem;
    color: var(--bs-secondary-color);
}
.itflow-select-footer .btn,
.itflow-select-done {
    --bs-btn-padding-y: .125rem;
    text-decoration: none;
}

/* Phones: the panel comes up from the bottom of the screen */
.itflow-select-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1074;
    background: rgba(0, 0, 0, .35);
    animation: itflowSelectFade .15s ease-out;
}
.itflow-select-panel.is-sheet {
    top: auto !important;
    right: 0;
    bottom: 0;
    left: 0 !important;
    width: auto !important;
    max-height: 80vh;
    padding-bottom: env(safe-area-inset-bottom);
    border-width: 1px 0 0;
    border-radius: 1rem 1rem 0 0;
    font-size: 1rem;
    animation: itflowSelectUp .2s ease-out;
}
.itflow-select-panel.is-sheet .itflow-select-sheet-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: .75rem .75rem .5rem 1rem;
    border-bottom: 0;
    font-size: inherit;
    font-weight: 600;
    color: var(--bs-body-color);
}
.itflow-select-panel.is-sheet .itflow-select-sheet-head + .itflow-select-search {
    border-top: 1px solid var(--bs-border-color-translucent);
}
.itflow-select-panel.is-sheet .itflow-select-list {
    flex: 1 1 auto;
    max-height: none;
}
.itflow-select-panel.is-sheet .itflow-select-option {
    min-height: 2.75rem;
}
.itflow-select-panel.is-sheet .itflow-select-search input {
    font-size: 1rem;
}
@keyframes itflowSelectUp {
    from { transform: translateY(100%); }
}
@keyframes itflowSelectFade {
    from { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
    .itflow-select-panel,
    .itflow-select-backdrop {
        animation: none;
    }
}

/* --- Muted contextual palette for dark mode ------------------------------
   AdminLTE 3 swapped in softer variants of the contextual colours whenever
   dark mode was on, so a success badge or a danger button did not glare off a
   dark surface. Bootstrap 5 does not do this - it keeps one palette for both
   modes. These are v3's own dark-mode values, taken from its
   .dark-mode .card-<colour> > .card-header rules.

   Overriding --bs-<colour> and its -rgb pair carries the change through every
   consumer at once: .bg-*, .text-*, .text-bg-*, .border-*, badges and tables.
   Buttons are handled separately below because .btn-* hardcodes its own hex
   rather than reading the theme colour.

   --bs-primary is deliberately left alone: btn-primary already follows
   --itflow-accent, and moving --bs-primary would fight that. */
[data-bs-theme=dark] {
    --bs-success: #00bc8c;
    --bs-success-rgb: 0, 188, 140;
    --bs-info: #3498db;
    --bs-info-rgb: 52, 152, 219;
    --bs-warning: #f39c12;
    --bs-warning-rgb: 243, 156, 18;
    --bs-danger: #e74c3c;
    --bs-danger-rgb: 231, 76, 60;
}
/* .text-bg-* hardcodes its foreground, so the pairs that changed lightness
   need re-stating. Same L>0.335 cut used everywhere else: the muted success
   (L=0.379) and warning (L=0.429) take dark text, info and danger keep white. */
[data-bs-theme=dark] .text-bg-success {
    color: #000;
}
[data-bs-theme=dark] .text-bg-info,
[data-bs-theme=dark] .text-bg-danger {
    color: #fff;
}

/* Contextual table rows hardcode a pale tint plus black text, which is
   unreadable on a dark table. ITFlow uses danger/warning/primary/secondary. */
[data-bs-theme=dark] .table-danger,
[data-bs-theme=dark] .table-warning,
[data-bs-theme=dark] .table-primary,
[data-bs-theme=dark] .table-secondary {
    --bs-table-color: var(--bs-body-color);
    --bs-table-striped-color: var(--bs-body-color);
    --bs-table-active-color: var(--bs-body-color);
    --bs-table-hover-color: var(--bs-body-color);
    --bs-table-border-color: var(--bs-border-color);
}
[data-bs-theme=dark] .table-danger {
    --bs-table-bg: rgba(231, 76, 60, .22);
}
[data-bs-theme=dark] .table-warning {
    --bs-table-bg: rgba(243, 156, 18, .22);
}
[data-bs-theme=dark] .table-primary {
    --bs-table-bg: rgba(63, 103, 145, .28);
}
[data-bs-theme=dark] .table-secondary {
    --bs-table-bg: rgba(108, 117, 125, .25);
}

/* Buttons hardcode their own hex instead of reading --bs-<colour>. */
[data-bs-theme=dark] .btn-success {
    --bs-btn-color: #000;
    --bs-btn-bg: #00bc8c;
    --bs-btn-border-color: #00bc8c;
    --bs-btn-hover-color: #000;
    --bs-btn-hover-bg: #26c69d;
    --bs-btn-hover-border-color: #1ac295;
    --bs-btn-active-color: #000;
    --bs-btn-active-bg: #33cda3;
    --bs-btn-active-border-color: #1ac295;
    --bs-btn-disabled-color: #000;
    --bs-btn-disabled-bg: #00bc8c;
    --bs-btn-disabled-border-color: #00bc8c;
}
[data-bs-theme=dark] .btn-info {
    --bs-btn-color: #fff;
    --bs-btn-bg: #3498db;
    --bs-btn-border-color: #3498db;
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: #2c81ba;
    --bs-btn-hover-border-color: #2a7aaf;
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: #2a7aaf;
    --bs-btn-active-border-color: #2772a4;
    --bs-btn-disabled-color: #fff;
    --bs-btn-disabled-bg: #3498db;
    --bs-btn-disabled-border-color: #3498db;
}
[data-bs-theme=dark] .btn-warning {
    --bs-btn-color: #000;
    --bs-btn-bg: #f39c12;
    --bs-btn-border-color: #f39c12;
    --bs-btn-hover-color: #000;
    --bs-btn-hover-bg: #f5ab36;
    --bs-btn-hover-border-color: #f4a62a;
    --bs-btn-active-color: #000;
    --bs-btn-active-bg: #f5b041;
    --bs-btn-active-border-color: #f4a62a;
    --bs-btn-disabled-color: #000;
    --bs-btn-disabled-bg: #f39c12;
    --bs-btn-disabled-border-color: #f39c12;
}
[data-bs-theme=dark] .btn-danger {
    --bs-btn-color: #fff;
    --bs-btn-bg: #e74c3c;
    --bs-btn-border-color: #e74c3c;
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: #c44133;
    --bs-btn-hover-border-color: #b93d30;
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: #b93d30;
    --bs-btn-active-border-color: #ae392d;
    --bs-btn-disabled-color: #fff;
    --bs-btn-disabled-bg: #e74c3c;
    --bs-btn-disabled-border-color: #e74c3c;
}
/* outline variants read --bs-<colour>, so they follow automatically apart
   from the foreground on hover */
[data-bs-theme=dark] .btn-outline-success:hover,
[data-bs-theme=dark] .btn-outline-warning:hover {
    --bs-btn-hover-color: #000;
}

/* --- FullCalendar --------------------------------------------------------
   v7's classic theme ships a dark palette keyed on [data-color-scheme=dark],
   which nothing was setting - that attribute is now emitted next to
   data-bs-theme in includes/header.php, so the built-in dark mode activates.

   These then pull the palette onto the app's own colours, so the calendar
   matches in BOTH modes rather than being a near-black (#030712) panel next to
   a #212529 page, and so events and the toolbar follow the theme accent. */
#calendar {
    /* Reserve the calendar's final height before it exists.

       agent/calendar.php renders an empty <div id="calendar"></div> and
       FullCalendar only fills it on DOMContentLoaded - which cannot happen
       until every parser-blocking script has run, including the 777KB
       fullcalendar.global.js that loads after the footer. Until then the div
       is zero pixels tall, so the page paints with no calendar and then snaps
       to full height, shoving everything below it down. That jump is the
       flash.

       The height is not a guess: it is the exact `height` agent/js/calendar.js
       gives the calendar on a wider screen. Matching it here means the box is
       the right size from first paint and nothing moves when the widget
       arrives. On a phone it sizes to its list instead. */
    min-height: calc(100vh - 11rem);

    --fc-classic-background: var(--bs-body-bg);
    --fc-classic-foreground: var(--bs-body-color);
    --fc-classic-muted-foreground: var(--bs-secondary-color);
    --fc-classic-border: var(--bs-border-color);
    --fc-classic-strong-border: var(--bs-border-color);

    /* events and the "primary" accent */
    --fc-classic-primary: var(--itflow-accent, #007bff);
    --fc-classic-event: var(--itflow-accent, #007bff);

    /* Only the pressed/active toolbar button is themed. FullCalendar's resting
       slate is the same in both its palettes, i.e. deliberate, and recolouring
       it to a dark grey would look wrong in light mode. */
    --fc-classic-button-strong: var(--itflow-accent, #007bff);
    --fc-classic-button-strong-border: var(--itflow-accent, #007bff);
}
/* light accents need a dark foreground on events and the active view button */
.theme-yellow #calendar,
.theme-orange #calendar,
.theme-teal #calendar {
    --fc-classic-primary-foreground: #000;
    --fc-classic-event-contrast: #000;
    --fc-classic-button-foreground: #000;
}

/* --- SweetAlert2 ----------------------------------------------------------
   v11 keys its dark palette on [data-swal2-theme=dark], an attribute it sets
   on its own container from the `theme` option - which defaults to "light",
   so the confirm dialogs stayed white in dark mode. js/confirm_modal.js now
   hands it the app's mode.

   Same treatment as FullCalendar above: its dark theme is its own near-black
   (#19191a) next to a #212529 page, so the two seed variables are repointed
   onto the app's colours. Everything else in its dark block - text, input
   background, validation message - derives from these two, so nothing further
   needs restating here. */
[data-swal2-theme=dark] {
    --swal2-dark-theme-black: var(--bs-body-bg);
    --swal2-dark-theme-white: var(--bs-body-color);

    /* The popup is borderless by default, which reads fine as a white panel on
       the backdrop but leaves a #212529 one with no edge against it. */
    --swal2-border: 1px solid var(--bs-border-color);
}

/* --- Close button focus ring ---------------------------------------------
   Bootstrap styles .btn-close on plain :focus rather than :focus-visible, so
   any programmatic or mouse-driven focus leaves a visible ring on it. Keyboard
   users still get the ring; a modal that merely opened does not. */
.btn-close:focus:not(:focus-visible) {
    box-shadow: none;
}
/* the modal container is focused on open and is not an interactive control,
   so it should never draw a ring of its own */
.modal:focus {
    outline: 0;
}

/* --- Primary colour: the two cases upstream cannot cover -------------------
   `data-lte-primary` on <body> now drives buttons, links, pagination, pills,
   dropdowns, list groups, progress, accordions and every form focus state
   from AdminLTE's own palette. --itflow-accent is still ours and still drives
   the navbar, sidebar, nav-tabs, TinyMCE, the select picker, FullCalendar and the
   theme picker.

   1. There is no `black` in AdminLTE's palette - its darkest neutral is
      gray-dark (#343a40), which is a different colour - so the same variables
      are supplied here. The generic [data-lte-primary] component rules then
      pick these up exactly as they do for a built-in colour. */
.theme-black {
    --bs-primary: #000000;
    --bs-primary-rgb: 0, 0, 0;
    --bs-link-color: #000000;
    --bs-link-color-rgb: 0, 0, 0;
    --bs-link-hover-color: #333333;
    --bs-link-hover-color-rgb: 51, 51, 51;
    --lte-primary-hover: #262626;
    --lte-primary-hover-border: #1a1a1a;
    --lte-primary-active: #1a1a1a;
    --lte-primary-active-border: #000000;
}

/* 2. AdminLTE gives teal WHITE button text (its v3 YIQ rule). White on
      #20c997 is a 2.13 contrast ratio, below the 4.5 AA threshold; black is
      9.86. Overriding their own variable keeps the dark text we had. */
.theme-teal {
    --lte-primary-color: #000000;
    --lte-primary-color-rgb: 0, 0, 0;
}

/* --- Colour inputs ---------------------------------------------------------
   Bootstrap sizes `.form-control-color` at width:3rem, but every colour input
   in ITFlow sits inside an .input-group, and `.input-group > .form-control`
   (0,2,0) sets `width: 1%; flex: 1 1 auto` - which outranks .form-control-color
   (0,1,0) and collapses the swatch to a sliver. Matching that specificity is
   the only way to win it back; the selector is strictly narrower than the one
   it ties with, so nothing but a colour input is affected.

   4rem rather than Bootstrap's 3rem: the swatch is the entire point of the
   control, and .text-sm keeps the height at the 35px of its neighbours, so
   there is only width available to read the colour by. */
.input-group > .form-control-color {
    flex: 0 0 auto;
    width: 4rem;
}

/* --- intl-tel-input --------------------------------------------------------
   The library wraps the input in a .iti container, which inside an
   .input-group becomes the flex item instead of the input. Bootstrap sizes its
   children with `.input-group > .form-control { flex: 1 1 auto; width: 1% }`,
   and that selector no longer matches the now-nested input - so without these
   the wrapper collapses to its content width and the field sits detached from
   the addon beside it.

   The wrapper takes the sizing the input used to get, and the input inside it
   is squared off on the left because .iti draws the country button there and
   the addon draws the rounded edge. */
.input-group > .iti {
    position: relative;
    flex: 1 1 auto;
    width: 1%;
    min-width: 0;
}
.input-group > .iti > .form-control {
    width: 100%;
}
.input-group > .iti:not(:last-child) > .form-control {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}
.input-group > .iti:not(:first-child) > .form-control,
.iti--separate-dial-code .form-control {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
}
/* the country button is chrome, not a control - keep it on the form-control
   palette so it does not read as a raised button in either mode */
.iti__selected-country {
    background-color: var(--bs-tertiary-bg);
    border: var(--bs-border-width) solid var(--bs-border-color);
    border-right: 0;
    border-radius: var(--bs-border-radius) 0 0 var(--bs-border-radius);
}
.iti__country-list,
.iti__dropdown-content {
    background-color: var(--bs-body-bg);
    color: var(--bs-body-color);
    border: var(--bs-border-width) solid var(--bs-border-color);
}
.iti__country.iti__highlight,
.iti__country:hover {
    background-color: var(--bs-secondary-bg);
}
.iti__dial-code {
    color: var(--bs-secondary-color);
}

/* --- Print ----------------------------------------------------------------
   AdminLTE 3 bundled Bootstrap 4, whose print reboot shrank every printout by
   declaring `@page { size: a3 }` and letting the browser scale that oversized
   page down onto the real sheet - roughly 71% on A4, 73% on Letter. Bootstrap
   5 dropped that block and AdminLTE 4 ships no page scaling of its own, so
   pages come out at 1:1 and read about 1.4x larger than they used to.
   AdminLTE 4.9.1 did add a real print block - it fixes the layout, the
   chrome and the trailing blank page, but not the scale, so this stays.

   Deliberately NOT restoring the @page rule: modern browsers treat a CSS page
   size as a paper REQUEST rather than a scale hint, so it can hand you literal
   A3 output instead of shrunken A4. Scaling the root font instead keeps the
   page at whatever paper is actually selected and lets the layout reflow to
   its real width, which suits the wide report tables better than shrinking the
   whole page ever did.

   Nothing else in the app sets a root font-size, and Bootstrap, AdminLTE and
   the .text-sm wrapper all size in rem, so this one line is the only knob:
   raise it for larger print, lower it for smaller. At 71% of a 16px default
   the app's .text-sm body text lands at ~9.9px (~7.4pt), which is what v3's
   page scaling was effectively producing. */
@media print {
    html {
        font-size: 71%;
    }

    /* AdminLTE 3 zeroed Bootstrap's card border (`border: 0 solid`) and drew
       the card's edge with a box-shadow instead - and Bootstrap 4's print
       reboot then killed box-shadows, so a printed card had no outline at all,
       just the header's own bottom rule. AdminLTE 4 gives .card a real 1px
       border, keeps the shadow, and its print block leaves cards alone, so
       both still print.

       border-WIDTH rather than the border shorthand, so .card-outline's 3px
       accent keeps its colour and can be handed its width straight back - it
       is a border-top longhand and survived v3's border:0 the same way. */
    .card {
        border-width: 0 !important;
    }
    .card.card-outline {
        border-top-width: 3px !important;
    }
    .card-footer {
        border-top-width: 0 !important;
    }

    /* Bootstrap 4 dropped every shadow when printing; they render as grey
       smudges on paper. Same rule it used, which also covers the dashboard
       small-boxes rather than cards alone. */
    *,
    *::before,
    *::after {
        box-shadow: none !important;
    }
}

/* Keep the layout viewport a constant width.

   This is what was making some navigations judder and others not. AdminLTE
   sizes .app-wrapper, .app-header, .app-main and .app-footer against 100vw,
   and 100vw INCLUDES the scrollbar, so the usable width is 100vw minus
   whatever the scrollbar takes. Nothing reserves that space, so the vertical
   scrollbar - and with it the layout width - appears and disappears purely on
   whether a given page happens to be taller than the window.

   For a view transition that is not cosmetic. ::view-transition-group(root) is
   sized to the viewport, and the UA animates the group's width and height from
   the outgoing value to the incoming one, stretching BOTH snapshots to fit for
   the whole duration and snapping at the end. Navigate between a page that
   scrolls and one that does not and every glyph on the page smears sideways by
   the scrollbar width and then jumps back.

   The client side nav is where this shows worst, because
   agent/includes/inc_client_top_head.php renders #clientHeader expanded on
   client_overview.php and collapsed everywhere else - so moving between
   Overview and any sibling page flips the scrollbar on and off almost every
   time.

   scrollbar-gutter reserves the space permanently, so the width never moves.
   The max-width correction has to come with it: with the gutter always
   present, an unqualified 100vw now overruns the layout viewport on EVERY
   page rather than only on tall ones, which would trade an intermittent
   horizontal jump for a permanent horizontal scrollbar. 100% is the width of
   the grid area these four already occupy, which is what the rule wanted.
   AdminLTE made the same correction upstream in 4.8.3. */
html {
    scrollbar-gutter: stable;
}

.app-wrapper,
.app-header,
.app-main,
.app-footer {
    max-width: 100%;
}

/* AdminLTE puts a clearfix ::after on every card header, body and footer. On a
   flex container that pseudo-element becomes an empty last flex item, and any
   gap-* utility then adds a gap after it - so the last real item (the client
   header's actions button, the overview's "View all" link) sits a gap short of
   the padding. Floats don't apply inside flex anyway, so the clearfix only
   ever does harm there. */
.card-header.d-flex::after,
.card-body.d-flex::after,
.card-footer.d-flex::after {
    content: none;
}

/* Client header - agent/includes/inc_client_top_head.php

   Initials, name and tags in one row; the name opens the panel underneath
   (#clientHeader), which holds the same columns as the overview's header. Which way the chevron points is carried by the icon class
   itself (fa-chevron-right / fa-chevron-down) - emitted by PHP for the first
   paint, swapped by the include's own script after that. Not a CSS rotation,
   so the direction cannot go stale behind a cached stylesheet. */
.itflow-client-head-main,
.itflow-client-head-toggle {
    min-width: 0;
}
.itflow-client-head-toggle {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    color: var(--bs-body-color);
    text-decoration: none;
}
.itflow-client-head-toggle:hover,
.itflow-client-head-toggle:focus-visible {
    color: var(--bs-body-color);
}
/* Name with the client type under it, together no taller than the 2rem
   initials tile beside them, so the row stays the same height */
.itflow-client-head-title {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.itflow-client-head-name {
    font-size: 1.125rem;
    font-weight: 600;
    line-height: 1.25rem;
    overflow-wrap: anywhere;
}
.itflow-client-head-type {
    font-size: .75rem;
    line-height: .75rem;
    color: var(--bs-secondary-color);
}
.client-header-chevron {
    font-size: .7rem;
    color: var(--bs-secondary-color);
}
.client-header-toggle:hover .client-header-chevron {
    color: var(--bs-body-color);
}
/* Open tickets and balance due beside the menu */
.itflow-client-head-glance {
    font-size: .875rem;
    white-space: nowrap;
}
.itflow-client-head-glance a {
    text-decoration: none;
}
/* Phone: a smaller name so most fit on one line beside the menu button, the
   tags under it, then open tickets and balance due on their own line */
@media (max-width: 767.98px) {
    .itflow-client-head-name {
        font-size: 1rem;
    }
    .itflow-client-head-glance {
        flex-basis: 100%;
    }
}

/* Search palette - js/global_search.js

   Opens over the page on Ctrl+K. Sits high rather than centred, so the
   results grow downwards from the box instead of the box jumping as they
   arrive. Everything takes its colour from the Bootstrap variables, so dark
   mode needs nothing extra; the highlighted row uses the theme accent. */
.itflow-search .modal-dialog {
    max-width: 44rem;
    margin-top: 8vh;
}
.itflow-search .modal-content {
    overflow: hidden;
    border: 0;
    box-shadow: 0 1rem 3rem rgba(0, 0, 0, .35);
}
.itflow-search-bar {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .75rem 1rem;
    border-bottom: 1px solid var(--bs-border-color);
}
.itflow-search-icon,
.itflow-search-spinner {
    flex: 0 0 auto;
    color: var(--bs-secondary-color);
}
.itflow-search-input {
    flex: 1 1 auto;
    min-width: 0;
    padding: .25rem 0;
    border: 0;
    outline: 0;
    background: transparent;
    color: var(--bs-body-color);
    font-size: 1.15rem;
}
.itflow-search-input::placeholder {
    color: var(--bs-secondary-color);
}
.itflow-search-results {
    max-height: min(60vh, 34rem);
    overflow-y: auto;
    padding: .25rem 0 .5rem;
}
.itflow-search-group {
    padding: .65rem 1rem .25rem;
    font-size: .7rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}
.itflow-search-group .fa-fw {
    margin-right: .35rem;
}
.itflow-search-item {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .45rem 1rem .45rem calc(1rem - 3px);
    border-left: 3px solid transparent;
    color: var(--bs-body-color);
    text-decoration: none;
    cursor: pointer;
}
.itflow-search-item:hover,
.itflow-search-item:focus {
    color: var(--bs-body-color);
    text-decoration: none;
}
.itflow-search-item.active {
    border-left-color: var(--itflow-accent, #007bff);
    background-color: rgba(var(--bs-emphasis-color-rgb), .06);
}
.itflow-search-item-icon {
    flex: 0 0 auto;
    color: var(--bs-secondary-color);
}
.itflow-search-item.active .itflow-search-item-icon {
    color: var(--itflow-accent, #007bff);
}
.itflow-search-item-body {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    min-width: 0;
}
/* Global search - a tag's own colour and icon in place of the group icon
   (the Tags group), and the tags a record was found by after its name */
.itflow-search-tag-icon {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 50%;
    font-size: .7rem;
    /* As a tag's pill - its icon in its colour on a wash of it */
    color: var(--itflow-tag-color, var(--bs-secondary));
    color: color-mix(in oklab, var(--itflow-tag-color, var(--bs-secondary)) var(--itflow-tag-ink, 75%), var(--bs-emphasis-color));
    background-color: var(--bs-tertiary-bg);
    background-color: color-mix(in srgb, var(--itflow-tag-color, var(--bs-secondary)) 14%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--itflow-tag-color, var(--bs-secondary)) 40%, var(--bs-border-color));
}
.itflow-search-item-title.has-tags {
    display: flex;
    align-items: center;
    gap: .375rem;
}
.itflow-search-item-text {
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.itflow-search-item-tags {
    display: inline-flex;
    flex: 0 0 auto;
    gap: .25rem;
}
.itflow-search-item-title,
.itflow-search-item-sub,
.itflow-search-item-context {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.itflow-search-item-sub,
.itflow-search-item-context {
    font-size: .8rem;
    color: var(--bs-secondary-color);
}
.itflow-search-item-aside {
    display: flex;
    flex: 0 1 auto;
    align-items: center;
    gap: .5rem;
    max-width: 40%;
}
.itflow-search-ref {
    margin-right: .5rem;
    font-family: var(--bs-font-monospace);
    font-size: .8rem;
    color: var(--bs-secondary-color);
}
.itflow-search mark {
    padding: 0;
    background: transparent;
    color: inherit;
    font-weight: 700;
}
.itflow-search-more .itflow-search-item-title,
.itflow-search-all .itflow-search-item-title {
    color: var(--bs-secondary-color);
}
.itflow-search-more.active .itflow-search-item-title,
.itflow-search-all.active .itflow-search-item-title {
    color: var(--bs-body-color);
}
.itflow-search-all {
    margin-top: .25rem;
    border-top: 1px solid var(--bs-border-color-translucent);
    padding-top: .6rem;
}
.itflow-search-empty,
.itflow-search-hint {
    padding: 1.25rem 1rem;
    text-align: center;
    color: var(--bs-secondary-color);
}
.itflow-search-empty .fa-fw {
    font-size: 1.5rem;
    margin-bottom: .5rem;
}
.itflow-search-hint {
    padding: .75rem 1rem;
    font-size: .85rem;
}
.itflow-search-footer {
    gap: 1rem;
    align-items: center;
    padding: .45rem 1rem;
    border-top: 1px solid var(--bs-border-color);
    background-color: var(--bs-tertiary-bg);
    font-size: .75rem;
    color: var(--bs-secondary-color);
}
.itflow-search kbd,
.navbar-search-kbd {
    padding: .05rem .35rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .25rem;
    background-color: var(--bs-body-bg);
    color: var(--bs-secondary-color);
    font-family: inherit;
    font-size: .7rem;
    box-shadow: none;
}
@media (max-width: 575.98px) {
    .itflow-search .modal-dialog {
        margin-top: 0;
    }
    .itflow-search .modal-content {
        display: flex;
        flex-direction: column;
    }
    .itflow-search-results {
        flex: 1 1 auto;
        max-height: none;
    }
    /* No room beside the title on a phone: client and status drop under it */
    .itflow-search-item {
        flex-wrap: wrap;
        row-gap: .15rem;
    }
    .itflow-search-item-body {
        flex: 1 1 0;
    }
    .itflow-search-item-aside {
        order: 3;
        max-width: none;
        width: 100%;
        padding-left: calc(1.25em + .75rem);
    }
}

/* The Ctrl K hint inside the top bar search box. Pointer events off so a click on
   it still lands on the box underneath and opens the palette. */
.navbar-search .navbar-search-field .navbar-search-kbd {
    position: absolute;
    top: 50%;
    right: .6rem;
    transform: translateY(-50%);
    pointer-events: none;
    background-color: transparent;
    border-color: rgba(var(--bs-emphasis-color-rgb), .25);
}
.navbar-search .navbar-search-field .form-control {
    cursor: pointer;
}

/* Full search results - agent/global_search.php. Same bold-not-yellow match
   marking as the palette, and the client column capped so a long client name
   cannot push the title off the row. */
.global-search-group mark {
    padding: 0;
    background: transparent;
    color: inherit;
    font-weight: 700;
}
.global-search-context {
    max-width: 14rem;
}
.global-search-group {
    scroll-margin-top: 4rem;
}

/* Notifications - js/notifications.js, the bell panel and agent/notifications.php

   One row design for both. The icon tile takes Bootstrap's subtle colour
   utilities (bg-*-subtle / text-*-emphasis), so each tone already has a dark
   mode version. Unread rows carry a dot and a heavier title; read rows step
   back. The read / unread button shows on hover and keyboard focus, and
   always on touch screens, where there is no hover. */
/* data-bs-theme on the panel (to escape the dark navbar) also puts Bootstrap's
   default blue links back. Carry the page's themed link colours in instead -
   resolved on body, where the theme colour and the page's mode both apply. */
body {
    --itflow-link-color: var(--bs-link-color);
    --itflow-link-color-rgb: var(--bs-link-color-rgb);
    --itflow-link-hover-color: var(--bs-link-hover-color);
    --itflow-link-hover-color-rgb: var(--bs-link-hover-color-rgb);
}
.itflow-notify-panel {
    --bs-link-color: var(--itflow-link-color);
    --bs-link-color-rgb: var(--itflow-link-color-rgb);
    --bs-link-hover-color: var(--itflow-link-hover-color);
    --bs-link-hover-color-rgb: var(--itflow-link-hover-color-rgb);
    width: min(25rem, calc(100vw - 1rem));
    overflow: hidden;
    box-shadow: 0 .75rem 2rem rgba(0, 0, 0, .25);
}
.itflow-notify-head {
    display: flex;
    align-items: center;
    padding: .75rem 1rem .25rem;
}
.itflow-notify-tabs {
    gap: 1rem;
    padding: 0 1rem;
    border-bottom: 1px solid var(--bs-border-color);
    font-size: .875rem;
}
.itflow-notify-tabs .nav-link {
    padding: .4rem 0;
    color: var(--bs-secondary-color);
}
.itflow-notify-tabs .nav-link.active {
    color: var(--bs-emphasis-color);
    border-bottom-color: var(--itflow-accent, #007bff);
}
.itflow-notify-list {
    max-height: min(65vh, 32rem);
    overflow-y: auto;
}
.itflow-notify-group {
    padding: .6rem 1rem .2rem;
    font-size: .7rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}
.itflow-notify-item {
    position: relative;
}
.itflow-notify-item .itflow-notify-link {
    display: flex;
    align-items: flex-start;
    gap: .75rem;
    padding: .6rem 2.75rem .6rem 1.75rem;
    white-space: normal;
    color: var(--bs-body-color);
    text-decoration: none;
}
.itflow-notify-item .itflow-notify-link:hover,
.itflow-notify-item .itflow-notify-link:focus {
    color: var(--bs-body-color);
    background-color: rgba(var(--bs-emphasis-color-rgb), .05);
}
.itflow-notify-icon {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    font-size: .85rem;
}
.itflow-notify-body {
    display: flex;
    flex: 1 1 0;
    flex-direction: column;
    min-width: 0;
}
.itflow-notify-top {
    display: flex;
    align-items: baseline;
    gap: .5rem;
}
.itflow-notify-type {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: .875rem;
}
.itflow-notify-time {
    flex: 0 0 auto;
    font-size: .75rem;
    color: var(--bs-secondary-color);
}
.itflow-notify-text {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    font-size: .8125rem;
    color: var(--bs-secondary-color);
    overflow-wrap: anywhere;
}
.itflow-notify-client {
    margin-top: .15rem;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: .75rem;
    color: var(--bs-secondary-color);
}
.itflow-notify-client .fa-fw {
    margin-right: .25rem;
    opacity: .7;
}
.itflow-notify-item.is-unread .itflow-notify-type {
    font-weight: 600;
    color: var(--bs-emphasis-color);
}
.itflow-notify-item.is-unread::before {
    content: "";
    position: absolute;
    top: 1.35rem;
    left: .7rem;
    width: .5rem;
    height: .5rem;
    border-radius: 50%;
    background-color: var(--itflow-accent, #007bff);
}
.itflow-notify-item:not(.is-unread) .itflow-notify-icon {
    opacity: .6;
}
.itflow-notify-toggle {
    position: absolute;
    top: .55rem;
    right: .5rem;
    width: 1.9rem;
    height: 1.9rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    color: var(--bs-secondary-color);
    opacity: 0;
}
.itflow-notify-toggle:hover,
.itflow-notify-toggle:focus-visible {
    color: var(--bs-emphasis-color);
    background-color: rgba(var(--bs-emphasis-color-rgb), .1);
}
.itflow-notify-item:hover .itflow-notify-toggle,
.itflow-notify-item:focus-within .itflow-notify-toggle {
    opacity: 1;
}
@media (hover: none) {
    .itflow-notify-toggle {
        opacity: 1;
    }
}
/* A finger needs a bigger target than a pointer: 44px on touch screens, with
   the row's text kept clear of it */
@media (pointer: coarse) {
    .itflow-notify-toggle {
        top: .3rem;
        right: .25rem;
        width: 2.75rem;
        height: 2.75rem;
    }
    .itflow-notify-item .itflow-notify-link {
        padding-right: 3.25rem;
    }
}
.itflow-notify-empty {
    padding: 2rem 1rem;
    text-align: center;
    color: var(--bs-secondary-color);
}
.itflow-notify-foot {
    display: block;
    padding: .6rem 1rem;
    border-top: 1px solid var(--bs-border-color);
    font-size: .875rem;
    text-align: center;
    text-decoration: none;
}
.itflow-notify-foot:hover {
    background-color: rgba(var(--bs-emphasis-color-rgb), .05);
}

/* The full page lists the same rows inside a card */
.itflow-notify-page .itflow-notify-item + .itflow-notify-item {
    border-top: 1px solid var(--bs-border-color-translucent);
}
.itflow-notify-page .itflow-notify-link {
    padding-top: .75rem;
    padding-bottom: .75rem;
}
.itflow-notify-page .itflow-notify-text {
    -webkit-line-clamp: 3;
}
.itflow-notify-page .itflow-notify-group {
    background-color: var(--bs-tertiary-bg);
    border-top: 1px solid var(--bs-border-color-translucent);
}
/* Bootstrap does not use Popper for dropdowns inside a navbar, so the panel is
   pinned to the bell's right edge and a phone screen cuts off its left side.
   On narrow screens it spans the width under the top bar instead. */
@media (max-width: 575.98px) {
    .app-header .navbar-nav .itflow-notify-panel[data-bs-popper] {
        position: fixed;
        top: 3rem;
        right: .5rem;
        left: .5rem;
        width: auto;
        margin-top: .25rem;
    }
}

/* Dashboard - agent/dashboard.php

   Built on cards, list-groups and Bootstrap's subtle colour utilities; this is
   only what those do not cover: the greeting and section headings, quieter
   card headers, the "Needs attention" rail, the money strip, the priority dot
   and chart heights. Every number on the page uses tabular figures so columns
   of amounts line up without a monospace font. */
.itflow-dash {
    font-variant-numeric: tabular-nums;
}
.itflow-dash-greeting {
    font-size: 1.6rem;
    font-weight: 600;
    letter-spacing: -.01em;
}
.itflow-dash-section {
    font-size: 1.125rem;
    font-weight: 600;
}
.itflow-dash .card-header {
    background: transparent;
    border-bottom: 0;
    padding-bottom: .25rem;
}
.itflow-dash .card-title {
    font-size: 1rem;
    font-weight: 600;
}
.itflow-dash .card > .list-group-flush {
    border-top: var(--bs-border-width) solid var(--bs-border-color-translucent);
}
.itflow-dash .card-header + .list-group {
    margin-top: .5rem;
}
/* Clickable rows read as normal text, not the greyed default */
.itflow-dash .list-group {
    --bs-list-group-action-color: var(--bs-body-color);
}

/* Needs attention: one card split into cells, each with a severity bar on top.
   The -1px margins tuck every cell's left/top hairline under the card edge, so
   only the lines between cells show however the row wraps. */
.itflow-dash-rail {
    display: flex;
    flex-wrap: wrap;
    margin: -1px 0 0 -1px;
}
.itflow-dash-rail-item {
    display: flex;
    flex: 1 1 10rem;
    flex-direction: column;
    gap: .15rem;
    min-width: 0;
    padding: 1rem 1.1rem .9rem;
    border-top: var(--bs-border-width) solid var(--bs-border-color-translucent);
    border-left: var(--bs-border-width) solid var(--bs-border-color-translucent);
    box-shadow: inset 0 3px 0 var(--itflow-dash-tone, var(--bs-secondary));
    color: inherit;
    text-decoration: none;
}
a.itflow-dash-rail-item:hover,
a.itflow-dash-rail-item:focus-visible {
    background-color: var(--bs-tertiary-bg);
    color: inherit;
}
.itflow-dash-rail-count {
    font-size: 1.75rem;
    font-weight: 600;
    line-height: 1.1;
}
.itflow-dash-rail-label {
    font-size: .875rem;
    font-weight: 500;
}
.itflow-dash-rail-label .fas {
    margin-right: .35rem;
}
.itflow-dash-rail-detail {
    font-size: .8rem;
    color: var(--bs-secondary-color);
}
.itflow-dash-rail-clear {
    flex-basis: 100%;
}

/* Finance: the period figures side by side, then "Right now" beside them */
.itflow-dash-money + .itflow-dash-money {
    border-top: var(--bs-border-width) solid var(--bs-border-color-translucent);
}
.itflow-dash-money a:hover,
.itflow-dash-money a:focus-visible {
    background-color: var(--bs-tertiary-bg);
}
.itflow-dash-money-value {
    margin: .1rem 0 .15rem;
    font-size: 1.5rem;
    font-weight: 600;
    line-height: 1.2;
}
.itflow-dash-now {
    border-top: var(--bs-border-width) solid var(--bs-border-color-translucent);
    background-color: var(--bs-tertiary-bg);
}
.itflow-dash-now .list-group {
    --bs-list-group-bg: transparent;
}
@media (min-width: 768px) {
    .itflow-dash-money + .itflow-dash-money {
        border-top: 0;
        border-left: var(--bs-border-width) solid var(--bs-border-color-translucent);
    }
}
@media (min-width: 992px) {
    .itflow-dash-now {
        border-top: 0;
        border-left: var(--bs-border-width) solid var(--bs-border-color-translucent);
    }
}

/* Your schedule: day headings, then time | colour mark | what */
.itflow-dash-schedule {
    border-top: var(--bs-border-width) solid var(--bs-border-color-translucent);
    margin-top: .5rem;
    padding-bottom: .4rem;
}
/* Beside the ticket list it takes that card's height and scrolls the rest;
   stacked on smaller screens it stops at a sensible height */
@media (max-width: 1199.98px) {
    .itflow-dash-schedule {
        max-height: 26rem;
        overflow-y: auto;
    }
}
@media (min-width: 1200px) {
    .itflow-dash-schedule {
        flex: 1 1 0;
        min-height: 14rem;
        overflow-y: auto;
    }
}
.itflow-dash-schedule-day {
    padding: .6rem 1rem .2rem;
    font-size: .8rem;
    font-weight: 600;
    color: var(--bs-secondary-color);
}
.itflow-dash-schedule-item {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .4rem 1rem;
    color: var(--bs-body-color);
    text-decoration: none;
}
.itflow-dash-schedule-item:hover,
.itflow-dash-schedule-item:focus-visible {
    background-color: var(--bs-tertiary-bg);
    color: var(--bs-body-color);
}
/* Earlier today - still listed, but stepped back */
.itflow-dash-schedule-item.is-past {
    opacity: .55;
}
.itflow-dash-schedule-time {
    flex: 0 0 4.25rem;
    font-size: .8rem;
    color: var(--bs-secondary-color);
    white-space: nowrap;
}
.itflow-dash-schedule-mark {
    flex: 0 0 auto;
    align-self: stretch;
    width: 3px;
    border-radius: 2px;
}

/* Ranked rows with a bar underneath: open tickets by tech, top clients */
.itflow-dash-bars {
    display: flex;
    flex-direction: column;
    gap: .35rem;
    margin-inline: -.5rem;
}
.itflow-dash-bar {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: .75rem;
    row-gap: .3rem;
    padding: .35rem .5rem;
    border-radius: var(--bs-border-radius-sm);
    color: var(--bs-body-color);
    text-decoration: none;
}
.itflow-dash-bar:hover,
.itflow-dash-bar:focus-visible {
    background-color: var(--bs-tertiary-bg);
    color: var(--bs-body-color);
}
.itflow-dash-bar-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.itflow-dash-bar-value {
    font-weight: 600;
    white-space: nowrap;
}
.itflow-dash-bar-track {
    display: flex;
    grid-column: 1 / -1;
    height: .375rem;
    overflow: hidden;
    border-radius: 1rem;
    background-color: var(--bs-secondary-bg);
}
.itflow-dash-bar-fill {
    height: 100%;
    background-color: var(--itflow-accent);
}

/* Receivables aging: one bar split by lateness, green through to deep red */
.itflow-dash-aging {
    display: flex;
    gap: 2px;
    height: .75rem;
    overflow: hidden;
    border-radius: 1rem;
    background-color: var(--bs-secondary-bg);
}
.itflow-dash-age-current {
    background-color: var(--bs-success);
}
.itflow-dash-age-1-30 {
    background-color: var(--bs-warning);
}
.itflow-dash-age-31-60 {
    background-color: var(--bs-orange);
}
.itflow-dash-age-61-90 {
    background-color: var(--bs-danger);
}
.itflow-dash-age-90plus {
    background-color: #842029;
}
[data-bs-theme=dark] .itflow-dash-age-90plus {
    background-color: #a52834;
}

.itflow-dash-dot {
    flex: 0 0 auto;
    width: .55rem;
    height: .55rem;
    border-radius: 50%;
}
/* Urgent is "dark" everywhere else in the ticket lists - invisible on a dark page */
[data-bs-theme=dark] .itflow-dash-dot.bg-dark {
    background-color: var(--bs-emphasis-color) !important;
}
.itflow-dash-chart {
    position: relative;
    height: 240px;
}
.itflow-dash-chart-donut {
    height: 180px;
}
.itflow-dash-donut-total {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    line-height: 1.25;
    pointer-events: none;
}
.itflow-dash-donut-total [data-donut-total] {
    font-size: 1.2rem;
}
.itflow-dash-legend {
    margin-inline: -.4rem;
    font-size: .85rem;
}
.itflow-dash-legend li {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .2rem .4rem;
    border-radius: var(--bs-border-radius-sm);
}
.itflow-dash-legend li:hover {
    background-color: var(--bs-tertiary-bg);
}
.itflow-dash-legend-swatch {
    flex: 0 0 auto;
    width: .6rem;
    height: .6rem;
    border-radius: 50%;
}
.itflow-dash-legend-label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.itflow-dash-legend-value {
    white-space: nowrap;
}
.itflow-dash-legend-share {
    flex: 0 0 2.5rem;
    text-align: right;
    color: var(--bs-secondary-color);
}
.itflow-dash-chart-lg {
    height: 300px;
}
.itflow-dash-chart-sm {
    min-height: 150px;
}

/* Clients list - agent/clients.php

   Rows are a table with Bootstrap's own utilities; this is only the initials
   tile beside each name (also used at the top of the client side nav), the
   small tag pills under it, and a tint on rows ticked for a bulk action. */
.itflow-client-avatar {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--bs-border-radius-lg);
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: .02em;
}
/* Tags - functions/tags.php tagPills() and tagPill(), on every list and detail
   page that has them, and global search. A pill opens the list filtered to that tag; the dashed "+" at the end
   opens the tag picker (js/tag_picker.js). The group sits above stretched-link
   row and cell links so the pills stay clickable on top of them. */
.itflow-tags {
    position: relative;
    z-index: 2;
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .25rem;
    max-width: 100%;
    vertical-align: middle;
}
/*
 * A tag's colour (--itflow-tag-color, tagColor()) is its accent, not its fill:
 * a faint wash of it, a hairline of it and its icon in it, with the name in
 * the page's own text colour - so a row of tags reads as labels beside the
 * record rather than the loudest thing on the page, in light and dark alike.
 * The icon is the colour taken part of the way to the text colour - further
 * in dark, where the darkest tags would otherwise sink - so a pale one still
 * shows on white and a dark one on dark, and the hairline starts from the
 * page's own border colour so even a near-black tag has an edge. Where
 * color-mix() isn't known, the plain lines before each give a neutral pill.
 */
.itflow-tag {
    --itflow-tag-tint: var(--itflow-tag-color, var(--bs-secondary));
    --itflow-tag-ink: 75%;
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    padding: .0625rem .5rem .0625rem .4rem;
    border: 1px solid var(--bs-border-color);
    border-color: color-mix(in srgb, var(--itflow-tag-tint) 40%, var(--bs-border-color));
    border-radius: 1rem;
    font-size: .75rem;
    font-weight: 500;
    line-height: 1.4;
    color: var(--bs-body-color);
    background-color: var(--bs-tertiary-bg);
    background-color: color-mix(in srgb, var(--itflow-tag-tint) 10%, transparent);
    text-decoration: none;
    white-space: nowrap;
    transition: background-color .15s, border-color .15s;
}
.itflow-tag > i {
    color: var(--itflow-tag-tint);
    color: color-mix(in oklab, var(--itflow-tag-tint) var(--itflow-tag-ink), var(--bs-emphasis-color));
}
[data-bs-theme="dark"] .itflow-tag,
[data-bs-theme="dark"] .itflow-search-tag-icon,
[data-bs-theme="dark"] .itflow-select-badge.is-soft {
    --itflow-tag-ink: 55%;
}
a.itflow-tag:hover,
a.itflow-tag:focus-visible {
    color: var(--bs-emphasis-color);
    border-color: color-mix(in srgb, var(--itflow-tag-tint) 65%, var(--bs-border-color));
    background-color: color-mix(in srgb, var(--itflow-tag-tint) 18%, transparent);
}
.itflow-tag-add {
    color: var(--bs-secondary-color);
    background-color: transparent;
    border-color: var(--bs-border-color);
    border-style: dashed;
    cursor: pointer;
}
.itflow-tag-add > i {
    color: inherit;
}
.itflow-tag-add:hover,
.itflow-tag-add:focus-visible,
.itflow-tag-add[aria-expanded="true"] {
    color: var(--itflow-accent, var(--bs-primary));
    border-color: currentColor;
    background-color: transparent;
}
/* The picker - the select picker's panel, plus the bulk note and the dash for
   a tag only some of the selected records have */
.itflow-tag-panel-note {
    padding: .5rem .75rem;
    border-bottom: 1px solid var(--bs-border-color-translucent);
    font-size: .8125rem;
    color: var(--bs-secondary-color);
}
.itflow-tag-panel .itflow-select-footer {
    gap: .25rem;
    padding-top: .375rem;
    padding-bottom: .375rem;
}
.itflow-tag-done {
    --bs-btn-padding-x: .75rem;
}
/* On a phone the sheet's own header has the Done */
.itflow-select-panel.is-sheet .itflow-tag-done {
    display: none;
}
.itflow-select-option.is-mixed .itflow-select-checkbox {
    border-color: var(--itflow-accent, var(--bs-primary));
    color: var(--itflow-accent, var(--bs-primary));
}
/* The tag window (admin/modals/tag/tag_form.php, js/tag_form.js) - round
   colour swatches ticked when chosen, and a grid of icons to pick from */
.itflow-tag-swatch {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    padding: 0;
    border: 2px solid var(--bs-body-bg);
    border-radius: 50%;
    box-shadow: 0 0 0 1px var(--bs-border-color);
    font-size: .75rem;
    color: var(--itflow-tag-text, #fff);
    background-color: var(--itflow-tag-color);
}
.itflow-tag-swatch i {
    visibility: hidden;
}
.itflow-tag-swatch.active i {
    visibility: visible;
}
.itflow-tag-swatch.active,
.itflow-tag-swatch:focus-visible {
    outline: 0;
    box-shadow: 0 0 0 2px var(--itflow-accent, var(--bs-primary));
}
.itflow-tag-icons {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(2.25rem, 1fr));
    gap: .125rem;
    max-height: 10.5rem;
    overflow-y: auto;
}
.itflow-tag-icon {
    --bs-btn-padding-x: 0;
    color: var(--bs-secondary-color);
}
.itflow-tag-icon:hover {
    color: var(--bs-body-color);
    background-color: var(--bs-tertiary-bg);
}
.itflow-tag-icon.active,
.itflow-tag-icon-custom.active {
    color: #fff;
    background-color: var(--itflow-accent, var(--bs-primary));
    border-color: transparent;
}
.itflow-tag-icon-custom,
.itflow-tag-icons [data-tag-icon-none] {
    grid-column: 1 / -1;
}
/* The category window (admin/modals/category/category_form.php,
   js/category_form.js) - the tag window's swatches and icons, each with a
   "none" choice - and a category as it looks on records (categoryChip()):
   its icon, or a dot, in its colour, then its name */
.itflow-category-swatch-none {
    color: var(--bs-secondary-color);
    background-color: var(--bs-body-bg);
}
.itflow-category-swatch-none i {
    visibility: visible;
}
.itflow-category-swatch-none.active {
    color: var(--itflow-accent, var(--bs-primary));
}
.itflow-tag-icons [data-category-icon-none] {
    grid-column: 1 / -1;
}
.itflow-category {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    max-width: 100%;
    color: var(--bs-body-color);
}
.itflow-category-mark {
    flex: none;
    color: var(--bs-secondary-color);
}
.itflow-category .itflow-category-dot {
    margin-right: 0;
}
/* Admin > Roles - a role's agents as overlapping faces, and in the role
   window what a level lets them do, the lines it doesn't greyed out */
.itflow-role-agents {
    display: inline-flex;
}
.itflow-role-agents > .itflow-contact-avatar + .itflow-contact-avatar {
    margin-left: -.5rem;
}
.itflow-role-agents > .itflow-contact-avatar {
    box-shadow: 0 0 0 2px var(--bs-body-bg);
}
.itflow-role-level-list li.is-off {
    color: var(--bs-secondary-color);
    opacity: .7;
}
/* A category's icon beside its name in a list (categoryMarkHtml()) - in its
   colour, set as the dot it stands in for is */
.itflow-category-icon {
    margin-right: .3rem;
    color: var(--bs-secondary-color);
}
.itflow-category-name {
    min-width: 0;
    overflow-wrap: anywhere;
}
a:hover .itflow-category-name,
a:focus-visible .itflow-category-name {
    text-decoration: underline;
}
.itflow-category-badge {
    font-size: .8125rem;
}
/* Admin > Categories - a long kind's name shortened rather than pushing its
   count out, and dragging the kinds that keep an order into it */
@media (min-width: 768px) {
    .itflow-category-kinds .nav-link {
        min-width: 0;
    }
}
.itflow-category-grip {
    display: inline-block;
    padding: .25rem .125rem;
    cursor: grab;
    touch-action: none;
}
[data-category-sortable] .sortable-ghost > *,
[data-custom-link-sortable] .sortable-ghost > * {
    background-color: var(--bs-tertiary-bg) !important;
}
/* Admin > Custom Links - the link window's preview, drawn the way its menu
   draws it: a line of a side menu (always dark), an icon on the top bar's
   theme colour, or an item of the client portal's light top bar */
.itflow-link-preview {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem .75rem;
    padding: .5rem .75rem;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    background-color: var(--bs-tertiary-bg);
}
.itflow-link-preview-stage {
    display: flex;
    flex: 1 1 12rem;
    align-items: center;
    min-width: 0;
    padding: .35rem .5rem;
    border-radius: var(--bs-border-radius);
    background-color: #343a40;
}
.itflow-link-preview-item {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    width: 100%;
    min-width: 0;
    padding: .35rem .6rem;
    border-radius: .25rem;
    color: #c2c7d0;
}
.itflow-link-preview-item > span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.itflow-link-preview-tab {
    margin-left: auto;
    font-size: .7rem;
    opacity: .7;
}
.itflow-link-preview[data-location="2"] .itflow-link-preview-stage {
    justify-content: flex-end;
    background-color: var(--itflow-accent, #007bff);
}
.itflow-link-preview[data-location="2"] .itflow-link-preview-item {
    width: auto;
    color: #fff;
}
.itflow-link-preview[data-location="2"] .itflow-link-preview-item > span,
.itflow-link-preview[data-location="2"] .itflow-link-preview-tab,
.itflow-link-preview[data-location="3"] .itflow-link-preview-tab {
    display: none;
}
.itflow-link-preview[data-location="3"] .itflow-link-preview-stage {
    border: 1px solid var(--bs-border-color-translucent);
    background-color: var(--bs-body-bg);
}
.itflow-link-preview[data-location="3"] .itflow-link-preview-item {
    width: auto;
    color: var(--bs-secondary-color);
    font-weight: 500;
}
/* The canned response picker above a reply box - a searchable list, each
   response with a line or two of what it says - and the / menu in the reply */
.itflow-canned-menu {
    width: 30rem;
    max-width: calc(100vw - 2rem);
}
.itflow-canned-list {
    max-height: 22rem;
    overflow-y: auto;
    padding-bottom: .25rem;
}
.itflow-canned-item {
    white-space: normal;
    padding-top: .375rem;
    padding-bottom: .375rem;
}
.itflow-canned-preview {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.itflow-canned-item:active .text-body-secondary,
.itflow-canned-item.active .text-body-secondary {
    color: inherit !important;
}
/* A file that goes with a picked response - its x leaves it off */
.itflow-canned-file {
    max-width: 100%;
    font-size: .8125rem;
}
.itflow-canned-file .text-truncate {
    max-width: 16rem;
}
.itflow-canned-file .btn-close {
    width: .5rem;
    height: .5rem;
    padding: .25rem;
    background-size: .5rem;
    margin-left: .125rem;
}
.tox .itflow-canned-ac-name {
    font-weight: 600;
}
.tox .itflow-canned-ac-preview {
    font-size: .8125rem;
    opacity: .75;
    white-space: normal;
}
/* @mentions in a ticket's internal notes (functions/ticket_mention.php, js/app.js
   itflowMentionAutocompleter). The name reads as a tag; one of you stands out.
   Only in an internal note - a client's reply can't dress text up as one. */
.ticket-reply[data-reply-group="internal"] .itflow-mention {
    color: var(--itflow-accent, var(--bs-primary));
    background-color: color-mix(in srgb, var(--itflow-accent, var(--bs-primary)) 12%, transparent);
    border-radius: .25rem;
    padding: 0 .25em;
    font-weight: 500;
    white-space: nowrap;
}
.ticket-reply[data-reply-group="internal"] .itflow-mention.is-me {
    color: var(--bs-warning-text-emphasis);
    background-color: var(--bs-warning-bg-subtle);
}
/* A note opened from a mention's link lands clear of the header, and shows which it is */
.ticket-reply {
    scroll-margin-top: 4.5rem;
}
.ticket-reply:target {
    box-shadow: 0 0 0 .2rem var(--bs-warning-border-subtle);
}
/* The @ picker: a face or initials, the name, the role */
.tox .itflow-mention-ac-avatar img,
.tox img.itflow-mention-ac-avatar {
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 50%;
    object-fit: cover;
}
.tox .itflow-mention-ac-initials {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 1.75rem;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 50%;
    background-color: var(--bs-secondary-bg, #e9ecef);
    color: var(--bs-body-color, #212529);
    font-size: .75rem;
    font-weight: 600;
}
.tox .itflow-mention-ac-initials,
.tox .itflow-mention-ac-avatar {
    margin-right: .5rem;
}
.tox .itflow-mention-ac-name {
    font-weight: 600;
}
.tox .itflow-mention-ac-role {
    font-size: .8125rem;
    opacity: .75;
}
.itflow-clients-street {
    max-width: 16rem;
}
/* A row ticked for a bulk action takes a subtle theme tint - every list with
   bulk checkboxes (clients, assets, contacts, tickets...), not just clients */
.table > tbody > tr:has(.bulk-select:checked) > * {
    --bs-table-bg-state: var(--bs-primary-bg-subtle);
}

/* Quick pickers - js/quick_pick.js. A ticket's priority, assignee or billing
   badge is a button that opens a small menu under it; the menu itself is the
   select picker's panel. On the ticket page the button also carries
   .ticket-prop-edit, so it looks like the other properties there. */
.itflow-quick-pick {
    padding: 0;
    border: 0;
    border-radius: 2rem;
    font: inherit;
    color: inherit;
    background: none;
    cursor: pointer;
    transition: opacity .15s;
}
.itflow-quick-pick-list:hover .badge,
.itflow-quick-pick-list:focus-visible .badge,
.itflow-quick-pick-list[aria-expanded="true"] .badge {
    box-shadow: 0 0 0 .2rem color-mix(in srgb, var(--itflow-accent, #0d6efd) 30%, transparent);
}
.itflow-quick-pick:focus-visible {
    outline: 0;
}
.itflow-quick-pick-detail {
    border-radius: var(--bs-border-radius);
}
.itflow-quick-pick.is-saving {
    opacity: .5;
    pointer-events: none;
}
/* A brief ring on the value that just changed */
.itflow-quick-pick.is-saved .badge {
    animation: itflowQuickSaved .9s ease-out;
}
@keyframes itflowQuickSaved {
    from { box-shadow: 0 0 0 .3rem color-mix(in srgb, var(--bs-success) 45%, transparent); }
    to { box-shadow: 0 0 0 .3rem transparent; }
}
@media (prefers-reduced-motion: reduce) {
    .itflow-quick-pick.is-saved .badge {
        animation: none;
    }
}

/* Client side nav - agent/includes/client_side_nav.php: the client's initials
   and name at the top, under the "All clients" link */
/* Same width, corners and left padding as the menu links below it, so the
   tile lines up with their icons; sits right under the "All clients" bar */
.itflow-client-nav-identity {
    display: flex;
    align-items: center;
    gap: .6rem;
    margin: 0;
    padding: .35rem .8rem;
    border: 1px solid rgba(255, 255, 255, .08);
    border-radius: var(--bs-border-radius);
    background-color: rgba(255, 255, 255, .05);
}
.itflow-client-avatar-sm {
    width: 2rem;
    height: 2rem;
    border-radius: var(--bs-border-radius);
    font-size: .7rem;
}
.itflow-client-nav-identity-label {
    font-size: .65rem;
    font-weight: 600;
    letter-spacing: .05em;
    line-height: 1.2;
    text-transform: uppercase;
    color: rgba(255, 255, 255, .55);
}
/* The card is the client switcher's button (js/client_switcher.js) */
button.itflow-client-nav-identity {
    width: 100%;
    text-align: left;
    color: inherit;
    font: inherit;
    cursor: pointer;
}
button.itflow-client-nav-identity:hover,
button.itflow-client-nav-identity[aria-expanded="true"] {
    background-color: rgba(255, 255, 255, .1);
}
button.itflow-client-nav-identity:focus-visible {
    outline: 2px solid var(--itflow-accent, var(--bs-primary));
    outline-offset: 1px;
}
.itflow-client-switcher-caret {
    flex: 0 0 auto;
    margin-left: auto;
    font-size: .75rem;
    color: rgba(255, 255, 255, .45);
}
.itflow-client-switcher {
    margin-bottom: .5rem;
}
.itflow-client-switcher-menu {
    width: 100%;
    margin-top: .25rem !important;
    padding: .5rem 0 .25rem;
}
.itflow-client-switcher-list {
    max-height: min(22rem, 60vh);
    overflow-y: auto;
}
.itflow-client-switcher-item {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding-top: .3rem;
    padding-bottom: .3rem;
    font-size: .875rem;
}
.itflow-client-avatar-xs {
    width: 1.5rem;
    height: 1.5rem;
    border-radius: var(--bs-border-radius-sm);
    font-size: .6rem;
}
.itflow-client-switcher-empty {
    padding: .4rem 1rem;
    font-size: .8rem;
    color: var(--bs-secondary-color);
}
/* Long names get two lines, then an ellipsis - the full name is in the tooltip */
.itflow-client-nav-identity-name {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    font-size: .875rem;
    font-weight: 600;
    line-height: 1.25;
    color: #fff;
    overflow-wrap: anywhere;
}

/* Client overview - agent/client_overview.php

   Reuses the dashboard's pieces (quiet card headers, the attention rail, the
   schedule list, money figures); this adds the large initials tile, the small
   labels in the header, contact avatars, the notes box and the money strip. */
.itflow-client-avatar-lg {
    width: 3.5rem;
    height: 3.5rem;
    border-radius: var(--bs-border-radius-lg);
    font-size: 1.1rem;
}
/* Phone: the name stays beside the initials and the buttons drop under them */
@media (max-width: 767.98px) {
    .itflow-ov-hero-name {
        flex: 1 1 0;
    }
    .itflow-ov-hero-actions {
        flex-basis: 100%;
    }
}
.itflow-ov-label {
    margin-bottom: .25rem;
    font-size: .8rem;
    color: var(--bs-secondary-color);
}
.itflow-ov-notes {
    min-height: 12rem;
    resize: vertical;
}
/* The money strip is the attention rail's layout without the coloured bar */
.itflow-ov-stats .itflow-dash-rail-item {
    --itflow-dash-tone: transparent;
    flex-basis: 12rem;
}

/* Racks - agent/racks.php, agent/rack.php, agent/includes/rack_elevation.php

   A rack is drawn as a cabinet: dark frame, numbered rails either side and a
   bay with one CSS grid row per U. Items are placed by grid-row (PHP works out
   the row from the U and which way the rack is numbered), empty U are buttons
   that open "add here". The frame stays dark in both themes - it is a picture
   of a rack, not page chrome - so its colours are fixed rather than taken from
   the Bootstrap variables.

   The row height shrinks for tall racks so a 42U rack still fits a screen. */
.min-w-0 {
    min-width: 0;
}
.itflow-rack-pair {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 1.5rem;
}
.itflow-rack {
    --rack-u: clamp(1.3rem, calc(60rem / var(--rack-rows)), 1.75rem);
    flex: 1 1 19rem;
    max-width: 30rem;
}
.itflow-rack-cap {
    margin-bottom: .35rem;
    font-size: .7rem;
    font-weight: 600;
    letter-spacing: .08em;
    text-align: center;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}
.itflow-rack-frame {
    display: flex;
    padding: .5rem .3rem;
    border-radius: .75rem;
    background: linear-gradient(180deg, #2b3035, #212529);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .06), 0 .25rem .75rem rgba(0, 0, 0, .18);
}
.itflow-rack-rail {
    display: grid;
    flex: 0 0 1.75rem;
    grid-template-rows: repeat(var(--rack-rows), var(--rack-u));
}
.itflow-rack-rail span {
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--bs-font-monospace);
    font-size: .62rem;
    color: rgba(255, 255, 255, .42);
}
.itflow-rack-bay {
    position: relative;
    display: grid;
    flex: 1 1 auto;
    min-width: 0;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: repeat(var(--rack-rows), var(--rack-u));
    border-right: 2px solid #3a4148;
    border-left: 2px solid #3a4148;
    background-color: #15181b;
    background-image: repeating-linear-gradient(to bottom, transparent 0, transparent calc(var(--rack-u) - 1px), rgba(255, 255, 255, .05) calc(var(--rack-u) - 1px), rgba(255, 255, 255, .05) var(--rack-u));
}
.itflow-rack-slot {
    grid-column: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 1px 2px;
    padding: 0;
    border: 1px dashed transparent;
    border-radius: .3rem;
    background: transparent;
    font-size: .7rem;
    color: rgba(255, 255, 255, .85);
}
.itflow-rack-slot span {
    opacity: 0;
    transition: opacity .12s ease-in-out;
}
button.itflow-rack-slot:hover,
button.itflow-rack-slot:focus-visible {
    border-color: rgba(255, 255, 255, .35);
    background-color: rgba(255, 255, 255, .07);
    outline: 0;
}
button.itflow-rack-slot:hover span,
button.itflow-rack-slot:focus-visible span {
    opacity: 1;
}

/* Items */
.itflow-rack-item {
    position: relative;
    grid-column: 1;
    margin: 1px 2px;
    overflow: hidden;
    border-radius: .3rem;
    color: #fff;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .14), inset 0 -1px 0 rgba(0, 0, 0, .25), 0 1px 2px rgba(0, 0, 0, .45);
}
.itflow-rack-item-body {
    display: flex;
    align-items: center;
    gap: .5rem;
    width: 100%;
    height: 100%;
    padding: 0 .5rem;
    border: 0;
    background: transparent;
    font: inherit;
    text-align: left;
    color: inherit;
    text-decoration: none;
}
a.itflow-rack-item-body:hover,
button.itflow-rack-item-body:hover {
    color: inherit;
    background-color: rgba(255, 255, 255, .08);
}
.itflow-rack-item-body:focus-visible {
    outline: 2px solid #fff;
    outline-offset: -2px;
}
.itflow-rack-item-icon {
    flex: 0 0 auto;
    font-size: .8rem;
    opacity: .9;
}
.itflow-rack-item-text {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    min-width: 0;
    line-height: 1.15;
}
.itflow-rack-item-name,
.itflow-rack-item-meta {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.itflow-rack-item-name {
    font-size: .78rem;
    font-weight: 600;
}
.itflow-rack-item-meta {
    font-size: .68rem;
    opacity: .78;
}
/* One U is one line: the name, then the quieter text beside it - which gives
   way first when the line is short */
.itflow-rack-h1 .itflow-rack-item-text {
    flex-direction: row;
    align-items: baseline;
    gap: .5rem;
}
.itflow-rack-h1 .itflow-rack-item-name {
    flex: 0 1 auto;
    max-width: 75%;
}
.itflow-rack-h1 .itflow-rack-item-meta {
    flex: 1 1 0;
    min-width: 0;
}
.itflow-rack-item-pos {
    flex: 0 0 auto;
    margin-left: auto;
    font-family: var(--bs-font-monospace);
    font-size: .62rem;
    opacity: .6;
}
.itflow-rack-item-edit {
    position: absolute;
    top: 50%;
    right: .3rem;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.35rem;
    height: 1.2rem;
    margin-top: -.6rem;
    padding: 0;
    border: 0;
    border-radius: .25rem;
    background-color: rgba(0, 0, 0, .35);
    font-size: .6rem;
    color: #fff;
    opacity: 0;
    transition: opacity .12s ease-in-out;
}
.itflow-rack-item:hover .itflow-rack-item-edit,
.itflow-rack-item:focus-within .itflow-rack-item-edit {
    opacity: 1;
}
.itflow-rack-item:has(.itflow-rack-item-edit):hover .itflow-rack-item-pos {
    visibility: hidden;
}
.itflow-rack-item-edit:hover {
    background-color: rgba(0, 0, 0, .55);
}
.itflow-rack-item.is-archived {
    opacity: .55;
}
.itflow-rack-item.is-archived .itflow-rack-item-name {
    text-decoration: line-through;
}
/* A full-depth item seen from its other side: it fills this face too */
.itflow-rack-item.is-ghost {
    border: 1px dashed rgba(255, 255, 255, .16);
    background: repeating-linear-gradient(45deg, rgba(255, 255, 255, .06) 0, rgba(255, 255, 255, .06) 5px, transparent 5px, transparent 10px), #1c2024;
    color: rgba(255, 255, 255, .55);
    box-shadow: none;
}
.itflow-rack-item.is-ghost .itflow-rack-item-body {
    cursor: default;
}

/* Tones - the faceplate colour of each kind of kit, shared by the elevation,
   the mini racks on the listing, the list chips and the legend */
.itflow-rack-tone-server { background: linear-gradient(180deg, #3d72bb, #2c5891); }
.itflow-rack-tone-network { background: linear-gradient(180deg, #27907f, #1b6c60); }
.itflow-rack-tone-firewall { background: linear-gradient(180deg, #c04e4e, #963838); }
.itflow-rack-tone-power { background: linear-gradient(180deg, #b8862f, #8e6420); }
.itflow-rack-tone-device { background: linear-gradient(180deg, #6d5fc4, #5447a1); }
.itflow-rack-tone-shelf { background: linear-gradient(180deg, #6b7682, #57616c); }
.itflow-rack-tone-patch {
    background: radial-gradient(rgba(0, 0, 0, .38) 1.2px, transparent 1.7px) 0 0 / 7px 7px, linear-gradient(180deg, #4d5864, #3b444e);
}
.itflow-rack-tone-cable {
    background: repeating-linear-gradient(90deg, rgba(255, 255, 255, .08) 0, rgba(255, 255, 255, .08) 2px, transparent 2px, transparent 9px), linear-gradient(180deg, #31373d, #262b30);
}
.itflow-rack-tone-blank {
    background: repeating-linear-gradient(90deg, rgba(255, 255, 255, .05) 0, rgba(255, 255, 255, .05) 10px, transparent 10px, transparent 13px), #1f2327;
    color: rgba(255, 255, 255, .7);
}

/* Small coloured tile with the item's icon - item list, "not racked yet" */
.itflow-rack-chip {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 1.9rem;
    height: 1.9rem;
    border-radius: var(--bs-border-radius);
    font-size: .8rem;
    color: #fff;
}
.itflow-rack-legend {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: .35rem 1.1rem;
}
.itflow-rack-swatch {
    display: inline-block;
    width: .75rem;
    height: .75rem;
    margin-right: .35rem;
    border-radius: .2rem;
    vertical-align: -.1rem;
}
.itflow-rack-swatch-ghost {
    border: 1px dashed var(--bs-secondary-color);
    background: repeating-linear-gradient(45deg, var(--bs-secondary-bg) 0, var(--bs-secondary-bg) 2px, transparent 2px, transparent 4px);
}

/* Rack page header and side cards */
.itflow-rack-head-icon {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    border-radius: var(--bs-border-radius-lg);
    background: linear-gradient(180deg, #2b3035, #1c1f23);
    font-size: 1.2rem;
    color: #fff;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .08);
}
.itflow-rack-dl {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: .4rem 1rem;
    font-size: .875rem;
}
.itflow-rack-dl dt {
    font-weight: 500;
    color: var(--bs-secondary-color);
}
.itflow-rack-dl dd {
    margin: 0;
    overflow-wrap: anywhere;
}
.itflow-rack-stats .fw-semibold {
    font-size: 1.1rem;
}
.itflow-rack-photo {
    position: relative;
    display: block;
    overflow: hidden;
    border-radius: var(--bs-border-radius);
}
.itflow-rack-photo img {
    display: block;
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    transition: transform .2s ease-in-out;
}
.itflow-rack-photo:hover img {
    transform: scale(1.04);
}
.itflow-rack-photo span {
    position: absolute;
    bottom: .35rem;
    left: .35rem;
    padding: .05rem .5rem;
    border-radius: 50rem;
    background-color: rgba(0, 0, 0, .6);
    font-size: .7rem;
    color: #fff;
}
.itflow-rack-form-photo img {
    max-width: 100%;
    max-height: 8rem;
    border-radius: var(--bs-border-radius);
}
.itflow-rack-fit:empty {
    display: none;
}

/* Listing cards: the whole card opens the rack, the menu sits above that link */
.itflow-rack-card {
    transition: box-shadow .15s ease-in-out, border-color .15s ease-in-out;
}
.itflow-rack-card:hover {
    border-color: var(--itflow-accent, var(--bs-primary));
    box-shadow: 0 .25rem .9rem rgba(0, 0, 0, .1);
}
.itflow-rack-card-menu {
    position: relative;
    z-index: 2;
}
.itflow-rack-mini {
    display: grid;
    flex: 0 0 2.4rem;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: repeat(var(--rack-rows), minmax(0, 1fr));
    align-self: flex-start;
    height: clamp(5.5rem, calc(var(--rack-rows) * .32rem), 9rem);
    padding: 2px;
    border: 3px solid #2b3035;
    border-radius: .4rem;
    background-color: #15181b;
}
.itflow-rack-mini span {
    grid-column: 1;
    margin: .5px 0;
    border-radius: 1px;
}
.itflow-rack-mini span.is-ghost {
    opacity: .45;
}

@media print {
    .itflow-rack-frame,
    .itflow-rack-bay,
    .itflow-rack-item,
    .itflow-rack-chip,
    .itflow-rack-swatch,
    .itflow-rack-head-icon {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }
    .itflow-rack-slot span,
    .itflow-rack-item-edit {
        display: none;
    }
    .itflow-rack {
        --rack-u: clamp(1rem, calc(48rem / var(--rack-rows)), 1.5rem);
    }
    .itflow-rack-items,
    .itflow-rack-pair {
        break-inside: avoid;
    }
}

/* Assets - agent/assets.php, agent/asset.php, agent/modals/asset/

   Each kind of asset has a colour (functions/asset.php assetTypeTone()), used
   for the icon tile on the list, the asset page header and the related-asset
   chips. The tile is the colour at low strength with the icon at full, so it
   reads in light and dark alike. */
.itflow-asset-tone-workstation { --itflow-asset-tone: #3d72bb; }
.itflow-asset-tone-server { --itflow-asset-tone: #6d5fc4; }
.itflow-asset-tone-virtual { --itflow-asset-tone: #9a5cc6; }
.itflow-asset-tone-network { --itflow-asset-tone: #23897a; }
.itflow-asset-tone-firewall { --itflow-asset-tone: #c04e4e; }
.itflow-asset-tone-wireless { --itflow-asset-tone: #1b8fc2; }
.itflow-asset-tone-phone { --itflow-asset-tone: #b8862f; }
.itflow-asset-tone-peripheral { --itflow-asset-tone: #5b6f8a; }
.itflow-asset-tone-other { --itflow-asset-tone: #6c757d; }
.itflow-asset-tone-storage { --itflow-asset-tone: #5f7a2a; }
.itflow-asset-tone-power { --itflow-asset-tone: #b5600b; }
[data-bs-theme="dark"] .itflow-asset-tone-workstation { --itflow-asset-tone: #6f9fe0; }
[data-bs-theme="dark"] .itflow-asset-tone-server { --itflow-asset-tone: #a197ee; }
[data-bs-theme="dark"] .itflow-asset-tone-virtual { --itflow-asset-tone: #c595ea; }
[data-bs-theme="dark"] .itflow-asset-tone-network { --itflow-asset-tone: #4fc4b0; }
[data-bs-theme="dark"] .itflow-asset-tone-firewall { --itflow-asset-tone: #ec8585; }
[data-bs-theme="dark"] .itflow-asset-tone-wireless { --itflow-asset-tone: #5cc0ec; }
[data-bs-theme="dark"] .itflow-asset-tone-phone { --itflow-asset-tone: #e3b35c; }
[data-bs-theme="dark"] .itflow-asset-tone-peripheral { --itflow-asset-tone: #9fb2cc; }
[data-bs-theme="dark"] .itflow-asset-tone-other { --itflow-asset-tone: #adb5bd; }
[data-bs-theme="dark"] .itflow-asset-tone-storage { --itflow-asset-tone: #a6c46b; }
[data-bs-theme="dark"] .itflow-asset-tone-power { --itflow-asset-tone: #f2a453; }
.itflow-asset-icon {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--bs-border-radius-lg);
    background-color: color-mix(in srgb, var(--itflow-asset-tone) 14%, transparent);
    color: var(--itflow-asset-tone);
    font-size: 1.05rem;
}
.itflow-asset-icon-lg {
    width: 3.5rem;
    height: 3.5rem;
    font-size: 1.5rem;
}
.itflow-asset-icon-sm {
    width: 1.75rem;
    height: 1.75rem;
    border-radius: var(--bs-border-radius);
    font-size: .8rem;
}
img.itflow-asset-icon {
    object-fit: cover;
    background: none;
}

/* Kind-of-asset tabs above the filter bar */
.itflow-asset-tabs .nav-link {
    padding: .3rem .75rem;
    color: var(--bs-secondary-color);
}
.itflow-asset-tabs .nav-link .badge {
    background-color: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
    font-weight: 500;
}
.itflow-asset-tabs .nav-link.active .badge {
    background-color: rgba(255, 255, 255, .25);
    color: inherit;
}

/* List rows */
.itflow-asset-table td {
    padding-top: .6rem;
    padding-bottom: .6rem;
}
.itflow-asset-name-cell {
    min-width: 15rem;
}
.itflow-asset-desc {
    max-width: 18rem;
}
.itflow-asset-model-cell {
    min-width: 9rem;
}
/* Tag pills and other controls inside a cell with a stretched-link stay clickable */
.itflow-above-stretch {
    position: relative;
    z-index: 2;
}
.btn.btn-xs {
    --bs-btn-padding-y: 0;
    --bs-btn-padding-x: .4rem;
    --bs-btn-font-size: .7rem;
    --bs-btn-border-radius: var(--bs-border-radius-sm);
    font-size: .7rem;
    line-height: 1.4;
}

/* Copy button beside a value - an IP, MAC, serial, email, username, URI or a
   password. Quiet until the row or line it sits in is pointed at: a table row,
   a list-group row, a quick-look line, or just its own parent element.
   .itflow-copy-always keeps it showing where copying is the point (an MFA
   secret). Markup:
   <button type="button" class="itflow-copy clipboardjs" title="Copy IP" data-clipboard-text="..."><i class="far fa-copy"></i></button>
   Copy buttons attached to an input stay input-group buttons. */
.itflow-copy {
    margin-left: .3rem;
    padding: 0 .15rem;
    border: 0;
    background: none;
    font-size: .8em;
    color: var(--bs-secondary-color);
    opacity: 0;
    transition: opacity .12s ease-in-out;
}
tr:hover .itflow-copy,
.list-group-item:hover .itflow-copy,
.itflow-glance-item:hover .itflow-copy,
:hover > .itflow-copy,
.itflow-copy-always .itflow-copy,
.itflow-copy:focus-visible {
    opacity: 1;
}
.itflow-copy:hover {
    color: var(--bs-emphasis-color);
}
@media (hover: none) {
    .itflow-copy {
        opacity: 1;
    }
}

/* Asset page */
.itflow-asset-dl {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: .45rem 1rem;
    font-size: .875rem;
}
.itflow-asset-dl dt {
    font-weight: 500;
    color: var(--bs-secondary-color);
}
.itflow-asset-dl dd {
    margin: 0;
    overflow-wrap: anywhere;
}
.itflow-asset-pills {
    gap: .25rem;
}
.itflow-asset-related .itflow-asset-pills .nav-link {
    padding: .3rem .7rem;
    font-size: .875rem;
}
.itflow-asset-related .itflow-asset-pills .nav-link:not(.active) {
    color: var(--bs-body-color);
}
.itflow-asset-related .itflow-asset-pills .nav-link.is-empty:not(.active) {
    color: var(--bs-secondary-color);
}
.itflow-asset-pills .nav-link .badge {
    background-color: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
    font-weight: 500;
}
.itflow-asset-pills .nav-link .badge.text-bg-danger {
    background-color: var(--bs-danger) !important;
    color: #fff !important;
}
.itflow-asset-pills .nav-link.active .badge {
    background-color: rgba(255, 255, 255, .25);
    color: inherit;
}
.itflow-asset-pane-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    padding: .75rem 1rem;
    border-bottom: 1px solid var(--bs-border-color-translucent);
}
.itflow-asset-related .table > :not(caption) > * > :first-child {
    padding-left: 1rem;
}
.itflow-asset-related .table > :not(caption) > * > :last-child {
    padding-right: 1rem;
}
.itflow-asset-related .table td:first-child {
    min-width: 11rem;
}
.itflow-asset-related .table td.checkbox-column {
    min-width: 0;
}
.itflow-asset-empty {
    padding: 2.5rem 1rem;
    text-align: center;
    color: var(--bs-secondary-color);
}
/* Empty state - a list with nothing in it, or nothing its filters let
   through (emptyStateHtml()): the list's icon in a round tile, a title, a
   line on what goes there and its buttons */
.itflow-empty-state {
    padding: 3rem 1rem;
    text-align: center;
}
.itflow-empty-state-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 4rem;
    height: 4rem;
    margin-bottom: 1rem;
    border-radius: 50%;
    font-size: 1.5rem;
    background: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
}
.itflow-empty-state-title {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--bs-emphasis-color);
}
.itflow-empty-state-text {
    max-width: 34rem;
    margin: .25rem auto 0;
    font-size: .875rem;
    color: var(--bs-secondary-color);
}
.itflow-empty-state-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: .5rem;
    margin-top: 1.25rem;
}
.itflow-asset-dl .font-monospace {
    font-size: .82rem;
}

/* Section heading inside a long form (asset add/edit) */
.itflow-form-section {
    margin-bottom: .75rem;
    padding-bottom: .35rem;
    border-bottom: 1px solid var(--bs-border-color-translucent);
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}

/* Asset quick pickers - status, location and who it is assigned to, as pills
   on the assets list and in the asset page header (functions/asset.php
   assetQuickHtml), as lines in the asset page's Where & who card */
.itflow-asset-pill {
    max-width: 15rem;
    padding: .35em .7em;
    vertical-align: middle;
}
.itflow-asset-pill > .text-truncate {
    min-width: 0;
}
.itflow-asset-pill-person {
    padding: .2rem .6rem .2rem .2rem;
}
/* Nothing set yet - a dashed slot, so it reads as something to fill in */
.itflow-asset-pill-empty {
    border: 1px dashed var(--bs-border-color);
    color: var(--bs-secondary-color);
    background: transparent;
}
/* In the Where & who card, and the quick look's glance lines, the picker is
   the whole line: it lights up on hover with a chevron, like the ticket
   page's properties. The negative margin keeps its text in line with the
   plain values above and below. */
.itflow-asset-dl .itflow-quick-pick-detail,
.itflow-asset-glance .itflow-quick-pick-detail {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    width: calc(100% + 1rem);
    min-width: 0;
    margin: -.3rem -.5rem;
    padding: .3rem .5rem;
    text-align: left;
}
.itflow-asset-dl .itflow-quick-pick-detail:hover,
.itflow-asset-glance .itflow-quick-pick-detail:hover,
.itflow-asset-dl .itflow-quick-pick-detail:focus-visible,
.itflow-asset-glance .itflow-quick-pick-detail:focus-visible,
.itflow-asset-dl .itflow-quick-pick-detail[aria-expanded="true"],
.itflow-asset-glance .itflow-quick-pick-detail[aria-expanded="true"] {
    background-color: var(--bs-tertiary-bg);
}
.itflow-asset-dl .itflow-quick-pick-detail + :not(:empty),
.itflow-asset-glance .itflow-quick-pick-detail + :not(:empty) {
    margin-top: .35rem;
}
.itflow-asset-dl .ticket-prop-edit-icon,
.itflow-asset-glance .ticket-prop-edit-icon {
    flex: 0 0 auto;
    font-size: .7rem;
    color: var(--bs-secondary-color);
    opacity: 0;
    transition: opacity .15s;
}
.itflow-asset-dl .itflow-quick-pick-detail:hover .ticket-prop-edit-icon,
.itflow-asset-glance .itflow-quick-pick-detail:hover .ticket-prop-edit-icon,
.itflow-asset-dl .itflow-quick-pick-detail:focus-visible .ticket-prop-edit-icon,
.itflow-asset-glance .itflow-quick-pick-detail:focus-visible .ticket-prop-edit-icon,
.itflow-asset-dl .itflow-quick-pick-detail[aria-expanded="true"] .ticket-prop-edit-icon,
.itflow-asset-glance .itflow-quick-pick-detail[aria-expanded="true"] .ticket-prop-edit-icon {
    opacity: 1;
}
@media (hover: none) {
    .itflow-asset-dl .ticket-prop-edit-icon,
    .itflow-asset-glance .ticket-prop-edit-icon {
        opacity: .6;
    }
}
.itflow-asset-dl .itflow-quick-pick-detail.is-saved,
.itflow-asset-glance .itflow-quick-pick-detail.is-saved {
    animation: itflowAssetQuickSaved .9s ease-out;
}
@keyframes itflowAssetQuickSaved {
    from { background-color: var(--bs-success-bg-subtle); }
    to { background-color: transparent; }
}
@media (prefers-reduced-motion: reduce) {
    .itflow-asset-dl .itflow-quick-pick-detail.is-saved,
    .itflow-asset-glance .itflow-quick-pick-detail.is-saved {
        animation: none;
    }
}

/* Asset add / edit tabs - one line, scrolling sideways on a phone */
.itflow-asset-form-tabs {
    gap: .25rem;
    scrollbar-width: thin;
}
.itflow-asset-form-tabs .nav-link {
    padding-inline: .75rem;
    white-space: nowrap;
}

/* Asset quick look - agent/modals/asset/asset.php. The glance lines under the
   header: an icon in place of a label, then the value */
.itflow-asset-glance {
    font-size: .875rem;
}
.itflow-glance-item {
    display: flex;
    align-items: flex-start;
    gap: .6rem;
    min-width: 0;
    padding: .3rem 0;
}
.itflow-glance-item > .fa-fw:first-child {
    flex: 0 0 auto;
    margin-top: .2rem;
    color: var(--bs-secondary-color);
}
.itflow-glance-item .font-monospace {
    font-size: .82rem;
}
.itflow-asset-quicknote,
.itflow-contact-quicknote {
    min-height: 2.6rem;
    max-height: 12rem;
    field-sizing: content;
    border-color: transparent;
    background-color: var(--bs-tertiary-bg);
    resize: vertical;
}
.itflow-asset-quicknote:focus,
.itflow-contact-quicknote:focus {
    background-color: var(--bs-body-bg);
}
.itflow-asset-quick-related {
    padding-top: .75rem;
    border-top: 1px solid var(--bs-border-color-translucent);
}
.itflow-asset-quick-related .table,
.itflow-asset-quick-related .list-group {
    font-size: .875rem;
}
.itflow-asset-quick-related .table > :not(caption) > * > :first-child {
    padding-left: 0;
}
.itflow-asset-quick-related .table > :not(caption) > * > :last-child {
    padding-right: 0;
}
.itflow-asset-quick-related .table td:first-child {
    min-width: 0;
}
.itflow-asset-quick-related .itflow-asset-pills {
    flex-wrap: nowrap;
    gap: .15rem;
    overflow-x: auto;
    scrollbar-width: thin;
}
.itflow-asset-quick-related .itflow-asset-pills .nav-link {
    padding: .25rem .55rem;
}

/* Contacts - functions/contact.php contactAvatar(): a photo, or initials on a
   soft colour that stays the same for the person (like the client avatars) */
.itflow-contact-avatar {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: .02em;
}
img.itflow-contact-avatar {
    object-fit: cover;
}
/* contactLink(): the avatar, then the name - in a table cell, a card or a line of text */
.itflow-contact-ref {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    min-width: 0;
    max-width: 100%;
    vertical-align: middle;
}
.itflow-contact-avatar-xs {
    width: 1.25rem;
    height: 1.25rem;
    font-size: .5rem;
    letter-spacing: 0;
}
.itflow-contact-avatar-sm {
    width: 1.75rem;
    height: 1.75rem;
    font-size: .65rem;
}
.itflow-contact-avatar-md {
    width: 2rem;
    height: 2rem;
    font-size: .7rem;
}
.itflow-contact-avatar-lg {
    width: 3.5rem;
    height: 3.5rem;
    font-size: 1.1rem;
}
/* Contacts list */
.itflow-contact-table td {
    padding-top: .6rem;
    padding-bottom: .6rem;
}
.itflow-contact-name-cell {
    min-width: 16rem;
}
.itflow-contact-role {
    max-width: 20rem;
}
.itflow-contact-reach > div + div {
    margin-top: .15rem;
}
/* What is linked to a contact - a small count that opens that tab on their page */
.itflow-contact-chip {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    padding: .1rem .5rem;
    border-radius: 2rem;
    font-size: .75rem;
    color: var(--bs-body-color);
    background-color: var(--bs-secondary-bg);
    text-decoration: none;
    white-space: nowrap;
}
.itflow-contact-chip i {
    color: var(--bs-secondary-color);
    font-size: .7rem;
}
.itflow-contact-chip:hover {
    color: var(--bs-emphasis-color);
    background-color: var(--bs-tertiary-bg);
    box-shadow: inset 0 0 0 1px var(--bs-border-color);
}
.itflow-contact-chip.is-alert {
    color: var(--bs-danger-text-emphasis);
    background-color: var(--bs-danger-bg-subtle);
}
.itflow-contact-chip.is-alert i {
    color: inherit;
}

/* Files & documents - agent/files.php, agent/document.php, the file and
   document quick looks, the upload and link modals.

   A file's type is a tinted tile like an asset's type (fileTypeTile() in
   functions/files.php): the colour family says what it is at a glance -
   PDFs red, Word blue, spreadsheets green - and created documents take the
   app's own blue. */
.itflow-file-icon {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--bs-border-radius-lg);
    background-color: color-mix(in srgb, var(--itflow-file-tone) 14%, transparent);
    color: var(--itflow-file-tone);
    font-size: 1.1rem;
}
.itflow-file-icon-sm {
    width: 1.75rem;
    height: 1.75rem;
    border-radius: var(--bs-border-radius);
    font-size: .8rem;
}
.itflow-file-icon-xs {
    width: 1.25rem;
    height: 1.25rem;
    border-radius: var(--bs-border-radius-sm);
    font-size: .65rem;
}
.itflow-file-icon-lg {
    width: 3.5rem;
    height: 3.5rem;
    font-size: 1.6rem;
}
.itflow-file-tone-pdf { --itflow-file-tone: #c8372d; }
.itflow-file-tone-word { --itflow-file-tone: #2b5797; }
.itflow-file-tone-excel { --itflow-file-tone: #1e7145; }
.itflow-file-tone-slides { --itflow-file-tone: #c4501c; }
.itflow-file-tone-image { --itflow-file-tone: #13857d; }
.itflow-file-tone-media { --itflow-file-tone: #8e44ad; }
.itflow-file-tone-archive { --itflow-file-tone: #8a6a2f; }
.itflow-file-tone-text { --itflow-file-tone: #5c6773; }
.itflow-file-tone-code { --itflow-file-tone: #4b5d8a; }
.itflow-file-tone-drawing { --itflow-file-tone: #d97706; }
.itflow-file-tone-cert { --itflow-file-tone: #a1781b; }
.itflow-file-tone-other { --itflow-file-tone: #6c757d; }
.itflow-file-tone-document { --itflow-file-tone: var(--itflow-accent, #0d6efd); }
[data-bs-theme="dark"] .itflow-file-tone-pdf { --itflow-file-tone: #f08a80; }
[data-bs-theme="dark"] .itflow-file-tone-word { --itflow-file-tone: #8ab4f0; }
[data-bs-theme="dark"] .itflow-file-tone-excel { --itflow-file-tone: #6fcf9a; }
[data-bs-theme="dark"] .itflow-file-tone-slides { --itflow-file-tone: #f2a072; }
[data-bs-theme="dark"] .itflow-file-tone-image { --itflow-file-tone: #5fd1c6; }
[data-bs-theme="dark"] .itflow-file-tone-media { --itflow-file-tone: #c99ae0; }
[data-bs-theme="dark"] .itflow-file-tone-archive { --itflow-file-tone: #d9b878; }
[data-bs-theme="dark"] .itflow-file-tone-text { --itflow-file-tone: #b4bec8; }
[data-bs-theme="dark"] .itflow-file-tone-code { --itflow-file-tone: #a3b3dc; }
[data-bs-theme="dark"] .itflow-file-tone-drawing { --itflow-file-tone: #f5b257; }
[data-bs-theme="dark"] .itflow-file-tone-cert { --itflow-file-tone: #e3c46b; }
[data-bs-theme="dark"] .itflow-file-tone-other { --itflow-file-tone: #adb5bd; }
[data-bs-theme="dark"] .itflow-file-tone-document { --itflow-file-tone: #8ab4f8; }

/* The folder tree beside the list */
.itflow-files-tree {
    background-color: var(--bs-tertiary-bg);
}
@media (min-width: 992px) {
    .itflow-files-tree #filesFolderTree {
        position: sticky;
        top: 4rem;
        max-height: calc(100vh - 5rem);
        overflow-y: auto;
    }
}
.itflow-folder > ul {
    display: none;
}
.itflow-folder.is-open > ul {
    display: block;
}
.itflow-folder-row {
    display: flex;
    align-items: center;
    padding-left: calc(var(--itflow-folder-depth, 0) * .9rem);
    border-radius: var(--bs-border-radius);
}
.itflow-folder-row:hover {
    background-color: var(--bs-secondary-bg);
}
.itflow-folder-row.active {
    background-color: var(--bs-primary-bg-subtle);
}
.itflow-folder-row.active .itflow-folder-link {
    color: var(--bs-primary-text-emphasis);
    font-weight: 600;
}
.itflow-folder-toggle {
    flex: 0 0 1.25rem;
    width: 1.25rem;
    padding: 0;
    border: 0;
    background: none;
    font-size: .65rem;
    color: var(--bs-secondary-color);
    transition: transform .12s ease-in-out;
}
.itflow-folder.is-open > .itflow-folder-row .itflow-folder-toggle {
    transform: rotate(90deg);
}
.itflow-folder-link {
    display: flex;
    flex: 1 1 auto;
    align-items: center;
    min-width: 0;
    padding: .3rem .4rem .3rem .1rem;
    font-size: .875rem;
    color: var(--bs-body-color);
    text-decoration: none;
}
.itflow-folder-link .fa-folder,
.itflow-folder-link .fa-folder-open,
.itflow-folder-link .fa-home {
    color: #d4a72c;
}
.itflow-folder-link .fa-home {
    color: var(--bs-secondary-color);
}
.itflow-folder-link .badge {
    background-color: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
    font-weight: 500;
}
.itflow-folder-menu .btn {
    padding: 0 .4rem;
    color: var(--bs-secondary-color);
    opacity: 0;
}
.itflow-folder-row:hover .itflow-folder-menu .btn,
.itflow-folder-menu .btn[aria-expanded="true"],
.itflow-folder-menu .btn:focus-visible {
    opacity: 1;
}
@media (hover: none) {
    .itflow-folder-menu .btn {
        opacity: 1;
    }
}

/* The list */
.itflow-files-main {
    position: relative;
}
.itflow-files-path .breadcrumb {
    font-size: .875rem;
}
.itflow-files-table td {
    padding-top: .55rem;
    padding-bottom: .55rem;
}
.itflow-files-name-cell {
    min-width: 14rem;
}
.itflow-files-desc {
    max-width: 32rem;
}
.itflow-files-linked {
    min-width: 8.5rem;
}
.itflow-files-name-cell .itflow-above-stretch {
    position: relative;
    z-index: 2;
}

/* The grid */
.itflow-file-card {
    position: relative;
    overflow: hidden;
    transition: box-shadow .12s ease-in-out;
}
.itflow-file-card:hover {
    box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .08);
}
.itflow-file-card:has(.bulk-select:checked) {
    outline: 2px solid var(--bs-primary);
    background-color: var(--bs-primary-bg-subtle);
}
.itflow-file-card-check {
    position: absolute;
    top: .4rem;
    left: .4rem;
    z-index: 3;
    display: flex;
    min-height: 0;
    margin: 0;
    padding: .2rem;
    border-radius: var(--bs-border-radius-sm);
    background-color: var(--bs-body-bg);
    box-shadow: 0 0 0 1px var(--bs-border-color-translucent);
    /* Out of the way of the preview until the card is pointed at or ticked */
    opacity: 0;
    transition: opacity .12s ease-in-out;
}
.itflow-file-card:hover .itflow-file-card-check,
.itflow-file-card-check:has(:checked),
.itflow-file-card-check:has(:focus-visible),
.itflow-files-grid:has(.bulk-select:checked) .itflow-file-card-check {
    opacity: 1;
}
@media (hover: none) {
    .itflow-file-card-check {
        opacity: 1;
    }
}
.itflow-file-card-check .form-check-input {
    margin: 0;
    background-color: var(--bs-body-bg);
}
.itflow-file-card-preview {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 9.5rem;
    overflow: hidden;
    border-bottom: 1px solid var(--bs-border-color-translucent);
    background-color: var(--bs-tertiary-bg);
    text-decoration: none;
}
.itflow-file-card-preview img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.itflow-file-card-preview iframe {
    width: 100%;
    /* Taller than the box and pulled up, so a viewer's toolbar is clipped away */
    height: calc(100% + 56px);
    margin-top: -56px;
    border: 0;
    pointer-events: none;
    background: #fff;
}
.itflow-file-card-preview pre {
    width: 100%;
    height: 100%;
    margin: 0;
    padding: .6rem .7rem;
    overflow: hidden;
    font-size: .65rem;
    line-height: 1.35;
    white-space: pre-wrap;
    word-break: break-word;
    color: var(--bs-secondary-color);
    background-color: var(--bs-body-bg);
}
.itflow-file-card.is-document .itflow-file-card-preview pre {
    font-family: var(--bs-body-font-family);
    font-size: .7rem;
}

/* Files dragged over the list */
.itflow-files-dropzone {
    position: absolute;
    z-index: 20;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    border: 2px dashed var(--bs-primary);
    border-radius: var(--bs-border-radius-lg);
    background-color: color-mix(in srgb, var(--bs-body-bg) 82%, transparent);
    color: var(--bs-primary-text-emphasis);
    pointer-events: none;
}
.itflow-files-dropzone[hidden] {
    display: none;
}

/* Upload modal */
.itflow-upload-drop {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .15rem;
    padding: 1.6rem 1rem;
    border: 2px dashed var(--bs-border-color);
    border-radius: var(--bs-border-radius-lg);
    color: var(--bs-secondary-color);
    text-align: center;
    cursor: pointer;
    transition: border-color .12s, background-color .12s;
}
.itflow-upload-drop:hover,
.itflow-upload-drop.is-over {
    border-color: var(--bs-primary);
    background-color: var(--bs-primary-bg-subtle);
    color: var(--bs-primary-text-emphasis);
}
.itflow-upload-drop.has-files {
    padding: .9rem 1rem;
}
.itflow-upload-drop:focus-within {
    outline: 2px solid var(--bs-primary);
    outline-offset: 2px;
}
.itflow-upload-list {
    max-height: 12rem;
    overflow-y: auto;
}
.itflow-upload-list li {
    padding: .2rem .25rem;
    border-bottom: 1px solid var(--bs-border-color-translucent);
}

/* File quick look preview */
.itflow-file-preview {
    overflow: hidden;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-lg);
    background-color: var(--bs-tertiary-bg);
    text-align: center;
}
.itflow-file-preview img {
    max-width: 100%;
    max-height: 22rem;
    object-fit: contain;
}
.itflow-file-preview iframe {
    display: block;
    width: 100%;
    height: 26rem;
    border: 0;
    background: #fff;
}
.itflow-file-preview pre {
    max-height: 20rem;
    margin: 0;
    padding: .75rem 1rem;
    overflow: auto;
    font-size: .75rem;
    text-align: left;
    white-space: pre-wrap;
    word-break: break-word;
}
.itflow-file-preview .itflow-asset-empty {
    border: 0;
}

/* Linked records - linkGroupsHtml() in functions/links.php */
.itflow-link-group + .itflow-link-group,
.itflow-link-group + .itflow-link-empty {
    margin-top: .9rem;
}
.itflow-link-group-head {
    display: flex;
    align-items: center;
    margin-bottom: .35rem;
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .02em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}
.itflow-link-group-head .badge {
    background-color: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
    font-weight: 500;
}
.itflow-link-group-head a {
    text-transform: none;
    letter-spacing: 0;
    font-weight: 500;
}
.itflow-link-row {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .3rem .4rem;
    margin: 0 -.4rem;
    border-radius: var(--bs-border-radius);
    font-size: .875rem;
}
.itflow-link-row:hover {
    background-color: var(--bs-tertiary-bg);
}
.itflow-link-icon {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: var(--bs-border-radius);
    background-color: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
    font-size: .8rem;
}
.itflow-link-remove {
    flex: 0 0 auto;
    padding: 0 .25rem;
    font-size: .8rem;
    color: var(--bs-secondary-color);
    opacity: 0;
    transition: opacity .12s ease-in-out;
}
.itflow-link-row:hover .itflow-link-remove,
.itflow-link-remove:focus-visible {
    opacity: 1;
}
.itflow-link-remove:hover {
    color: var(--bs-danger);
}
@media (hover: none) {
    .itflow-link-remove {
        opacity: 1;
    }
}
.itflow-link-empty {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .35rem;
}
.itflow-link-types .nav-link {
    padding: .3rem .7rem;
    font-size: .875rem;
}
.itflow-link-types .nav-link:not(.active) {
    color: var(--bs-body-color);
}

/* The document page and quick looks */
.itflow-document-body {
    min-height: 12rem;
    overflow-wrap: anywhere;
}
.itflow-document-quick-content {
    max-height: 55vh;
    overflow: auto;
    padding: 1rem 1.25rem;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-lg);
    overflow-wrap: anywhere;
}
.itflow-document-history .list-group-item {
    padding-top: .5rem;
    padding-bottom: .5rem;
}
.itflow-document-history .list-group-item:hover .itflow-copy {
    opacity: 1;
}
.itflow-preview-nav {
    z-index: 2;
}
@media print {
    .itflow-document-head .card-body {
        padding: 0;
    }
    .itflow-document-head,
    .itflow-document-body {
        border: 0;
        box-shadow: none;
    }
}
/* In a quick look's tabs the rows sit flush with the pane, like its other lists */
.itflow-asset-quick-related .itflow-link-row {
    margin: 0;
    padding-left: 0;
    padding-right: 0;
}

/* Licenses - agent/software.php, agent/license.php, agent/modals/software/

   A license's tile is its software type's icon on that type's colour - the
   asset tones (functions/software.php softwareTypeStyle()). Seats are a
   count over a thin bar: blue with seats free, amber full, red over, grey
   with none in use (softwareSeatBar()). */
.itflow-seats {
    min-width: 6.5rem;
    max-width: 11rem;
    font-size: .875rem;
    line-height: 1.3;
}
.itflow-seats-bar {
    height: .3rem;
    margin: .25rem 0 .2rem;
    background-color: var(--bs-secondary-bg);
}
.itflow-seats-glance .itflow-seats {
    max-width: 14rem;
}
.itflow-seats-glance .itflow-seats-bar {
    margin-top: .3rem;
}
/* Keys - monospace, cut short on screen, copied whole */
.itflow-license-key {
    max-width: 16rem;
    font-size: .82rem;
}
.itflow-license-key-cell {
    min-width: 0;
    max-width: 20rem;
}
.itflow-license-main-key {
    background-color: var(--bs-tertiary-bg);
}
.itflow-license-main-key .itflow-license-key {
    max-width: 28rem;
}
/* Devices / Users headings inside the Seats tab */
.itflow-license-section {
    padding: .6rem 1rem .4rem;
    border-bottom: 1px solid var(--bs-border-color-translucent);
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}
.itflow-license-section .badge {
    background-color: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
    font-weight: 500;
    letter-spacing: 0;
}
.itflow-asset-related .table + .itflow-license-section,
.table-responsive + .itflow-license-section {
    margin-top: .5rem;
}
.itflow-license-holder-sub {
    padding-left: 1.85rem;
}
/* Linked documents and files on the license page sit in the pane's padding */
.itflow-license-links {
    padding: .5rem 1rem;
}
.itflow-license-links .itflow-link-row {
    margin: 0 -.4rem;
}

/* Locations - agent/locations.php, agent/location.php, agent/modals/location/

   A location's tile is its photo, or a pin (a building for the primary) on
   the location tone (functions/location.php locationTile()). */
.itflow-asset-tone-location { --itflow-asset-tone: #c2410c; }
[data-bs-theme="dark"] .itflow-asset-tone-location { --itflow-asset-tone: #f59e72; }
.itflow-location-address-cell {
    min-width: 12rem;
}
.itflow-location-email {
    max-width: 18rem;
}
/* The access notes on a ticket's Site card - a few lines, then it scrolls */
.itflow-ticket-site-notes {
    max-height: 7.5rem;
    overflow-y: auto;
}

/* Vendors - agent/vendors.php, agent/vendor.php, agent/modals/vendor/

   A vendor's tile is its initials on a colour picked by its name
   (functions/vendor.php vendorTile()), square like the asset and license
   tiles, so one vendor is the same colour at every client. */
.itflow-vendor-tile {
    font-weight: 600;
    font-size: .85rem;
    letter-spacing: .02em;
}
.itflow-vendor-tile-lg {
    font-size: 1.2rem;
}
.itflow-vendor-tile-sm {
    font-size: .65rem;
    letter-spacing: 0;
}
.itflow-vendor-tile-xs {
    width: 1.25rem;
    height: 1.25rem;
    border-radius: .3rem;
    font-size: .5rem;
    letter-spacing: 0;
}
/* A PIN or code shown as dots until it is asked for */
.itflow-secret {
    font-family: var(--bs-font-monospace);
}
.itflow-secret:not(.is-shown) .itflow-secret-value {
    display: none;
}
.itflow-secret.is-shown .itflow-secret-mask {
    display: none;
}
.itflow-secret-toggle {
    border: 0;
    background: none;
    padding: 0 .25rem;
    color: var(--bs-secondary-color);
    font-size: .8em;
}
.itflow-secret-toggle:hover {
    color: var(--bs-emphasis-color);
}
/* The vendor list's support and account cells */
.itflow-vendor-support-cell {
    min-width: 13rem;
}
.itflow-vendor-email {
    max-width: 16rem;
}

/* Credentials - agent/credentials.php, agent/modals/credential/ and every
   credential row elsewhere (functions/credential.php, js/credentials.js).
   The password is dots until the eye fetches it; the 2FA button counts the
   code down and turns red for its last five seconds. */
.itflow-credential-pw {
    display: inline-flex;
    align-items: center;
    gap: .15rem;
    white-space: nowrap;
}
.itflow-credential-pw-mask {
    letter-spacing: .05em;
    color: var(--bs-secondary-color);
}
.itflow-credential-pw-value {
    user-select: all;
    background: var(--bs-tertiary-bg);
    border-radius: var(--bs-border-radius-sm);
    padding: 0 .3rem;
}
.itflow-credential-reveal {
    border: 0;
    background: none;
    padding: 0 .3rem;
    color: var(--bs-secondary-color);
}
.itflow-credential-reveal:hover {
    color: var(--bs-emphasis-color);
}
.itflow-credential-otp {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
    border: 1px solid var(--bs-border-color);
    border-radius: 50rem;
    background: var(--bs-body-bg);
    padding: .05rem .55rem;
    font-size: .85em;
    color: var(--bs-secondary-color);
    white-space: nowrap;
}
.itflow-credential-otp:hover {
    color: var(--bs-emphasis-color);
    border-color: var(--bs-secondary-color);
}
.itflow-credential-otp.is-live {
    color: var(--bs-emphasis-color);
    font-family: var(--bs-font-monospace);
    font-weight: 600;
}
.itflow-credential-otp-time {
    font-size: .8em;
    font-weight: 400;
    color: var(--bs-secondary-color);
}
.itflow-credential-otp.is-ending .itflow-credential-otp-time {
    color: var(--bs-danger);
}
.itflow-credential-user {
    max-width: 14rem;
    display: inline-block;
    vertical-align: bottom;
}
.itflow-credential-dl dd {
    min-height: 1.5rem;
}
.itflow-credential-note {
    white-space: normal;
    max-height: 10rem;
    overflow-y: auto;
    padding: .5rem .75rem;
    background: var(--bs-tertiary-bg);
    border-radius: var(--bs-border-radius);
}
/* The list's "For" column - an asset, a contact and the first links, kept to one width */
.itflow-credential-for {
    max-width: 15rem;
}
/* Credentials listed on an asset, contact, vendor or license (credentialTableHtml) */
.itflow-credential-name-cell {
    min-width: 12rem;
    max-width: 22rem;
}

/* Domains - agent/domains.php and agent/modals/domain/ (functions/domain.php).
   Records are monospace, one per line with a copy button; the registrar and
   hosts column keeps to one width. */
.itflow-domain-dl dt {
    white-space: nowrap;
}
.itflow-domain-dl dd {
    min-height: 1.5rem;
    min-width: 0;
}
.itflow-domain-who {
    max-width: 18rem;
}
.itflow-domain-checks li + li {
    margin-top: .25rem;
}
.itflow-domain-mail > .d-inline-flex {
    flex-wrap: nowrap !important;
}

/* Certificates - agent/certificates.php and agent/modals/certificate/
   (functions/certificate.php). The host column and the issuer keep to one
   width; the fingerprint breaks anywhere rather than widen the quick look. */
.itflow-certificate-host {
    max-width: 15rem;
}
.itflow-certificate-table .itflow-asset-desc {
    max-width: 14rem;
}
.itflow-certificate-issuer {
    max-width: 10rem;
}
.itflow-certificate-fingerprint {
    overflow-wrap: anywhere;
    line-height: 1.35;
}
.itflow-certificate-check-result {
    padding: .75rem;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    background: var(--bs-tertiary-bg);
}

/* Tickets - agent/tickets.php (ticket_list.php and the board, ticket_kanban.php
   with agent/css/ticket_kanban.css), the ticket quick look, and the ticket
   tables on other pages (functions/ticket.php). */
.itflow-ticket-list > :not(caption) > * > * {
    padding-left: .45rem;
    padding-right: .45rem;
}
.itflow-ticket-list .itflow-ticket-main {
    min-width: 16rem;
}
.itflow-ticket-subject {
    overflow-wrap: anywhere;
}
.itflow-ticket-table .itflow-ticket-subject {
    min-width: 12rem;
}
/* What it is about, under the subject: number, age, source, category, asset... */
.itflow-ticket-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    column-gap: .65rem;
    row-gap: .2rem;
    margin-top: .15rem;
}
.itflow-ticket-dot {
    margin-right: .3rem;
    font-size: .5rem;
    vertical-align: middle;
    color: var(--bs-secondary-color);
}
.itflow-ticket-asset {
    display: inline-block;
    max-width: 12rem;
    vertical-align: bottom;
}
.itflow-ticket-who-cell > * {
    max-width: 12rem;
}
.itflow-ticket-activity {
    min-width: 7rem;
}
.itflow-ticket-who {
    max-width: 8rem;
}
.itflow-ticket-tasks {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    white-space: nowrap;
}
.itflow-ticket-tasks .progress {
    width: 2.5rem;
    height: .3rem;
}
/* Our move - a dot before the subject, like an unread mail */
.itflow-ticket-move {
    flex: 0 0 auto;
    width: .5rem;
    height: .5rem;
    margin-top: .45rem;
    border-radius: 50%;
}
.itflow-ticket-move.is-ours {
    background-color: var(--bs-primary);
}
/* Late, or close to it - an edge down the row or the card. The row keeps
   Bootstrap's own shadow under it, which is what paints hover and selection. */
.itflow-ticket-row.is-danger > td:first-child {
    box-shadow: inset 3px 0 0 var(--bs-danger), inset 0 0 0 9999px var(--bs-table-bg-state, var(--bs-table-bg-type, var(--bs-table-accent-bg)));
}
.itflow-ticket-row.is-warning > td:first-child {
    box-shadow: inset 3px 0 0 var(--bs-warning), inset 0 0 0 9999px var(--bs-table-bg-state, var(--bs-table-bg-type, var(--bs-table-accent-bg)));
}
/* Urgent is dark everywhere - on a dark page it needs to stand out the other way */
[data-bs-theme=dark] .itflow-ticket-list .badge.text-bg-dark,
[data-bs-theme=dark] .itflow-ticket-card .badge.text-bg-dark,
[data-bs-theme=dark] .itflow-ticket-table .badge.text-bg-dark,
[data-bs-theme=dark] .itflow-ticket-glance .badge.text-bg-dark {
    background-color: var(--bs-emphasis-color) !important;
    color: var(--bs-body-bg) !important;
}

/* A card on the board */
.itflow-ticket-card {
    position: relative;
    padding: .6rem .7rem;
    font-size: .875rem;
    background-color: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color-translucent);
    border-radius: var(--bs-border-radius);
    box-shadow: var(--bs-box-shadow-sm);
}
.itflow-ticket-card:hover {
    border-color: var(--bs-border-color);
}
.itflow-ticket-card.is-danger {
    box-shadow: inset 3px 0 0 var(--bs-danger), var(--bs-box-shadow-sm);
}
.itflow-ticket-card.is-warning {
    box-shadow: inset 3px 0 0 var(--bs-warning), var(--bs-box-shadow-sm);
}
.itflow-ticket-card .itflow-ticket-move {
    margin-top: 0;
}
.itflow-ticket-card-subject {
    display: -webkit-box;
    margin: .3rem 0 .15rem;
    overflow: hidden;
    font-weight: 600;
    color: var(--bs-body-color);
    text-decoration: none;
    overflow-wrap: anywhere;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
}
.itflow-ticket-card-subject:hover {
    color: var(--bs-link-hover-color);
}
.itflow-ticket-card .itflow-contact-avatar-xs {
    margin-right: .25rem;
}
.itflow-ticket-card .itflow-ticket-meta {
    column-gap: .5rem;
}

/* Ticket quick look - agent/modals/ticket/ticket.php. The details and replies
   are whatever came in by email, so they scroll in their box and their
   pictures and tables fit it. */
.itflow-ticket-glance-text {
    max-height: 14rem;
    overflow: auto;
    overflow-wrap: anywhere;
}
.itflow-ticket-glance-text img {
    max-width: 100%;
    height: auto;
}
.itflow-ticket-glance-text table {
    max-width: 100%;
}
.itflow-ticket-glance-text p:last-child {
    margin-bottom: 0;
}

/* Projects - agent/projects.php, agent/project.php and the project quick look
   (functions/project.php). Progress and time are a slim bar with the figure
   beside it; the project page leads with four stat cards. */
.itflow-project-progress {
    display: flex;
    align-items: center;
    gap: .5rem;
}
.itflow-project-progress .progress {
    flex: 0 0 3.5rem;
    height: .4rem;
}
.itflow-project-progress-cell {
    min-width: 7.5rem;
}
.itflow-project-main {
    max-width: 20rem;
}
.itflow-project-list .itflow-ticket-who-cell > * {
    max-width: 10.5rem;
}
@media (max-width: 1399.98px) {
    .itflow-project-main {
        max-width: 17rem;
    }
}
.itflow-project-desc {
    max-width: 20rem;
}
.itflow-project-icon {
    --itflow-asset-tone: #5a61c9;
}
.itflow-project-icon.is-done {
    --itflow-asset-tone: #2f8a57;
}
[data-bs-theme="dark"] .itflow-project-icon {
    --itflow-asset-tone: #9ba1f2;
}
[data-bs-theme="dark"] .itflow-project-icon.is-done {
    --itflow-asset-tone: #6fcf97;
}
.itflow-project-stat-label {
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .02em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}
.itflow-project-stat-value {
    margin-top: .25rem;
    font-size: 1.5rem;
    font-weight: 600;
    line-height: 1.2;
}
.itflow-project-stat .progress {
    height: .45rem;
}
.itflow-project-scope {
    overflow-wrap: anywhere;
}
.itflow-project-tasks li {
    padding: .2rem 0;
}

/* Services - agent/services.php, agent/service.php and the service quick
   look (functions/service.php). Each row says what it depends on as small
   count chips, and the first thing that needs attention. */
.itflow-service-main {
    max-width: 20rem;
}
.itflow-service-desc {
    max-width: 16rem;
}
.itflow-service-attention,
.itflow-service-attention > div {
    max-width: 15rem;
}
.itflow-service-list .itflow-ticket-who-cell > * {
    max-width: 10rem;
}
.itflow-service-chips-cell {
    min-width: 11rem;
}
@media (max-width: 1599.98px) {
    .itflow-service-main {
        max-width: 16rem;
    }
    .itflow-service-desc {
        max-width: 12rem;
    }
    .itflow-service-attention,
    .itflow-service-attention > div {
        max-width: 12rem;
    }
}
.itflow-service-chips {
    max-width: 15.5rem;
}
.itflow-service-text {
    white-space: pre-line;
    overflow-wrap: anywhere;
}
.itflow-service-issues li {
    padding: .1rem 0;
    overflow-wrap: anywhere;
}
.itflow-service-notes-peek {
    max-height: 9rem;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(to bottom, #000 70%, transparent);
    mask-image: linear-gradient(to bottom, #000 70%, transparent);
}
.itflow-service-importance .btn {
    line-height: 1.25;
}
.itflow-service-callee .itflow-link-remove {
    opacity: 0;
}
.itflow-service-callee:hover .itflow-link-remove,
.itflow-service-callee .itflow-link-remove:focus-visible {
    opacity: 1;
}
@media (hover: none) {
    .itflow-service-callee .itflow-link-remove {
        opacity: 1;
    }
}
.itflow-service-alert ul {
    font-size: .9rem;
}

/* --- Calendar (agent/calendar.php, agent/js/calendar.js) ------------------- */
@media (max-width: 767.98px) {
    #calendar {
        min-height: 50vh;
    }
}
.itflow-calendar-page.is-loading #calendar {
    opacity: .75;
    transition: opacity .15s;
}
/* A calendar or source to show or hide: a checkbox in its own colour */
.itflow-cal-toggle {
    padding: .2rem 0;
}
.itflow-cal-toggle .form-check-input {
    border-color: var(--itflow-cal-color);
    flex-shrink: 0;
}
.itflow-cal-toggle .form-check-input:checked {
    background-color: var(--itflow-cal-color);
    border-color: var(--itflow-cal-color);
}
.itflow-cal-toggle .form-check-input:focus {
    box-shadow: 0 0 0 .2rem color-mix(in srgb, var(--itflow-cal-color) 25%, transparent);
}
.itflow-cal-toggle label {
    cursor: pointer;
}
.itflow-cal-toggle-icon {
    color: var(--itflow-cal-color);
}
/* One item on the calendar: time, icon, title, and where / who when there is room */
.itflow-cal-event {
    overflow: hidden;
    font-size: .8rem;
    line-height: 1.3;
    padding: 0 .15rem;
}
.itflow-cal-event.is-daygrid {
    white-space: nowrap;
    text-overflow: ellipsis;
}
.itflow-cal-event.is-list {
    font-size: .875rem;
}
.itflow-cal-event.is-list .itflow-cal-time {
    display: inline-block;
    min-width: 8.5rem;
    font-weight: 400;
    color: var(--bs-secondary-color);
}
.itflow-cal-event.is-list .itflow-cal-detail {
    margin-left: 8.75rem;
}
@media (max-width: 575.98px) {
    .itflow-cal-event.is-list .itflow-cal-time {
        display: block;
        min-width: 0;
    }
    .itflow-cal-event.is-list .itflow-cal-detail {
        margin-left: 0;
    }
}
/* The sidebar keeps its width; the calendar takes the rest */
@media (min-width: 992px) {
    .itflow-cal-side {
        flex: 0 0 15.5rem;
        max-width: 15.5rem;
    }
}
.itflow-cal-time {
    font-weight: 600;
    margin-right: .25rem;
}
.itflow-cal-event.is-timegrid .itflow-cal-time {
    display: block;
    font-weight: 400;
    opacity: .9;
}
.itflow-cal-event.is-timegrid .itflow-cal-title {
    font-weight: 600;
}
.itflow-cal-icon {
    font-size: .8em;
    opacity: .85;
    margin-right: .15rem;
}
.itflow-cal-detail {
    font-size: .8em;
    opacity: .85;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.itflow-cal-done .itflow-cal-title {
    text-decoration: line-through;
}
.itflow-cal-done {
    opacity: .6;
}
/* To schedule - open tickets to drag onto the calendar */
.itflow-cal-unscheduled {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .35rem .5rem;
    margin-bottom: .25rem;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    background: var(--bs-body-bg);
    cursor: grab;
    user-select: none;
}
.itflow-cal-unscheduled:hover {
    background: var(--bs-tertiary-bg);
}
#calendarUnscheduled {
    max-height: 22rem;
    overflow-y: auto;
}
.itflow-cal-priority {
    width: .5rem;
    height: .5rem;
    border-radius: 50%;
    flex-shrink: 0;
}
/* The event quick look's tile, in its calendar's colour */
.itflow-cal-tile {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: .5rem;
    background: var(--itflow-cal-color);
    color: #fff;
    font-size: 1.1rem;
}
.itflow-cal-help-tabs .nav-link {
    white-space: nowrap;
}
.swal2-radio .itflow-cal-swal-input,
.swal2-radio {
    gap: 1rem;
}

/* ---------- Networks and asset interfaces ---------- */

/* A tile small enough for a line of text - networkLink(), interfaceAssetRef() (a vendor's has its own, .itflow-vendor-tile-xs) */
.itflow-asset-icon-xs:not(.itflow-vendor-tile) {
    width: 1.25rem;
    height: 1.25rem;
    border-radius: .3rem;
    font-size: .6rem;
}
/* A network's type - its icon in its colour, then the name (the type picker on lists) */
.itflow-net-type {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    white-space: nowrap;
}
.itflow-net-type i {
    color: var(--itflow-asset-tone);
}
.itflow-net-vlan {
    display: inline-block;
    padding: 0 .4rem;
    border-radius: 999px;
    background: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
    font-size: .75em;
    font-weight: 600;
    letter-spacing: .02em;
    line-height: 1.5;
    white-space: nowrap;
}
/* How full a network is - networkUsageBar() */
.itflow-net-usage {
    display: flex;
    align-items: center;
    gap: .5rem;
    min-width: 8rem;
}
.itflow-net-usage .progress {
    flex: 1 1 auto;
    height: .4rem;
    min-width: 3rem;
}
.itflow-net-usage-cell {
    min-width: 10rem;
}
.itflow-net-main .itflow-service-desc {
    max-width: 18rem;
}

/* The address plan on the network page */
.itflow-net-plan-search {
    max-width: 22rem;
    flex: 1 1 14rem;
}
.itflow-net-plan td {
    vertical-align: middle;
}
.itflow-net-plan .itflow-net-free td {
    color: var(--bs-secondary-color);
    background: repeating-linear-gradient(-45deg, transparent 0 .5rem, color-mix(in srgb, var(--bs-success) 5%, transparent) .5rem 1rem);
    padding-top: .15rem;
    padding-bottom: .15rem;
}
.itflow-net-plan .itflow-net-pool td {
    background: color-mix(in srgb, var(--bs-info) 10%, transparent);
    color: var(--bs-info-text-emphasis);
    border-top: 2px solid color-mix(in srgb, var(--bs-info) 45%, transparent);
}
/* Addresses inside the DHCP range sit under its band, set in */
.itflow-net-plan tr.is-in-pool > td.itflow-net-plan-ip {
    box-shadow: inset 3px 0 0 color-mix(in srgb, var(--bs-info) 45%, transparent);
}
.itflow-net-plan tr.itflow-net-flagged > td {
    background: color-mix(in srgb, var(--bs-warning) 8%, transparent);
}
.itflow-net-unplaced .itflow-contact-ref {
    max-width: 14rem;
}
/* The four kinds of documented address, as one choice */
.itflow-net-ip-types .btn {
    flex: 1 1 auto;
    white-space: nowrap;
}
.itflow-net-cidr-info {
    min-height: 1.25rem;
}

/* An asset's Interfaces tab - the name and what it is kept readable */
.itflow-iface-cell {
    min-width: 11rem;
}

/* An asset's interfaces as a row of ports - switches, firewalls, access points */
.itflow-port-map {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
    padding: 1rem;
}
/* Between the copper ports and the SFP cages - a row of their own */
.itflow-port-break {
    flex-basis: 100%;
    height: .15rem;
}
.itflow-port {
    position: relative;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 3.25rem;
    height: 3rem;
    padding: .15rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .4rem;
    background: var(--bs-tertiary-bg);
    color: var(--bs-secondary-color);
    font-size: .65rem;
    line-height: 1.15;
    text-decoration: none;
    overflow: hidden;
}
.itflow-port:hover,
.itflow-port:focus-visible {
    border-color: var(--bs-primary);
    color: var(--bs-body-color);
}
.itflow-port .itflow-port-name {
    font-family: var(--bs-font-monospace);
    font-weight: 600;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.itflow-port .itflow-port-lamp {
    width: .55rem;
    height: .55rem;
    border-radius: 50%;
    background: var(--bs-secondary-bg);
    border: 1px solid var(--bs-border-color);
    margin-bottom: .2rem;
}
.itflow-port.is-connected {
    border-color: color-mix(in srgb, var(--bs-success) 55%, transparent);
    background: color-mix(in srgb, var(--bs-success) 10%, var(--bs-body-bg));
    color: var(--bs-body-color);
}
.itflow-port.is-connected .itflow-port-lamp {
    background: var(--bs-success);
    border-color: var(--bs-success);
}
.itflow-port.is-addressed:not(.is-connected) .itflow-port-lamp {
    background: var(--bs-info);
    border-color: var(--bs-info);
}
.itflow-port.is-primary::after {
    content: "";
    position: absolute;
    top: .2rem;
    right: .2rem;
    width: .35rem;
    height: .35rem;
    border-radius: 50%;
    background: var(--bs-primary);
}
.itflow-port-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    padding: 0 1rem .75rem;
    font-size: .8rem;
    color: var(--bs-secondary-color);
}
.itflow-port-legend .itflow-port-lamp {
    display: inline-block;
    width: .55rem;
    height: .55rem;
    border-radius: 50%;
    margin-right: .3rem;
    border: 1px solid var(--bs-border-color);
    background: var(--bs-secondary-bg);
    vertical-align: middle;
}

/* Users - admin/users.php, admin/modals/user/*, and your account (agent/user/*).
   functions/user.php userAvatar() uses the contact avatar classes; xl is the
   profile page and the account menu. */
.itflow-contact-avatar-xl {
    width: 5rem;
    height: 5rem;
    font-size: 1.6rem;
}
.itflow-user-main {
    min-width: 15rem;
}
.itflow-user-list td {
    padding-top: .6rem;
    padding-bottom: .6rem;
}
/* The account menu in the top bar - initials when there is no picture */
.app-header .navbar-nav > .user-menu .nav-link .itflow-contact-avatar {
    width: 1.75rem;
    height: 1.75rem;
}
.itflow-user-header .itflow-contact-avatar {
    width: 5.5rem;
    height: 5.5rem;
    margin: 0 auto;
    border: 3px solid rgba(255, 255, 255, .2);
    font-size: 1.8rem;
}
/* Client access: one row per client, scrolling inside the modal */
.itflow-user-access {
    max-height: 22rem;
    overflow-y: auto;
}
.itflow-user-access .btn-group-sm > .btn {
    min-width: 3.25rem;
}
/* MFA set up: the QR code on white, whatever the theme - an authenticator
   app reads dark on light - and the code, spaced out like the app shows it */
.itflow-mfa-qr-box {
    display: inline-block;
    padding: .25rem;
    background: #fff;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-lg);
    line-height: 0;
}
.itflow-mfa-qr {
    width: 12rem;
    height: 12rem;
}
.itflow-mfa-code {
    letter-spacing: .4em;
}
.itflow-mfa-code::placeholder {
    letter-spacing: .4em;
    opacity: .35;
}
.itflow-mfa-state {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    font-size: 1rem;
}
.itflow-mfa-state.is-on {
    background: var(--bs-success-bg-subtle);
    color: var(--bs-success-text-emphasis);
}
.itflow-mfa-state.is-off {
    background: var(--bs-danger-bg-subtle);
    color: var(--bs-danger-text-emphasis);
}
/* Preferences: what light and dark look like */
.itflow-theme-pick {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    padding: .5rem .9rem;
}
/* Its own name - it was .itflow-theme-swatch, the Theme settings page's, and squeezed that page's swatches to this width */
.itflow-mode-swatch {
    display: inline-block;
    width: 1.75rem;
    height: 1.25rem;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-sm);
}
.itflow-mode-swatch.is-light {
    background: linear-gradient(90deg, #343a40 0 30%, #f8f9fa 30%);
}
.itflow-mode-swatch.is-dark {
    background: linear-gradient(90deg, #343a40 0 30%, #212529 30%);
}

/* Pagination (includes/filter_footer.php) - on a phone a long run of page
   numbers wraps instead of pushing the page wider than the screen */
.pagination {
    flex-wrap: wrap;
    row-gap: .25rem;
}

/* Reports - agent/reports/, functions/reports.php

   The report header (title and dates on the dark bar, the filters under it),
   a strip of figures, then cards of charts and tables. Section cards have the
   dashboard's quiet headers, and every figure uses tabular numbers so columns
   of amounts line up. Charts are drawn by js/reports.js. Printed, the menu,
   the filters and the buttons drop away and the company, the date printed and
   who printed it appear under the title instead. */
.itflow-report {
    font-variant-numeric: tabular-nums;
}
.itflow-report > .card,
.itflow-report > .row {
    margin-bottom: 1rem;
}
.itflow-report-subtitle {
    margin-left: .6rem;
    font-size: .875rem;
    font-weight: 400;
    opacity: .75;
}
.itflow-report-print-meta {
    display: none;
}
.itflow-report-group-title {
    font-size: 1.125rem;
    font-weight: 600;
}
/* Sections: a heading and its chart or table, without the heavy header bar */
.itflow-report-section > .card-header {
    background: transparent;
    border-bottom: 0;
    padding-bottom: .25rem;
}
.itflow-report-section .card-title {
    font-size: 1rem;
    font-weight: 600;
}
.itflow-report-section > .table-responsive,
.itflow-report-section > .list-group {
    border-top: var(--bs-border-width) solid var(--bs-border-color-translucent);
    margin-top: .5rem;
}
.itflow-report-section .list-group {
    --bs-list-group-action-color: var(--bs-body-color);
}

/* The figures along the top: cells that wrap onto as many rows as they need,
   with hairlines between them drawn by the 1px gap over the border colour */
.itflow-report-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: 1px;
    overflow: hidden;
    background-color: var(--bs-border-color-translucent);
}
.itflow-report-stat {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-width: 0;
    padding: .9rem 1rem;
    background-color: var(--bs-card-bg, var(--bs-body-bg));
    color: inherit;
    text-decoration: none;
}
a.itflow-report-stat:hover,
a.itflow-report-stat:focus-visible {
    background-color: var(--bs-tertiary-bg);
    color: inherit;
}
.itflow-report-stat-label {
    font-size: .8rem;
    color: var(--bs-secondary-color);
}
.itflow-report-stat-value {
    margin: .1rem 0;
    overflow: hidden;
    font-size: 1.45rem;
    font-weight: 600;
    line-height: 1.2;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.itflow-report-stat-sub {
    font-size: .8rem;
    color: var(--bs-secondary-color);
}

.itflow-report-chart {
    position: relative;
    height: 260px;
}
.itflow-report-chart-sm {
    height: 200px;
}
.itflow-report-chart-lg {
    height: 320px;
}
.itflow-report-chart-donut {
    height: 190px;
}
@media (max-width: 575.98px) {
    .itflow-report-chart,
    .itflow-report-chart-lg {
        height: 240px;
    }
}

/* Tables: sortable headings, and a totals row that reads as one */
.itflow-report-table > tfoot > tr > td {
    border-top: 2px solid var(--bs-border-color);
    border-bottom: 0;
    background-color: var(--bs-tertiary-bg);
}
.itflow-report-sortable {
    cursor: pointer;
    user-select: none;
}
.itflow-report-sortable::after {
    content: "\f0dc";
    margin-left: .35rem;
    font-family: "Font Awesome 5 Free";
    font-weight: 900;
    font-size: .7rem;
    opacity: .25;
}
.itflow-report-sortable[aria-sort=ascending]::after {
    content: "\f0de";
    opacity: .8;
}
.itflow-report-sortable[aria-sort=descending]::after {
    content: "\f0dd";
    opacity: .8;
}
.itflow-report-table td.itflow-report-sub {
    padding-left: 1.75rem;
}
.itflow-report-table tr.itflow-report-group-row > td {
    background-color: var(--bs-tertiary-bg);
    font-weight: 600;
}
/* A year of months is wide - the first column stays put while it scrolls */
.itflow-report-grid > :not(caption) > tr > :first-child {
    position: sticky;
    left: 0;
    z-index: 1;
    min-width: 11rem;
    background-color: var(--bs-card-bg, var(--bs-body-bg));
}
.itflow-report-grid > thead > tr > :first-child {
    background-color: var(--bs-tertiary-bg);
}
.itflow-report-grid > tfoot > tr > :first-child,
.itflow-report-grid tr.itflow-report-group-row > :first-child {
    background-color: var(--bs-tertiary-bg);
}
.itflow-report-grid {
    font-size: .875rem;
}
.itflow-report-grid td,
.itflow-report-grid th {
    white-space: nowrap;
}
.itflow-report a.itflow-report-amount {
    color: inherit;
    text-decoration: none;
}
.itflow-report a.itflow-report-amount:hover,
.itflow-report a.itflow-report-amount:focus-visible {
    color: var(--bs-link-hover-color);
    text-decoration: underline;
}
.itflow-report-table .font-monospace {
    white-space: nowrap;
}
/* A tight table wraps its headings and long client names before it scrolls */
.itflow-report-table > thead > tr > th {
    vertical-align: bottom;
}
.itflow-report-table:not(.itflow-report-grid) > thead > tr > th:not(:first-child) {
    min-width: 4.5rem;
}
.itflow-report-client-name {
    min-width: 9rem;
}
/* A column of free text (a scope, a purpose) gets room before the numbers do */
.itflow-report-text {
    min-width: 14rem;
}
.itflow-report-zero {
    color: var(--bs-tertiary-color);
}

/* A share of something as a thin bar under or beside a figure */
.itflow-report-meter {
    display: flex;
    height: .375rem;
    min-width: 4rem;
    overflow: hidden;
    border-radius: 1rem;
    background-color: var(--bs-secondary-bg);
}
.itflow-report-meter > span {
    height: 100%;
    background-color: var(--itflow-accent);
}

/* When tickets come in: weekday by hour, darker for more */
.itflow-report-heat {
    width: 100%;
    border-collapse: separate;
    border-spacing: 2px;
    font-size: .7rem;
}
.itflow-report-heat th {
    padding: 0 .25rem;
    font-weight: 500;
    color: var(--bs-secondary-color);
    text-align: center;
    white-space: nowrap;
}
.itflow-report-heat th[scope=row] {
    text-align: right;
}
.itflow-report-heat td {
    height: 1.4rem;
    min-width: .7rem;
    border-radius: 3px;
    background-color: color-mix(in srgb, var(--itflow-accent) calc(var(--heat, 0) * 100%), var(--bs-secondary-bg));
}

/* The Reports page: a card per report */
.itflow-report-card {
    transition: border-color .12s ease-in-out, background-color .12s ease-in-out;
}
.itflow-report-card:hover,
.itflow-report-card:focus-visible {
    border-color: var(--itflow-accent);
    background-color: var(--bs-tertiary-bg);
}
.itflow-report-card-icon {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--bs-border-radius-lg);
    font-size: 1.05rem;
}

/* Client review: notes on what to do next */
.itflow-report-advice {
    margin: 0;
    padding: 0;
    list-style: none;
}
.itflow-report-advice li {
    display: flex;
    gap: .75rem;
    padding: .55rem 0;
    border-top: var(--bs-border-width) solid var(--bs-border-color-translucent);
}
.itflow-report-advice li:first-child {
    border-top: 0;
}
.itflow-report-advice i {
    margin-top: .2rem;
}

@media print {
    .itflow-report-print-meta {
        display: block;
        padding: 0 1rem .5rem;
        font-size: .8rem;
        color: var(--bs-secondary-color);
    }
    .itflow-report-head .card-header {
        background-color: transparent !important;
        color: var(--bs-body-color) !important;
    }
    .itflow-report-head .card-title {
        font-size: 1.4rem;
    }
    .itflow-report .card {
        break-inside: avoid;
    }
    .itflow-report .card.itflow-report-long {
        break-inside: auto;
    }
    .itflow-report-stats,
    .itflow-report-heat td,
    .itflow-report-meter,
    .itflow-report-meter > span,
    .itflow-dash-aging > span,
    .itflow-dash-legend-swatch {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }
    .itflow-report-sortable::after {
        display: none;
    }
    .itflow-report-grid > :not(caption) > tr > :first-child {
        position: static;
    }
    .itflow-report .table-responsive {
        overflow: visible;
    }
    /* A printed page is narrower than the large breakpoint - keep side-by-side cards side by side */
    .itflow-report .row > .col-lg-4 { flex: 0 0 auto; width: 33.333%; }
    .itflow-report .row > .col-lg-5 { flex: 0 0 auto; width: 41.667%; }
    .itflow-report .row > .col-lg-6 { flex: 0 0 auto; width: 50%; }
    .itflow-report .row > .col-lg-7 { flex: 0 0 auto; width: 58.333%; }
    .itflow-report .row > .col-lg-8 { flex: 0 0 auto; width: 66.667%; }
    /* Chrome drops what a stretched card holds when it splits a row of them across pages */
    .itflow-report .row {
        break-inside: avoid;
    }
    .itflow-report .row .card.h-100 {
        height: auto !important;
    }
    .itflow-report .badge,
    .itflow-report .itflow-dash-dot,
    .itflow-report .progress-bar {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }
}

/* Shared links (functions/share.php) - the page the person it was sent to
   sees (guest/share.php), the QR code in the share window, and the list */
.itflow-share-page {
    max-width: 560px;
}
.itflow-share-page-wide {
    max-width: 960px;
}
.itflow-share-logo {
    max-height: 56px;
    max-width: 220px;
}
.itflow-share-icon {
    width: 3.5rem;
    height: 3.5rem;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.4rem;
}
.itflow-share-icon-sm {
    width: 2.5rem;
    height: 2.5rem;
    font-size: 1rem;
    flex-shrink: 0;
}
.itflow-share-note {
    background: var(--bs-tertiary-bg);
    border-left: 3px solid var(--bs-primary);
    border-radius: .25rem;
    padding: .6rem .8rem;
    white-space: pre-line;
    overflow-wrap: anywhere;
}
.itflow-share-secret {
    background: var(--bs-tertiary-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: .375rem;
    padding: 1rem 3.25rem 1rem 1rem;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    font-size: .95rem;
    max-height: 60vh;
    overflow: auto;
}
.itflow-share-otp {
    letter-spacing: .15em;
}
.itflow-share-otp-bar {
    height: .25rem;
}
.itflow-share-otp-bar .progress-bar {
    transition: width .25s linear;
}
.itflow-share-document {
    overflow-wrap: anywhere;
}
.itflow-share-qr {
    width: 180px;
    height: 180px;
    max-width: 100%;
}
.itflow-share-recipient {
    max-width: 220px;
}
@media print {
    .itflow-share-page {
        max-width: none;
        padding: 0 !important;
    }
    .itflow-share-page .card {
        border: 0;
        box-shadow: none !important;
    }
}

/* Billing - invoices, quotes and recurring invoices (includes/billing_paper.php,
   the agent billing pages and the guest invoice and quote pages) */
.itflow-paper {
    position: relative;
    padding: 2rem 2.25rem;
    background-color: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color-translucent);
    border-radius: var(--bs-border-radius-lg);
    box-shadow: 0 1px 3px rgba(0, 0, 0, .06);
    overflow: hidden;
}
.itflow-paper::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 4px;
    background-color: var(--bs-primary);
}
.itflow-paper-head,
.itflow-paper-parties,
.itflow-paper-bottom {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 1.25rem 2rem;
}
.itflow-paper-head {
    padding-bottom: 1.5rem;
    border-bottom: 1px solid var(--bs-border-color-translucent);
}
.itflow-paper-from {
    max-width: 24rem;
}
.itflow-paper-logo {
    display: block;
    max-width: 11rem;
    max-height: 4.5rem;
    margin-bottom: .75rem;
    object-fit: contain;
}
.itflow-paper-title {
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--bs-primary-text-emphasis);
}
.itflow-paper-dates {
    display: grid;
    grid-template-columns: auto auto;
    justify-content: end;
    gap: .15rem 1rem;
    margin: .5rem 0 0;
    font-size: .875rem;
}
.itflow-paper-dates dt {
    font-weight: 500;
    color: var(--bs-secondary-color);
}
.itflow-paper-dates dd {
    margin: 0;
}
.itflow-paper-parties {
    padding: 1.25rem 0;
}
.itflow-paper-label {
    margin-bottom: .2rem;
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}
.itflow-paper-label .text-transform-none {
    text-transform: none;
    letter-spacing: normal;
}
.itflow-paper-amount {
    font-size: 1.6rem;
    font-weight: 600;
    line-height: 1.2;
    font-variant-numeric: tabular-nums;
}
.itflow-paper-scope {
    margin-bottom: 1rem;
    padding: .55rem .85rem;
    border-radius: var(--bs-border-radius);
    background-color: var(--bs-tertiary-bg);
}
.itflow-paper-items {
    --bs-table-bg: transparent;
    font-variant-numeric: tabular-nums;
}
.itflow-paper-items thead th {
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
    border-bottom-width: 2px;
}
.itflow-paper-items td {
    padding-top: .7rem;
    padding-bottom: .7rem;
}
.itflow-paper-item {
    min-width: 12rem;
    width: 55%;
}
/* A line's rate under its tax wraps, so a long name ("Quebec GST + QST
   14.975%") doesn't widen the column past the paper */
.itflow-paper-tax-label {
    white-space: normal;
    min-width: 6.5rem;
    line-height: 1.25;
}
.itflow-paper-handle {
    width: 1.5rem;
    padding-left: 0 !important;
    padding-right: 0 !important;
}
.itflow-paper-handle .drag-handle {
    display: inline-block;
    padding: .1rem .25rem;
    color: var(--bs-secondary-color);
    cursor: grab;
    opacity: .5;
}
.itflow-paper-items tbody tr:hover .drag-handle {
    opacity: 1;
}
.itflow-paper-actions {
    width: 2.5rem;
}
.itflow-paper-actions .btn {
    padding-top: 0;
    padding-bottom: 0;
}
.itflow-paper-items tr.sortable-ghost {
    background-color: var(--bs-primary-bg-subtle);
}
.itflow-paper-items tr.itflow-paper-flash {
    animation: itflow-paper-flash 2s ease-out;
}
@keyframes itflow-paper-flash {
    from { background-color: var(--bs-warning-bg-subtle); }
    to { background-color: transparent; }
}
.itflow-paper-add > td {
    padding: .75rem !important;
    border-bottom: 0;
    background-color: var(--bs-tertiary-bg);
    border-radius: var(--bs-border-radius);
}
.itflow-paper-add-grid {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: .5rem;
}
.itflow-paper-add-item {
    flex: 1 1 15rem;
}
.itflow-paper-add-qty {
    flex: 0 0 4.5rem;
}
.itflow-paper-add-price {
    flex: 0 0 7rem;
}
.itflow-paper-add-seat {
    flex: 0 0 7.5rem;
}
/* A quote's lines billed once and each month, quarter or year - a heading over each, a block of totals each */
.itflow-paper-items tr.itflow-paper-group > td {
    padding-top: 1.1rem;
    padding-bottom: .35rem;
    border-bottom: 1px solid var(--bs-border-color);
}
.itflow-paper-items tbody tr.itflow-paper-group:first-child > td {
    padding-top: .5rem;
}
.itflow-paper-totals tr.itflow-paper-totals-head th {
    padding-top: .9rem;
    font-size: .7rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}
.itflow-paper-totals tr.itflow-paper-totals-head:first-child th {
    padding-top: 0;
}
/* Unbilled Time - an unticked row fades, the hours box is narrow, and the billing panel stays in view on wide screens */
.itflow-unbilled-table tr.itflow-unbilled-off > td:not(.checkbox-column) {
    opacity: .45;
}
.itflow-unbilled-table tbody tr[data-unbilled-row] {
    cursor: pointer;
}
.itflow-unbilled-hours {
    width: 6.5rem;
}
.itflow-unbilled-hours .form-control {
    min-width: 4.5rem;
}
@media (max-width: 575.98px) {
    .itflow-unbilled-hours {
        width: 4.75rem;
    }
    .itflow-unbilled-hours .form-control {
        min-width: 3.5rem;
    }
}
@media (min-width: 1200px) {
    .itflow-unbilled-panel {
        position: sticky;
        top: 4.5rem;
    }
}
/* A recurring invoice's add row has one more box - the item takes the top row, the numbers the one under it */
.itflow-paper-add-grid-seats .itflow-paper-add-item {
    flex-basis: 100%;
}
.itflow-paper-add-tax {
    flex: 0 1 9rem;
}
.itflow-paper-add-go {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin-left: auto;
}
.itflow-paper-bottom {
    align-items: flex-start;
    padding-top: 1.25rem;
}
.itflow-paper-notes {
    flex: 1 1 18rem;
    max-width: 32rem;
}
.itflow-paper-totals {
    flex: 0 1 19rem;
    margin-left: auto;
    font-size: .9rem;
    font-variant-numeric: tabular-nums;
}
.itflow-paper-totals th {
    padding: .25rem 1.5rem .25rem 0;
    font-weight: 500;
    color: var(--bs-secondary-color);
}
.itflow-paper-totals td {
    padding: .25rem 0;
    text-align: right;
    white-space: nowrap;
}
.itflow-paper-totals tr.text-success th,
.itflow-paper-totals tr.text-success td {
    color: var(--bs-success-text-emphasis);
}
.itflow-paper-totals .itflow-paper-total th,
.itflow-paper-totals .itflow-paper-total td {
    padding-top: .5rem;
    border-top: 1px solid var(--bs-border-color);
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--bs-emphasis-color);
}
.itflow-paper-footer {
    margin-top: 2rem;
    padding-top: 1rem;
    border-top: 1px solid var(--bs-border-color-translucent);
    font-size: .8rem;
    text-align: center;
    color: var(--bs-secondary-color);
}
.itflow-paper-stamp {
    position: absolute;
    top: 2.75rem;
    left: 50%;
    margin-left: -4rem;
    padding: .2rem .9rem;
    border: 3px solid currentColor;
    border-radius: var(--bs-border-radius);
    font-size: 1.35rem;
    font-weight: 700;
    letter-spacing: .14em;
    text-transform: uppercase;
    opacity: .3;
    transform: rotate(-12deg);
    pointer-events: none;
}
@media (max-width: 767.98px) {
    .itflow-paper {
        padding: 1.25rem 1rem;
    }
    .itflow-paper-dates {
        justify-content: start;
    }
    .itflow-paper-totals {
        flex-basis: 100%;
    }
    .itflow-paper-stamp {
        display: none;
    }
}

/* Header tile and money on the billing pages and lists */
.itflow-billing-tile {
    --itflow-asset-tone: var(--bs-primary);
}
.itflow-billing-tile-invoice { --itflow-asset-tone: #2f6fd8; }
.itflow-billing-tile-quote { --itflow-asset-tone: #8a55d6; }
.itflow-billing-tile-recurring { --itflow-asset-tone: #1f9d83; }
[data-bs-theme="dark"] .itflow-billing-tile-invoice { --itflow-asset-tone: #6f9fe0; }
[data-bs-theme="dark"] .itflow-billing-tile-quote { --itflow-asset-tone: #b08ae8; }
[data-bs-theme="dark"] .itflow-billing-tile-recurring { --itflow-asset-tone: #4fc4b0; }

/* Products - a tile by type, and the type choice in New and Edit */
.itflow-product-tile-service { --itflow-asset-tone: #0f8a9d; }
.itflow-product-tile-product { --itflow-asset-tone: #c4720f; }
[data-bs-theme="dark"] .itflow-product-tile-service { --itflow-asset-tone: #4cc3d4; }
[data-bs-theme="dark"] .itflow-product-tile-product { --itflow-asset-tone: #f0a24a; }
.itflow-product-type .btn {
    flex: 1 1 0;
    padding-top: .55rem;
    padding-bottom: .55rem;
    line-height: 1.25;
}
.itflow-product-type .btn-check:checked + .btn {
    color: var(--bs-primary-text-emphasis);
    background-color: var(--bs-primary-bg-subtle);
    border-color: var(--bs-primary-border-subtle);
}

/* Sold hardware - Add to Assets, a block per invoice line with a row per unit */
.itflow-hw-line {
    padding: .75rem;
    border: 1px solid var(--bs-border-color-translucent);
    border-radius: var(--bs-border-radius-lg);
    background-color: var(--bs-tertiary-bg);
}
.itflow-hw-unit + .itflow-hw-unit {
    margin-top: .375rem;
}
.itflow-hw-linking .input-group:has([data-hw-new]) {
    opacity: .45;
}
.itflow-hw-assets {
    padding-left: 2.25rem;
}

/* Update Prices - lines not picked are muted, the footer stays in reach */
.itflow-reprice-off td:not(.checkbox-column) {
    opacity: .55;
}
.itflow-reprice-table .input-group {
    min-width: 8.5rem;
}
.itflow-reprice-footer {
    position: sticky;
    bottom: 0;
    z-index: 2;
    background-color: var(--bs-body-bg);
}
.itflow-money {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.itflow-billing-stat {
    display: block;
    height: 100%;
    padding: .9rem 1.1rem;
    border: 1px solid var(--bs-border-color-translucent);
    border-radius: var(--bs-border-radius-lg);
    background-color: var(--bs-body-bg);
    color: inherit;
    text-decoration: none;
    transition: border-color .12s ease-in-out, box-shadow .12s ease-in-out;
}
a.itflow-billing-stat:hover {
    border-color: var(--bs-primary-border-subtle);
    box-shadow: 0 1px 4px rgba(0, 0, 0, .06);
    color: inherit;
}
.itflow-billing-stat.active {
    border-color: var(--bs-primary);
    box-shadow: inset 0 0 0 1px var(--bs-primary);
}
.itflow-billing-stat-label {
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}
.itflow-billing-stat-value {
    margin-top: .15rem;
    font-size: 1.45rem;
    font-weight: 600;
    line-height: 1.25;
    font-variant-numeric: tabular-nums;
}
.itflow-billing-stat-note {
    font-size: .8rem;
    color: var(--bs-secondary-color);
}
.itflow-billing-progress {
    height: .45rem;
}
.itflow-billing-table td {
    padding-top: .65rem;
    padding-bottom: .65rem;
}
.itflow-billing-number {
    min-width: 13rem;
}
.itflow-billing-history {
    max-height: 26rem;
    overflow-y: auto;
}
.itflow-billing-history li {
    position: relative;
    padding: 0 0 .85rem 1.35rem;
    font-size: .875rem;
}
.itflow-billing-history li::before {
    content: "";
    position: absolute;
    left: .3rem;
    top: .45rem;
    width: .5rem;
    height: .5rem;
    border-radius: 50%;
    background-color: var(--bs-secondary-color);
}
.itflow-billing-history li::after {
    content: "";
    position: absolute;
    left: .52rem;
    top: 1.1rem;
    bottom: .1rem;
    width: 1px;
    background-color: var(--bs-border-color);
}
.itflow-billing-history li:last-child::after {
    display: none;
}
@media print {
    .itflow-paper-col {
        flex: 0 0 100% !important;
        width: 100% !important;
        max-width: 100% !important;
    }
    .itflow-paper {
        border: 0;
        box-shadow: none;
        padding: 0;
    }
    .itflow-paper::before {
        display: none;
    }
}

/* ---------- Expenses (agent/expenses.php, modals/expense/) ---------- */
.itflow-category-dot {
    display: inline-block;
    width: .6rem;
    height: .6rem;
    margin-right: .45rem;
    border-radius: 50%;
    background-color: var(--bs-secondary-bg);
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12);
    vertical-align: .05rem;
}
.itflow-expense-receipt-empty {
    padding: 1.25rem 1rem;
    border: 1px dashed var(--bs-border-color);
    border-radius: var(--bs-border-radius-lg);
    background-color: var(--bs-tertiary-bg);
    color: var(--bs-secondary-color);
    text-align: center;
}
/* Unbilled Time - an expense's price box, and its row ticks like a ticket's */
.itflow-unbilled-table tbody tr[data-unbilled-expense-row] {
    cursor: pointer;
}
.itflow-unbilled-price {
    width: 7.5rem;
}
.itflow-unbilled-price .form-control {
    min-width: 5.5rem;
}
@media (max-width: 575.98px) {
    .itflow-unbilled-price {
        width: 6rem;
    }
    .itflow-unbilled-price .form-control {
        min-width: 4.5rem;
    }
}
/* Import Statement's review - the statement text keeps to a width, the picks stay usable, the Import bar stays in view */
.itflow-import-table tbody tr[data-import-row] {
    cursor: pointer;
}
.itflow-import-table .itflow-import-text {
    max-width: 22rem;
    min-width: 12rem;
}
.itflow-import-table .itflow-import-pick {
    min-width: 10.5rem;
}
.itflow-import-footer {
    position: sticky;
    bottom: 0;
    z-index: 3;
    background-color: var(--bs-tertiary-bg);
}
/* Trips - the route and what for take the room left and cut short, rather than push the miles off the side (agent/trips.php, a site's Trips tab) */
.itflow-trip-route {
    width: 100%;
    max-width: 0;
    min-width: 14rem;
}
/* Income - what it was takes the room left and cuts short, rather than push the amount off the side (agent/income.php) */
.itflow-income-from {
    width: 100%;
    max-width: 0;
    min-width: 14rem;
}
/* Import Deposits' review - what a deposit pays, with the client's invoices to tick (agent/income_import.php) */
.itflow-import-table .itflow-import-details {
    min-width: 16rem;
    max-width: 24rem;
}
.itflow-import-invoices {
    max-height: 7.5rem;
    overflow-y: auto;
    padding: 0.25rem 0.5rem;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-sm);
    background-color: var(--bs-body-bg);
}
.itflow-import-invoices.is-invalid {
    border-color: var(--bs-form-invalid-border-color);
}
/* Accounts and their ledger - the account's name, and who or what each line is, take the room left and cut short (agent/accounts.php, agent/transactions.php) */
.itflow-account-name,
.itflow-ledger-what {
    width: 100%;
    max-width: 0;
    min-width: 14rem;
}
/* A deposit out of a cash account - what is waiting in it, to tick (agent/modals/transfer/transfer_form.php) */
.itflow-deposit-list {
    max-height: 16rem;
    overflow-y: auto;
}

/* Reconcile - agent/reconcile.php. A line ticked as cleared on the statement
   takes the success tint; the Difference card turns green once it balances. */
.itflow-reconcile-table > tbody > tr.itflow-reconcile-ticked > * {
    --bs-table-bg-type: rgba(var(--bs-success-rgb), .07);
}
/* AdminLTE's .app-main is overflow: auto, which makes it the bar's scroll box,
   but the page scrolls the window - so on this page it lets the bar stick */
.app-main:has(.itflow-reconcile-bar),
.layout-fixed .app-main:has(.itflow-reconcile-bar) {
    overflow: visible;
}
.itflow-reconcile-bar {
    position: sticky;
    bottom: 0;
    z-index: 3;
    background-color: var(--bs-body-bg);
    box-shadow: 0 -.25rem .75rem rgba(0, 0, 0, .06);
}
.itflow-billing-stat.itflow-reconcile-balanced {
    border-color: var(--bs-success-border-subtle);
    background-color: var(--bs-success-bg-subtle);
}
.itflow-reconcile-table .form-check-input {
    width: 1.15rem;
    height: 1.15rem;
    margin-top: 0;
    cursor: pointer;
}

/* ==========================================================================
   Client portal (client/) - the shell from client/includes/header.php and
   the pages built on it. The portal sets a CSP of default-src 'self', so
   nothing here may lean on inline styles: every look is a class.
   ========================================================================== */
.itflow-portal {
    --itflow-portal-header-height: 4rem;
    --itflow-portal-tabbar-height: 3.75rem;
}
.itflow-portal-header {
    position: sticky;
    top: 0;
    z-index: 1030;
    display: flex;
    align-items: center;
    min-height: var(--itflow-portal-header-height);
    background-color: var(--bs-body-bg);
    border-bottom: 1px solid var(--bs-border-color-translucent);
    box-shadow: 0 1px 3px rgba(0, 0, 0, .04);
}
.itflow-portal-brand {
    display: inline-flex;
    flex: 0 1 auto;
    align-items: center;
    gap: .6rem;
    min-width: 0;
    color: var(--bs-emphasis-color);
    font-weight: 600;
    text-decoration: none;
}
.itflow-portal-brand:hover {
    color: var(--bs-emphasis-color);
}
.itflow-portal-brand img {
    display: block;
    height: 2.25rem;
    max-width: 11rem;
    object-fit: contain;
}
.itflow-portal-brand .itflow-brand-mark-initials {
    width: 2.25rem;
    height: 2.25rem;
    font-size: .75rem;
}
.itflow-portal-brand-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.itflow-portal-nav {
    align-items: center;
    gap: .15rem;
}
.itflow-portal-nav-link {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    padding: .45rem .75rem;
    border-radius: var(--bs-border-radius);
    color: var(--bs-secondary-color);
    font-weight: 500;
    text-decoration: none;
    white-space: nowrap;
}
.itflow-portal-nav-link:hover,
.itflow-portal-nav-link.show {
    background-color: var(--bs-tertiary-bg);
    color: var(--bs-emphasis-color);
}
.itflow-portal-nav-link.active {
    background-color: color-mix(in srgb, var(--itflow-accent, #007bff) 12%, transparent);
    color: var(--itflow-accent, #007bff);
}
.itflow-portal .dropdown-item.active,
.itflow-portal .dropdown-item:active {
    background-color: color-mix(in srgb, var(--itflow-accent, #007bff) 12%, transparent);
    color: var(--itflow-accent, #007bff);
}
.itflow-portal .dropdown-item i {
    color: var(--bs-secondary-color);
}
.itflow-portal .dropdown-item.active i {
    color: inherit;
}
.itflow-portal-account {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    max-width: 16rem;
    padding: .25rem .5rem .25rem .25rem;
    border: 0;
    border-radius: 2rem;
    background: transparent;
    color: var(--bs-body-color);
}
.itflow-portal-account:hover,
.itflow-portal-account[aria-expanded="true"] {
    background-color: var(--bs-tertiary-bg);
}

/* Avatars - a photo, or initials on a soft tone picked from the name */
.itflow-portal-avatar {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    object-fit: cover;
    font-size: .75rem;
    font-weight: 600;
    line-height: 1;
}
.itflow-portal-avatar-sm { width: 1.75rem; height: 1.75rem; font-size: .65rem; }
.itflow-portal-avatar-lg { width: 2.5rem; height: 2.5rem; font-size: .85rem; }
.itflow-portal-avatar-xl { width: 3.25rem; height: 3.25rem; font-size: 1.05rem; }
.itflow-portal-avatar-tone-1 { background-color: var(--bs-primary-bg-subtle); color: var(--bs-primary-text-emphasis); }
.itflow-portal-avatar-tone-2 { background-color: var(--bs-success-bg-subtle); color: var(--bs-success-text-emphasis); }
.itflow-portal-avatar-tone-3 { background-color: var(--bs-warning-bg-subtle); color: var(--bs-warning-text-emphasis); }
.itflow-portal-avatar-tone-4 { background-color: var(--bs-danger-bg-subtle); color: var(--bs-danger-text-emphasis); }
.itflow-portal-avatar-tone-5 { background-color: var(--bs-info-bg-subtle); color: var(--bs-info-text-emphasis); }
.itflow-portal-avatar-tone-6 { background-color: var(--bs-secondary-bg); color: var(--bs-secondary-color); }

.itflow-portal-main {
    flex: 1 0 auto;
    padding-top: 1.5rem;
    padding-bottom: 2rem;
}
.itflow-portal-footer {
    padding: .9rem 0;
    border-top: 1px solid var(--bs-border-color-translucent);
    background-color: var(--bs-body-bg);
    color: var(--bs-secondary-color);
    font-size: .8rem;
}

/* Phone: the tab bar along the bottom, and the menu that slides in */
.itflow-portal-tabbar {
    position: fixed;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 1030;
    display: flex;
    height: calc(var(--itflow-portal-tabbar-height) + env(safe-area-inset-bottom, 0px));
    padding-bottom: env(safe-area-inset-bottom, 0px);
    border-top: 1px solid var(--bs-border-color-translucent);
    background-color: var(--bs-body-bg);
    box-shadow: 0 -1px 4px rgba(0, 0, 0, .05);
}
.itflow-portal-tabbar a {
    display: flex;
    flex: 1 1 0;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .2rem;
    min-width: 0;
    color: var(--bs-secondary-color);
    font-size: .7rem;
    text-decoration: none;
}
.itflow-portal-tabbar a i {
    font-size: 1.1rem;
}
.itflow-portal-tabbar a.active {
    color: var(--itflow-accent, #007bff);
    font-weight: 600;
}
.itflow-portal-tabbar a.itflow-portal-tabbar-new i {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.1rem;
    height: 2.1rem;
    border-radius: 50%;
    background-color: var(--bs-primary);
    color: #fff;
    font-size: .95rem;
}
@media (max-width: 991.98px) {
    .itflow-portal {
        padding-bottom: calc(var(--itflow-portal-tabbar-height) + env(safe-area-inset-bottom, 0px));
    }
    .itflow-portal-main {
        padding-top: 1rem;
    }
}
.itflow-portal-menu {
    --bs-offcanvas-width: min(20rem, 85vw);
}
.itflow-portal-menu-heading {
    margin: 1rem 0 .35rem;
    color: var(--bs-secondary-color);
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
}
.itflow-portal-menu-heading:first-child {
    margin-top: 0;
}
.itflow-portal-menu-link {
    display: flex;
    align-items: center;
    gap: .65rem;
    width: 100%;
    padding: .55rem .6rem;
    border: 0;
    border-radius: var(--bs-border-radius);
    background: transparent;
    color: var(--bs-body-color);
    text-align: start;
    text-decoration: none;
}
.itflow-portal-menu-link i {
    color: var(--bs-secondary-color);
}
.itflow-portal-menu-link:hover {
    background-color: var(--bs-tertiary-bg);
    color: var(--bs-emphasis-color);
}
.itflow-portal-menu-link.active {
    background-color: color-mix(in srgb, var(--itflow-accent, #007bff) 12%, transparent);
    color: var(--itflow-accent, #007bff);
    font-weight: 600;
}
.itflow-portal-menu-link.active i {
    color: inherit;
}

/* A page's title row: the title with a line under it, and its buttons */
.itflow-portal-page-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: .75rem 1rem;
    margin-bottom: 1.25rem;
}
.itflow-portal-page-head h1 {
    margin: 0;
    font-size: 1.5rem;
    font-weight: 600;
}
.itflow-portal-page-head p {
    margin: .2rem 0 0;
    color: var(--bs-secondary-color);
}
.itflow-portal-back {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    margin-bottom: .5rem;
    color: var(--bs-secondary-color);
    font-size: .875rem;
    text-decoration: none;
}
.itflow-portal-back:hover {
    color: var(--bs-emphasis-color);
}

/* A plain panel - the portal's cards */
.itflow-portal-panel {
    overflow: hidden;
    border: 1px solid var(--bs-border-color-translucent);
    border-radius: var(--bs-border-radius-lg);
    background-color: var(--bs-body-bg);
}
.itflow-portal-panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    padding: .85rem 1.1rem;
    border-bottom: 1px solid var(--bs-border-color-translucent);
}
.itflow-portal-panel-head h2 {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
}
.itflow-portal-panel-head h2 i {
    margin-right: .45rem;
    color: var(--bs-secondary-color);
}
.itflow-portal-panel-head a {
    font-size: .85rem;
    text-decoration: none;
}
.itflow-portal-panel-body {
    padding: 1rem 1.1rem;
}
.itflow-portal-panel .itflow-empty-state {
    padding: 2rem 1rem;
}

/* Where a ticket stands, for the client */
.itflow-portal-state {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    padding: .2rem .6rem;
    border-radius: 2rem;
    font-size: .75rem;
    font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
}
.itflow-portal-state i {
    width: auto;
    font-size: .7rem;
}
.itflow-portal-state-new { background-color: var(--bs-info-bg-subtle); color: var(--bs-info-text-emphasis); }
.itflow-portal-state-progress { background-color: var(--bs-primary-bg-subtle); color: var(--bs-primary-text-emphasis); }
.itflow-portal-state-you { background-color: var(--bs-warning-bg-subtle); color: var(--bs-warning-text-emphasis); }
.itflow-portal-state-hold { background-color: var(--bs-secondary-bg); color: var(--bs-secondary-color); }
.itflow-portal-state-resolved { background-color: var(--bs-success-bg-subtle); color: var(--bs-success-text-emphasis); }
.itflow-portal-state-closed { background-color: var(--bs-tertiary-bg); color: var(--bs-secondary-color); }

/* Tabs along the top of a list, underlined, each with its count */
.itflow-portal-tabs {
    display: flex;
    gap: .25rem;
    margin-bottom: 1rem;
    border-bottom: 1px solid var(--bs-border-color-translucent);
    overflow-x: auto;
    scrollbar-width: none;
}
.itflow-portal-tabs a {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    gap: .45rem;
    padding: .6rem .8rem;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    color: var(--bs-secondary-color);
    font-weight: 500;
    text-decoration: none;
    white-space: nowrap;
}
.itflow-portal-tabs a:hover {
    color: var(--bs-emphasis-color);
}
.itflow-portal-tabs a.active {
    border-bottom-color: var(--itflow-accent, #007bff);
    color: var(--bs-emphasis-color);
    font-weight: 600;
}
.itflow-portal-tabs .badge {
    background-color: var(--bs-tertiary-bg);
    color: var(--bs-secondary-color);
    font-weight: 600;
}
.itflow-portal-tabs a.itflow-portal-tab-alert .badge {
    background-color: var(--bs-warning-bg-subtle);
    color: var(--bs-warning-text-emphasis);
}

/* A list of tickets */
.itflow-portal-list {
    margin: 0;
    padding: 0;
    list-style: none;
}
.itflow-portal-list > li + li {
    border-top: 1px solid var(--bs-border-color-translucent);
}
.itflow-portal-ticket {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: .85rem 1.1rem;
    color: inherit;
    text-decoration: none;
}
a.itflow-portal-ticket:hover {
    background-color: var(--bs-tertiary-bg);
    color: inherit;
}
.itflow-portal-ticket-main {
    flex: 1 1 auto;
    min-width: 0;
}
.itflow-portal-ticket-subject {
    overflow: hidden;
    color: var(--bs-emphasis-color);
    font-weight: 600;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.itflow-portal-ticket-meta {
    display: flex;
    flex-wrap: wrap;
    gap: .15rem .9rem;
    margin-top: .15rem;
    color: var(--bs-secondary-color);
    font-size: .8rem;
}
.itflow-portal-ticket-side {
    display: flex;
    flex: 0 0 auto;
    flex-direction: column;
    align-items: flex-end;
    gap: .3rem;
    text-align: end;
}
.itflow-portal-ticket-side small {
    color: var(--bs-secondary-color);
}
@media (max-width: 575.98px) {
    .itflow-portal-ticket {
        flex-wrap: wrap;
        gap: .5rem;
        padding: .8rem .9rem;
    }
    .itflow-portal-ticket-side {
        flex-direction: row;
        align-items: center;
        gap: .6rem;
    }
}

/* Paging under a list */
.itflow-portal-pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    padding: .75rem 1.1rem;
    border-top: 1px solid var(--bs-border-color-translucent);
    color: var(--bs-secondary-color);
    font-size: .85rem;
}

/* A ticket's progress: received, in progress, resolved, closed */
.itflow-portal-steps {
    display: flex;
    margin: 0;
    padding: 0;
    list-style: none;
    counter-reset: step;
}
.itflow-portal-steps li {
    position: relative;
    flex: 1 1 0;
    padding-top: 1.6rem;
    color: var(--bs-secondary-color);
    font-size: .78rem;
    text-align: center;
}
.itflow-portal-steps li::before {
    content: "";
    position: absolute;
    top: .35rem;
    left: 50%;
    z-index: 1;
    width: .8rem;
    height: .8rem;
    margin-left: -.4rem;
    border: 2px solid var(--bs-border-color);
    border-radius: 50%;
    background-color: var(--bs-body-bg);
}
.itflow-portal-steps li + li::after {
    content: "";
    position: absolute;
    top: .7rem;
    right: 50%;
    left: -50%;
    height: 2px;
    background-color: var(--bs-border-color);
}
.itflow-portal-steps li.done::before,
.itflow-portal-steps li.current::before {
    border-color: var(--itflow-accent, #007bff);
    background-color: var(--itflow-accent, #007bff);
}
.itflow-portal-steps li.done + li::after,
.itflow-portal-steps li.done + li.current::after {
    background-color: var(--itflow-accent, #007bff);
}
.itflow-portal-steps li.current {
    color: var(--bs-emphasis-color);
    font-weight: 600;
}
.itflow-portal-steps li.current::before {
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--itflow-accent, #007bff) 22%, transparent);
}

/* The conversation on a ticket - oldest first, the client's own on the right */
.itflow-portal-thread {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}
.itflow-portal-msg {
    display: flex;
    align-items: flex-start;
    gap: .75rem;
    max-width: 100%;
}
.itflow-portal-msg-mine {
    flex-direction: row-reverse;
}
.itflow-portal-msg-body {
    min-width: 0;
    max-width: min(46rem, calc(100% - 3rem));
}
.itflow-portal-msg-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .2rem .6rem;
    margin-bottom: .3rem;
    font-size: .8rem;
}
.itflow-portal-msg-mine .itflow-portal-msg-head {
    justify-content: flex-end;
}
.itflow-portal-msg-head strong {
    color: var(--bs-emphasis-color);
}
.itflow-portal-msg-head span {
    color: var(--bs-secondary-color);
}
.itflow-portal-msg-bubble {
    padding: .75rem 1rem;
    border: 1px solid var(--bs-border-color-translucent);
    border-radius: var(--bs-border-radius-lg);
    border-top-left-radius: .25rem;
    background-color: var(--bs-body-bg);
    overflow-wrap: anywhere;
}
.itflow-portal-msg-mine .itflow-portal-msg-bubble {
    border-color: color-mix(in srgb, var(--itflow-accent, #007bff) 25%, transparent);
    border-top-left-radius: var(--bs-border-radius-lg);
    border-top-right-radius: .25rem;
    background-color: color-mix(in srgb, var(--itflow-accent, #007bff) 7%, var(--bs-body-bg));
}
.itflow-portal-msg-bubble > :last-child {
    margin-bottom: 0;
}
.itflow-portal-msg-bubble img {
    max-width: 100%;
    height: auto;
}
.itflow-portal-event {
    display: flex;
    align-items: center;
    gap: .75rem;
    color: var(--bs-secondary-color);
    font-size: .8rem;
}
.itflow-portal-event::before,
.itflow-portal-event::after {
    content: "";
    flex: 1 1 auto;
    height: 1px;
    background-color: var(--bs-border-color-translucent);
}

/* Attachments - on a message, and the drop zone on a form */
.itflow-portal-files {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
    margin-top: .6rem;
}
.itflow-portal-file-chip {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    max-width: 100%;
    padding: .3rem .65rem;
    border: 1px solid var(--bs-border-color-translucent);
    border-radius: 2rem;
    background-color: var(--bs-tertiary-bg);
    color: var(--bs-body-color);
    font-size: .8rem;
    text-decoration: none;
}
a.itflow-portal-file-chip:hover {
    border-color: var(--bs-primary-border-subtle);
    color: var(--bs-emphasis-color);
}
.itflow-portal-file-chip i {
    color: var(--bs-secondary-color);
}
.itflow-portal-drop {
    position: relative;
    padding: .9rem 1rem;
    border: 1px dashed var(--bs-border-color);
    border-radius: var(--bs-border-radius-lg);
    color: var(--bs-secondary-color);
    font-size: .875rem;
    transition: border-color .12s ease-in-out, background-color .12s ease-in-out;
}
.itflow-portal-drop.is-dragging {
    border-color: var(--itflow-accent, #007bff);
    background-color: color-mix(in srgb, var(--itflow-accent, #007bff) 6%, transparent);
}
.itflow-portal-drop input[type=file] {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}
.itflow-portal-drop label {
    color: var(--itflow-accent, #007bff);
    font-weight: 600;
    cursor: pointer;
}
.itflow-portal-drop input[type=file]:focus-visible + label {
    outline: 2px solid var(--itflow-accent, #007bff);
    outline-offset: 2px;
}
.itflow-portal-drop .itflow-portal-files {
    margin-top: .6rem;
}
.tox-tinymce.is-invalid {
    border-color: var(--bs-form-invalid-border-color) !important;
}

/* Details down the side of a ticket */
.itflow-portal-facts {
    margin: 0;
}
.itflow-portal-facts > div {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: .55rem 0;
}
.itflow-portal-facts > div + div {
    border-top: 1px solid var(--bs-border-color-translucent);
}
.itflow-portal-facts dt {
    color: var(--bs-secondary-color);
    font-weight: 400;
}
.itflow-portal-facts dd {
    margin: 0;
    min-width: 0;
    text-align: end;
    overflow-wrap: anywhere;
}

/* Home: the figures along the top and the "needs you" list */
.itflow-portal-stat {
    display: flex;
    align-items: center;
    gap: .9rem;
    height: 100%;
    padding: 1rem 1.1rem;
    border: 1px solid var(--bs-border-color-translucent);
    border-radius: var(--bs-border-radius-lg);
    background-color: var(--bs-body-bg);
    color: inherit;
    text-decoration: none;
}
a.itflow-portal-stat:hover {
    border-color: var(--bs-primary-border-subtle);
    box-shadow: 0 1px 4px rgba(0, 0, 0, .06);
    color: inherit;
}
.itflow-portal-stat-icon {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 2.6rem;
    height: 2.6rem;
    border-radius: 50%;
    background-color: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
    font-size: 1.05rem;
}
.itflow-portal-stat-value {
    color: var(--bs-emphasis-color);
    font-size: 1.35rem;
    font-weight: 600;
    line-height: 1.2;
}
.itflow-portal-stat-label {
    color: var(--bs-secondary-color);
    font-size: .8rem;
}
.itflow-portal-stat > span:last-child {
    min-width: 0;
    overflow-wrap: anywhere;
}
@media (max-width: 575.98px) {
    .itflow-portal-stat {
        flex-direction: column;
        align-items: flex-start;
        gap: .5rem;
        padding: .85rem;
    }
    .itflow-portal-stat-icon {
        width: 2.1rem;
        height: 2.1rem;
        font-size: .9rem;
    }
    .itflow-portal-stat-value {
        font-size: 1.15rem;
    }
}
.itflow-portal-stat-alert .itflow-portal-stat-icon {
    background-color: var(--bs-warning-bg-subtle);
    color: var(--bs-warning-text-emphasis);
}
.itflow-portal-stat-danger .itflow-portal-stat-icon {
    background-color: var(--bs-danger-bg-subtle);
    color: var(--bs-danger-text-emphasis);
}
.itflow-portal-todo {
    display: flex;
    align-items: center;
    gap: .85rem;
    padding: .75rem 1.1rem;
    color: inherit;
    text-decoration: none;
}
a.itflow-portal-todo:hover {
    background-color: var(--bs-tertiary-bg);
    color: inherit;
}
.itflow-portal-todo-icon {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    background-color: var(--bs-warning-bg-subtle);
    color: var(--bs-warning-text-emphasis);
    font-size: .8rem;
}
.itflow-portal-todo-icon.is-danger {
    background-color: var(--bs-danger-bg-subtle);
    color: var(--bs-danger-text-emphasis);
}
.itflow-portal-todo-icon.is-info {
    background-color: var(--bs-info-bg-subtle);
    color: var(--bs-info-text-emphasis);
}
.itflow-portal-todo-main {
    flex: 1 1 auto;
    min-width: 0;
}
.itflow-portal-todo-main div:first-child {
    overflow: hidden;
    color: var(--bs-emphasis-color);
    font-weight: 600;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.itflow-portal-todo-main div + div {
    color: var(--bs-secondary-color);
    font-size: .8rem;
}
/* A row to be read whole - the guest ticket page's booking and approvals: the
   title wraps rather than being cut off on a phone, and the button keeps to one line */
.itflow-portal-todo-wrap .itflow-portal-todo-main div:first-child {
    white-space: normal;
}
.itflow-portal-todo-wrap > .btn {
    flex: 0 0 auto;
    white-space: nowrap;
}
@media (max-width: 575.98px) {
    /* The button goes under the text, in line with it, so the text keeps the width */
    .itflow-portal-todo-wrap {
        flex-wrap: wrap;
    }
    .itflow-portal-todo-wrap .itflow-portal-todo-main {
        flex-basis: calc(100% - 2.85rem);
    }
    .itflow-portal-todo-wrap > .btn {
        margin-left: 2.85rem;
    }
}

.itflow-portal-preview-image {
    max-height: 600px;
}

/* Billing: amounts down the side of a list, a document's state, and the big
   figure on an invoice, quote or receipt */
.itflow-portal-amount {
    color: var(--bs-emphasis-color);
    font-weight: 600;
}
.itflow-portal-amount small {
    color: var(--bs-secondary-color);
    font-size: .75rem;
}
.itflow-portal-state-late { background-color: var(--bs-danger-bg-subtle); color: var(--bs-danger-text-emphasis); }
.itflow-portal-big-amount {
    color: var(--bs-emphasis-color);
    font-size: 1.75rem;
    font-weight: 600;
    line-height: 1.2;
    margin: .15rem 0 .5rem;
}
.itflow-portal-outcome {
    display: flex;
    align-items: center;
    gap: .85rem;
}
.itflow-portal-outcome-icon {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    background-color: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
}
.itflow-portal-outcome-icon.is-success {
    background-color: var(--bs-success-bg-subtle);
    color: var(--bs-success-text-emphasis);
}
.itflow-portal-outcome-icon.is-warning {
    background-color: var(--bs-warning-bg-subtle);
    color: var(--bs-warning-text-emphasis);
}
.itflow-portal-note {
    display: flex;
    gap: .6rem;
    padding: .65rem .8rem;
    border-radius: var(--bs-border-radius);
    background-color: var(--bs-tertiary-bg);
    font-size: .85rem;
}
.itflow-portal-note i {
    margin-top: .15rem;
    color: var(--bs-secondary-color);
}

/* Pay invoices: a row to tick, the ways to pay, and the total with its button */
.itflow-portal-payrow {
    cursor: pointer;
    margin: 0;
}
.itflow-portal-payrow > .form-check-input {
    flex: 0 0 auto;
    width: 1.2rem;
    height: 1.2rem;
    margin: 0;
}
@media (max-width: 575.98px) {
    .itflow-portal-payrow {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr);
        align-items: start;
        column-gap: .75rem;
    }
    .itflow-portal-payrow > .form-check-input {
        margin-top: .2rem;
    }
    .itflow-portal-payrow > .itflow-portal-ticket-side {
        grid-column: 2;
    }
}
.itflow-portal-list > li.is-selected {
    background-color: rgba(var(--bs-primary-rgb), .05);
}
.itflow-portal-list > li.is-selected .itflow-portal-payrow:hover {
    background-color: transparent;
}
@media (min-width: 992px) {
    .itflow-portal-paybox {
        position: sticky;
        top: calc(var(--itflow-portal-header-height) + 1rem);
    }
}
.itflow-portal-methods {
    display: grid;
    gap: .5rem;
}
.itflow-portal-method {
    display: flex;
    align-items: center;
    gap: .75rem;
    margin: 0;
    padding: .65rem .8rem;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    cursor: pointer;
}
.itflow-portal-method .form-check-input {
    flex: 0 0 auto;
    margin: 0;
}
.itflow-portal-method:has(input:checked) {
    border-color: var(--bs-primary);
    box-shadow: inset 0 0 0 1px var(--bs-primary);
}
.itflow-portal-method.is-disabled {
    cursor: not-allowed;
    opacity: .6;
}
.itflow-portal-paybar {
    padding: 1rem 1.1rem;
    border-top: 1px solid var(--bs-border-color-translucent);
    background-color: var(--bs-tertiary-bg);
}
.itflow-portal-paybar .itflow-portal-big-amount {
    margin: 0;
}
.itflow-portal-stripe-element {
    min-height: 3rem;
}

/* A saved card's brand, in a grey tile */
.itflow-portal-card-brand {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2rem;
    border-radius: var(--bs-border-radius);
    background-color: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
    font-size: 1.25rem;
}

/* Statement: how late, in five tiles */
.itflow-portal-aging {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: .5rem;
    height: 100%;
}
.itflow-portal-aging > div {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: .15rem;
    padding: .6rem .7rem;
    border: 1px solid var(--bs-border-color-translucent);
    border-radius: var(--bs-border-radius-lg);
    background-color: var(--bs-body-bg);
    min-width: 0;
}
.itflow-portal-aging span {
    color: var(--bs-secondary-color);
    font-size: .72rem;
    white-space: nowrap;
}
.itflow-portal-aging strong {
    overflow: hidden;
    color: var(--bs-emphasis-color);
    font-size: .9rem;
    text-overflow: ellipsis;
}
.itflow-portal-aging .is-late strong {
    color: var(--bs-danger-text-emphasis);
}
@media (max-width: 575.98px) {
    .itflow-portal-aging {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}
.itflow-portal-table > thead th {
    color: var(--bs-secondary-color);
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
}
.itflow-portal-panel .table > :not(caption) > * > * {
    padding-left: 1.1rem;
    padding-right: 1.1rem;
}

/* A receipt */
.itflow-portal-receipt {
    max-width: 46rem;
}
.itflow-portal-receipt-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 1.25rem 1.1rem;
    border-bottom: 1px solid var(--bs-border-color-translucent);
}
.itflow-portal-receipt-head .itflow-portal-big-amount {
    margin: 0;
}
.itflow-portal-receipt-foot {
    padding: .9rem 1.1rem;
    border-top: 1px solid var(--bs-border-color-translucent);
    color: var(--bs-secondary-color);
    font-size: .8rem;
}

/* Your IT: a grey tile for each device, license, domain or document, the
   roles on a contact, and a document as written */
.itflow-portal-tile {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--bs-border-radius-lg);
    background-color: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
    font-size: 1rem;
}
.itflow-portal-tile-sm {
    width: 2rem;
    height: 2rem;
    font-size: .85rem;
}
.itflow-portal-tile-lg {
    width: 3.25rem;
    height: 3.25rem;
    font-size: 1.35rem;
}

/* New ticket: report a problem, or one of the request forms */
.itflow-portal-requests {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
    gap: .75rem;
}
.itflow-portal-request {
    display: flex;
    align-items: flex-start;
    gap: .85rem;
    height: 100%;
    padding: 1rem 1.1rem;
    border: 1px solid var(--bs-border-color-translucent);
    border-radius: var(--bs-border-radius-lg);
    background-color: var(--bs-body-bg);
    color: inherit;
    text-decoration: none;
}
a.itflow-portal-request:hover,
a.itflow-portal-request:focus-visible {
    border-color: var(--bs-primary-border-subtle);
    box-shadow: 0 1px 4px rgba(0, 0, 0, .06);
    color: inherit;
}
.itflow-portal-request-title {
    display: block;
    color: var(--bs-emphasis-color);
    font-weight: 600;
}
.itflow-portal-request-text {
    display: block;
    margin-top: .15rem;
    color: var(--bs-secondary-color);
    font-size: .85rem;
}
.itflow-portal-roles {
    display: inline-flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: .25rem;
}
.itflow-portal-roles > span {
    padding: .1rem .5rem;
    border: 1px solid var(--bs-border-color);
    border-radius: 2rem;
    color: var(--bs-secondary-color);
    font-size: .72rem;
    font-weight: 600;
    white-space: nowrap;
}
.itflow-portal-pdf {
    display: block;
    width: 100%;
    height: 75vh;
    border: 0;
}
.itflow-portal-document {
    overflow-x: auto;
    overflow-wrap: anywhere;
}
.itflow-portal-document img {
    max-width: 100%;
    height: auto;
}
.itflow-portal-document > :last-child {
    margin-bottom: 0;
}
@media (max-width: 575.98px) {
    .itflow-portal-ticket > .itflow-portal-tile {
        display: none;
    }
}
/* Announcements on the portal's home page (Admin > Client Portal) - a
   coloured edge and icon for the tone, the text in the body colour */
.itflow-portal-announcement {
    display: flex;
    gap: .85rem;
    padding: .9rem 1rem;
    border: 1px solid var(--bs-border-color);
    border-left: .3rem solid var(--bs-info);
    border-radius: var(--bs-border-radius-lg);
    background-color: var(--bs-body-bg);
}
.itflow-portal-announcement.is-warning { border-left-color: var(--bs-warning); }
.itflow-portal-announcement.is-danger { border-left-color: var(--bs-danger); }
.itflow-portal-announcement-icon {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    background-color: var(--bs-info-bg-subtle);
    color: var(--bs-info-text-emphasis);
}
.itflow-portal-announcement.is-warning .itflow-portal-announcement-icon {
    background-color: var(--bs-warning-bg-subtle);
    color: var(--bs-warning-text-emphasis);
}
.itflow-portal-announcement.is-danger .itflow-portal-announcement-icon {
    background-color: var(--bs-danger-bg-subtle);
    color: var(--bs-danger-text-emphasis);
}
.itflow-portal-announcement-title {
    font-size: 1rem;
    font-weight: 600;
    margin: .3rem 0 .2rem;
}
.itflow-portal-announcement-body {
    overflow-wrap: anywhere;
}
/* View as contact: the strip over the portal saying whose view it is */
.itflow-portal-viewas {
    padding: .45rem 0;
    background-color: var(--bs-warning-bg-subtle);
    color: var(--bs-warning-text-emphasis);
    border-bottom: 1px solid var(--bs-warning-border-subtle);
    font-size: .9rem;
}
/* Admin > Client Portal: an announcement's tone as a small coloured dot */
.itflow-announcement-dot {
    display: inline-block;
    width: .6rem;
    height: .6rem;
    border-radius: 50%;
    background-color: var(--bs-info);
}
.itflow-announcement-dot.is-warning { background-color: var(--bs-warning); }
.itflow-announcement-dot.is-danger { background-color: var(--bs-danger); }

/* Printing an invoice, quote or receipt: the document and nothing round it */
@media print {
    .itflow-portal-header,
    .itflow-portal-tabbar,
    .itflow-portal-footer,
    .itflow-portal-main > .alert {
        display: none !important;
    }
    .itflow-portal {
        padding-bottom: 0 !important;
        background: #fff !important;
    }
    .itflow-portal-main {
        max-width: none;
        padding: 0;
    }
    .itflow-portal-receipt {
        max-width: none;
        border: 0;
    }
}

/* The pages not rebuilt yet: their black table heads and borders, softened to
   sit in the light shell */
.itflow-portal-main .table-dark {
    --bs-table-color: var(--bs-emphasis-color);
    --bs-table-bg: var(--bs-tertiary-bg);
    --bs-table-border-color: var(--bs-border-color);
}
.itflow-portal-main .table.border-dark,
.itflow-portal-main .table .border-dark {
    border-color: var(--bs-border-color) !important;
}

/* ==========================================================================
   Setup wizard (setup/index.php, setup/steps/) - a centred installer: the
   brand, a step tracker, one card per step and a footer. No sidebar, so it
   works on a phone; light or dark as the system is set.
   ========================================================================== */
.itflow-setup {
    min-height: 100vh;
}
.itflow-setup-wrap {
    max-width: 52rem;
    margin: 0 auto;
    padding: 2rem 1rem 3rem;
}
.itflow-setup-brand {
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: .6rem;
    font-size: 2rem;
    font-weight: 300;
    margin-bottom: 1.5rem;
}
.itflow-setup-brand-sub {
    font-size: 1rem;
    color: var(--bs-secondary-color);
    text-transform: uppercase;
    letter-spacing: .08em;
}
.itflow-setup-steps {
    margin-bottom: 1.25rem;
}
.itflow-setup-steps ol {
    justify-content: space-between;
    margin: 0;
    padding: 0;
    position: relative;
}
/* The line the steps sit on */
.itflow-setup-steps ol::before {
    content: "";
    position: absolute;
    top: 1rem;
    left: 2rem;
    right: 2rem;
    border-top: 2px solid var(--bs-border-color);
}
.itflow-setup-step {
    position: relative;
    flex: 1 1 0;
    text-align: center;
    min-width: 0;
}
.itflow-setup-step > a,
.itflow-setup-step > span {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .35rem;
    color: var(--bs-secondary-color);
    text-decoration: none;
}
.itflow-setup-step > a:hover .itflow-setup-step-label {
    text-decoration: underline;
}
.itflow-setup-step-marker {
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: .85rem;
    font-weight: 600;
    background: var(--bs-body-bg);
    border: 2px solid var(--bs-border-color);
    color: var(--bs-secondary-color);
    position: relative;
}
.itflow-setup-step-label {
    font-size: .8rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}
.itflow-setup-step.is-done .itflow-setup-step-marker {
    background: var(--bs-success);
    border-color: var(--bs-success);
    color: #fff;
}
.itflow-setup-step.is-done > a {
    color: var(--bs-body-color);
}
.itflow-setup-step.is-current .itflow-setup-step-marker {
    background: var(--bs-primary);
    border-color: var(--bs-primary);
    color: #fff;
    box-shadow: 0 0 0 .25rem rgba(var(--bs-primary-rgb), .2);
}
.itflow-setup-step.is-current .itflow-setup-step-label {
    color: var(--bs-emphasis-color);
    font-weight: 600;
}
.itflow-setup-card {
    border: 1px solid var(--bs-border-color);
    box-shadow: 0 .25rem 1rem rgba(0, 0, 0, .05);
}
/* What a step needs, or what to do next - an icon beside a heading and a line */
.itflow-setup-needs > li {
    display: flex;
    gap: .9rem;
    padding: .55rem 0;
}
.itflow-setup-needs > li > i {
    color: var(--bs-primary);
    margin-top: .2rem;
}
.itflow-setup-needs > li strong {
    display: block;
}
.itflow-setup-needs > li span {
    display: block;
    color: var(--bs-secondary-color);
    font-size: .9rem;
}
.itflow-setup-needs > li > div {
    min-width: 0;
}
/* A cron line, a command or config.php - wrapped on a phone rather than pushing the page sideways */
.itflow-setup-card pre {
    white-space: pre-wrap;
    word-break: break-all;
}
.itflow-setup-checks .list-group-item {
    background: transparent;
}
/* The picture picked for the avatar or logo, before it is sent */
.itflow-setup-preview {
    flex: 0 0 auto;
    width: 3.5rem;
    height: 3.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px dashed var(--bs-border-color);
    border-radius: .5rem;
    background: var(--bs-tertiary-bg);
    color: var(--bs-secondary-color);
    font-size: 1.25rem;
    overflow: hidden;
}
.itflow-setup-preview.is-round {
    border-radius: 50%;
}
.itflow-setup-preview.has-image {
    border-style: solid;
}
.itflow-setup-preview.has-image > i {
    display: none;
}
.itflow-setup-preview > img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.itflow-setup-preview:not(.is-round) > img {
    object-fit: contain;
    padding: .2rem;
}
/* Finish - what to do once signed in, numbered */
.itflow-setup-next {
    counter-reset: itflow-setup-next;
}
.itflow-setup-next > li {
    counter-increment: itflow-setup-next;
    position: relative;
    padding: .45rem 0 .45rem 2.1rem;
}
.itflow-setup-next > li::before {
    content: counter(itflow-setup-next);
    position: absolute;
    left: 0;
    top: .45rem;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 50%;
    background: var(--bs-tertiary-bg);
    border: 1px solid var(--bs-border-color);
    font-size: .75rem;
    font-weight: 600;
    display: flex;
    align-items: center;
    justify-content: center;
}
/* Finish - telling the ITFlow project, and exactly what that sends */
.itflow-setup-share {
    border: 1px solid var(--bs-border-color);
    border-radius: .5rem;
    padding: 1rem;
}
.itflow-setup-share-list {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: .15rem 1rem;
}
.itflow-setup-share-list dt {
    font-weight: 400;
    color: var(--bs-secondary-color);
}
.itflow-setup-share-list dd {
    margin: 0;
    min-width: 0;
    overflow-wrap: anywhere;
}
/* Restore - where a backup is dropped */
.itflow-setup-drop {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: .15rem;
    padding: 1.5rem 1rem;
    margin-bottom: .5rem;
    border: 2px dashed var(--bs-border-color);
    border-radius: .5rem;
    background: var(--bs-tertiary-bg);
    cursor: pointer;
    overflow-wrap: anywhere;
    transition: border-color .15s, background-color .15s;
}
.itflow-setup-drop:hover,
.itflow-setup-drop.is-over {
    border-color: var(--bs-primary);
    background: rgba(var(--bs-primary-rgb), .06);
}
.itflow-setup-drop.has-file {
    border-style: solid;
}
.itflow-setup-drop.has-file > i {
    color: var(--bs-primary) !important;
}
/* Region - money and a date as they will look */
.itflow-setup-sample {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem 1rem;
    padding: .6rem .9rem;
    border-radius: .5rem;
    background: var(--bs-tertiary-bg);
    font-size: .9rem;
}
.itflow-setup-sample[hidden] {
    display: none;
}
.itflow-setup-sample > span:not(:first-child) {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.itflow-setup-footer {
    text-align: center;
    font-size: .8rem;
    color: var(--bs-secondary-color);
    margin-top: 1.5rem;
}
.itflow-setup-footer a {
    color: inherit;
}
.itflow-setup-footer > span {
    margin: 0 .35rem;
}
@media (max-width: 575.98px) {
    .itflow-setup-wrap {
        padding-top: 1rem;
    }
    .itflow-setup-brand {
        font-size: 1.6rem;
        margin-bottom: 1rem;
    }
}

/* ==========================================================================
   Get started (admin/getting_started.php, admin/getting_started/) - what is
   left to set up after the install, in the setup wizard's frame: the steps
   along the top, one card each. And its card on the dashboard.
   ========================================================================== */
.itflow-gs-wrap {
    max-width: 56rem;
}
.itflow-gs-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1.5rem;
}
.itflow-gs-top-actions {
    display: flex;
    align-items: center;
    gap: .25rem;
    flex-shrink: 0;
}
.itflow-gs-brand {
    display: flex;
    align-items: baseline;
    gap: .6rem;
    min-width: 0;
    font-size: 1.5rem;
    font-weight: 300;
}
.itflow-gs-logo {
    max-height: 2.25rem;
    max-width: 10rem;
    object-fit: contain;
    align-self: center;
}
/* A step put off - its marker dashed */
.itflow-setup-step.is-skipped .itflow-setup-step-marker {
    border-style: dashed;
}
.itflow-gs-progress {
    height: .4rem;
}
/* The Cron step's tasks - a mark that turns green as each is done */
.itflow-gs-tasks > li {
    display: flex;
    gap: .9rem;
    padding: .9rem 0;
}
.itflow-gs-tasks > li + li {
    border-top: 1px solid var(--bs-border-color);
}
.itflow-gs-tasks > li:first-child {
    padding-top: 0;
}
.itflow-gs-task-mark,
.itflow-gs-summary-mark {
    flex: 0 0 auto;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: .85rem;
    background: var(--bs-tertiary-bg);
    border: 2px solid var(--bs-border-color);
    color: var(--bs-secondary-color);
}
.itflow-gs-tasks > li.is-done .itflow-gs-task-mark,
.itflow-gs-summary-mark.is-done {
    background: var(--bs-success);
    border-color: var(--bs-success);
    color: #fff;
}
.itflow-gs-summary-mark.is-skipped {
    border-style: dashed;
}
/* Something the step can also do - a switch, and its fields under it */
.itflow-gs-optional,
.itflow-gs-key {
    border: 1px solid var(--bs-border-color);
    border-radius: .5rem;
    padding: 1rem;
}
.itflow-gs-key {
    background: var(--bs-tertiary-bg);
}
.itflow-gs-day {
    min-width: 3.25rem;
}
/* People and clients - a grey initials tile beside each */
.itflow-gs-people > li {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .5rem 0;
}
.itflow-gs-people > li + li {
    border-top: 1px solid var(--bs-border-color);
}
.itflow-gs-person-initials,
.itflow-gs-pack-icon,
.itflow-gs-card-icon {
    flex: 0 0 auto;
    width: 2.25rem;
    height: 2.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--bs-tertiary-bg);
    border: 1px solid var(--bs-border-color);
    color: var(--bs-secondary-color);
    font-size: .8rem;
    font-weight: 600;
}
.itflow-gs-pack-icon,
.itflow-gs-card-icon {
    border-radius: .5rem;
    font-weight: 400;
    font-size: .9rem;
}
.itflow-gs-packs label[for] {
    cursor: pointer;
}
.itflow-gs-packs .list-group-item.is-here .itflow-gs-pack-icon,
.itflow-gs-packs .list-group-item.is-here .fw-semibold {
    opacity: .6;
}
.itflow-gs-pack-about {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
/* "or", across the card between two ways of doing a step */
.itflow-gs-or {
    display: flex;
    align-items: center;
    gap: .75rem;
    margin: 1.5rem 0;
    color: var(--bs-secondary-color);
    font-size: .8rem;
    text-transform: uppercase;
    letter-spacing: .08em;
}
.itflow-gs-or::before,
.itflow-gs-or::after {
    content: "";
    flex: 1 1 auto;
    border-top: 1px solid var(--bs-border-color);
}
/* The summary */
.itflow-gs-done-mark {
    width: 3.5rem;
    height: 3.5rem;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.4rem;
    background: var(--bs-success);
    color: #fff;
}
.itflow-gs-done-mark.is-partial {
    background: var(--bs-primary);
}
.itflow-gs-summary .list-group-item {
    background: transparent;
}
/* The dashboard's card - each step a chip, ticked as it is done */
.itflow-gs-card {
    border-left: 3px solid var(--bs-primary);
}
.itflow-gs-chip {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    padding: .2rem .6rem;
    border-radius: 2rem;
    font-size: .8rem;
    text-decoration: none;
    border: 1px solid var(--bs-border-color);
    background: var(--bs-tertiary-bg);
    color: var(--bs-secondary-color);
}
.itflow-gs-chip:hover {
    color: var(--bs-body-color);
    border-color: var(--bs-secondary-color);
}
.itflow-gs-chip.is-done {
    color: var(--bs-success-text-emphasis);
    background: var(--bs-success-bg-subtle);
    border-color: var(--bs-success-border-subtle);
}
.itflow-gs-chip.is-skipped {
    border-style: dashed;
    background: transparent;
}
@media (max-width: 575.98px) {
    .itflow-gs-brand {
        font-size: 1.25rem;
    }
    .itflow-gs-brand .itflow-setup-brand-sub {
        display: none;
    }
}

/* ==========================================================================
   Starter content's Pick which (admin/includes/starter_content_pick.php,
   js/starter_content.js) - on Maintenance > Starter Content and Get started:
   what a pack would add, each item ticked and shown as it will look, in a
   box that scrolls; and Preview's window.
   ========================================================================== */
.itflow-starter-pick > summary {
    color: var(--bs-link-color);
    cursor: pointer;
    width: max-content;
}
.itflow-starter-pick-box {
    max-height: 20rem;
    overflow-y: auto;
    padding: .25rem .75rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .375rem;
    background: var(--bs-body-bg);
    text-align: start;
}
/* One to a line, each with what it is for; tags two or more across, as they are only their pill */
.itflow-starter-pick-items {
    display: grid;
    grid-template-columns: 1fr;
}
.itflow-starter-pick-items.is-pills {
    grid-template-columns: repeat(auto-fill, minmax(min(12rem, 100%), 1fr));
    column-gap: 1rem;
}
.itflow-starter-item {
    display: flex;
    align-items: flex-start;
    gap: .6rem;
    padding: .4rem 0;
    min-width: 0;
}
.itflow-starter-pick-items:not(.is-pills) .itflow-starter-item + .itflow-starter-item {
    border-top: 1px solid var(--bs-border-color-translucent);
}
.itflow-starter-item > .form-check-input {
    margin-top: .2rem;
}
.itflow-starter-item-label {
    cursor: pointer;
    flex: 1 1 auto;
    font-weight: 400;
    margin-bottom: 0;
}
/* A tag named longer than its column wraps inside its pill rather than pushing the box sideways */
.itflow-starter-item-label .itflow-tag {
    max-width: 100%;
    white-space: normal;
}
.itflow-starter-item-about {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.itflow-starter-pick-group {
    grid-column: 1 / -1;
    font-size: .75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--bs-secondary-color);
    margin: .6rem 0 .1rem;
}
.itflow-starter-pick-group:first-child {
    margin-top: .25rem;
}
/* Maintenance > Starter Content - the list under its pack, in the first column */
.itflow-starter-pack-cell {
    min-width: 18rem;
}
/* Preview - the facts as a list beside their labels, then what it says as it reads */
.itflow-starter-preview-facts {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: .35rem 1rem;
    margin-bottom: 1rem;
}
.itflow-starter-preview-facts dt {
    font-weight: 400;
    color: var(--bs-secondary-color);
}
.itflow-starter-preview-facts dd {
    margin: 0;
    min-width: 0;
    overflow-wrap: anywhere;
}
.itflow-starter-preview-head {
    font-size: .8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--bs-secondary-color);
    margin: 1.25rem 0 .5rem;
}
.itflow-starter-preview-doc,
.itflow-starter-preview-notes {
    border: 1px solid var(--bs-border-color);
    border-radius: .375rem;
    padding: .75rem 1rem;
    background: var(--bs-tertiary-bg);
    overflow-x: auto;
}
.itflow-starter-preview-doc table {
    width: 100%;
    margin-bottom: .75rem;
    border-collapse: collapse;
}
.itflow-starter-preview-doc th,
.itflow-starter-preview-doc td {
    border: 1px solid var(--bs-border-color);
    padding: .25rem .5rem;
    vertical-align: top;
}
.itflow-starter-preview-doc > :last-child {
    margin-bottom: 0;
}
.itflow-starter-preview-list {
    padding-left: 1.25rem;
    margin-bottom: 0;
}
.itflow-starter-preview-list > li {
    padding: .15rem 0;
}
/* [Words in brackets] - filled in when it is used */
.itflow-starter-fill {
    background: rgba(var(--bs-primary-rgb), .12);
    color: var(--bs-emphasis-color);
    border-radius: .25rem;
    padding: 0 .2rem;
}
@media (max-width: 575.98px) {
    .itflow-starter-preview-facts {
        grid-template-columns: 1fr;
        gap: 0;
    }
    .itflow-starter-preview-facts dd {
        margin-bottom: .5rem;
    }
}

/* ==========================================================================
   Settings (admin/settings*.php, functions/settings.php, js/settings.js) - a
   page header, sections with what they are for beside their fields, a save
   bar that says when something is changed, the overview's tiles and Find a
   setting.
   ========================================================================== */
.itflow-settings-head {
    display: flex;
    gap: 1rem;
    align-items: flex-start;
    margin-bottom: 1.25rem;
}
.itflow-settings-head-icon {
    flex: 0 0 auto;
    width: 2.75rem;
    height: 2.75rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: .75rem;
    font-size: 1.15rem;
    color: var(--itflow-accent, var(--bs-primary));
    background: color-mix(in srgb, var(--itflow-accent, var(--bs-primary)) 12%, transparent);
}
.itflow-settings-card > .card-body {
    padding: 0 1.25rem;
}
.itflow-settings-section {
    padding: 1.5rem 0;
}
.itflow-settings-section + .itflow-settings-section {
    border-top: 1px solid var(--bs-border-color);
}
@media (min-width: 992px) {
    .itflow-settings-section-about {
        padding-right: 1.5rem;
    }
}
.itflow-settings-field + .itflow-settings-field {
    margin-top: 1rem;
}
.itflow-settings-field .form-switch + .form-text,
.itflow-settings-field .form-switch ~ .form-text {
    margin-top: .1rem;
    padding-left: 2.5em;
}
.itflow-settings-field .form-label {
    font-weight: 500;
}
/* A setting gone to from Find a setting */
.itflow-settings-lit {
    border-radius: .5rem;
    animation: itflow-settings-lit 2.6s ease-out;
}
@keyframes itflow-settings-lit {
    0%, 35% {
        background-color: color-mix(in srgb, var(--bs-warning) 28%, transparent);
        box-shadow: 0 0 0 .5rem color-mix(in srgb, var(--bs-warning) 28%, transparent);
    }
    100% {
        background-color: transparent;
        box-shadow: 0 0 0 .5rem transparent;
    }
}
/* The save bar - at the foot of the form, and of the window while the form runs past it */
.itflow-settings-savebar {
    position: sticky;
    bottom: 0;
    z-index: 5;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: .5rem;
    margin: 0 -1.25rem;
    padding: .75rem 1.25rem;
    border-top: 1px solid var(--bs-border-color);
    background: var(--bs-body-bg);
    border-radius: 0 0 var(--bs-card-border-radius, .375rem) var(--bs-card-border-radius, .375rem);
}
.itflow-settings-savebar-note {
    visibility: hidden;
}
.itflow-settings-savebar.is-dirty {
    box-shadow: 0 -.5rem 1rem rgba(0, 0, 0, .08);
}
.itflow-settings-savebar.is-dirty .itflow-settings-savebar-note {
    visibility: visible;
}
.itflow-settings-savebar:not(.is-dirty) [data-settings-undo] {
    visibility: hidden;
}
/* What a value will look like - money and a date, a next number */
.itflow-settings-sample {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem 1rem;
    padding: .6rem .9rem;
    border-radius: .5rem;
    background: var(--bs-tertiary-bg);
    font-size: .9rem;
}
.itflow-settings-sample[hidden] {
    display: none;
}
.itflow-settings-sample > span:not(:first-child) {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
/* The number the next one gets, and a clash with one in use */
.itflow-settings-sample.itflow-settings-next {
    gap: .35rem .5rem;
}
.itflow-settings-next [data-settings-clash] {
    flex-basis: 100%;
}
/* A sentence saying how what is set works out - the reminder schedule, how a trip bills */
.itflow-settings-note {
    padding: .6rem .9rem;
    border-radius: .5rem;
    background: var(--bs-tertiary-bg);
    font-size: .875rem;
}
/* A picture - the logo, the tab icon - as it is, or as picked */
.itflow-settings-picture {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 5rem;
    padding: .75rem;
    border: 1px dashed var(--bs-border-color);
    border-radius: .5rem;
    background: var(--bs-tertiary-bg);
}
.itflow-settings-picture img {
    max-width: 100%;
    max-height: 6rem;
}
.itflow-settings-picture.is-icon img {
    width: 2rem;
    height: 2rem;
}
/* The overview's what-needs-looking-at - the text takes the room, the button goes under it only when there is none */
.itflow-settings-attention-text {
    flex: 1 1 18rem;
    min-width: 0;
}
/* A theme colour's dot */
.itflow-settings-dot {
    display: inline-block;
    width: .75rem;
    height: .75rem;
    margin-right: .4rem;
    border-radius: 50%;
    vertical-align: -.05rem;
    background: var(--itflow-accent, var(--bs-primary));
}
/* The overview - Find a setting, and a tile for each page */
.itflow-settings-find {
    position: relative;
    max-width: 44rem;
}
.itflow-settings-results {
    position: absolute;
    z-index: 20;
    left: 0;
    right: 0;
    top: calc(100% + .25rem);
    max-height: 26rem;
    overflow-y: auto;
    box-shadow: 0 .5rem 1.5rem rgba(0, 0, 0, .15);
}
.itflow-settings-results mark {
    padding: 0;
    background: color-mix(in srgb, var(--bs-warning) 40%, transparent);
    color: inherit;
}
.itflow-settings-results .list-group-item.active .text-body-secondary {
    color: inherit !important;
}
.itflow-settings-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
    gap: .75rem;
}
.itflow-settings-tile {
    display: flex;
    gap: .9rem;
    align-items: flex-start;
    padding: 1rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .6rem;
    background: var(--bs-body-bg);
    color: var(--bs-body-color);
    text-decoration: none;
    transition: border-color .15s, box-shadow .15s;
}
.itflow-settings-tile:hover,
.itflow-settings-tile:focus-visible {
    border-color: var(--itflow-accent, var(--bs-primary));
    box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .06);
    color: var(--bs-body-color);
}
.itflow-settings-tile.is-off {
    opacity: .6;
}
.itflow-settings-tile-icon {
    flex: 0 0 auto;
    width: 2.25rem;
    height: 2.25rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: .5rem;
    color: var(--itflow-accent, var(--bs-primary));
    background: color-mix(in srgb, var(--itflow-accent, var(--bs-primary)) 12%, transparent);
}
.itflow-settings-tile-title {
    display: block;
    font-weight: 600;
}
.itflow-settings-tile-about {
    display: block;
    font-size: .8125rem;
    color: var(--bs-secondary-color);
}
.itflow-settings-tile-now {
    display: block;
    margin-top: .4rem;
    font-size: .8125rem;
    overflow-wrap: anywhere;
}
/* Modules - one row each, what it holds under its name */
.itflow-settings-module + .itflow-settings-module {
    margin-top: .25rem;
    padding-top: .75rem;
    border-top: 1px solid var(--bs-border-color-translucent);
}
/* A short list of what is what - Telemetry's report */
.itflow-settings-list {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: .15rem 1rem;
}
.itflow-settings-list dt {
    font-weight: 400;
    color: var(--bs-secondary-color);
}
.itflow-settings-list dd {
    margin: 0;
    min-width: 0;
    overflow-wrap: anywhere;
}
/* Fields that mean nothing while their switch is off - still there to set up */
[data-settings-depends-on] {
    transition: opacity .15s;
}
[data-settings-depends-on].is-off {
    opacity: .55;
}

/* ---------- Mail Queue ---------- */
/* Why an email failed, under its status on the list */
.itflow-mail-queue-why {
    max-width: 22rem;
}
/* The email as it will arrive - its own white page, whatever the theme */
.itflow-mail-queue-frame {
    height: 45vh;
    min-height: 18rem;
    background: #fff;
}
.itflow-mail-queue-facts dd {
    margin-bottom: .35rem;
}

/* An AI summary of a ticket (agent/modals/ticket/ticket_summary.php) - its sections close together */
.itflow-ai-summary h6 {
    font-weight: 600;
    margin: 1rem 0 0.35rem;
}
.itflow-ai-summary ul {
    margin-bottom: 0.25rem;
    padding-left: 1.25rem;
}
.itflow-ai-summary p:last-child {
    margin-bottom: 0;
}
/* Write it with AI - each line's numbers, side by side, wrapping on a phone */
.itflow-ai-line-qty {
    flex: 0 0 7rem;
}
.itflow-ai-line-billed {
    flex: 0 0 9.5rem;
}
.itflow-ai-line-price {
    flex: 0 0 9rem;
}

/* Admin > Debug (admin/debug.php) - a grey tile for each section's icon, and
   each check as its level's icon beside what was found and what to do */
.itflow-debug-section-icon {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 1.85rem;
    height: 1.85rem;
    border-radius: .5rem;
    font-size: .85rem;
    color: var(--bs-secondary-color);
    background-color: var(--bs-secondary-bg);
}
.itflow-debug-item {
    display: flex;
    gap: .6rem;
    align-items: flex-start;
}
.itflow-debug-item-icon {
    margin-top: .2rem;
}
.itflow-debug-fix {
    color: var(--bs-secondary-color);
    overflow-wrap: anywhere;
}
.itflow-debug-fix code {
    white-space: normal;
    overflow-wrap: anywhere;
}
.itflow-debug-attention li + li {
    border-top: 1px solid color-mix(in srgb, currentColor 15%, transparent);
}
.itflow-debug-bar {
    height: .4rem;
}
/* Its figures wrap as flex rather than grid, so a short last row stretches
   across rather than leaving empty cells */
.itflow-debug-stats .itflow-report-stats {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
}
.itflow-debug-stats .itflow-report-stat {
    flex: 1 1 8.5rem;
}
.itflow-debug-stats .itflow-report-stat-value {
    font-size: 1.25rem;
}

/* A ticket status's badge (ticketStatusBadgeHtml()) - its colour, with dark or white text, whichever reads on it */
.itflow-ticket-status {
    background-color: var(--itflow-status-bg, var(--bs-secondary));
    color: var(--itflow-status-text, #fff);
}

/* Contracts as documents (includes/contract_paper.php) - the document from
   contractDocumentHtml(), which carries classes and no styles of its own, the
   signature block, and the signing pad (includes/contract_signature_pad.php,
   js/signature_pad.js). The pad and the signatures are drawn on white in
   either theme - what is signed goes on paper; in dark mode a drawn
   signature shown on the page is turned light. */
.itflow-contract-doc-title {
    margin: 1.5rem 0 .35rem;
    font-size: 1.5rem;
    font-weight: 600;
    text-wrap: balance;
}
.itflow-contract-doc-between {
    margin-bottom: 1.25rem;
    color: var(--bs-secondary-color);
}
.itflow-contract-doc-parties {
    width: 100%;
    margin-bottom: .5rem;
}
.itflow-contract-doc-parties td {
    padding: 0 1.5rem .75rem 0;
    vertical-align: top;
}
.itflow-contract-doc-label {
    margin-bottom: .2rem;
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}
.itflow-contract-doc-muted {
    font-size: .875rem;
    color: var(--bs-secondary-color);
}
.itflow-contract-doc-heading {
    margin: 1.5rem 0 .5rem;
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--bs-primary-text-emphasis);
}
.itflow-contract-doc-table {
    width: 100%;
    margin-bottom: .5rem;
    border-collapse: collapse;
    font-size: .9rem;
}
.itflow-contract-doc-table th,
.itflow-contract-doc-table td {
    padding: .45rem .6rem .45rem 0;
    border-bottom: 1px solid var(--bs-border-color-translucent);
    text-align: left;
    vertical-align: top;
}
.itflow-contract-doc-table thead th {
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}
.itflow-contract-doc-summary th {
    width: 26%;
    font-weight: 500;
    color: var(--bs-secondary-color);
}
.itflow-contract-doc-terms {
    overflow-wrap: anywhere;
}
.itflow-contract-doc-terms img {
    max-width: 100%;
    height: auto;
}
.itflow-contract-signatures {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1.5rem 2rem;
    margin-top: 2rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--bs-border-color-translucent);
    break-inside: avoid;
}
.itflow-contract-signature-mark {
    display: flex;
    align-items: flex-end;
    height: 4.5rem;
    margin-bottom: .35rem;
    border-bottom: 1px solid var(--bs-border-color);
}
.itflow-contract-signature-mark img {
    max-width: 100%;
    max-height: 4.25rem;
}
[data-bs-theme="dark"] .itflow-contract-signature-mark img {
    filter: invert(1) hue-rotate(180deg);
}
.itflow-contract-signature-typed,
.itflow-signature-typed-preview {
    font-family: "Segoe Script", "Bradley Hand", "Snell Roundhand", "Brush Script MT", cursive;
    font-size: 1.75rem;
    line-height: 1.2;
}
.itflow-signature-canvas-wrap {
    position: relative;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    background-color: #fff;
}
.itflow-signature-canvas {
    display: block;
    width: 100%;
    height: 10rem;
    cursor: crosshair;
    touch-action: none;
}
.itflow-signature-line {
    position: absolute;
    right: 1rem;
    bottom: 2.25rem;
    left: 1rem;
    border-bottom: 1px dashed #adb5bd;
    pointer-events: none;
}
.itflow-signature-hint {
    position: absolute;
    bottom: .55rem;
    left: 1rem;
    font-size: .8rem;
    color: #6c757d;
    pointer-events: none;
}
.itflow-signature-hint.is-error {
    color: #b02a37;
    font-weight: 600;
}
.itflow-signature-typed-preview {
    display: flex;
    align-items: center;
    min-height: 5.5rem;
    padding: .5rem 1rem;
    overflow: hidden;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    background-color: #fff;
    color: #1d2433;
    white-space: nowrap;
}
.itflow-signature-typed-preview.is-empty {
    font-family: inherit;
    font-size: .875rem;
    color: #6c757d;
}
.itflow-contract-trail {
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: .875rem;
}
.itflow-contract-trail li {
    display: flex;
    gap: .6rem;
    padding: .3rem 0;
}
.itflow-contract-trail li > i {
    margin-top: .2rem;
    color: var(--bs-secondary-color);
}
/* Prepaid hours on a contract - what is left, and a bar of what was used (a <progress>, as the portal allows no inline styles) */
.itflow-contract-hours-left {
    font-size: 2rem;
    font-weight: 600;
    line-height: 1.15;
    font-variant-numeric: tabular-nums;
}
.itflow-hours-bar {
    display: block;
    width: 100%;
    height: .6rem;
    border: 0;
    border-radius: 999px;
    overflow: hidden;
    background-color: var(--bs-secondary-bg);
    color: var(--bs-primary);
    appearance: none;
    -webkit-appearance: none;
}
.itflow-hours-bar::-webkit-progress-bar {
    background-color: var(--bs-secondary-bg);
    border-radius: 999px;
}
.itflow-hours-bar::-webkit-progress-value {
    background-color: var(--bs-primary);
    border-radius: 999px;
}
.itflow-hours-bar::-moz-progress-bar {
    background-color: var(--bs-primary);
    border-radius: 999px;
}
@media (max-width: 575.98px) {
    .itflow-contract-signatures {
        grid-template-columns: minmax(0, 1fr);
    }
    .itflow-contract-doc-parties td {
        display: block;
        width: 100% !important;
    }
}

/* Joining the client portal - from an invite or a sign-up (client/join.php): room for two fields to a row */
@media (min-width: 576px) {
    .login-box.itflow-join-box {
        width: 460px;
    }
}
