/**
 * Bootstrap Component Extensions and Overrides for Loon (Bootstrap 6)
 *
 * Customisations for Bootstrap components. All values come from variables.css.
 *
 * Bootstrap 6 uses cascade layers. These rules go into two of them:
 *   - "content": element styles (links, headings, paragraphs…), which Bootstrap's
 *     components can still override, as in Bootstrap 5
 *   - "custom": component overrides, which beat Bootstrap's components but lose to
 *     its utilities, so a utility like .p-0 or .d-none still wins, as in Bootstrap 5
 *
 * Structure:
 *   Typography and content (content layer)
 *   1. Component tokens   – Bootstrap 6 component variables, set to the Loon look
 *   2. Tables
 *   3. Forms
 *   4. Buttons
 *   5. Navigation and navbar
 *   6. Menus (was dropdowns)
 *   7. Accordion
 *   8. Breadcrumb
 *   9. Cards
 *  10. Dialogs (was modals)
 *  11. Tooltips and toasts
 *  12. List groups
 *  13. Drawers (was offcanvas)
 *  14. Interactive helpers
 *  15. Profile pages
 *  16. Drawer tokens (outside the layers, see note there)
 */

@layer content {


/* =============================================================================
   TYPOGRAPHY AND CONTENT
   Element styles sit in Bootstrap's "content" layer, below its components, so a
   component (a menu item, a page link, a button on an <a>) still sets its own
   colour and spacing – the same as Bootstrap 5, where element selectors lost to
   class selectors.
   ============================================================================= */

hr {
  margin: var(--bs-spacer) 0;
}

h6, .h6, h5, .h5, h4, .h4, h3, .h3, h2, .h2, h1, .h1 {
  margin-bottom: calc(var(--bs-spacer) * 0.75);
  font-weight: 600;
  line-height: var(--bs-body-line-height);
}

h1, .h1 {
  font-size: calc(1.2875rem + 0.45vw);
}

h2, .h2 {
  font-size: calc(1.275rem + 0.3vw);
}

h3, .h3 {
  font-size: calc(1.2625rem + 0.15vw);
}

h4, .h4 {
  font-size: 1.25rem;
}

h5, .h5 {
  font-size: 1.125rem;
}

h6, .h6 {
  font-size: 1rem;
}

@media (min-width: 1200px) {
  h1, .h1 { font-size: 1.625rem; }
  h2, .h2 { font-size: 1.5rem; }
  h3, .h3 { font-size: 1.375rem; }
}

p {
  margin-bottom: var(--bs-spacer-2);
}

b, strong {
  font-weight: 800;
}

small {
  font-size: small;
  font-weight: initial;
}

smaller {
  font-size: smaller;
  font-weight: initial;
}

small i {
  font-size: small;
}

/* Bootstrap 6 dropped .lead – kept as a Loon class */
.lead {
  font-size: calc(var(--bs-body-font-size) * 1.25);
}

/* Links */
a {
  color: var(--bs-link-color);
  text-decoration: none;
  line-height: var(--bs-body-line-height);
}

a:hover {
  color: var(--bs-link-hover-color);
}

table tbody tr td a:hover {
  text-decoration: underline;
}

/* List inline */
.list-inline {
  --bs-list-inline-padding: 1rem;
}

.list-inline-item:not(:last-child) {
  margin-right: var(--bs-list-inline-padding);
}

/* Blockquote */
.blockquote {
  margin-bottom: var(--bs-spacer);
  font-size: 1rem;
}

.blockquote-footer {
  margin-top: calc(var(--bs-spacer) * -1);
  margin-bottom: var(--bs-spacer);
  font-size: var(--bs-body-font-size);
  color: var(--bs-gray-500);
}

/* Code and inline elements */
mark {
  color: currentColor;
}

code {
  font-size: 0.875em;
  background-color: var(--bs-gray-200);
  padding: 0.125rem 0.25rem;
  border-radius: var(--bs-border-radius);
}

kbd {
  padding: 0.2rem 0.4rem;
  color: var(--bs-white);
  background-color: var(--bs-black);
}

[data-bs-theme=dark] kbd {
  color: var(--bs-black);
  background-color: var(--bs-white);
}

/* Figures and images */
.img-thumbnail {
  padding: 0.25rem;
  background-color: var(--bs-body-bg);
  border: var(--bs-border-width) solid var(--bs-border-color);
  border-radius: var(--bs-border-radius);
  box-shadow: var(--bs-box-shadow-sm);
}

.figure-img {
  margin-bottom: 0.625rem;
}

.figure-caption {
  color: var(--bs-gray-600);
}

caption {
  padding-top: 0.75rem;
  padding-bottom: 0.75rem;
  color: color-mix(in srgb, var(--bs-body-color) 75%, transparent);
}

th {
  font-weight: 600;
}

/* Icons */
i {
  vertical-align: middle;
  font-size: var(--bs-icon-font-size);
  font-weight: var(--bs-body-font-weight);
  line-height: 1;
}

}


