/*--------------------------------------------------------------
# Bootstrap "primary" -> site accent colour
--------------------------------------------------------------
This site's real brand colour is --accent-color (a deep navy, #102799 --
see static/assets/css/main.css): every plain link, the nav hover state
and the hero/CTA buttons already use it. Bootstrap's own "primary"
utilities (badges, buttons, search/filter/pagination/accordion "active"
states) key off a *separate*, unrelated --bs-primary token that stays at
Bootstrap's stock #0d6efd unless remapped -- so every primary badge/button
used to render in a different, off-brand blue right next to the theme's
own navy links.

Originally added as research/templates/research/includes/_accent_theme.html,
opted into individually by the publication/lab pages -- that comment
already flagged this as "worth promoting into static/css/custom.css
site-wide later". The student app needs the same remap for its own
Bootstrap tabs/badges/accordion, which is exactly that second consumer,
so it's promoted here instead of being copy-pasted into a second
per-page include. Every page gets this automatically (custom.css is
already loaded site-wide in base.html); the research include still works
too, it just re-declares the same values.

Most Bootstrap utilities (badges, borders, .accordion-button,
.pagination) already read their colour through --bs-primary-* custom
properties, so overriding those here re-themes them everywhere with no
class changes in the page markup. .btn-primary/.btn-outline-primary and
the form focus ring are the exception: this Bootstrap build compiles
those with literal hex values instead of var(--bs-primary), so they get
their own small override below, using the same "redeclare the
component's own custom properties" technique as .history-card below
rather than fighting Bootstrap's specificity by hand.
--------------------------------------------------------------*/
:root {
  --bs-primary: var(--accent-color, #102799);
  --bs-primary-rgb: 16, 39, 153;
  --bs-primary-text-emphasis: color-mix(in srgb, var(--accent-color), black 60%);
  --bs-primary-bg-subtle: color-mix(in srgb, var(--accent-color), white 80%);
  --bs-primary-border-subtle: color-mix(in srgb, var(--accent-color), white 60%);
  --bs-link-color: var(--accent-color, #102799);
  --bs-link-color-rgb: 16, 39, 153;
  --bs-link-hover-color: color-mix(in srgb, var(--accent-color), black 15%);
  --bs-link-hover-color-rgb: 14, 33, 130;
  --bs-pagination-active-bg: var(--accent-color, #102799);
  --bs-pagination-active-border-color: var(--accent-color, #102799);
  --bs-accordion-btn-focus-box-shadow: 0 0 0 .25rem rgba(16, 39, 153, .25);
  /* .link-body-emphasis defaults to pure black; align it with this
     theme's own heading colour instead. */
  --bs-emphasis-color: var(--heading-color, #172624);
  --bs-emphasis-color-rgb: 23, 38, 36;

  /* Neutral text: Bootstrap's near-black defaults (--bs-body-color etc.,
     derived from #212529/#000) -> this theme's own softer greys
     (--default-color #444 / --heading-color). Same promotion as above --
     originally only on the Projects & Research pages via
     _theme_overrides.html, brought site-wide so ".text-muted",
     ".text-body-secondary", ".link-body-emphasis" etc. read as one grey
     family everywhere instead of two competing ones. Mix ratios (not
     Bootstrap's own formula) chosen to keep "muted" text at roughly 6:1
     contrast on white -- comfortably above the 4.5:1 AA minimum -- rather
     than fading it out. */
  --bs-body-color: var(--default-color, #444444);
  --bs-body-color-rgb: 68, 68, 68;
  --bs-secondary-color: color-mix(in srgb, var(--default-color, #444444), transparent 12%);
  --bs-tertiary-color: color-mix(in srgb, var(--default-color, #444444), transparent 32%);
}

/* .text-bg-light hard-codes color:#000 regardless of background in
   Bootstrap's compiled CSS -- forced back to the same muted grey as
   .text-muted so a light badge/pill doesn't read pure black next to
   everything else on the page. */
.text-bg-light {
  color: var(--bs-secondary-color) !important;
}

.btn-primary {
  --bs-btn-bg: var(--accent-color, #102799);
  --bs-btn-border-color: var(--accent-color, #102799);
  --bs-btn-hover-bg: color-mix(in srgb, var(--accent-color), black 15%);
  --bs-btn-hover-border-color: color-mix(in srgb, var(--accent-color), black 20%);
  --bs-btn-active-bg: color-mix(in srgb, var(--accent-color), black 20%);
  --bs-btn-active-border-color: color-mix(in srgb, var(--accent-color), black 25%);
  --bs-btn-focus-shadow-rgb: 52, 71, 168;
  --bs-btn-disabled-bg: var(--accent-color, #102799);
  --bs-btn-disabled-border-color: var(--accent-color, #102799);
}

.btn-outline-primary {
  --bs-btn-color: var(--accent-color, #102799);
  --bs-btn-border-color: var(--accent-color, #102799);
  --bs-btn-hover-bg: var(--accent-color, #102799);
  --bs-btn-hover-border-color: var(--accent-color, #102799);
  --bs-btn-active-bg: var(--accent-color, #102799);
  --bs-btn-active-border-color: var(--accent-color, #102799);
  --bs-btn-focus-shadow-rgb: 16, 39, 153;
  --bs-btn-disabled-color: var(--accent-color, #102799);
  --bs-btn-disabled-border-color: var(--accent-color, #102799);
}

/* Bootstrap compiles the form-control/select focus ring to a literal
   rgba(13,110,253,...) rather than a variable, so it needs a direct
   override too -- same soft-glow treatment, recoloured. */
.form-control:focus,
.form-select:focus {
  border-color: color-mix(in srgb, var(--accent-color), white 45%);
  box-shadow: 0 0 0 .25rem color-mix(in srgb, var(--accent-color), transparent 75%);
}

/*--------------------------------------------------------------
# Hover-outline card/image (History page and reusable elsewhere)
--------------------------------------------------------------*/
/* For plain elements (e.g. .image-container, which isn't a Bootstrap
   component): a transparent border that lights up in the site's accent
   color on hover/focus, plus a soft matching glow and lift. Bootstrap's
   reboot already puts every element in border-box sizing, so the border
   never shifts layout on hover. */
.history-hover-outline {
  border: 2px solid transparent;
  border-radius: var(--bs-border-radius-lg, 0.5rem);
  transition: border-color 0.3s ease, box-shadow 0.3s ease, transform 0.3s ease;
}

.history-hover-outline:hover,
.history-hover-outline:focus-within {
  border-color: var(--accent-color);
  box-shadow: 0 1rem 2rem color-mix(in srgb, var(--accent-color), transparent 85%);
  transform: translateY(-4px);
}

/* For an actual Bootstrap .card: override its own --bs-card-* custom
   properties instead (the Bootstrap 5.3 way to reskin a component without
   touching Sass or fighting its own border shorthand with !important) --
   .card already draws its border *from* --bs-card-border-color, so setting
   a plain `border` alongside it would just fight that declaration. */
.history-card {
  --bs-card-border-color: transparent;
  --bs-card-border-width: 2px;
  background-color: var(--surface-color, #fff);
  transition: box-shadow 0.3s ease, transform 0.3s ease;
}

.history-card:hover,
.history-card:focus-within {
  --bs-card-border-color: var(--accent-color);
  box-shadow: 0 1rem 2rem color-mix(in srgb, var(--accent-color), transparent 85%);
  transform: translateY(-4px);
}

/*--------------------------------------------------------------
# History Section – redesigned layout (history_page.html)
--------------------------------------------------------------*/

/* ── Outer section spacing ── */
.history-section {
  padding: 60px 0;
}

/* ── Row: stretch children to equal height ── */
.history-main-row {
  display: flex;
  flex-wrap: wrap;
  border-radius: 1rem;
  overflow: hidden;
  box-shadow: 0 20px 60px color-mix(in srgb, var(--default-color), transparent 88%);
}

/* ── Image column ── */
.history-image-col {
  display: flex;
}

.history-image-wrapper {
  position: relative;
  width: 100%;
  min-height: 420px;
  overflow: hidden;
  /* override the history-hover-outline border-radius so corners stay inside row */
  border-radius: 0;
}

/* The image fills its wrapper completely */
.history-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
  transition: transform 0.55s ease;
}

.history-image-wrapper:hover .history-img {
  transform: scale(1.04);
}

/* Gradient dark scrim at the bottom of the image */
.history-image-wrapper::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    transparent 50%,
    color-mix(in srgb, var(--accent-color), black 60%) 100%
  );
  pointer-events: none;
}

/* ── Badge overlay (mortarboard + code/name) ── */
.history-img-badge {
  position: absolute;
  bottom: 28px;
  left: 28px;
  z-index: 2;
  background: color-mix(in srgb, var(--surface-color), transparent 10%);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid color-mix(in srgb, var(--accent-color), transparent 70%);
  border-radius: 0.75rem;
  padding: 14px 18px;
  box-shadow: 0 4px 20px color-mix(in srgb, var(--default-color), transparent 80%);
}

.history-img-badge .badge-inner {
  display: flex;
  align-items: center;
  gap: 12px;
}

.history-img-badge .bi {
  font-size: 1.75rem;
  color: var(--accent-color);
  flex-shrink: 0;
}

.history-img-badge .badge-text {
  display: flex;
  flex-direction: column;
  line-height: 1.3;
}

.history-img-badge .badge-code {
  font-size: 1rem;
  font-weight: 700;
  color: var(--heading-color);
  letter-spacing: 0.5px;
}

.history-img-badge .badge-name {
  font-size: 0.78rem;
  color: color-mix(in srgb, var(--default-color), transparent 20%);
}

/* ── Vertical accent bar on the right edge of the image ── */
.history-img-accent-bar {
  position: absolute;
  top: 0;
  right: 0;
  width: 5px;
  height: 100%;
  background: linear-gradient(
    to bottom,
    var(--accent-color),
    color-mix(in srgb, var(--accent-color), transparent 60%)
  );
  z-index: 2;
}

/* ── Content column ── */
.history-content-col {
  display: flex;
}

.history-content-card {
  background-color: var(--surface-color, #fff);
  display: flex;
  flex-direction: column;
  width: 100%;
}

.history-content-inner {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: 48px 44px;
  /* Make inner content fill height so CTA anchors to bottom */
  height: 100%;
}

/* ── "Our Story" kicker label ── */
.history-section-label {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 18px;
}

.history-label-line {
  display: block;
  width: 36px;
  height: 3px;
  border-radius: 2px;
  background: var(--accent-color);
  flex-shrink: 0;
}

.history-label-text {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--accent-color);
}

/* ── Main heading ── */
.history-title {
  font-size: clamp(1.5rem, 2.5vw, 2rem);
  font-weight: 700;
  color: var(--heading-color);
  margin-bottom: 0;
  line-height: 1.2;
}

/* ── Short decorative underline beneath the title ── */
.history-title-underline {
  width: 56px;
  height: 4px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--accent-color), color-mix(in srgb, var(--accent-color), transparent 50%));
  margin-top: 14px;
  margin-bottom: 28px;
}

/* ── Rich-text body ── */
.history-body-text {
  flex: 1;
  overflow-y: auto;
  color: color-mix(in srgb, var(--default-color), transparent 10%);
  line-height: 1.8;
  font-size: 0.97rem;
  /* Subtle custom scrollbar */
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--accent-color), transparent 50%) transparent;
  /* Max height so very long histories stay tidy */
  max-height: 340px;
  padding-right: 6px;
}

.history-body-text::-webkit-scrollbar {
  width: 4px;
}

.history-body-text::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--accent-color), transparent 50%);
  border-radius: 4px;
}

.history-body-text p:first-child {
  margin-top: 0;
}

.history-body-text p:last-child {
  margin-bottom: 0;
}

/* ── Placeholder text ── */
.history-placeholder {
  flex: 1;
  color: color-mix(in srgb, var(--default-color), transparent 35%);
  font-style: italic;
  font-size: 1rem;
}

/* ── CTA link ── */
.history-cta {
  margin-top: 32px;
  padding-top: 24px;
  border-top: 1px solid color-mix(in srgb, var(--default-color), transparent 88%);
}

.history-cta-link {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--accent-color);
  text-decoration: none;
  transition: gap 0.25s ease, opacity 0.25s ease;
}

.history-cta-link:hover {
  gap: 16px;
  opacity: 0.85;
  color: var(--accent-color);
}

.history-cta-link i {
  font-size: 1.25rem;
  transition: transform 0.25s ease;
}

.history-cta-link:hover i {
  transform: translateX(4px);
}

/* ── Responsive ── */
@media (max-width: 991.98px) {
  .history-main-row {
    border-radius: 0.75rem;
  }

  .history-image-wrapper {
    min-height: 300px;
    /* On mobile, image is on top so turn off right accent bar */
    border-right: none;
  }

  .history-img-accent-bar {
    display: none;
  }

  .history-content-inner {
    padding: 36px 28px;
  }

  .history-body-text {
    max-height: 280px;
  }
}

@media (max-width: 575.98px) {
  .history-section {
    padding: 40px 0;
  }

  .history-content-inner {
    padding: 28px 20px;
  }

  .history-img-badge {
    bottom: 16px;
    left: 16px;
    padding: 10px 14px;
  }

  .history-img-badge .bi {
    font-size: 1.4rem;
  }
}


/*--------------------------------------------------------------
# News cards (.news-card) -- shared by the homepage "Recent Blog
# Posts" teaser (home_news.html) and the news detail page's
# "Related News" grid (news_det_page.html)
--------------------------------------------------------------
Originally scoped to `.recent-blog-posts .card`, so it only
existed on the homepage teaser. news_det_page.html's related-news
section reuses the exact same card markup (.card.news-card, plus
.news-card-main/-compact for the size variant), so the base look
now hangs off `.news-card` itself instead of a section ancestor --
same rules, usable from any section.

home_news.html context: home/models.py now sends two separate
context vars -- `main_news` (the NewsDetPage with is_main=True,
falling back to the single latest one if no page has been flagged
main yet) and `news` (the latest 3 *other* articles, is_main
excluded). Editorial "banner + grid" layout: main_news renders full
width as a horizontal split card (.news-card-main -- image one
side, title/intro/meta the other), and the 3 others sit below it as
an equal-height 3-up grid of .news-card-compact cards -- no more
flex-column sidebar list, so there's no asymmetric column-height
matching to fight with.
--------------------------------------------------------------*/
.section-kicker {
  display: block;
  margin-bottom: 0.5rem;
  color: var(--accent-color);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 1.5px;
  text-transform: uppercase;
}

.news-card {
  border: none;
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
  transition: transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
  overflow: hidden;
  height: 100%;
  background-color: var(--surface-color);
}

.news-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 15px 35px color-mix(in srgb, var(--default-color), transparent 85%);
}

.news-card .card-img-wrapper {
  position: relative;
  display: block;
  overflow: hidden;
}

.news-card .card-img-wrapper img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.3s ease-in-out;
}

.news-card:hover .card-img-wrapper img {
  transform: scale(1.1);
}

.news-card .card-body {
  padding: 1.5rem;
}

.news-card .card-body .card-title {
  font-size: 1.25rem;
  margin-bottom: 0.75rem;
  color: var(--heading-color);
  font-weight: 600;
}

.news-card .card-body .card-title a {
  color: inherit;
}

.news-card .card-body .card-title a:hover {
  color: var(--accent-color);
}

.news-card .card-body .card-text {
  font-size: 0.9rem;
  color: color-mix(in srgb, var(--default-color), transparent 25%);
}

/* Shared meta row: date, view count, and (compact cards only) a
   plain-text category label */
.news-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.9rem;
  margin-bottom: 0.6rem;
  font-size: 0.85rem;
  color: color-mix(in srgb, var(--default-color), transparent 35%);
}

.news-date i,
.news-author i,
.news-views i {
  margin-right: 0.3rem;
  color: var(--accent-color);
}

.news-cat-text {
  font-weight: 700;
  font-size: 0.75rem;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--accent-color);
}

.news-cat-text + .news-date::before {
  content: "•";
  margin-right: 0.9rem;
  opacity: 0.5;
}

/* Main story (is_main=True): a full-width horizontal split card --
   image fills one side, title/intro/meta sit in the other -- rather
   than a tall stacked image-then-text card, so a full-width card
   still reads as one wide banner instead of a very tall block.
   Stacks back to image-on-top below the `md` breakpoint. */
.news-card-main {
  display: flex;
  flex-direction: row;
  align-items: stretch;
  min-height: 400px;
}

.news-card-main .card-img-wrapper {
  width: 55%;
  flex-shrink: 0;
}

.news-card-main .card-body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 45%;
  padding: 2.5rem 3rem;
}

.news-card-main .card-body .card-title {
  font-size: 1.85rem;
  line-height: 1.25;
  margin-bottom: 1rem;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
}

.news-card-main .card-body .card-text {
  font-size: 1rem;
  line-height: 1.7;
  margin-bottom: 1.25rem;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 4;
  overflow: hidden;
}

@media (max-width: 767.98px) {
  .news-card-main {
    flex-direction: column;
    min-height: 0;
  }

  .news-card-main .card-img-wrapper,
  .news-card-main .card-body {
    width: 100%;
  }

  .news-card-main .card-img-wrapper {
    aspect-ratio: 16 / 9;
  }

  .news-card-main .card-body {
    padding: 1.75rem;
  }

  .news-card-main .card-body .card-title {
    font-size: 1.4rem;
  }
}

.news-cat-badge {
  position: absolute;
  top: 16px;
  left: 16px;
  padding: 0.35rem 0.9rem;
  border-radius: 999px;
  background-color: var(--accent-color);
  color: var(--contrast-color);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  box-shadow: 0 6px 16px color-mix(in srgb, var(--accent-color), transparent 60%);
}

.news-readmore {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: auto;
  color: var(--accent-color);
  font-weight: 600;
  font-size: 0.95rem;
}

.news-readmore i {
  transition: transform 0.25s ease;
}

.news-card-main:hover .news-readmore i {
  transform: translateX(4px);
}

/* Secondary story cards: the latest 3 articles (main_news excluded),
   laid out as an equal-height 3-up grid below the main story
   (home_news.html's `.row.row-cols-lg-3` wraps each in a `.col`,
   with `h-100` on the card itself so Bootstrap's default flex
   `align-items: stretch` makes all 3 match the tallest one's
   height -- safe here since the 3 siblings share the same card
   type/column width/content shape, unlike the old design's lone
   compact card being force-stretched to match an unrelated, much
   taller featured column). Also reused as-is by news_det_page.html's
   3-up related-news CSS grid further below, where the browser's
   default grid stretch achieves the same equal-height effect
   without needing `h-100`. `height: auto` here is what that second,
   h-100-less usage relies on to size by its own content. */
.news-card-compact {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  height: auto;
}

.news-card-compact .card-img-wrapper {
  width: 100%;
  aspect-ratio: 16 / 9;
}

.news-card-compact .card-body {
  padding: 1rem 1.1rem;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.news-card-compact .news-meta {
  margin-bottom: 0.35rem;
  font-size: 0.75rem;
}

.news-card-compact .card-body .card-title {
  font-size: 1.05rem;
  margin-bottom: 0.4rem;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

.news-card-compact .card-body .card-text {
  font-size: 0.85rem;
  line-height: 1.5;
  margin-bottom: 0.6rem;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

.news-card-compact .news-footer {
  min-width: 0;
  margin-top: auto;
  font-size: 0.8rem;
  color: color-mix(in srgb, var(--default-color), transparent 35%);
}

.news-card-compact .news-author {
  min-width: 0;
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.news-card-compact .news-views {
  flex-shrink: 0;
}

/* "View all news" CTA + empty state */
.news-view-all-wrap {
  text-align: center;
  margin-top: 2.5rem;
}

.news-view-all {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.7rem 1.75rem;
  border: 2px solid var(--accent-color);
  border-radius: 999px;
  color: var(--accent-color);
  font-weight: 600;
  transition: background-color 0.25s ease, color 0.25s ease;
}

.news-view-all i {
  transition: transform 0.25s ease;
}

.news-view-all:hover {
  background-color: var(--accent-color);
  color: var(--contrast-color);
}

.news-view-all:hover i {
  transform: translateX(4px);
}

.news-empty {
  padding: 3.5rem 1rem;
  text-align: center;
  color: color-mix(in srgb, var(--default-color), transparent 35%);
}

.news-empty i {
  display: block;
  margin-bottom: 1rem;
  font-size: 2.5rem;
  color: color-mix(in srgb, var(--accent-color), transparent 60%);
}

/*--------------------------------------------------------------
# Announcements list (home_info.html)
--------------------------------------------------------------
AnnDetPage has no image field (unlike NewsDetPage), so this can't
reuse .news-card's thumbnail layout. Instead each row gets the
same accent-filled "day/month" date badge already established for
.blog-posts .meta .post-date, just promoted into its own class so
a plain Bootstrap .card can use it without a .blog-posts ancestor.
--------------------------------------------------------------*/
.ann-card {
  background-color: var(--surface-color);
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.ann-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 15px 35px color-mix(in srgb, var(--default-color), transparent 88%) !important;
}

.ann-date {
  width: 64px;
  padding: 0.6rem 0.4rem;
  background-color: var(--accent-color);
  color: var(--contrast-color);
  line-height: 1.1;
}

.ann-date-day {
  font-size: 1.5rem;
  font-weight: 700;
}

.ann-date-month {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.5px;
}

/* Flex children default to a content-based min-width, which stops
   long titles/excerpts from wrapping and pushes the row wider than
   its card instead -- this is the one thing Bootstrap's own flex
   utilities can't express. */
.ann-content {
  min-width: 0;
}

.ann-title a {
  color: var(--heading-color);
}

.ann-card:hover .ann-title a {
  color: var(--accent-color);
}

.ann-excerpt {
  font-size: 0.95rem;
  line-height: 1.7;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

.ann-arrow {
  color: var(--accent-color);
  font-size: 1.1rem;
  transition: transform 0.25s ease;
}

.ann-card:hover .ann-arrow {
  transform: translateX(4px);
}

@media (max-width: 576px) {
  .ann-date {
    width: 52px;
    padding: 0.45rem 0.3rem;
  }

  .ann-date-day {
    font-size: 1.15rem;
  }
}

/*--------------------------------------------------------------
# Announcement detail page (ann_det_page.html)
--------------------------------------------------------------*/
.ann-detail-card {
  background-color: var(--surface-color);
}

.ann-detail-date i {
  color: var(--accent-color);
  margin-right: 0.25rem;
}

/* Bootstrap's reboot doesn't opinionate paragraph/heading/list rhythm
   inside arbitrary rich text, so the CMS-authored body gets its own
   typography scale here -- same muted-body colour and relaxed
   line-height already used for .faq-item's .content-inner p. */
.ann-detail-body {
  color: color-mix(in srgb, var(--default-color), transparent 15%);
  font-size: 1.05rem;
  line-height: 1.85;
}

.ann-detail-body > *:last-child {
  margin-bottom: 0;
}

.ann-detail-body p {
  margin-bottom: 1.25rem;
}

.ann-detail-body h1,
.ann-detail-body h2,
.ann-detail-body h3,
.ann-detail-body h4,
.ann-detail-body h5,
.ann-detail-body h6 {
  color: var(--heading-color);
  font-weight: 600;
  margin-top: 1.75rem;
  margin-bottom: 1rem;
}

.ann-detail-body ul,
.ann-detail-body ol {
  margin-bottom: 1.25rem;
  padding-left: 1.5rem;
}

.ann-detail-body li {
  margin-bottom: 0.5rem;
}

.ann-detail-body a {
  color: var(--accent-color);
  text-decoration-thickness: 1px;
}

.ann-detail-body img {
  max-width: 100%;
  height: auto;
  border-radius: 0.5rem;
}

.ann-detail-body blockquote {
  margin: 1.5rem 0;
  padding: 0.75rem 1.5rem;
  border-left: 3px solid var(--accent-color);
  color: var(--heading-color);
  font-style: italic;
}

.ann-attachment {
  background-color: color-mix(in srgb, var(--accent-color), white 92%);
}

.ann-attachment i {
  font-size: 1.75rem;
  color: var(--accent-color);
}

.ann-back-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--heading-color);
  font-weight: 600;
  transition: color 0.25s ease, gap 0.25s ease;
}

.ann-back-link:hover {
  color: var(--accent-color);
  gap: 0.65rem;
}

/*--------------------------------------------------------------
# Featured Courses Section
--------------------------------------------------------------*/
.featured-courses .course-card {
  background: var(--surface-color);
  border-radius: 15px;
  overflow: hidden;
  box-shadow: 0 5px 25px color-mix(in srgb, var(--default-color), transparent 90%);
  transition: all 0.3s ease;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.featured-courses .course-card:hover {
  transform: translateY(-10px);
  box-shadow: 0 15px 40px color-mix(in srgb, var(--default-color), transparent 85%);
}

.featured-courses .course-image {
  position: relative;
  overflow: hidden;
  height: 220px;
}

.featured-courses .course-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.3s ease;
}

.featured-courses .course-image:hover img {
  transform: scale(1.05);
}

.featured-courses .course-image .badge {
  position: absolute;
  top: 15px;
  left: 15px;
  padding: 6px 12px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.featured-courses .course-image .badge.featured {
  background: var(--accent-color);
  color: var(--contrast-color);
}

.featured-courses .course-image .badge.new {
  background: #28a745;
  color: white;
}

.featured-courses .course-image .badge.certificate {
  background: #ffc107;
  color: #212529;
}

.featured-courses .course-image .badge.popular {
  background: #ff6b35;
  color: white;
}

.featured-courses .course-image .price-badge {
  position: absolute;
  top: 15px;
  right: 15px;
  background: var(--heading-color);
  color: var(--contrast-color);
  padding: 8px 15px;
  border-radius: 25px;
  font-weight: 700;
  font-size: 14px;
}

.featured-courses .course-content {
  padding: 25px;
  flex: 1;
  display: flex;
  flex-direction: column;
}

.featured-courses .course-meta {
  display: flex;
  gap: 15px;
  margin-bottom: 15px;
}

.featured-courses .course-meta span {
  font-size: 12px;
  padding: 4px 10px;
  border-radius: 15px;
  font-weight: 500;
}

.featured-courses .course-meta span.level {
  background: color-mix(in srgb, var(--accent-color), transparent 85%);
  color: var(--accent-color);
}

.featured-courses .course-meta span.duration {
  background: color-mix(in srgb, var(--heading-color), transparent 85%);
  color: var(--heading-color);
}

.featured-courses h3 {
  margin-bottom: 15px;
  font-size: 20px;
  line-height: 1.3;
}

.featured-courses h3 a {
  color: var(--heading-color);
  text-decoration: none;
  transition: color 0.3s ease;
}

.featured-courses h3 a:hover {
  color: var(--accent-color);
}

.featured-courses p {
  color: color-mix(in srgb, var(--default-color), transparent 20%);
  font-size: 14px;
  line-height: 1.6;
  margin-bottom: 20px;
}

.featured-courses .instructor {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 20px;
}

.featured-courses .instructor .instructor-img {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
}

.featured-courses .instructor .instructor-info h6 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--heading-color);
}

.featured-courses .instructor .instructor-info span {
  font-size: 12px;
  color: color-mix(in srgb, var(--default-color), transparent 40%);
}

.featured-courses .course-stats {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 25px;
  padding-top: 15px;
  border-top: 1px solid color-mix(in srgb, var(--default-color), transparent 90%);
}

.featured-courses .course-stats .rating {
  display: flex;
  align-items: center;
  gap: 3px;
}

.featured-courses .course-stats .rating i {
  color: #ffc107;
  font-size: 12px;
}

.featured-courses .course-stats .rating span {
  color: color-mix(in srgb, var(--default-color), transparent 30%);
  font-size: 12px;
  margin-left: 8px;
  font-weight: 500;
}

.featured-courses .course-stats .students {
  display: flex;
  align-items: center;
  gap: 5px;
}

.featured-courses .course-stats .students i {
  color: var(--accent-color);
  font-size: 14px;
}

.featured-courses .course-stats .students span {
  color: color-mix(in srgb, var(--default-color), transparent 30%);
  font-size: 12px;
  font-weight: 500;
}

.featured-courses .btn-course {
  display: inline-block;
  background: var(--accent-color);
  color: var(--contrast-color);
  padding: 12px 25px;
  border-radius: 25px;
  text-decoration: none;
  font-weight: 600;
  text-align: center;
  transition: all 0.3s ease;
  margin-top: auto;
}

.featured-courses .btn-course:hover {
  background: color-mix(in srgb, var(--accent-color), black 10%);
  transform: translateY(-2px);
}

.featured-courses .more-courses {
  margin-top: 50px;
}

.featured-courses .more-courses .btn-more {
  display: inline-block;
  background: transparent;
  color: var(--accent-color);
  padding: 15px 40px;
  border: 2px solid var(--accent-color);
  border-radius: 30px;
  text-decoration: none;
  font-weight: 600;
  transition: all 0.3s ease;
}

.featured-courses .more-courses .btn-more:hover {
  background: var(--accent-color);
  color: var(--contrast-color);
  transform: translateY(-3px);
}

@media (max-width: 768px) {
  .featured-courses .course-image {
    height: 200px;
  }

  .featured-courses .course-content {
    padding: 20px;
  }

  .featured-courses h3 {
    font-size: 18px;
  }

  .featured-courses .course-stats {
    flex-direction: column;
    gap: 10px;
    align-items: flex-start;
  }
}
/*--------------------------------------------------------------
# Program details
--------------------------------------------------------------*/
.program-details {
  display: flex;
  gap: 20px;
}

.program-details .detail-item {
  display: flex;
  align-items: center;
}

.program-details .detail-item i {
  color: var(--accent-color);
  margin-right: 8px;
  font-size: 1rem;
}

.program-details .detail-item span {
  color: color-mix(in srgb, var(--heading-color), transparent 20%);
  font-weight: 600;
  font-size: 0.85rem;
}
/*--------------------------------------------------------------
# Blog Posts Section
--------------------------------------------------------------*/
.blog-posts {
  padding-top: 60px;
  padding-bottom: 62px;
}

.blog-posts article {
  background-color: var(--surface-color);
  box-shadow: 0px 2px 20px rgba(0, 0, 0, 0.1);
  transition: 0.3s;
  border-radius: 8px;
  overflow: hidden;
}

.blog-posts .post-img img {
  transition: 0.5s;
}

.blog-posts .post-content {
  padding: 30px;
}

.blog-posts .post-title {
  font-size: 20px;
  line-height: 24px;
  color: var(--heading-color);
  font-weight: 600;
  transition: 0.3s;
  margin-bottom: 20px;
}

.blog-posts .meta {
  position: relative;
  margin-top: -20px;
  padding: 0 30px;
}

.blog-posts .meta i {
  font-size: 16px;
  color: var(--accent-color);
}

.blog-posts .meta span {
  font-size: 15px;
  color: color-mix(in srgb, var(--default-color), transparent 40%);
}

.blog-posts .meta .post-date {
  background-color: var(--accent-color);
  color: var(--contrast-color);
  font-size: 13px;
  padding: 6px 12px;
  text-align: center;
  margin-right: 15px;
  border-radius: 4px;
}

.blog-posts .meta .post-date span {
  display: block;
  color: var(--contrast-color);
  font-weight: 700;
  font-size: 20px;
}

.blog-posts .readmore {
  display: flex;
  align-items: center;
  font-weight: 400;
  line-height: 1;
  transition: 0.3s;
  color: color-mix(in srgb, var(--heading-color), transparent 20%);
}

.blog-posts .readmore i {
  line-height: 0;
  margin-left: 6px;
  font-size: 16px;
}

.blog-posts article:hover .post-title,
.blog-posts article:hover .readmore {
  color: var(--accent-color);
}

.blog-posts article:hover .post-img img {
  transform: scale(1.1);
}

/*--------------------------------------------------------------
# Pagination 2 Section
--------------------------------------------------------------*/
.pagination-2 {
  padding-top: 0;
}

.pagination-2 nav {
  position: relative;
}

.pagination-2 ul {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 0;
  margin: 0;
  list-style: none;
}

.pagination-2 li {
  margin: 0;
  transition: all 0.3s ease-in-out;
}

.pagination-2 li.ellipsis {
  color: color-mix(in srgb, var(--default-color), transparent 40%);
  padding: 8px 16px;
  user-select: none;
}

.pagination-2 li a {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  height: 40px;
  padding: 8px 16px;
  color: var(--default-color);
  background-color: var(--surface-color);
  border-radius: 8px;
  text-decoration: none;
  transition: all 0.3s ease-in-out;
  box-shadow: 0 2px 4px color-mix(in srgb, var(--default-color), transparent 90%);
}

.pagination-2 li a.active {
  background-color: var(--accent-color);
  color: var(--contrast-color);
  transform: translateY(-2px);
  box-shadow: 0 4px 8px color-mix(in srgb, var(--accent-color), transparent 70%);
}

.pagination-2 li a:hover:not(.active) {
  background-color: color-mix(in srgb, var(--accent-color), transparent 90%);
  transform: translateY(-1px);
  box-shadow: 0 3px 6px color-mix(in srgb, var(--default-color), transparent 85%);
}

.pagination-2 li a i {
  font-size: 14px;
}

.pagination-2 li a span {
  margin: 0 4px;
}

@media (max-width: 575px) {
  .pagination-2 ul {
    gap: 4px;
  }

  .pagination-2 li a {
    min-width: 36px;
    height: 36px;
    padding: 8px 12px;
    font-size: 14px;
  }
}

/*--------------------------------------------------------------
# Blog Details Section
--------------------------------------------------------------*/
.blog-details {
  max-width: 1200px;
  margin: 0 auto;
  position: relative;
}

.blog-details .article-header {
  max-width: 800px;
  margin: 0 auto 3rem;
  text-align: center;
}

.blog-details .article-header .meta-categories {
  margin-bottom: 1.5rem;
}

.blog-details .article-header .meta-categories .category {
  display: inline-block;
  padding: 0.4rem 1.2rem;
  margin: 0 0.5rem;
  background: color-mix(in srgb, var(--accent-color), transparent 90%);
  color: var(--accent-color);
  border-radius: 30px;
  font-size: 0.9rem;
  transition: all 0.3s ease;
}

.blog-details .article-header .meta-categories .category:hover {
  background: var(--accent-color);
  color: var(--contrast-color);
  transform: translateY(-2px);
}

.blog-details .article-header .title {
  font-size: 3.2rem;
  line-height: 1.2;
  margin-bottom: 2rem;
  color: var(--heading-color);
}

@media (max-width: 768px) {
  .blog-details .article-header .title {
    font-size: 2.2rem;
  }
}

.blog-details .article-header .article-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 1.5rem;
}

.blog-details .article-header .article-meta .author {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.blog-details .article-header .article-meta .author .author-img {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  object-fit: cover;
}

.blog-details .article-header .article-meta .author .author-info {
  text-align: left;
}

.blog-details .article-header .article-meta .author .author-info h4 {
  margin: 0;
  font-size: 1.1rem;
  color: var(--heading-color);
}

.blog-details .article-header .article-meta .author .author-info span {
  color: color-mix(in srgb, var(--default-color), transparent 30%);
  font-size: 0.9rem;
}

.blog-details .article-header .article-meta .post-info {
  display: flex;
  gap: 1.5rem;
  color: color-mix(in srgb, var(--default-color), transparent 30%);
  font-size: 0.95rem;
}

.blog-details .article-header .article-meta .post-info span {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

@media (max-width: 768px) {
  .blog-details .article-header .article-meta {
    justify-content: center;
    text-align: center;
  }

  .blog-details .article-header .article-meta .post-info {
    width: 100%;
    justify-content: center;
    flex-wrap: wrap;
  }
}

.blog-details .article-featured-image {
  margin: 0 -2rem 3rem;
  height: 500px;
  overflow: hidden;
  border-radius: 16px;
}

.blog-details .article-featured-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (max-width: 768px) {
  .blog-details .article-featured-image {
    margin: 0 -1rem 2rem;
    height: 300px;
  }
}

.blog-details .article-wrapper {
  display: grid;
  grid-template-columns: minmax(200px, 300px) 1fr;
  gap: 3rem;
  position: relative;
}

@media (max-width: 992px) {
  .blog-details .article-wrapper {
    grid-template-columns: 1fr;
  }

  /* Read the article before being asked to share/tag it. The sidebar
     is first in source order (it's the left column on desktop), so
     without this it would stack *above* the article on narrow
     screens instead of after it. */
  .blog-details .article-wrapper .article-content {
    order: 1;
  }

  .blog-details .article-wrapper .article-sidebar {
    order: 2;
    position: static;
  }
}

/* Sidebar: originally just the table-of-contents; now also holds the
   Share and Tags blocks that used to live in a separate .article-footer
   below the content (moved in per a design request -- keeping them in
   the sticky sidebar puts them within reach the whole time you're
   reading, not just after scrolling past the article). */
.blog-details .article-wrapper .article-sidebar {
  position: sticky;
  top: 100px;
  height: fit-content;
  background: var(--surface-color);
  border-radius: 12px;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
  overflow: hidden;
}

.blog-details .article-wrapper .article-sidebar .sidebar-section {
  padding: 2rem;
}

.blog-details .article-wrapper .article-sidebar .sidebar-section + .sidebar-section {
  border-top: 1px solid color-mix(in srgb, var(--default-color), transparent 90%);
}

/* Share/Tags need to stay reachable on mobile even though the ToC
   jump-nav (a pure desktop reading convenience) doesn't. */
@media (max-width: 992px) {
  .blog-details .article-wrapper .article-sidebar .sidebar-toc {
    display: none;
  }
}

.blog-details .article-wrapper .article-sidebar h3 {
  font-size: 1.2rem;
  margin-bottom: 1.5rem;
  color: var(--heading-color);
}

.blog-details .article-wrapper .article-sidebar .sidebar-toc nav ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.blog-details .article-wrapper .article-sidebar .sidebar-toc nav ul li {
  margin-bottom: 0.75rem;
}

.blog-details .article-wrapper .article-sidebar .sidebar-toc nav ul li a {
  color: color-mix(in srgb, var(--default-color), transparent 30%);
  text-decoration: none;
  font-size: 0.95rem;
  transition: all 0.3s ease;
  padding-left: 1rem;
  position: relative;
}

.blog-details .article-wrapper .article-sidebar .sidebar-toc nav ul li a::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--accent-color);
  transform: translateY(-50%);
  opacity: 0;
  transition: all 0.3s ease;
}

.blog-details .article-wrapper .article-sidebar .sidebar-toc nav ul li a:hover,
.blog-details .article-wrapper .article-sidebar .sidebar-toc nav ul li a.active {
  color: var(--heading-color);
}

.blog-details .article-wrapper .article-sidebar .sidebar-toc nav ul li a:hover::before,
.blog-details .article-wrapper .article-sidebar .sidebar-toc nav ul li a.active::before {
  opacity: 1;
}

/* Share/Tags headings reuse the same h4 look .article-footer used to
   give them; the buttons/tags themselves are unchanged, just narrower
   (sidebar column vs. a full-width footer row) so the share buttons
   stack instead of wrapping into a ragged multi-line row. */
.blog-details .article-wrapper .article-sidebar h4 {
  color: var(--heading-color);
  margin-bottom: 1.5rem;
  font-size: 1.05rem;
}

.blog-details .article-wrapper .article-sidebar .share-buttons {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.blog-details .article-wrapper .article-sidebar .share-button {
  justify-content: flex-start;
}

.blog-details .article-wrapper .article-sidebar .tags {
  gap: 0.5rem;
}

.blog-details .article-wrapper .article-content {
  font-size: 1.15rem;
  line-height: 1.8;
  /* Anchor targets land here (see #content/#related/#gallery) --
     matches the sticky header's own height so the jump doesn't leave
     the target's own heading hidden underneath it. */
  scroll-margin-top: 140px;
}

.blog-details .article-wrapper .article-content .content-section {
  margin-bottom: 4rem;
}

.blog-details .article-wrapper .article-content .content-section .lead {
  font-size: 1.4rem;
  line-height: 1.6;
  color: var(--heading-color);
  margin-bottom: 2rem;
}

.blog-details .article-wrapper .article-content .content-section h2 {
  font-size: 2.2rem;
  color: var(--heading-color);
  margin-bottom: 1.5rem;
}

.blog-details .article-wrapper .article-content .content-section .highlight-quote {
  margin: 3rem 0;
  padding: 3rem;
  background: var(--surface-color);
  border-radius: 12px;
  position: relative;
}

.blog-details .article-wrapper .article-content .content-section .highlight-quote::before {
  content: "“";
  position: absolute;
  top: 1rem;
  left: 1rem;
  font-size: 5rem;
  color: color-mix(in srgb, var(--accent-color), transparent 85%);
  font-family: serif;
  line-height: 1;
}

.blog-details .article-wrapper .article-content .content-section .highlight-quote blockquote {
  padding-left: 3rem;
}

.blog-details .article-wrapper .article-content .content-section .highlight-quote blockquote p {
  font-size: 1.5rem;
  font-style: italic;
  color: var(--heading-color);
  margin-bottom: 1rem;
}

.blog-details .article-wrapper .article-content .content-section .highlight-quote blockquote cite {
  font-style: normal;
  color: color-mix(in srgb, var(--default-color), transparent 30%);
}

.blog-details .article-wrapper .article-content .content-section .image-with-caption {
  margin: 2rem 0;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
}

.blog-details .article-wrapper .article-content .content-section .image-with-caption.right {
  float: right;
  max-width: 450px;
  margin: 0 0 2rem 2rem;
}

@media (max-width: 768px) {
  .blog-details .article-wrapper .article-content .content-section .image-with-caption.right {
    float: none;
    max-width: 100%;
    margin: 2rem 0;
  }
}

.blog-details .article-wrapper .article-content .content-section .image-with-caption img {
  width: 100%;
}

.blog-details .article-wrapper .article-content .content-section .image-with-caption figcaption {
  padding: 1rem;
  background: var(--surface-color);
  text-align: center;
  font-size: 0.9rem;
  color: color-mix(in srgb, var(--default-color), transparent 30%);
}

.blog-details .article-wrapper .article-content .content-section .feature-points {
  display: grid;
  gap: 2rem;
  margin: 2rem 0;
}

.blog-details .article-wrapper .article-content .content-section .feature-points .point {
  display: flex;
  gap: 1rem;
  align-items: flex-start;
}

.blog-details .article-wrapper .article-content .content-section .feature-points .point i {
  font-size: 2rem;
  color: var(--accent-color);
}

.blog-details .article-wrapper .article-content .content-section .feature-points .point h4 {
  margin: 0 0 0.5rem;
  color: var(--heading-color);
}

.blog-details .article-wrapper .article-content .content-section .feature-points .point p {
  margin: 0;
  font-size: 1rem;
}

.blog-details .article-wrapper .article-content .content-section .comparison-grid {
  margin: 2rem 0;
}

.blog-details .article-wrapper .article-content .content-section .comparison-grid .comparison-card {
  background: var(--surface-color);
  border-radius: 12px;
  padding: 2rem;
  height: 100%;
}

.blog-details .article-wrapper .article-content .content-section .comparison-grid .comparison-card .icon {
  margin-bottom: 1rem;
}

.blog-details .article-wrapper .article-content .content-section .comparison-grid .comparison-card .icon i {
  font-size: 2rem;
  color: var(--accent-color);
}

.blog-details .article-wrapper .article-content .content-section .comparison-grid .comparison-card h4 {
  color: var(--heading-color);
  margin-bottom: 1rem;
}

.blog-details .article-wrapper .article-content .content-section .comparison-grid .comparison-card ul {
  padding-left: 1.2rem;
  margin: 0;
}

.blog-details .article-wrapper .article-content .content-section .comparison-grid .comparison-card ul li {
  margin-bottom: 0.5rem;
  color: color-mix(in srgb, var(--default-color), transparent 15%);
}

.blog-details .article-wrapper .article-content .content-section .key-principles {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem;
  margin: 3rem 0;
}

@media (max-width: 768px) {
  .blog-details .article-wrapper .article-content .content-section .key-principles {
    grid-template-columns: 1fr;
  }
}

.blog-details .article-wrapper .article-content .content-section .key-principles .principle {
  text-align: center;
  padding: 2rem;
  background: var(--surface-color);
  border-radius: 12px;
  position: relative;
}

.blog-details .article-wrapper .article-content .content-section .key-principles .principle .number {
  position: absolute;
  top: -1rem;
  left: 50%;
  transform: translateX(-50%);
  background: var(--accent-color);
  color: var(--contrast-color);
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  font-weight: bold;
}

.blog-details .article-wrapper .article-content .content-section .key-principles .principle h4 {
  color: var(--heading-color);
  margin: 1rem 0;
}

.blog-details .article-wrapper .article-content .content-section .key-principles .principle p {
  margin: 0;
  font-size: 0.95rem;
}

.blog-details .article-wrapper .article-content .content-section .info-box {
  display: flex;
  gap: 1.5rem;
  padding: 2rem;
  background: color-mix(in srgb, var(--accent-color), transparent 95%);
  border-radius: 12px;
  margin: 2rem 0;
}

.blog-details .article-wrapper .article-content .content-section .info-box .icon i {
  font-size: 2.5rem;
  color: var(--accent-color);
}

.blog-details .article-wrapper .article-content .content-section .info-box .content h4 {
  color: var(--heading-color);
  margin-bottom: 0.5rem;
}

.blog-details .article-wrapper .article-content .content-section .info-box .content p {
  margin: 0;
}

.blog-details .article-wrapper .article-content .content-section .future-trends {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem;
  margin: 2rem 0;
}

@media (max-width: 768px) {
  .blog-details .article-wrapper .article-content .content-section .future-trends {
    grid-template-columns: 1fr;
  }
}

.blog-details .article-wrapper .article-content .content-section .future-trends .trend {
  text-align: center;
  padding: 2rem;
  background: var(--surface-color);
  border-radius: 12px;
  transition: transform 0.3s ease;
}

.blog-details .article-wrapper .article-content .content-section .future-trends .trend:hover {
  transform: translateY(-5px);
}

.blog-details .article-wrapper .article-content .content-section .future-trends .trend i {
  font-size: 2.5rem;
  color: var(--accent-color);
  margin-bottom: 1rem;
}

.blog-details .article-wrapper .article-content .content-section .future-trends .trend h4 {
  color: var(--heading-color);
  margin-bottom: 1rem;
}

.blog-details .article-wrapper .article-content .content-section .future-trends .trend p {
  margin: 0;
  font-size: 0.95rem;
}

/* Share buttons + tags: originally scoped under a .article-footer
   .share-article / .article-tags wrapper that sat below the content.
   Both now live in the sidebar instead (.sidebar-share/.sidebar-tags),
   so these are scoped to just .blog-details -- the one ancestor both
   the old and new locations share -- rather than a specific container
   that no longer exists. */
.blog-details .share-buttons {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
}

.blog-details .share-buttons .share-button {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 1.5rem;
  background: var(--surface-color);
  border-radius: 30px;
  color: var(--heading-color);
  text-decoration: none;
  transition: all 0.3s ease;
}

.blog-details .share-buttons .share-button i {
  font-size: 1.2rem;
}

.blog-details .share-buttons .share-button:hover {
  background: var(--accent-color);
  color: var(--contrast-color);
  transform: translateY(-2px);
}

.blog-details .share-buttons .share-button.twitter:hover {
  background: #1DA1F2;
}

.blog-details .share-buttons .share-button.facebook:hover {
  background: #4267B2;
}

.blog-details .share-buttons .share-button.linkedin:hover {
  background: #0077B5;
}

.blog-details .tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.blog-details .tags .tag {
  padding: 0.5rem 1rem;
  background: color-mix(in srgb, var(--accent-color), transparent 90%);
  color: var(--accent-color);
  border-radius: 30px;
  font-size: 0.9rem;
  text-decoration: none;
  transition: all 0.3s ease;
}

.blog-details .tags .tag:hover {
  background: var(--accent-color);
  color: var(--contrast-color);
  transform: translateY(-2px);
}

/* Extra share targets: the template originally had one broken Facebook
   link (build_absolute_uli -- typo for build_absolute_uri, so it never
   produced a working share URL). .twitter/.facebook/.linkedin already
   had a hover colour above; whatsapp/email/copy-link are new. */
.blog-details .share-buttons .share-button.whatsapp:hover {
  background: #25d366;
}

.blog-details .share-buttons .share-button.email:hover {
  background: var(--accent-color);
}

.blog-details .share-buttons .share-button.copy-link {
  border: none;
  cursor: pointer;
  font: inherit;
}

.blog-details .share-buttons .share-button.copy-link.copied {
  background: #16a34a;
  color: #fff;
}

/* Read-aloud control (browser text-to-speech) */
.blog-details .article-header .article-audio {
  margin-top: 1.5rem;
}

.blog-details .article-header .audio-toggle,
.blog-details .article-header .audio-stop {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.65rem 1.4rem;
  border: 1px solid color-mix(in srgb, var(--accent-color), transparent 70%);
  border-radius: 999px;
  background: color-mix(in srgb, var(--accent-color), transparent 94%);
  color: var(--accent-color);
  font-weight: 600;
  font-size: 0.95rem;
  transition: background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}

.blog-details .article-header .audio-toggle:hover,
.blog-details .article-header .audio-toggle[aria-pressed="true"] {
  background: var(--accent-color);
  color: var(--contrast-color);
  border-color: var(--accent-color);
}

.blog-details .article-header .audio-stop {
  padding: 0.65rem 0.9rem;
  margin-left: 0.5rem;
}

.blog-details .article-header .audio-stop:hover {
  background: color-mix(in srgb, var(--accent-color), transparent 80%);
  color: var(--accent-color);
}

.blog-details .article-header .audio-toggle[aria-pressed="true"] i {
  animation: audio-pulse 1.6s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  .blog-details .article-header .audio-toggle[aria-pressed="true"] i {
    animation: none;
  }
}

@keyframes audio-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.5; }
}

/* Related News (news_det_page.html): reuses the .news-card /
   .news-card-compact rules above as-is (both already lay the card
   out as a top image + body), just arranged as a 3-up grid instead
   of the homepage's single-column sidebar list. The flex-direction/
   card-img-wrapper redeclarations below are now redundant with the
   shared .news-card-compact rules but kept as an explicit, page-
   scoped guarantee in case the shared defaults ever change again. */
.blog-details .article-related {
  margin-top: 4rem;
  padding-top: 2rem;
  border-top: 1px solid color-mix(in srgb, var(--default-color), transparent 90%);
  scroll-margin-top: 140px;
}

/* news_det_page.html's image gallery is its own <section id="gallery">
   outside .blog-details entirely, so it needs the same scroll-margin-top
   set independently to match the other two ToC jump targets. */
#gallery {
  scroll-margin-top: 140px;
}

.blog-details .article-related h4 {
  color: var(--heading-color);
  margin-bottom: 1.5rem;
}

.blog-details .related-news-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
}

@media (max-width: 768px) {
  .blog-details .related-news-grid {
    grid-template-columns: 1fr;
  }
}

.blog-details .related-news-grid .news-card-compact {
  flex-direction: column;
  align-items: stretch;
}

.blog-details .related-news-grid .news-card-compact .card-img-wrapper {
  width: 100%;
  aspect-ratio: 16 / 9;
}

/*--------------------------------------------------------------
# Reusable Icon Badges & Hover Cards
--------------------------------------------------------------*/
.icon-circle {
  width: 64px;
  height: 64px;
  background-color: color-mix(in srgb, var(--accent-color), transparent 90%);
  transition: background-color 0.3s ease, transform 0.3s ease;
}

.icon-circle i {
  color: var(--accent-color);
  font-size: 1.5rem;
  transition: color 0.3s ease;
}

.icon-circle.icon-circle-sm {
  width: 56px;
  height: 56px;
}

.icon-circle.icon-circle-sm i {
  font-size: 1.25rem;
}

.icon-circle.icon-circle-lg {
  width: 72px;
  height: 72px;
}

.icon-circle.icon-circle-lg i {
  font-size: 1.75rem;
}

/* On narrow phones, shrink the large Vision/Mission badge so it sits
   comfortably on the same line as its heading instead of crowding it. */
@media (max-width: 575.98px) {
  .icon-circle.icon-circle-lg {
    width: 56px;
    height: 56px;
  }

  .icon-circle.icon-circle-lg i {
    font-size: 1.35rem;
  }
}

/* Card with a permanent accent-colored left edge (pairs with .rounded-end-4
   so the flat left side reads as a deliberate stripe, not a clipped corner).
   The stripe deepens to full accent and the card lifts on hover; the icon
   badge inverts to a solid accent fill so the whole card reads as one state. */
.hover-card {
  border: 1px solid color-mix(in srgb, var(--default-color), transparent 92%);
  border-left: 4px solid color-mix(in srgb, var(--accent-color), transparent 55%);
  box-shadow: 0 2px 12px color-mix(in srgb, var(--default-color), transparent 93%);
  transition: transform 0.35s ease, box-shadow 0.35s ease, border-left-color 0.35s ease;
}

.hover-card:hover {
  transform: translateY(-8px);
  border-left-color: var(--accent-color);
  box-shadow: 0 20px 40px color-mix(in srgb, var(--default-color), transparent 85%);
}

.hover-card:hover .icon-circle {
  background-color: var(--accent-color);
  transform: scale(1.08);
}

.hover-card:hover .icon-circle i {
  color: var(--contrast-color);
}

/* Same accent left-edge treatment as .hover-card but without the lift --
   for wide, static panels where a jumping edge under the cursor would be distracting. */
.hover-outline {
  border: 1px solid color-mix(in srgb, var(--default-color), transparent 92%);
  border-left: 4px solid color-mix(in srgb, var(--accent-color), transparent 55%);
  box-shadow: 0 2px 12px color-mix(in srgb, var(--default-color), transparent 93%);
  transition: border-left-color 0.3s ease, box-shadow 0.3s ease;
}

.hover-outline:hover {
  border-left-color: var(--accent-color);
  box-shadow: 0 15px 35px color-mix(in srgb, var(--default-color), transparent 88%);
}

/* Hover/focus lift on cards: Bootstrap has no utility for a
   hover-triggered transform. Originally scoped to the Projects & Research
   directory pages via research/includes/_theme_overrides.html; promoted
   here (same reasoning as the accent-colour remap above) so other
   directory-style listings -- e.g. the Organizations & Clubs directory --
   can use the same card "language" without re-declaring it per page. */
.hover-lift {
  transition: transform .15s ease-in-out, box-shadow .15s ease-in-out;
}
.hover-lift:hover,
.hover-lift:focus-within {
  transform: translateY(-4px);
  box-shadow: 0 1rem 2rem color-mix(in srgb, var(--default-color), transparent 88%) !important;
}

/* Caps a text block at exactly N lines with a trailing ellipsis -- e.g. a
   grid of directory cards whose excerpts vary in length still lines up
   evenly. Standard CSS (line-clamp is supported unprefixed since
   2023-2024; -webkit- kept alongside for older engines), not a framework
   substitute. Same promotion story as .hover-lift above. */
.line-clamp-2 {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}

/* Gentle zoom on an image when its container is hovered -- originally for
   the About page's hero photo, now reused by every plain photo-gallery
   link across the site (e.g. facility_det_page.html's own gallery, and
   the Organization Gallery below). */
.img-hover-zoom {
  overflow: hidden;
}

.img-hover-zoom img {
  transition: transform 0.5s ease;
}

.img-hover-zoom:hover img {
  transform: scale(1.06);
}

/*--------------------------------------------------------------
# Organization Gallery photo card (org_club_page.html)
#
# Same .img-hover-zoom base as facility_det_page.html's own gallery, but
# with a caption strip: unlike Facility's gallery (one facility, one
# entity), this one mixes photos from every organization, so a visitor
# needs some way to tell which organization a given photo belongs to.
--------------------------------------------------------------*/
.org-gallery-item {
  position: relative;
  aspect-ratio: 4 / 3;
}

.org-gallery-item img {
  display: block;
}

/* Small circular zoom affordance, top-right -- hidden until hover/focus so
   it doesn't compete with the caption strip below, then fades in and
   picks up the site's accent color to match the hover language used
   elsewhere (.hover-card, .filter-pills). */
.org-gallery-zoom {
  width: 34px;
  height: 34px;
  background: color-mix(in srgb, black, transparent 35%);
  color: #fff;
  font-size: 0.95rem;
  opacity: 0;
  transform: scale(0.85);
  transition: opacity 0.25s ease, transform 0.25s ease, background-color 0.25s ease;
}

.org-gallery-item:hover .org-gallery-zoom,
.org-gallery-item:focus-visible .org-gallery-zoom {
  opacity: 1;
  transform: scale(1);
}

.org-gallery-item:hover .org-gallery-zoom {
  background: var(--accent-color);
}

/* The photo's own caption (or its organization's name as a fallback --
   see OrgClubPage.get_context) stays visible at all times, not just on
   hover, since ":hover" never fires on a touchscreen and a visitor still
   needs to know whose photo this is. */
.org-gallery-caption {
  background: linear-gradient(to top, color-mix(in srgb, black, transparent 20%), transparent);
  color: #fff;
  padding-top: 2rem;
}

@media (prefers-reduced-motion: reduce) {
  .org-gallery-zoom {
    transition: none;
  }
}

/*--------------------------------------------------------------
# Laboratory Gallery mosaic (lab_det_page.html)
#
# Same GLightbox + .img-hover-zoom language as the Facility and
# Organization galleries, laid out as a mosaic: with 3+ photos the first
# one is featured at 2x2. Images are absolutely positioned so the featured
# tile's size comes from the grid tracks (set by the 4:3 tiles), never from
# the photo's own dimensions.
--------------------------------------------------------------*/
.lab-gallery-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1rem;
}

.lab-gallery-item {
  aspect-ratio: 4 / 3;
}

.lab-gallery-item img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.lab-gallery-featured .lab-gallery-item:first-child {
  grid-column: span 2;
  aspect-ratio: 16 / 9;
}

@media (min-width: 768px) {
  .lab-gallery-grid {
    grid-template-columns: repeat(4, 1fr);
  }

  .lab-gallery-featured .lab-gallery-item:first-child {
    grid-row: span 2;
    aspect-ratio: auto;
  }
}

/* Soft dark wash on hover so the zoom icon reads on any photo. */
.lab-gallery-overlay {
  background: linear-gradient(to top, color-mix(in srgb, black, transparent 45%), transparent 60%);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.lab-gallery-zoom {
  width: 34px;
  height: 34px;
  background: color-mix(in srgb, black, transparent 35%);
  color: #fff;
  font-size: 0.95rem;
  opacity: 0;
  transform: scale(0.85);
  transition: opacity 0.25s ease, transform 0.25s ease, background-color 0.25s ease;
}

.lab-gallery-item:hover .lab-gallery-overlay,
.lab-gallery-item:focus-visible .lab-gallery-overlay,
.lab-gallery-item:hover .lab-gallery-zoom,
.lab-gallery-item:focus-visible .lab-gallery-zoom {
  opacity: 1;
}

.lab-gallery-item:hover .lab-gallery-zoom,
.lab-gallery-item:focus-visible .lab-gallery-zoom {
  transform: scale(1);
}

.lab-gallery-item:hover .lab-gallery-zoom {
  background: var(--accent-color);
}

@media (prefers-reduced-motion: reduce) {
  .lab-gallery-overlay,
  .lab-gallery-zoom {
    transition: none;
  }
}

/*--------------------------------------------------------------
# Show more / show less (card text truncation)
--------------------------------------------------------------*/
/* Core show/hide is Bootstrap's own .collapse component (see
   custom/templates/custom/includes/show_more.html) -- the preview and
   full-text blocks share one toggle class so a single click shows one and
   hides the other, with no custom JS. Everything below is progressive
   enhancement on top of that: it only needs :has() support to notice which
   state a card is in, and degrades harmlessly (no card-widening, no label
   swap) without it -- the actual show/hide keeps working regardless. */
.show-more-toggle {
  text-decoration: none;
  cursor: pointer;
}

.show-more-toggle:hover {
  text-decoration: underline;
}

.show-more-toggle .label-less {
  display: none;
}

.show-more-toggle .show-more-icon {
  font-size: 0.75em;
  transition: transform 0.3s ease;
}

.show-more-wrap:has(.show-more-full.show) .label-more {
  display: none;
}

.show-more-wrap:has(.show-more-full.show) .label-less {
  display: inline;
}

.show-more-wrap:has(.show-more-full.show) .show-more-icon {
  transform: rotate(180deg);
}

/* Opening a card's "show more" widens its own grid column to a full-width
   horizontal card instead of just growing taller in a narrow one, and
   forces its content row (if any -- see the Values cards) horizontal even
   on narrow viewports where it would normally stack. */
.expandable-card-col {
  transition: flex-basis 0.35s ease, max-width 0.35s ease;
}

.expandable-card-col:has(.show-more-full.show) {
  flex: 0 0 100%;
  max-width: 100%;
}

.expandable-card-col:has(.show-more-full.show) .card-body {
  flex-direction: row !important;
  text-align: left !important;
}

/*--------------------------------------------------------------
# Modern Header / Navbar
--------------------------------------------------------------
Visual + interaction refresh of includes/header.html and
includes/topbar.html. This is a pure override layer: main.css
(the vendor CoreBiz template) still owns the base header/navmenu
rules *and* every JS hook they render around --
.mobile-nav-toggle, .toggle-dropdown, .mobile-nav-active,
.dropdown-active, .scrolled -- so everything below only restyles
those same classes/states and needs no changes to
static/assets/js/main.js. The few genuinely new interactions
(close the mobile drawer by clicking its backdrop or pressing
Esc, keep aria-expanded in sync) are added separately, in
static/js/custom.js, so they stay decoupled from the vendor file.
--------------------------------------------------------------*/

/* Topbar: quieter utility bar */
.header .topbar {
  font-size: 13px;
}

.header .topbar .contact-info i a,
.header .topbar .contact-info i span {
  transition: opacity 0.25s ease;
}

.header .topbar .contact-info i a:hover {
  opacity: 0.85;
}

/* Language switcher: was a row of plain-text code links hidden
   entirely below 768px (d-none d-md-flex), so mobile visitors had
   no way to change language at all. Replaced with a compact
   dropdown (Bootstrap's own dropdown JS -- already loaded site-wide
   -- handles open/close, outside-click, Esc and keyboard nav, so no
   extra JS is needed here) that fits the topbar at every width and
   shows each language's full display name instead of just its code.
   data-bs-display="static" on the toggle turns off Popper for this
   instance, so the menu is positioned by plain CSS instead of an
   inline `transform` -- which leaves the transform below free for
   the open/close animation without JS fighting it. */
.language-switcher .language-toggle {
  border: none;
  gap: 6px;
  padding: 5px 12px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.4px;
  color: var(--contrast-color);
  background-color: color-mix(in srgb, var(--contrast-color), transparent 85%);
  transition: background-color 0.25s ease;
}

.language-switcher .language-toggle i {
  font-size: 14px;
  line-height: 1;
}

.language-switcher .language-toggle:hover,
.language-switcher .language-toggle[aria-expanded="true"] {
  background-color: color-mix(in srgb, var(--contrast-color), transparent 72%);
}

.language-switcher .language-toggle:focus-visible {
  outline: 2px solid var(--contrast-color);
  outline-offset: 2px;
}

.language-switcher .language-toggle::after {
  margin-left: 2px;
  opacity: 0.7;
}

.language-switcher .language-menu {
  /* Bootstrap only right-aligns .dropdown-menu-end via a
     [data-bs-popper]-qualified rule, which Popper adds -- but
     data-bs-display="static" on the toggle (see topbar.html) turns
     Popper off on purpose, so that qualified rule never matches and
     the menu fell back to its in-flow position, overflowing past the
     viewport at some widths since the toggle sits at the far right of
     the topbar. Pin it explicitly instead of depending on Popper. */
  right: 0;
  left: auto;
  min-width: 12rem;
  margin-top: 10px;
  padding: 6px;
  border: 1px solid color-mix(in srgb, var(--default-color), transparent 90%);
  border-radius: 12px;
  box-shadow: 0 16px 40px color-mix(in srgb, var(--default-color), transparent 85%);
  display: block !important;
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  transform: translateY(6px) scale(0.98);
  transition: opacity 0.18s ease, transform 0.18s ease, visibility 0.18s;
}

.language-switcher .language-menu.show {
  visibility: visible;
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0) scale(1);
}

.language-switcher .language-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 8px;
  font-size: 14px;
  color: var(--nav-dropdown-color);
}

.language-switcher .language-item-code {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  padding: 2px 6px;
  border-radius: 6px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.4px;
  background-color: color-mix(in srgb, var(--accent-color), transparent 90%);
  color: var(--accent-color);
}

.language-switcher .language-item-name {
  flex: 1;
}

.language-switcher .language-item-check {
  color: var(--accent-color);
  font-size: 14px;
}

.language-switcher .language-item:hover,
.language-switcher .language-item:focus-visible {
  background-color: color-mix(in srgb, var(--accent-color), transparent 94%);
  color: var(--nav-dropdown-hover-color);
}

.language-switcher .language-item.active {
  background-color: color-mix(in srgb, var(--accent-color), transparent 92%);
  color: var(--nav-dropdown-hover-color);
  font-weight: 600;
}

@media (max-width: 420px) {
  .header .topbar .contact-info i:nth-child(2) span {
    display: none;
  }

  .language-switcher .language-current {
    display: none;
  }

  .language-switcher .language-toggle {
    padding: 6px 9px;
  }
}

/* #header is sticky-top, and main.css animates its topbar's height
   (40px -> 0) plus (below) the branding row's padding purely off
   scroll position. While that 0.3-0.5s transition plays, the sticky
   header's own box keeps resizing, and Chrome/Edge's scroll anchoring
   "helpfully" nudges window.scrollY to compensate for the shrinking
   space above the fold -- which can walk scrollY back across the
   100px/60px switch points on its own, re-triggering the same
   collapse/expand and reading as the header vibrating on scroll. html
   is the box that actually establishes the page's scroll anchoring
   here, so that's where anchoring needs to be off, not #header itself. */
html {
  overflow-anchor: none;
}

/* Branding row: logo lockup (monogram + wordmark) and a subtle
   divider that fades away once the page is scrolled */
.header {
  transition: box-shadow 0.3s ease;
}

.scrolled .header {
  box-shadow: 0 10px 30px color-mix(in srgb, var(--default-color), transparent 88%);
}

.header .branding {
  padding: 14px 0;
  border-bottom: 1px solid color-mix(in srgb, var(--default-color), transparent 93%);
  transition: padding 0.3s ease, border-color 0.3s ease;
}

.scrolled .header .branding {
  padding: 8px 0;
  border-bottom-color: transparent;
}

.header .logo {
  gap: 12px;
  transition: opacity 0.25s ease;
}

.header .logo:hover {
  opacity: 0.85;
}

.header .logo-mark {
  display: block;
  flex-shrink: 0;
  width: 52px;
  height: 52px;
  border-radius: 10px;
  object-fit: contain;
  /* Brightness lift so the logo reads crisply on any header background;
     drop-shadow follows the image shape (not the bounding box) for a
     natural glow rather than a blurry square. */
  filter:
    brightness(1.12)
    contrast(1.05)
    drop-shadow(0 2px 10px color-mix(in srgb, var(--accent-color), transparent 55%));
  transition: filter 0.3s ease, transform 0.3s ease;
}

.header .logo:hover .logo-mark {
  filter:
    brightness(1.22)
    contrast(1.08)
    drop-shadow(0 4px 16px color-mix(in srgb, var(--accent-color), transparent 40%));
  transform: scale(1.05);
}

/* .sitename is a <p>, not a heading -- the page's own content title is
   the only <h1> now (was a duplicate h1 before, one per page render).
   Re-declares what main.css's ".header .logo h1"/generic heading rule
   used to provide, since neither selector matches a <p>. */
.header .logo p.sitename {
  font-family: var(--heading-font);
  font-weight: 700;
  color: var(--heading-color);
  font-size: 26px;
  letter-spacing: 0.3px;
  margin: 0;
}

/* Desktop navmenu: animated underline, rotating chevrons and a
   card-style dropdown with a hover "dot" indicator */
@media (min-width: 1200px) {
  .navmenu > ul > li > a {
    position: relative;
  }

  .navmenu > ul > li > a::after {
    content: "";
    position: absolute;
    left: 15px;
    right: 15px;
    bottom: 12px;
    height: 2px;
    border-radius: 2px;
    background: var(--nav-hover-color);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.3s ease;
  }

  .navmenu > ul > li:hover > a::after,
  .navmenu > ul > li.active > a::after {
    transform: scaleX(1);
  }

  .navmenu .dropdown > a i {
    transition: transform 0.3s ease;
  }

  .navmenu .dropdown:hover > a i {
    transform: rotate(180deg);
  }

  .navmenu .dropdown ul {
    padding: 8px;
    border-radius: 12px;
    border: 1px solid color-mix(in srgb, var(--default-color), transparent 92%);
    box-shadow: 0 20px 45px color-mix(in srgb, var(--default-color), transparent 85%);
    transform: translateY(8px);
  }

  .navmenu .dropdown:hover > ul {
    transform: translateY(0);
  }

  .navmenu .dropdown ul li {
    border-radius: 8px;
  }

  .navmenu .dropdown ul a {
    position: relative;
    border-radius: 8px;
    padding-left: 26px;
  }

  .navmenu .dropdown ul a::before {
    content: "";
    position: absolute;
    left: 12px;
    top: 50%;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--nav-dropdown-hover-color);
    opacity: 0;
    transform: translateY(-50%) scale(0.3);
    transition: transform 0.2s ease, opacity 0.2s ease;
  }

  .navmenu .dropdown ul a:hover,
  .navmenu .dropdown ul li:hover > a {
    background-color: color-mix(in srgb, var(--accent-color), transparent 94%);
  }

  .navmenu .dropdown ul a:hover::before,
  .navmenu .dropdown ul li:hover > a::before {
    opacity: 1;
    transform: translateY(-50%) scale(1);
  }
}

/* Keyboard focus states -- the previous design had none on nav links
   or the (non-focusable) <i>-based mobile toggle */
.navmenu a:focus-visible {
  outline: 2px solid var(--accent-color);
  outline-offset: -2px;
  border-radius: 6px;
}

.mobile-nav-toggle:focus-visible {
  outline: 2px solid var(--accent-color);
  outline-offset: 2px;
  border-radius: 8px;
}

/* Mobile navmenu: a proper right-hand slide-in drawer with a dimmed,
   blurred backdrop, instead of the old rounded box floating 20px in
   from every edge of the screen */
@media (max-width: 1199px) {
  .mobile-nav-toggle {
    background: none;
    border: none;
    padding: 4px;
    border-radius: 8px;
  }

  .mobile-nav-active .navmenu {
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
  }

  /* The vendor rule paints this white -- correct for the old design,
     where it sat over the dark full-screen backdrop, but it now sits
     over the (light) drawer panel itself and would disappear. */
  .mobile-nav-active .mobile-nav-toggle {
    top: 20px;
    right: 20px;
    width: 40px;
    height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 20px;
    color: var(--nav-color);
    background-color: color-mix(in srgb, var(--default-color), transparent 90%);
    border-radius: 50%;
  }

  .header .navmenu > ul {
    display: flex;
    flex-direction: column;
    position: fixed;
    inset: 0 0 0 auto;
    width: min(86vw, 340px);
    height: 100vh;
    margin: 0;
    padding: 84px 8px 24px;
    border-radius: 0;
    background-color: var(--nav-mobile-background-color);
    box-shadow: -16px 0 40px rgba(0, 0, 0, 0.18);
    transform: translateX(100%);
    transition: transform 0.35s ease;
    overflow-y: auto;
  }

  .mobile-nav-active .header .navmenu > ul {
    transform: translateX(0);
  }

  .header .navmenu a {
    border-radius: 8px;
  }

  .header .navmenu .dropdown ul {
    border-radius: 10px;
  }

  .header .navmenu > ul > li > a:hover,
  .header .navmenu > ul > li.active > a {
    background-color: color-mix(in srgb, var(--accent-color), transparent 93%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .header,
  .header .branding,
  .header .logo,
  .navmenu a,
  .navmenu > ul > li > a::after,
  .navmenu .dropdown > a i,
  .navmenu .dropdown ul,
  .navmenu .dropdown ul a::before,
  .header .navmenu > ul,
  .mobile-nav-toggle {
    transition: none !important;
  }
}

/*--------------------------------------------------------------
# Home Hero: responsive fixes for its two "card" components
--------------------------------------------------------------
home/templates/home/home_hero.html renders two card-like pieces:
the floating metrics card on the hero image, and the 3 "value"
feature cards below it. Neither was actually responsive:

1. .floating-card is `position: absolute; bottom: ...` with no
   width limit. main.css already stacks its 4 metrics into a
   column below 576px -- which makes the card much taller, and
   because it's pinned by `bottom`, that extra height pushes its
   *top* edge upward. Below ~400px wide it rides up far enough to
   cover the CTA button above the image; even where it doesn't
   reach that far it still crops a large chunk of the photo. Fixed
   below by dropping the overlap entirely at that width: the card
   becomes a normal in-flow block just under the image (a small
   negative margin keeps a tasteful "tucked under" look) and its
   metrics form a 2x2 grid instead of one tall column, so it can
   never again grow into something else's space.

2. .feature-item had no width tier between "3 per row" (lg, the
   template's old col-lg-4) and "1 per row" (below md) -- at
   768-991px (col-md-6) 3 cards wrapped as an unbalanced 2-then-1.
   The template now uses a single `col-md-4`, which (Bootstrap
   breakpoints cascade upward) gives 3-per-row from 768px up and
   1-per-row below it, with no awkward middle tier.

3. .feature-item had no card chrome at all (no background/border/
   shadow) -- just padded text, inconsistent with every other card
   pattern on the site. Adding one safely requires equal-height
   boxes first (the template now pairs `d-flex` columns with
   `.feature-item.h-100`), since the value copy's length varies a
   lot between languages (English/Portuguese run noticeably longer
   than Tetum) and un-equalized cards would show jagged bottoms
   the moment a visible card boundary was added.
--------------------------------------------------------------*/
@media (max-width: 576px) {
  .hero .hero-content .hero-image .floating-card {
    position: static;
    left: auto;
    right: auto;
    bottom: auto;
    width: 100%;
    margin-top: -2.5rem;
  }

  .hero .hero-content .hero-image .floating-card .card-content {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1.5rem 1rem;
  }
}

.hero .hero-features .feature-item {
  background: var(--surface-color);
  border: 1px solid color-mix(in srgb, var(--default-color), transparent 92%);
  border-radius: 16px;
  box-shadow: 0 10px 30px color-mix(in srgb, var(--default-color), transparent 93%);
}

.hero .hero-features .feature-item:hover {
  box-shadow: 0 16px 40px color-mix(in srgb, var(--default-color), transparent 88%);
  border-color: color-mix(in srgb, var(--accent-color), transparent 70%);
}

/*--------------------------------------------------------------
# Rich text alignment -- front-end output
#
# Applied to whatever a RichTextField's `|richtext` filter renders,
# site-wide (this file is loaded on every page, unlike the per-app
# stylesheets). Paired with the admin-editor-only preview rules in
# static/css/richtext-align-admin.css, and registered as Draftail
# features in custom/wagtail_hooks.py -- both sides key off these same
# four class names, since that's the class Wagtail actually saves into
# the stored HTML when an editor picks an alignment.
--------------------------------------------------------------*/
.richtext-align-left {
  text-align: left;
}

.richtext-align-center {
  text-align: center;
}

.richtext-align-right {
  text-align: right;
}

.richtext-align-justify {
  text-align: justify;
}

/*--------------------------------------------------------------
# Filter pills -- generic Isotope filter buttons
#
# facility.css already has its own bespoke ".facility-filters" version of
# this same pill-button look; this is that same visual language promoted
# to a plain, app-agnostic class (deliberately NOT named ".isotope-filters"
# itself, so it doesn't retroactively restyle facility's own filters) for
# pages using the site's shared Isotope filtering (main.js's
# ".isotope-filters li" click handler) without their own dedicated
# stylesheet -- e.g. org_club_page.html's Organization Gallery, filtered
# by department.
--------------------------------------------------------------*/
.filter-pills {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem;
  list-style: none;
  padding: 0;
  margin: 0 0 2.5rem;
}

.filter-pills li {
  cursor: pointer;
  padding: 0.55rem 1.1rem;
  border-radius: 999px;
  font-weight: 600;
  font-size: 0.92rem;
  color: var(--heading-color);
  background: color-mix(in srgb, var(--heading-color), transparent 95%);
  border: 1px solid color-mix(in srgb, var(--heading-color), transparent 88%);
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
  user-select: none;
}

/* The visible label is an <a>, not the <li> itself -- without this, every
   rule above setting `color` on .filter-pills li is inheritance-only and
   loses to Bootstrap's own `a { color: var(--bs-link-color) }` (which this
   theme maps to var(--accent-color), see custom.css's --bs-link-color
   remap), since an explicit rule on the element always beats an inherited
   one regardless of the ancestor rule's specificity. Most visibly, the
   active pill's background is *also* var(--accent-color), so without this
   the active tab's text became the exact same color as its own background. */
.filter-pills li a {
  color: inherit;
}

.filter-pills li:hover {
  border-color: color-mix(in srgb, var(--accent-color), transparent 55%);
  color: var(--accent-color);
}

.filter-pills li.filter-active {
  color: #fff;
  background: var(--accent-color);
  border-color: var(--accent-color);
}

/* Optional count badge (e.g. lab_page.html's "All Laboratories 14") --
   plain Bootstrap `.badge` with no bg-* utility, so these two rules are
   the only thing setting its color either state. */
.filter-pills li .badge {
  background-color: color-mix(in srgb, var(--heading-color), transparent 85%);
  color: inherit;
}

.filter-pills li.filter-active .badge {
  background-color: color-mix(in srgb, #fff, transparent 15%);
  color: var(--accent-color);
}

@media (prefers-reduced-motion: reduce) {
  .filter-pills li {
    transition: none;
  }
}

/*--------------------------------------------------------------
# Organization Gallery department tabs (org_club_page.html)
#
# Real <a href> links, not Bootstrap's JS tab component -- filtering here
# is server-side (a page reload with a new ?dept= querystring) so gallery
# pagination stays correct, so these are just .nav-tabs restyled as an
# underline tab strip, not wired up with data-bs-toggle/role="tab".
--------------------------------------------------------------*/
.org-gallery-tabs {
  border-bottom: 1px solid color-mix(in srgb, var(--default-color), transparent 88%);
  gap: 0.25rem;
}

.org-gallery-tabs .nav-link {
  border: none;
  border-bottom: 3px solid transparent;
  border-radius: 0;
  margin-bottom: -1px;
  padding: 0.65rem 1.1rem;
  color: var(--default-color);
  font-weight: 600;
  background: transparent;
  transition: color 0.2s ease, border-color 0.2s ease;
}

.org-gallery-tabs .nav-link:hover,
.org-gallery-tabs .nav-link:focus-visible {
  color: var(--accent-color);
  border-color: color-mix(in srgb, var(--accent-color), transparent 60%);
}

.org-gallery-tabs .nav-link.active {
  color: var(--accent-color);
  border-color: var(--accent-color);
  background: transparent;
}

@media (prefers-reduced-motion: reduce) {
  .org-gallery-tabs .nav-link {
    transition: none;
  }
}

/*--------------------------------------------------------------
# Organizations & Clubs -- modern card + typography system
# (org_club_page.html, org_club_det_page.html, includes/org_club_card.html)
#
# A distinct, more premium look for this directory than the site-wide
# .hover-card: an accent-tinted outline instead of a plain grey border, and
# a soft two-layer shadow -- a tight neutral layer for edge definition plus
# a wider accent-coloured glow -- instead of one flat grey shadow. Scoped to
# its own class rather than changing .hover-card itself, since that class is
# used across many other pages this request doesn't touch.
--------------------------------------------------------------*/
.org-card {
  border: 1px solid color-mix(in srgb, var(--accent-color), transparent 88%);
  box-shadow:
    0 1px 2px color-mix(in srgb, var(--default-color), transparent 94%),
    0 10px 28px color-mix(in srgb, var(--accent-color), transparent 90%);
  transition: transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease;
}

.org-card:hover,
.org-card:focus-within {
  transform: translateY(-6px);
  border-color: color-mix(in srgb, var(--accent-color), transparent 55%);
  box-shadow:
    0 2px 6px color-mix(in srgb, var(--default-color), transparent 90%),
    0 20px 44px color-mix(in srgb, var(--accent-color), transparent 80%);
}

/* Static variant (sidebar/info cards that shouldn't lift on hover, matching
   the .hover-card / .hover-outline distinction already established). */
.org-card-static {
  border: 1px solid color-mix(in srgb, var(--accent-color), transparent 88%);
  box-shadow:
    0 1px 2px color-mix(in srgb, var(--default-color), transparent 94%),
    0 10px 28px color-mix(in srgb, var(--accent-color), transparent 92%);
}

/* Card title: tighter tracking and a touch heavier than Bootstrap's default
   card-title weight, closer to contemporary directory/marketplace card type. */
.org-card-title {
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--heading-color);
}

/* Small accent-coloured "eyebrow" label above a heading or list of facts --
   replaces the plain text-uppercase text-muted pattern for a more modern,
   editorial feel while keeping the same all-caps/small-size structure. */
.org-eyebrow {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent-color);
}

/* Section heading rule -- replaces Bootstrap's plain grey .border-bottom
   utility on the organization detail page's own section titles with a
   short, accent-coloured underline instead of a full-width grey line. */
.org-section-heading {
  position: relative;
  border-bottom: 1px solid color-mix(in srgb, var(--default-color), transparent 90%) !important;
}

.org-section-heading::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -1px;
  width: 3.5rem;
  height: 3px;
  background-color: var(--accent-color);
  border-radius: 999px;
}

/* Compact info row (activities/achievements list items) -- an accent-tinted
   outline and fill instead of Bootstrap's plain grey .border or flat
   .bg-body-tertiary, so these smaller rows still read as part of the same
   modern card language as the bigger cards on this page. */
.org-info-row {
  border: 1px solid color-mix(in srgb, var(--accent-color), transparent 88%);
  background-color: color-mix(in srgb, var(--accent-color), transparent 96%);
  transition: border-color 0.2s ease, background-color 0.2s ease;
}

.org-info-row:hover {
  border-color: color-mix(in srgb, var(--accent-color), transparent 65%);
  background-color: color-mix(in srgb, var(--accent-color), transparent 93%);
}

@media (prefers-reduced-motion: reduce) {
  .org-card {
    transition: none;
  }
}

/*--------------------------------------------------------------
# Laboratories -- modern card + typography system
# (lab_page.html, lab_det_page.html, includes/lab_card.html)
#
# Same "modern card" language as the Organizations & Clubs pages' .org-card
# above -- an accent-tinted outline and a soft two-layer shadow (a tight
# neutral layer for edge definition plus a wider accent-coloured glow)
# instead of a plain grey border/shadow. Kept as its own scoped class
# rather than reusing .org-card directly, matching this codebase's existing
# convention of a dedicated class per feature area.
--------------------------------------------------------------*/
.lab-card {
  border: 1.5px solid color-mix(in srgb, var(--accent-color), transparent 68%) !important;
  box-shadow:
    0 2px 18px color-mix(in srgb, var(--accent-color), transparent 92%);
  transition: transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease;
}

.lab-card:hover,
.lab-card:focus-within {
  transform: translateY(-6px);
  border-color: color-mix(in srgb, var(--accent-color), transparent 40%) !important;
  box-shadow:
    0 16px 44px color-mix(in srgb, var(--accent-color), transparent 78%);
}

.lab-card-img {
  transition: transform 0.45s ease;
}

.lab-card:hover .lab-card-img,
.lab-card:focus-within .lab-card-img {
  transform: scale(1.06);
}

.lab-img-overlay {
  background: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.72) 0%,
    rgba(0, 0, 0, 0.38) 45%,
    transparent 100%
  );
}

