/* AIA Design System & Refinements */

:root {
  --color-primary: #6ebf13;
  --color-primary-dark: #5ca10e;
  --color-primary-rgb: 13, 198, 193;

  /* Accessible teal. #0dc6c1 only reaches 2.13:1 against white or with white
     text on it; both directions fail WCAG AA. Use --color-primary for
     decoration (icon tiles, borders, illustration) and these two for anything
     carrying text: button fills, badges, status labels, body links. */
  --color-primary-text: #0dc6c1;        /* 5.99:1 on white, 5.99:1 under white */
  --color-primary-text-hover: #0a9893;  /* 8.05:1 */

  /* Set from the real header height at runtime; see layouts/app.blade.php. */
  --header-h: 68px;

  /* Type scale, 16px base on a ~1.2 ratio. Sizes used to be set per component
     with no relationship between them (0.775 / 0.825 / 0.9 / 0.95 / 0.975 /
     1.075rem), which is why headings and body copy never sat in a consistent
     rhythm. Every component below now picks from this list. */
  --fs-2xs: 0.75rem;    /* 12px  eyebrows, badges */
  --fs-xs:  0.8125rem;  /* 13px  meta, captions */
  --fs-sm:  0.875rem;   /* 14px  dense UI */
  --fs-md:  0.9375rem;  /* 15px  card body, buttons, nav */
  --fs-base: 1rem;      /* 16px  body copy */
  --fs-lg:  1.0625rem;  /* 17px  lead paragraphs */
  --fs-xl:  1.125rem;   /* 18px  card titles, footer headings */
  --fs-2xl: 1.375rem;   /* 22px  minor headings */

  /* Fluid display sizes, clamped so they stay proportional at every width. */
  --fs-h1:      clamp(2rem, 2.9vw, 2.625rem);      /* 32 - 42 */
  --fs-h1-page: clamp(1.875rem, 2.9vw, 2.375rem);  /* 30 - 38 */
  --fs-h2:      clamp(1.625rem, 2.4vw, 2.0625rem); /* 26 - 33 */
  --fs-stat:    clamp(2rem, 2.8vw, 2.5rem);        /* 32 - 40 */

  /* Line heights paired to role rather than one global value. */
  --lh-tight: 1.375;
  --lh-snug: 1.5;
  --lh-body: 1.65;
  --lh-loose: 1.75;
  --color-secondary: #67b410;
  --color-secondary-dark: #589c0d;
  --color-dark: #0f172a;
  --color-headings: #16181b;
  --color-body: #334155;
  --color-muted: #64748b;
  --color-border: #e2e8f0;
  --color-bg-light: #f8fafc;
}

/* Base Setup */
html {
  scroll-behavior: smooth;
}

body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  color: var(--color-body);
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  background-color: #ffffff;
}

/* Rich text from the admin editor ships inline text-align:justify, which sets
   rivers at our column width. Inline styles need !important to override. */
[style*="text-align:justify"],
[style*="text-align: justify"] {
  text-align: left !important;
}

h1, h2, h3, h4, h5, h6,
.display-1, .display-2, .display-3, .display-4, .display-5, .display-6 {
  font-family: 'Satoshi', sans-serif;
  color: var(--color-headings);
  letter-spacing: -0.015em;
}

/* ==========================================================================
   1. GLOBAL PRIMARY COLOR OVERRIDES (Eliminate Bootstrap Blue Default)
   ========================================================================== */
.btn-primary {
  background-color: var(--color-primary-text) !important;
  border-color: var(--color-primary-text) !important;
  color: #ffffff !important;
  font-weight: 600 !important;
  min-height: 44px !important;
  box-shadow: 0 2px 8px rgba(11, 111, 108, 0.25) !important;
  transition: all 0.25s ease !important;
}

.btn-primary:hover,
.btn-primary:focus,
.btn-primary:active,
.btn-primary.active {
  background-color: var(--color-primary-text-hover) !important;
  border-color: var(--color-primary-text-hover) !important;
  color: #ffffff !important;
  transform: translateY(-1px);
  box-shadow: 0 4px 14px rgba(11, 111, 108, 0.35) !important;
}

.btn-primary:disabled,
.btn-primary.disabled,
.btn-primary[disabled] {
  background-color: #64748b !important;
  border-color: #64748b !important;
  color: #ffffff !important;
  opacity: 0.7 !important;
  cursor: not-allowed !important;
  transform: none !important;
  box-shadow: none !important;
}

.btn-secondary {
  background-color: var(--color-primary) !important;
  border-color: var(--color-primary) !important;
  color: #ffffff !important;
  font-weight: 600 !important;
  min-height: 44px !important;
  box-shadow: 0 2px 8px rgba(11, 111, 108, 0.25) !important;
  transition: all 0.25s ease !important;
}

.btn-secondary:hover,
.btn-secondary:focus,
.btn-secondary:active,
.btn-secondary.active {
  background-color: var(--color-primary-dark) !important;
  border-color: var(--color-primary-dark) !important;
  color: #ffffff !important;
  transform: translateY(-1px);
  box-shadow: 0 4px 14px rgba(11, 111, 108, 0.35) !important;
}

.btn-secondary:disabled,
.btn-secondary.disabled,
.btn-secondary[disabled] {
  background-color: #64748b !important;
  border-color: #64748b !important;
  color: #ffffff !important;
  opacity: 0.7 !important;
  cursor: not-allowed !important;
  transform: none !important;
  box-shadow: none !important;
}

.btn-outline-primary {
  border-color: var(--color-primary-text) !important;
  color: var(--color-primary-text) !important;
  font-weight: 600 !important;
  min-height: 44px !important;
  transition: all 0.25s ease !important;
}

.btn-outline-primary:hover,
.btn-outline-primary:focus,
.btn-outline-primary:active {
  background-color: var(--color-primary-text) !important;
  border-color: var(--color-primary-text) !important;
  color: #ffffff !important;
  box-shadow: 0 4px 12px rgba(11, 111, 108, 0.25) !important;
}

/* Card "read more" links. The theme's base .btn no longer paints a fill, so
   these render as text links again. */
.btn-link {
  color: var(--color-primary-text) !important;
  min-height: 44px !important;
  display: inline-flex !important;
  align-items: center !important;
  text-decoration: none !important;
}

.btn-link:hover,
.btn-link:focus {
  color: var(--color-primary-text-hover) !important;
  text-decoration: underline !important;
}

/* text-primary is used both for body links and for decorative glyphs; the
   darker token clears 4.5:1 in both roles. */
.text-primary {
  color: var(--color-primary-text) !important;
}

.bg-primary {
  background-color: var(--color-primary-text) !important;
}

/* Decorative fills that carry no text keep the bright brand teal. */
.bg-primary-brand,
.service-icon-box,
.badge-icon {
  background-color: rgba(13, 198, 193, 0.12) !important;
}

.bg-primary-subtle {
  background-color: rgba(13, 198, 193, 0.12) !important;
  color: var(--color-primary-text) !important;
}

.badge.bg-primary,
.badge.text-bg-primary {
  background-color: var(--color-primary-text) !important;
  color: #ffffff !important;
}

.border-primary {
  border-color: var(--color-primary) !important;
}

.form-control:focus,
.form-select:focus {
  border-color: var(--color-primary-text) !important;
  box-shadow: 0 0 0 0.25rem rgba(11, 111, 108, 0.2) !important;
}

/* ==========================================================================
   2. NAVIGATION BAR (Clean, Crisp & Proportional)
   ========================================================================== */
.fbs__net-navbar {
  position: sticky !important;
  top: 0 !important;
  background-color: #ffffff !important;
  box-shadow: 0 2px 14px rgba(0, 0, 0, 0.05) !important;
  border-bottom: 1px solid rgba(0, 0, 0, 0.06) !important;
  padding: 20px 0 !important;
  z-index: 1030 !important;
  width: 100% !important;
}

.fbs__net-navbar .navbar-brand {
  display: inline-flex !important;
  align-items: center !important;
  padding: 0 !important;
  margin: 0 !important;
}

.fbs__net-navbar .navbar-brand .logo.dark {
  display: block !important;
  max-height: 36px !important;
  width: auto !important;
  object-fit: contain !important;
}

.fbs__net-navbar .navbar-brand .logo.light {
  display: none !important;
}

/* Nav links.
   Seven items plus the logo and the header CTA used to overflow .container at
   1440px, wrapping "Kontak" onto a second row and pushing the sticky header to
   101px. Tightened padding keeps it on one row down to the lg breakpoint. */
.fbs__net-navbar .navbar-nav > li > .nav-link {
  color: #1e293b !important;
  font-size: var(--fs-md) !important;
  font-weight: 500 !important;
  padding: 10px 10px !important;
  min-height: 44px !important;
  border-radius: 50rem !important;
  transition: all 0.2s ease !important;
  display: inline-flex !important;
  align-items: center !important;
  gap: 4px !important;
  white-space: nowrap !important;
}

@media (min-width: 1200px) {
  .fbs__net-navbar .navbar-nav > li > .nav-link {
    padding: 10px 13px !important;
  }
}

.fbs__net-navbar .navbar-nav {
  flex-wrap: nowrap !important;
}

@media (max-width: 991.98px) {
  .fbs__net-navbar .navbar-nav {
    flex-wrap: wrap !important;
  }
}

.fbs__net-navbar .navbar-nav > li > .nav-link:before {
  display: none !important;
}

.fbs__net-navbar .navbar-nav > li > .nav-link:hover,
.fbs__net-navbar .navbar-nav > li > .nav-link:focus {
  color: var(--color-primary-text) !important;
  background-color: rgba(13, 198, 193, 0.1) !important;
}

