  :root {
    /* ---- Design tokens: single source of truth for the whole site.
       Every other stylesheet should reference these instead of
       hardcoding hex values -- that's what let the same brand color
       drift into ~10 different literal hex codes across pages. ---- */

    /* Brand */
    --brand-primary: #f4aa24;    /* golden orange */
    --brand-hover: #ffb938;
    --brand-active: #e89b1f;
    --brand-gradient: linear-gradient(135deg, var(--brand-primary), var(--brand-hover));

    /* Text */
    --text-primary: #333333;
    --text-dark: #2b2b2b;
    --text-darkest: #1a1a1a;
    /* Was #6c757d (Bootstrap's stock gray) -- measured 4.30:1 on
       --bg-light and 4.69:1 on white, both under WCAG AA's 4.5:1 floor
       for normal text. Darkened just enough to clear it (5.7-6.2:1) while
       staying visually "muted" relative to --text-primary. */
    --text-muted: #5a6268;

    /* Neutral scale (backgrounds, borders, placeholders) */
    --gray-50: #f9fafb;
    --gray-100: #f3f4f6;
    --gray-200: #e5e7eb;
    --gray-300: #d1d5db;
    --gray-400: #9ca3af;
    --gray-500: #6c6c6c;
    --gray-border: #dadada;

    /* Status */
    --status-online: #22c55e;
    --status-offline: #9ca3af;

    /* Surfaces */
    --bg-light: #f5f5f5;
    --bg-white: #ffffff;

    /* Radii */
    --radius-sm: .5rem;
    --radius-md: .75rem;
    --radius-lg: 1rem;
    --radius-xl: 1.25rem;
    --radius-pill: 999px;

    /* Shadows */
    --shadow-card: 0 2px 8px rgba(0, 0, 0, 0.06);
    --shadow-card-hover: 0 10px 24px rgba(0, 0, 0, 0.12);
    --shadow-brand-sm: 0 4px 10px rgba(244, 170, 36, 0.35);
    --shadow-brand-md: 0 8px 20px rgba(244, 170, 36, 0.45);

    /* Bootstrap variable overrides -- keep these aliased to the brand
       tokens above so Bootstrap's own components (buttons, focus rings,
       etc.) stay in sync automatically. */
    --bs-primary: var(--brand-primary);
    --bs-body-bg: var(--bg-light);
    --bs-body-color: var(--text-primary);
  }

  body {
    font-family: "Nunito", sans-serif;
    background-color: var(--bs-body-bg);
    color: var(--bs-body-color);
  }

  h1,
  h2,
  h3,
  h4,
  .brand-text {
    font-family: "Outfit", sans-serif !important;
  }

  main .container {
    max-width: 1100px;
  }

  /* NAVBAR: more see-through "glass" */
  .navbar {
    background-color: rgba(245, 245, 245, 0.08) !important; /* very transparent */
    border-bottom: 1px solid rgba(255, 255, 255, 0.35);
    /* Above every page-level sticky bar, and not on the same level as
       them (Bootstrap's .sticky-top is 1020, .fixed-top is 1030 -- this
       is chrome, so it takes the chrome number).

       Not cosmetic. .sticky-top makes the navbar a *stacking context*, so
       the mobile menu inside it (#navbarMain, .offcanvas, z-index 1045)
       can never paint above whatever the navbar itself outranks -- 1045
       is measured inside this box, not against the page. With the navbar
       at 1020 that put the open menu level with every other .sticky-top
       on the site, and a tie is broken by document order: the settings
       page's section nav (.settings-nav-wrap, also 1020) comes later, so
       on a phone its pills rendered *through* the open menu. Anything
       that has to sit above the menu (the consent banner, the settings
       save toast) is at 1080 and still does. */
    z-index: 1030;
  }

  /* The blur sits on a pseudo-element instead of on .navbar itself.
     backdrop-filter makes an element a containing block for its
     fixed-position descendants, and the mobile menu (.mm-offcanvas) is a
     descendant: while closed it's translated 100% to the right, so being
     anchored to the navbar instead of the viewport made it add its own
     width to the document's scroll width. Every page could then be
     swiped sideways on a phone. The pseudo-element has no positioned
     descendants of its own, so the same glass effect costs nothing. */
  .navbar::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;              /* behind the navbar's own content */
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    pointer-events: none;
  }

  /* Brand: no pill, just logo + text */
  .navbar-brand-custom {
    padding: 0;
    margin-right: 1.6rem;
    background: transparent;
    border-radius: 0;
    box-shadow: none;
  }

  /* Bigger logo */
  .mm-logo-icon {
    width: 46px;
    height: 46px;
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.35));
  }

  .brand-text {
    font-family: "Quicksand", sans-serif !important;
    font-weight: 600;
    font-size: 1.35rem;
    color: var(--text-darkest); /* near-black for softer, playful look */
    letter-spacing: 0.4px;
    text-shadow:
      0 0 1px rgba(255, 255, 255, 0.4),
      0 1px 2px rgba(255, 255, 255, 0.35); /* subtle highlight for contrast */
    transition: transform 0.18s ease;
  }

  .brand-text:hover {
    transform: scale(1.03);
  }

  /* Toggler visibility/contrast */
  .navbar.navbar-dark .navbar-toggler {
    border: 0;
  }

  .navbar.navbar-dark .navbar-toggler-icon {
    filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.3));
  }

  /* Smaller logo on phones */
  @media (max-width: 575.98px) {
    .mm-logo-icon {
      width: 38px;
      height: 38px;
    }
  }

  /* Offcanvas (mobile menu) stays white */
  .mm-offcanvas {
    background: var(--bg-white);
  }