@layer custom {


/* =============================================================================
   1. COMPONENT TOKENS
   Bootstrap 6 sets these on the component class itself, so they are set here
   rather than in variables.css.
   ============================================================================= */

/* Buttons – sizing shared by every button style */
.btn,
.btn-solid,
.btn-outline,
.btn-subtle,
.btn-text,
.btn-link,
.btn-icon {
  --bs-btn-disabled-opacity: 0.35;
  --bs-btn-disabled-color: var(--bs-disabled-color);
  --bs-btn-disabled-bg: var(--bs-disabled-bg);
  --bs-btn-disabled-border-color: var(--bs-disabled-border-color);
}

/* Plain .btn – transparent with a border, as in Bootstrap 5 */
.btn:not(.btn-solid, .btn-outline, .btn-subtle, .btn-text, .btn-link, .btn-icon) {
  --bs-btn-bg: transparent;
  --bs-btn-color: var(--bs-body-color);
  --bs-btn-border-color: var(--bs-border-color);
  --bs-btn-hover-bg: var(--bs-hover-bg);
  --bs-btn-hover-color: var(--bs-hover-color);
  --bs-btn-hover-border-color: transparent;
  --bs-btn-active-bg: var(--bs-component-active-bg);
  --bs-btn-active-color: var(--bs-component-active-color);
  --bs-btn-active-border-color: var(--bs-component-active-bg);
}

/* Cards */
/* Every card: content starts at the layout space from each edge (40px, 20px on phones);
   headers and footers are bars with 16px above and below */
.card {
  --bs-card-spacer-y: var(--loon-space);
  --bs-card-spacer-x: var(--loon-space);
  --bs-card-cap-padding-y: var(--loon-bar-padding-y);
  --bs-card-cap-padding-x: var(--loon-space);
  --bs-card-cap-bg: transparent;
  --bs-card-bg: var(--bs-component-bg);
  --bs-card-border-color: var(--bs-border-color-translucent);
  --bs-card-border-radius: var(--bs-border-radius);
  --bs-card-box-shadow: var(--loon-surface-shadow);
  --bs-card-title-spacer-y: 0.5rem;
}

/* Bars holding fields or buttons (table toolbars, footers): the controls sit centred in
   the 72px bar – 14px above and below normal controls, 18px around small text buttons.
   Small icon buttons (close, settings) don't count. */
:is(.card-header, .card-footer):has(.btn-sm:not(.btn-icon), .form-control-sm) {
  --bs-card-cap-padding-y: calc((var(--loon-bar-height) - var(--bs-btn-input-sm-min-height)) / 2);
}

:is(.card-header, .card-footer):has(.form-control:not(.form-control-sm), .btn:not(.btn-sm)) {
  --bs-card-cap-padding-y: var(--loon-bar-padding-y-controls);
}

/* Tables */
.table {
  --bs-table-cell-padding-y: 1rem;
  --bs-table-cell-padding-x: 1.25rem;
  --bs-table-bg: var(--bs-component-bg);
  --bs-table-color: var(--bs-body-color);
  --bs-table-border-color: var(--loon-row-border); /* row lines a step lighter than field borders */
  --bs-table-group-separator-color: var(--bs-gray-500);
  --bs-table-hover-bg-factor: 4%; /* a light grey under the pointer, not a block */
}

/* Form controls – height from the shared control sizes in variables.css; text starts
   12px in (10px small, 16px large) */
.form-control {
  --bs-control-padding-x: var(--bs-input-padding-x);
  --bs-control-box-shadow: none;
  --bs-control-placeholder-color: var(--bs-placeholder-color);
  --bs-control-disabled-bg: var(--bs-disabled-bg);
  --bs-control-select-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
  --bs-control-select-bg-dark: var(--bs-control-select-bg);
}

.form-control-sm {
  --bs-control-padding-x: 0.625rem;
}

.form-control-lg {
  --bs-control-padding-x: 1rem;
}

.form-label,
.col-form-label {
  --bs-label-font-weight: 500;
  --bs-label-padding-y: calc(0.375rem + var(--bs-border-width));
}

.check,
.radio {
  --bs-check-size: 1em;
  --bs-radio-size: 1em;
}

/* Tick box – the Loon circle, the same glyphs as the select lists (plugins.css, VirtualSelect):
   an empty grey circle; ticked, a blue circle with a tick; partly ticked, a blue circle with
   a dash. One look for every tick box in the app: table rows, filter and column menus, forms. */
.check {
  appearance: none;
  -webkit-appearance: none;
  display: inline-grid;
  flex: none;
  place-content: center;
  width: var(--bs-icon-font-size);
  height: var(--bs-icon-font-size);
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  box-shadow: none;
  color: var(--bs-gray-500);
  vertical-align: middle;
  cursor: pointer;
  transition: color var(--bs-transition-base-timer) ease-in-out;
}

/* Bootstrap draws its tick with a hidden, masked ::before; reset that and use the icon font */
.check::before {
  content: "\f28a"; /* icon-circle */
  position: static;
  inset: auto;
  opacity: 1;
  transform: none;
  mask-image: none;
  background: none;
  pointer-events: none;
  font-family: var(--bs-icon-font-family);
  font-size: var(--bs-icon-font-size);
  font-weight: normal;
  line-height: 1;
  transition: none;
}

.check:not(:checked, :indeterminate):hover,
:is(.menu-item, label):hover > .check:not(:checked, :indeterminate) {
  color: var(--bs-body-color);
}

.check:checked,
.check:indeterminate {
  color: var(--bs-primary);
}

.check:checked::before {
  content: "\f270"; /* icon-check2-circle */
}

.check:indeterminate::before {
  content: "\f2e6"; /* icon-dash-circle */
}

.check:focus-visible {
  outline: var(--bs-focus-ring-width) solid var(--bs-primary-focus-ring);
  outline-offset: 1px;
}

.check:disabled {
  opacity: var(--bs-btn-disabled-opacity);
  cursor: default;
}

.form-text {
  --bs-form-text-color: color-mix(in srgb, var(--bs-body-color) 75%, transparent);
}

.switch {
  --bs-switch-height: 1.375rem;
  --bs-switch-width: 2.625rem;
}

/* Menus – the shared floating-list tokens from variables.css (same as select drop-downs) */
.menu {
  --bs-menu-min-width: var(--bs-component-min-width);
  --bs-menu-gap: 0;
  --bs-menu-spacer: var(--loon-pop-offset);
  --bs-menu-padding-x: 0;
  --bs-menu-padding-y: var(--loon-pop-padding);
  --bs-menu-font-size: var(--bs-btn-input-font-size); /* same text size as a field */
  --bs-menu-color: var(--bs-body-color);
  --bs-menu-bg: var(--bs-component-bg);
  --bs-menu-border-color: var(--loon-pop-border-color);
  --bs-menu-border-radius: var(--loon-pop-radius);
  --bs-menu-box-shadow: var(--loon-pop-shadow);
  --bs-menu-divider-bg: var(--bs-border-body);
  --bs-menu-divider-margin-x: 0;
  --bs-menu-divider-margin-y: var(--loon-pop-padding);
  --bs-menu-item-padding-x: var(--loon-item-padding-x);
  --bs-menu-item-padding-y: var(--loon-item-padding-y);
  --bs-menu-item-gap: 0.5rem; /* space between an icon and the text */
  --bs-menu-item-border-radius: var(--loon-item-radius);
  --bs-menu-item-color: var(--bs-body-color);
  --bs-menu-item-hover-color: var(--bs-body-color);
  --bs-menu-item-hover-bg: var(--loon-item-hover-bg);
  --bs-menu-item-active-color: var(--loon-item-selected-color);
  --bs-menu-item-active-bg: var(--loon-item-selected-bg);
  --bs-menu-item-disabled-color: var(--bs-disabled-color);
  --bs-menu-icon-size: 1rem;
  --bs-menu-header-color: var(--bs-fg-3);
  --bs-menu-header-padding-x: var(--loon-item-padding-x);
  --bs-menu-header-padding-y: var(--loon-item-padding-y);
}

/* Nav */
.nav {
  --bs-nav-gap: 0;
  --bs-nav-link-padding-x: 1.25rem;
  --bs-nav-link-padding-y: 0.625rem;
  --bs-nav-link-color: var(--bs-body-color);
  --bs-nav-link-hover-color: var(--bs-hover-color);
  --bs-nav-link-hover-bg: transparent;
  --bs-nav-link-active-color: var(--bs-active-color);
  --bs-nav-link-active-bg: transparent;
  --bs-nav-link-disabled-color: var(--bs-disabled-color);
}

.nav-tabs {
  --bs-nav-tabs-border-color: var(--bs-border-color);
  --bs-nav-tabs-border-radius: var(--bs-border-radius);
  --bs-nav-tabs-link-hover-border-color: var(--bs-secondary-bg) var(--bs-secondary-bg) var(--bs-border-color);
  --bs-nav-tabs-link-active-color: var(--bs-active-color);
  --bs-nav-tabs-link-active-bg: var(--bs-component-bg);
  --bs-nav-tabs-link-active-border-color: var(--bs-border-color) var(--bs-border-color) var(--bs-component-bg);
}

.nav-pills {
  --bs-nav-pills-bg: transparent;
  --bs-nav-pills-padding: 0;
  --bs-nav-pills-border-radius: var(--bs-border-radius);
  --bs-nav-pills-link-border-radius: var(--bs-border-radius);
  --bs-nav-pills-link-active-color: var(--bs-component-active-color);
  --bs-nav-pills-link-active-bg: var(--bs-component-active-bg);
}

/* Accordion */
.accordion {
  --bs-accordion-bg: var(--bs-body-bg);
  --bs-accordion-color: var(--bs-body-color);
  --bs-accordion-border-color: var(--bs-border-color);
  --bs-accordion-border-radius: var(--bs-border-radius);
  --bs-accordion-btn-color: var(--bs-body-color);
  --bs-accordion-btn-bg: var(--bs-body-bg);
  --bs-accordion-active-color: var(--bs-primary);
  --bs-accordion-active-bg: var(--bs-active-bg);
}

/* Breadcrumb – plain text links with a slash divider */
.breadcrumb {
  --bs-breadcrumb-font-size: var(--bs-body-font-size-xs);
  --bs-breadcrumb-divider-color: var(--bs-placeholder-color);
  --bs-breadcrumb-divider-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 6 12'%3e%3cpath fill='none' stroke='black' stroke-linecap='round' d='M5 1 1 11'/%3e%3c/svg%3e");
  --bs-breadcrumb-divider-width: 0.375rem;
  --bs-breadcrumb-divider-height: 0.75rem;
  --bs-breadcrumb-link-padding-x: 0;
  --bs-breadcrumb-link-padding-y: 0;
  --bs-breadcrumb-link-color: var(--bs-body-color);
  --bs-breadcrumb-link-hover-color: var(--bs-link-color);
  --bs-breadcrumb-link-hover-bg: transparent;
  --bs-breadcrumb-link-active-color: color-mix(in srgb, var(--bs-body-color) 75%, transparent);
  --bs-breadcrumb-link-border-radius: 0;
}

/* Pagination */
.pagination {
  --bs-pagination-min-height: 0;
  --bs-pagination-padding-x: 0.75rem;
  --bs-pagination-padding-y: 0.375rem;
  --bs-pagination-font-size: 1rem;
  --bs-pagination-bg: var(--bs-body-bg);
  --bs-pagination-border-radius: var(--bs-border-radius);
  --bs-pagination-hover-bg: var(--bs-hover-bg);
  --bs-pagination-active-color: var(--bs-component-active-color);
  --bs-pagination-active-bg: var(--bs-component-active-bg);
  --bs-pagination-active-border-color: var(--bs-component-active-bg);
  --bs-pagination-disabled-color: var(--bs-disabled-color);
  --bs-pagination-disabled-bg: var(--bs-disabled-bg);
}

/* Alerts – a plain block as in Bootstrap 5 (Bootstrap 6 makes it a flex row) */
.alert {
  --bs-alert-padding-x: 1rem;
  --bs-alert-padding-y: 1rem;
  --bs-alert-border-radius: var(--bs-border-radius);
  position: relative;
  display: block;
  margin-bottom: 1rem;
  color: var(--bs-theme-fg-emphasis, var(--bs-alert-color));
}

/* .alert-dismissible is gone from Bootstrap 6 – kept as a Loon class */
.alert-dismissible {
  padding-right: 3rem;
}

.alert-dismissible .btn-close {
  position: absolute;
  top: var(--bs-alert-padding-y);
  right: var(--bs-alert-padding-x);
  z-index: 2;
}

/* Badges */
.badge {
  --bs-badge-color: #fff;
  --bs-badge-bg: transparent;
  --bs-badge-padding-x: 0.65em;
  --bs-badge-padding-y: 0.35em;
  --bs-badge-font-size: 0.75em;
  --bs-badge-font-weight: 700;
  --bs-badge-border-radius: var(--bs-border-radius);
  --bs-badge-border-width: 0;
}

/* Subtle and outline badges keep their theme colours (the tokens above sit in a later
   layer than Bootstrap's and would turn them white on transparent) */
.badge-subtle {
  --bs-badge-color: var(--bs-theme-fg);
  --bs-badge-bg: var(--bs-theme-bg-subtle);
}

.badge-outline {
  --bs-badge-color: var(--bs-theme-fg);
  --bs-badge-bg: transparent;
}

/* Progress */
.progress {
  --bs-progress-height: 1rem;
  --bs-progress-font-size: 0.75rem;
  --bs-progress-bg: var(--bs-secondary-bg);
  --bs-progress-border-radius: var(--bs-border-radius);
  --bs-progress-bar-color: #fff;
  --bs-progress-bar-bg: var(--bs-primary);
}

/* List groups */
.list-group {
  --bs-list-group-bg: var(--bs-component-bg);
  --bs-list-group-border-radius: var(--bs-border-radius);
  --bs-list-group-item-padding-x: var(--bs-spacer-3);
  --bs-list-group-item-padding-y: calc(var(--bs-spacer-3) * 0.75);
  --bs-list-group-active-color: var(--bs-component-active-color);
  --bs-list-group-active-bg: var(--bs-component-active-bg);
  --bs-list-group-active-border-color: var(--bs-component-active-bg);
  --bs-list-group-action-color: color-mix(in srgb, var(--bs-body-color) 75%, transparent);
  --bs-list-group-action-hover-color: var(--bs-hover-color);
  --bs-list-group-action-hover-bg: var(--bs-hover-bg);
  --bs-list-group-action-active-color: var(--bs-component-active-color);
  --bs-list-group-action-active-bg: var(--bs-active-bg);
}

/* Dialogs */
.dialog {
  --bs-dialog-width: 500px;
  --bs-dialog-bg: var(--bs-component-bg);
  --bs-dialog-border-radius: var(--bs-border-radius-lg);
  --bs-dialog-box-shadow: var(--bs-box-shadow-sm);
  --bs-dialog-backdrop-bg: rgba(0, 0, 0, 0.8);
  --bs-dialog-backdrop-blur: 0;
  --bs-dialog-header-border-color: var(--bs-border-color);
  --bs-dialog-footer-border-color: var(--bs-border-color);
}

/* Tooltips, popovers and toasts */
.tooltip {
  --bs-tooltip-padding-x: var(--bs-spacer-2);
  --bs-tooltip-padding-y: 0.25rem;
  --bs-tooltip-font-size: var(--bs-body-font-size-sm);
  --bs-tooltip-color: var(--bs-white);
  --bs-tooltip-bg: var(--bs-black);
  --bs-tooltip-border-radius: var(--bs-border-radius);
  --bs-tooltip-opacity: 0.9;
}

[data-bs-theme=dark] .tooltip {
  --bs-tooltip-color: var(--bs-black);
  --bs-tooltip-bg: var(--bs-white);
}

.popover {
  --bs-popover-border-radius: var(--bs-border-radius-lg);
  --bs-popover-inner-border-radius: calc(var(--bs-border-radius-lg) - var(--bs-border-width));
}

.toast {
  --bs-toast-padding-x: 0.75rem;
  --bs-toast-padding-y: 0.5rem;
  --bs-toast-font-size: 0.875rem;
  --bs-toast-bg: color-mix(in srgb, var(--bs-body-bg) 85%, transparent);
  --bs-toast-header-bg: color-mix(in srgb, var(--bs-body-bg) 85%, transparent);
  --bs-toast-header-color: var(--bs-placeholder-color);
  --bs-toast-border-radius: var(--bs-border-radius);
}

[data-bs-theme=dark] .toast {
  --bs-toast-bg: #383940;
}

/* Avatars – Bootstrap 6 now ships an .avatar; keep ours plain and let size classes in plugins.css decide */
.avatar {
  --bs-avatar-bg: transparent;
  --bs-avatar-color: inherit;
  --bs-avatar-border-radius: 0;
  --bs-avatar-font-weight: 400;
}


/* Logo – inline SVG (LOGO_*_SVG) that takes its colour from --loon-logo-color */
.logo {
  display: inline-block;
  color: var(--loon-logo-color);
}

.logo > svg {
  display: block;
  width: 100%;
  height: auto;
}

/* Stacked logo on the sign-in page */
.logo-stacked {
  width: 160px;
}


/* =============================================================================
   2. TABLES
   ============================================================================= */

.table {
  margin-bottom: 0;
  vertical-align: middle;
  position: relative;
  z-index: 1;
}

/* Horizontal row borders only, drawn on top of each row */
.table > :not(caption) > * > * {
  border-bottom-width: 0;
  border-top-width: var(--bs-table-border-width);
}

.table > :not(caption):first-child > *:first-child > * {
  border-top-width: 0;
}

.table > thead {
  vertical-align: middle;
}

.table > tfoot > * > * {
  border-top-color: var(--bs-gray-500);
}

.table-sm {
  --bs-table-cell-padding-y: 0.625rem;
}

.table-sm > :not(caption) > * > * {
  --bs-table-cell-padding-y: 0.625rem;
  --bs-table-cell-padding-x: 1.25rem;
}

.table-borderless > :not(caption) > * > * {
  border-top-width: 0;
}

.table-columned > :not(caption) > * > * {
  border-top-width: 0;
  border-left-width: 1px;
}

.table-columned > :not(caption) > * > *:first-child {
  border-left: 0;
}

.row > .table-responsive {
  padding-top: calc(var(--bs-gutter-x) * 0.5);
}

/* Text overflow cell */
td.text-overflow {
  position: relative;
  width: 30%;
}

td.text-overflow:before {
  content: '&nbsp;';
  visibility: hidden;
}

td.text-overflow > span {
  position: absolute;
  left: 0;
  right: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding: 0 var(--bs-table-cell-padding-x);
}

.table-hover.dt-error > tbody > tr {
  pointer-events: none;
}

table thead th.th-date,
table thead th.td-date {
  min-width: 128px;
}

/* Editable cells */
td.editable {
  position: relative;
  padding-left: 0;
  padding-top: 0;
  padding-bottom: 0;
}

td.editable .btn-icon i {
  color: var(--bs-placeholder-color);
}

td.editable .btn-icon:hover i {
  color: var(--bs-body-color);
}

/* Tables inside cards – round the outer corners */
.card > .table:first-child > :first-child > tr:first-child > :first-child,
.card > [class*=table-responsive]:first-child > .table:first-child > :first-child > tr:first-child > :first-child {
  border-top-left-radius: calc(var(--bs-border-radius) - var(--bs-border-width));
}

.card > .table:first-child > :first-child > tr:first-child > :last-child,
.card > [class*=table-responsive]:first-child > .table:first-child > :first-child > tr:first-child > :last-child {
  border-top-right-radius: calc(var(--bs-border-radius) - var(--bs-border-width));
}

.card > .table:last-child > :last-child > tr:last-child > :first-child,
.card > [class*=table-responsive]:last-child > .table:last-child > :last-child > tr:last-child > :first-child {
  border-bottom-left-radius: calc(var(--bs-border-radius) - var(--bs-border-width));
}

.card > .table:last-child > :last-child > tr:last-child > :last-child,
.card > [class*=table-responsive]:last-child > .table:last-child > :last-child > tr:last-child > :last-child {
  border-bottom-right-radius: calc(var(--bs-border-radius) - var(--bs-border-width));
}

.card-body + [class*=table-responsive],
.card-body + .table {
  border-top: var(--bs-border-width) solid var(--bs-border-color);
}

/* A table that runs edge to edge in a card: its first and last columns line up with the
   rest of the card (the layout space) */
.card > .card-body.p-0 .table > * > tr > :first-child,
.card > .table > * > tr > :first-child,
.card > [class*=table-responsive] > .table > * > tr > :first-child {
  padding-inline-start: var(--loon-space);
}

.card > .card-body.p-0 .table > * > tr > :last-child,
.card > .table > * > tr > :last-child,
.card > [class*=table-responsive] > .table > * > tr > :last-child {
  padding-inline-end: var(--loon-space);
}

/* Table header – a quiet grey band: smaller, lighter text; the sorted column reads darker */
.table > thead > tr > th {
  padding-block: 0.625rem;
  font-size: var(--bs-btn-input-sm-font-size);
  font-weight: 500;
  color: var(--bs-fg-3);
  background-color: var(--bs-bg-1);
}

.table > thead > tr > th:is(.dt-ordering-asc, .dt-ordering-desc) {
  color: var(--bs-body-color);
}

/* Table card – a standalone table (Table::render): a bar, the table, a footer.
   It sizes itself by its own width (container), so it works the same in a page,
   a tab or a dialog. */
.table-card {
  container: table-card / inline-size;
}

/* Bar: search on the left, actions on the right. On a narrow table the search takes
   the free width and the add button shrinks to its icon (btn-icon-until-lg). */
.table-card > .card-header.table-bar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

:is(.table-bar, .table-toolbar) > .table-search {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 22.5rem;
}

/* Toolbar – the row under the views (search, later filters); same height as a bar */
.table-card > .table-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  padding: var(--loon-bar-padding-y-controls) var(--loon-space);
  border-bottom: var(--bs-border-width) solid var(--bs-border-color-translucent);
}