.fbs__net-navbar .navbar-nav > li > .nav-link.active {
  color: var(--color-primary-text) !important;
  background-color: rgba(13, 198, 193, 0.14) !important;
  font-weight: 600 !important;
}

/* Dropdown Menu */
.fbs__net-navbar .navbar-nav .dropdown-menu {
  background-color: #ffffff !important;
  border: 1px solid #e2e8f0 !important;
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.08) !important;
  border-radius: 14px !important;
  padding: 8px !important;
  min-width: 250px !important;
}

.fbs__net-navbar .navbar-nav .dropdown-menu .dropdown-item {
  color: #334155 !important;
  font-size: var(--fs-md) !important;
  font-weight: 500 !important;
  padding: 10px 14px !important;
  border-radius: 8px !important;
  transition: all 0.15s ease !important;
}

.fbs__net-navbar .navbar-nav .dropdown-menu .dropdown-item:hover,
.fbs__net-navbar .navbar-nav .dropdown-menu .dropdown-item:focus {
  background-color: rgba(13, 198, 193, 0.11) !important;
  color: var(--color-primary-text) !important;
  font-weight: 600 !important;
  padding-left: 18px !important;
}

/* Header Action Buttons */
.header-cta-group {
  display: flex;
  align-items: center;
  gap: 10px;
}

.fbs__net-navbar.dark a.btn-cert-check,
.btn-cert-check {
  background-color: var(--color-primary-text) !important;
  border: 1px solid var(--color-primary-text) !important;
  color: #ffffff !important;
  font-size: var(--fs-md) !important;
  font-weight: 600 !important;
  border-radius: 50rem !important;
  padding: 10px 18px !important;
  min-height: 44px !important;
  display: inline-flex !important;
  align-items: center !important;
  gap: 0.5rem !important;
  transition: all 0.25s ease !important;
  box-shadow: 0 2px 8px rgba(11, 111, 108, 0.25) !important;
  text-decoration: none !important;
  white-space: nowrap !important;
}

/* .btn-cert-check forces display:inline-flex, which has the same specificity
   as Bootstrap's .d-none and wins on source order. That kept the CTA visible
   below sm and pushed the mobile header onto a second row. */
/* Must out-specify the .fbs__net-navbar.dark a.btn-cert-check rule above; a
   media query adds no specificity of its own. Below sm the CTA lives in the
   offcanvas menu, and keeping it here forced the header onto a second row. */
@media (max-width: 575.98px) {
  .fbs__net-navbar.dark a.btn-cert-check.d-none {
    display: none !important;
  }
}

.fbs__net-navbar.dark a.btn-cert-check:hover,
.btn-cert-check:hover {
  background-color: var(--color-primary-text-hover) !important;
  border-color: var(--color-primary-text-hover) !important;
  color: #ffffff !important;
  transform: translateY(-1px) !important;
  box-shadow: 0 4px 14px rgba(11, 111, 108, 0.35) !important;
}

.fbs__net-navbar-toggler {
  width: 44px !important;
  height: 44px !important;
  border-radius: 10px !important;
  border: 1px solid #cbd5e1 !important;
  background-color: #ffffff !important;
  color: #0f172a !important;
  display: none !important;
  align-items: center !important;
  justify-content: center !important;
}

@media (max-width: 991.98px) {
  .fbs__net-navbar-toggler {
    display: inline-flex !important;
  }
}

/* ==========================================================================
   3. PROPORTIONAL TYPOGRAPHY & SECTION HEADERS
   ========================================================================== */
.hero__v14 {
  padding-top: 48px;
  padding-bottom: 64px;
}

.hero-title {
  font-size: var(--fs-h1) !important;
  font-weight: 700 !important;
  line-height: var(--lh-tight) !important;
  letter-spacing: -0.022em !important;
  color: #0f172a !important;
  text-wrap: balance;
}

.hero-subtitle {
  font-size: var(--fs-lg) !important;
  line-height: var(--lh-loose) !important;
  color: #475569 !important;
  /* ~60 characters keeps the lead readable at the hero column width. */
  max-width: 34em;
}

.section-badge {
  font-size: var(--fs-2xs) !important;
  font-weight: 600 !important;
  text-transform: uppercase !important;
  letter-spacing: 0.06em !important;
  padding: 6px 14px !important;
  border-radius: 50rem !important;
  display: inline-flex !important;
  align-items: center !important;
  gap: 6px !important;
  background: rgba(13, 198, 193, 0.1) !important;
  color: var(--color-primary-text) !important;
  border: 1px solid rgba(13, 198, 193, 0.3) !important;
  margin-bottom: 0.75rem !important;
}

.section-title {
  font-size: var(--fs-h2) !important;
  font-weight: 700 !important;
  line-height: var(--lh-snug) !important;
  letter-spacing: -0.018em !important;
  color: #0f172a !important;
  text-wrap: balance;
}

.section-subtitle {
  font-size: var(--fs-lg) !important;
  line-height: var(--lh-body) !important;
  color: #5b6b7c !important;
  max-width: 56ch;
}

/* A centred section intro needs its measure centred too, or the block sits
   left of the heading above it. */
.text-center .section-subtitle,
.text-center > .section-subtitle,
.mx-auto .section-subtitle {
  margin-left: auto;
  margin-right: auto;
}

.card-title {
  font-size: var(--fs-xl) !important;
  font-weight: 700 !important;
  line-height: var(--lh-snug) !important;
  letter-spacing: -0.01em !important;
  color: #0f172a !important;
}

.card-desc {
  font-size: var(--fs-md) !important;
  line-height: 1.6 !important;
  color: #475569 !important;
}

.card-meta {
  font-size: var(--fs-xs) !important;
  font-weight: 500 !important;
  color: #64748b !important;
}

/* PureCounter Stats Typography */
.stat-number {
  font-size: var(--fs-stat) !important;
  font-variant-numeric: tabular-nums;
  font-weight: 800 !important;
  color: var(--color-primary-text) !important;
  line-height: 1.1 !important;
}

.stat-label {
  font-size: var(--fs-xs) !important;
  font-weight: 600 !important;
  text-transform: uppercase !important;
  letter-spacing: 0.05em !important;
  color: #64748b !important;
  margin-top: 0.5rem !important;
}

/* ==========================================================================
   4. CARDS & ELEVATIONS
   ========================================================================== */
.aia-card {
  background: #ffffff;
  border-radius: 16px;
  border: 1px solid #edf2f7;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.04);
  transition: transform 0.3s ease, box-shadow 0.3s ease;
  overflow: hidden;
}

/* The lift is a response to the pointer, so it belongs only on cards that are
   part of a collection the user is scanning: search results, listings, grids.
   On a static panel — a search form, a sidebar box, a result readout — it
   moves under the cursor with nothing to click, which reads as a glitch. Those
   cards carry .aia-card alone; collection items opt in. */
.aia-card-hover:hover {
  transform: translateY(-3px);
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.08);
}

/* Service Card Icons */
.service-icon-box {
  width: 52px;
  height: 52px;
  border-radius: 14px;
  background-color: rgba(13, 198, 193, 0.12) !important;
  color: var(--color-primary-text) !important;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
}

/* ==========================================================================
   5. SUBPAGE BANNER
   ========================================================================== */
.page-header-banner {
  background: linear-gradient(135deg, #091a24 0%, #0d2c38 100%);
  padding: 64px 0;
  position: relative;
  overflow: hidden;
}

.page-header-banner::before {
  content: "";
  position: absolute;
  top: -50%;
  right: -20%;
  width: 500px;
  height: 500px;
  background: radial-gradient(circle, rgba(13, 198, 193, 0.15) 0%, rgba(13, 198, 193, 0) 70%);
  border-radius: 50%;
  pointer-events: none;
}

.page-header-banner h1 {
  color: #ffffff !important;
  font-weight: 700 !important;
  font-size: var(--fs-h1-page) !important;
  line-height: var(--lh-tight);
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.page-header-banner .lead {
  font-size: var(--fs-lg) !important;
  line-height: var(--lh-body);
}

/* Centre the capped box too, or it stays flush left under a centred heading.
   A centred lead also wants a shorter measure and balanced lines; at 78ch it
   wrapped to a full line and a two-word orphan. */
.text-center > .page-header-banner .lead,
.page-header-banner .text-center .lead,
.container.text-center .lead {
  margin-inline: auto;
}

.page-header-banner .container.text-center:not(.text-lg-start) .lead {
  max-width: 62ch;
  text-wrap: balance;
}

@media (min-width: 992px) {
  .container.text-center.text-lg-start .lead {
    margin-inline: 0;
  }
}

.page-header-banner .breadcrumb-item,
.page-header-banner .breadcrumb-item a {
  color: rgba(255, 255, 255, 0.78);
  font-size: var(--fs-sm);
  text-decoration: none;
}

.page-header-banner .breadcrumb-item.active {
  color: var(--color-primary);
}

.page-header-banner .breadcrumb-item + .breadcrumb-item::before {
  color: rgba(255, 255, 255, 0.4);
}

/* ==========================================================================
   6. FLOATING ACTIONS & BACK TO TOP
   ========================================================================== */
#back-to-top {
  position: fixed;
  bottom: 24px;
  right: 24px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background-color: var(--color-primary-text);
  color: #fff;
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.4rem;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.15);
  z-index: 998;
  opacity: 0;
  visibility: hidden;
  transition: all 0.3s ease;
}

#back-to-top.active {
  opacity: 1;
  visibility: visible;
}