/* Ensure the mobile offcanvas always uses full viewport height */
@media (max-width: 991.98px) {
  .mm-offcanvas {
    position: fixed;        /* reinforce Bootstrap’s behavior */
    top: 0;
    bottom: 0;
    /* vh is the *large* viewport -- it measures the screen as if the
       mobile browser's toolbar were hidden. The comment here said
       "dynamic viewport", but that unit is dvh; with vh the panel is
       taller than what the phone shows and its last entries sit behind
       the browser chrome. vh stays as the fallback for browsers without
       dvh, which is what this already was. */
    height: 100vh;
    height: 100dvh;
    max-height: 100vh;
    max-height: 100dvh;
    overflow-y: auto;
  }
}

  .mm-offcanvas .nav-link {
    color: var(--text-primary);
    padding: 0.8rem 0;
    font-size: 1.05rem;
  }

  .mm-offcanvas .nav-link:hover,
  .mm-offcanvas .nav-link.active {
    background: var(--gray-100);
    border-radius: var(--radius-md);
    color: #000 !important;
  }

  .navbar .nav-underline .nav-link {
  margin: 0 0.35rem;
  padding: 0.35rem 1.1rem;
  border-radius: var(--radius-pill);
  background-color: var(--brand-primary);
  color: var(--text-dark);
  border-bottom: none;
  box-shadow: none;
  opacity: 0.96;
  transition: box-shadow 0.22s ease, transform 0.18s ease,
              background-color 0.18s ease, opacity 0.15s ease, color 0.15s ease;
}

/* Was a blurred "glow" (0 0 Npx, no offset) on hover/active -- a dated
   effect regardless of color. Same brand gold, just a normal soft
   elevation shadow instead, matching how .btn-auth-login already reads
   as a confident, not gaudy, brand-colored control. */
.navbar .nav-underline .nav-link:hover {
  background-color: var(--brand-hover);
  box-shadow: var(--shadow-brand-sm);
  transform: translateY(-1px);
  opacity: 1;
}

