/* ============================================================================
 * stack-compat.css — replaces public/css/theme.css (the Stack commercial
 * Bootstrap theme, 195 KB) and bridges Bootstrap 4 markup onto Bootstrap 5.
 *
 * Two jobs:
 *
 *   PART A  Bootstrap 4 -> 5 shims. Bootstrap 5 dropped .form-group (1,879
 *           uses here), .jumbotron (274), .input-group-prepend/append (212)
 *           and a few others. Reimplementing them is a few dozen lines;
 *           rewriting the markup would be thousands of edits for no benefit.
 *
 *   PART B  The Stack vocabulary still present in the views. A scan of every
 *           class used in views/ against Bootstrap 5 and our own stylesheets
 *           found exactly 90 classes that would lose all styling if theme.css
 *           were deleted. All of them are reimplemented below, on the tokens
 *           in tokens.css rather than the theme's hardcoded hexes — which is
 *           what makes them theme correctly per tenant for the first time.
 *
 * Stack sized everything in em against a 14px root. Those values are mapped
 * onto the 4pt spacing scale here rather than carried over literally, so
 * spacing is consistent with the rest of the system.
 *
 * NOTE: public/js/stack-theme-scripts.js is still loaded and still owns the
 * behaviour for .tabs-container and .modal-container. The CSS those scripts
 * depend on is preserved below. Porting those ~130 markup sites to native
 * Bootstrap 5 tabs and modals is the remaining step to retire Stack entirely.
 * ==========================================================================*/

/* ============================================================================
 * PART 0 — Base element layer
 *
 * theme.css carried a set of element-level resets that nothing else replaces:
 * Bootstrap 5's Reboot is deliberately lighter than Bootstrap 4's and, for
 * example, does not constrain image width at all. Dropping these silently
 * un-styles every page rather than any particular component, which is exactly
 * why the class-by-class audit missed them.
 *
 * Values are mapped onto the spacing scale. Stack sized these in em against a
 * 14px root (1.857em = 26px); --space-6 is 24px, the nearest step.
 * ==========================================================================*/

/* Without this, any <img> lacking .img-fluid renders at intrinsic size — a
   3000px logo overflows the page and destroys the layout. */
img {
  max-width: 100%;
  margin-bottom: var(--space-6);
}

/* The app's markup assumes unstyled lists throughout; restoring Bootstrap's
   default bullets here would add markers to every nav, menu and card list. */
ul,
ol {
  list-style: none;
  line-height: var(--leading-normal);
}

table {
  width: 100%;
  margin-bottom: var(--space-6);
}

/* Cell padding, header fill and row rules for tables that do not carry
 * Bootstrap's .table class — which is most of them here, including every
 * DataTable (`class="table--alternate-row datatable"`).
 *
 * This is not only cosmetic. DataTables positions its sort arrows with
 * `position: absolute; bottom: 0.9em` inside the th, so it depends on the cell
 * having vertical padding to sit in. With the padding gone the header collapsed
 * to text height and the arrows — drawn at opacity 0.3 — landed on top of the
 * label and read as invisible.
 *
 * Bootstrap's own `.table > :not(caption) > * > *` is more specific, so tables
 * that do use .table keep Bootstrap's spacing and are unaffected.
 */
table th,
table td {
  padding: var(--space-4);
}
table th {
  background: var(--surface-sunken);
  color: var(--ink);
  font-weight: var(--weight-semibold);
}
table tr:not(:last-of-type) {
  border-bottom: 1px solid var(--border);
}

form {
  max-width: 100%;
  position: relative;
}

label {
  margin: var(--space-1) 0 0;
  font-size: var(--text-sm);
}

textarea {
  display: block;
  width: 100%;
  max-width: 100%;
}

iframe {
  width: 100%;
}

pre {
  padding: var(--space-3);
  line-height: var(--leading-normal);
  max-height: 500px;
}

blockquote {
  margin-bottom: var(--space-6);
  padding: 0;
  font-size: var(--text-xl);
  line-height: var(--leading-snug);
}

/* ============================================================================
 * PART A — Bootstrap 4 -> 5 compatibility
 * ==========================================================================*/

/* .form-group was Bootstrap 4's field wrapper; BS5 expects utility margins. */
.form-group {
  margin-bottom: var(--space-4);
}
.form-group:last-child {
  margin-bottom: 0;
}

/* .jumbotron was removed in BS5. */
.jumbotron {
  padding: var(--space-9) var(--space-6);
  margin-bottom: var(--space-7);
  background-color: var(--surface-sunken);
  border-radius: var(--radius-lg);
}
.jumbotron-fluid {
  padding-right: 0;
  padding-left: 0;
  border-radius: 0;
}