/* Views – tabs on the top bar, each with its row count. The bar loses its padding so
   the tabs are as tall as the bar and the chosen tab's line sits on its bottom edge.
   Too many tabs for the width: they scroll sideways. */
.table-card > .card-header.table-bar:has(> .table-views) {
  --bs-card-cap-padding-y: 0;
  min-height: var(--loon-bar-height);
}

.table-views {
  display: flex;
  align-self: stretch;
  gap: 1.75rem;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}

.table-view {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: 0.5rem;
  padding: 0 0.125rem;
  border: 0;
  background: transparent;
  color: var(--bs-fg-2);
  font: inherit;
  font-size: var(--bs-btn-input-font-size);
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  box-shadow: inset 0 -2px 0 transparent;
  transition: color var(--bs-transition-base-timer), box-shadow var(--bs-transition-base-timer);
}

.table-view:hover {
  color: var(--bs-body-color);
}

.table-view.active {
  color: var(--bs-body-color);
  box-shadow: inset 0 -2px 0 var(--bs-primary);
}

/* Row count chip – grey, tinted on the chosen view; pulses while it is loading */
.table-view-count {
  display: inline-flex;
  align-items: center;
  height: 1.25rem;
  padding: 0 0.375rem;
  border-radius: var(--bs-border-radius);
  background-color: var(--bs-bg-2);
  color: var(--bs-fg-2);
  font-size: 0.75rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.table-view-count:empty {
  min-width: 1.75rem;
  animation: table-skeleton 1.6s ease-in-out infinite;
}

.table-view.active .table-view-count {
  background-color: var(--loon-item-selected-bg);
  color: var(--loon-item-selected-color);
}

/* In the menu the counts are plain grey numbers on the right, like the filter menus.
   The menu button itself only names the view ("All ⌄"); the footer has the row count. */
.table-views-menu .menu-item .table-view-count {
  height: auto;
  margin-inline-start: auto;
  padding: 0 0 0 1rem;
  background: none;
  color: var(--bs-fg-3);
  font-weight: 400;
}

.table-views-toggle > i {
  font-size: 0.875rem;
}

/* The menu button replaces the tabs on a narrow table (below) */
.table-views-menu {
  display: none;
  min-width: 0;
}

/* Filters – one button per filter; ticked values tint it and show on it */
.table-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
}

.table-filter-toggle > i {
  font-size: 0.875rem;
}

.table-filter-value {
  margin-inline-start: calc(var(--bs-btn-gap, 0.5rem) * -1); /* ": Administration" sits right after the label */
  max-width: 10rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.table-filter-value::before {
  content: ": ";
}

.table-filter-value:empty {
  display: none;
}

.table-filter-toggle.is-filtered {
  border-color: var(--bs-primary-border);
  background-color: var(--loon-item-selected-bg);
  color: var(--loon-item-selected-color);
}

/* Filter and column menus: tick boxes, a count on the right, scroll when long */
.table-filter-menu {
  min-width: 15rem;
  max-height: 22rem;
  overflow-y: auto;
}

:is(.table-filter-option, .table-columns-option) {
  cursor: pointer;
}

.table-filter-count {
  margin-inline-start: auto;
  padding-inline-start: 1rem;
  font-size: 0.75rem;
  color: var(--bs-fg-3);
  font-variant-numeric: tabular-nums;
}

.table-filter-search {
  padding: 0.25rem var(--loon-item-padding-x) 0.375rem;
}

/* Tools – row height switch and column chooser, on the right of their bar */
.table-tools {
  display: flex;
  flex: none;
  align-items: center;
  gap: 0.75rem;
  margin-inline-start: auto;
}

.table-bar > .table-tools + .table-actions {
  margin-inline-start: 0;
}

.table-density {
  display: inline-flex;
  gap: 2px;
  height: var(--bs-btn-input-min-height);
  padding: 3px;
  box-sizing: border-box;
  border: var(--bs-border-width) solid var(--bs-border-color);
  border-radius: var(--bs-border-radius);
}

.table-density > button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  border: 0;
  border-radius: calc(var(--bs-border-radius) - 2px);
  background: transparent;
  color: var(--bs-fg-3);
  cursor: pointer;
}

.table-density > button:hover {
  color: var(--bs-body-color);
}

.table-density > button.active {
  background-color: var(--bs-bg-2);
  color: var(--bs-body-color);
}

.table-density i,
.table-columns-toggle > i {
  font-size: 1rem;
}

/* Bordered icon buttons: the column chooser and every "⋯" menu (tables, page header) */
.table-columns-toggle,
.table-more-toggle,
.page-header-more {
  border: var(--bs-border-width) solid var(--bs-border-color);
}

/* The "⋯" menu has the row height only while the switch is hidden (narrow tables, below);
   with nothing else in it, the whole button waits until then */
@container table-card (width >= 40rem) {
  .table-more-density,
  .table-more-density-only {
    display: none;
  }
}

/* Tick-box column (selectable tables) – as narrow as the box; the cell is the click target.
   The box is 16px: it marks the row, it should not outweigh the row's text and avatar. */
.table > * > tr > .table-select {
  --bs-icon-font-size: 1rem;
  width: 1%;
  padding-inline-end: 0.25rem;
  cursor: pointer;
}

.table .table-select .check {
  display: grid;
}

/* The tick-box header never sorts: no room for a sort arrow next to its box. Its wrapper
   is a block, so the box sits in the middle of the band rather than on the text baseline. */
.table > thead > tr > th.table-select .dt-column-header {
  display: flex;
}

.table > thead > tr > th.table-select .dt-column-order {
  display: none;
}

/* Folded table (Responsive moved columns into the rows): the tick-box column keeps to its
   box and the other columns share the free width. DataTables puts each column's % width
   on a <col>; with % widths left on, the browser hands part of the free width to the tick
   box as well, leaving a gap after it. */
.dataTable.collapsed:has(.table-select) > colgroup > col,
.dataTable.collapsed:has(.table-select) > thead > tr > th {
  width: auto !important;
}

.dataTable.collapsed > thead > tr > th.table-select {
  width: 1px !important;
}

/* Cells (the Table helpers: person, title, status, date, money…) – one look for every table */
.cell-person {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
  vertical-align: middle;
}

.cell-person > .avatar {
  flex: none;
  width: 2.25rem;
  height: 2.25rem;
  line-height: 2.25rem;
  font-size: var(--bs-btn-input-sm-font-size);
  font-weight: 600;
}

.table.density-compact .cell-person > .avatar {
  width: 1.75rem;
  height: 1.75rem;
  line-height: 1.75rem;
  font-size: 0.6875rem;
}

/* The record's name (Table::title, ::person) */
.cell-title > :first-child {
  font-weight: 500;
}

/* Phone and email: body colour until hovered */
.cell-link {
  color: inherit;
  text-decoration: none;
}

.cell-link:hover {
  color: var(--bs-primary);
}

/* Amounts and numbers: even-width digits, on the right */
.cell-num {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.table > tbody > tr:not(.child) > td:has(.cell-num) {
  text-align: end;
}

/* File: its type icon, then the name */
.cell-file {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}

.cell-file > i {
  flex: none;
  color: var(--bs-fg-3);
  font-size: var(--bs-icon-font-size);
}

/* Attachment and yes/no ticks: quiet icons */
.cell-attachment,
.cell-flag {
  color: var(--bs-fg-3);
  font-size: var(--bs-icon-font-size);
  line-height: 1;
}

.cell-attachment:hover {
  color: var(--bs-primary);
}

.cell-stack {
  display: inline-flex;
  flex-direction: column;
  min-width: 0;
  vertical-align: middle;
}

.cell-sub {
  font-size: var(--bs-btn-input-sm-font-size);
  line-height: var(--bs-body-line-height-sm);
  color: var(--bs-fg-3);
}

/* Initials circles: five soft theme colours, picked from the name */
.cell-tone-1 { background-color: var(--bs-primary-bg-subtle); color: var(--bs-primary-fg-emphasis); }
.cell-tone-2 { background-color: var(--bs-success-bg-subtle); color: var(--bs-success-fg-emphasis); }
.cell-tone-3 { background-color: var(--bs-warning-bg-subtle); color: var(--bs-warning-fg-emphasis); }
.cell-tone-4 { background-color: var(--bs-info-bg-subtle); color: var(--bs-info-fg-emphasis); }
.cell-tone-5 { background-color: var(--bs-accent-bg-subtle); color: var(--bs-accent-fg-emphasis); }

/* Status: a tinted label with a dot */
.cell-status {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  height: 1.5rem;
  padding: 0 0.625rem;
  border-radius: var(--bs-border-radius);
  background-color: var(--bs-secondary-bg);
  color: var(--bs-secondary-fg);
  font-size: var(--bs-body-font-size-xs);
  font-weight: 500;
  white-space: nowrap;
}

.cell-status::before {
  content: "";
  width: 0.375rem;
  height: 0.375rem;
  border-radius: 50%;
  background-color: currentColor;
}

.cell-status-success { background-color: var(--bs-success-bg-subtle); color: var(--bs-success-fg-emphasis); }
.cell-status-warning { background-color: var(--bs-warning-bg-subtle); color: var(--bs-warning-fg-emphasis); }
.cell-status-danger { background-color: var(--bs-danger-bg-subtle); color: var(--bs-danger-fg-emphasis); }
.cell-status-info { background-color: var(--bs-info-bg-subtle); color: var(--bs-info-fg-emphasis); }
.cell-status-primary { background-color: var(--bs-primary-bg-subtle); color: var(--bs-primary-fg-emphasis); }

/* Ticked rows: a light tint of the primary colour */
.table > tbody > tr.is-selected > td {
  background-color: color-mix(in srgb, var(--bs-primary) 6%, var(--bs-component-bg));
}

/* Selection line – opens under the bars when rows are ticked (grid rows 0fr → 1fr slides it) */
.table-selection {
  display: grid;
  grid-template-rows: 0fr;
  background-color: color-mix(in srgb, var(--bs-primary) 6%, var(--bs-component-bg));
  transition: grid-template-rows var(--bs-transition-base-timer) ease, background-color var(--bs-transition-base-timer);
}

.table-card.has-selection .table-selection {
  grid-template-rows: 1fr;
  border-bottom: var(--bs-border-width) solid var(--bs-border-color-translucent);
}

.table-selection-inner {
  min-height: 0;
  overflow: hidden;
}

.table-selection-main,
.table-selection-confirm {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
  min-height: var(--bs-btn-input-sm-min-height);
  padding: 0.625rem var(--loon-space);
  font-size: var(--bs-btn-input-sm-font-size);
}

.table-selection-count {
  font-weight: 600;
  color: var(--bs-body-color);
}

.table-selection-every {
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--bs-link-color);
  font: inherit;
  font-weight: 500;
  cursor: pointer;
}