/* Static variant for panels that shouldn't lift on hover (sidebar info
   panel, stat cards) -- same outline/shadow, no transform. */
.lab-card-static {
  border: 1px solid color-mix(in srgb, var(--accent-color), transparent 88%);
  box-shadow:
    0 1px 2px color-mix(in srgb, var(--default-color), transparent 94%),
    0 10px 28px color-mix(in srgb, var(--accent-color), transparent 92%);
}

.lab-card-title {
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--heading-color);
}

/* Small accent-coloured "eyebrow" label -- same idea as .org-eyebrow, for
   the sidebar "Laboratory Information" heading. */
.lab-eyebrow {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent-color);
}

@media (prefers-reduced-motion: reduce) {
  .lab-card {
    transition: none;
  }
}

/*--------------------------------------------------------------
# Laboratories -- second design pass: decorative hero, a stat strip that
# floats over its bottom edge, a single Isotope-filtered card grid (see
# .filter-pills above -- replaced an earlier version of this block with
# real Bootstrap JS tabs switching between two differently-shaped views),
# a modernised standalone-card accordion, and a coloured closing CTA.
# (lab_page.html, lab_det_page.html)
--------------------------------------------------------------*/

/* Soft blurred colour blobs behind the hero content -- purely decorative,
   z-index'd behind everything, ignored by prefers-reduced-motion since
   nothing here animates. */