/* BS5 folds prepend/append into flex children of .input-group. These wrappers
 * still exist in the markup, so make them transparent to the flex layout. */
.input-group-prepend,
.input-group-append {
  display: flex;
  align-items: stretch;
}
.input-group-prepend .input-group-text,
.input-group-append .input-group-text,
.input-group-prepend .btn,
.input-group-append .btn {
  border-radius: 0;
}
.input-group > .input-group-prepend:first-child > :first-child {
  border-top-left-radius: var(--radius-md);
  border-bottom-left-radius: var(--radius-md);
}
.input-group > .input-group-append:last-child > :last-child {
  border-top-right-radius: var(--radius-md);
  border-bottom-right-radius: var(--radius-md);
}

/* .btn-block was replaced by .d-grid wrappers. */
.btn-block {
  display: block;
  width: 100%;
}
.btn-block + .btn-block {
  margin-top: var(--space-2);
}

/* The custom-file component was removed outright. */
.custom-file {
  position: relative;
  display: block;
  width: 100%;
}

/* Bootstrap 3 panels — four remaining sites, styled as cards. */
.panel {
  position: relative;
  background-color: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-6);
}
.panel-heading {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  background-color: var(--surface-sunken);
  border-radius: var(--radius-md) var(--radius-md) 0 0;
}
.panel-title {
  margin: 0;
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
}
.panel-body {
  padding: var(--space-4);
}

/* A bare .badge had no background in BS4 and is used that way here; BS5's
 * badge assumes a text-bg-* companion. Give the bare case a sane default. */
.badge:not([class*='text-bg-']):not([class*='bg-']) {
  background-color: var(--brand-primary);
  color: var(--brand-primary-contrast);
}

/* ============================================================================
 * PART B — Stack vocabulary, rebuilt on tokens
 * ==========================================================================*/

/* ---- Boxes ------------------------------------------------------------- */
.boxed {
  position: relative;
  overflow: hidden;
  padding: var(--space-6);
  margin-bottom: var(--space-6);
  background-color: var(--surface-raised);
  border-radius: var(--radius-md);
}
.boxed.boxed--sm {
  padding: var(--space-4);
}
.boxed.boxed--lg {
  padding: var(--space-8);
}
.boxed.boxed--border {
  border: 1px solid var(--border);
}
.unpad {
  padding: 0;
}
.allow-overflow {
  overflow: visible;
}

/* ---- Elevation ---------------------------------------------------------- */
.box-shadow {
  box-shadow: var(--shadow-md);
}
.box-shadow-shallow {
  box-shadow: var(--shadow-sm);
}
.box-shadow-wide {
  box-shadow: var(--shadow-lg);
}

/* ---- Radius ------------------------------------------------------------- */
.border--round,
.border--round:before,
.border--round .background-image-holder {
  border-radius: var(--radius-md);
}

/* ---- Sections and vertical rhythm --------------------------------------- */
section.space--xxs,
footer.space--xxs {
  padding-top: var(--space-6);
  padding-bottom: var(--space-6);
}
section.space--sm,
footer.space--sm {
  padding-top: var(--space-10);
  padding-bottom: var(--space-10);
}
.height-100 {
  min-height: 100vh;
}
.heading-block {
  margin-bottom: var(--space-9);
}
.mt--1 {
  margin-top: var(--space-6);
}
.mt--2 {
  margin-top: var(--space-9);
}
footer.footer-2 .row:last-child {
  margin-top: var(--space-9);
}

/* ---- Positioning -------------------------------------------------------- */
.pos-top { top: 0; }
.pos-left { left: 0; }
.pos-right { right: 0; }
.pos-vertical-center {
  position: relative;
  top: 50%;
  transform: translateY(-50%);
}
@media (max-width: 767.98px) {
  .pos-vertical-center {
    top: 0;
    transform: none;
  }
}

/* ---- Display helpers ---------------------------------------------------- */
.block { display: block; }
a.block {
  font-weight: var(--weight-normal);
  text-decoration: none;
  color: var(--ink-muted);
}
.btn.block {
  margin-left: 0;
}
.btn.block + .btn.block {
  margin-top: var(--space-3);
}
.text-justify { text-align: justify; }

/* Stack's breakpoint visibility classes, mapped to Bootstrap 5 breakpoints. */
.hidden-sm { display: none !important; }
.visible-sm { display: none !important; }
@media (min-width: 576px) and (max-width: 767.98px) {
  .visible-sm { display: block !important; }
  tr.visible-sm { display: table-row !important; }
  th.visible-sm,
  td.visible-sm { display: table-cell !important; }
}
@media (max-width: 575.98px) {
  .text-left-xs { text-align: left; }
}
@media (max-width: 767.98px) {
  .text-left-sm { text-align: left; }
}