.navbar .nav-underline .nav-link.active {
  background-color: var(--brand-active);
  box-shadow: var(--shadow-brand-sm);
  opacity: 1;
  color: var(--text-darkest);
}


    /* If you have a logout button in navbar */
    .navbar .btn-logout {
      --bs-btn-color: var(--text-primary);
      --bs-btn-bg: var(--brand-primary);
      --bs-btn-border-color: transparent;
      --bs-btn-hover-bg: var(--brand-hover);
      --bs-btn-hover-border-color: transparent;
      --bs-btn-active-bg: var(--brand-active);
      --bs-btn-active-border-color: transparent;
      box-shadow: var(--shadow-brand-md);
    }

  /* Slider handle */
  .noUi-handle {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: #ffc107;
    border: 2px solid #fff;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
    top: -10px;
  }

  .noUi-handle:hover {
    background: #e0a800;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4);
  }

  .noUi-handle:after {
    display: block;
    color: #fff;
    font-size: 14px;
    line-height: 24px;
    text-align: center;
  }

  /* Auth buttons (login / register) */
  .btn-auth-login,
  .btn-auth-register {
    border-radius: var(--radius-pill);
    font-weight: 600;
    padding: 0.45rem 1.4rem;
    font-size: 0.9rem;
    border-width: 0;
    transition:
      transform 0.15s ease,
      box-shadow 0.18s ease,
      background-color 0.18s ease,
      color 0.18s ease;
  }

  /* Login = primary yellow pill */
  .btn-auth-login {
    background: var(--brand-gradient);
    color: var(--text-darkest);
    box-shadow: var(--shadow-brand-md);
  }

  .btn-auth-login:hover {
    background: linear-gradient(135deg, var(--brand-hover), #ffc95c);
    transform: translateY(-1px);
    box-shadow: 0 10px 26px rgba(244, 170, 36, 0.55);
    color: #111;
  }

  .btn-auth-login:active {
    transform: translateY(0);
    box-shadow: 0 4px 10px rgba(244, 170, 36, 0.4);
  }

  /* Register = light / outlined pill */
  .btn-auth-register {
    background: rgba(255, 255, 255, 0.9);
    color: var(--text-primary);
    border: 1px solid rgba(244, 170, 36, 0.9);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  }

  .btn-auth-register:hover {
    background: #fffaf0;
    color: #222;
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
  }

  .btn-auth-register:active {
    transform: translateY(0);
    box-shadow: 0 3px 8px rgba(0, 0, 0, 0.1);
  }

  /* Mobile navbar toggler -- was a blurred golden "glow" box-shadow on
     hover/focus (dated regardless of color) with outline:none and no
     real replacement focus indicator. Same brand gold, a normal soft
     shadow, and a visible focus outline for keyboard users. */
  @media (max-width: 991.98px) {
    .navbar.navbar-dark .navbar-toggler {
      border-radius: var(--radius-pill);
      border: 0;
      padding: 0.35rem 0.55rem;
      background-color: var(--brand-primary);
      box-shadow: var(--shadow-brand-sm);
      transition:
        box-shadow 0.2s ease,
        transform 0.15s ease,
        background-color 0.15s ease;
    }

    .navbar.navbar-dark .navbar-toggler:hover {
      background-color: var(--brand-hover);
      box-shadow: var(--shadow-brand-md);
      transform: scale(1.03);
    }

    .navbar.navbar-dark .navbar-toggler:focus-visible {
      outline: 2px solid var(--text-darkest);
      outline-offset: 2px;
    }

    .navbar.navbar-dark .navbar-toggler-icon {
      filter: drop-shadow(0 0 2px rgba(0, 0, 0, 0.6));
    }
  }
.zoomable-image {
  cursor: zoom-in;
}

#imageZoomModal .modal-dialog {
  max-width: 100vw;
  margin: 0;
}

#imageZoomModal .modal-content {
  background-color: transparent;  /* no background box at all */
  border: none;
  box-shadow: none;
}

#imageZoomModal .modal-body {
  min-height: 100vh;  /* center vertically in viewport */
}

/* Image: max 90% of viewport width/height */
#imageZoomModalImg {
  max-width: 90vw;
  max-height: 90vh;
  width: auto;
  height: auto;
  display: block;
}

#imageZoomModal .btn-close {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  background-color: #ffffff;
  opacity: 1;                    /* always fully visible */
  padding: 0;                    /* center the icon nicely */
  box-shadow: 0 0 8px rgba(0, 0, 0, 0.5);
}

/* Make sure the X stays black */
#imageZoomModal .btn-close {
  filter: none;  /* remove Bootstrap's default white filter */
}

/* Slight hover effect (optional) */
#imageZoomModal .btn-close:hover {
  transform: scale(1.05);
}
:root {
  scrollbar-gutter: stable;
}

/* ==========================================================================
   Shared brand button system -- see DESIGN_GUIDE.md section 2.
   Three roles, all pill-shaped, all built from the tokens above:
     .btn-brand                 primary action (solid gradient)
     .btn-brand-outline         secondary action (outlined)
     .btn-brand-outline-danger  action that warrants a pause (outlined, danger)
   Use these instead of stock Bootstrap btn-warning/btn-dark/btn-outline-dark
   for anything that's "the brand's" call to action on a page -- that mix is
   what caused profile_detail.html to look like a different button system
   than home.html/chat_list.html.
   ========================================================================== */
.btn-brand,
.btn-primary-pill {
  background: var(--brand-gradient);
  color: var(--text-dark);
  border-radius: var(--radius-pill);
  border: none;
  padding: 0.4rem 1.15rem;
  font-weight: 600;
  box-shadow: var(--shadow-brand-sm);
  transition: transform 0.15s ease, box-shadow 0.18s ease, background-color 0.18s ease;
}