.lab-hero {
  position: relative;
  overflow: hidden;
}

.lab-hero::before,
.lab-hero::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  filter: blur(70px);
  z-index: 0;
  pointer-events: none;
}

.lab-hero::before {
  width: 26rem;
  height: 26rem;
  top: -12rem;
  right: -8rem;
  background: color-mix(in srgb, var(--accent-color), transparent 87%);
}

.lab-hero::after {
  width: 20rem;
  height: 20rem;
  bottom: -10rem;
  left: -6rem;
  background: color-mix(in srgb, var(--accent-color), transparent 92%);
}

.lab-hero > .container {
  position: relative;
  z-index: 1;
}

/* Unified stat strip: one elevated card with a divider between each
   figure, instead of four separate boxed cards repeating the same shadow
   four times. */
.lab-stat-strip {
  border: 1px solid color-mix(in srgb, var(--accent-color), transparent 88%);
  border-radius: 1rem;
  box-shadow:
    0 1px 2px color-mix(in srgb, var(--default-color), transparent 94%),
    0 10px 28px color-mix(in srgb, var(--accent-color), transparent 90%);
  overflow: hidden;
}

.lab-stat {
  padding: 1.35rem 1rem;
  border-top: 1px solid color-mix(in srgb, var(--accent-color), transparent 88%);
}