#back-to-top:hover {
  background-color: var(--color-primary-text-hover);
  transform: translateY(-2px);
}

/* The primary contact route on the whole site, sized to read as such: 60px
   against the 44px back-to-top beside it. Bottom stays at 78px, which keeps a
   10px gap over that button. */
.floating-wa-btn {
  position: fixed;
  bottom: 78px;
  right: 24px;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  background: #25d366;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
  box-shadow: 0 4px 16px rgba(37, 211, 102, 0.35);
  z-index: 999;
  text-decoration: none;
  transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

/* The pulse is a ring behind the button rather than the button itself moving:
   a button that changes size is a moving target for anyone aiming at it. */
.floating-wa-btn::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: #25d366;
  z-index: -1;
  animation: wa-pulse 2.4s cubic-bezier(0.25, 0.46, 0.45, 0.94) infinite;
}

@keyframes wa-pulse {
  0% {
    transform: scale(1);
    opacity: 0.6;
  }
  70% {
    transform: scale(1.6);
    opacity: 0;
  }
  100% {
    transform: scale(1.6);
    opacity: 0;
  }
}

/* A looping animation in the corner of every page is the exact thing reduced
   motion is asking about. */
@media (prefers-reduced-motion: reduce) {
  .floating-wa-btn::before {
    animation: none;
  }
}

.floating-wa-btn:hover {
  background: #1ebe5d;
  color: #fff;
  transform: scale(1.08) translateY(-2px);
  box-shadow: 0 8px 24px rgba(37, 211, 102, 0.45);
}

/* The ring competes with the hover state; on hover the button speaks for
   itself. */
.floating-wa-btn:hover::before,
.floating-wa-btn:focus-visible::before {
  animation-play-state: paused;
  opacity: 0;
}

/* ==========================================================================
   Toast Notification (Contact Form Feedback)
   Harmonized with AIA Design System Color Tokens & Proportions
   ========================================================================== */
.cf-toast-container {
  position: fixed;
  bottom: 24px;
  right: 24px;
  z-index: 1090;
  width: min(420px, calc(100vw - 32px));
  pointer-events: none;
}

.cf-toast {
  background-color: #ffffff;
  border-radius: 14px;
  border: 1px solid var(--color-border);
  box-shadow: 0 16px 36px -4px rgba(15, 23, 42, 0.14), 0 4px 12px -2px rgba(15, 23, 42, 0.06);
  padding: 14px 14px 14px 16px;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  opacity: 0;
  visibility: hidden;
  transform: translateY(16px) scale(0.98);
  transition: opacity 0.28s cubic-bezier(0.16, 1, 0.3, 1),
              transform 0.28s cubic-bezier(0.16, 1, 0.3, 1),
              visibility 0.28s;
  pointer-events: none;
  position: relative;
  overflow: hidden;
}

.cf-toast.show {
  opacity: 1;
  visibility: visible;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}

/* Subtle brand accent stripe on the left */
.cf-toast::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 4px;
  border-radius: 14px 0 0 14px;
}

.cf-toast--success::before {
  background: linear-gradient(180deg, var(--color-primary-text) 0%, var(--color-secondary) 100%);
}

.cf-toast--error::before {
  background: linear-gradient(180deg, #dc2626 0%, #ef4444 100%);
}

/* Icon Box */
.cf-toast-icon-box {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-top: 1px;
}

.cf-toast--success .cf-toast-icon-box {
  background-color: rgba(13, 198, 193, 0.12);
  color: var(--color-primary-text);
  border: 1px solid rgba(11, 111, 108, 0.2);
}

.cf-toast--error .cf-toast-icon-box {
  background-color: #fef2f2;
  color: #dc2626;
  border: 1px solid rgba(220, 38, 38, 0.2);
}

.cf-toast-icon {
  font-size: 1.15rem;
  line-height: 1;
}

/* Content & Typography */
.cf-toast-content {
  flex: 1;
  min-width: 0;
  padding-top: 1px;
}

.cf-toast-title {
  display: block;
  font-family: 'Satoshi', sans-serif;
  font-size: var(--fs-md);
  font-weight: 700;
  color: var(--color-headings);
  letter-spacing: -0.015em;
  line-height: var(--lh-tight);
  margin-bottom: 3px;
}

.cf-toast-msg {
  font-family: 'Inter', sans-serif;
  font-size: var(--fs-sm);
  font-weight: 400;
  color: var(--color-body);
  line-height: var(--lh-snug);
  margin: 0;
  word-break: break-word;
}

/* Close Action */
.cf-toast-close {
  background: transparent;
  border: none;
  width: 28px;
  height: 28px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-muted);
  cursor: pointer;
  flex-shrink: 0;
  padding: 0;
  margin: -2px -2px 0 0;
  transition: background-color 0.2s ease, color 0.2s ease;
}

.cf-toast-close i {
  font-size: 0.95rem;
  line-height: 1;
}

.cf-toast-close:hover {
  background-color: var(--color-bg-light);
  color: var(--color-headings);
}

.cf-toast-close:focus-visible {
  outline: 2px solid var(--color-primary-text);
  outline-offset: 1px;
}

@media (max-width: 575.98px) {
  .cf-toast-container {
    bottom: 16px;
    right: 16px;
    left: 16px;
    width: auto;
  }

  .cf-toast {
    padding: 12px 12px 12px 14px;
    gap: 10px;
  }
}

/* Contact Form Inline Feedback (if fallback triggers) */
#cf-success-msg,
#cf-error-msg {
  border-radius: 12px;
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
  padding: 12px 16px;
}

#cf-success-msg {
  background-color: rgba(13, 198, 193, 0.08);
  border: 1px solid rgba(11, 111, 108, 0.25);
  color: var(--color-primary-text);
}

#cf-error-msg {
  background-color: #fef2f2;
  border: 1px solid #fecaca;
  color: #991b1b;
}

/* Filter Button */
.filter-button {
  border: 1px solid #e2e8f0;
  color: #334155;
  padding: 11px 18px;
  min-height: 44px;
  border-radius: 50rem;
  font-size: var(--fs-md);
  font-weight: 500;
  text-decoration: none;
  background-color: #ffffff;
  transition: all 0.2s ease;
  display: inline-block;
  cursor: pointer;
}

.filter-button:hover,
.filter-button.active {
  background-color: var(--color-primary-text) !important;
  border-color: var(--color-primary-text) !important;
  color: #ffffff !important;
  box-shadow: 0 4px 12px rgba(11, 111, 108, 0.25);
}

/* Responsive Rules */
@media (max-width: 575.98px) {
  .hero__v14 .hero-card.absolute-1-inner {
    position: static !important;
    margin-top: 1rem;
    width: 100%;
    left: auto !important;
    top: auto !important;
  }
  .hero__v14 .hero-card.absolute-2-inner {
    position: static !important;
    margin-top: 0.75rem;
    width: 100%;
    right: auto !important;
    bottom: auto !important;
  }
}

/* ==========================================================================
   8. ACCESSIBILITY & LAYOUT FIXES
   ========================================================================== */

/* The purchased theme sets outline:none on .btn and .nav-link with nothing in
   its place, so keyboard users had no focus indicator anywhere on the site. */
a:focus-visible,
button:focus-visible,
.btn:focus-visible,
.nav-link:focus-visible,
.dropdown-item:focus-visible,
.filter-button:focus-visible,
.btn-cert-check:focus-visible,
.floating-wa-btn:focus-visible,
#back-to-top:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid var(--color-primary-text) !important;
  outline-offset: 2px !important;
  border-radius: 6px;
}

.page-header-banner a:focus-visible,
.footer a:focus-visible,
.cta__v1 a:focus-visible {
  outline-color: #7cf0ec !important;
}

/* Skip link, first focusable element, revealed on focus. */
.skip-to-content {
  position: absolute;
  left: 12px;
  top: -100px;
  z-index: 2000;
  padding: 12px 20px;
  border-radius: 0 0 10px 10px;
  background: var(--color-primary-text);
  color: #fff;
  font-weight: 600;
  text-decoration: none;
  transition: top 0.2s ease;
}

.skip-to-content:focus {
  top: 0;
  color: #fff;
}

/* Anchor targets sat behind the sticky header because scroll-margin was a
   hardcoded 80px while the real header measured 101px. --header-h is written
   from the measured height at runtime. */
.section,
section[id],
[id]:target {
  scroll-margin-top: calc(var(--header-h) + 20px);
}

/* Reveal-on-scroll left 38 of 45 elements at opacity 0 at rest, so the page
   rendered blank without JS. AOS adds .aos-init once it boots; until then, and
   permanently if it never boots, content stays visible. */
[data-aos]:not(.aos-init) {
  opacity: 1 !important;
  transform: none !important;
  visibility: visible !important;
}

@media (prefers-reduced-motion: reduce) {
  [data-aos] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  html {
    scroll-behavior: auto;
  }
}

/* --------------------------------------------------------------------------
   Article thumbnails.
   .article-thumb-wrap was referenced by two templates and defined by none, so
   images rendered at intrinsic size, roughly 800px tall in a four-up grid.
   -------------------------------------------------------------------------- */
.article-thumb-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background-color: #eef2f5;
}

.article-thumb-wrap img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.4s ease;
}

.aia-card-hover:hover .article-thumb-wrap img {
  transform: scale(1.04);
}

/* --------------------------------------------------------------------------
   Gallery captions.
   Titles were dark text laid straight onto photographs, unreadable against
   bright windows and whiteboards. A scrim gives them a consistent ground.
   -------------------------------------------------------------------------- */
.gallery-thumb-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: 14px;
}