/* ---- Backgrounds and colour helpers ------------------------------------- */
.bg--white {
  background: var(--surface-raised);
}
.bg--white h1, .bg--white h2, .bg--white h3,
.bg--white h4, .bg--white h5, .bg--white h6 {
  color: var(--ink);
}
.bg--white p, .bg--white span, .bg--white ul,
.bg--white a:not(.btn) {
  color: var(--ink-muted);
}
.bg--facebook { background: #3b5998; color: #fff; }
.bg--twitter { background: #1da1f2; color: #fff; }
.bg--success { background: var(--success); color: var(--success-fg); }
.color--primary { color: var(--brand-primary) !important; }
.color--success { color: var(--success); }

/* ---- Images ------------------------------------------------------------- */
.image--sm {
  max-height: var(--space-11);
}
img.image--sm:not(:last-child) {
  margin-bottom: var(--space-3);
}
.background-image-holder {
  position: absolute;
  inset: 0;
  height: 100%;
  background-size: cover !important;
  background-position: 50% 50% !important;
  background-color: var(--surface-sunken);
  z-index: 0;
  opacity: 0;
  transition: opacity var(--dur-slow) linear;
}
.background-image-holder:not([class*='col-']) {
  width: 100%;
}
.background-image-holder.fadeIn {
  opacity: 1;
}
.background-image-holder img {
  display: none;
}
.imagebg {
  position: relative;
}
.imagebg .container {
  position: relative;
  z-index: 2;
}
.imagebg:not(.image--light) h1, .imagebg:not(.image--light) h2,
.imagebg:not(.image--light) h3, .imagebg:not(.image--light) h4,
.imagebg:not(.image--light) p, .imagebg:not(.image--light) .icon {
  color: var(--ink-inverse);
}
.imageblock {
  position: relative;
  padding: 0;
}
.imageblock > .container,
.imageblock > div[class*='col-']:not(.imageblock__content) {
  padding-top: var(--space-12);
  padding-bottom: var(--space-12);
  overflow: hidden;
}
.imageblock .imageblock__content {
  position: absolute;
  height: 100%;
  top: 0;
  z-index: 2;
  padding: 0;
}
.imageblock.allow-overflow .imageblock__content {
  overflow: visible;
}
@media (max-width: 767.98px) {
  .imageblock .imageblock__content {
    position: relative;
    height: 18rem;
  }
}

/* ---- Icons -------------------------------------------------------------- */
.icon {
  line-height: 1em;
  font-size: 2.75rem;
}
.icon:not(.block) {
  display: inline-block;
}
.icon--xs { font-size: var(--text-base); }
.icon--sm { font-size: 1.65rem; }
.icon--lg { font-size: 3.9rem; }

/* ---- Buttons ------------------------------------------------------------
 * Stack's own button variants, remapped onto the tenant tokens. These used to
 * be hardcoded #4a90e2 / #31639c regardless of tenant.
 */
/* theme.css set this, and .btn--icon below depends on it to anchor its
   absolutely-positioned icon. Bootstrap 5 does not position .btn at all, so
   without it the icon escapes to the nearest positioned ancestor. */
.btn {
  position: relative;
}

/* Outline and hover affordance for buttons with no colour variant — the
 * `.btn .btn-xs` "Details" links in table Actions columns are the main case.
 * Bootstrap gives a bare .btn a transparent border and no background, so
 * without this it reads as plain text rather than a control.
 *
 * The :not([class*='primary']) guard is theme.css's own; .btn-accent is added
 * because it carries a token-derived edge that should win. Filled variants keep
 * the border colour their --bs-btn-* set declares.
 */
.btn:not([class*='primary']):not(.btn-accent) {
  border-color: var(--border-strong);
}
.btn:not([class*='primary']):not(.btn-accent):hover {
  border-color: var(--ink);
}

/* The lift on hover. custom.css already transitions transform on .btn and has a
   matching .btn:active { translateY(1px) } press, both of which were left
   without the hover half when theme.css went. */
.btn:hover {
  transform: translate3d(0, -2px, 0);
}
@media (prefers-reduced-motion: reduce) {
  .btn:hover {
    transform: none;
  }
}

.btn__text {
  display: inline-block;
  line-height: 1;
}
.btn--icon {
  position: relative;
  padding-left: var(--space-9);
}
.btn--icon i,
.btn--icon .fa,
.btn--icon .fas,
.btn--icon .far {
  position: absolute;
  left: var(--space-4);
  top: 50%;
  transform: translateY(-50%);
}
.btn--primary,
.btn--primary:visited {
  background: var(--brand-primary);
  border-color: var(--brand-primary);
  color: var(--brand-primary-contrast);
}
.btn--primary .btn__text,
.btn--primary .btn__text i {
  color: var(--brand-primary-contrast);
}
.btn--primary:hover { background: var(--brand-primary-hover); border-color: var(--brand-primary-hover); }
.btn--primary:active { background: var(--brand-primary-active); }
.btn--primary-1,
.btn--primary-1:visited {
  background: var(--brand-primary);
  border-color: var(--brand-primary);
}
.btn--primary-1 .btn__text { color: var(--brand-primary-contrast); }
.btn--primary-1:hover { background: var(--brand-primary-hover); }
.btn--secondary {
  background: var(--brand-secondary);
  border-color: var(--border-strong);
  color: var(--brand-secondary-contrast);
}
.btn--secondary:hover { background: var(--brand-secondary-hover); }
.btn--secondary:active { background: var(--brand-secondary-active); }
.btn.btn-xs {
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  padding: var(--space-1) var(--space-3);
}
.btn.btn--sm + .btn--sm {
  margin-left: var(--space-3);
}
.btn--lg .btn__text {
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
}
.btn.btn--lg.type--uppercase .btn__text {
  letter-spacing: 1px;
}
button[type='submit'].btn--loading {
  position: relative;
  overflow: hidden;
  pointer-events: none;
  color: transparent;
}
button[type='submit'].btn--loading * {
  opacity: 0;
}
button[type='submit'].btn--loading:after {
  content: '';
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  height: 100%;
  background: var(--brand-primary-hover);
  animation: stack-load 1.5s ease-out infinite;
}
@keyframes stack-load {
  0% { width: 0; opacity: 1; }
  90% { width: 100%; opacity: 1; }
  100% { width: 100%; opacity: 0; }
}

/* ---- Tabs ---------------------------------------------------------------
 * Driven by public/js/stack-theme-scripts.js, which clones .tab__content into
 * .tabs-content and toggles .active on the list items. Keep these selectors
 * exactly as the script expects.
 */
.tabs-container {
  position: relative;
}
.tabs-container.tabs--vertical {
  overflow: hidden;
}
.tabs-container.tabs--vertical .tabs {
  width: 25%;
  float: left;
}
.tabs-container.tabs--vertical .tabs li {
  display: block;
}
.tabs-content {
  margin-top: var(--space-4);
}
.tabs .tab__content {
  display: none;
}
.tabs-content li > .tab__content {
  width: 100%;
  display: none;
}
.tabs-content > .active > .tab__content {
  display: block;
}
.tabs-content > li:not(.active) .tab__content {
  display: none !important;
}
.tabs-container[data-content-align='left'] .tabs-content {
  text-align: left;
}

/* ---- Stack's own modal --------------------------------------------------
 * Separate from Bootstrap's modal and triggered by .modal-trigger. The inner
 * .modal-content selector collides with Bootstrap's, so every rule here stays
 * scoped under .modal-container.
 */
.modal-container {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: 0;
  z-index: 1055;
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-slow) linear, visibility var(--dur-slow) linear;
}
.modal-container.modal-active {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}
.modal-container:before {
  content: '';
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  background: rgba(16, 24, 40, 0.72);
  z-index: 1;
}
.modal-container .modal-content {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate3d(-50%, -50%, 0);
  backface-visibility: hidden;
  max-height: 100%;
  overflow-y: auto;
  z-index: 2;
  padding: 0;
  border: none;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  background: var(--surface-overlay);
}
.modal-container .modal-content:not(.height--natural) {
  width: 50%;
  height: 50%;
}
/* Collapsed as well as faded, so a closed modal never intercepts clicks or
   contributes scroll height while its container is still in the document. */
.modal-container:not(.modal-active) .modal-content {
  display: none;
}
@media (max-width: 767.98px) {
  .modal-container .modal-content:not(.height--natural) {
    width: 92%;
    height: auto;
  }
}
.modal-container .modal-content .modal-close-cross {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  z-index: 99;
  cursor: pointer;
  opacity: 0.5;
  transition: opacity var(--dur-fast) linear;
}
.modal-container .modal-content .modal-close-cross:before {
  content: '\00D7';
  font-size: 1.5em;
}
.modal-container .modal-content .modal-close-cross:hover {
  opacity: 1;
}
.modal-content.section-modal {
  pointer-events: none;
}
.modal-content.section-modal [class*='col-'] {
  pointer-events: auto;
}
.modal-instance .modal-body {
  display: none;
}
.modal-trigger {
  cursor: pointer;
}

/* ---- Switchable ---------------------------------------------------------
 * Stack reversed column order with floats, which fights Bootstrap 5's flex
 * grid. Rebuilt with flex `order`, so it composes with the grid instead.
 */
.switchable {
  position: relative;
}
@media (min-width: 768px) {
  .switchable.switchable--switch .row > div[class*='col-']:first-child {
    order: 2;
  }
  .switchable.switchable--switch .row > div[class*='col-']:last-child {
    order: 1;
  }
}
.switchable .switchable__text {
  margin-top: var(--space-6);
}
@media (min-width: 768px) {
  .switchable .switchable__text {
    margin-top: 0;
  }
}

/* ---- Features ----------------------------------------------------------- */
.feature:not(.boxed) {
  margin-bottom: var(--space-9);
}
.feature h5 {
  margin: 0;
}
.feature-large .feature:not(.boxed) {
  margin-bottom: var(--space-6);
}
.feature-large h4:first-child {
  margin-bottom: var(--space-2);
}
.feature-7 {
  height: 13rem;
  margin-bottom: var(--space-6);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.feature-7 h3 {
  margin: 0;
}
.feature-8 {
  padding: var(--space-8) 0 var(--space-9);
}
.feature-8:not(.boxed) {
  margin-bottom: 0;
}
.feature-8 .feature__body {
  max-width: 85%;
  margin: 0 auto;
}

/* ---- Cover / slides ----------------------------------------------------- */
.cover {
  position: relative;
}
.cover .btn + .modal-instance {
  margin-top: var(--space-6);
}
.slide .boxed:last-child {
  margin-bottom: 0;
}
.slide:not([class*='col-']) > img:only-child {
  width: 100%;
}

/* ---- Text blocks -------------------------------------------------------- */
.text-block {
  margin-bottom: var(--space-6);
}
.text-block h2, .text-block .h2 { margin-bottom: var(--space-3); }
.text-block h3, .text-block .h3 { margin-bottom: var(--space-3); }
.text-block h4:not(:last-child), .text-block .h4:not(:last-child) { margin-bottom: var(--space-2); }
.text-block h5, .text-block .h5 { margin: 0; }
.text-block .icon + h4 { margin-top: var(--space-3); }
h1.h1--large, .h1.h1--large {
  font-weight: 200;
  font-size: var(--text-4xl);
  line-height: var(--leading-tight);
}
hr.short {
  width: var(--space-8);
  border-color: var(--brand-accent);
  opacity: 1;
}

/* ---- Bars and horizontal menus ------------------------------------------ */
.bar.bar--sm {
  padding: var(--space-3) 0;
}
.bar__module:not(:only-child) {
  display: inline-block;
}
.bar__module:not(:last-child) {
  margin-right: var(--space-3);
}
.bar__module .btn {
  display: block;
}
.menu-horizontal {
  list-style: none;
  margin: 0;
  padding: 0;
}
.bar-1 .menu-horizontal > li,
.bar-2 .menu-horizontal > li {
  display: inline-block;
}
.bar-1 .menu-horizontal > li:not(:first-child),
.bar-2 .menu-horizontal > li:not(:first-child) {
  margin-left: var(--space-3);
}
.menu-horizontal > li > a,
.menu-horizontal > li > span,
.menu-horizontal > li > .modal-instance > .modal-trigger {
  color: var(--ink);
  transition: opacity var(--dur-base) var(--ease);
}
.menu-horizontal > li:not(:hover) > a,
.menu-horizontal > li:not(:hover) > span,
.menu-horizontal > li:not(:hover) > .modal-instance > .modal-trigger {
  opacity: 0.6;
}
.hamburger-toggle i {
  color: var(--ink);
}
.bar:not(.bg--dark):not(.bar--transparent) .logo-light { display: none; }
.bar.bg--dark .logo-dark,
.bar--transparent:not(.bar--dark) .logo-dark { display: none; }

/* ---- Lists and tables --------------------------------------------------- */
.list--hover li {
  transition: opacity var(--dur-base) var(--ease);
}
.list--hover li:not(:hover) {
  opacity: 0.6;
}
.list-inline--images img {
  max-height: var(--space-8);
}
.list-inline--images li:not(:last-child) {
  margin-right: var(--space-11);
  margin-bottom: var(--space-6);
}
.table--alternate-row tbody tr:nth-child(even) {
  background: var(--surface-sunken);
}

/* ---- Custom radio / select ---------------------------------------------- */
.input-radio,
.input-select,
.input-checkbox {
  display: inline-block;
  user-select: none;
}
.input-radio input,
.input-select input,
.input-checkbox input {
  position: absolute !important;
  opacity: 0 !important;
  height: 0 !important;
  width: 0 !important;
}
.input-radio label,
.input-select label,
.input-checkbox label {
  display: block !important;
  cursor: pointer;
}
.input-radio {
  padding: 0;
}
.input-radio label {
  width: var(--space-6);
  height: var(--space-6);
  border-radius: var(--radius-circle);
  border: 2px solid var(--border-strong);
  background: var(--surface-raised);
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.input-radio input:checked + label,
.input-radio label.checked {
  background: var(--brand-primary);
  border-color: var(--brand-primary);
}
.input-radio input:focus-visible + label {
  box-shadow: var(--shadow-focus);
}
.input-select {
  position: relative;
}
.input-select i {
  position: absolute;
  top: 50%;
  right: var(--space-4);
  transform: translateY(-50%);
  font-size: 0.87em;
  pointer-events: none;
}

/* ---- Progress ----------------------------------------------------------- */
.progress-horizontal:after {
  content: '';
  display: table;
  clear: both;
}
.progress-horizontal:not(:last-child) {
  margin-bottom: var(--space-6);
}
.progress-horizontal__bar {
  position: relative;
  overflow: hidden;
  height: var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  border: 1px solid var(--border);
}
.progress-horizontal .progress-horizontal__progress {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  background: var(--brand-primary);
}
.progress-horizontal.progress-horizontal--sm .progress-horizontal__bar {
  height: var(--space-2);
}
.progress-horizontal.progress-horizontal--lg .progress-horizontal__bar {
  height: var(--space-6);
}

/* ---- Video play affordance ---------------------------------------------- */
.video-play-icon {
  position: relative;
  z-index: 4;
  display: inline-block;
  width: var(--space-12);
  height: var(--space-12);
  border-radius: var(--radius-circle);
  border: 2px solid var(--surface-raised);
  background: var(--surface-raised);
  cursor: pointer;
  box-shadow: var(--shadow-md);
}
.video-play-icon.video-play-icon--sm {
  width: var(--space-9);
  height: var(--space-9);
}
.video-play-icon:before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-40%, -50%);
  border-top: 0.55rem solid transparent;
  border-bottom: 0.55rem solid transparent;
  border-left: 0.9rem solid var(--brand-primary);
}
.video-play-icon.video-play-icon--sm:before {
  border-top-width: 0.35rem;
  border-bottom-width: 0.35rem;
  border-left-width: 0.6rem;
}

/* ---- Sidebar navigation -------------------------------------------------
 * views/partials/navbar.ejs and views/admin/partials/navbar.ejs render
 *
 *   <div class="nav-container nav-container--sidebar"> … sidebar … </div>
 *   <div class="main-container nav-container--sidebar"> … page … </div>
 *
 * as two sibling block elements. They only sit side by side because the
 * sidebar is taken out of flow with position: fixed and the main container is
 * floated beside it. custom.css sets the *widths* of both but neither the
 * positioning nor the float, so with theme.css gone the sidebar occupied the
 * full width and the page content was pushed underneath it.
 *
 * custom.css loads after this file and overrides only width and padding, so
 * the positioning declared here survives.
 */
.nav-sidebar-column {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 3;
  width: var(--sidebar-width);
  height: 100vh;
  overflow-y: auto;
  padding: var(--space-8) var(--space-6);
  border-right: 1px solid var(--border);
  /* Scrollbar hidden to match the rest of the chrome; the column still
     scrolls with wheel, trackpad and keyboard. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.nav-sidebar-column::-webkit-scrollbar {
  display: none;
}
.nav-sidebar-column:not([class*='bg-']) {
  background: var(--surface-raised);
}

.nav-container.nav-container--sidebar + .main-container {
  float: right;
}

/* Keep a gutter between the page container and the edges of the content
 * column.
 *
 * Bootstrap 5 added a container tier that Bootstrap 4 did not have:
 * >= 1400px viewport gives .container a max-width of 1320px, where Bootstrap 4
 * capped at 1140px. The media query keys off the VIEWPORT, but .container sits
 * inside .main-container, which is only `100vw - sidebar` wide. So between
 * roughly 1400px and 1560px the cap is larger than the column and the container
 * fills it edge to edge, leaving no margin at all — at a 1500px viewport the
 * column is 1259px and the container was exactly 1259px.
 *
 * Setting `width` rather than `max-width` preserves Bootstrap's per-breakpoint
 * caps: the container is still clamped to 1320px on a wide screen, but never
 * grows to within less than a gutter of its parent. `margin-inline: auto` is
 * already on .container, so the space is split evenly.
 *
 * Desktop only. On mobile the column is full width and the container's own
 * padding is enough; adding another 16px each side would cramp a phone.
 */
@media (min-width: 991px) {
  .main-container > .container {
    width: calc(100% - 2 * var(--space-4));
  }
}
.nav-container.nav-container--right .nav-sidebar-column {
  right: 0;
  left: auto;
}
.nav-container.nav-container--right + .main-container {
  float: left;
}

/* Off-canvas below the sidebar breakpoint. The toggle adds .active via the
   data-toggle-class handler in stack-theme-scripts.js. 990px matches the
   companion rules already in custom.css. */
@media only screen and (max-width: 990px) {
  .nav-sidebar-column {
    left: calc(-1 * var(--sidebar-width));
    transition: left var(--dur-slow) ease, box-shadow var(--dur-slow) ease;
    box-shadow: none;
  }
  .nav-sidebar-column.active {
    left: 0;
    box-shadow: 2px 0 4px rgba(16, 24, 40, 0.1);
  }
  .nav-container.nav-container--sidebar + .main-container {
    float: none;
  }
}

.nav-sidebar-column-toggle {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 4;
  width: var(--space-9);
  height: var(--space-9);
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-raised);
  cursor: pointer;
  transition: left var(--dur-slow) ease;
}
.nav-sidebar-column-toggle.toggled-class {
  left: var(--sidebar-width);
}

/* ---- Nav dropdowns ------------------------------------------------------
 * The sidebar's collapsible groups. stack-theme-scripts.js toggles
 * .dropdown--active; without the hidden default every group renders expanded,
 * which is the other half of the sidebar layout collapse.
 */
.dropdown .dropdown__trigger {
  cursor: pointer;
  user-select: none;
}
.dropdown .dropdown__container {
  position: absolute;
  z-index: 999;
  min-width: 100%;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-slow) ease;
}
.dropdown.dropdown--active > .dropdown__container {
  opacity: 1;
  pointer-events: auto;
}
.dropdown .dropdown__content:not([class*='bg-']) {
  background: var(--surface-raised);
}