.lab-stat:first-child {
  border-top: none;
}

@media (min-width: 768px) {
  .lab-stat {
    border-top: none;
    border-left: 1px solid color-mix(in srgb, var(--accent-color), transparent 88%);
  }
  .lab-stat:first-child {
    border-left: none;
  }
}

.lab-stat-value {
  font-size: 2.1rem;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--heading-color);
}

.lab-stat-label {
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--default-color), transparent 25%);
}

/* Floating variant: pulled up over the hero's bottom edge with a negative
   top margin instead of stacking flush below it, so the strip reads as a
   bridge between the hero and the directory section rather than another
   plain stacked block. Needs its own background since it now overlaps the
   hero -- .lab-stat-strip alone doesn't set one, relying on the page's
   base background showing through. */
.lab-stat-strip--floating {
  position: relative;
  z-index: 2;
  margin-top: -3rem;
  background-color: var(--surface-color);
}

@media (max-width: 767.98px) {
  .lab-stat-strip--floating {
    margin-top: -1.5rem;
  }
}

/* Empty-state panel -- replaces the plain Bootstrap `.alert-light.border`
   box with the same accent-tinted outline language as the rest of the
   page. */
.lab-empty-state {
  border: 1px solid color-mix(in srgb, var(--accent-color), transparent 88%);
  background-color: color-mix(in srgb, var(--accent-color), transparent 97%);
  border-radius: 1rem;
  padding: 2rem 1.25rem;
}