.gallery-thumb-wrap img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.45s ease;
}

.gallery-thumb-wrap:hover img {
  transform: scale(1.05);
}

.gallery-caption-scrim {
  position: absolute;
  inset: auto 0 0 0;
  padding: 42px 16px 14px;
  background: linear-gradient(to top, rgba(6, 20, 24, 0.92) 0%, rgba(6, 20, 24, 0.65) 45%, rgba(6, 20, 24, 0) 100%);
  pointer-events: none;
}

/* .card-title sets #0f172a with !important, so captions laid over a photo need
   their own white declaration to win. */
.gallery-title,
.gallery-caption-scrim .gallery-title {
  color: #ffffff !important;
  font-size: var(--fs-md);
  font-weight: 600;
  line-height: 1.35;
  margin: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.gallery-category-badge {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 2;
  background: var(--color-primary-text);
  color: #ffffff;
  font-size: var(--fs-2xs);
  font-weight: 600;
  padding: 5px 11px;
  border-radius: 50rem;
}

/* --------------------------------------------------------------------------
   Carousel controls.
   The next arrow was positioned at x=437 on a 390px viewport: unreachable, and
   the reason the whole document scrolled sideways on mobile.
   -------------------------------------------------------------------------- */
.custom-prev,
.custom-next {
  width: 44px !important;
  height: 44px !important;
  border-radius: 50% !important;
  border: 1px solid #cbd5e1 !important;
  background-color: #ffffff !important;
  color: var(--color-primary-text) !important;
  text-decoration: none !important;
  flex-shrink: 0;
  transition: all 0.2s ease;
}

.custom-prev:hover,
.custom-next:hover {
  background-color: var(--color-primary-text) !important;
  border-color: var(--color-primary-text) !important;
  color: #ffffff !important;
}

@media (max-width: 991.98px) {
  .custom-prev,
  .custom-next {
    position: static !important;
    transform: none !important;
    margin: 0 !important;
  }
}

/* Nothing on the page should push the document wider than the viewport.
   `hidden` did that, but it also makes the element a scroll container, and a
   scroll container on html/body is what kept the sticky header from sticking:
   the header's scrollport was body itself, which is exactly as tall as its
   content, so there was never any distance for it to stick over. `clip`
   trims the same overflow without creating that container. The `hidden` line
   stays first as the fallback for browsers without `clip` (Safari < 16). */
html,
body {
  overflow-x: hidden;
  overflow-x: clip;
}

/* --------------------------------------------------------------------------
   Floating actions.
   The WhatsApp button and back-to-top stacked as two overlapping circles over
   card content; on mobile the WhatsApp one landed on the hero subject face.
   -------------------------------------------------------------------------- */
/* Size is set once, up in the button's own rule; this block only places it. */
.floating-wa-btn {
  bottom: 24px !important;
  right: 20px !important;
  transition: transform 0.3s ease, bottom 0.3s ease, box-shadow 0.3s ease !important;
}

#back-to-top {
  bottom: 24px;
  right: 20px;
  width: 44px;
  height: 44px;
}

/* Back-to-top only appears after scrolling, so lift WhatsApp clear of it then
   rather than reserving the space permanently. */
body.has-back-to-top .floating-wa-btn {
  bottom: 80px !important;
}

@media (max-width: 575.98px) {
  .floating-wa-btn {
    width: 52px !important;
    height: 52px !important;
    font-size: 1.75rem !important;
    bottom: 16px !important;
    right: 16px !important;
  }
  #back-to-top {
    bottom: 16px;
    right: 16px;
  }
  body.has-back-to-top .floating-wa-btn {
    bottom: 70px !important;
  }
}

/* --------------------------------------------------------------------------
   Touch targets. 74 interactive elements measured under the 44px minimum.
   -------------------------------------------------------------------------- */
.form-control,
.form-select {
  min-height: 44px;
  /* Anything under 16px makes iOS Safari zoom the viewport on focus. */
  font-size: 16px !important;
}

textarea.form-control {
  min-height: 120px;
}

.btn-sm {
  min-height: 44px !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
}

.footer .social a {
  width: 44px !important;
  height: 44px !important;
  border-radius: 50% !important;
  color: var(--color-primary-text) !important;
  background-color: rgba(13, 198, 193, 0.12) !important;
  transition: all 0.2s ease;
}

.footer .social a:hover {
  background-color: var(--color-primary-text) !important;
  color: #ffffff !important;
}

/* --------------------------------------------------------------------------
   Grid rhythm. Cards in a row shared a row but not a height.
   -------------------------------------------------------------------------- */
.row.equal-cards > [class*="col-"] {
  display: flex;
}

.row.equal-cards > [class*="col-"] > * {
  width: 100%;
}

/* Two-line clamp for card titles, so they wrap instead of truncating mid-word. */
.clamp-2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.clamp-3 {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Status labels carried meaning in hue alone and read as a second link beside
   the teal CTA. Give them a badge shape and a dot. */
.status-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 11px;
  border-radius: 50rem;
  font-size: var(--fs-xs);
  font-weight: 600;
  background-color: #eef9e2;
  color: #6ebf13;
  border: 1px solid #b8d09c;
}

.status-pill::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background-color: currentColor;
  flex-shrink: 0;
}

/* Empty states need a way onward, not just a sentence. */
.empty-state-icon {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background-color: rgba(13, 198, 193, 0.12);
  color: var(--color-primary-text);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.6rem;
}

/* Reserve the drawing area so lazy images do not shift the layout in. */
img[loading="lazy"] {
  background-color: #f1f5f9;
}

/* Schedule date chip: month tab and day box shared no width. */
.schedule-date-chip {
  width: 72px;
  flex-shrink: 0;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid var(--color-border);
  text-align: center;
}

.schedule-date-chip .month {
  background-color: var(--color-primary-text);
  color: #ffffff;
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 4px 0;
}

.schedule-date-chip .day {
  background-color: #f8fafc;
  color: #0f172a;
  font-weight: 700;
  line-height: 1.2;
  padding: 6px 0 8px;
  font-variant-numeric: tabular-nums;
}

/* Bootstrap renders <code> in #d63384, the only pink on the site. Keep inline
   code on the neutral scale instead. */
code {
  color: #334155;
  background-color: #f1f5f9;
  padding: 1px 6px;
  border-radius: 4px;
}

/* .text-warning (#ffc107) on .bg-warning-subtle is roughly 1.6:1. Amber only
   reads as a warning if it can actually be read. */
.bg-warning-subtle.text-warning,
.text-warning.bg-warning-subtle {
  color: #915000 !important;
}

/* Testimonial carousel arrows sat at 42px, just under the touch minimum. */
.testimonials__v7-prev,
.testimonials__v7-next {
  width: 44px !important;
  height: 44px !important;
  color: var(--color-primary-text) !important;
}

.testimonials__v7-prev:hover,
.testimonials__v7-next:hover {
  background-color: var(--color-primary-text) !important;
  border-color: var(--color-primary-text) !important;
  color: #ffffff !important;
}

/* Hero photo slider arrows and dots. main.css styles .about-slider-dots off
   --accent-color, the purchased theme's orange, never redefined on this site;
   bring the active dot onto the same brand teal as every other control. */
.about-slider-prev,
.about-slider-next {
  color: var(--color-primary-text) !important;
}

.about-slider-prev:hover,
.about-slider-next:hover {
  background-color: var(--color-primary-text) !important;
  border-color: var(--color-primary-text) !important;
  color: #ffffff !important;
}

.about-slider-dots .swiper-pagination-bullet {
  background: var(--color-border) !important;
}

.about-slider-dots .swiper-pagination-bullet-active {
  background: var(--color-primary-text) !important;
}

/* The logo link is the tallest thing in the header row; pad it to the target
   size without changing the mark. */
.fbs__net-navbar .navbar-brand {
  min-height: 44px !important;
}

/* Printing never fires the scroll observer, so a printed page would drop every
   section that had not been revealed on screen. */
@media print {
  [data-aos] {
    opacity: 1 !important;
    transform: none !important;
  }
  .floating-wa-btn,
  #back-to-top,
  .skip-to-content {
    display: none !important;
  }
}

/* ==========================================================================
   9. NAVBAR DROPDOWN
   ==========================================================================
   Two rules fought over this menu: onepage.css pinned it to width: 200px above
   992px while aia-custom set min-width: 250px, and Bootstrap's
   .dropdown-item { white-space: nowrap } meant the longest programme names
   painted straight out of the white panel and over the page behind it.
   The panel now sizes to its content within a sensible range, and items wrap. */

.fbs__net-navbar .navbar-nav .dropdown > .dropdown-menu,
.fbs__net-navbar .navbar-nav .dropend > .dropdown-menu,
.fbs__net-navbar .navbar-nav .dropstart > .dropdown-menu,
.fbs__net-navbar .navbar-nav .dropdown-menu {
  width: auto !important;
  min-width: 17rem !important;
  max-width: 22rem !important;
  padding: 0.5rem !important;
}

.fbs__net-navbar .navbar-nav .dropdown-menu .dropdown-item {
  /* The overflow itself. */
  white-space: normal !important;
  overflow-wrap: anywhere;
  line-height: 1.4 !important;
  min-height: 44px;
  display: flex !important;
  align-items: center;
}

/* Bootstrap's default active/hover fills are blue; keep the menu on-brand and
   readable in every state. */
.fbs__net-navbar .navbar-nav .dropdown-menu .dropdown-item:active,
.fbs__net-navbar .navbar-nav .dropdown-menu .dropdown-item.active {
  background-color: var(--color-primary-text) !important;
  color: #ffffff !important;
}