.table-selection-every:hover {
  color: var(--bs-link-hover-color);
  text-decoration: underline;
}

.table-selection-divider {
  width: var(--bs-border-width);
  height: 1.25rem;
  background-color: var(--bs-primary-border);
}

.table-selection .btn > i {
  font-size: 0.875rem;
}

.table-selection-clear {
  margin-inline-start: auto;
}

/* Delete question takes the line's place, tinted red */
.table-selection-confirm {
  display: none;
}

.table-card.is-confirming .table-selection {
  background-color: var(--bs-danger-bg-subtle);
}

.table-card.is-confirming .table-selection-main {
  display: none;
}

.table-card.is-confirming .table-selection-confirm {
  display: flex;
}

.table-selection-question {
  margin-inline-end: auto;
  font-weight: 600;
  color: var(--bs-danger-fg-emphasis);
}

/* Skeleton tick box – a circle, like the tick box */
.table-sk-check {
  width: var(--bs-icon-font-size);
  height: var(--bs-icon-font-size);
  margin-block: calc((1lh - var(--bs-icon-font-size)) / 2);
  border-radius: 50%;
}

/* Row height (the switch above) */
.table.density-compact {
  --bs-table-cell-padding-y: 0.5rem;
}

.table.density-comfortable {
  --bs-table-cell-padding-y: 1.375rem;
}

/* Sorting – a faint up/down arrow on a sortable header when hovered, a firm arrow on the
   sorted one (DataTables adds .dt-column-order and the dt-ordering-* classes) */
.table > thead > tr > th:is(.dt-orderable-asc, .dt-orderable-desc) {
  cursor: pointer;
  user-select: none;
}

.table > thead .dt-column-header {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
}

.table > thead .dt-column-order {
  display: inline-flex;
  width: 0.875rem;
}

.table > thead .dt-column-order::before {
  font-family: var(--bs-icon-font-family);
  font-size: 0.75rem;
  line-height: 1;
  content: "\f127";
  opacity: 0;
  transition: opacity var(--bs-transition-base-timer);
}

.table > thead > tr > th:is(.dt-orderable-asc, .dt-orderable-desc):hover .dt-column-order::before {
  opacity: 0.5;
}

.table > thead > tr > th.dt-ordering-asc .dt-column-order::before {
  content: "\f148";
  opacity: 1;
}

.table > thead > tr > th.dt-ordering-desc .dt-column-order::before {
  content: "\f128";
  opacity: 1;
}

/* Right-aligned columns (numbers, amounts): the arrow goes before the title, so the title
   lines up with the right edge of the values under it */
.table > thead > tr > th:is(.text-end, .dt-type-numeric) .dt-column-header {
  flex-direction: row-reverse;
}

.table-bar > .table-actions {
  display: flex;
  flex: none;
  align-items: center;
  gap: 0.75rem;
  margin-inline-start: auto;
}

/* Footer: the count on the left, the pages in the middle, the page size on the right (the
   two outer columns share the rest equally, so the pages stay centred). Always one bar
   tall, skeleton or not, so nothing moves when it fills in. */
.table-card > .card-footer.table-footer {
  --bs-card-cap-padding-y: calc((var(--loon-bar-height) - var(--bs-btn-input-sm-min-height)) / 2);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 0.75rem 1.5rem;
  min-height: var(--loon-bar-height);
}

.table-info {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  font-size: var(--bs-btn-input-sm-font-size);
  color: var(--bs-fg-3);
}

.table-size {
  display: flex;
  justify-content: flex-end;
}

.table-info strong {
  font-weight: 600;
  color: var(--bs-body-color);
}

.table-length > i {
  font-size: 0.875rem;
}

.table-pages {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

/* Page buttons: plain numbers, the current one tinted like a selected menu row;
   previous / next have a border */
.table-page {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--bs-btn-input-sm-min-height);
  height: var(--bs-btn-input-sm-min-height);
  padding: 0 0.375rem;
  border: var(--bs-border-width) solid transparent;
  border-radius: var(--bs-border-radius);
  background: transparent;
  color: var(--bs-fg-1);
  font: inherit;
  font-size: var(--bs-btn-input-sm-font-size);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}

.table-page:hover {
  background-color: var(--bs-hover-bg);
}

.table-page.active {
  background-color: var(--loon-item-selected-bg);
  color: var(--loon-item-selected-color);
  font-weight: 600;
}

.table-page-nav {
  border-color: var(--bs-border-color);
}

.table-page-nav > i {
  font-size: 1rem;
}

.table-page:disabled {
  opacity: var(--bs-btn-disabled-opacity);
  background: transparent;
  cursor: default;
}

.table-page-gap {
  min-width: 1.75rem;
  text-align: center;
  color: var(--bs-fg-3);
}

.table-page-of {
  display: none;
  padding: 0 0.375rem;
  font-size: var(--bs-btn-input-sm-font-size);
  color: var(--bs-fg-3);
  white-space: nowrap;
}

/* Tabs that do not fit the bar fold into one menu button ("All 627 ⌄"); app.js measures
   and sets .views-folded. The bar gets its normal padding back. */
.table-card.views-folded .table-views {
  display: none;
}

.table-card.views-folded .table-views-menu {
  display: block;
}

.table-card.views-folded > .card-header.table-bar:has(> .table-views) {
  --bs-card-cap-padding-y: var(--loon-bar-padding-y-controls);
}

/* Toolbar on a smaller table: the search gets a full row, filters and tools share the next */
@container table-card (width < 48rem) {
  .table-toolbar > .table-search {
    flex: 1 1 100%;
    max-width: none;
  }

  .table-toolbar > .table-filters {
    flex: 1 1 auto;
  }
}

/* No room for the row height switch; on a phone the column chooser goes too (columns
   that do not fit fold into the rows anyway) */
@container table-card (width < 40rem) {
  .table-density {
    display: none;
  }
}