/* Inside the sidebar the panel is inline rather than floating, and collapses
   with display so it takes no space at all when closed. */
.nav-sidebar-column .dropdown .dropdown__container,
.nav-sidebar-column .dropdown .dropdown__content {
  position: relative;
  left: 0 !important;
  pointer-events: auto;
}
.nav-sidebar-column .dropdown:not(.dropdown--active) .dropdown__container {
  display: none;
}
.nav-sidebar-column .dropdown.dropdown--active > .dropdown__container {
  display: block;
}
.nav-sidebar-column .dropdown.dropdown--hover:hover > .dropdown__container {
  display: block;
}
.nav-sidebar-column .dropdown .dropdown__content {
  transform: none !important;
  box-shadow: none;
  background: none !important;
  padding: var(--space-2) 0 var(--space-2) var(--space-2);
}

/* ---- Accordions ---------------------------------------------------------
 * Also collapsed by CSS and expanded by stack-theme-scripts.js.
 */
.accordion li .accordion__content {
  opacity: 0;
  visibility: hidden;
  max-height: 0;
  overflow: hidden;
  transition: opacity var(--dur-base) ease, max-height var(--dur-base) ease;
}
.accordion li.active .accordion__content {
  opacity: 1;
  visibility: visible;
  max-height: 80rem;
}
.accordion li .accordion__title {
  cursor: pointer;
}