.fbs__net-navbar .navbar-nav .dropdown-menu .dropdown-divider {
  margin: 0.5rem 0.25rem !important;
  border-top-color: var(--color-border) !important;
  opacity: 1;
}

@media (min-width: 992px) {
  /* The menu is positioned a few pixels below the toggle. Without something
     spanning that gap the pointer leaves .dropdown on the way down and the
     menu closes before it can be reached. */
  .fbs__net-navbar .navbar-nav .nav-item.dropdown > .dropdown-menu::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: -14px;
    height: 14px;
  }

  .fbs__net-navbar .navbar-nav .nav-item.dropdown > .dropdown-menu {
    margin-top: 6px !important;
  }
}

/* Inside the offcanvas the menu is a plain nested list, not a floating panel.
   These selectors have to match the specificity of the block above, whose
   `.dropdown > .dropdown-menu` member is (0,4,0); a shorter selector here loses
   and the 17rem min-width stretches the drawer into horizontal scroll. */
@media (max-width: 991.98px) {
  .fbs__net-navbar .navbar-nav .dropdown > .dropdown-menu,
  .fbs__net-navbar .navbar-nav .dropend > .dropdown-menu,
  .fbs__net-navbar .navbar-nav .dropstart > .dropdown-menu,
  .fbs__net-navbar .navbar-nav .nav-item .dropdown-menu {
    max-width: none !important;
    min-width: 0 !important;
    box-shadow: none !important;
    border: none !important;
    border-left: 2px solid var(--color-border) !important;
    border-radius: 0 !important;
    margin: 0.25rem 0 0.5rem 0.5rem !important;
  }
}

/* Client marquee: the hover treatment used to live in inline onmouseover /
   onmouseout handlers on every logo. */
.client-logo {
  max-height: 48px;
  max-width: 140px;
  object-fit: contain;
  filter: grayscale(100%);
  opacity: 0.75;
  transition: filter 0.3s ease, opacity 0.3s ease;
}

.logo-item:hover .client-logo {
  filter: none;
  opacity: 1;
}

/* Fallback for a client whose logo file is missing. */
.client-logo-text {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--color-muted);
  white-space: nowrap;
}

/* ==========================================================================
   10. SPACING SYSTEM
   ==========================================================================
   Vertical rhythm was set entirely by Bootstrap utilities, so every section
   landed on py-5 (48px) except two bands on py-4 (24px). That gave 96px
   between same-coloured sections, 72px where a band met one, and no relation
   to the 1240px container. These tokens put section, band, banner and footer
   spacing on one 8px-based scale that steps down at each breakpoint.

   Bootstrap's spacing utilities carry !important, so overriding them needs
   both a type selector for specificity and !important of our own. */

:root {
  --space-section: 5rem;   /* 80px  standard section */
  --space-band: 3rem;      /* 48px  narrow accent bands */
  --space-banner: 4.5rem;  /* 72px  subpage header */
  --space-hero-top: 3.5rem;
  --space-hero-bottom: 4.5rem;
  --space-footer-top: 4rem;
  --space-footer-bottom: 2.5rem;
  --gutter: 1.25rem;       /* 20px  container side padding */
}

@media (max-width: 991.98px) {
  :root {
    --space-section: 3.75rem;  /* 60px */
    --space-band: 2.5rem;      /* 40px */
    --space-banner: 3.25rem;   /* 52px */
    --space-hero-top: 2.5rem;
    --space-hero-bottom: 3rem;
    --space-footer-top: 3rem;
    --space-footer-bottom: 2rem;
  }
}

@media (max-width: 575.98px) {
  :root {
    --space-section: 3rem;     /* 48px */
    --space-band: 2rem;        /* 32px */
    --space-banner: 2.5rem;    /* 40px */
    --space-hero-top: 2rem;
    --space-hero-bottom: 2.5rem;
    --gutter: 1.25rem;
  }
}

/* Container gutters were 12px a side, so on a 1264px laptop the content very
   nearly touched the viewport edge. */
.container,
.container-fluid {
  padding-left: var(--gutter) !important;
  padding-right: var(--gutter) !important;
}

@media (min-width: 1200px) {
  .container {
    padding-left: 1.5rem !important;
    padding-right: 1.5rem !important;
  }
}

/* Standard content sections. */
section.section,
section.py-5 {
  padding-top: var(--space-section) !important;
  padding-bottom: var(--space-section) !important;
}

/* Narrow accent bands: the client marquee and the in-house CTA strip. */
section.clients__v2,
section.cta__v1,
section.py-4 {
  padding-top: var(--space-band) !important;
  padding-bottom: var(--space-band) !important;
}

/* The hero carries its own asymmetry: less above (the header already provides
   separation), more below before the first band. */
section.hero__v14 {
  padding-top: var(--space-hero-top) !important;
  padding-bottom: var(--space-hero-bottom) !important;
}

.page-header-banner {
  padding-top: var(--space-banner);
  padding-bottom: var(--space-banner);
}

.footer {
  padding-top: var(--space-footer-top) !important;
  padding-bottom: var(--space-footer-bottom) !important;
}

/* --------------------------------------------------------------------------
   Section heads.
   .section-title set margin-bottom with !important, so the mb-2 and mb-3
   utilities on it were both dead and produced the same 8px. Dropping the
   !important lets the markup's own utilities work again, with a sensible
   default when none is given.
   -------------------------------------------------------------------------- */
/* Uniform across every section: the markup's mb-2 / mb-3 varied per template
   and produced 8px, 12px and 16px gaps for the same relationship. */
.section-title {
  margin-bottom: 1.25rem !important;
}

/* The compact CTA strip is a tighter block, so its heading sits closer. */
.band-title {
  margin-bottom: 0.75rem !important;
}

.section-badge {
  margin-bottom: 0.875rem !important;
}

/* The subtitle closes the head block; spacing to the content below belongs to
   the head's wrapper, not to the paragraph. */
.section-subtitle {
  margin-bottom: 0;
}

.hero-title {
  margin-bottom: 1rem !important;
}

.hero-subtitle {
  margin-bottom: 2rem !important;
}

/* Consistent gap between a section head and the grid beneath it, replacing the
   mix of mb-4 / mb-5 / none in the templates. */
.section > .container > .row:first-child:not(:only-child) {
  margin-bottom: 2.5rem;
}

@media (max-width: 767.98px) {
  .section > .container > .row:first-child:not(:only-child) {
    margin-bottom: 1.75rem;
  }
}

/* --------------------------------------------------------------------------
   Cards.
   Padding ran 0 / 16 / 24 / 48px across the site with no rule behind it.
   24px is the standard; the large form and prose panels step up to 32px
   rather than 48px, which left their content stranded in the middle.
   -------------------------------------------------------------------------- */
.aia-card.p-4.p-md-5 {
  padding: 2rem !important;
}

@media (max-width: 767.98px) {
  .aia-card.p-4.p-md-5 {
    padding: 1.5rem !important;
  }
}

/* Cards whose image sits flush to the edge carry their padding on the inner
   block; 20px pairs better with the 24px used by padded cards. */
.aia-card > .p-3 {
  padding: 1.25rem !important;
}

.aia-card > .p-3.pt-0 {
  padding-top: 0 !important;
}

/* Card footers sat directly against the divider above them. */
.aia-card .border-top.pt-3 {
  padding-top: 1rem !important;
  margin-top: 0.25rem;
}

/* --------------------------------------------------------------------------
   Mobile navigation drawer.
   -------------------------------------------------------------------------- */

/* Bootstrap focuses the .offcanvas panel itself when it opens. That is a
   programmatic focus on a tabindex="-1" container, but Chrome still matches
   :focus-visible, so the global focus ring painted a teal outline down the
   whole drawer. Rings belong on controls the user actually lands on. */
.offcanvas:focus,
.offcanvas:focus-visible,
.modal:focus-visible,
main[tabindex]:focus,
[tabindex="-1"]:focus-visible {
  outline: none !important;
}

/* Keep it for the skip-link target, which is a deliberate destination. */
main#main-content:focus-visible {
  outline: 3px solid var(--color-primary-text) !important;
  outline-offset: -3px !important;
}

/* Above lg the .offcanvas element is not a drawer at all - Bootstrap flattens
   it into the inline navbar - so its panel styling has to stay scoped to the
   widths where it actually slides in. */
@media (max-width: 991.98px) {
  .offcanvas {
    border-right: none !important;
    box-shadow: 0 0 40px rgba(6, 20, 24, 0.18) !important;
  }

  .offcanvas-header {
    padding: 1rem 1.25rem !important;
    border-bottom: 1px solid var(--color-border) !important;
  }

  .offcanvas-body {
    padding: 0.75rem 1.25rem 1.5rem !important;
  }
}

/* A weak scrim let the page behind stay fully readable, so the drawer never
   read as the foreground layer. */
.offcanvas-backdrop.show {
  opacity: 0.6 !important;
}

/* The navbar toggler swaps to a close icon while the drawer is open, which put
   a second, competing close button on the backdrop beside the drawer's own. */
body.offcanvas-active .fbs__net-navbar-toggler {
  display: none !important;
}

/* Bootstrap's scroll lock adds inline padding-right on <body> sized to the
   removed scrollbar, so it can compensate on desktop. On touch viewports that
   scrollbar is 0-width (or the browser reports one anyway), so the padding
   shoved every fixed-position and static element 15px left the instant the
   drawer opened, then snapped back on close - the "glitch" on mobile. */
body.offcanvas-active {
  padding-right: 0 !important;
}