@container table-card (width < 30rem) {
  .table-columns {
    display: none;
  }

  /* Phone: the main column (first after the tick box) wraps instead of folding away,
     so every row keeps its name; the rest open from the row */
  .table > tbody > tr > td:first-child:not(.table-select),
  .table > tbody > tr > td.table-select + td {
    white-space: normal;
  }

  /* Tick box: close to the row's content */
  .table > * > tr > .table-select + * {
    padding-inline-start: 0.5rem;
  }

  /* Selection line on a phone: two lines – the count, then the actions (the divider breaks the line) */
  .table-selection-divider {
    flex-basis: 100%;
    height: 0;
    background: none;
  }

  /* Filters two to a row, their text shortened with … when long; the "⋯" menu stays on
     their row (the filters give it room rather than pushing it onto a row of its own) */
  .table-toolbar > .table-filters {
    flex: 1 1 0;
  }

  .table-filter {
    flex: 1 1 40%;
    min-width: 0;
  }

  .table-filter-toggle {
    width: 100%;
    min-width: 0;
  }

  .table-filter-toggle > :is(.table-filter-label, .table-filter-value) {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .table-filter-toggle > .table-filter-value {
    flex: 1 1 auto;
    margin-inline-start: 0;
    text-align: start;
  }

  /* Filtered: the value alone ("Administration"), the tint says it is a filter */
  .table-filter-toggle.is-filtered > .table-filter-label {
    display: none;
  }

  .table-filter-value::before {
    content: none;
  }
}

/* Medium table (tablet, half-width column): pages become ‹ 3 of 63 ›, so the footer
   stays one row */
@container table-card (width < 48rem) {
  .table-pages > .table-page:not(.active, .table-page-nav),
  .table-pages > .table-page-gap {
    display: none;
  }

  .table-page-of {
    display: inline;
  }
}

/* Narrow table (phone, dialog): the pages get their own row on top, centred; the count
   (without its "Showing" word) and the page size share the row under it */
@container table-card (width < 30rem) {
  .table-card > .card-footer.table-footer {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
  }

  .table-pages {
    order: -1;
    flex: 1 1 100%;
    justify-content: center;
  }

  .table-pages:empty {
    display: none;
  }

  .table-info-label {
    display: none;
  }
}

/* First load: skeleton rows (second <tbody>) as tall as real rows, pale bars that
   breathe; the real <tbody> stays hidden until the data is in */
.table > tbody.table-skeleton {
  display: none;
}

.preload .table > tbody.table-skeleton {
  display: table-row-group;
}

.preload .table > tbody:not(.table-skeleton) {
  display: none;
}

.table-sk {
  display: block;
  height: 0.625rem;
  max-width: 14rem;
  margin-block: calc((1lh - 0.625rem) / 2);
  border-radius: 0.3125rem;
  background-color: var(--bs-bg-3);
  animation: table-skeleton 1.6s ease-in-out infinite;
}

.text-end > .table-sk {
  margin-inline-start: auto;
}

.text-center > .table-sk {
  margin-inline: auto;
}

.table-footer .table-sk {
  margin-block: 0;
}

/* On a narrow table DataTables tucks the right-hand columns away once the data is in;
   the skeleton shows only the first ones, so the table does not change shape */
@container table-card (width < 48rem) {
  .preload .table tr > :nth-child(n+4) {
    display: none;
  }
}

@container table-card (width < 30rem) {
  .preload .table tr > :nth-child(n+3) {
    display: none;
  }
}

.table-sk-control {
  width: 7rem;
  height: var(--bs-btn-input-sm-min-height);
  border-radius: var(--bs-border-radius);
  background-color: var(--bs-bg-2);
}

.table-sk-text {
  width: 8.5rem;
}

.table-sk-pages {
  width: 12rem;
  height: var(--bs-btn-input-sm-min-height);
  border-radius: var(--bs-border-radius);
  background-color: var(--bs-bg-2);
}

@keyframes table-skeleton {
  50% {
    opacity: 0.45;
  }
}

/* Page change, search or sort: the rows stay, dimmed and not clickable, while a thin
   bar runs under the header (.dt-processing, see plugins.css) */
.table > tbody {
  transition: opacity var(--bs-transition-base-timer);
}

.table.is-busy > tbody {
  opacity: 0.45;
  pointer-events: none;
}


/* =============================================================================
   3. FORMS
   ============================================================================= */

.form-label {
  margin-bottom: var(--bs-form-label-margin-bottom);
  display: flex;
}

/* Stacked column labels lose their top padding on small screens */
@media (width < 576px) {
  .col-form-label[class*="sm:col-"] {
    padding-top: 0;
  }
}

@media (width < 768px) {
  .col-form-label[class*="md:col-"] {
    padding-top: 0;
  }
}

@media (width < 1024px) {
  .col-form-label[class*="lg:col-"] {
    padding-top: 0;
  }
}

@media (width < 1280px) {
  .col-form-label[class*="xl:col-"] {
    padding-top: 0;
  }
}

@media (width < 1536px) {
  .col-form-label[class*="2xl:col-"] {
    padding-top: 0;
  }
}

/* Form controls (also used on <select> – .form-select is gone in Bootstrap 6) */
.form-control {
  font-weight: var(--bs-body-font-weight);
  transition: border-color var(--bs-transition-base-timer) ease-in-out, box-shadow var(--bs-transition-base-timer) ease-in-out;
}

.form-control:hover {
  border-color: var(--bs-border-hover-color);
}

.form-control:focus,
.form-control:focus-within {
  background-color: var(--bs-input-focus-bg);
  border-color: var(--bs-input-focus-border-color);
  outline: 0;
  box-shadow: var(--bs-input-focus-box-shadow);
}

select.form-control,
.form-control[readonly] {
  cursor: pointer;
}

.form-control:disabled {
  cursor: not-allowed;
}

.form-control[readonly]:focus {
  border-color: var(--bs-primary);
}

.form-control-plaintext:focus {
  outline: 0;
}

/* Labels, help text and section titles: a tad inside the field's rounded corner */
.form-label,
.form-text,
.form-section-title,
.form-section-note {
  padding-inline-start: var(--bs-form-text-inset);
}

/* Form text */
.form-text {
  margin-top: var(--bs-form-text-margin-top);
  color: var(--bs-form-text-color);
  font-size: 0.8125rem;
}

/* Fields in a form: 20px apart, across and down */
form .grid {
  --bs-gap: 1.25rem;
}

/* Form section title (a char(0) column): a clear 16px title with a short grey note */
.form-section-title {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
}

.form-section-note {
  margin: 0.125rem 0 0;
  font-size: 0.875rem;
  color: var(--bs-fg-3);
}

.form-text i {
  font-size: small;
}

/* Selects */
select.form-control:focus {
  box-shadow: none;
}

select.form-control:required:invalid {
  color: var(--bs-gray-600);
}

select.form-control option[value=""][disabled] {
  display: none;
}

/* Native list selects (multiple / size) – same item look as menus and select drop-downs */
select.form-control:is([multiple], [size]:not([size="1"])) {
  padding: var(--loon-pop-padding) 0;
}

select.form-control:is([multiple], [size]:not([size="1"])) option {
  padding: var(--loon-item-padding-y) var(--loon-item-padding-x);
  font-size: var(--bs-btn-input-font-size);
  border-radius: var(--loon-item-radius);
}

select.form-control:is([multiple], [size]:not([size="1"])) option:checked {
  color: var(--loon-item-selected-color);
  background: var(--loon-item-selected-bg);
}

select.form-control.inline {
  padding-top: var(--bs-spacer-1);
  padding-bottom: var(--bs-spacer-1);
}

/* Inline form controls */
form .form-control.inline {
  width: initial;
  min-height: 0;
  display: inline;
  border: none;
  border-bottom: 1px solid;
  border-radius: 0;
  outline: 0;
  padding: var(--bs-spacer-1) var(--bs-spacer-2);
}

form select.form-control.inline {
  padding-left: 0;
}

/* Checkbox, radio and switch – vertically centred in a form row */
.form-field:has(> .check, > .radio, > .switch) {
  align-items: center;
}

/* Developer gear next to form labels and titles – shows only when you hover the
   label or title itself, not the input. Hidden gears take no space. */
.btn.dev-gear {
  display: none;
  /* never taller than the label, so showing it moves nothing */
  --bs-btn-padding-y: 0;
  --bs-btn-min-height: 0;
  --bs-btn-line-height: 1;
  --bs-btn-border-width: 0;
  min-width: 0;
  line-height: 1;
}

.btn.dev-gear::after {
  content: none;
}

.card-header:hover .btn.dev-gear,
.grid > * > :first-child:hover .btn.dev-gear,
section > :first-child:hover .btn.dev-gear,
.btn.dev-gear:focus-visible {
  display: inline-flex;
}

/* Colour field (FormElements::renderColorPicker + ColorField in app.js): preset
   colours as 28px circles and a pen for any other colour. The row is as tall as a
   field, so it lines up with the fields next to it. */
.color-field {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  min-height: var(--bs-btn-input-min-height);
}

.color-swatch {
  --swatch: var(--bs-gray-400);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 1.75rem;
  height: 1.75rem;
  padding: 0;
  font-size: 0.875rem;
  line-height: 1;
  color: #fff;
  background: var(--swatch);
  border: 0;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
  cursor: pointer;
  transition: transform 0.12s ease-out, box-shadow 0.12s ease-out;
}

.color-swatch:hover {
  transform: scale(1.1);
}

.color-swatch:focus-visible {
  outline: 2px solid var(--bs-component-active-bg);
  outline-offset: 3px;
}

.color-swatch:disabled {
  cursor: default;
  opacity: 0.5;
  transform: none;
}

/* Picked: a ring in its own colour (with a gap) and a tick */
.color-swatch.active {
  box-shadow: 0 0 0 2px var(--bs-component-bg), 0 0 0 4px var(--swatch);
}

.color-swatch.active:not(.color-swatch-custom)::after {
  content: "\f633"; /* icon-check2 */
  font-family: var(--bs-icon-font-family);
  font-size: 1rem;
}

/* Light colours get a dark tick and pen */
.color-swatch.is-light {
  color: var(--bs-gray-900);
}

/* The pen: a white circle in a thin rainbow ring until a colour of your own is picked */
.color-swatch-custom:not(.active) {
  color: var(--bs-fg-2);
  background:
    radial-gradient(circle, var(--bs-component-bg) 0 58%, transparent 60%),
    conic-gradient(#EF4444, #F59E0B, #10B981, #06B6D4, #3B82F6, #8B5CF6, #EC4899, #EF4444);
  box-shadow: none;
}

.color-swatch-custom:not(.active):hover {
  color: var(--bs-body-color);
}

/* A required colour that is missing */
.color-field:has(> .is-invalid) .color-swatch:not(.active) {
  box-shadow: inset 0 0 0 1px var(--bs-danger);
}

/* The custom colour picker (opens in the floating panel, like the calendar):
   shade area, hue slider with the eyedropper, and the hex field with a preview */
.color-pop {
  position: fixed;
  z-index: 1090;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  width: 15rem;
  padding: 0.75rem;
  color: var(--bs-body-color);
  background-color: var(--bs-component-bg);
  border: var(--bs-border-width) solid var(--loon-pop-border-color);
  border-radius: var(--loon-pop-radius);
  box-shadow: var(--loon-pop-shadow);
  opacity: 0;
  transition: opacity 0.12s ease-out;
}

.color-pop.show {
  opacity: 1;
}

.color-pop-area {
  position: relative;
  height: 9rem;
  background-color: var(--hue, #f00);
  background-image: linear-gradient(to top, #000, transparent), linear-gradient(to right, #fff, transparent);
  border-radius: var(--bs-border-radius);
  cursor: crosshair;
  touch-action: none;
}

.color-pop-area:focus-visible {
  outline: 2px solid var(--bs-component-active-bg);
  outline-offset: 2px;
}

.color-pop-knob {
  position: absolute;
  width: 0.875rem;
  height: 0.875rem;
  margin: -0.4375rem 0 0 -0.4375rem;
  background-color: var(--picked);
  border: 2px solid #fff;
  border-radius: 50%;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2), 0 1px 3px rgba(0, 0, 0, 0.3);
  pointer-events: none;
}

.color-pop-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* Hue: a rainbow track with a white knob */
.color-pop-hue {
  flex: 1 1 auto;
  height: 0.75rem;
  margin: 0;
  background: linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00);
  border-radius: 1rem;
  outline: 0;
  appearance: none;
  -webkit-appearance: none;
}

.color-pop-hue::-webkit-slider-thumb {
  width: 1rem;
  height: 1rem;
  background-color: #fff;
  border: 0;
  border-radius: 50%;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2), 0 1px 3px rgba(0, 0, 0, 0.3);
  cursor: pointer;
  -webkit-appearance: none;
}

.color-pop-hue::-moz-range-thumb {
  width: 1rem;
  height: 1rem;
  background-color: #fff;
  border: 0;
  border-radius: 50%;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2), 0 1px 3px rgba(0, 0, 0, 0.3);
  cursor: pointer;
}

.color-pop-hue:focus-visible::-webkit-slider-thumb {
  box-shadow: 0 0 0 2px var(--bs-component-active-bg);
}

.color-pop-preview {
  flex-shrink: 0;
  width: var(--bs-btn-input-sm-min-height);
  height: var(--bs-btn-input-sm-min-height);
  background-color: var(--picked);
  border-radius: var(--bs-border-radius);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
}

.color-pop-hex {
  font-variant-numeric: tabular-nums;
  text-transform: uppercase;
}

/* Form control feedback (icon inside the control) */
.form-control-feedback {
  position: relative;
}

.form-control-feedback-start .form-control {
  padding-left: calc(var(--bs-spacer-2) * 2 + var(--bs-icon-font-size));
}

.form-control-feedback-end .form-control {
  padding-right: calc(var(--bs-spacer-2) * 2 + var(--bs-icon-font-size));
}

.form-control-feedback-icon {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 4;
  display: flex;
  align-items: center;
  padding: var(--bs-spacing);
  font-size: var(--bs-icon-font-size);
  line-height: 1;
  color: var(--bs-gray-600);
  pointer-events: none;
}

.form-control-feedback-start .form-control-feedback-icon {
  left: 0;
}

.form-control-feedback-end .form-control-feedback-icon {
  right: 0;
}

.form-floating.form-control-feedback-start > label {
  left: calc(var(--bs-spacer-3) + var(--bs-icon-font-size));
}

.form-floating.form-control-feedback-end > label {
  right: calc(var(--bs-spacer-3) + var(--bs-icon-font-size));
}

/* Input group with an icon inside the field – the field keeps its full width and corners
   (the icon is absolute, so Bootstrap's input-group joins don't apply).
   The icon sits at the field's normal text inset (12px), and the text follows 8px after
   it – the same icon-to-text gap as buttons and menu items. */
.input-group.input-group-icon {
  --loon-input-icon-size: calc(var(--bs-icon-font-size) * 0.8);
}

.input-group.input-group-icon .form-control {
  margin-inline-start: 0;
  border-radius: var(--bs-border-radius);
}

.input-group.input-group-icon .input-group-text {
  position: absolute;
  z-index: 9;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--loon-input-icon-size);
  height: 100%;
  padding: 0;
  font-size: var(--loon-input-icon-size);
  color: var(--bs-placeholder-color);
  background: none;
  border: none;
}

.input-group.input-group-icon .input-group-text > * {
  font-size: inherit;
}

.input-group.input-group-icon .input-group-text:first-child {
  left: var(--bs-input-padding-x);
}

.input-group.input-group-icon .input-group-text:not(:first-child) {
  right: var(--bs-input-padding-x);
}

.input-group.input-group-icon .form-control:not(:first-child),
.input-group.input-group-icon label:last-child {
  padding-left: calc(var(--bs-input-padding-x) + var(--loon-input-icon-size) + 0.5rem);
}

.input-group.input-group-icon .form-control:first-child,
.input-group.input-group-icon label:not(:last-child) {
  padding-right: calc(var(--bs-input-padding-x) + var(--loon-input-icon-size) + 0.5rem);
}


/* =============================================================================
   4. BUTTONS
   ============================================================================= */

/* Icon-only button – a square exactly as tall as the other buttons of its size
   (40px, 32px with .btn-sm, 48px with .btn-lg). The width is a minimum, so .w-100 still
   works. Without a style class it is quiet: no border, grey only on hover. */
.btn-icon {
  --bs-btn-gap: 0;
  min-width: var(--bs-btn-min-height);
  padding-inline: 0;
  aspect-ratio: auto;
}

.btn-icon:not(.btn-solid, .btn-outline, .btn-subtle) {
  --bs-btn-bg: transparent;
  --bs-btn-color: var(--bs-body-color);
  --bs-btn-hover-bg: var(--bs-hover-bg);
  --bs-btn-hover-color: var(--bs-hover-color);
  --bs-btn-border-color: transparent;
  --bs-btn-hover-border-color: transparent;
}

.btn-icon span:empty {
  display: none;
}

/* A button that shows only its icon below 1024px (its text has d-none lg:d-inline):
   a square there, a normal button from 1024px */
@media (width < 1024px) {
  .btn-icon-until-lg {
    --bs-btn-gap: 0;
    min-width: var(--bs-btn-min-height);
    padding-inline: 0;
  }
}