/* ---- Toast notifications ------------------------------------------------
 * Driven by mr.notifications in public/js/stack-theme-scripts.js and by
 * showNotification() in public/js/custom.js.
 *
 * views/partials/message.ejs renders its notification markup unconditionally —
 * outside the `if (notification)` guard — and relies entirely on CSS to keep it
 * hidden until revealed. So these rules are not decoration: without them the
 * green success box sits in normal flow at the bottom of every page that
 * includes the partial, which is every page with a header.
 *
 * The script toggles .notification--reveal to show and .notification--dismissed
 * to hide, so those class names and the [data-animation] attribute selectors
 * have to stay exactly as they are.
 */
.notification {
  position: fixed;
  z-index: 1080;
  margin: var(--space-6);
  padding: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-slow) linear;
}
.notification:not([class*='bg--']) {
  background: none;
}
.notification > .boxed {
  margin: 0;
}
.notification > .feature,
.notification .feature__body {
  margin-bottom: 0;
}
.notification[class*='col-'] {
  min-width: 400px;
}
@media (max-width: 767.98px) {
  .notification[class*='col-'] {
    min-width: 0;
  }
}

.notification.notification--reveal {
  pointer-events: auto;
}
.notification.notification--reveal[data-animation='from-bottom'] {
  animation: notification-from-bottom var(--dur-slow) linear 0s forwards;
}
.notification.notification--reveal[data-animation='from-top'] {
  animation: notification-from-top var(--dur-slow) linear 0s forwards;
}
.notification.notification--reveal[data-animation='from-left'] {
  animation: notification-from-left var(--dur-slow) linear 0s forwards;
}
.notification.notification--reveal[data-animation='from-right'] {
  animation: notification-from-right var(--dur-slow) linear 0s forwards;
}
/* Revealed with no data-animation at all: still needs to become visible. */
.notification.notification--reveal:not([data-animation]) {
  opacity: 1;
}
.notification.notification--dismissed {
  animation: notification-fade-out 0.4s linear 0s forwards !important;
  pointer-events: none;
}