.offcanvas .btn-close {
  width: 44px;
  height: 44px;
  margin: 0 !important;
  padding: 0 !important;
  border-radius: 50%;
  opacity: 0.7;
}

.offcanvas .btn-close:hover {
  opacity: 1;
  background-color: var(--color-bg-light);
}

/* Drawer nav items: full-width rows with real breathing room, rather than
   inline pills inherited from the desktop bar. */
@media (max-width: 991.98px) {
  .offcanvas .navbar-nav > li > .nav-link {
    padding: 0.75rem 0.875rem !important;
    border-radius: 10px !important;
    width: 100%;
    justify-content: space-between;
  }

  .offcanvas .navbar-nav > .nav-item {
    margin-bottom: 0.125rem;
  }

  /* The submenu's accent link lost its colour to the item rule above it. */
  .fbs__net-navbar .navbar-nav .dropdown-menu .dropdown-item.text-primary {
    color: var(--color-primary-text) !important;
    font-weight: 600 !important;
  }

  .offcanvas .nav-item.d-lg-none {
    margin-top: 1.25rem !important;
    padding-top: 1.25rem !important;
  }
}

/* --------------------------------------------------------------------------
   Buttons inside the navbar list.
   onepage.css paints every anchor in the bar with the bar's own inverse colour
   at .fbs__net-navbar.dark ul li a — (0,2,3) and !important, so it beat the
   variant's own colour. In the drawer that inverse colour is dark slate, and
   it landed on the primary CTA's teal fill at 1.9:1: the label was drawn, just
   not readable. A button carries its colour with its variant, so hand it back.
   -------------------------------------------------------------------------- */
.fbs__net-navbar ul li a.btn-primary,
.fbs__net-navbar.dark ul li a.btn-primary {
  color: #ffffff !important;
}

.fbs__net-navbar ul li a.btn-outline-success,
.fbs__net-navbar.dark ul li a.btn-outline-success {
  color: #146c43 !important;              /* 4.9:1 on white */
  border-color: #146c43 !important;
}

.fbs__net-navbar ul li a.btn-outline-success:hover,
.fbs__net-navbar.dark ul li a.btn-outline-success:hover {
  color: #ffffff !important;
  background-color: #146c43 !important;
}

/* Applies at every width: the accent item in the services submenu. */
.fbs__net-navbar .navbar-nav .dropdown-menu .dropdown-item.text-primary {
  color: var(--color-primary-text) !important;
  font-weight: 600 !important;
}

/* ==========================================================================
   11. SECTION PROSE
   ==========================================================================
   The About block styled its running copy with card classes: .card-desc for
   the paragraphs (15px, meant for a card body) and .card-meta for the
   checklist (13px, meant for dates and captions). Against a 33px heading that
   produced three unrelated sizes in one column, with the list reading as a
   footnote rather than as content. Section prose gets its own step. */

.section-prose {
  font-size: var(--fs-base) !important;  /* 16px - body, a step under the 17px lead */
  line-height: 1.7 !important;
  color: var(--color-body) !important;
  /* Inter's zero glyph is ~0.63em, so ch overstates the character count:
     60ch lands near 72 characters of running text. */
  max-width: 60ch;
}

.section-prose p {
  margin-bottom: 1.125rem;
}

.section-prose p:last-child {
  margin-bottom: 0;
}

/* Rich text from the editor renders <strong> at the browser default black,
   which jumped hard against the slate body around it. */
.section-prose strong,
.section-prose b {
  color: var(--color-headings);
  font-weight: 700;
}

/* Checklists in a section are content, not metadata. */
.section-list {
  max-width: 60ch;
}

.section-list > li {
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  color: var(--color-body);
}

.section-list > li + li {
  margin-top: 0.625rem;
}

.section-list .bi {
  font-size: 1.05rem;
  line-height: 1.5;
}

/* --------------------------------------------------------------------------
   Inline contact block (icon + label + number).
   gap-2 gave 8px between a 24px glyph and a two-line stack, so the icon sat
   almost against the label.
   -------------------------------------------------------------------------- */
.inline-contact {
  display: flex;
  align-items: center;
  gap: 0.875rem;
}

.inline-contact .inline-contact-icon {
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: 50%;
  background-color: rgba(13, 198, 193, 0.12);
  color: var(--color-primary-text);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.15rem;
}

.inline-contact .inline-contact-label {
  display: block;
  font-size: var(--fs-xs);
  color: var(--color-muted);
  line-height: 1.4;
  margin-bottom: 2px;
}

.inline-contact .inline-contact-value {
  font-size: var(--fs-base);
  font-weight: 700;
  color: var(--color-headings);
  line-height: 1.3;
  white-space: nowrap;
}

/* The CTA row that holds the button and the contact block. */
.about-cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.25rem 2rem;
  margin-top: 2rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--color-border);
}

/* Pull quotes sit inside a large card but are the point of that card, so they
   step up from the card body size rather than sharing it. */
.testimonial-quote {
  font-size: var(--fs-lg) !important;
  line-height: var(--lh-loose) !important;
  color: var(--color-body) !important;
}

/* Scale utilities, so markup can name a step instead of reaching for a
   Bootstrap fs-* utility that lands between steps (20px, 24px, 28px). */
.text-step-xl  { font-size: var(--fs-xl) !important; }   /* 18 */
.text-step-2xl { font-size: var(--fs-2xl) !important; }  /* 22 */

/* Band heading: a compact statement strip, so it sits a step below a full
   section title rather than on the Bootstrap .h3 default of 28px. */