.btn-icon-lg,
.btn-icon-lg > i,
.btn-icon-lg > i:before {
  font-size: var(--bs-body-font-size-lg);
}

.btn-icon-sm,
.btn-icon-sm > i,
.btn-icon-sm > i:before {
  font-size: var(--bs-body-font-size-sm);
}

.btn-transparent {
  --bs-btn-bg: transparent;
}

.btn-link {
  text-decoration: underline;
}

/* Labeled buttons (icon block on one side) */
.btn-labeled {
  position: relative;
}

.btn-labeled-start {
  padding-left: calc(var(--bs-spacer-2) * 2 + var(--bs-border-width) * 2 + var(--bs-body-font-size) * var(--bs-body-line-height) + var(--bs-spacer-3));
}

.btn-labeled-end {
  padding-right: calc(var(--bs-spacer-2) * 2 + var(--bs-border-width) * 2 + var(--bs-body-font-size) * var(--bs-body-line-height) + var(--bs-spacer-3));
}

.btn-labeled-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  top: calc(var(--bs-border-width) * -1);
  bottom: calc(var(--bs-border-width) * -1);
  padding: var(--bs-spacer-2);
  width: calc(var(--bs-spacer-2) * 2 + var(--bs-border-width) * 2 + var(--bs-body-font-size) * var(--bs-body-line-height));
}

.btn-labeled-start .btn-labeled-icon {
  left: calc(var(--bs-border-width) * -1);
  border-top-left-radius: inherit;
  border-bottom-left-radius: inherit;
}

.btn-labeled-end .btn-labeled-icon {
  right: calc(var(--bs-border-width) * -1);
  border-top-right-radius: inherit;
  border-bottom-right-radius: inherit;
}

/* Sizes: .btn-sm and .btn-lg come straight from the control sizes in variables.css */

/* Small icon buttons (close, settings) – no background, ever. They take the colour
   of where they sit (white on a coloured header, grey on a card) at 70% and go to
   full colour on hover. currentColor, not inherit: inherit in a custom property
   copies the parent's variable, not its colour. */
.btn-icon.btn-sm {
  --bs-btn-color: currentColor;
  --bs-btn-bg: transparent;
  --bs-btn-hover-color: currentColor;
  --bs-btn-hover-bg: transparent;
  --bs-btn-active-color: currentColor;
  --bs-btn-active-bg: transparent;
  --bs-btn-active-border-color: transparent;
  opacity: 0.7;
}

.btn-icon.btn-sm > i {
  font-size: 1rem;
}

.btn-icon.btn-sm:hover,
.btn-icon.btn-sm:focus-visible {
  opacity: 1;
}


/* =============================================================================
   5. NAVIGATION AND NAVBAR
   ============================================================================= */

.navbar {
  background-color: var(--bs-component-bg);
  flex-wrap: nowrap;
  justify-content: flex-start;
}

/* .navbar-dark is gone from Bootstrap 6 – kept as a Loon class */
.navbar-dark {
  background-color: var(--bs-dark);
}

.navbar-nav {
  --bs-nav-gap: 0;
  flex-direction: row;
}

.navbar-brand {
  margin: unset;
  padding: var(--bs-spacing-3) var(--bs-spacing-2);
  font-size: var(--bs-body-font-size);
  position: relative;
  min-width: 4em;
  min-height: calc(var(--bs-body-font-size) * var(--bs-body-line-height) + (var(--bs-spacing-3) * 2));
  display: flex;
  align-items: center;
}

.navbar-brand::before {
  content: "Brand";
  visibility: hidden;
  height: 0;
  overflow: hidden;
}

.navbar-brand > a {
  padding: 0;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  width: 100%;
  height: 100%;
  justify-content: center;
}

.navbar-brand > a > svg {
  width: 2em;
  height: auto;
  pointer-events: none;
}

/* Navbar items (links, buttons and menu toggles) */
.nav-item > a,
.nav-item > .btn,
.nav-item .btn[data-bs-toggle=menu] {
  padding: var(--bs-spacer-3);
  color: var(--bs-btn-color);
  background: unset;
  border-radius: 0;
  border-color: transparent;
}

.navbar-dark .nav-item > a,
.navbar-dark .nav-item > .btn,
.navbar-dark .nav-item .btn[data-bs-toggle=menu] {
  color: #fff;
}

.nav-item,
.nav-item .btn[data-bs-toggle=menu],
.navbar-nav-link {
  border: none;
}

.nav-item:hover,
.navbar-nav-link:hover {
  background-color: var(--bs-hover-bg);
}

.navbar-dark .nav-item:hover,
.navbar-dark .navbar-nav-link:hover {
  background-color: var(--bs-highlight-bg);
}

.navbar-dark .nav-item > .btn:hover {
  background: unset;
}

.navbar-nav-link-icon i {
  display: flex;
  align-items: center;
}

.nav-sidebar .nav-item-header:not(:first-child) {
  padding-top: 1.875rem;
}

/* Module menus (the bar under the navbar) – the app's main menus: at least 15rem wide and
   never narrower than their module's button */
.navbar-2 .menu {
  --bs-menu-min-width: 15rem;
  min-width: max(var(--bs-menu-min-width), 100%);
}

/* Underlined tabs (page header and cards) */
.nav-tabs-underline {
  box-shadow: none;
}

.nav-tabs-underline > .nav-item > .nav-link {
  margin-bottom: calc(var(--bs-border-width) * -1);
  padding: var(--bs-spacing-2);
  color: var(--bs-body-color);
  border: var(--bs-border-width) solid transparent;
  border-bottom-width: 2px;
  border-radius: var(--bs-border-radius) var(--bs-border-radius) 0 0;
}

.nav-tabs-underline > .nav-item > .nav-link:hover {
  border-color: transparent;
}

.nav-tabs-underline > .nav-item > .nav-link.active {
  background-color: var(--bs-body-bg);
  border-color: transparent;
  border-bottom-color: var(--bs-primary);
}

/* Plain links in underlined tabs (Nav::build renders <a> without .nav-link) */
.nav-tabs-underline > .nav-item > a:not(.nav-link) {
  padding: var(--bs-spacing-2);
  border: var(--bs-border-width) solid transparent;
  border-bottom-width: 2px;
}

.nav-tabs-underline > .nav-item > a.active:not(.nav-link) {
  border-bottom-color: var(--bs-primary);
}

/* Menu toggles inside underlined tabs */
.nav-tabs-underline [data-bs-toggle=menu] {
  border: none;
  background: transparent;
  padding: var(--bs-spacing);
  position: relative;
}

.nav-tabs-underline [data-bs-toggle=menu]:hover,
.nav-tabs-underline [data-bs-toggle=menu]:focus,
.nav-tabs-underline [data-bs-toggle=menu].show {
  background-color: var(--bs-hover-bg);
  border: none;
  box-shadow: none;
}

.nav-tabs-underline [data-bs-toggle=menu].active:before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(var(--bs-border-width) - 1px);
  height: calc(var(--bs-border-width) * 2);
  background-color: var(--bs-primary);
  transition: background-color ease-in-out var(--bs-transition-base-timer);
}


/* =============================================================================
   6. MENUS (was dropdowns)
   ============================================================================= */

/* Toggle styled as a form field */
button.form-control[data-bs-toggle=menu] {
  justify-content: left;
}

/* Chevron on a menu button – small and quiet, turns over while the menu is open */
.menu-caret {
  font-size: 0.75rem;
  opacity: 0.7;
  transition: transform var(--bs-transition-base-timer) ease-in-out;
}

[aria-expanded="true"] > .menu-caret {
  transform: rotate(180deg);
}

/* Split button: the chevron half is narrow and square */
.menu-toggle-split {
  --bs-btn-padding-x: var(--bs-btn-padding-y);
}

/* Open toggle: a grey "pressed" look – except solid colour buttons, which keep their colour */
[data-bs-toggle=menu]:not(.btn-solid):focus,
[data-bs-toggle=menu]:not(.btn-solid).show,
[data-bs-toggle=menu]:not(.btn-solid)[aria-expanded=true] {
  --bs-btn-active-bg: var(--bs-hover-bg);
  --bs-btn-active-color: var(--bs-hover-color);
  --bs-btn-active-border-color: var(--bs-border-color);
  background-color: var(--bs-hover-bg);
}

.navbar-dark [data-bs-toggle=menu]:focus,
.navbar-dark [data-bs-toggle=menu]:active,
.navbar-dark [data-bs-toggle=menu].show {
  background-color: var(--bs-highlight-bg);
}

.menu.show {
  margin-top: var(--bs-menu-spacer);
}

.menu .list-group {
  border-radius: 0;
}

.menu .list-group .list-group-item {
  padding: var(--bs-spacer-2) var(--bs-spacer-3);
  border: none;
}

.menu .list-group .list-group-item:hover {
  cursor: pointer;
}

/* Items: icons are quiet grey and take the item's colour on hover. A coloured item
   (class="menu-item theme-danger") keeps its colour for the icon too. */
.menu-item {
  line-height: var(--bs-body-line-height);
}

.menu-item > i {
  font-size: var(--bs-menu-icon-size);
  color: var(--bs-fg-3);
}

.menu-item:hover > i,
.menu-item.active > i,
.menu-item[class*="theme-"] > i {
  color: inherit;
}

/* Selected item: a soft blue tint, not a solid bar (the same as a selected option in a select) */
.menu-item.active {
  font-weight: 500;
}

.menu-item.active:hover {
  color: var(--bs-menu-item-active-color);
  background-color: var(--bs-menu-item-active-bg);
}

/* Selected list-group item keeps the solid style on hover */
.list-group-item.active:hover,
.list-group-item-action.active:hover {
  background-color: var(--bs-component-active-bg-hover);
  color: var(--bs-component-active-color);
}

/* Section header: a small grey caption in normal case, no background – the same as
   option groups in a select */
.menu-header {
  font-size: 0.8125rem; /* same as help text under a field */
  font-weight: 600;
}

/* Plain text in a menu (e.g. an email under the name) */
.menu-text {
  padding: 0 var(--bs-menu-item-padding-x) var(--bs-menu-item-padding-y);
  font-size: var(--bs-body-font-size-sm);
  color: var(--bs-fg-3);
}


/* =============================================================================
   7. ACCORDION
   Native <details>/<summary> in Bootstrap 6
   ============================================================================= */

.accordion-header {
  font-size: 0.875rem;
}

.accordion-body {
  box-shadow: inset 0 var(--bs-border-width) 0 var(--bs-border-color);
}


/* =============================================================================
   8. BREADCRUMB
   ============================================================================= */

.breadcrumb {
  overflow-y: auto;
  flex-wrap: nowrap;
}

.breadcrumb-item {
  align-items: center;
  white-space: nowrap;
}

.breadcrumb-link {
  min-height: 0;
}

.breadcrumb-divider {
  margin-inline: 0.5rem;
}

/* Text dividers instead of the slash */
.breadcrumb-dash .breadcrumb-divider::before,
.breadcrumb-arrow .breadcrumb-divider::before,
.breadcrumb-arrows .breadcrumb-divider::before {
  width: auto;
  height: auto;
  background: none;
  mask: none;
}

.breadcrumb-dash .breadcrumb-divider::before {
  content: "—";
}

.breadcrumb-arrow .breadcrumb-divider::before {
  content: "→";
}

[dir=rtl] .breadcrumb-arrow .breadcrumb-divider::before {
  content: "←";
}

.breadcrumb-arrows .breadcrumb-divider::before {
  content: "»";
}


/* =============================================================================
   9. CARDS
   ============================================================================= */

.card {
  margin-bottom: 0;
}

/* Bootstrap 6 makes header and body flex columns – Bootstrap 5 used plain blocks.
   A .row or a .d-flex utility on them still turns them into a flex row. */
.card-header:not(.row),
.card-body:not(.row) {
  display: block;
}

.card-header,
.card-body {
  flex-direction: row;
  align-items: normal;
  gap: 0;
}

/* Bootstrap 6 also zeroes the margins of everything directly inside a card body;
   restore the Bootstrap 5 spacing */
.card-body > :is(h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6) {
  margin-block: 0 calc(var(--bs-spacer) * 0.75);
}