.btn-brand:hover,
.btn-primary-pill:hover {
  background: linear-gradient(135deg, var(--brand-hover), #ffc95c);
  color: var(--text-darkest);
  box-shadow: 0 6px 16px rgba(244, 170, 36, 0.45);
  transform: translateY(-1px);
}

.btn-brand:active,
.btn-primary-pill:active {
  background: var(--brand-active);
  box-shadow: 0 3px 8px rgba(244, 170, 36, 0.4);
  transform: translateY(0);
}

.btn-brand-outline {
  background: rgba(255, 255, 255, 0.9);
  color: var(--text-primary);
  border: 1px solid rgba(244, 170, 36, 0.9);
  border-radius: var(--radius-pill);
  padding: 0.4rem 1.15rem;
  font-weight: 600;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  transition: transform 0.15s ease, box-shadow 0.18s ease, background-color 0.18s ease;
}

.btn-brand-outline:hover {
  background: #fffaf0;
  color: #222;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
  transform: translateY(-1px);
}

.btn-brand-outline-danger {
  background: #fff;
  color: #dc3545;
  border: 1px solid #dc3545;
  border-radius: var(--radius-pill);
  padding: 0.4rem 1.15rem;
  font-weight: 600;
  transition: transform 0.15s ease, box-shadow 0.18s ease, background-color 0.18s ease, color 0.18s ease;
}

.btn-brand-outline-danger:hover {
  background: #dc3545;
  color: #fff;
  box-shadow: 0 6px 16px rgba(220, 53, 69, 0.35);
  transform: translateY(-1px);
}

/* Small shared utilities -- pulled out of repeated inline style="" blocks
   per DESIGN_GUIDE.md rule 1 (base.css is the source of truth, not a
   one-off inline style next to it). */
.line-clamp-3 {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.icon-circle-32 {
  width: 32px;
  height: 32px;
}

/* Lets a flex item shrink below the width of its own content, which is
   what makes .text-truncate inside one actually truncate instead of
   pushing the row off the side of the screen. A flex item defaults to
   min-width:auto, and max-width:100% doesn't help -- the floor is the
   min-width, not the max.

   Four templates were already asking for this class (chat_list,
   notifications, blocked_profiles) on the reasonable assumption that
   Bootstrap ships it. It doesn't: 5.3 has max-width utilities (.mw-100)
   and viewport ones (.min-vw-100), but no min-width scale. So every one
   of those was a no-op, and the layouts they were meant to hold together
   overflowed on narrow screens. */
.min-w-0 {
  min-width: 0;
}

/* ==========================================================================
   Unread-message badge in the navbar
   ========================================================================== */
/* Inline rather than absolutely positioned over the link: the nav is an
   offcanvas list below lg and an inline row above it, and a badge pinned
   to a corner only lands correctly in one of those. */
.nav-unread-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.25rem;
  height: 1.25rem;
  margin-left: .35rem;
  padding: 0 .35rem;
  border-radius: var(--radius-pill);
  background: var(--brand-primary);
  color: var(--text-dark);
  font-size: .7rem;
  font-weight: 700;
  line-height: 1;
  vertical-align: middle;
}

/* ==========================================================================
   Site-wide announcement banner (templates/base.html)
   ========================================================================== */
/* Colours come from Bootstrap's .alert-{level}, which is the whole reason
   Announcement.Level's stored values are Bootstrap's own suffixes -- so
   adding a level never means adding CSS here. This block only handles the
   parts an .alert doesn't: the leading icon's optical alignment against
   the title, and keeping a long body readable. */
.site-announcement-icon {
  flex-shrink: 0;
  /* Sits on the title's baseline rather than the box's top edge, which on
     a two-line announcement floats it above the text it belongs to. */
  margin-top: .15rem;
  font-size: 1.1rem;
}

/* The body keeps .alert-{level}'s inherited text colour: that colour is
   tuned for contrast against its own tinted background, and muting it
   further -- the reflex for secondary text -- would put it under the AA
   floor. The weight drop is what separates it from the title instead. */
.site-announcement-body {
  font-size: .925rem;
  font-weight: 400;
  /* An announcement is prose, not a label: unbounded line length across a
     desktop container is the difference between one people read and one
     they dismiss unread. */
  max-width: 70ch;
}