/* The close cross is appended to every .notification by stack-theme-scripts.js,
   so it must be styled even though it appears nowhere in the markup. */
.notification .notification-close-cross {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  z-index: 99;
  cursor: pointer;
  opacity: 0.7;
  transition: opacity var(--dur-fast) linear;
}
.notification .notification-close-cross:before {
  content: '\00D7';
  font-size: 1.5em;
}
.notification .notification-close-cross:hover {
  opacity: 1;
}

@keyframes notification-from-bottom {
  from { transform: translate3d(0, 100%, 0); opacity: 0; }
  to   { transform: translate3d(0, 0, 0);    opacity: 1; }
}
@keyframes notification-from-top {
  from { transform: translate3d(0, -100%, 0); opacity: 0; }
  to   { transform: translate3d(0, 0, 0);     opacity: 1; }
}
@keyframes notification-from-left {
  from { transform: translate3d(-100%, 0, 0); opacity: 0; }
  to   { transform: translate3d(0, 0, 0);     opacity: 1; }
}
@keyframes notification-from-right {
  from { transform: translate3d(100%, 0, 0); opacity: 0; }
  to   { transform: translate3d(0, 0, 0);    opacity: 1; }
}
@keyframes notification-fade-out {
  from { opacity: 1; }
  to   { opacity: 0; }
}