.band-title {
  font-size: clamp(1.375rem, 2vw, 1.625rem) !important;  /* 22 - 26 */
  line-height: var(--lh-snug) !important;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

/* Footer column headings. They are h2: the footer's landmarks sit directly
   under the page h1, and on a listing page with no other section heading an
   h3 here made every page skip a level. */
.footer h2,
.footer h3 {
  font-size: var(--fs-xl) !important;
  letter-spacing: -0.005em;
}

/* --------------------------------------------------------------------------
   Long-form rich text (service detail, article detail).
   The editor emits bare <p>, <h3>, <ul>, so these ran at browser defaults:
   28px headings against 16px body, on an 89-character measure.
   -------------------------------------------------------------------------- */
.service-content {
  font-size: var(--fs-lg);
  line-height: var(--lh-loose);
  color: var(--color-body);
  max-width: 60ch;
}

.service-content > *:first-child {
  margin-top: 0;
}

.service-content p {
  margin-bottom: 1.125rem;
}

.service-content h2,
.service-content h3,
.service-content h4,
.service-content h5,
.service-content h6 {
  font-size: var(--fs-2xl);
  font-weight: 700;
  line-height: var(--lh-snug);
  letter-spacing: -0.012em;
  color: var(--color-headings);
  /* More space above than below, so a heading binds to the text it introduces. */
  margin-top: 2.25rem;
  margin-bottom: 0.75rem;
}

.service-content h4,
.service-content h5,
.service-content h6 {
  font-size: var(--fs-xl);
  margin-top: 1.75rem;
}

.service-content ul,
.service-content ol {
  margin-bottom: 1.25rem;
  padding-left: 1.35rem;
}

.service-content li {
  margin-bottom: 0.5rem;
}

.service-content li:last-child {
  margin-bottom: 0;
}

.service-content strong,
.service-content b {
  color: var(--color-headings);
}

.service-content img {
  max-width: 100%;
  height: auto;
  border-radius: 12px;
  margin: 1.5rem 0;
}

/* Sidebar panel headings sit a step below the page title, on the scale. */
.col-lg-4 .aia-card h2,
.col-lg-4 .aia-card h3 {
  font-size: var(--fs-xl) !important;
}

/* The floating action stack is fixed to the bottom-right, so at the end of the
   page it sat on top of the footer's last row and made the "Kontak" link
   unreachable. Reserve room for it below the credits. */
@media (max-width: 991.98px) {
  .footer {
    padding-bottom: calc(var(--space-footer-bottom) + 4.5rem) !important;
  }
}

/* ==========================================================================
   12. HEADING-TO-CONTENT RHYTHM
   ==========================================================================
   Same rule everywhere: the space under a heading belongs to the heading's
   role, not to whichever utility class the template happened to carry. Each
   relationship below was measured inconsistent across pages. */

/* Subpage banner: a 38px h1 sat 8px above its lead, the same too-tight gap the
   section titles had. Scaled to match the section rhythm. */
.page-header-banner h1 {
  margin-bottom: 1.25rem !important;
}

/* The breadcrumb is a kicker above the title, so it stays tight. */
.page-header-banner .breadcrumb {
  margin-bottom: 0.625rem !important;
}

/* Card titles: a default rather than a forced value. Some titles are one half
   of a tight pair - a testimonial name above its role - and carry mb-0 on
   purpose, so an !important here would wrongly push those apart. */
.aia-card .card-title {
  margin-bottom: 0.5rem;
}

/* Panel headings inside sidebar cards: heading, rule, then content. */
.aia-card > h2,
.aia-card > h3,
.aia-card > .card-title + .card-desc {
  margin-bottom: 0.75rem;
}

/* Footer column heading to its list. */
.footer h2,
.footer h3 {
  margin-bottom: 1rem !important;
}

/* ==========================================================================
   13. PAGE HEADER BANNER
   ==========================================================================
   Text on the dark banner all used Bootstrap's .text-white-50, which is a flat
   50% white regardless of role: the lead paragraph, the byline and the date all
   sat at the same washed-out weight, and the lead read as disabled rather than
   as supporting copy. Split by role instead. */

.page-header-banner .banner-meta {
  color: rgba(255, 255, 255, 0.72);
  font-size: var(--fs-sm);
}

.page-header-banner .banner-meta .bi {
  color: var(--color-primary);
}

.page-header-banner .lead,
.page-header-banner .text-white-50 {
  color: rgba(255, 255, 255, 0.78) !important;
}

/* Breadcrumb: the trail is secondary, the current page is the accent. */
.page-header-banner .breadcrumb-item a {
  color: rgba(255, 255, 255, 0.72);
  text-decoration: none;
}

.page-header-banner .breadcrumb-item a:hover {
  color: #ffffff;
  text-decoration: underline;
}

.page-header-banner .breadcrumb-item.active {
  color: #5fe0dc;
}

/* Rhythm inside the banner: the breadcrumb and byline form one eyebrow group
   above the title, so they bind tightly to each other and loosely to it. */
.page-header-banner .breadcrumb {
  margin-bottom: 0.75rem !important;
}

.page-header-banner .banner-meta {
  margin-bottom: 1rem !important;
}

.page-header-banner h1 {
  margin-bottom: 1.25rem !important;
}

.page-header-banner .lead {
  margin-bottom: 0 !important;
}

/* Banner headline runs the full container width. text-wrap: balance evens the
   line lengths, which on a long title pulls it into a narrow block, so the
   banner uses pretty instead: it only prevents a short last line. */
.page-header-banner h1 {
  max-width: none;
  text-wrap: pretty;
}

@media (min-width: 992px) {
  .page-header-banner .breadcrumb {
    flex-wrap: nowrap;
    max-width: 100%;
  }
}

/* Below lg a three-level trail with a long article title breaks across lines
   and reads as broken rather than as a path. The current page is stated by the
   h1 immediately below, so the trail stops at the parent. */
@media (max-width: 991.98px) {
  /* Only collapse a trail deep enough to break: at three or more levels the
     current item is a long title that wraps. A two-level trail would be left
     showing nothing but "Beranda", so it keeps its current item. */
  .page-header-banner .breadcrumb-item.active:nth-child(n+3) {
    display: none !important;
  }

  .page-header-banner .breadcrumb {
    flex-wrap: wrap;
    row-gap: 0.25rem;
  }
}

.page-header-banner .breadcrumb-item.active {
  min-width: 0;
}

/* Banner CTA sits beneath the lead, aligned to the same left edge, rather than
   in a side column that collided with the full-width headline. */
.page-header-banner .banner-cta {
  margin-top: 1.5rem;
}

@media (max-width: 991.98px) {
  .page-header-banner .banner-cta {
    margin-top: 1.25rem;
    text-align: center;
  }
}

/* ==========================================================================
   14. ICON BUTTONS
   ==========================================================================
   A .rounded-circle only draws a circle when the box is square. On a .btn it
   never is: onepage.css sets .btn { padding: 10px 25px }, so the horizontal
   padding pushes the width past whatever inline size the markup asked for,
   and the .btn-sm min-height pins the height independently. The share button
   asked for 36x36 and rendered 52x44.

   Squaring is enforced here rather than left to inline styles, so any future
   icon button is round by construction. */
.btn.rounded-circle,
.rounded-circle.d-flex,
.rounded-circle.d-inline-flex {
  padding: 0 !important;
  aspect-ratio: 1 / 1;
  flex-shrink: 0;
}

/* Interactive circles also have to clear the 44px touch minimum; decorative
   ones (icon tiles, avatars) keep whatever size the markup gave them. */
a.rounded-circle,
button.rounded-circle,
.btn.rounded-circle {
  min-width: 44px;
  min-height: 44px;
}

/* Centre the glyph now that the padding is gone. */
.btn.rounded-circle > .bi,
.rounded-circle.d-flex > .bi,
.rounded-circle.d-inline-flex > .bi {
  line-height: 1;
}

/* ==========================================================================
   15. CAROUSEL COUNTER
   ==========================================================================
   onepage.css gives .slide-count a fixed 100px width, but the flex row inside
   it has no justification, so "1 / 5" (36px) packed to the left edge and sat
   32px off the centre between the two arrow buttons. */
.testimonials__v7 .slide-count,
.slide-count {
  justify-content: center;
  /* Tabular figures so the box does not jump when 9 becomes 10. */
  font-variant-numeric: tabular-nums;
}

.slide-count #current-slide,
.slide-count #total-slides {
  min-width: 1ch;
  text-align: center;
}

/* ==========================================================================
   16. CERTIFICATE SEARCH CARD
   ==========================================================================
   The one thing this page exists to do sat in a cramped box: a 24px heading on
   an 8px gap to a 14px subtitle, an 8px gutter between the field and its
   submit, and 8px to the helper line. Everything here is one step looser, and
   the field itself gets the presence of a primary action. */

.cert-search-box {
  padding: 2.5rem !important;
}

.cert-search-title {
  font-size: var(--fs-2xl) !important;   /* 22px, on the scale; was 24 */
  line-height: var(--lh-snug);
  margin-bottom: 0.625rem !important;
}

.cert-search-sub {
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  color: var(--color-muted);
  max-width: 52ch;
  margin: 0 auto 2rem;
}

.cert-search-row {
  gap: 0.75rem;
}

.cert-search-box .form-control {
  min-height: 52px;
  font-size: var(--fs-base) !important;
}

.cert-search-box .btn {
  min-height: 52px;
  padding-inline: 1.75rem !important;
}

.cert-search-box .form-text {
  margin-top: 0.75rem;
  font-size: var(--fs-sm);
}

/* Breathing room between the search card and the guidance panel below it. */
.cert-search-box {
  margin-bottom: 2rem !important;
}

@media (max-width: 767.98px) {
  .cert-search-box {
    padding: 1.75rem 1.25rem !important;
  }
  .cert-search-sub {
    margin-bottom: 1.5rem;
  }
}

/* ==========================================================================
   17. CERTIFICATE RESULT CARD
   ==========================================================================
   The result panel sits directly under the search card and reads as its
   answer, so it is the same object: same white card, same border, same
   radius, no accent stripe down the side and no extra elevation. Status is
   carried by the icon and the pill, which is where a reader looks anyway.

   Its type runs one step under the search card above it: 18px title, 16px
   values, 14px labels, so the three levels are told apart by size rather
   than by weight alone. */

.cert-result {
  padding: 1.75rem !important;
}

.cert-result-head {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1.25rem;
  padding-bottom: 1.125rem;
  border-bottom: 1px solid var(--color-border);
}

/* The revoked card has running copy under the head, not a table, so it closes
   with space rather than a rule. */
.cert-result-head-plain {
  border-bottom: none;
  padding-bottom: 0;
  margin-bottom: 1rem;
}

.cert-result-icon {
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.25rem;
  line-height: 1;
}

.cert-result-heading {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.375rem;
}

/* A status pill is a label, not a sentence: it reads at a glance and the
   heading beside it already says what was found. */
.cert-result-badge {
  font-size: var(--fs-2xs) !important;
  font-weight: 700;
  letter-spacing: 0.02em;
  padding: 0.25rem 0.625rem !important;
  line-height: 1.2;
}

.cert-result-title {
  font-size: var(--fs-xl) !important;   /* 18px, one step under the search card */
  line-height: var(--lh-snug);
  font-weight: 700;
  color: var(--color-headings);
  margin: 0;
}

.cert-result-note {
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  color: var(--color-body);
  max-width: 60ch;
}

/* --------------------------------------------------------------------------
   Data rows.
   The label column was a 38% share of the card, which parked the values in
   the middle with a lake of white between the two. It is now sized to its own
   longest label, so the pair reads as one line.
   -------------------------------------------------------------------------- */
.cert-result-table th,
.cert-result-table td {
  padding: 0.625rem 0 !important;
  line-height: var(--lh-snug);
  vertical-align: middle;
  background-color: transparent;
}

.cert-result-table th {
  width: 1%;
  white-space: nowrap;
  padding-right: 2rem !important;
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--color-muted);
}

.cert-result-table td {
  font-size: var(--fs-base);
  color: var(--color-body);
}

/* The rule belongs between rows, so the last one closes flush with the card's
   own padding instead of leaving a stranded line. */
.cert-result-table tr + tr th,
.cert-result-table tr + tr td {
  border-top: 1px solid var(--color-border);
}

.cert-result-number {
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--color-primary-text);
  background-color: rgba(13, 198, 193, 0.1);
  padding: 0.1875rem 0.5rem;
  border-radius: 6px;
  word-break: break-all;
}

@media (max-width: 575.98px) {
  .cert-result {
    padding: 1.25rem !important;
  }

  .cert-result-head {
    gap: 0.875rem;
    margin-bottom: 1rem;
    padding-bottom: 1rem;
  }

  /* Two columns put both sides on two or three lines each; stacking the label
     over its value keeps every value on one. */
  .cert-result-table th,
  .cert-result-table td {
    display: block;
    width: auto;
    white-space: normal;
    padding-right: 0 !important;
  }

  .cert-result-table th {
    padding-bottom: 0.125rem !important;
  }

  .cert-result-table td {
    padding-top: 0 !important;
    padding-bottom: 0.875rem !important;
  }

  .cert-result-table tr + tr th {
    padding-top: 0.875rem !important;
    border-top: 1px solid var(--color-border);
  }

  .cert-result-table tr + tr td {
    border-top: none;
  }

  .cert-result-table tr:last-child td {
    padding-bottom: 0 !important;
  }
}