/* Standalone-card accordion: each item is its own rounded, outlined card
   with a gap between (Bootstrap's own accordion flushes items together
   with shared borders and square inner corners) -- and the expanded
   button picks up a soft accent fill instead of Bootstrap's default
   blue-on-white active state. */
.lab-accordion .accordion-item {
  border: 1px solid color-mix(in srgb, var(--accent-color), transparent 88%);
  border-radius: 1rem;
  overflow: hidden;
  margin-bottom: 0.75rem;
  box-shadow:
    0 1px 2px color-mix(in srgb, var(--default-color), transparent 95%),
    0 6px 18px color-mix(in srgb, var(--accent-color), transparent 93%);
}

.lab-accordion .accordion-item:last-child {
  margin-bottom: 0;
}

.lab-accordion .accordion-button {
  font-weight: 700;
  color: var(--heading-color);
  background-color: var(--surface-color);
}

.lab-accordion .accordion-button:not(.collapsed) {
  background-color: color-mix(in srgb, var(--accent-color), transparent 93%);
  color: var(--accent-color);
  box-shadow: none;
}

.lab-accordion .accordion-button:focus {
  box-shadow: none;
  border-color: transparent;
}

/* Closing CTA band -- a soft accent gradient fill instead of the plain
   .hover-outline treatment used for this same banner pattern elsewhere on
   the site (kept as its own class rather than changing .hover-outline
   itself, which many other pages still use as-is). */