/* Reduced motion disables the animations above. Because the hidden state is
   opacity: 0 and the animation is what raises it, skipping the animation would
   leave the notification permanently invisible — so set the end state directly.
   theme.css had no equivalent; notifications were simply lost for these users. */
@media (prefers-reduced-motion: reduce) {
  .notification.notification--reveal {
    animation: none !important;
    opacity: 1;
    transform: none;
  }
  .notification.notification--dismissed {
    animation: none !important;
    opacity: 0;
  }
}

/* ---- Hover dropdowns ----------------------------------------------------
 * Built by public/js/property.js. Bootstrap only opens dropdowns on click, so
 * without this the hover affordance is simply absent.
 */
.dropdown--hover:hover > .dropdown-menu {
  display: block;
  margin-top: 0;
}

/* ---- Slider list --------------------------------------------------------
 * stack-theme-scripts.js builds <ul class="slides"> and relies on the
 * non-initialised state hiding every slide but the first, so the page does not
 * flash a stack of them before Flickity takes over.
 */
.slides:not(.flickity-enabled) > li:not(:first-child) {
  display: none;
}

/* ---- Back to top -------------------------------------------------------- */
.back-to-top {
  position: fixed;
  right: var(--space-6);
  bottom: var(--space-9);
  width: var(--space-9);
  height: var(--space-9);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-circle);
  background: var(--surface-raised);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-md);
  z-index: 99;
  transition: transform var(--dur-base) var(--ease), opacity var(--dur-base) var(--ease);
}
.back-to-top i {
  color: var(--ink);
}
.back-to-top:not(.active) {
  opacity: 0;
  transform: translate3d(0, 20px, 0);
  pointer-events: none;
}
.back-to-top.active:hover {
  transform: translate3d(0, -5px, 0);
}

/* ---- Admin sidebar ------------------------------------------------------ */
.admin-sidebar:not([class*='bg-']) {
  background: var(--brand-primary);
}

/* ---- Masonry ------------------------------------------------------------
 * Retained as layout hooks for public/js/stack-theme-scripts.js; the script
 * sets the positions inline.
 */
.masonry__container {
  position: relative;
}
.masonry__filters {
  list-style: none;
  padding: 0;
}
.masonry__filters li {
  display: inline-block;
  cursor: pointer;
  margin-right: var(--space-3);
}
