/* ============================================================
   Utilities
   Single-purpose helper classes, kept under the Bootstrap 5.3
   names the ERB views already use. Every declaration carries
   !important, as Bootstrap's did: these are last-word overrides
   on top of components.

   Order matters twice over. Within this layer specificity is
   uniform, so a later rule wins: the bg-opacity classes sit
   after the bg-* classes, and every responsive variant sits in
   the trailing breakpoint blocks, after its base class.
   ============================================================ */

@layer utilities {
  /* ----------------------------------------------------------
     Spacing
     Bootstrap's scale: 0 = 0, 1 = .25rem, 2 = .5rem, 3 = 1rem,
     4 = 1.5rem, 5 = 3rem — the --space-* tokens one for one.
     ---------------------------------------------------------- */

  .m-0 { margin: 0 !important; }

  .mb-0 { margin-bottom: 0 !important; }
  .mb-1 { margin-bottom: var(--space-1) !important; }
  .mb-2 { margin-bottom: var(--space-2) !important; }
  .mb-3 { margin-bottom: var(--space-3) !important; }
  .mb-4 { margin-bottom: var(--space-4) !important; }

  .mt-2 { margin-top: var(--space-2) !important; }
  .mt-3 { margin-top: var(--space-3) !important; }
  .mt-4 { margin-top: var(--space-4) !important; }

  .me-1 { margin-right: var(--space-1) !important; }
  .me-2 { margin-right: var(--space-2) !important; }

  .ms-auto { margin-left: auto !important; }

  .mx-auto {
    margin-right: auto !important;
    margin-left: auto !important;
  }

  .my-auto {
    margin-top: auto !important;
    margin-bottom: auto !important;
  }

  .my-4 {
    margin-top: var(--space-4) !important;
    margin-bottom: var(--space-4) !important;
  }

  .p-0 { padding: 0 !important; }
  .p-3 { padding: var(--space-3) !important; }
  .p-4 { padding: var(--space-4) !important; }
  .p-5 { padding: var(--space-5) !important; }

  .px-0 {
    padding-right: 0 !important;
    padding-left: 0 !important;
  }

  .px-3 {
    padding-right: var(--space-3) !important;
    padding-left: var(--space-3) !important;
  }

  .px-4 {
    padding-right: var(--space-4) !important;
    padding-left: var(--space-4) !important;
  }

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

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

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

  .ps-0 { padding-left: 0 !important; }
  .ps-3 { padding-left: var(--space-3) !important; }

  /* ----------------------------------------------------------
     Display and flexbox
     ---------------------------------------------------------- */

  .d-flex { display: flex !important; }
  .d-block { display: block !important; }
  .d-none { display: none !important; }
  .d-grid { display: grid !important; }
  .d-inline-flex { display: inline-flex !important; }

  .flex-column { flex-direction: column !important; }
  .flex-wrap { flex-wrap: wrap !important; }
  .flex-fill { flex: 1 1 auto !important; }
  .flex-shrink-0 { flex-shrink: 0 !important; }
  .flex-grow-1 { flex-grow: 1 !important; }

  .align-items-center { align-items: center !important; }
  .align-items-start { align-items: flex-start !important; }
  .align-items-baseline { align-items: baseline !important; }

  .justify-content-center { justify-content: center !important; }
  .justify-content-between { justify-content: space-between !important; }
  .justify-content-end { justify-content: flex-end !important; }

  .gap-2 { gap: var(--space-2) !important; }
  .gap-3 { gap: var(--space-3) !important; }

  /* ----------------------------------------------------------
     Typography
     ---------------------------------------------------------- */

  /* em, not rem: .small shrinks relative to its own context. */
  .small { font-size: 0.875em; }

  .text-center { text-align: center !important; }
  .text-start { text-align: left !important; }
  .text-uppercase { text-transform: uppercase !important; }
  .text-nowrap { white-space: nowrap !important; }
  .text-decoration-none { text-decoration: none !important; }

  .text-truncate {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .text-primary { color: var(--color-primary) !important; }
  .text-dark { color: var(--color-dark) !important; }
  .text-danger { color: var(--color-danger) !important; }
  .text-body { color: var(--color-body) !important; }
  .text-success { color: var(--color-success) !important; }
  .text-warning { color: var(--color-warning) !important; }

  /* Paired fore/background: black on the light violet secondary. */
  .text-bg-secondary {
    color: #000 !important;
    background-color: color-mix(in srgb, var(--color-secondary) calc(var(--bg-opacity, 1) * 100%), transparent) !important;
  }

  .fw-bold { font-weight: 700 !important; }
  .fw-semibold { font-weight: 600 !important; }
  .fw-medium { font-weight: 500 !important; }
  .fst-italic { font-style: italic !important; }

  .lh-base { line-height: var(--line-height) !important; }

  /* fs-1 through fs-4 are fluid below 1200px — the viewport term
     grows them with the window, then they settle at a fixed size.
     fs-5 never scaled in Bootstrap, so it is a flat value. */
  .fs-1 {
    font-size: calc(1.375rem + 1.5vw) !important;

    @media (min-width: 1200px) { font-size: 2.5rem !important; }
  }

  .fs-2 {
    font-size: calc(1.325rem + 0.9vw) !important;

    @media (min-width: 1200px) { font-size: 2rem !important; }
  }

  .fs-3 {
    font-size: calc(1.3rem + 0.6vw) !important;

    @media (min-width: 1200px) { font-size: 1.75rem !important; }
  }

  .fs-4 {
    font-size: calc(1.275rem + 0.3vw) !important;

    @media (min-width: 1200px) { font-size: 1.5rem !important; }
  }

  .fs-5 { font-size: 1.25rem !important; }

  /* ----------------------------------------------------------
     Sizing, borders, surfaces
     ---------------------------------------------------------- */

  .w-100 { width: 100% !important; }
  .h-100 { height: 100% !important; }

  .rounded { border-radius: var(--radius) !important; }
  .rounded-3 { border-radius: var(--radius-lg) !important; }
  .rounded-circle { border-radius: 50% !important; }
  .rounded-pill { border-radius: var(--radius-pill) !important; }

  .border { border: 1px solid var(--color-border) !important; }
  .border-0 { border: 0 !important; }

  .shadow-sm { box-shadow: var(--shadow-sm) !important; }

  .align-middle { vertical-align: middle !important; }

  .position-relative { position: relative !important; }

  .sticky-top {
    position: sticky;
    top: 0;
    z-index: 1020;
  }

  /* Backgrounds.
     Each one mixes its colour with `transparent` by --bg-opacity,
     which is how `class="bg-primary bg-opacity-10"` works: the
     bg-* class sets the colour and a default opacity of 1, and a
     bg-opacity-* class — declared below, so it wins at equal
     specificity — swaps that number out. color-mix() in srgb
     against transparent is a plain alpha multiply, so 10% of the
     token is exactly rgb(token / 0.1). */
  .bg-primary {
    --bg-opacity: 1;
    background-color: color-mix(in srgb, var(--color-primary) calc(var(--bg-opacity) * 100%), transparent) !important;
  }

  .bg-success {
    --bg-opacity: 1;
    background-color: color-mix(in srgb, var(--color-success) calc(var(--bg-opacity) * 100%), transparent) !important;
  }

  .bg-warning {
    --bg-opacity: 1;
    background-color: color-mix(in srgb, var(--color-warning) calc(var(--bg-opacity) * 100%), transparent) !important;
  }

  .bg-white {
    --bg-opacity: 1;
    background-color: color-mix(in srgb, #fff calc(var(--bg-opacity) * 100%), transparent) !important;
  }

  .bg-body-secondary {
    --bg-opacity: 1;
    background-color: color-mix(in srgb, #e9ecef calc(var(--bg-opacity) * 100%), transparent) !important;
  }

  .bg-transparent {
    --bg-opacity: 1;
    background-color: transparent !important;
  }

  /* Must stay after the bg-* rules above to override their 1. */
  .bg-opacity-10 { --bg-opacity: 0.1; }
  .bg-opacity-50 { --bg-opacity: 0.5; }

  /* ----------------------------------------------------------
     Accessibility
     Off-screen for sighted users, still read by screen readers:
     a 1px clipped box rather than display:none, which would drop
     the element from the accessibility tree entirely.
     ---------------------------------------------------------- */

  .visually-hidden {
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    white-space: nowrap !important;
    border: 0 !important;

    /* <caption> must stay in flow to keep its table association. */
    &:not(caption) { position: absolute !important; }

    * { overflow: hidden !important; }
  }

  /* ----------------------------------------------------------
     Responsive variants
     Min-width breakpoints: sm 576px, md 768px, lg 992px. These
     come last so each one outranks the base class it refines.
     ---------------------------------------------------------- */

  @media (min-width: 576px) {
    .flex-sm-row { flex-direction: row !important; }
    .align-items-sm-center { align-items: center !important; }
  }

  @media (min-width: 768px) {
    .d-md-inline { display: inline !important; }
    .p-md-4 { padding: var(--space-4) !important; }
    .p-md-5 { padding: var(--space-5) !important; }
  }

  @media (min-width: 992px) {
    .d-lg-block { display: block !important; }
    .mb-lg-2 { margin-bottom: var(--space-2) !important; }
  }
}