.lab-cta {
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--accent-color), transparent 92%),
    color-mix(in srgb, var(--accent-color), transparent 97%));
  border: 1px solid color-mix(in srgb, var(--accent-color), transparent 82%);
}

/*--------------------------------------------------------------
# Generic decorative hero background -- soft blurred colour blobs behind
# hero content. Same recipe as .lab-hero above, given a plain, honest name
# since it has no lab-specific logic at all -- reused here for
# student_page.html / stud_life_page.html rather than adding a third
# near-identical scoped copy. (.lab-hero itself is left alone, already
# shipped and verified.)
--------------------------------------------------------------*/
.hero-blobs {
  position: relative;
  overflow: hidden;
}

.hero-blobs::before,
.hero-blobs::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  filter: blur(70px);
  z-index: 0;
  pointer-events: none;
}

.hero-blobs::before {
  width: 26rem;
  height: 26rem;
  top: -12rem;
  right: -8rem;
  background: color-mix(in srgb, var(--accent-color), transparent 87%);
}

.hero-blobs::after {
  width: 20rem;
  height: 20rem;
  bottom: -10rem;
  left: -6rem;
  background: color-mix(in srgb, var(--accent-color), transparent 92%);
}

.hero-blobs > .container {
  position: relative;
  z-index: 1;
}