/* ==========================================================================
   18. MOBILE TYPE SCALE
   ==========================================================================
   The type scale was written once for the desktop column and reused verbatim
   at 390px, where the same steps read very differently: a 17px lead beside an
   18px card title is a distinction you can measure but not see, and 17px prose
   on a 350px column runs about 40 characters a line, which turns every
   paragraph into a wall. Below 576px the middle of the scale steps down one
   notch and the display sizes tighten, so the ladder stays legible:

     32/26/18/17/16/15  ->  30/24/17/16/15/14

   Only the tokens move; components keep referring to the same names. */

@media (max-width: 575.98px) {
  :root {
    --fs-lg:  1rem;        /* 17 -> 16  leads, prose, pull quotes */
    --fs-xl:  1.0625rem;   /* 18 -> 17  card titles, footer headings */
    --fs-2xl: 1.25rem;     /* 22 -> 20  minor headings */

    --fs-h1:      1.875rem;   /* 32 -> 30 */
    --fs-h1-page: 1.75rem;    /* 30 -> 28 */
    --fs-h2:      1.5rem;     /* 26 -> 24 */
    --fs-stat:    1.75rem;    /* 32 -> 28 */
  }
}

/* --------------------------------------------------------------------------
   Bootstrap's .fs-* utilities are RFS: they resolve to calc(1.275rem + 0.3vw)
   and friends, so a .fs-4 heading measured 21.6px at 390px and 25.9px at
   1440 — a size that belongs to no step of the scale and drifts with the
   viewport. Map them onto the scale so markup can keep using them.
   -------------------------------------------------------------------------- */
.fs-2 { font-size: var(--fs-h2) !important; }
.fs-3 { font-size: var(--fs-2xl) !important; }
.fs-4 { font-size: var(--fs-2xl) !important; }
.fs-5 { font-size: var(--fs-xl) !important; }
.fs-6 { font-size: var(--fs-base) !important; }

/* Eyebrow above a section: a heading semantically, a label visually. */
.section-eyebrow {
  font-size: var(--fs-xs) !important;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-muted);
}

/* The theme hardcoded 13.5px here, the one size on the site that belonged to
   no step. */
.footer .credits,
.footer .credits a {
  font-size: var(--fs-xs) !important;
}

/* The date chip's day number was 1.6rem (25.6px), landing between the 22px
   minor heading and the 26px section title. */
.schedule-date-chip .day {
  font-size: var(--fs-2xl) !important;
}

/* Drawer CTAs: the theme's 25px button padding left "Hubungi via WhatsApp"
   wrapping to two lines in a 285px drawer. */
@media (max-width: 991.98px) {
  .offcanvas .nav-item .btn {
    font-size: var(--fs-md) !important;
    padding-inline: 1rem !important;
    /* .btn-primary carried a 44px floor, the outline variant did not, so the
       WhatsApp CTA sat at 40px — under the touch minimum. */
    min-height: 44px !important;
  }
}

/* Two sizes the theme fixed in px sat outside the scale on mobile: the accent
   band's heading (a clamp whose floor was the desktop 22px) and the FAQ
   question (a flat 18px in onepage.css). Both are minor headings. */
@media (max-width: 575.98px) {
  .band-title {
    font-size: var(--fs-2xl) !important;
  }

  .faq__v3 .custom-accordion .accordion-item .accordion-header .accordion-button,
  .accordion-button {
    font-size: var(--fs-xl) !important;
  }
}

/* ==========================================================================
   19. SCHEDULE CARD HEAD
   ==========================================================================
   The head packed four different things into two rows: a tag and the venue
   shared a line above the title, then the date range sat below it. So the
   place was read before the thing being scheduled, the two 13px metadata
   lines were split either side of the heading, and at 390px the venue wrapped
   into the tag. Now it runs tag -> title -> date and place together, which is
   also the order someone reads a listing in: what, then when and where. */

.schedule-head {
  display: flex;
  align-items: flex-start;
  gap: 1.125rem;
  margin-bottom: 0.25rem;
}

.schedule-head-body {
  flex: 1 1 auto;
  min-width: 0;
}

.schedule-tag {
  font-size: var(--fs-2xs) !important;
  font-weight: 700;
  letter-spacing: 0.02em;
  padding: 0.3125rem 0.625rem !important;
  margin-bottom: 0.625rem;
}

.schedule-title {
  font-size: var(--fs-xl) !important;
  font-weight: 700;
  line-height: var(--lh-snug);
  color: var(--color-headings);
  margin: 0 0 1rem;
}

/* Date and venue are the same kind of fact, so they share a size, a colour and
   a left edge: one per row under the title. Side by side, the venue trailed
   off to the right of the date with nothing holding it there. */
.schedule-meta {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.schedule-meta > li {
  display: flex;
  align-items: baseline;
  gap: 0.4375rem;
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--color-muted);
  min-width: 0;
}

.schedule-meta .bi {
  color: var(--color-primary-text);
  font-size: 0.9375rem;
  flex-shrink: 0;
}

/* The description sits inside the title column, on the same left edge as the
   title and the meta rows. Running it the full card width put its first line
   under the date chip, so the block it belonged to changed shape halfway
   down. */
.schedule-desc {
  font-size: var(--fs-md);
  line-height: var(--lh-body);
  color: var(--color-body);
  margin: 0.875rem 0 0;
}

@media (max-width: 575.98px) {
  .schedule-head {
    gap: 0.875rem;
  }

  .schedule-date-chip {
    width: 60px;
  }
}

/* ==========================================================================
   20. BUTTON ICON AND LABEL
   ==========================================================================
   The gap between a button's icon and its label was set by whatever utility
   the markup happened to carry: me-1 (4px), me-2 (8px), gap-1, gap-2, or a
   literal space in the HTML. Same component, five different gaps, and the 4px
   ones read as one glued-together shape. It is a property of the button, so
   the button sets it: every .btn is a centred flex row with one gap, and icon
   margins inside are neutralised. */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  /* The 44px touch floor lived on .btn-primary only, so the outline variants
     came out at 42px. It belongs to every button. */
  min-height: 44px;
}

/* One gap at every size. A smaller button does not want a tighter pair — it
   wants the same relationship at a smaller scale, and 4px on a .btn-sm read as
   the icon touching its label. */

/* me-1 / me-2 / ms-1 on an icon inside a button would add to the gap. */
.btn > .bi {
  margin: 0 !important;
  line-height: 1;
  flex-shrink: 0;
}

/* An icon should sit slightly under the cap height of its label, not match it;
   at 1em the glyphs looked heavier than the text beside them. */
.btn > .bi:not([class*="fs-"]) {
  font-size: 1.05em;
}

/* Icon-only controls have no label to sit beside. */
.btn.rounded-circle {
  gap: 0;
}

/* Optical correction. The 8px gap is measured between glyph boxes, and most
   Bootstrap Icons keep a little side bearing inside theirs. bi-person-plus
   does not: its plus sign runs out to the right edge of the box, so the same
   8px reads as about 5 against the label. 3px back gives it the gap the other
   icons already appear to have. */
.btn > .bi.bi-person-plus,
.btn > .bi.bi-person-plus-fill {
  margin-inline-end: 0.1875rem !important;
}

/* ==========================================================================
   21. PAGINATION
   ==========================================================================
   The paginator was the last place Bootstrap's default blue survived: square
   joined boxes, #0d6efd on the current page, and a 33px hit area. It now uses
   the same pill shape, teal, and 44px touch floor as every other control. */

.pagination {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin-bottom: 0;
  flex-wrap: wrap;
}

/* The count sentence sits beside the list; its paragraph margin pushed the
   two out of line even inside an align-items-center row. */
nav:has(.pagination) p {
  margin-bottom: 0;
}

/* The count and the list are a justify-content-between pair, which gives them
   no space of their own once the row is centred rather than full width. */
nav .d-sm-flex:has(.pagination) {
  gap: 1.5rem;
  flex-wrap: wrap;
}

.page-link {
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 0.75rem;
  border: 1px solid var(--color-border);
  border-radius: 50rem;
  color: var(--color-primary-text);
  background-color: #ffffff;
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1;
  transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.page-link:hover,
.page-link:focus {
  background-color: rgba(13, 198, 193, 0.12);
  border-color: var(--color-primary);
  color: var(--color-primary-text-hover);
}

.page-link:focus-visible {
  outline: 2px solid var(--color-primary-text);
  outline-offset: 2px;
  box-shadow: none;
}

.page-item.active .page-link {
  background-color: var(--color-primary-text);
  border-color: var(--color-primary-text);
  color: #ffffff;
}

/* Disabled arrows are still announced, so they keep their shape and only lose
   contrast enough to read as unavailable. */
.page-item.disabled .page-link {
  background-color: var(--color-bg-light);
  border-color: var(--color-border);
  color: var(--color-muted);
  opacity: 1;
}

/* Below sm the paginator swaps to a Previous / Next pair, which are word
   labels rather than single glyphs. */
@media (max-width: 575.98px) {
  .d-sm-none .page-link {
    padding: 0 1rem;
  }
}

/* ==========================================================================
   Contact form captcha status icon
   main.css is not loaded on this build, so the captcha field styles live here.
   ========================================================================== */
.captcha-input {
  padding-right: 2.5rem;
}

.captcha-status-icon {
  position: absolute;
  top: 50%;
  right: 0.875rem;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
  line-height: 1;
  pointer-events: none;
}

.captcha-status-icon .bi {
  display: block;
  font-size: inherit;
  line-height: 1;
}

.captcha-status-icon.captcha-status--valid {
  color: #198754;
}

.captcha-status-icon.captcha-status--invalid {
  color: #dc3545;
}

.captcha-status-icon.captcha-status--checking {
  color: #6b7280;
}

.footer {
  background: rgb(146 157 174 / 13%);
}