.card-body > p {
  margin-block: 0 var(--bs-spacer-2);
}

.card-body > hr {
  margin-block: var(--bs-spacer);
}

.card-body > :is(ul, ol, dl, blockquote, pre, figure) {
  margin-block: 0 1rem;
}

.card-header,
.card-body {
  border-radius: calc(var(--bs-border-radius) - var(--bs-border-width)) calc(var(--bs-border-radius) - var(--bs-border-width)) 0 0;
}

/* Bootstrap 6 adds a divider between consecutive bodies – Bootstrap 5 did not */
:where(.card > :is(.card-img-top, .card-img-bottom, .card-body, .list-group) + :is(.card-body, .card-img-bottom, .list-group)) {
  border-block-start: 0;
}

/* Consecutive bodies read as one flow: one layout space between them, not two */
.card > .card-body + .card-body {
  padding-top: 0;
}

/* Breadcrumb bar under the page title */
.page-breadcrumb {
  padding: 0.75rem var(--loon-space);
  border-top: var(--bs-border-width) solid var(--bs-border-color-translucent);
}

.card-title {
  margin-bottom: var(--bs-card-title-spacer-y);
}

.card-header:empty,
.card-header:has(.card-title:empty),
.card-body:empty,
.card-footer:empty {
  display: none !important;
}

/* Header actions don't add height */
.card-header > div.sm\:ms-auto,
.card-header > div.sm\:me-auto {
  margin-top: -0.5rem;
  margin-bottom: -0.5rem;
}

/* Card and dialog titles: 18px semibold on a 24px line, in the header's colour (white on
   a coloured header). With 24px above and below, every title bar is 72px. */
.card-header .card-title {
  color: inherit;
  font-size: 1.125rem;
  font-weight: 600;
  line-height: 1.5rem;
  letter-spacing: -0.01em;
}

/* Page header: the page name (24px on a 32px line), same side space and bar rhythm.
   Its buttons don't add height. */
.page-header {
  padding-block: var(--loon-bar-padding-y);
}

.page-heading {
  font-size: 1.5rem;
  font-weight: 600;
  line-height: 2rem;
  letter-spacing: -0.015em;
}

.page-header .btn {
  margin-block: calc((2rem - var(--bs-btn-min-height)) / 2);
}

/* Action label on a plain header (New, Edit…): in the action colour */
.card-header:not([class*="theme-"]) .badge-action[class*="theme-"] {
  color: var(--bs-theme-fg);
}

/* Action label in front of a header title (New, Edit…) – an outline in the header's
   text colour: white text and a white border on a coloured header (set directly: a
   badge inside a themed header would otherwise take the header's own background) */
.card-header .badge-action {
  color: inherit;
  background-color: transparent;
  border: var(--bs-border-width) solid currentColor;
  --bs-badge-font-size: 0.75rem;
  --bs-badge-padding-x: 0.5rem;
  --bs-badge-padding-y: 0.25rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.card-header > .card-title {
  margin-bottom: 0;
}

/* Tabs in a card bar (the page header's tabs, card tabs) – the same tabs as a table's
   views: 14px medium text, grey until chosen, a 2px line under the chosen one, as wide as
   its text. The first tab's text starts at the card's content edge. Tabs are spaced with
   margins, not gap: the overflow script (shorterNav, app.js) measures them with margins. */
.card-nav-tabs {
  padding-top: 0;
  padding-bottom: 0;
  padding-inline: var(--loon-space);
  scrollbar-width: none;
}

.card-nav-tabs::-webkit-scrollbar {
  display: none;
}

.card-nav-tabs .nav-tabs-underline li.nav-item {
  width: max-content;
  height: auto;
  white-space: nowrap;
  display: flex;
}

.card-nav-tabs .nav-tabs-underline > .nav-item + .nav-item {
  margin-inline-start: 1.75rem;
}

.card-nav-tabs .nav-tabs-underline > .nav-item > :is(a, button) {
  display: flex;
  align-items: center;
  min-height: 3.5rem;
  margin: 0;
  padding: 0 0.125rem;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--bs-fg-2);
  font-size: var(--bs-btn-input-font-size);
  font-weight: 500;
  box-shadow: inset 0 -2px 0 transparent;
  transition: color var(--bs-transition-base-timer), box-shadow var(--bs-transition-base-timer);
}

.card-nav-tabs .nav-tabs-underline > .nav-item > :is(a, button):is(:hover, :focus, .show) {
  color: var(--bs-body-color);
  background: transparent;
}

.card-nav-tabs .nav-tabs-underline > .nav-item > :is(a, button).active {
  color: var(--bs-body-color);
  background: transparent;
  box-shadow: inset 0 -2px 0 var(--bs-primary);
}

/* "More" (the tabs that do not fit) – a chevron after it, like the views menu */
.card-nav-tabs .nav-more > button::after {
  content: "\f282"; /* icon-chevron-down */
  margin-inline-start: 0.375rem;
  font-family: var(--bs-icon-font-family);
  font-size: 0.75rem;
  line-height: 1;
}

/* A text button at the end of a card bar (Edit…) – its text, not its padding, lines up
   with the card's content edge */
.card-header > .btn-text:last-child {
  margin-inline-end: calc(var(--bs-btn-padding-x) * -1);
}

/* Vertical card group */
.card-group-vertical > .card {
  margin-bottom: 0;
}

.card-group-vertical > .card + .card {
  border-top: 0;
}

.card-group-vertical > .card:not(:last-child) {
  border-bottom-right-radius: 0;
  border-bottom-left-radius: 0;
}

.card-group-vertical > .card:not(:last-child) .card-img-top,
.card-group-vertical > .card:not(:last-child) .card-header {
  border-bottom-left-radius: 0;
}

.card-group-vertical > .card:not(:last-child) .card-img-bottom,
.card-group-vertical > .card:not(:last-child) .card-footer {
  border-bottom-right-radius: 0;
}

.card-group-vertical > .card:not(:first-child) {
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}

.card-group-vertical > .card:not(:first-child) .card-img-top,
.card-group-vertical > .card:not(:first-child) .card-header {
  border-top-left-radius: 0;
}

.card-group-vertical > .card:not(:first-child) .card-img-bottom,
.card-group-vertical > .card:not(:first-child) .card-footer {
  border-top-right-radius: 0;
}

.card-group-vertical .card-header {
  border-bottom: 0;
}

.card-group-vertical .card-body {
  border-top: var(--bs-border-width) solid var(--bs-border-color);
}

/* Card images */
.card-body .card-img {
  border-radius: var(--bs-border-radius);
}

.card-img-actions {
  position: relative;
}

.card-img-actions:hover .card-img-actions-overlay,
.card-img-actions:focus .card-img-actions-overlay {
  opacity: 1;
  visibility: visible;
}

.card-img-actions-overlay {
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  inset: 0;
  background-color: rgba(0, 0, 0, 0.75);
  opacity: 0;
  visibility: hidden;
  transition: all ease-in-out var(--bs-transition-base-timer);
}

@media (prefers-reduced-motion: reduce) {
  .card-img-actions-overlay {
    transition: none;
  }
}

/* Card actions */
[data-card-action] {
  cursor: pointer;
  line-height: 1;
}

[data-card-action=collapse] i {
  transition: transform ease-in-out var(--bs-transition-collapse-timer);
}

@media (prefers-reduced-motion: reduce) {
  [data-card-action=collapse] i {
    transition: none;
  }
}

.card-collapsed [data-card-action=collapse] i {
  transform: rotate(180deg);
}

/* Card header tabs */
.card-header-tabs {
  padding: 1rem;
}

.card-header-tabs .nav-link {
  border-top-width: 0;
}

/* Fullscreen card */
.card-fullscreen {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: auto;
  border-radius: 0;
  z-index: 1055;
}

/* Loading overlay on a card */
.card-overlay {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: color-mix(in srgb, var(--bs-component-bg) 75%, transparent);
  z-index: 1001;
  animation: cardOverlayEnter var(--bs-transition-base-timer) ease;
  border-radius: var(--bs-border-radius);
}

[data-bs-theme=dark] .card-overlay {
  background-color: rgba(0, 0, 0, 0.5);
}

.card-overlay-fadeout {
  animation: cardOverlayExit var(--bs-transition-base-timer) ease;
}

@keyframes cardOverlayEnter {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes cardOverlayExit {
  from { opacity: 1; }
  to { opacity: 0; }
}

/* Cards inside tab panes sit flush */
.tab-content > .tab-pane > .card,
.tab-content > .tab-pane > .card > .card-header {
  border: 0;
  box-shadow: none;
}


/* =============================================================================
   10. DIALOGS (was modals)
   Native <dialog class="dialog"> in Bootstrap 6
   ============================================================================= */

.dialog-body {
  padding-top: 2rem;
  padding-bottom: 2rem;
}

/* Fixed dialog – a card inside a dialog, card supplies the surface.
   800px keeps a 2-column form easy to read; phones get the full screen (below). */
.dialog-fixed {
  --bs-dialog-width: 800px;
  --bs-dialog-margin: 2.5vh;
  --bs-dialog-bg: transparent;
  --bs-dialog-border-width: 0;
  --bs-dialog-box-shadow: none;
  margin-top: var(--bs-dialog-margin); /* top-aligned, not centred */
}

.dialog-fixed .card {
  width: 100%;
  display: flex;
  flex-direction: column;
  min-height: 200px;
  max-height: calc(100vh - var(--bs-dialog-margin) * 2);
  overflow: hidden;
  border: none;
}

.dialog-fixed .card form {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
}

.dialog-fixed .card .card-body {
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
}

.dialog-fixed .card .card-header,
.dialog-fixed .card .card-footer {
  flex-shrink: 0;
}

/* Dialog card – the same spacing as every card: the layout space around the content,
   bars (header and footer) with 16px above and below.
   Coloured header (class theme-*): a 56px band in the action colour.
   Plain header: white, the title sits at the layout space from the top and flows
   straight into the body (no line).
   Footer: light grey with a hairline, buttons on the right. */
.dialog-fixed .card {
  --bs-card-cap-bg: var(--bs-bg-1);
  --bs-card-border-color: var(--bs-border-body);
  border-radius: var(--bs-border-radius-lg);
}

.dialog-fixed .card-header {
  padding: var(--loon-space) var(--loon-space) 0;
  background-color: var(--bs-component-bg);
  border-bottom: 0;
}

.dialog-fixed .card-header:not([class*="theme-"], .loading) + .card-body {
  padding-top: 1.75rem;
}

/* Cancel and other plain buttons stay white on the grey footer */
.card-footer .btn:not(.btn-solid, .btn-outline, .btn-subtle, .btn-text, .btn-link, .btn-icon) {
  --bs-btn-bg: var(--bs-component-bg);
}

.dialog-fixed .card-header[class*="theme-"] {
  padding-block: var(--loon-bar-padding-y);
  background-color: var(--bs-theme-bg);
}

/* While a coloured header loads: a grey band of the same size, so nothing moves */
.dialog-fixed .card-header.loading {
  padding-block: var(--loon-bar-padding-y);
  background-color: var(--bs-bg-2);
}

/* Close button: a 36px square centred on the 24px title line. It takes no extra height
   and its X lines up with the right edge of the content. */
.dialog-fixed .card-header .btn-icon.btn-sm {
  margin: -0.375rem -0.625rem -0.375rem auto;
}

/* Phones: a 44px close button, easy to hit with a thumb */
@media (width < 576px) {
  .dialog-fixed .card-header .btn-icon.btn-sm {
    --bs-btn-min-height: var(--bs-btn-input-min-height);
    margin: -0.625rem -0.75rem -0.625rem auto;
  }

  .dialog-fixed .card-header .btn-icon.btn-sm > i {
    font-size: 1.25rem;
  }
}

@media (max-height: 600px) {
  .dialog-fixed {
    --bs-dialog-margin: 1vh;
  }
}

@media (min-height: 768px) {
  .dialog-fixed {
    --bs-dialog-margin: 3vh;
  }
}

/* Full screen on phones */
@media (width < 576px) {
  .dialog-fixed {
    --bs-dialog-margin: 0;
    width: 100%;
    max-width: none;
    height: 100%;
    max-height: none;
  }

  .dialog-fixed .card {
    max-height: none;
    height: 100%;
  }

  .dialog-fixed .card,
  .dialog-fixed .card-header,
  .dialog-fixed .card-footer {
    border-radius: 0;
  }
}

/* Extra sizes */
@media (width >= 576px) {
  .dialog-xs {
    --bs-dialog-width: 300px;
  }

  .dialog-full {
    --bs-dialog-width: 94%;
  }
}

.dialog [data-modal]:hover {
  text-decoration: underline;
  cursor: pointer;
}

/* Close button */
@media (prefers-reduced-motion: no-preference) {
  .btn-close {
    transition: all var(--bs-transition-base-timer) ease-in-out;
  }
}


/* =============================================================================
   11. TOOLTIPS AND TOASTS
   ============================================================================= */

.tooltip-custom[data-bs-placement^=top] .tooltip-arrow::before {
  border-top-color: var(--bs-primary);
}

.toast-header .btn-close,
.toast-body .btn-close {
  margin-right: calc(var(--bs-spacer-3) * -1);
}

.toast-icon .toast-body > span {
  padding-right: var(--bs-toast-padding-x);
}


/* =============================================================================
   12. LIST GROUPS
   ============================================================================= */

.list-group-sm {
  padding: 0.75rem var(--bs-spacer-2);
}

.list-group[class*="col-"] {
  padding-left: calc(var(--bs-gutter-x) * 0.5);
  padding-right: calc(var(--bs-gutter-x) * 0.5);
}

/* Collapse toggles inside list groups and accordion items */
.list-group-item > .btn[data-bs-toggle="collapse"].active:not(.collapsed),
.accordion-item > .btn[data-bs-toggle="collapse"].active:not(.collapsed),
.list-group-item > .btn[data-bs-toggle="collapse"]:not(.collapsed),
.accordion-item > .btn[data-bs-toggle="collapse"]:not(.collapsed),
.list-group-item > .btn[data-bs-toggle="collapse"]:active,
.accordion-item > .btn[data-bs-toggle="collapse"]:active {
  background-color: var(--bs-hover-bg);
  color: var(--bs-body-color);
  border-color: var(--bs-border-color);
  border-top-color: transparent;
}

.list-group-item > .btn[data-bs-toggle="collapse"].active.collapsed:hover,
.accordion-item > .btn[data-bs-toggle="collapse"].active.collapsed:hover {
  background-color: var(--bs-hover-bg);
  color: var(--bs-body-color);
}

.list-group-item > .btn[data-bs-toggle="collapse"].active.collapsed,
.accordion-item > .btn[data-bs-toggle="collapse"].active.collapsed {
  background-color: transparent;
  color: var(--bs-body-color);
  border-color: transparent;
}

aside .list-group-item .btn {
  border-radius: 0;
  border-color: transparent;
}

/* Chevron rotation */
.accordion-item .btn .icon-chevron-down {
  transition: transform 0.3s ease;
}

.accordion-item .btn[aria-expanded="true"] .icon-chevron-down,
.accordion-item .btn:not(.collapsed) .icon-chevron-down {
  transform: rotate(180deg);
}

.accordion-item .btn[aria-expanded="false"] .icon-chevron-down,
.accordion-item .btn.collapsed .icon-chevron-down {
  transform: rotate(0deg);
}


/* =============================================================================
   13. DRAWERS (was offcanvas)
   Native <dialog class="drawer"> in Bootstrap 6. Tokens are in section 15.
   ============================================================================= */

.drawer-header {
  z-index: 9;
  min-height: var(--bs-navbar-link-height);
  padding: var(--bs-spacing);
  background: var(--bs-component-bg);
  border-bottom: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color);
}