/*--------------------------------------------------------------
# Student Life -- modern card + typography system
# (student_page.html, stud_life_page.html, includes/category_card.html)
#
# Same "modern card" language as .org-card / .lab-card above.
--------------------------------------------------------------*/
.stud-card {
  border: 1px solid color-mix(in srgb, var(--accent-color), transparent 88%);
  box-shadow:
    0 1px 2px color-mix(in srgb, var(--default-color), transparent 94%),
    0 10px 28px color-mix(in srgb, var(--accent-color), transparent 90%);
  transition: transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease;
}

.stud-card:hover,
.stud-card:focus-within {
  transform: translateY(-6px);
  border-color: color-mix(in srgb, var(--accent-color), transparent 55%);
  box-shadow:
    0 2px 6px color-mix(in srgb, var(--default-color), transparent 90%),
    0 20px 44px color-mix(in srgb, var(--accent-color), transparent 80%);
}

.stud-card-static {
  border: 1px solid color-mix(in srgb, var(--accent-color), transparent 88%);
  box-shadow:
    0 1px 2px color-mix(in srgb, var(--default-color), transparent 94%),
    0 10px 28px color-mix(in srgb, var(--accent-color), transparent 92%);
}

.stud-card-title {
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--heading-color);
}

.stud-eyebrow {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent-color);
}

.stud-empty-state {
  border: 1px solid color-mix(in srgb, var(--accent-color), transparent 88%);
  background-color: color-mix(in srgb, var(--accent-color), transparent 97%);
  border-radius: 1rem;
  padding: 2rem 1.25rem;
}

@media (prefers-reduced-motion: reduce) {
  .stud-card {
    transition: none;
  }
}

/*--------------------------------------------------------------
# Page Preloader
#
# Full-viewport overlay shown while the page's HTML, styles and
# images finish loading, hidden by the inline <script> right after
# #page-preloader in templates/base.html once the browser's `load`
# event fires (see that script for why `load` alone already covers
# "wait for images, but don't hang on a broken one", and why the hide
# logic lives inline instead of in static/js/custom.js).
#
# Kept here rather than assets/css/main.css even though it reuses
# the vendor CoreBiz template's `imagesloaded` script and load-
# event idiom in spirit: main.css/main.js already ship a dormant
# `#preloader` (a 4-dot bounce, never actually placed in any
# template) -- this is a separate, deliberately different id so
# the two never collide, letting the vendor file stay untouched.
--------------------------------------------------------------*/
#page-preloader {
  position: fixed;
  inset: 0;
  z-index: 999999;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  /* Blue-tinted white — slightly off-white so the accent glows read
     against the background instead of washing out */
  background: #f0f4ff;
  transition: opacity 0.6s ease, visibility 0.6s ease;
}

/* Two-layer radial background: centre bloom + bottom vignette */
#page-preloader::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(
      ellipse 65% 60% at 50% 48%,
      color-mix(in srgb, var(--accent-color) 12%, transparent) 0%,
      transparent 70%
    ),
    radial-gradient(
      ellipse 120% 55% at 50% 110%,
      color-mix(in srgb, var(--accent-color) 8%, transparent) 0%,
      transparent 60%
    );
  pointer-events: none;
}

#page-preloader.page-preloader-hidden {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

/* Spinner container — circular elevated card */
.page-preloader-inner {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 90px;
  height: 90px;
  border-radius: 50%;
  background: #ffffff;
  /* Three-layer shadow: tight edge ring, mid diffuse, wide ambient */
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--accent-color) 8%, transparent),
    0 4px 14px color-mix(in srgb, var(--accent-color) 16%, transparent),
    0 12px 32px color-mix(in srgb, var(--accent-color) 12%, transparent),
    0 20px 44px rgba(0, 0, 0, 0.07);
}

/* Animated glow bloom that pulses behind the logo */
.page-preloader-inner::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  background: radial-gradient(
    circle at center,
    color-mix(in srgb, var(--accent-color) 14%, transparent) 0%,
    transparent 72%
  );
  animation: page-preloader-glow-bloom 2.4s ease-in-out infinite;
}

/* Outer ring — slow clockwise */
.page-preloader-ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid transparent;
  border-top-color: var(--accent-color);
  border-right-color: color-mix(in srgb, var(--accent-color) 40%, transparent);
  animation: page-preloader-spin 1.3s cubic-bezier(0.37, 0, 0.63, 1) infinite;
}

