/* ==========================================================================
   bayan-cms-media.css — makes editor-supplied images safe in template slots.

   The EduSpace markup was built around hand-cropped artwork, so most image
   slots have no aspect constraint at all: whatever you put in, the card grows
   to fit. That is fine for a designer's 640x427 photo and ruinous for what
   the university actually publishes — 141 of the migrated images are portrait
   (some 2480x3508 event posters, one 5037x3072 camera original), and dropping
   one into a news card stretches it several screens tall and pushes the text
   out of its own box.

   So every slot the CMS can fill gets a fixed ratio and object-fit: cover.
   The card keeps its designed shape no matter what is uploaded, and nobody
   has to crop before publishing.

   Loads after the template and the theme; only touches images inside CMS
   slots, never the template's own decorative art.
   ========================================================================== */

/* ------------------------------------------------------------- news --- */
.news-left-items .news-thumb {
  overflow: hidden;
  border-radius: 12px;
}
.news-left-items .news-thumb img {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: center;
  display: block;
}

.news-right-items .news-thumb {
  overflow: hidden;
  border-radius: 10px;
  flex: 0 0 auto;
}
.news-right-items .news-thumb img {
  width: 120px;
  height: 120px;
  aspect-ratio: 1;
  object-fit: cover;
  object-position: center;
  display: block;
}

/* The right-hand list is a row of thumbnail + text; without a min-width of 0
   a long untranslated headline can force the row wider than its column. */
.news-right-items {
  display: flex;
  gap: 16px;
  align-items: center;
}
.news-right-items .news-content {
  min-width: 0;
  flex: 1;
}
.news-right-items .news-content h4 {
  overflow-wrap: anywhere;
}