.drawer-body {
  background: var(--bs-component-bg);
  padding: 0;
}


/* =============================================================================
   14. INTERACTIVE HELPERS
   ============================================================================= */

/* Icon that appears on hover */
.hover-icon > i {
  opacity: 0;
}

.hover-icon:hover > i {
  opacity: 0.5;
}

.hover-icon > i:hover {
  opacity: 1;
}

/* Auth pages (sign-in, verify, join) – a centred, normal app card */
.auth {
  width: 100%;
  max-width: 28rem;
  margin-inline: auto;
}

/* Auth and legal cards use the layout space inside, like dialogs */
:is(.auth, .legal) .card-body {
  padding: var(--loon-space);
}

.auth .logo-stacked {
  width: 120px;
}

/* Phones: no card – the page itself becomes the white surface */
@media (width < 576px) {
  body:has(.auth) {
    background-color: var(--bs-component-bg);
  }

  .auth .card {
    --bs-card-bg: transparent;
    border: 0;
    box-shadow: none;
  }
}

.auth-provider-logo {
  width: 1.125rem;
}

.auth-provider-logo > svg {
  display: block;
  width: 100%;
  height: auto;
}

.auth-social {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

/* A thin line on each side of a small "or" */
.auth-or {
  display: flex;
  align-items: center;
  gap: 1rem;
  font-size: var(--bs-body-font-size-sm);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bs-fg-4);
}

.auth-or::before,
.auth-or::after {
  content: "";
  flex: 1;
  height: var(--bs-border-width);
  background-color: var(--bs-border-color);
}

/* Email: the summary is the "Sign in with Email" button; when open it becomes a "back" link under the form */
.auth-email {
  display: flex;
  flex-direction: column;
}

.auth-email > summary {
  display: block; /* block (not list-item) drops the triangle */
}

.auth-email[open] > summary {
  order: 1;
  margin-top: 1.5rem;
  text-align: center;
}

.auth-email[open] > summary:hover .auth-email-close {
  color: var(--bs-body-color);
  text-decoration: underline;
}

.auth-email:not([open]) .auth-email-close,
.auth-email[open] .auth-email-open {
  display: none;
}

.auth:has(.auth-email[open]) :is(.auth-social, .auth-or) {
  display: none;
}

/* Legal pages (terms, privacy) – the same card as sign-in, wider for reading */
.legal {
  width: 100%;
  max-width: 48rem;
  margin-inline: auto;
}

.legal .logo-stacked {
  width: 120px;
}

/* Calmer headings than the prose defaults – the page title stays the biggest */
.legal .prose h2 {
  font-size: 1.25em;
  font-weight: 600;
}

.legal .prose h3 {
  font-size: 1em;
  font-weight: 600;
}

/* Phones: no card – the same as sign-in */
@media (width < 576px) {
  body:has(.legal) {
    background-color: var(--bs-component-bg);
  }

  .legal .card {
    --bs-card-bg: transparent;
    border: 0;
    box-shadow: none;
  }
}

/* Show/hide by active state */
.d-active {
  display: none;
}

.active > .d-active-none {
  display: none;
}

.active > .d-active {
  display: block;
}


/* =============================================================================
   15. PROFILE PAGES
   One template for every record (users, employees, CRM accounts, vehicles…), built by
   Profile::render(). The sections come first in the HTML; from 1024px the summary
   panel sits on their left (row-reverse). On phones the panel is hidden (d-none
   lg:d-block), so a phone shows the page header and the sections only.
   ============================================================================= */

.profile {
  display: flex;
  flex-direction: row-reverse;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--bs-spacer-4);
}

.profile-main {
  flex: 999 1 560px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--bs-spacer-4);
}

.profile-summary {
  flex: 1 1 300px;
  min-width: 0;
}

/* Label/value rows – label on the left, value beside it. When the card is too narrow
   for both (phones), the value drops under its label by itself. */
.profile-rows {
  margin: 0;
  padding-block: 0.25rem;
}

.profile-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.125rem var(--bs-spacer-3);
  padding: 0.875rem var(--loon-space);
}

.profile-row + .profile-row {
  border-top: var(--bs-border-width) solid var(--bs-border-muted);
}

.profile-row > dt {
  flex: 0 0 12.5rem;
  font-weight: 400;
  color: var(--bs-fg-3);
}

.profile-row > dd {
  flex: 1 1 15rem;
  min-width: 0;
  margin: 0;
  overflow-wrap: anywhere;
}

/* Colour values: a small swatch before the code */
.profile-swatch {
  display: inline-block;
  width: 0.875rem;
  height: 0.875rem;
  margin-inline-end: 0.5rem;
  border: var(--bs-border-width) solid var(--bs-border-color-translucent);
  border-radius: var(--bs-radius-3);
  vertical-align: -0.125rem;
}

/* Summary panel – photo, subtitle and badges centred at the top, key details below */
.profile-summary-head {
  padding: var(--loon-space);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.875rem;
  text-align: center;
}

.profile-photo {
  position: relative;
  width: 6rem;
  height: 6rem;
}

.profile-photo > img,
.profile-photo > span {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
  font-weight: 600;
  color: var(--bs-warning-fg-emphasis);
  background-color: var(--bs-warning-bg-subtle);
}

/* Records that aren't people (e.g. vehicles) show their page icon instead of initials */
.profile-photo > .profile-photo-icon {
  font-size: 2.5rem;
  color: var(--bs-fg-2);
  background-color: var(--bs-bg-2);
}

/* Change photo – a small round button on the photo's corner */
.profile-photo-edit {
  position: absolute;
  right: -0.25rem;
  bottom: -0.25rem;
  border-radius: 50%;
  background-color: var(--bs-component-bg);
  box-shadow: var(--bs-box-shadow);
}

.profile-summary-subtitle {
  margin: 0.25rem 0 0;
  font-size: 1rem;
  font-weight: 600;
}

.profile-summary-badges {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
}

.profile-facts {
  margin: 0;
  padding: var(--loon-space);
  border-top: var(--bs-border-width) solid var(--bs-border-color-translucent);
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.profile-fact {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  min-width: 0;
}

.profile-fact > div {
  min-width: 0;
}

.profile-fact-icon {
  flex: none;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--bs-border-radius);
  background-color: var(--bs-bg-2);
  color: var(--bs-fg-2);
  display: flex;
  align-items: center;
  justify-content: center;
}

.profile-fact dt {
  font-size: 0.8125rem;
  font-weight: 400;
  color: var(--bs-fg-3);
}

.profile-fact dd {
  margin: 0;
  overflow-wrap: anywhere;
}

/* Lists of related things (workspaces, sessions…) – Profile::listItems(): a tile, the
   title and a grey line under it, then a chevron (links) or a button */
.profile-list {
  display: flex;
  flex-direction: column;
  padding-block: 0.25rem;
}

.profile-list-item {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  padding: 0.75rem var(--loon-space);
  color: inherit;
  text-decoration: none;
}

.profile-list-item + .profile-list-item {
  border-top: var(--bs-border-width) solid var(--bs-border-muted);
}

a.profile-list-item:hover {
  background-color: var(--bs-hover-bg);
}

.profile-list-tile {
  flex: none;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--bs-border-radius);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.8125rem;
  font-weight: 600;
}

.profile-list-text {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.profile-list-title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
  font-weight: 500;
}

.profile-list-sub {
  font-size: 0.8125rem;
  color: var(--bs-fg-3);
}

.profile-list-chevron {
  flex: none;
  color: var(--bs-fg-3);
}

/* A grey note in a profile card – on its own, or under rows or a list */
.profile-note {
  margin: 0;
  padding: 0.875rem var(--loon-space);
  font-size: 0.8125rem;
  color: var(--bs-fg-3);
}

:is(.profile-rows, .profile-list) + .profile-note {
  border-top: var(--bs-border-width) solid var(--bs-border-muted);
}

}


/* =============================================================================
   16. DRAWER TOKENS
   Bootstrap 6 declares the drawer tokens outside its layers, so they have to be
   overridden outside a layer too. Flush to the screen edge, as in Bootstrap 5.
   ============================================================================= */

.drawer {
  --bs-drawer-inset: 0;
  --bs-drawer-width: 100%;
  --bs-drawer-padding-x: 0;
  --bs-drawer-padding-y: 0;
  --bs-drawer-bg: var(--bs-component-bg);
  --bs-drawer-border-radius: 0;
  --bs-drawer-border-width: 0;
  --bs-drawer-box-shadow: none;
  --bs-drawer-backdrop-bg: rgba(0, 0, 0, 0.5);
  --bs-drawer-backdrop-blur: 0;
}

@media (width >= 768px) {
  .drawer {
    --bs-drawer-width: 400px;
  }
}