/* Inner ring — faster, counter-clockwise */
.page-preloader-ring--inner {
  inset: 11px;
  border-width: 1.5px;
  border-top-color: transparent;
  border-bottom-color: color-mix(in srgb, var(--accent-color) 85%, transparent);
  border-left-color: color-mix(in srgb, var(--accent-color) 35%, transparent);
  animation: page-preloader-spin-reverse 0.9s cubic-bezier(0.37, 0, 0.63, 1) infinite;
}

/* Logo — float animation also breathes the shadow:
   resting position has a soft cast shadow,
   lifted position brightens into a full glow */
.page-preloader-logo {
  position: relative;
  width: 42px;
  height: auto;
  border-radius: 0.5rem;
  z-index: 1;
  animation: page-preloader-float 2.4s ease-in-out infinite;
}

/* Three-dot bounce */
.page-preloader-dots {
  display: flex;
  align-items: center;
  gap: 6px;
}

.page-preloader-dots span {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent-color);
  opacity: 0.25;
  animation: page-preloader-dot 1.2s ease-in-out infinite;
}

.page-preloader-dots span:nth-child(1) { animation-delay: 0s; }
.page-preloader-dots span:nth-child(2) { animation-delay: 0.18s; }
.page-preloader-dots span:nth-child(3) { animation-delay: 0.36s; }

/* Shimmer progress bar at bottom */
.page-preloader-bar {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: color-mix(in srgb, var(--accent-color) 10%, transparent);
  overflow: hidden;
}

.page-preloader-bar::after {
  content: '';
  position: absolute;
  top: 0;
  left: -65%;
  width: 55%;
  height: 100%;
  background: linear-gradient(
    90deg,
    transparent 0%,
    color-mix(in srgb, var(--accent-color) 60%, transparent) 40%,
    var(--accent-color) 60%,
    transparent 100%
  );
  border-radius: 0 2px 2px 0;
  animation: page-preloader-shimmer 1.5s ease-in-out infinite;
}

@keyframes page-preloader-spin {
  to { transform: rotate(360deg); }
}

@keyframes page-preloader-spin-reverse {
  to { transform: rotate(-360deg); }
}

/* Float up + shadow breathes: resting = cast shadow, lifted = glow halo */
@keyframes page-preloader-float {
  0%, 100% {
    transform: translateY(0);
    filter:
      drop-shadow(0 6px 16px color-mix(in srgb, var(--accent-color) 30%, transparent))
      drop-shadow(0 10px 28px rgba(0, 0, 0, 0.14));
  }
  50% {
    transform: translateY(-7px);
    filter:
      drop-shadow(0 0 14px color-mix(in srgb, var(--accent-color) 55%, transparent))
      drop-shadow(0 0 36px color-mix(in srgb, var(--accent-color) 30%, transparent))
      drop-shadow(0 18px 36px rgba(0, 0, 0, 0.07));
  }
}

/* Glow bloom that scales up in sync with the logo rising */
@keyframes page-preloader-glow-bloom {
  0%, 100% { transform: translate(-50%, -50%) scale(1);   opacity: 0.55; }
  50%       { transform: translate(-50%, -50%) scale(1.5); opacity: 1;    }
}

@keyframes page-preloader-dot {
  0%, 80%, 100% { transform: scale(1);   opacity: 0.25; }
  40%           { transform: scale(1.6); opacity: 1;    }
}

@keyframes page-preloader-shimmer {
  0%   { left: -65%; }
  100% { left: 110%; }
}

@media (max-width: 575.98px) {
  .page-preloader-inner {
    width: 76px;
    height: 76px;
  }

  .page-preloader-ring--inner {
    inset: 9px;
  }

  .page-preloader-logo {
    width: 34px;
  }

  .page-preloader-inner::before {
    width: 42px;
    height: 42px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .page-preloader-ring,
  .page-preloader-ring--inner,
  .page-preloader-logo,
  .page-preloader-dots span,
  .page-preloader-bar::after,
  .page-preloader-inner::before {
    animation: none;
  }

  #page-preloader {
    transition: none;
  }
}

/*--------------------------------------------------------------
# Footer — dark-background overrides
# The dark footer sets --background-color to the same value as
# --accent-color (#102799). The theme's default hover state for
# links uses var(--accent-color), making all hover text invisible
# against the background. Everything below fixes that and adds
# modern hover polish.
--------------------------------------------------------------*/

/* Section headings: subtle separator line */
.footer.dark-background h4 {
  color: #ffffff;
  letter-spacing: 0.4px;
  padding-bottom: 14px;
  margin-bottom: 18px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.15);
}

/* About block */
.footer.dark-background .footer-about a {
  color: #ffffff;
}

.footer.dark-background .footer-about a:hover {
  color: rgba(255, 255, 255, 0.75);
}

.footer.dark-background .footer-about p {
  color: rgba(255, 255, 255, 0.75);
  line-height: 1.75;
}

/* Social media list — icon + name layout */
.footer.dark-background .footer-social {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.footer.dark-background .footer-social-item {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
  color: rgba(255, 255, 255, 0.72);
  transition: color 0.25s ease, transform 0.25s ease;
  width: fit-content;
}

.footer.dark-background .footer-social-icon {
  width: 36px;
  height: 36px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.25);
  background-color: rgba(255, 255, 255, 0.08);
  font-size: 16px;
  transition: background-color 0.25s ease, border-color 0.25s ease, color 0.25s ease;
}

.footer.dark-background .footer-social-name {
  font-size: 14px;
  font-weight: 500;
  line-height: 1;
}

.footer.dark-background .footer-social-item:hover {
  color: #ffffff;
  transform: translateX(5px);
}

.footer.dark-background .footer-social-item:hover .footer-social-icon {
  background-color: rgba(255, 255, 255, 0.2);
  border-color: #ffffff;
  color: #ffffff;
}

/* Chevron icons inside service links */
.footer.dark-background .footer-links ul i {
  color: rgba(255, 255, 255, 0.45);
  font-size: 13px;
  margin-right: 5px;
  transition: color 0.25s ease, transform 0.25s ease;
  display: inline-block;
  line-height: 1;
}

/* Row separator lines */
.footer.dark-background .footer-links ul li {
  padding: 9px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  transition: transform 0.25s ease;
}

.footer.dark-background .footer-links ul li:first-child {
  padding-top: 0;
  border-top: none;
}

.footer.dark-background .footer-links ul li:last-child {
  border-bottom: none;
}

/* Link text: dim at rest, full white on hover with a slide */
.footer.dark-background .footer-links ul a {
  color: rgba(255, 255, 255, 0.72);
  display: inline-flex;
  align-items: center;
  transition: color 0.25s ease, transform 0.25s ease;
}

.footer.dark-background .footer-links ul a:hover {
  color: #ffffff;
  transform: translateX(5px);
}

.footer.dark-background .footer-links ul a:hover i {
  color: #ffffff;
  transform: translateX(2px);
}

/* Contact section */
.footer.dark-background .footer-contact p {
  color: rgba(255, 255, 255, 0.76);
  line-height: 1.65;
}

.footer.dark-background .footer-contact strong {
  color: #ffffff;
}

.footer.dark-background .footer-contact span {
  color: rgba(255, 255, 255, 0.72);
}

/* Copyright row */
.footer.dark-background .copyright {
  border-top-color: rgba(255, 255, 255, 0.18);
  color: rgba(255, 255, 255, 0.6);
}

.footer.dark-background .copyright .sitename {
  color: #ffffff;
}

.footer.dark-background .credits {
  color: rgba(255, 255, 255, 0.48);
}

/* ── Visitor country stats widget ─────────────────────────────────────── */
.visitor-country-card {
  background: #fff;
  border: 1px solid #e8e8f0;
  border-radius: 12px;
  padding: 18px 12px 14px;
  box-shadow: 0 2px 8px rgba(0,0,0,.05);
  transition: transform .2s, box-shadow .2s;
}
.visitor-country-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 6px 18px rgba(0,0,0,.10);
}
.visitor-flag {
  font-size: 2.2rem;
  line-height: 1.2;
  margin-bottom: 6px;
}
.visitor-name {
  font-size: .78rem;
  font-weight: 600;
  color: #333;
  margin-bottom: 4px;
  line-height: 1.3;
  word-break: break-word;
}
.visitor-count {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--accent-color, #2e1f5e);
  line-height: 1.2;
}
.visitor-bar {
  background: #eee;
  border-radius: 4px;
  height: 5px;
  margin: 6px 0 3px;
  overflow: hidden;
}
.visitor-bar-fill {
  background: var(--accent-color, #2e1f5e);
  height: 100%;
  border-radius: 4px;
  transition: width .4s ease;
}
.visitor-pct {
  font-size: .7rem;
  color: #aaa;
}
.visitor-stats-section .section-title h2 {
  font-size: 1.6rem;
}
.visitor-stats-section .section-title p {
  font-size: .95rem;
}

/*--------------------------------------------------------------
# About Page -- modern Vision/Mission/Objectives/Values cards
# (about/templates/about/about_page.html)
#
# Each card uses a --vm-color custom property set inline on the element,
# letting one class handle four visually distinct cards (blue, teal,
# amber, purple) without four separate modifier classes.
--------------------------------------------------------------*/
.about-vm-card {
  background: var(--surface-color);
  border: none !important;
  border-top: 4px solid var(--vm-color, var(--accent-color)) !important;
  border-radius: 1rem !important;
  box-shadow:
    0 2px 8px rgba(0,0,0,.06),
    0 4px 24px color-mix(in srgb, var(--vm-color, var(--accent-color)), transparent 88%);
  transition: transform 0.32s ease, box-shadow 0.32s ease;
  position: relative;
  overflow: hidden;
}

.about-vm-card::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    135deg,
    color-mix(in srgb, var(--vm-color, var(--accent-color)), transparent 93%) 0%,
    transparent 55%
  );
  pointer-events: none;
  border-radius: inherit;
}

.about-vm-card:hover {
  transform: translateY(-7px);
  box-shadow:
    0 4px 12px rgba(0,0,0,.08),
    0 18px 44px color-mix(in srgb, var(--vm-color, var(--accent-color)), transparent 76%);
}

.about-vm-icon {
  width: 68px;
  height: 68px;
  flex-shrink: 0;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.65rem;
  color: var(--vm-color, var(--accent-color));
  background: color-mix(in srgb, var(--vm-color, var(--accent-color)), transparent 84%);
  transition: background 0.32s ease, color 0.32s ease, transform 0.32s ease;
}

.about-vm-card:hover .about-vm-icon {
  background: var(--vm-color, var(--accent-color));
  color: #fff;
  transform: scale(1.1) rotate(6deg);
}

.about-vm-label {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--vm-color, var(--accent-color));
  opacity: 0.75;
  display: block;
  margin-bottom: 0.2rem;
}

/* About section hero -- fac_code badge with gradient fill */
.about-fac-badge {
  background: linear-gradient(
    135deg,
    color-mix(in srgb, var(--accent-color), transparent 82%),
    color-mix(in srgb, var(--accent-color), transparent 70%)
  );
  color: var(--accent-color);
  border: 1px solid color-mix(in srgb, var(--accent-color), transparent 68%);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
}

/* Decorative accent dot strip below "About FECT" heading */
.about-section-divider {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 1.25rem;
}

.about-section-divider span {
  display: inline-block;
  height: 4px;
  border-radius: 999px;
  background: var(--accent-color);
}

@media (prefers-reduced-motion: reduce) {
  .about-vm-card,
  .about-vm-icon {
    transition: none;
  }
}

/*--------------------------------------------------------------
# show_more_dialog modal -- modern design
# (custom/templates/custom/includes/show_more_dialog.html)
--------------------------------------------------------------*/

/* Icon circle inside the gradient modal header */
.sm-modal-icon {
  width: 56px;
  height: 56px;
  font-size: 1.55rem;
  color: #fff;
  background: rgba(255, 255, 255, 0.18);
  border: 1.5px solid rgba(255, 255, 255, 0.28);
  flex-shrink: 0;
  transition: background 0.25s ease;
}

.modal:hover .sm-modal-icon {
  background: rgba(255, 255, 255, 0.26);
}

/* "Faculty Profile" eyebrow label */
.sm-modal-eyebrow {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.65);
}

/* Modal body: readable richtext with comfortable spacing */
.sm-modal-body {
  background: var(--surface-color);
}

.sm-modal-content {
  color: var(--default-color);
  font-size: 0.975rem;
  line-height: 1.85;
}

.sm-modal-content p {
  margin-bottom: 0.9rem;
}

.sm-modal-content p:last-child {
  margin-bottom: 0;
}

.sm-modal-content ul,
.sm-modal-content ol {
  padding-left: 1.35rem;
  margin-bottom: 0.9rem;
}

.sm-modal-content li {
  margin-bottom: 0.35rem;
}

.sm-modal-content h1,
.sm-modal-content h2,
.sm-modal-content h3,
.sm-modal-content h4,
.sm-modal-content h5,
.sm-modal-content h6 {
  color: var(--heading-color);
  font-weight: 700;
  margin-top: 1.25rem;
  margin-bottom: 0.5rem;
}

.sm-modal-content strong,
.sm-modal-content b {
  color: var(--heading-color);
  font-weight: 600;
}

/* "Read more" trigger button -- subtle underline-grow on hover */
.show-more-toggle {
  position: relative;
  transition: color 0.2s ease, gap 0.2s ease;
}

.show-more-toggle::after {
  content: '';
  position: absolute;
  bottom: -2px;
  left: 0;
  width: 0;
  height: 1.5px;
  background: var(--accent-color);
  border-radius: 999px;
  transition: width 0.25s ease;
}

.show-more-toggle:hover::after {
  width: 100%;
}

.show-more-toggle:hover .show-more-icon {
  transform: translateX(3px);
  transition: transform 0.2s ease;
}

@media (prefers-reduced-motion: reduce) {
  .show-more-toggle::after,
  .show-more-icon {
    transition: none;
  }
}