/* Migrated headlines run long. Clamp them so a card stays a card. */
.news-left-items .news-content h3,
.news-right-items .news-content h4 {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.news-left-items .news-content p {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ------------------------------------------------------------ events --- */
/* Event cards are background-image based, so they cannot stretch — but the
   title can, and an untruncated migrated title overlaps the meta row. */
.event-card-items .content h4 {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.event-card-items .post-cat {
  white-space: nowrap;
}

/* The template paints a solid white ::before over every event card and only
   swaps it for a translucent scrim on :hover or .active — so the photograph,
   the title colour and the button were all hidden until the pointer landed on
   a card, and one arbitrary card (the template marks the second `active`)
   looked different from the rest. On a touch screen there is no hover at all,
   so the strip simply read as a row of blank white boxes.
   Every card now shows its picture and its content at rest; hover only
   deepens the scrim, which is what the effect was presumably for. */
.event-wrapper .event-card-items::before {
  /* At rest the photograph is shown as it is. The only darkening is a
     bottom-up gradient behind the caption: the title and the button are white
     and sit on top of the picture, and Bayan's event posters are mostly light,
     so without it the text disappears into them. It fades to fully clear by
     the upper half, which is where the faces and the crest are. */
  background: linear-gradient(
    to top,
    rgba(51, 32, 10, 0.88) 0%,
    rgba(51, 32, 10, 0.55) 28%,
    rgba(51, 32, 10, 0) 55%
  );
}
.event-wrapper .event-card-items:hover::before,
.event-wrapper .event-card-items:focus-within::before {
  /* The full brown wash is the hover state, as it was in the template. */
  background: rgba(51, 32, 10, 0.85);
}

/* The content block was translated down out of view and the button faded out,
   both restored only on hover. */
.event-wrapper .event-card-items .content {
  transform: translateY(0);
}
.event-wrapper .event-card-items .content h4 a,
.event-wrapper .event-card-items .content .date-list li,
.event-wrapper .event-card-items .content .date-list li i {
  color: var(--white);
  /* Bayan's posters are busy, so a title can land on a pale patch even inside
     the gradient. A shadow buys the contrast back without darkening the
     picture any further, which is the thing to avoid here. */
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.55);
}
.event-wrapper .event-card-items .content .theme-btn {
  margin-bottom: 0;
  opacity: 1;
  visibility: visible;
}

/* A card with no photograph fell back to a template stock image; a flat brand
   panel is honest where borrowed artwork is not. */
.event-wrapper .event-card-items {
  background-color: #33200a;
}

/* ---- separated grid ------------------------------------------------------
   The template's strip is four cards butted together inside one bordered box,
   separated by hairlines and sized by their own text — so a two-line title
   made a shorter card than a three-line one, and the row came out ragged.
   As a spaced grid each card is its own tile: one fixed height for all of
   them, its own rounded frame, and the caption pinned to the bottom. */
.event-wrapper--grid {
  border: none;
}
.event-wrapper--grid .event-card-items {
  height: 100%;
  min-height: 420px;
  padding: 26px;
  border-right: none;
  border-radius: 10px;
  display: flex;
  flex-direction: column;
  /* flex-end, not space-between: the date badge is absolutely positioned by
     the template (top: 40px), so .content is the only child actually in the
     flex flow — and space-between leaves a lone child at the start, which put
     the caption at the top of the card overlapping the badge. */
  justify-content: flex-end;
  align-items: flex-start;
}
.event-wrapper--grid .event-card-items::before {
  border-radius: 10px;
}
.event-wrapper--grid .event-card-items .content {
  /* The template pushed the caption down with a 130px top margin, which is
     what made the card's height depend on its title. */
  margin-top: 0;
  width: 100%;
}
.event-wrapper--grid .event-card-items .content h4 {
  /* Two lines for every card, so the captions line up across the row. */
  -webkit-line-clamp: 2;
  min-height: 2.6em;
}

@media (max-width: 575px) {
  .event-wrapper--grid .event-card-items {
    min-height: 340px;
    padding: 20px;
  }
}

/* ----------------------------------------------------- testimonials --- */
.testimonial-card-items .client-img img,
.testimonial-items .client-img img,
.testimonial-card-items img[class*="avatar"] {
  width: 80px;
  height: 80px;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 50%;
}

/* --------------------------------------------------------- partners --- */
/* Logos arrive at wildly different sizes; contain keeps them from cropping
   and the height cap keeps the row even. */
.brand-image img {
  max-width: 100%;
  max-height: 70px;
  width: auto;
  height: auto;
  object-fit: contain;
}

/* -------------------------------------------------- gallery / strip --- */
.instagram-image {
  overflow: hidden;
}
.instagram-image img {
  width: 100%;
  height: auto;
  aspect-ratio: 1;
  object-fit: cover;
  display: block;
}

/* ------------------------------------------------------------ about --- */
.about-image > img,
.faq-image img,
.video-image > img {
  max-width: 100%;
  height: auto;
}
.video-image {
  overflow: hidden;
}
.video-image > img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

/* -------------------------------------------------------- blog list --- */
.single-blog-post .post-featured-thumb {
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}
.single-blog-post .post-content h2 {
  overflow-wrap: anywhere;
}

/* ---------------------------------------------------------- staff ------ */
.team-image img,
.instructor-image img {
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  object-position: top center;
}

/* --------------------------------------------------------- global ------ */
/* Nothing the CMS renders may exceed its column, whatever its intrinsic
   width. This is the backstop for slots not listed above. */
.news-section img,
.event-section img,
.testimonial-section-3 img,
.global-partners-section img,
.instagram-section img,
.faq-section img {
  max-width: 100%;
}

/* Long unbroken strings — a URL pasted into a title, an Arabic word with no
   spaces — must wrap rather than widen their container. */
.news-content h3,
.news-content h4,
.news-content p,
.event-card-items h4,
.bu-college__name {
  overflow-wrap: break-word;
}

@media (max-width: 575px) {
  .news-right-items .news-thumb img {
    width: 88px;
    height: 88px;
  }
}

/* ==========================================================================
   .bu-footer — the site footer.

   Written from scratch rather than reusing the template's `.footer-section-3`
   grid, which was shaped around the EduSpace demo's four link widgets. With
   this content it collapsed to one stacked column, and under RTL that left
   everything pinned to one edge with a screenful of empty space beside it.

   A three-column CSS grid with logical properties instead: the layout is
   symmetric in both reading directions and needs no RTL-specific overrides.
   ========================================================================== */

.bu-footer {
  background: #faf7f1;
  border-top: 1px solid #efe7d8;
  color: #5c5348;
  padding-block-start: 64px;
}

.bu-footer .container {
  max-width: 1320px;
  margin-inline: auto;
  padding-inline: 20px;
}

.bu-footer__grid {
  display: grid;
  /* Brand column takes the slack; the two list columns stay compact. */
  grid-template-columns: minmax(260px, 1.5fr) repeat(2, minmax(200px, 1fr));
  gap: 40px 56px;
  padding-block-end: 52px;
}

.bu-footer__col { min-width: 0; }

.bu-footer__logo img {
  height: 52px;
  width: auto;
  margin-block-end: 18px;
}
.bu-footer__intro {
  margin: 0;
  font-size: 15px;
  line-height: 1.75;
  max-width: 42ch;
}

.bu-footer__head {
  font-size: 17px;
  font-weight: 700;
  color: #33200a;
  margin: 0 0 18px;
  position: relative;
  padding-block-end: 10px;
}
.bu-footer__head::after {
  content: "";
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: 0;
  width: 34px;
  height: 2px;
  background: var(--theme-blue, #0066b3);
}

.bu-footer__links,
.bu-footer__contact {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.bu-footer__links a {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: #5c5348;
  font-size: 15px;
  text-decoration: none;
  transition: color 0.16s ease, gap 0.16s ease;
}
.bu-footer__links a:hover {
  color: var(--theme-blue, #0066b3);
  gap: 13px;
}
/* The chevron must point the way the text reads. */
.bu-footer__links i {
  font-size: 10px;
  opacity: 0.55;
}
[dir="rtl"] .bu-footer__links i { transform: scaleX(-1); }

.bu-footer__contact li {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  font-size: 15px;
  line-height: 1.65;
  /* An email address is one unbreakable token; in a narrow phone column it
     runs straight out of the card unless it is allowed to break. */
  min-width: 0;
  overflow-wrap: anywhere;
}
.bu-footer__contact li > span,
.bu-footer__contact li > a,
.bu-footer__contact bdi {
  min-width: 0;
  overflow-wrap: anywhere;
}
.bu-footer__contact i {
  color: var(--theme-blue, #0066b3);
  font-size: 14px;
  margin-block-start: 4px;
  flex: 0 0 auto;
}
.bu-footer__contact a {
  color: inherit;
  text-decoration: none;
}
.bu-footer__contact a:hover { color: var(--theme-blue, #0066b3); }

.bu-footer__bar {
  border-top: 1px solid #efe7d8;
  padding-block: 20px;
}
.bu-footer__barinner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
.bu-footer__barinner p {
  margin: 0;
  font-size: 14px;
}
.bu-footer__barinner ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  gap: 22px;
}
.bu-footer__barinner a {
  color: #5c5348;
  font-size: 14px;
  text-decoration: none;
}
.bu-footer__barinner a:hover { color: var(--theme-blue, #0066b3); }

@media (max-width: 991px) {
  .bu-footer__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 34px 32px;
  }
  .bu-footer__col--brand { grid-column: 1 / -1; }
}

/* Phones keep the two link columns side by side rather than collapsing to one
   tall stack — six links and three contact rows in a single column push the
   copyright bar most of a screen further down for no benefit. Only the brand
   block spans the full width. */
@media (max-width: 575px) {
  .bu-footer { padding-block-start: 44px; }
  .bu-footer__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 28px 20px;
    padding-block-end: 32px;
  }
  .bu-footer__col--brand {
    grid-column: 1 / -1;
    text-align: center;
  }
  .bu-footer__col--brand .bu-footer__intro {
    margin-inline: auto;
    max-width: 34ch;
  }
  .bu-footer__logo img { height: 44px; }

  .bu-footer__head { font-size: 15px; margin-block-end: 14px; }
  .bu-footer__links,
  .bu-footer__contact { gap: 10px; }
  .bu-footer__links a { font-size: 14px; gap: 7px; }
  .bu-footer__contact li { font-size: 13.5px; gap: 8px; }
  .bu-footer__contact i { font-size: 12px; }

  .bu-footer__barinner {
    justify-content: center;
    text-align: center;
    gap: 10px;
  }
  .bu-footer__barinner ul { gap: 18px; }
}

/* Below ~360px two columns genuinely stop fitting. */
@media (max-width: 359px) {
  .bu-footer__grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   University header: one nav row, larger crest.

   The template's bar was sized for six short English words. Seven sections in
   Kurdish and Arabic are longer, and with the language switcher and search
   beside them the row wrapped onto a second line. Tightening the item spacing
   and stopping labels breaking mid-word keeps it on one line at desktop
   widths; below 1200px the template already swaps to the offcanvas menu.
   ========================================================================== */

.header-3 .header-main {
  gap: 18px;
  flex-wrap: nowrap;
}

/* The inner pages render the same bar, so the no-wrap rules have to apply
   there too — without this the seven sections spilled onto a second line on
   /about, /events and the rest. */
.header-section-3 .header-main {
  flex-wrap: nowrap;
}

.header-3 .main-menu nav > ul > li {
  margin-inline: 0;
}
.header-3 .main-menu nav > ul > li > a {
  padding-inline: 11px;
  font-size: 15px;
  /* A section name must never break across two lines. */
  white-space: nowrap;
}

/* The nav takes the slack so the logo and the right-hand controls keep their
   size instead of being squeezed. */
.header-3 .header-left {
  flex: 1 1 auto;
  min-width: 0;
}
.header-3 .main-menu nav > ul {
  display: flex;
  flex-wrap: nowrap;
  justify-content: center;
}

/* A university crest carries the institution's identity — it was rendering
   smaller than the search icon beside it. */
.header-3 .header-logo img,
.header-3 .header-logo-2 img {
  height: 62px;
  width: auto;
  max-width: none;
}
.header-3 .header-logo,
.header-3 .header-logo-2 {
  flex: 0 0 auto;
}

/* The template's .container caps the header at 1266px, which was ample for its
   five-item demo nav. Bayan's navigation carries seven sections with names as
   long as "Quality Assurance & Research", and it needs 958px of the 790px the
   capped container left it — so the row overflowed under the language switcher
   instead of wrapping (flex-wrap: nowrap above turns a wrap into an overflow).
   Letting the header alone use the full width returns ~250px and the nav fits.
   Only the header container is widened; page content keeps the template grid. */
@media (min-width: 1200px) {
  .header-3 > .container,
  .header-section-3 .container {
    max-width: calc(100% - 64px);
  }
}

/* Applied at every desktop width, not just a middle band: at exactly 1600px
   the nav still needed 1078px of 1030px, because the band stopped at 1599. */
@media (min-width: 1200px) {
  .header-3 .main-menu nav > ul > li > a {
    padding-inline: 7px;
    font-size: 14px;
  }
  .header-3 .header-main { gap: 12px; }
}

@media (max-width: 1399px) {
  .header-3 .main-menu nav > ul > li > a {
    padding-inline: 8px;
    font-size: 14.5px;
  }
  .header-3 .header-logo img,
  .header-3 .header-logo-2 img { height: 54px; }
}

/* The band the tuning above did not reach: 1200px to 1400px.
 *
 * The template swaps to the offcanvas menu at 1200px — `d-xl-none` on the
 * hamburger — which was the right line for its six short demo labels. It is
 * not the right line for seven sections named "Quality Assurance & Research"
 * and "Services & Facilities": at 1280px the row needed 767px of the ~695px
 * left beside the crest and the language switcher, so the last section ran
 * underneath the switcher and was clipped at the window edge. That is the
 * section holding Facilities, Centres, Careers, Documents and International,
 * so the clipped item was not a decorative one.
 *
 * Shrinking further was tried and rejected: clearing 1200px in all three
 * languages needed an 11px label, and Kurdish and Arabic at 11px are not
 * readable. Moving the swap point up is the honest fix — the offcanvas
 * carries the same database-driven tree, in full, with room for it.
 *
 * `!important` is required only because Bootstrap's own `.d-xl-none` is
 * declared with it; nothing else here overrides a utility class.
 */
@media (max-width: 1399.98px) {
  .header-3 .mean__menu-wrapper {
    display: none;
  }
  .header-3 .header__hamburger.d-xl-none {
    display: block !important;
  }
}

/* Just above that line the bar comes back, and Kurdish is the width that
 * decides whether it fits: its seven labels measure 881px against English's
 * 767px, so at 1400px the row wanted 1346px of the 1312px available. Six
 * pixels off each item returns 42px, which clears it. Above 1600px there is
 * room without this, so the wider spacing stands there. */
@media (min-width: 1400px) and (max-width: 1599.98px) {
  .header-3 .main-menu nav > ul > li > a {
    padding-inline: 4px;
  }
}

@media (max-width: 1199px) {
  /* Below this the template shows the hamburger, so the crest can grow back. */
  .header-3 .header-logo img,
  .header-3 .header-logo-2 img { height: 56px; }
}

@media (max-width: 575px) {
  .header-3 .header-logo img,
  .header-3 .header-logo-2 img { height: 46px; }
}

/* ------------------------------------------------- detail page images --- */
/* Bayan's events and news are illustrated with announcement POSTERS, not
   landscape photographs — the one for the Ethiopian Renaissance Dam seminar is
   2480x3068. The template's detail layouts assume a wide hero and put no
   constraint on the image at all, so a poster rendered at its own proportions:
   836px wide by 1034px tall, taller than the viewport, pushing the Event
   Information panel and everything under it out of alignment.

   Capped height with object-fit: contain, on a brand panel. `contain` rather
   than `cover` because a poster carries the title, the speakers and the time
   as text — cropping it to a landscape strip cuts the information out. A
   landscape photograph letterboxes slightly at the sides instead, which is the
   cheaper of the two compromises. */
.details-image,
.single-post-image,
.courses-image,
.event-image-items {
  background-color: #33200a;
  border-radius: 10px;
  overflow: hidden;
}

.details-image img,
.single-post-image img,
.courses-image img,
.event-image-items img {
  display: block;
  width: 100%;
  max-height: 480px;
  object-fit: contain;
}

@media (max-width: 991px) {
  .details-image img,
  .single-post-image img,
  .courses-image img,
  .event-image-items img {
    max-height: 380px;
  }
}

/* A staff portrait is a face: crop to a square rather than letterbox it. */
.team-details-image img,
.instructor-details-image img {
  width: 100%;
  max-height: 460px;
  object-fit: cover;
  object-position: top center;
  border-radius: 10px;
}

/* ------------------------------------------------------ page banner --- */
/*
   The photograph is the banner, not a card inside it.
                      ────────────
   The template put the picture in a rounded box below the heading, with the
   brown showing around it and a white block filling the lower third behind
   it. That made the banner nearly a thousand pixels tall to show a 600px
   picture. Now the picture fills the whole banner and the brown sits over it
   as a wash, so the same photograph reads far larger in less height.

   And the banner is pinned. `position: sticky` holds it against the top of
   the viewport while the page scrolls up over it — the sections below only
   have to be opaque and positioned for the browser to do the rest on the
   compositor. No scroll listener, no JS, nothing to fall out of sync with
   the scroll position, and it degrades to an ordinary banner wherever sticky
   is not supported.

   The one thing sticky needs is a banner shorter than the viewport. With
   `top: 0` an element taller than the screen sticks immediately and its
   bottom can never be reached, so the height is capped in vh as well as px.
*/
.bu-banner.has-media {
  position: sticky;
  top: 0;
  display: flex;
  align-items: center;
  height: min(84vh, 820px);
  min-height: 460px;
}

/* The template fills the lower third with white, which was the backdrop for
   the picture card. There is no card now, and the photograph runs to the
   bottom edge. */
.bu-banner.has-media::before {
  display: none;
}

.bu-banner .bu-banner__media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  /* Below the wash and the artwork, above the banner's own background. */
  z-index: 0;
}

.bu-banner .bu-banner__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  /* Three layers, because one wash cannot do both jobs.
   *
   * A single even wash has to be dark enough for the white text on top of it,
   * and the text is the whole top of the banner: the header is transparent
   * here, so 16px white links sit straight on the photograph and need 4.5:1.
   * That is what forced the old wash to 0.94 — and measured against a real
   * page's photograph it only just cleared it, at 4.54, while the heading in
   * the middle was already under the line at 2.78. A lighter blue at the same
   * weights put the heading at 1.4:1. Nothing lighter was available while one
   * layer was carrying everything.
   *
   * So the wash itself is light — the photograph reads through it — and the
   * two places that hold white text get their own darkening: a fall from one
   * edge behind the header, and a soft ellipse behind the heading. Between
   * them they cover a small part of the banner. The rest is photograph.
   *
   * Every number is a custom property because the dev-only banner tweaker
   * (components/dev/BannerTweaker.tsx) drives them live. The values below are
   * the design; the tweaker only overrides them inline on <html>, so nothing
   * here changes unless someone is actively dragging a slider. */
  background:
    /* behind the heading */
    radial-gradient(
      ellipse var(--bu-scrim-focus-w) var(--bu-scrim-focus-h) at 50% 50%,
      rgb(var(--bu-scrim-shade) / var(--bu-scrim-focus-alpha)) 0%,
      rgb(var(--bu-scrim-shade) / calc(var(--bu-scrim-focus-alpha) * 0.75)) 50%,
      rgb(var(--bu-scrim-shade) / calc(var(--bu-scrim-focus-alpha) * 0.29)) 82%,
      rgb(var(--bu-scrim-shade) / 0) 100%
    ),
    /* behind the header */
    linear-gradient(
      var(--bu-scrim-edge-angle),
      rgb(var(--bu-scrim-shade) / var(--bu-scrim-edge-alpha)) 0,
      rgb(var(--bu-scrim-shade) / var(--bu-scrim-edge-mid))
        calc(var(--bu-scrim-edge-size) * 0.45),
      rgb(var(--bu-scrim-shade) / 0) var(--bu-scrim-edge-size)
    ),
    /* The wash: rising from the bottom, and in from the sides.
     *
     * It was flat across the whole banner, which put a blue veil over the
     * middle of every photograph — the part worth seeing. The colour now
     * enters from three edges and leaves the middle alone: it frames the
     * picture instead of covering it.
     *
     * The rise is the dominant one and it goes bottom to top, which is the
     * way round it was asked for. It is also the right way round: the bottom
     * of a banner is where the page beneath it begins, so a colour that grows
     * towards that join reads as the two belonging together, where a colour
     * falling from the top reads as something laid over the photograph. */
    linear-gradient(
      to top,
      rgb(var(--bu-scrim-tint) / var(--bu-scrim-rise-alpha)) 0%,
      rgb(var(--bu-scrim-tint) / 0) var(--bu-scrim-rise-stop)
    ),
    linear-gradient(
      to right,
      rgb(var(--bu-scrim-tint) / var(--bu-scrim-tint-alpha)) 0%,
      rgb(var(--bu-scrim-tint) / 0) var(--bu-scrim-edge-reach),
      rgb(var(--bu-scrim-tint) / 0) calc(100% - var(--bu-scrim-edge-reach)),
      rgb(var(--bu-scrim-tint) / var(--bu-scrim-tint-alpha)) 100%
    );
}

/* The banner wash, as numbers.
 *
 * On :root rather than on the scrim itself so an inline override on <html>
 * wins — a declaration on the element would outrank anything inherited, and
 * the tweaker would have nothing to push against.
 *
 * Channels are stored unbracketed ("107 158 212") so one variable can serve
 * every alpha in the stack through `rgb(var(--x) / <alpha>)`. */
:root {
  /* The crest's deepest blue, chosen in the banner tweaker and copied out.
     It was the pale blue; deep reads as the crest rather than as a filter,
     which matters more now the wash only touches the edges. */
  --bu-scrim-tint: 0 58 122;
  --bu-scrim-tint-alpha: 0.3;
  /* The crest's deepest blue, used for both darkenings. */
  --bu-scrim-shade: 16 44 84;
  /* The edge fade: which edge it falls from, how strong, and how far. 180deg
     is from the top, which is where the transparent header sits. */
  --bu-scrim-edge-angle: 180deg;
  /* The fall from the top edge. This one is not decoration and cannot move
     to the bottom with the rest: the site header is transparent and its links
     are white 16px text, so something has to sit behind them. It is as short
     as it can be — steep rather than long, 165px of a 470px banner, a quarter
     less than it covered before. Measured across the seven photographs in
     use, the links come out at 5.8:1 worst case against a floor of 4.5.
     Shortening it to 120px drops them to 1.7. */
  --bu-scrim-edge-alpha: 0.97;
  --bu-scrim-edge-mid: 0.84;
  --bu-scrim-edge-size: 165px;
  /* The blue rising from the bottom, and where it runs out. */
  --bu-scrim-rise-alpha: 0.45;
  --bu-scrim-rise-stop: 62%;
  /* How far in from each side the wash reaches before it is gone. */
  --bu-scrim-edge-reach: 34%;
  /* The pool behind the heading. */
  --bu-scrim-focus-alpha: 0.55;
  --bu-scrim-focus-w: 42%;
  --bu-scrim-focus-h: 30%;
}

/* The colour under the photograph, for the moment before it loads and the
   edges it does not reach. It is set in bayan-theme-generated.css, which is
   machine-written and says not to edit it; this file is the last stylesheet
   the page loads, so the override belongs here beside the wash it matches. */
.bu-banner,
.breadcrumb-wrapper {
  background-color: #3370b4;
}

/* The heading and the two arc fans both sit over the photograph. */
.bu-banner > .container,
.bu-banner .shape-1,
.bu-banner .shape-2 {
  position: relative;
  z-index: 2;
}

.bu-banner .shape-1,
.bu-banner .shape-2 {
  position: absolute;
}

.bu-banner > .container {
  width: 100%;
}

/* The heading centres in the banner now instead of sitting above a picture,
   so the template's asymmetric padding is no longer doing anything. */
.bu-banner.has-media .page-heading {
  padding: 40px 0;
}

.bu-banner.has-media .page-heading h1 {
  margin-bottom: 0;
  /* The heading sits in the middle of the banner, which is exactly where the
     wash no longer goes — the colour was asked to leave the picture alone and
     frame it instead. Something still has to carry white type over a bright
     photograph there, and the honest choice is a shadow on the letters rather
     than a veil over the photograph: it darkens only what it needs to.
     Three layers, because one soft shadow at this size reads as blur and one
     tight shadow reads as a sticker: a tight contact shadow for the edge of
     each stroke, a mid one for weight, and a wide one to lift the whole word
     off whatever is behind it. */
  text-shadow:
    0 1px 2px rgba(4, 22, 44, 0.55),
    0 3px 12px rgba(4, 22, 44, 0.45),
    0 8px 42px rgba(4, 22, 44, 0.4);
}

/*
   What the pin needs from everything else: the sections below the banner
   have to paint over it.

   A banner stuck at `top: 0` stays there for the whole page, so whatever is
   at the top of the viewport at any scroll position has to be opaque —
   otherwise the pinned photograph shows through the page content further
   down. The template's sections are all transparent over a white <body>,
   which is exactly what fails here.

   `position: relative` is the whole of the stacking change. It moves each
   section into the same painting layer as the positioned banner, where DOM
   order decides — and they all come after it. Deliberately no `z-index`:
   that would make every section a stacking context and change how things
   inside them stack.

   The background goes on through `:where()`, which contributes no
   specificity at all, so any section that already has a colour of its own —
   the footer, the colleges strip — keeps it and this only fills in the
   sections that were relying on the body being white.

   `.bu-chat` is excluded because it is the assistant, already fixed to the
   viewport at its own z-index, and is a sibling only because it is mounted
   in the layout.
*/
.bu-banner ~ *:not(.bu-chat) {
  position: relative;
}

:where(.bu-banner ~ *:not(.bu-chat)) {
  background-color: #fff;
}

@media (max-width: 991px) {
  .bu-banner.has-media {
    height: min(68vh, 620px);
    min-height: 400px;
  }
}

@media (max-width: 575px) {
  .bu-banner.has-media {
    height: min(62vh, 520px);
    min-height: 340px;
  }
}

/* A pinned banner is motion tied to scrolling, which is the kind a visitor
   who has asked for reduced motion is asking not to have. It becomes an
   ordinary banner that scrolls away with the page. */
@media (prefers-reduced-motion: reduce) {
  .bu-banner.has-media {
    position: static;
  }
}

/* --------------------------------------------- page banner ornaments --- */
/* The artwork is the template's own, unaltered — the arcs cut into one PNG
   per stroke (they recompose to the source with zero pixels different) and
   the dot grid shown through a 3-4px window per dot. See BannerOrnaments for
   why nothing here is redrawn. What changed is only that each stroke and each
   dot is now its own element, so they animate one at a time instead of the
   whole picture lighting up together. */

/* Each stroke layer is the full 126x254 canvas with one stroke on it, so they
   stack in register. */
.breadcrumb-wrapper .shape-1,
.breadcrumb-wrapper .shape-2 {
  width: 126px;
  height: 254px;
}
.breadcrumb-wrapper .shape-1 .bu-orn__arc,
.breadcrumb-wrapper .shape-2 .bu-orn__arc {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0.15;
  animation: bu-draw 5.4s ease-in-out infinite;
}

/* Drawn, held, then let go — so the fan is never fully still and never fully
   complete. Each stroke is a separate element with its own delay, so they
   arrive in sequence across the fan. */
@keyframes bu-draw {
  0%        { opacity: 0.12; }
  18%       { opacity: 0.95; }
  55%       { opacity: 0.8; }
  80%, 100% { opacity: 0.12; }
}

/* The dot diamond, the drifting dot strip and the rotating cross used to be
   styled here, each with a blink on a long cycle. They are gone from the
   banner — over a photograph they landed on people's faces and the blink read
   as a rendering fault — so their rules, and the `bu-blink` keyframes they
   shared, went with them. The fans at the edges are all that is left. */

@media (prefers-reduced-motion: reduce) {
  .breadcrumb-wrapper .bu-orn__arc {
    animation: none;
    opacity: 0.65;
  }
}

/* ------------------------------------------------- RTL dropdown caret --- */
/* The caret is the last child of the link and carries the template's physical
   `margin-left: 5px`, both written for left-to-right. Under dir="rtl" the
   last child lands at the visual LEFT of the label, and the margin then pads
   the wrong side — so on the Arabic and Kurdish menus every arrow sat away
   from the word it belongs to.
   Reordering rather than repositioning: the link becomes a flex row, and in
   RTL the caret takes order:-1 so it is first along the right-to-left axis,
   which puts it on the right of the label. `gap` replaces the physical
   margin, so the spacing is correct in both directions. */

.header-3 .main-menu nav > ul > li > a,
nav[dir] > ul > li > a,
.mobile-menu[dir] li > a {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

nav[dir] > ul > li > a > i,
.mobile-menu[dir] li > a > i,
.header-3 .main-menu nav > ul > li > a > i {
  margin: 0;
}

nav[dir="rtl"] > ul > li > a > i,
.mobile-menu[dir="rtl"] li > a > i {
  order: -1;
}

/* ----------------------------------------------------- college page --- */
/* The department list is the substance of a college page — for two of the
   three, Bayan publishes almost nothing else — so it gets a real card rather
   than a bullet. */
.bu-college-dept {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 18px 20px;
  border: 1px solid rgba(51, 32, 10, 0.14);
  border-radius: 10px;
  height: 100%;
  transition: border-color 0.25s ease, transform 0.25s ease;
}
.bu-college-dept:hover {
  border-color: var(--theme-red, #a4361f);
  transform: translateY(-3px);
}
.bu-college-dept i {
  font-size: 20px;
  color: var(--theme-red, #a4361f);
  flex: 0 0 auto;
}
.bu-college-dept span {
  font-weight: 600;
  line-height: 1.4;
}

.bu-college-meta {
  display: grid;
  gap: 14px;
}
.bu-college-meta li {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.bu-college-meta li > span {
  font-size: 13px;
  opacity: 0.7;
}

/* ------------------------------------------------- Arabic-script type --- */
/* Sora carries no Arabic glyphs, so Kurdish and Arabic text was rendered by
   whatever fallback the operating system picked — at sizes chosen for Latin.
   Arabic script sits on a smaller apparent size than Latin at the same px
   value, and the fallback made it smaller still, which is why the RTL
   navigation read as tiny beside the English.

   Noto Sans Arabic first for anything in an RTL run, and a modest size lift
   on top, so the two scripts look like the same size to a reader rather than
   measuring the same in px. */

[dir="rtl"],
[lang="ar"],
[lang="ku"] {
  font-family: "Noto Sans Arabic", "Geeza Pro", "Segoe UI", Tahoma,
    "Sora", sans-serif;
}

/* Inheritance is not enough on its own. The template sets font-family on the
   elements themselves — the nav link, headings, buttons — so those keep Sora
   and their Arabic glyphs still fall through to the system default. Naming
   them explicitly is what actually changes the rendering. */
[dir="rtl"] a,
[dir="rtl"] p,
[dir="rtl"] li,
[dir="rtl"] span,
[dir="rtl"] h1,
[dir="rtl"] h2,
[dir="rtl"] h3,
[dir="rtl"] h4,
[dir="rtl"] h5,
[dir="rtl"] h6,
[dir="rtl"] button,
[dir="rtl"] input,
[dir="rtl"] textarea,
[dir="rtl"] .theme-btn {
  font-family: "Noto Sans Arabic", "Geeza Pro", "Segoe UI", Tahoma,
    "Sora", sans-serif;
}

/* The navigation is where the mismatch showed worst: it was pushed down to
   14px to fit seven sections on one line, which Latin carries and Arabic
   does not. */
nav[dir="rtl"] > ul > li > a,
.header-3 .main-menu nav[dir="rtl"] > ul > li > a,
.mobile-menu[dir="rtl"] li > a {
  font-size: 16px;
  /* Repeated at this specificity on purpose: the template sets Sora on this
     exact selector, so the generic [dir="rtl"] a rule above loses to it. */
  font-family: "Noto Sans Arabic", "Geeza Pro", "Segoe UI", Tahoma,
    "Sora", sans-serif;
}

@media (min-width: 1200px) and (max-width: 1399px) {
  nav[dir="rtl"] > ul > li > a,
  .header-3 .main-menu nav[dir="rtl"] > ul > li > a {
    font-size: 15.5px;
  }
}

/* Body copy, headings and the offcanvas get the same treatment: a size that
   matches the Latin rendering rather than the same number. */
[dir="rtl"] p,
[dir="rtl"] li,
[dir="rtl"] .bu-footer__links a,
[dir="rtl"] .bu-footer__contact li,
.mobile-menu[dir="rtl"] li > a {
  font-size: 1.06em;
}

/* No icon rule is needed here: Font Awesome and flaticon each declare their
   own font-family on the glyph class, so they never inherit the container's.
   An earlier version of this block forced `font-family: inherit` on them,
   which would have overridden that and turned every icon into a box. */

/* ------------------------------------------------------- card images --- */
/* The photograph is the biggest thing on a card, and on every listing it was
   the one part that did nothing — you had to aim at the "Read More" line to
   open the story you were already pointing at. Each is now a link to the same
   place as the heading beside it.

   They carry aria-hidden and tabIndex={-1} on purpose: the heading is already
   a link to the same URL, so exposing a second one would make every card two
   identical stops for a keyboard or a screen reader. This is a bigger target
   for a pointer, not a new destination. */
.bu-card-link {
  display: block;
  cursor: pointer;
}
.bu-card-link img {
  display: block;
  width: 100%;
}

/* ------------------------------------------------------ marquee in RTL --- */
/* The scrolling strip sets 55px text on a 32px line-height, inside a
   .scrolling-wrap that is overflow:hidden and exactly as tall as its content.
   Latin survives that because Sora's descenders are shallow — Arabic script's
   are not, so ۆ ی ژ and every Sorani vowel sign were sliced off along the
   bottom edge.
   The line box is opened up in RTL only, so the Latin strip keeps the tight
   rhythm it was drawn with, and the wrap grows with it. */
[dir="rtl"] .mycustom-marque .cmn-textslide,
[dir="rtl"] .scrolling-wrap .cmn-textslide {
  line-height: 1.5;
  /* Sora has no Arabic glyphs at all, so this text was being rendered by
     whatever the system chose — with metrics the 32px line box never
     accounted for. */
  font-family: "Noto Sans Arabic", "Geeza Pro", "Segoe UI", Tahoma,
    "Sora", sans-serif;
  padding-block: 4px;
}

/* The wrap clips horizontally on purpose — that is the marquee — but it must
   not clip vertically. */
[dir="rtl"] .scrolling-wrap {
  overflow-x: hidden;
  overflow-y: visible;
  /* The track itself stays left-to-right even on an RTL page. It is a
     conveyor, not a sentence: the three copies are laid out in a flex row and
     each is animated translateX(-100%), so they refill from the right. Under
     direction: rtl the flex order reverses and the copies march away from the
     side they are supposed to refill from, which left a growing white gap
     after the last item instead of looping seamlessly. */
  direction: ltr;
}

/* Each label is still a right-to-left phrase and shapes as one. */
[dir="rtl"] .scrolling-wrap .cmn-textslide {
  direction: rtl;
}

/* ==================================================== department cards ===
   The template's programme cards were a photo in a box tinted with its
   alternating `bg-2`/`bg-3` pastels — pink and cream, from a palette that has
   nothing to do with Bayan's brown and gold — and each card sized itself to
   its own title, so a row of them came out ragged.

   Rebuilt on the reference layout: a row of equal white tiles, each a mark
   beside a title and its college, turning solid brand brown under the
   pointer with the title underlined in gold.
   ======================================================================== */

/*
   A column, not a row.

   With the icon beside the title the name only had about half the card to
   wrap in, so "Department of Business Administration (DBAD)" took four lines
   while "Department of Law (DLAW)" took two. Every card was the same height,
   but the link underneath sat anywhere from 27px to 73px off the bottom
   depending on the name above it, and a row of cards whose one action lands
   at four different heights reads as broken alignment however tidy the boxes
   are.

   Stacking gives the name the full width — nothing wraps past two lines now —
   and `margin-top: auto` on the link drops it to the floor of every card, so
   all seven share one baseline.
*/
.bu-dept-grid .bu-dept-card {
  /* Overridden per card with the college's own colour. Declared here so the
     property always resolves, including for a college with none set. */
  --bu-dept-accent: #c89a11;

  /* The same colour dark enough to draw with — the stored one is chosen to
     sit on a white card, not to be drawn in, and the gold in particular does
     not clear WCAG 1.4.11 as-is. Both are handed in by the component; see
     lib/collegeColor.ts for the measurements. */
  --bu-dept-ink: #8a6a12;

  display: flex;
  flex-direction: column;
  /* Centred on the card's own axis rather than ranged left. Seven of these
     sit in a row, and a column of left-aligned blocks under a left-aligned
     icon reads as a list that happens to be in boxes; centred, each one is
     its own tile. */
  align-items: center;
  text-align: center;
  gap: 16px;
  height: 100%;              /* every tile matches the tallest in its row */
  min-height: 210px;
  padding: 28px 22px 24px;
  border-radius: 16px;
  background: #fff;
  border: 1px solid rgba(51, 32, 10, 0.1);
  box-shadow: 0 1px 2px rgba(51, 32, 10, 0.04);
  /* The photograph inside is `inset: 0`, which needs a positioned ancestor to
     mean "this card". Without it the layer sized itself to the viewport and
     `overflow: hidden` quietly cropped the mistake — so the clip-path's origin
     was measured from the page's top-left rather than the card's, and only the
     first card in the grid landed anywhere near its own icon. */
  position: relative;
  overflow: hidden;            /* the photograph is clipped to the card */
  transition: background-color 0.22s ease, border-color 0.22s ease,
              transform 0.22s ease, box-shadow 0.22s ease;
}

.bu-dept-card__mark {
  flex: 0 0 auto;
  position: relative;
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: 14px;
  /* A wash of the college's colour. Decorative only — where color-mix is
     unsupported the flat cream below stands in and nothing is lost. */
  background: rgba(200, 154, 17, 0.12);
  background: color-mix(in srgb, var(--bu-dept-accent) 12%, #fff);
  color: var(--bu-dept-ink);
  font-size: 24px;
  /* ease-out on the way in, which is what a thing arriving should do. */
  transition: background-color 0.24s ease-out, color 0.24s ease-out,
              transform 0.24s cubic-bezier(0.34, 1.3, 0.64, 1);
}

/* A ring that expands out of the mark on contact. Drawn on a pseudo-element
   so it can scale past the tile without affecting layout. */
.bu-dept-card__mark::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  border: 2px solid var(--bu-dept-ink);
  opacity: 0;
  transform: scale(0.85);
  transition: opacity 0.3s ease-out, transform 0.3s ease-out;
}

.bu-dept-card__mark i {
  display: block;
  transition: transform 0.28s cubic-bezier(0.34, 1.3, 0.64, 1);
}

.bu-dept-card__text {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  width: 100%;
  /* Takes the card's spare height, which is what gives the arrow's
     `margin-top: auto` a floor to fall to — the arrow lives in here, not
     beside it, so without this it simply follows the college line and every
     card lands its arrow at a different height. */
  flex: 1 1 auto;
  min-width: 0;              /* long department names must wrap, not overflow */
}

.bu-dept-card__title {
  font-size: 18px;
  font-weight: 700;
  line-height: 1.35;
  color: #33200a;
  /* A border rather than text-decoration: it only appears on the active
     card, and an underline that thickens on hover reads as a state change
     rather than as a link that was always there. */
  border-bottom: 2px solid transparent;
  align-self: center;
  padding-bottom: 2px;
  transition: color 0.22s ease, border-color 0.22s ease;
}

.bu-dept-card__college {
  font-size: 13.5px;
  line-height: 1.6;          /* the readable range, not the template's 1.2 */
  color: rgba(51, 32, 10, 0.62);
  transition: color 0.22s ease;
}

/*
   The photograph, revealed out of the icon.

   Every department has its own picture of itself sitting in the database and
   the card was showing a generic glyph instead. Now the glyph is what the
   picture comes out of: a clip-path circle centred on the icon opens from
   nothing to past the far corner, so the image appears to grow from the mark
   rather than cross-fading over it.

   The origin is written in logical terms because the icon sits on the right
   in Kurdish and Arabic — 54px is the card's 26px padding plus half the 56px
   mark, which puts the circle's centre exactly on the glyph in either
   direction.
*/
.bu-dept-card__photo {
  /* The icon moved to the top centre, so the circle starts there. Being a
     percentage it also mirrors for free — the RTL override the left-hand
     origin needed is gone with it. */
  --bu-dept-origin-x: 50%;

  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  overflow: hidden;
  clip-path: circle(0% at var(--bu-dept-origin-x) 54px);
  opacity: 0;
  /*
     Leaving is not arriving in reverse.

     With one transition on both, taking the pointer off the card played the
     sweep backwards — a circle visibly closing in on the icon, which reads as
     the card breaking rather than settling. So the exit fades instead: the
     opacity drops quickly and the clip-path is only reset once the image is
     already invisible, which is what the 0s-after-a-delay does. Nothing is
     seen to shrink.
  */
  transition: opacity 0.16s ease-in, clip-path 0s linear 0.16s;
}

.bu-dept-card__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Held slightly over-size at rest and released as it opens, so the picture
     settles instead of snapping to a stop. */
  transform: scale(1.14);
  transition: transform 0.6s cubic-bezier(0.22, 0.61, 0.36, 1);
}

/*
   The wash that makes the text survive whatever the photograph is doing.

   Sized from measurement, not taste. The text block runs from 22% to 67% of
   the card's height, and the tightest thing in it is the gold "Read More" —
   against a near-white photograph the gold needs the scrim at 0.82 alpha to
   clear 4.5:1, where white would be fine at half that. So the scrim holds
   0.88 all the way to 72% and only thins above the text, which is also what
   keeps the top of the picture visible instead of drowning the whole frame.

   At the title's top edge that works out to 0.885 alpha: white 14.8:1,
   cream 8.3:1, gold 5.7:1.
*/
.bu-dept-card__photo::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to top,
    rgba(18, 11, 3, 0.95) 0%,
    rgba(18, 11, 3, 0.88) 72%,
    rgba(18, 11, 3, 0.55) 88%,
    rgba(18, 11, 3, 0.34) 100%
  );
}

.bu-dept-card:hover .bu-dept-card__photo,
.bu-dept-card:focus-visible .bu-dept-card__photo,
.bu-dept-card:active .bu-dept-card__photo {
  clip-path: circle(140% at var(--bu-dept-origin-x) 54px);
  opacity: 1;
  transition: opacity 0.1s ease-out,
              clip-path 0.52s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.bu-dept-card:hover .bu-dept-card__photo img,
.bu-dept-card:focus-visible .bu-dept-card__photo img,
.bu-dept-card:active .bu-dept-card__photo img {
  transform: scale(1);
}

/* Everything else rides above the photograph. */
.bu-dept-card__mark,
.bu-dept-card__text {
  position: relative;
  z-index: 1;
}

/*
   The arrow sits under the text, centred, on the floor of the card.

   It was pinned to the bottom corner, which was right while the card ranged
   left — a lone glyph in the middle of a centred tile would have read as
   something left behind. Centred it is the end of the column instead, and
   `margin-top: auto` keeps every card's arrow on one baseline however many
   lines the name above it took.
*/
.bu-dept-card__more {
  position: relative;
  z-index: 1;
  margin: auto 0 0;
  padding: 0;
}

.bu-dept-card__more {
  margin-top: auto;
  padding-top: 10px;
  font-size: 13px;
  font-weight: 600;
  color: #a4361f;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  transition: color 0.22s ease;
}
/* The arrow points the way the text runs. */
[dir="rtl"] .bu-dept-card__more i {
  transform: scaleX(-1);
}

/* ---- active tile ------------------------------------------------------ */
/* :focus-visible as well as :hover — the card is a link, and a keyboard user
   has to be able to see which one they are on. */
.bu-dept-grid .bu-dept-card:hover,
.bu-dept-grid .bu-dept-card:focus-visible,
.bu-dept-grid .bu-dept-card:active {
  border-color: var(--bu-dept-ink);
  background: #33200a;
  border-color: #33200a;
  transform: translateY(-3px);
  box-shadow: 0 14px 28px rgba(51, 32, 10, 0.22);
  outline: none;
}
/* Once the photograph has grown out of it, the mark stops competing with it:
   a glass chip instead of a solid block, which keeps the department's symbol
   legible without punching a coloured hole in the picture. */
.bu-dept-card:hover .bu-dept-card__mark,
.bu-dept-card:focus-visible .bu-dept-card__mark,
.bu-dept-card:active .bu-dept-card__mark {
  background: rgba(255, 255, 255, 0.16);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.32);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  color: #fff;
  transform: scale(1.08) rotate(-6deg);
}
/* The glyph counter-rotates a little less than its tile, so it tilts with the
   square rather than spinning inside it. */
.bu-dept-card:hover .bu-dept-card__mark i,
.bu-dept-card:focus-visible .bu-dept-card__mark i,
.bu-dept-card:active .bu-dept-card__mark i {
  transform: rotate(6deg) scale(1.12);
}
.bu-dept-card:hover .bu-dept-card__mark::after,
.bu-dept-card:focus-visible .bu-dept-card__mark::after,
.bu-dept-card:active .bu-dept-card__mark::after {
  opacity: 0.45;
  transform: scale(1.28);
}
.bu-dept-card:hover .bu-dept-card__title,
.bu-dept-card:focus-visible .bu-dept-card__title,
.bu-dept-card:active .bu-dept-card__title {
  color: #fff;
  border-bottom-color: #C89A11;   /* the gold rule from the reference */
}
.bu-dept-card:hover .bu-dept-card__college,
.bu-dept-card:focus-visible .bu-dept-card__college,
.bu-dept-card:active .bu-dept-card__college {
  color: rgba(233, 220, 196, 0.85);
}
.bu-dept-card:hover .bu-dept-card__more,
.bu-dept-card:focus-visible .bu-dept-card__more,
.bu-dept-card:active .bu-dept-card__more {
  color: #C89A11;
}

/* Touch has no hover at all, so the press is the feedback: the tile takes the
   active styling above and dips slightly under the finger. */
.bu-dept-grid .bu-dept-card:active {
  transform: translateY(-1px) scale(0.985);
  transition-duration: 0.09s;
}

/*
   One card per row is a different card.

   This block used to turn the card into a row, on the stated grounds that
   "below 768px Bootstrap drops the grid to a single column". That was true
   when it was written and is not true now: the grid is two across on a phone,
   so the card is about 188px wide, and a row inside 188px gives the icon 46
   of them and leaves the name roughly sixty — every department wrapping to
   four or five stacked words beside a badge.

   So it is a tile again, which is what 188px wants: the mark on top, the name
   under it, the college under that, each on the card's full width. Read down,
   not along.
*/
@media (max-width: 767px) {
  .bu-dept-grid .bu-dept-card {
    flex-direction: column;
    align-items: center;
    gap: 12px;
    min-height: 0;
    padding: 20px 14px;
    text-align: center;
  }

  .bu-dept-card__mark {
    width: 44px;
    height: 44px;
    font-size: 19px;
  }

  .bu-dept-card__text {
    align-items: center;
    gap: 5px;
  }

  .bu-dept-card__title {
    align-self: center;
    font-size: 15px;
    /* Long Kurdish and Arabic department names are single unbreakable words
       at this width; let them break rather than push the card wider. */
    overflow-wrap: anywhere;
  }

  .bu-dept-card__college {
    font-size: 12px;
    line-height: 1.5;
  }

  /* The chevron cost a line of its own on a card this small, for an
     affordance the whole tile already has — it is one link, and tapping
     anywhere on it works. */
  .bu-dept-card__more {
    display: none;
  }

  /* The icon is back on top and centred, so the circle the photograph grows
     out of starts there: half the card across, 20px of padding plus half of
     a 44px mark down. A percentage mirrors for free in right-to-left. */
  .bu-dept-card__photo {
    --bu-dept-origin-x: 50%;
    clip-path: circle(0% at var(--bu-dept-origin-x) 42px);
  }

  

  .bu-dept-card:hover .bu-dept-card__photo,
  .bu-dept-card:focus-visible .bu-dept-card__photo,
  .bu-dept-card:active .bu-dept-card__photo {
    clip-path: circle(140% at var(--bu-dept-origin-x) 42px);
  }
}

@media (hover: none) {
  /*
     No pointer means no hover, and a reveal that only fires while a finger is
     held down is a reveal nobody sees. On touch the photograph is simply the
     card: open at rest, with the text already in its over-image colours.
     Tapping still navigates; nothing is hidden behind an interaction that
     does not exist here.
  */
  /* A 140% circle covers the card from anywhere, so this only has to be
     open — the origin is whatever the layout in force already set. */
  .bu-dept-card__photo {
    clip-path: circle(140% at var(--bu-dept-origin-x) 50%);
    opacity: 1;
  }

  .bu-dept-card__photo img {
    transform: scale(1);
  }

  .bu-dept-card__mark {
    background: rgba(255, 255, 255, 0.16);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.32);
    color: #fff;
  }

  .bu-dept-card__title {
    color: #fff;
  }

  .bu-dept-card__college {
    color: rgba(233, 220, 196, 0.85);
  }

  .bu-dept-card__more {
    color: #c89a11;
  }
}

@media (prefers-reduced-motion: reduce) {
  .bu-dept-grid .bu-dept-card,
  .bu-dept-card__mark,
  .bu-dept-card__title,
  .bu-dept-card__college,
  .bu-dept-card__more {
    transition: none;
  }
  .bu-dept-grid .bu-dept-card:hover,
  .bu-dept-grid .bu-dept-card:focus-visible,
  .bu-dept-grid .bu-dept-card:active,
  .bu-dept-card:hover .bu-dept-card__mark,
  .bu-dept-card:hover .bu-dept-card__mark i {
    transform: none;
  }
  .bu-dept-card__mark,
  .bu-dept-card__mark i,
  .bu-dept-card__mark::after {
    transition: none;
  }

  /* The photograph is content, not decoration, so it still arrives — it just
     fades in place rather than sweeping out of the icon. */
  .bu-dept-card__photo {
    clip-path: none;
    opacity: 0;
    transition: opacity 0.2s ease-out;
  }

  .bu-dept-card__photo img {
    transform: scale(1);
    transition: none;
  }

  .bu-dept-card:hover .bu-dept-card__photo,
  .bu-dept-card:focus-visible .bu-dept-card__photo,
  .bu-dept-card:active .bu-dept-card__photo {
    opacity: 1;
  }
}

/* ------------------------------------------------------ counters band --- */
/* The template leaves each statistic left-aligned, so the 65px icon sat hard
   against the left edge of a number four characters wide and read as though
   it had slipped out of place. Centring the column puts the icon over its own
   number, which is what the spacing was always implying. */
.counter-wrapper-2 .counter-items {
  text-align: center;
  /* Equal shares of the row as well: `space-between` sizes each item to its
     own content, so "2400" pushed its column wider than "7" and the four
     centres came out unevenly spaced across the band. */
  flex: 1 1 0;
}

/* ------------------------------------------------------------- footer --- */
/*
   The nameplate behind the footer.

   The template stacks it under the columns as its own block, sized at a flat
   350px because its own name — "EduSpace" — is one short word. "Bayan
   University" at that size wrapped onto two lines and ran off the bottom of
   the footer; shrinking it to fit then left a band of empty brown as tall as
   the text, which is a lot of footer to spend on a watermark.

   So it moves behind the columns instead. Out of flow it costs no height at
   all, and one short word can be set as large as it wants to be: at 400px
   "Bayan" is 1243px wide, 98% of a 1272px viewport, and that ratio holds at
   any width — hence 30vw, capped so it stops growing on an ultra-wide screen.

   A longer word typed into `footer.nameplate` clips at the footer's edges
   rather than putting a horizontal scrollbar on the whole page.
*/
.footer-section {
  position: relative;
  overflow: hidden;
}

.footer-section .footer-name {
  position: absolute;
  inset: 0;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Decorative and behind everything: it must never take a click meant for
     the link sitting on top of it. */
  pointer-events: none;
  z-index: 0;
}

.footer-section .footer-name h2 {
  margin: 0;
  font-size: min(30vw, 460px);
  line-height: 1;
  white-space: nowrap;
  letter-spacing: 2px;
}

/* The columns and the copyright ride above the watermark. */
.footer-section > .container {
  position: relative;
  z-index: 1;
}

/* The contact column is a plain list here, not the template's icon rows, so
   it needs its own spacing rather than inheriting a bulleted default. */
.footer-section .contact-info li + li {
  margin-top: 12px;
}

/* The back-to-top button is gone — the assistant holds that corner now. The
   template still styles `.back-to-top`, and one of the archived demo bodies
   may yet carry the markup, so hide it rather than leave two floating
   buttons stacked on each other. */
.back-to-top {
  display: none !important;
}

/* ----------------------------------------------------- feature icons --- */
/*
   The four line icons on the brown band — sports, music, flexibility,
   accreditation. The template leaves them completely inert, which next to a
   department grid whose icons all react made them look like images that had
   failed to load rather than a deliberate stillness.

   Same idea as the department mark: the icon tilts, and a disc opens behind
   it out of nothing. Drawn on a pseudo-element so it can grow past the glyph
   without moving anything beside it.
*/
.icon-items .icon {
  position: relative;
  display: inline-grid;
  place-items: center;
  transition: transform 0.28s cubic-bezier(0.34, 1.3, 0.64, 1);
}

.icon-items .icon::before {
  content: "";
  position: absolute;
  inset: -18px;
  border-radius: 50%;
  background: rgba(233, 220, 196, 0.12);
  opacity: 0;
  transform: scale(0.6);
  transition: opacity 0.3s ease-out, transform 0.34s cubic-bezier(0.34, 1.3, 0.64, 1);
}

.icon-items .icon i {
  position: relative;
  transition: color 0.24s ease-out;
}

/* The whole tile is the target, not the 40px glyph — these sit in a column
   with their heading, and reaching for the words should light it too. */
.icon-items:hover .icon,
.icon-items:focus-within .icon {
  transform: scale(1.1) rotate(-7deg);
}

.icon-items:hover .icon::before,
.icon-items:focus-within .icon::before {
  opacity: 1;
  transform: scale(1);
}

.icon-items:hover .icon i,
.icon-items:focus-within .icon i {
  color: var(--bayan-gold, #c89a11);
}

/* Touch has no hover, and these are not links — there is nothing to press
   and nothing to reveal, so on a touch screen they simply rest. */
@media (prefers-reduced-motion: reduce) {
  .icon-items .icon,
  .icon-items .icon::before,
  .icon-items .icon i {
    transition: none;
  }

  .icon-items:hover .icon,
  .icon-items:focus-within .icon {
    transform: none;
  }
}

/* ------------------------------------- the join under the page banner --- */
/*
   The section under the banner was sliding up into it.

   Two faults meeting. Bootstrap's `.row.g-5` carries
   `margin-top: calc(-1 * var(--bs-gutter-y))` — minus 48px — to cancel its
   own gutter. Six of the ten inner pages open with a section carrying `pt-0`,
   and a block with no top padding lets its first child's margin collapse
   straight out of it, so that minus 48 became the section's own margin and
   dragged the whole thing up under the banner. On /faq the heading ended up
   51px *above* the banner's bottom edge.

   It was there before and did not show: the banner used to end in white
   space, so the overlap landed on nothing. Now it ends in a photograph and
   the section is opaque, so the heading collides with the picture.

   `display: flow-root` gives the section its own block formatting context,
   which is the whole fix for the collapse — the margin stays inside where it
   belongs and cancels the gutter it was written for.

   The padding is the second half. Those sections zero their top deliberately,
   because the template's banner finished with a band of white they were
   meant to sit against. That band is gone, so they need an edge of their own.
   `!important` only because Bootstrap's utility is itself `!important` and
   there is no other way past it.
*/
.bu-banner + * {
  display: flow-root;
}

.bu-banner + .pt-0 {
  padding-top: 80px !important;
}

@media (max-width: 767px) {
  .bu-banner + .pt-0 {
    padding-top: 52px !important;
  }
}

/* The page heading is the record's own text.
 *
 * The template capitalises every word in `.page-heading h1`, which is
 * harmless on "Academic Calendar" and wrong on anything the university did
 * not write in title case: a paper called "Climate adaptation planning in the
 * Kurdistan Region" rendered as "Climate Adaptation Planning In The Kurdistan
 * Region", which is not its title and not how it is cited.
 *
 * Every heading this banner shows now comes from a database row that an
 * editor typed deliberately, so the right treatment is none.
 */
.breadcrumb-wrapper .page-heading h1 {
  text-transform: none;
}

/* The drawer's menu, in the band where the drawer is the only menu.
 *
 * The template hides the offcanvas menu at 1200px, because that is where its
 * desktop bar takes over — `.offcanvas__info .mobile-menu { display: none }`
 * inside `@media (min-width: 1200px)`.
 *
 * Moving the bar's own breakpoint to 1400px above left a 200px band with no
 * navigation at all: the hamburger was shown, and opening it gave a greeting,
 * an address and two buttons with no menu under them. The two lines have to
 * agree, so this pushes the drawer's to match.
 */
@media (min-width: 1200px) and (max-width: 1399.98px) {
  .offcanvas__info .mobile-menu {
    display: block;
  }
}

/* ------------------------------------------------- nav hover, on brand ----
 * The template hovers the header-3 navigation to `--theme-red`, which the
 * crest remap resolves to #8c2f1e — a rust that reads as orange over the
 * campus photograph and belongs to no part of the crest.
 *
 * Two colours, because the bar has two backgrounds: gold over the photograph,
 * where it is the wheat of the crest and carries at distance, and blue once
 * `.sticky` turns the bar white, where gold would measure about 2.5:1 against
 * it. Blue on white is 6.4:1.
 *
 * `!important` matches the template's own declaration on these selectors;
 * there is no way to win them on specificity alone.
 * ------------------------------------------------------------------------- */
.header-3 .header-main .main-menu ul li a:hover,
.header-3.style-2 .header-main .main-menu ul li a:hover {
  color: var(--bayan-gold, #c89a11) !important;
}

.sticky.header-3 .header-main .main-menu ul li a:hover,
.sticky.header-3.style-2 .header-main .main-menu ul li a:hover {
  color: var(--bayan-blue, #0066b3) !important;
}

/* The chevron is a separate element and inherits nothing, so without this the
   label turned gold and the arrow beside it stayed white. */
.header-3 .header-main .main-menu ul li a:hover > i {
  color: inherit;
}

/* ------------------------------------------------------------- faq image --
 * The one CMS image slot this file had missed.
 *
 * The template's own asset here is 300×430 and the markup gives the image no
 * size at all, so it rendered at its natural width inside a 621px column and
 * left 345px of the column empty. On an English page that reads as a wide
 * gutter; on a Kurdish or Arabic one the column mirrors and the whole gap
 * lands against the left edge of the screen, which is what makes it look
 * like the section is broken rather than airy.
 *
 * Sized to the height of the questions beside it rather than to a fixed
 * ratio: the accordion's height depends on how many questions an editor has
 * published, and any ratio picked here would be wrong for some of them. The
 * row is `align-items-stretch` so there is a height to fill.
 * ------------------------------------------------------------------------ */
/* The picture is taken out of the flow so it cannot drive the row's height.
 * With it in the flow, `height: 100%` had nothing definite to resolve against
 * — the column's height came from the picture and the picture's height came
 * from the column — so it fell back to the natural aspect and rendered 890px
 * tall beside 761px of questions, moving the empty space rather than
 * removing it. Absolute inside a relative column, the row is sized by the
 * questions alone and the picture fills exactly that. */
@media (min-width: 992px) {
  .faq-wrapper .bu-faq-media {
    position: relative;
  }
  .faq-wrapper .bu-faq-media .faq-image {
    position: absolute;
    /* The row's gutter is padding on the column, so inset from it rather
       than from the column's edge. */
    inset: 0 calc(var(--bs-gutter-x, 1.5rem) * 0.5);
  }
}

.faq-wrapper .faq-image {
  height: 100%;
  min-height: 380px;
  border-radius: 12px;
  overflow: hidden;
}
.faq-wrapper .faq-image img {
  width: 100%;
  height: 100%;
  /* cover, so an upload of any shape fills the panel instead of letterboxing
     inside it — the same treatment every other slot in this file gets. */
  object-fit: cover;
  object-position: center;
  display: block;
}

/* Below lg the columns stack and a full-height image would be a screen of
   photograph before the reader reaches a single question.
   991.98 rather than 991: the desktop rules start at 992, and an integer
   boundary leaves a viewport of 991.5 — which scaled displays really do
   report — matching neither side. */
@media (max-width: 991.98px) {
  /* Stacked, the picture fell to the very bottom, below every question, where
     it read as a stray photograph rather than part of the section. It leads
     instead: the questions are the content and belong under a picture, not
     after one. */
  .faq-wrapper .bu-faq-media {
    order: -1;
  }
  .faq-wrapper .faq-image {
    height: auto;
    min-height: 0;
  }
  .faq-wrapper .faq-image img {
    height: auto;
    aspect-ratio: 16 / 10;
    /* A ceiling for wide phones and small tablets, where 16/10 of the full
       column would otherwise be most of the screen before the first question. */
    max-height: 300px;
    /* Biased upward. A wide, short box cropped from the middle beheaded the
       subject; faces sit in the upper third of nearly every photograph an
       editor will upload.

       This has to live here, after the base rule that sets
       `object-position: center` — a media query adds no specificity, so an
       earlier block loses to a later one at the same weight no matter how
       narrow its condition. That is exactly how the first attempt failed. */
    object-position: center 22%;
  }
}

/* ------------------------------------------- headings under a hard edge ---
 * Three homepage sections carry the template's `pt-0`, which is right in the
 * original composition: each follows a section that ends with 100px of its
 * own bottom padding on the same white background, so the gap reads as shared
 * breathing room and the heading has plenty of air above it.
 *
 * Two of them no longer follow that kind of neighbour, and in both cases a
 * visible edge lands directly on the heading:
 *
 *   .event-section  follows the colleges band, which is cream — so the 100px
 *                   above the boundary is cream and the white section starts
 *                   at the heading with nothing above it.
 *   .news-section   follows the marquee, which draws a 1px rule along its
 *                   bottom — so the heading sits flush under a hairline.
 *
 * Only those two. `.faq-section` also has `pt-0` and also follows a padded
 * section, but that one is white-on-white with no rule between them, which is
 * exactly the case `pt-0` was written for; giving it padding too would add
 * 100px of nothing.
 *
 * A clamp rather than a breakpoint, so the space tracks the section padding
 * the template already scales with the viewport.
 * ------------------------------------------------------------------------ */
.bu-colleges + .event-section,
.marquee-section.border-bottom + .news-section {
  /* `pt-0` is a Bootstrap utility and declares `!important`; there is no way
     to win it on specificity alone. */
  padding-top: clamp(40px, 5.5vw, 80px) !important;
}

/* ------------------------------------------ the same hover on every story --
 * The template gives `.news-left-items` a hover treatment and gives the
 * right-hand column nothing: two corner brackets that draw themselves around
 * the card from 0×0 to full size, plus a coloured glow.
 *
 * That asymmetry made sense in the original markup, where the right column
 * was ONE bordered box containing a list of `.news-right-box` rows — a list
 * does not light up row by row. Here each story is its own card, so three
 * cards sit beside a fourth that behaves differently, and only the big one
 * responds to the pointer.
 *
 * Same effect, same timings, scaled to the smaller card's 10px radius. The
 * declarations mirror the template's rather than reinterpreting them, so if
 * the original is ever restyled these still match.
 *
 * The glow is the one thing not copied verbatim: the template hardcodes
 * `rgba(173, 1, 25, 0.2)`, a crimson from the palette the theme replaced, and
 * it is a literal so the variable remap never reached it. Both cards now take
 * the crest's brown, which is what a shadow under this palette should be.
 * ------------------------------------------------------------------------ */

.news-right-items {
  position: relative;
  transition: 0.4s ease-in-out;
}

.news-right-items::before,
.news-right-items::after {
  position: absolute;
  content: "";
  width: 0;
  height: 0;
  transition: 0.5s;
  opacity: 0;
  visibility: hidden;
  /* Brackets are decoration drawn over the card; without this they sit under
     the thumbnail's own border radius and clip against it. */
  pointer-events: none;
}
.news-right-items::before {
  top: 0;
  left: 0;
  border-top: 1px solid var(--theme-red);
  border-left: 1px solid var(--theme-red);
}
.news-right-items::after {
  bottom: 0;
  right: 0;
  border-bottom: 1px solid var(--theme-red);
  border-right: 1px solid var(--theme-red);
}

.news-right-items:hover::before,
.news-right-items:hover::after,
.news-right-items:focus-within::before,
.news-right-items:focus-within::after {
  width: 100%;
  height: 100%;
  visibility: visible;
  opacity: 1;
  border-radius: 10px;
}

/* Keyboard users get the same feedback as the pointer does — the card's link
   is what receives focus, and without this the frame only ever appeared on
   hover. */
.news-left-items:hover,
.news-left-items:focus-within,
.news-right-items:hover,
.news-right-items:focus-within {
  box-shadow: 10px 4px 60px rgba(51, 32, 10, 0.18);
}
.news-left-items:focus-within::before,
.news-left-items:focus-within::after {
  width: 100%;
  height: 100%;
  visibility: visible;
  opacity: 1;
  border-radius: 7px;
}

/* ------------------------------------------- the right-hand banner fan ----
 * The template pins the two decorative fans differently:
 *
 *   .shape-2  top: 0; left: 0     — an edge
 *   .shape-1  right: 0; bottom: 33%  — a third of the way up
 *
 * A percentage was fine for the template's own banner, which is a fixed ~300px
 * strip: 33% of it put the fan near the bottom corner. Bayan's banner is not
 * that. With a photograph behind it, it runs 756px tall, and 33% of that is
 * 249px — so the right-hand fan floats in the middle of the picture while the
 * left one stays welded to its corner. Only the right side moves, because
 * only the right side was given a percentage.
 *
 * Pinned to the bottom edge instead, which is where the template's own
 * `.style-2` variant puts it — so this is the position the artwork was drawn
 * for, just expressed in a way that survives a taller banner.
 *
 * Scoped to `.bu-banner`, our banner, so the template's other breadcrumb
 * usages keep their original placement.
 * ------------------------------------------------------------------------ */
.breadcrumb-wrapper.bu-banner .shape-1 {
  bottom: 0;
}

/* ------------------------------------------- changing language in place ---
 * Following the language link is a full document navigation: the browser
 * throws the page away and rebuilds it, re-fetching every photograph, losing
 * the scroll position and blanking the screen — for a change that only
 * affects the words. LanguageSwitcher now sets the cookie itself and asks the
 * router to re-render, so the server-rendered text is swapped in place.
 *
 * These two classes are the seam. `busy` is on while the new tree is in
 * flight; `in` replaces it for the moment it lands, and is removed again so
 * an ordinary navigation cannot replay it.
 *
 * Only opacity, blur and a small translate — no layout property is touched,
 * so a swap cannot reflow the page or shift what is under the pointer.
 *
 * The chrome is excluded. The header, the offcanvas and the assistant carry
 * their own state (an open menu, a conversation), and fading them out while
 * a menu is open reads as a fault rather than a transition.
 * ------------------------------------------------------------------------ */

html.bu-lang-busy body > :where(section, footer, .marquee-section, .bu-colleges) {
  opacity: 0.32;
  filter: blur(2px);
  transition: opacity 0.16s ease, filter 0.16s ease;
}

html.bu-lang-in body > :where(section, footer, .marquee-section, .bu-colleges) {
  animation: bu-lang-rise 0.52s cubic-bezier(0.22, 1, 0.36, 1) both;
}

/* A short stagger down the page, so the new language arrives as a wave
   rather than all at once. Six steps is enough — past the sixth section the
   reader is not looking at the top of the page anyway. */
html.bu-lang-in body > :where(section, footer, .marquee-section, .bu-colleges):nth-of-type(1) { animation-delay: 0s; }
html.bu-lang-in body > :where(section, footer, .marquee-section, .bu-colleges):nth-of-type(2) { animation-delay: 0.05s; }
html.bu-lang-in body > :where(section, footer, .marquee-section, .bu-colleges):nth-of-type(3) { animation-delay: 0.1s; }
html.bu-lang-in body > :where(section, footer, .marquee-section, .bu-colleges):nth-of-type(4) { animation-delay: 0.14s; }
html.bu-lang-in body > :where(section, footer, .marquee-section, .bu-colleges):nth-of-type(5) { animation-delay: 0.18s; }
html.bu-lang-in body > :where(section, footer, .marquee-section, .bu-colleges):nth-of-type(n + 6) { animation-delay: 0.22s; }

@keyframes bu-lang-rise {
  from {
    opacity: 0.28;
    filter: blur(3px);
    transform: translateY(7px);
  }
  to {
    opacity: 1;
    filter: blur(0);
    transform: none;
  }
}

/* The header is chrome, so it does not travel — but the labels in it are text
   like any other, so they cross-fade on the spot. */
html.bu-lang-busy .header-3 .main-menu,
html.bu-lang-busy .bu-lang__code {
  opacity: 0.4;
  transition: opacity 0.16s ease;
}
html.bu-lang-in .header-3 .main-menu,
html.bu-lang-in .bu-lang__code {
  animation: bu-lang-fade 0.4s ease both;
}
@keyframes bu-lang-fade {
  from { opacity: 0.35; }
  to { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  html.bu-lang-busy body > :where(section, footer, .marquee-section, .bu-colleges),
  html.bu-lang-busy .header-3 .main-menu,
  html.bu-lang-busy .bu-lang__code {
    opacity: 1;
    filter: none;
  }
  html.bu-lang-in body > :where(section, footer, .marquee-section, .bu-colleges),
  html.bu-lang-in .header-3 .main-menu,
  html.bu-lang-in .bu-lang__code {
    animation: none;
  }
}

/* -------------------------------------------------------------------------
   The footer, in Kurdish and Arabic, on a phone.

   Two separate faults, both only visible in that combination — which is why
   they survived: the English desktop footer they were checked against is
   correct.
   ------------------------------------------------------------------------- */

/* 1. The bullet was on the wrong side of the word.

   main.css marks each footer link with an absolutely-positioned dot, placed
   with PHYSICAL properties: `padding-left: 20px` on the anchor and `left: 0`
   on the dot. Physical means left, in every language. Set right-to-left, the
   text runs to the right and the dot stays pinned to the far left of the
   line — detached from the words it belongs to, with the gap it was supposed
   to occupy opening on the opposite side.

   Logical properties say "the side the text starts on" instead, which is the
   left in English and the right in Kurdish and Arabic. The physical values
   are zeroed first because they are still what main.css sets. */
.footer-widget-wrapper .single-footer-widget .list-area li a {
  padding-left: 0;
  padding-inline-start: 20px;

  /* inline-block, so the indent survives a wrap.
     On an inline box, padding applies to the first line only: "Academic
     Programs" put its bullet and its indent on line one, then began line two
     hard against the column edge, outside the list the dot was marking. A
     block box indents every line it produces. */
  display: inline-block;
  vertical-align: top;
}

.footer-widget-wrapper .single-footer-widget .list-area li a::before {
  left: auto;
  inset-inline-start: 0;

  /* Centre the dot on the line instead of pinning it 8px from the top.
     main.css's 8px was measured against the Latin face's 26px line; Kurdish
     and Arabic set a 30px line here, so the dot floated above the words it
     marks. `lh` is the line's own height, so this stays centred whatever the
     script or the size — with a literal fallback for anything that does not
     know the unit. */
  top: 12px;
  top: calc((1lh - 6px) / 2);
}

/* 2. Four full-width columns, one under the other.

   The template's footer columns are col-md-6, so below 768px all four stack
   and each link list becomes one item per row across the full width. With
   short labels that leaves most of every line empty — the "space on the
   left" in right-to-left — and made the footer 1249px tall on a 375px
   screen. Three and a half screens of it.

   The lists run in two columns on phones instead. It uses the width that was
   already empty, so nothing is cramped by it, and it halves the height. */
@media (max-width: 767.98px) {
  .footer-widget-wrapper .single-footer-widget .list-area {
    columns: 2;
    column-gap: 20px;
  }

  /* A link that wraps to two lines must not be split down the middle by the
     column break. */
  .footer-widget-wrapper .single-footer-widget .list-area li {
    break-inside: avoid;
    -webkit-column-break-inside: avoid;
  }

  /* The template's between-item spacing assumes a single column; in two it
     reads as a gap the eye tries to align across. */
  .footer-widget-wrapper .single-footer-widget .list-area li:not(:last-child) {
    margin-bottom: 12px;
  }

  /* The watermark is set to 30vw, sized for a desktop column it sits behind.
     At phone width it is as wide as the content and reads as a stain rather
     than a wash. */
  .footer-section .footer-name h2 {
    font-size: 22vw;
  }
}

/* The assistant's launcher is fixed to the bottom of the viewport, and on a
   phone it is a full-width bar rather than the small circle it is on desktop.
   Scrolled to the end of the page it therefore sat on top of the last thing
   in the footer — the address, and then the copyright line. Reserve its
   height plus the home-indicator inset, so the footer ends above it. */
@media (max-width: 767.98px) {
  .footer-section .footer-bottom {
    padding-bottom: calc(72px + env(safe-area-inset-bottom));
  }
}

/* The footer wordmark is a logotype, not a sentence.

   Migration 00043 makes it read "Bayan" in all three languages, because a
   mark is a picture of a name and does not get retranslated when the page
   around it does. That leaves one Latin word inside a right-to-left page, and
   two things have to be said about it.

   bayan-theme.css zeroes letter-spacing under [dir="rtl"] with !important —
   correct, because Arabic-script letters join and tracking pulls them apart.
   There are no joining letters here, and the mark is set at 22-30vw where the
   template's 2px of tracking is doing visible work, so it is put back.

   And the word is isolated from the surrounding direction, so the paragraph
   direction cannot reorder it or reposition its punctuation. */
.footer-section .footer-name h2 {
  letter-spacing: 2px !important;
  direction: ltr;
  unicode-bidi: isolate;
}

/* -------------------------------------------------------------------------
   Icon cards, two across on a phone.

   The template's card grids are col-md-6, so below 768px every one of them
   becomes a single full-width column. For a card that is an icon, three
   words and a short line of description, that is a whole phone screen for
   something 200px tall — four of them turn a section into four screens of
   scrolling, and the eye never gets to compare them, which is the entire
   point of putting features in a grid.

   Applied only to the grids whose cards are icon-and-text. The event and
   course cards are deliberately left one-up: they carry portrait posters
   with titles over them, and at half a phone's width the picture stops
   being readable and the title starts wrapping to four lines. Narrower is
   not automatically better.
   ------------------------------------------------------------------------- */
@media (max-width: 767.98px) {
  /* Descendant selectors, not a child chain: these sections put a wrapper
     div between the container and the row (.feature-wrapper-3), and a chain
     of `>` silently matches nothing when it is there. */
  .feature-section-3 .row > [class*="col-"],
  .popular-courses-section-33 .row > [class*="col-"] {
    flex: 0 0 auto;
    width: 50%;
  }
}

/* =========================================================================
   .bu-search — the search overlay.

   No card. Two earlier versions had one: the template's white block pinned to
   the top with the page showing through behind it, and then a centred panel
   with a heading, a close button and a framed field — a lot of furniture
   around one text box, and furniture that announces itself before the thing
   it contains.

   What is left is the question. The site's own paper closes over the page
   from both edges, and in the middle of it sits a single line of type with
   the caret already in it, writing itself through the things people actually
   come here for.
   ========================================================================= */

.bu-search {
  /* The chat widget's palette, repeated rather than referenced: bayan-chat.css
     scopes its --bu-chat-* variables to `.bu-chat`, so they do not resolve
     out here, and one overlay should not depend on another component's box
     existing anyway.

     The overlay used the site's blue before. That was wrong next to the thing
     it shares a screen with — the chat launcher sits in the corner in brown
     and gold while the search curtain came up in blue behind it. Two overlays,
     two palettes, one screen. */
  --bu-search-brown: #33200a;
  --bu-search-gold: #c89a11;
  --bu-search-cream: #e9dcc4;
  --bu-search-ink: #120b03;

  position: fixed;
  inset: 0;
  z-index: 9995;
  display: grid;
  /* minmax(0, 1fr): an auto column takes the item's max-content width, and
     the form's is wider than a phone, so the line would hang off the edge. */
  grid-template-columns: minmax(0, 1fr);
  align-content: center;
  justify-items: center;
  gap: 18px;
  padding: 24px;
  visibility: hidden;
  pointer-events: none;
  transition: visibility 0s linear 0.45s;
}

.bu-search.is-open {
  visibility: visible;
  pointer-events: auto;
  transition: visibility 0s;
}

/* --------------------------------------------------------------- paper -- */

.bu-search__paper {
  position: absolute;
  inset: 0;
  z-index: -1;
}

.bu-search__paper-half {
  position: absolute;
  left: 0;
  right: 0;
  /* A pixel of overlap so no seam shows where the two meet. */
  height: calc(50% + 1px);
  background: var(--bayan-cream, #f7f5f2);
  transition: transform 0.45s cubic-bezier(0.83, 0, 0.17, 1);
}

.bu-search__paper-half--top { top: 0; transform: translateY(-100%); }
.bu-search__paper-half--bottom { bottom: 0; transform: translateY(100%); }

.bu-search.is-open .bu-search__paper-half { transform: none; }

/* --------------------------------------------------------------- close -- */

/* On the screen's corner, not on a panel — there is no panel for it to be a
   corner of, and a close button belongs to the overlay rather than to the
   line of type. */
.bu-search__close {
  position: absolute;
  top: max(18px, env(safe-area-inset-top));
  inset-inline-end: 18px;
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: rgba(51, 32, 10, 0.45);
  font-size: 17px;
  cursor: pointer;
  opacity: 0;
  transition:
    opacity 0.3s ease 0.3s,
    background 0.18s ease,
    color 0.18s ease,
    transform 0.25s ease;
}

.bu-search.is-open .bu-search__close { opacity: 1; }

.bu-search__close:hover,
.bu-search__close:focus-visible {
  background: rgba(51, 32, 10, 0.07);
  color: var(--bayan-brown-deep, #33200a);
  transform: rotate(90deg);
}

/* ---------------------------------------------------------------- line -- */

.bu-search__form {
  position: relative;
  display: flex;
  align-items: center;
  gap: 14px;
  width: min(680px, 100%);
  padding-bottom: 14px;

  /* Arrives after the paper, so the two read as one movement. */
  opacity: 0;
  transform: translateY(10px);
  transition:
    opacity 0.32s ease 0.24s,
    transform 0.4s cubic-bezier(0.22, 1, 0.36, 1) 0.24s;
}

.bu-search.is-open .bu-search__form {
  opacity: 1;
  transform: none;
}

/* The rule under the line, drawn from the middle outwards as it opens. It is
   the only chrome the field has, and it is a line rather than a box because a
   box would be a card again. */
.bu-search__form::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: linear-gradient(
    to right,
    transparent,
    var(--bu-search-gold) 18%,
    var(--bu-search-gold) 82%,
    transparent
  );
  transform: scaleX(0);
  transition: transform 0.55s cubic-bezier(0.22, 1, 0.36, 1) 0.3s;
}

.bu-search.is-open .bu-search__form::after { transform: scaleX(1); }

.bu-search__icon {
  flex: 0 0 auto;
  font-size: clamp(18px, 4.5vw, 22px);
  color: rgba(51, 32, 10, 0.32);
  transition: color 0.22s ease;
}

.bu-search__form:focus-within .bu-search__icon { color: var(--bu-search-gold); }

/* The input and its animated placeholder share one box so their type lands in
   exactly the same place. */
.bu-search__field {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
}

/* The :focus half is not redundant. main.css carries a bare
   `input:focus { color: var(--white) }`, written for the newsletter field on
   its dark bar, and `input:focus` — an element plus a pseudo-class — outranks
   a lone class. Without this the text turns white the instant somebody types
   into it. */
.bu-search__input,
.bu-search__input:focus {
  width: 100%;
  min-width: 0;
  border: 0;
  background: transparent;
  padding: 6px 0;
  /* Never below 16px: iOS zooms the page in on a smaller focused field. */
  font-size: clamp(20px, 5.4vw, 30px);
  font-weight: 500;
  line-height: 1.3;
  color: var(--bayan-brown-deep, #33200a);
  outline: none;
}

/* Safari draws its own clear button on type=search; it lands on the submit
   and cannot be styled to match anything here. */
.bu-search__input::-webkit-search-decoration,
.bu-search__input::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}

.bu-search__ghost {
  position: absolute;
  inset-inline-start: 0;
  top: 50%;
  transform: translateY(-50%);
  /* The real caret sits at the start of the empty field and the suggestion
     types after it, so the caret appears to be doing the writing. That is why
     there is no second, drawn caret here. */
  pointer-events: none;
  white-space: nowrap;
  overflow: hidden;
  max-width: 100%;
  font-size: clamp(20px, 5.4vw, 30px);
  font-weight: 500;
  line-height: 1.3;
  color: rgba(51, 32, 10, 0.3);
}

.bu-search__go {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 50%;
  background: var(--bu-search-brown);
  color: var(--bu-search-cream);
  font-size: 15px;
  cursor: pointer;
  transition: background 0.18s ease, opacity 0.2s ease, transform 0.2s ease;
}

.bu-search__go:hover:not(:disabled) { background: var(--bu-search-ink); }
.bu-search__go:active:not(:disabled) { transform: scale(0.94); }

/* Nothing to submit, nothing to press. A dimmed slab sitting in an empty
   field reads as a control that failed to load rather than one that is
   waiting; it scales in once there is a word to send. */
.bu-search__go:disabled {
  opacity: 0;
  transform: scale(0.6);
  pointer-events: none;
}

/* ---------------------------------------------------------------- hint -- */

.bu-search__hint {
  margin: 0;
  font-size: 12.5px;
  color: rgba(51, 32, 10, 0.42);
  opacity: 0;
  transition: opacity 0.3s ease 0.42s;
}

.bu-search.is-open .bu-search__hint { opacity: 1; }

.bu-search__hint kbd {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 5px;
  background: rgba(51, 32, 10, 0.07);
  border: 1px solid rgba(51, 32, 10, 0.1);
  font-family: inherit;
  font-size: 11.5px;
  color: rgba(51, 32, 10, 0.6);
  /* A Latin key name inside a right-to-left sentence: isolate it so the
     paragraph direction cannot move it away from the words describing it. */
  unicode-bidi: isolate;
}

/* -------------------------------------------------------------- motion -- */

@media (prefers-reduced-motion: reduce) {
  .bu-search__paper-half,
  .bu-search__form,
  .bu-search__form::after,
  .bu-search__close,
  .bu-search__hint {
    transition-duration: 0.01ms !important;
    transition-delay: 0s !important;
  }
  .bu-search__form::after { transform: scaleX(1); }
}

/* ---------------------------------------------------------------- dark -- */

/* This was a cold blue-grey — #0b1622 paper with #eef2f6 type — and it is what
 * anyone with their phone in dark mode actually saw: a blue curtain, with the
 * brown-and-gold chat launcher sitting on top of it.
 *
 * It is the same palette as the light theme now, turned over. Ink where the
 * paper was, cream where the ink was, gold on the line. Dark mode is kept
 * rather than dropped: a full-screen sheet of cream at night is a flashbang,
 * and the chat panel is a small box in a corner while this covers everything. */
@media (prefers-color-scheme: dark) {
  .bu-search__paper-half { background: var(--bu-search-ink); }
  .bu-search__icon { color: rgba(233, 220, 196, 0.34); }
  .bu-search__form:focus-within .bu-search__icon { color: var(--bu-search-gold); }
  .bu-search__input,
  .bu-search__input:focus { color: var(--bu-search-cream); }
  .bu-search__ghost { color: rgba(233, 220, 196, 0.3); }
  .bu-search__close { color: rgba(233, 220, 196, 0.5); }
  .bu-search__close:hover {
    background: rgba(233, 220, 196, 0.1);
    color: var(--bu-search-cream);
  }
  .bu-search__hint { color: rgba(233, 220, 196, 0.42); }
  .bu-search__hint kbd {
    background: rgba(233, 220, 196, 0.1);
    border-color: rgba(233, 220, 196, 0.16);
    color: rgba(233, 220, 196, 0.72);
  }
  /* The button inverts too: a brown circle on near-black brown disappears. */
  .bu-search__go { background: var(--bu-search-gold); color: var(--bu-search-ink); }
  .bu-search__go:hover:not(:disabled) { background: var(--bu-search-cream); }
  .bu-search__hit > i {
    background: rgba(233, 220, 196, 0.1);
    color: var(--bu-search-gold);
  }
  .bu-search__hit-text { color: var(--bu-search-cream); }
}

/* ------------------------------------------------------- live results -- */

/* What matches, under the line, changing as the words change. The list is a
   plain column rather than a floating panel: the overlay already owns the
   whole screen, so there is nothing for a dropdown to drop over. */
.bu-search__hits {
  width: min(680px, 100%);
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: min(46vh, 380px);
  overflow-y: auto;
  overscroll-behavior: contain;   /* stops the page behind scrolling at the end */
  animation: bu-search-hits-in 0.28s cubic-bezier(0.22, 1, 0.36, 1) both;

  /* The platform scrollbar is a heavy bar against a list this quiet, and on
     the overlay it reads as a design element rather than a control. */
  scrollbar-width: thin;
  scrollbar-color: rgba(51, 32, 10, 0.2) transparent;

  /* Fade the last row out instead of slicing it in half: a row cut level
     looks like a rendering fault, while one fading says "there is more". */
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 26px), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 26px), transparent);
}

.bu-search__hits::-webkit-scrollbar { width: 6px; }
.bu-search__hits::-webkit-scrollbar-track { background: transparent; }
.bu-search__hits::-webkit-scrollbar-thumb {
  background: rgba(51, 32, 10, 0.18);
  border-radius: 3px;
}

@keyframes bu-search-hits-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

.bu-search__hit {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 11px 13px;
  border: 0;
  border-radius: 12px;
  background: transparent;
  text-align: start;
  cursor: pointer;
  transition: background 0.14s ease;
}

.bu-search__hit.is-active { background: rgba(0, 102, 179, 0.09); }

.bu-search__hit > i {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: 9px;
  background: rgba(51, 32, 10, 0.08);
  color: var(--bu-search-brown);
  font-size: 14px;
}

.bu-search__hit-text {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

/* One line each. A summary that wraps to three turns a list of six results
   into a page of its own, and the point of the list is to be scanned. */
.bu-search__hit-title,
.bu-search__hit-sub {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bu-search__hit-title {
  font-size: 14.5px;
  font-weight: 600;
  color: var(--bayan-brown-deep, #33200a);
}

.bu-search__hit-sub {
  font-size: 12.5px;
  color: rgba(51, 32, 10, 0.5);
}

.bu-search__hit-kind {
  flex: 0 0 auto;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: rgba(51, 32, 10, 0.38);
}

@media (max-width: 420px) {
  /* The label is the least useful thing on the row once the width is tight —
     the icon already says what kind of thing it is. */
  .bu-search__hit-kind { display: none; }
}

/* There is no Esc key on a phone. The hint is instructions for a keyboard
   that is not there, taking a line under the field that the results want. */
@media (max-width: 767.98px) {
  .bu-search__hint { display: none; }
}

@media (prefers-color-scheme: dark) {
  .bu-search__hit.is-active { background: rgba(255, 255, 255, 0.07); }
  .bu-search__hit > i { background: rgba(255, 255, 255, 0.08); color: #a8ccec; }
  .bu-search__hit-title { color: #eef2f6; }
  .bu-search__hit-sub { color: rgba(238, 242, 246, 0.5); }
  .bu-search__hit-kind { color: rgba(238, 242, 246, 0.38); }
}

/* =========================================================================
   .bu-results — the /search page.
   ========================================================================= */

.bu-results__head { margin-bottom: 26px; }

.bu-results__count {
  margin: 0 0 4px;
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  /* Brown, like the overlay that leads here and the icons beside it. The
     literal value rather than --bu-search-brown, because that variable is
     declared on .bu-search and the results page is not inside it.
     This was the last blue left in search after the palette change — the
     icons had been converted and the count above them had not, which is
     worse than leaving both. */
  color: #33200a;
}

.bu-results__term {
  margin: 0;
  font-size: clamp(26px, 5vw, 38px);
  font-weight: 700;
  color: var(--bayan-brown-deep, #33200a);
  /* The term came from a query string and can be anything, including a very
     long word with no spaces in it. */
  overflow-wrap: anywhere;
}

.bu-results__list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-width: 780px;
}

.bu-results__item {
  display: flex;
  align-items: center;
  gap: 15px;
  padding: 14px 16px;
  border-radius: 14px;
  background: #fff;
  border: 1px solid rgba(0, 58, 122, 0.07);
  text-decoration: none;
  transition: transform 0.16s ease, border-color 0.16s ease, box-shadow 0.16s ease;
}

.bu-results__item:hover {
  transform: translateY(-1px);
  border-color: rgba(0, 102, 179, 0.3);
  box-shadow: 0 8px 20px rgba(0, 58, 122, 0.08);
}

.bu-results__icon {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 11px;
  background: rgba(51, 32, 10, 0.08);
  color: var(--bu-search-brown);
  font-size: 15px;
}

.bu-results__text {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.bu-results__title {
  font-size: 15.5px;
  font-weight: 600;
  color: var(--bayan-brown-deep, #33200a);
}

/* Two lines of summary, then stop: enough to tell one result from another,
   not enough for a long page to push the next result off the screen. */
.bu-results__sub {
  font-size: 13px;
  line-height: 1.5;
  color: rgba(51, 32, 10, 0.55);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.bu-results__kind {
  flex: 0 0 auto;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: rgba(51, 32, 10, 0.4);
}

.bu-results__miss {
  margin: 0;
  font-size: 15px;
  color: rgba(51, 32, 10, 0.6);
}

@media (max-width: 480px) {
  .bu-results__kind { display: none; }
}

/* =========================================================================
   Sideways scroll on a phone.

   The off-canvas drawer is `position: fixed; right: 0` and parked off-screen
   with `transform: translateX(calc(100% + 80px))`. At 360px that puts its far
   edge around 827px — a 460px tail of empty page hanging off the right.

   Chromium contains it: fixed-position boxes do not contribute to the
   document's scrollable overflow, so the page does not pan. iOS Safari has
   never honoured that for a transformed fixed element, and `overflow-x:
   hidden` on <body> does not save it either — the drawer is what you find
   when you swipe left on a phone and the whole site slides over.

   `visibility: hidden` is the fix rather than a wider clip, because the
   drawer should not be there at all when it is shut: rendered but off-screen,
   it also stayed in the tab order, so a keyboard could walk into an invisible
   menu and a screen reader could read it out.

   The visibility change is delayed by the length of the slide, so closing
   still animates — it disappears once it has finished leaving, not as it
   starts.
   ========================================================================= */

.offcanvas__info {
  visibility: hidden;
  transition:
    opacity 0.45s ease-in-out,
    transform 0.45s ease-in-out,
    visibility 0s linear 0.45s;
}

.offcanvas__info.info-open {
  visibility: visible;
  transition:
    opacity 0.45s ease-in-out,
    transform 0.45s ease-in-out,
    visibility 0s;
}

/* Belt and braces on the document itself.
   `clip` rather than `hidden`: hidden on the root makes the viewport a scroll
   container, which is how a page ends up scrollable-but-clipped and how the
   body's own `overflow-x: hidden` got propagated into something subtly
   different from what it looks like. `clip` simply refuses to scroll. */
html {
  overflow-x: clip;
}

/* =========================================================================
   .instagram-slider — the photograph strip.

   Swiper eases every transition by default, which is right for a slide
   somebody stops and reads: it arrives and settles. A strip of photographs
   is not read, it is watched, and there the ease curve reads as a lurch —
   the row jumps, coasts and stalls once per step.

   Linear, so each step travels at one pace and the strip drifts rather than
   snaps. The step itself is 1500ms against a 1500ms rest (see
   behaviors/sliders.ts), which keeps it moving about half the time.
   ========================================================================= */

.instagram-slider .swiper-wrapper {
  transition-timing-function: linear;
}

/* Motion that never stops is exactly what this setting exists to silence, and
   a strip of faces sliding under the reader is hard to ignore. */
@media (prefers-reduced-motion: reduce) {
  .instagram-slider .swiper-wrapper {
    transition-duration: 0ms !important;
  }
}

/* =========================================================================
   .odometer — numbers read left to right in every language.

   The counter band showed 2400 as "0042" and 120 as "021" in Arabic and
   Kurdish. Not a data fault — the API returns 2400, 120, 7, 23 identically
   for all three languages. The odometer builds one <span> per digit, and in
   an RTL container those inline spans lay out right to left, so the number
   is assembled backwards. Measured on the live page: the About counters
   computed `direction: ltr` and were correct, while the band's inherited
   `direction: rtl` and were reversed.

   Digits are written left to right in Arabic and Kurdish exactly as in
   English — it is only the words around them that flow the other way. So the
   number is isolated from the paragraph direction rather than following it.
   `isolate` as well as `direction`, so a number sitting inside a
   right-to-left sentence cannot drag its neighbours around either.
   ========================================================================= */

.odometer,
.odometer-inside {
  direction: ltr;
  unicode-bidi: isolate;
}

/* ------------------------------------------------- the header on a phone ---
 * The hamburger sat hard against the right edge of the screen — one pixel
 * past it, in fact — while the search icon beside it kept a comfortable
 * margin. It was not the hamburger's own spacing: the whole right-hand group
 * had been pushed out of the row.
 *
 * The arithmetic, measured on a 375px phone. The container offers 351px. The
 * crest at 56px tall measures 224px wide, and there are 36px of margins
 * between the two groups, which leaves 91px for a group that needs 125. The
 * row overflows by 34px, and because `.header-logo` is `flex: 0 0 auto` it
 * will not give way — so everything to its right is shoved off the screen
 * instead, hamburger last and therefore furthest out.
 *
 * Two changes, because either alone would leave the fault latent. The crest
 * comes down to a size the row can actually hold; and the logo is allowed to
 * compress, so that a language whose right-hand group runs wider squeezes the
 * crest rather than pushing the menu button off the phone again.
 * -------------------------------------------------------------------------- */
@media (max-width: 575.98px) {
  .header-3 .header-logo img,
  .header-3 .header-logo-2 img {
    height: 44px;
  }

  .header-3 .header-logo,
  .header-3 .header-logo-2 {
    flex: 0 1 auto;
    min-width: 0;
  }

  .header-3 .header-logo img,
  .header-3 .header-logo-2 img {
    max-width: 100%;
    object-fit: contain;
  }

  /* The group keeps its own size rather than being the thing that collapses:
     a search icon and a menu button have no spare width to give. */
  .header-3 .header-right {
    flex: 0 0 auto;
  }
}
