/* ==========================================================================
   Overrides for the Medinexa clone. Loaded LAST in the stylesheet chain.

   The template's animation runtime (GSAP/ScrollTrigger/SplitText, Swiper, WOW,
   Lenis, counters, marquee) is now loaded by app/_components/MedinexaRuntime,
   so the Swiper static-reconstruction and scroll-reveal force-visible rules
   that used to live here have been removed — the runtime drives those elements.
   Keep this file for genuinely static fixups only.
   ========================================================================== */

/* #preloader is dropped from the markup entirely; keep this as a safety net in
   case any preloader overlay is ever reintroduced. */
#preloader,
.preloader-logo {
  display: none !important;
}

/* Hero: Alegria's banner photo is far brighter than the template's, so the white
   hero copy needs a scrim to stay legible. Sits inside .mx-hero-img (z-index:-1,
   clip-path) so it is masked with the photo and stays behind the text. */
.mx-hero-sec .mx-hero-img::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    100deg,
    rgba(11, 31, 63, 0.92) 0%,
    rgba(11, 31, 63, 0.75) 32%,
    rgba(11, 31, 63, 0.25) 58%,
    rgba(11, 31, 63, 0) 78%
  );
}

/* The template paired this line with stock "member" avatars. Alegria has no
   client photos and would not publish them, so the list was dropped. */
.mx-hero-client.no-avatars > p {
  margin-left: 0;
}
/* The theme underlines this number (it held "9.5" in the template). Against
   "Over 10 Years" an underline reads as a broken link. */
.mx-hero-client.no-avatars > p span {
  text-decoration: none;
}

/* Header logo. The theme has no sizing rule for .logo_site-size, so the
   238x150 source needs one. */
.mx-header-section .brand-logo img.logo_site-size {
  display: block;
  width: 132px;
  height: auto;
}
.mobile_menu_content .m-brand-logo img.logo_site-m-size {
  width: 150px;
  height: auto;
}
/* Footer logo sits on the white .mx-ftr1-area card, so it uses the same
   full-colour transparent logo as the header. */
.mx-ftr-newslatter .brand-logo img.logo_site-size {
  width: 160px;
  height: auto;
}

/* ---------------------------------------------------------------------------
   Hero entrance.

   Replaces the template's GSAP/SplitText hero intro (disabled in script.js).
   Deliberately pure CSS, running at first paint rather than after the
   post-hydration runtime loads:

   - `animation-fill-mode: both` holds the `from` state only while the
     animation is pending or running. If this stylesheet loads but the JS
     never does, the hero still resolves to fully visible. There is no
     JS-added class gating visibility — that mistake left content stuck
     hidden on a stale cache once already.
   - No `opacity: 0` is ever declared as a static rule, so the hero is
     visible by default in any browser that skips the animation.
   --------------------------------------------------------------------------- */
@keyframes mx-hero-rise {
  from {
    opacity: 0;
    transform: translate3d(0, 28px, 0);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes mx-hero-settle {
  from {
    transform: scale(1.08);
  }
  to {
    transform: scale(1);
  }
}

.mx-hero-sec .mx-slug,
.mx-hero-sec .mx_hero_title,
.mx-hero-sec .hero_desc,
.mx-hero-sec .mx-hero-text .mx-btn1,
.mx-hero-sec .mx-hero-client {
  animation: mx-hero-rise 0.85s cubic-bezier(0.23, 1, 0.32, 1) both;
}
.mx-hero-sec .mx-slug {
  animation-delay: 0.05s;
}
.mx-hero-sec .mx_hero_title {
  animation-delay: 0.16s;
}
.mx-hero-sec .hero_desc {
  animation-delay: 0.32s;
}
.mx-hero-sec .mx-hero-text .mx-btn1 {
  animation-delay: 0.44s;
}
.mx-hero-sec .mx-hero-client {
  animation-delay: 0.56s;
}
.mx-hero-sec .mx-hero-img > img {
  animation: mx-hero-settle 1.6s cubic-bezier(0.23, 1, 0.32, 1) both;
}

@media (prefers-reduced-motion: reduce) {
  .mx-hero-sec .mx-slug,
  .mx-hero-sec .mx_hero_title,
  .mx-hero-sec .hero_desc,
  .mx-hero-sec .mx-hero-text .mx-btn1,
  .mx-hero-sec .mx-hero-client,
  .mx-hero-sec .mx-hero-img > img {
    animation: none;
  }
}

/* About: the template's slots were sized by tall source images, so these slots
   collapsed without a pinned height. Pin them and crop with object-fit.
   about-pic-1.webp is 920x1060 (0.868) against a 440x505 slot (0.871) — the
   client cropped it for this box, so `center` takes essentially the whole frame
   and nothing upscales, even under img-parallax's 1.5x (which needs 660x758). */
.mx-abt-sec .mx-abt1-img {
  height: 505px;
}
.mx-abt-sec .mx-abt1-img > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}
/* .mx-abt1-exp pulls itself up by -188px to overlap the bottom of this image.
   The slot must stay tall enough to absorb that, or the "10+ Years" card lands
   on top of the section heading. 460px keeps the wrapper flush with .mx-abt1-img. */
.mx-abt-sec .mx-abt1-img2 .item-img {
  height: 460px;
}
.mx-abt-sec .mx-abt1-img2 .item-img > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 40%;
}
/* Below 992px the theme wraps .mx-abt1-content and centers it, so every flex item
   sizes to its own max-content. The template's .item-img shrink-wraps to ab2.webp
   (290x426 + 10px border = 310x446) and stays a centered portrait card. Alegria's
   photo is landscape (about-pic-2.webp, 1080x940), so `width:100%` above stretched
   .item-img across the whole container and
   the 291px .mx-abt1-exp card (translateX(-20px)) hung off the left gutter. Pin the
   template's own box back so the wrapper shrink-wraps and centers as it does there. */
@media (max-width: 991px) {
  .mx-abt-sec .mx-abt1-img2 .item-img {
    width: 310px;
    max-width: 100%;
    height: 446px;
  }
}

/* FeatureBoxes: the tall bento tile took its height from a portrait source image.
   The tile is still stretched to the bento's right column rather than sized by its
   photo, so the tile survives a future swap back to a panoramic source.
   10-plus-years.webp is 400x710 — the first true portrait here, so it fills the
   tall tile with only a vertical crop and needs no off-center framing. */
.elementor-element-eb769dd,
.elementor-element-eb769dd > .elementor-element-32b00ea,
.elementor-element-eb769dd .elementor-widget-container {
  display: flex;
  flex-direction: column;
  flex: 1;
}
.mx-intro-item1 {
  flex: 1;
  display: flex;
  min-height: 500px;
}
.mx-intro-item1 .item-img {
  flex: 1;
  min-height: 0;
}
/* The "50+" tile's widget is the only child of the f90cfdc flex row, but Elementor
   leaves it width:auto/flex-grow:0, so it shrink-wraps to its text's max-content and
   leaves a gap on the right. The template does this too (369px of 406px at 430px) —
   its copy is simply longer than Alegria's, which hides the gap. Fill the row. */
.elementor-element-f90cfdc > .elementor-element-21bf558 {
  width: 100%;
  flex-grow: 1;
}
.mx-intro-item1 .item-img > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* Services: Alegria has 3 services, so the template's 4-per-view Swiper was
   replaced with a static grid. Mirrors the Swiper breakpoints it superseded
   (4→3→2→1 becomes 3→3→2→1) and its 20px spaceBetween. */
.mx-ser1-grid-inner {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  align-items: stretch;
}
.mx-ser1-col {
  display: flex;
  min-width: 0;
}
.mx-ser1-col > .mx-ser1-item {
  width: 100%;
}
@media (max-width: 991px) {
  .mx-ser1-grid-inner {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 575px) {
  .mx-ser1-grid-inner {
    grid-template-columns: 1fr;
  }
}

/* Testimonials: the template's author block had an avatar; Alegria's reviewers
   are real Google reviewers with no photos, so the avatar was dropped. */
.mx-testi1-item .auth-inner .btm-text {
  padding-left: 0;
}

/* Appointment form: replaces the Contact Form 7 markup. */
.mx-form-status {
  margin-top: 16px;
  min-height: 1.5em;
  text-align: center;
}
.mx-form-status[data-form-status="error"] {
  color: #d33;
}
.mx-appoint-callout {
  margin-top: 24px;
}
.mx-appoint-callout a {
  color: var(--mx-prime-c);
  font-weight: 600;
}

/* Confirmation panel — the success state shared by both forms.
   The theme gives `.mx-appoint-form` a WHITE card but its `.ver_2` variant a
   NAVY one (style.css:7512, background var(--mx-prime-c2)), and whitens only
   `.form-title h3` and `.form-title p` there (:7522, :7526). `.mx-form-sent`
   was never in that list, so on /contact-us the thank-you rendered dark navy
   on navy — invisible. Measured against #0B1F3F: the brand-blue link is
   2.64:1 and the #d33 error above is 3.49:1, both under the 4.5:1 AA floor —
   so the FAILURE state was nearly as unreadable as the success one. The
   replacements are #fff (15.4:1) and #ff8a8a (7.17:1). */
.mx-form-sent {
  padding: 24px 0 8px;
}
.mx-form-sent .mx-sent-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 64px;
  margin: 0 auto 24px;
  border-radius: 50%;
  font-size: 30px;
  line-height: 1;
  color: var(--mx-prime-c);
  background-color: rgba(27, 79, 232, 0.1);
}
.mx-form-sent p {
  margin: 0 auto;
  max-width: 450px;
}
.mx-form-sent .mx-sent-note {
  margin-top: 20px;
  font-size: 15px;
  opacity: 0.75;
}

/* Once the panel is up, the card's own title ("Send Us a Message" plus its
   intro) is stale — it invites an action that has already happened, and it was
   what made the confirmation read as an error rather than a success. Hiding it
   lets the whole card read as one deliberate confirmation. */
.mx-appoint-form:has(.mx-form-sent) .form-title {
  display: none;
}

/* On /contact-us the card is a flex item in `.mx-appoint2-content` and stretches
   to the height of the column beside it (756px measured at 1920px). The form
   fills that; a four-line thank-you does not, and left-aligned at the top it
   read as a card that had failed to load. Centring the panel in the space the
   card already occupies keeps the row's geometry identical and makes the empty
   area look deliberate. Harmless on the other three routes, where the card is
   not in a stretch row and this block is its only child. */
.mx-appoint-form:has(.mx-form-sent) {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* The navy card. Everything above assumes dark ink on white. */
.mx-appoint-form:is(.ver_2) .mx-form-sent h3,
.mx-appoint-form:is(.ver_2) .mx-form-sent p {
  color: #fff;
}
.mx-appoint-form:is(.ver_2) .mx-form-sent .mx-sent-icon {
  color: #fff;
  background-color: rgba(255, 255, 255, 0.12);
}
.mx-appoint-form:is(.ver_2) .mx-form-sent a {
  color: #fff;
  font-weight: 600;
  text-decoration: underline;
}
.mx-appoint-form:is(.ver_2) .mx-form-status[data-form-status="error"] {
  color: #ff8a8a;
}

/* Info cards: drop the fixed card height once the cards stop sharing a row.
   The theme sets `.cta-bottom { height: 336px }` — a flex column with
   `justify-content: space-between` — and never reduces it at any breakpoint.
   Across three side-by-side columns that fixed height IS the design: it is what
   keeps the coloured boxes aligned when each card holds a different number of
   list rows. Below 768px the theme collapses the grid to ONE column, and the
   same rule then just pads each card out to 336px and pushes its phone numbers
   to the bottom. Measured at 390px: 298 / 233 / 196px of real content in three
   336px boxes — 38 / 103 / 140px of dead space, 281px in the section.
   Nothing shares a row here, so let each card size to its content. Scoped to
   the single-column range only; 768px and up keeps the template's alignment. */
@media only screen and (min-width: 576px) and (max-width: 767px),
  only screen and (min-width: 481px) and (max-width: 575px),
  (max-width: 480px) {
  .mx-app-cta-item .cta-bottom {
    height: auto;
  }
  /* The white watermark is `position: absolute; right/bottom: -50px` with no
     z-index, so it paints OVER .cta-bottom. On a 336px card it lands in the
     empty lower half and reads as decoration; against a content-height card it
     crosses the copy. It already did on card 3, where it cut through the
     phone number — the one thing on this card a caller needs. The theme makes
     the same call for its own `.mx-step1-item .item-shape`, which is
     `display: none` at every width below 1200px. */
  .mx-app-cta-item .item-shape {
    display: none;
  }
}

/* ---------------------------------------------------------------------------
   Mobile nav drawer
   The template ships a near-black (#0f0d0d) drawer with white links and a red
   (#d60606) close X — no colour in it belongs to Alegria, and logo.webp's black
   wordmark bar disappears into the background. Repaint it white to match the
   header, where the same logo already reads correctly.
   Also fixes three template defects, noted per rule below.
   --------------------------------------------------------------------------- */

/* theme: background-color:#0f0d0d; height:100vh; overflow-y:scroll.
   100vh lets the iOS address bar clip the drawer's bottom -> 100dvh.
   overflow-y:scroll reserved a permanent scrollbar gutter -> auto. */
.mobile_menu_content {
  background-color: #fff;
  height: 100dvh;
  overflow-y: auto;
  box-shadow: 0 3px 24px rgba(11, 31, 63, 0.16);
}

/* theme: border-bottom rgba(255,255,255,.06) — invisible on white. */
.mobile_menu_content .mobile-main-navigation .navbar-nav li {
  border-bottom: 1px solid rgba(11, 31, 63, 0.1);
}

/* theme: color:#fff. The 18px link had no min tap height and no transition. */
.mobile_menu_content .mobile-main-navigation .navbar-nav li a {
  color: var(--mx-prime-c2);
  display: flex;
  align-items: center;
  min-height: 44px;
  border-left: 3px solid transparent;
  padding-left: 12px;
  transition: color 0.2s ease-in-out, border-color 0.2s ease-in-out;
}

/* The theme defines NO hover state for mobile nav links, and never styles
   .current-menu-item even though the class is present in the markup. */
.mobile_menu_content .mobile-main-navigation .navbar-nav li a:hover,
.mobile_menu_content .mobile-main-navigation .navbar-nav li a:focus-visible {
  color: var(--mx-prime-c);
}
.mobile_menu_content .mobile-main-navigation .navbar-nav li.current-menu-item a {
  color: var(--mx-prime-c);
  border-left-color: var(--mx-prime-c);
}

/* Same gap in the DESKTOP nav, and it only started to matter once there was a
   second page: the theme styles a resting pill (#f6f7f9) and a navy hover, but
   never .current-menu-item, so every item looked identical no matter where you
   were. Brand blue reads as "you are here" without being mistaken for the hover.
   Scoped to #main-nav so it cannot reach the drawer, which shares class names.
   The id beats the theme's :hover selector, so the current page stays marked
   while hovered — it is not somewhere you can navigate to. */
#main-nav > li.current-menu-item > a {
  color: #fff;
  background-color: var(--mx-prime-c);
}

/* theme: color:#d60606 on a bare 20px glyph — off-palette, and the tap target
   was ~20px against a 44px minimum. */
.mobile_menu .mobile_menu_close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background-color: #f6f7f9;
  color: var(--mx-prime-c2);
  transition: color 0.2s ease-in-out, background-color 0.2s ease-in-out;
}
.mobile_menu .mobile_menu_close:hover {
  color: var(--mx-prime-c);
  background-color: rgba(27, 79, 232, 0.08);
}

/* theme: color:#fff, and :hover uses var(--ra-base-c1) — a variable that is
   defined NOWHERE in the vendored CSS, so the hover was dead. */
.mobile_menu .ptx-mobile-header-social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid rgba(11, 31, 63, 0.15);
  color: var(--mx-prime-c2);
  transition: color 0.2s ease-in-out, border-color 0.2s ease-in-out;
}
.mobile_menu .ptx-mobile-header-social a:hover {
  color: var(--mx-prime-c);
  border-color: var(--mx-prime-c);
}

/* theme: rgba(0,0,0,.9). A navy scrim reads better behind a white panel. */
.mobile_menu_overlay {
  background-color: rgba(11, 31, 63, 0.6);
}

/* NEW markup (mx-m-* is not a theme namespace). Below 1400px the header hides
   .ct-call, and below 480px it hides .ct-btn — so on a phone the header offered
   no way to call and no way to apply. The drawer carries both instead.
   Radius/height match .mx-btn1 so these read as the site's buttons. */
.mx-m-cta {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 28px;
}
.mx-m-cta a {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  min-height: 48px;
  padding: 0 20px;
  border-radius: 30px;
  font-weight: 600;
  font-size: 16px;
  transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
}
.mx-m-call {
  background-color: var(--mx-prime-c);
  color: #fff;
}
.mx-m-call:hover {
  background-color: var(--mx-prime-c2);
  color: #fff;
}
.mx-m-call svg {
  width: 20px;
  height: 20px;
}
.mx-m-join {
  border: 1px solid rgba(11, 31, 63, 0.25);
  color: var(--mx-prime-c2);
}
.mx-m-join:hover {
  background-color: var(--mx-prime-c2);
  color: #fff;
}

/* ---------------------------------------------------------------------------
   Inert anchors
   Two different reasons an <a> here can have no href, sharing one rule:

   [data-paused] — TEMPORARY. Down to ONE: the footer's `Login`, one anchor per
     route. /our-services, /about-us and /contact-us shipped and un-paused
     theirs; /join-our-team was RETIRED rather than built — its four CTAs now
     open the careers popup and carry a real mailto: href, so they are ordinary
     links (app/_careers.ts). Decide Login's fate — build it or cut it — and
     when it goes, delete `a[data-paused]` from the selector below but KEEP
     `a[data-static]`. `grep data-paused app/` is the live inventory.

   [data-static] — PERMANENT. The task chips on /our-services are wrapped in <a>
     only because the theme's CSS is keyed to `li a .list-area` and would not
     apply otherwise. They were never links and never will be.

   An <a> without href is already non-focusable and inert to the keyboard; this
   block covers the pointer: no link cursor, and no :hover effects firing on
   something that can't be clicked. The theme styles these as `a`, not `a[href]`,
   so the design is unchanged either way.
   --------------------------------------------------------------------------- */
a[data-paused],
a[data-static] {
  cursor: default;
  pointer-events: none;
}

/* ---------------------------------------------------------------------------
   Footer background wordmark ("Alegria")
   The theme hardcodes font-size:324px (150px only below 768px) and
   letter-spacing:-20px, inside .mx-footer-sec.over-hidden. Those fixed sizes
   don't fit the fluid .container at most widths, so the word was clipped: it
   overflowed by 36px at 390px, and the template is worse at 768-1199px, where
   the font snaps back to 324px inside a ~714px container.

   The container is fluid (0.93-0.98 of the viewport, capped at 1584px), so one
   viewport-relative size fits everywhere. The usable box is narrower than the
   container: below 992px .mx-footer-sec takes margin:0 24px, and .container adds
   12px padding, so the text must fit `container - 24`. Solving that across
   320-1920 makes 26vw the largest safe factor (320px is the binding case); it
   lands the word at ~89-92% of the usable box. min() caps it at the theme's
   324px from ~1246px up, leaving desktop exactly as it was.

   Sizes are set on .mx-ftr-text so the -80px card overlap can scale with them:
   -80/324 = -0.247em, so the same ~27% of the word tucks behind the card at
   every width, as the template does on desktop. letter-spacing likewise moves
   to -0.062em (= -20/324) instead of a fixed -20px, which was disproportionately
   tight at the 150px mobile size. */
.mx-ftr-text {
  font-size: min(324px, 26vw);
  margin-bottom: -0.247em;
}
.mx-ftr-text h2 {
  font-size: inherit;
  letter-spacing: -0.062em;
  white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   /our-services
   Everything below is scoped to the inner-page sections; the homepage never
   renders these classes.
   --------------------------------------------------------------------------- */

/* Breadcrumb banner. The theme darkens the photo with a flat `#00000047` (~28%
   black) on .sn-breadcrumb-wrapper, which is nowhere near enough for the centred
   white .bread_title over Alegria's banners, all of which are bright, outdoor or
   backlit shots. Replace it with the same navy the hero scrim uses, weighted
   toward the top where the title sits. The wrapper paints the photo inline, so
   the scrim goes on ::before rather than replacing the background shorthand. */
.sn-breadcrumb-sec .sn-breadcrumb-wrapper {
  position: relative;
  background-color: transparent;
  background-size: cover;
  background-position: center 30%;
  background-repeat: no-repeat;
}
.sn-breadcrumb-sec .sn-breadcrumb-wrapper::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(11, 31, 63, 0.86) 0%,
    rgba(11, 31, 63, 0.72) 55%,
    rgba(11, 31, 63, 0.78) 100%
  );
}
/* The header is `position: fixed`, 115px tall and TRANSPARENT, so from 576px up
   it floats over the top of the banner photo — the template's own design, and
   .sn-breadcrumb-content's 180px top padding keeps .bread_title clear of it.
   At 575px and below the theme stops overlaying and reserves space instead:
   `.sn-breadcrumb-sec { padding-top: 80px }`. That 80px was measured against the
   template's short wordmark. Alegria's logo is 132x83 sitting 24px down, so its
   bottom edge lands at 107px and the banner slid under it by 27px — the header
   read as sitting ON the photo with the logo half-cut. Reserve the header's real
   height instead. Same media range the theme's own rule uses. */
@media only screen and (min-width: 481px) and (max-width: 575px),
  (max-width: 480px) {
  .sn-breadcrumb-sec {
    padding-top: 115px;
  }
}
.sn-breadcrumb-sec .container {
  position: relative;
  z-index: 1;
}

/* Gutter alignment. post-9.css gives the Elementor container a 1584px content
   width with zero padding, while every theme section (.container) is 1584px with
   12px padding — 1560px of content. On the template's own /service/ page that
   never shows, because the page IS one Elementor container. Here the cards sit
   above theme sections, so the 12px mismatch reads as a wobble at desktop and,
   below 768px where the content width drops out, leaves the cards edge-to-edge
   while everything else keeps its gutter. Match the theme.

   Scoped to 7c122e8, the page's OWN container — the only one post-9.css gives
   zero padding. Unscoped it also hit AppointmentIntro's .e-con-inner, which
   carries its own 12px on the outer container (see the shared-sections block at
   the end of this file), doubling that section's gutter to 24px. */
.elementor-9 .elementor-element-7c122e8 > .e-con-inner {
  padding-left: 12px;
  padding-right: 12px;
}

/* Service cards: same treatment the homepage's mx-ser1 cards got. The template
   runs 5 demo services through a Swiper (slidesPerView 4, spaceBetween 12,
   breakpoints 4-3-2-1); Alegria has 3, so it is a static grid whose columns
   mirror the breakpoints it replaced. */
.mx-ser2-grid-inner {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  align-items: stretch;
}
.mx-ser2-col {
  display: flex;
  min-width: 0;
}
.mx-ser2-col > .mx-ser2-item {
  width: 100%;
}
@media (max-width: 991px) {
  .mx-ser2-grid-inner {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 767px) {
  .mx-ser2-grid-inner {
    grid-template-columns: 1fr;
  }
}

/* The template's card CSS reserves 58px under the icon and 45px under the copy
   for a 4-across carousel. Stretched to 3 columns with Alegria's shorter copy
   that leaves the cards looking hollow, so pull both in. */
.mx-ser2-item .item-icon {
  margin-bottom: 32px;
}
.mx-ser2-item .item-text p {
  padding-bottom: 28px;
}

/* Service detail rows. This composition has no counterpart on the template's
   /service/ page — the .mx-assist-list block is borrowed from the theme's home-4
   demo, so only the surrounding spacing is ours. */
.mx-svc-details {
  padding-top: 30px;
  padding-bottom: 100px;
}
.mx-svc-details .mx-assist-list + .mx-assist-list {
  margin-top: 80px;
}
/* These rows are jump targets from the cards above. Without this the heading
   lands flush against the viewport top, and the sticky header (111px, fixed,
   revealed on any upward scroll) would sit straight over it. */
.mx-svc-details .mx-assist-list {
  scroll-margin-top: 130px;
}

/* Photo sizing. The theme gives .item-img no width at all, so it shrink-wraps to
   its image — the same trap the About section hit. It must be PINNED, not sized
   by the img: `.img-cover img` carries `height: 100% !important`, which beats any
   height set on the img itself and falls back to the intrinsic aspect ratio. (A
   flexible column plus a fixed img height produced 930x883 photos for exactly
   this reason.) So pin the wrapper and let img-cover fill it, the same way
   .mx-abt1-img does on the homepage.

   620px wide is deliberate: the source photos are 632x600, so the slot renders
   them at essentially 1:1 horizontally and stays as sharp as the originals allow
   (they are already noted as low-res for their slots). 460px tall crops ~1/4 off
   the vertical rather than distorting. */
.mx-assist-list .item-img {
  flex: 0 0 auto;
  width: 620px;
  max-width: 100%;
  height: 460px;
  max-height: none;
  align-self: flex-start;
}
/* The theme's `max-width: 600px` is meant for the chip labels but also lands on
   the text column, which would leave ~400px of dead space beside the photo.
   Scoped with `>` so only the column is freed; labels keep the cap. */
.mx-svc-details .mx-assist-list > .item-text {
  flex: 1 1 auto;
  min-width: 0;
  max-width: none;
}

/* The theme only wraps this row below 768px, so 768-1199 would squeeze a 620px
   photo against the text. Stack them early instead, and alternate the photo side
   only while the row is genuinely side-by-side — three identical left-photo rows
   stacked reads as a repeating template, but once stacked the order is vertical
   and reversing it just scrambles the reading order. */
@media (min-width: 1200px) {
  .mx-svc-details .mx-assist-list:nth-child(even) {
    flex-direction: row-reverse;
  }
}
@media (max-width: 1199px) {
  .mx-assist-list {
    flex-wrap: wrap;
  }
  /* Stacked, the photo would stretch to the full row — 961px at 991px viewport,
     a 1.5x upscale of a 632px-wide source that is already soft. Cap it at native
     width and centre it instead of magnifying it. */
  .mx-assist-list .item-img {
    width: 100%;
    max-width: 632px;
    height: 380px;
    margin-left: auto;
    margin-right: auto;
  }
}
@media (max-width: 575px) {
  .mx-assist-list .item-img {
    height: 260px;
  }
}

/* Task chips. The list is Alegria's real task list, so it runs to 13 items —
   longer than the donor demo's 4. Two columns keep the row from towering over
   its photo, and the theme's 45px ul offset is too much under a heading. */
.mx-assist-list .item-text ul {
  margin-top: 24px;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 12px;
}
/* Fall back to one column wherever the text column is too narrow to carry two:
   below 768px, and in the 1200-1399 band where the row is side-by-side and a
   fixed 620px photo leaves the text only ~530px. Labels like "Assistance with
   Activities of Daily Living" hit three lines in a 254px pill otherwise. */
@media (max-width: 767px), (min-width: 1200px) and (max-width: 1399px) {
  .mx-assist-list .item-text ul {
    grid-template-columns: 1fr;
  }
}
/* The theme zeroes margin-bottom on every .headline heading, and the donor demo
   never puts a heading in this block, so Escort Services' paragraph butted
   straight against its h2. The task lists set their own 24px, which wins the
   sibling-margin collapse, so this only affects the paragraph. */
.mx-svc-details .mx-assist-list > .item-text > h2 {
  margin-bottom: 18px;
}

/* The donor demo lets each pill shrink-wrap to its label, which is fine for four
   evenly-sized items but reads as ragged across a 13-item grid. The <a> is inline
   by default, so the .list-area flex inside it never fills the cell — make it a
   block so every pill in a column lines up. */
.mx-assist-list .item-text li > a {
  display: block;
}

/* .item-text is the theme's class for BOTH the text column and each chip label,
   so its max-width:600px lands on the labels too. Harmless there, but the label
   must be allowed to wrap rather than blow out the pill. */
.mx-assist-list .item-text li a .list-area .item-text {
  min-width: 0;
}
.mx-assist-list .item-text li a .list-area .item-icon {
  flex: 0 0 auto;
}

/* ---- /contact-us -----------------------------------------------------------
   The theme's mx-appt-list chip puts its glyph in a 72px tile painted
   --mx-prime-c2 (navy), but colours every `i` inside the chip #000 — because the
   template fills that tile with a white SVG <img>, not an icon font. Our chips
   use Font Awesome classes, so the glyph inherited black on navy: measured
   1.28:1, effectively invisible. Repaint it white (16.4:1) and size it to the
   tile. Scoped to .item-icon so the chip's trailing arrow, which sits on the
   light page background, keeps the theme's black. */
.mx-appt-list .item-icon i {
  color: #fff;
  font-size: 26px;
}

/* The template desaturates its map to sit quietly behind the design:
   post-11.css sets
     filter: brightness(109%) contrast(96%) saturate(0%) blur(0) hue-rotate(132deg)
   on the iframe — saturate(0%) is what makes it greyscale. Alegria wants the
   normal Google Maps colours, which also makes the pin and the road hierarchy
   easier to read. Same selector as post-11.css so specificity ties and this
   wins on load order; only `filter` is overridden, so the 550px height that
   rule also sets is left alone. */
.elementor-11 .elementor-element.elementor-element-5eb5c90 iframe {
  filter: none;
}

/* ---- Shared homepage sections reused on inner pages ------------------------
   AppointmentIntro / AppointmentForm / Marquee / Testimonials are homepage
   sections, but their Elementor container geometry only exists in post-5.css,
   where every rule is scoped under `.elementor-5`. Reused under `.elementor-9`
   (and the inner pages still to come) those selectors do not match, so the
   containers fall back to Elementor's stock `.e-con` defaults from
   frontend.min.css — 10px padding, min(100%, 1140px) content width, 20px gap.
   On "Getting Care Started Is Simple" that cost 90px of padding top and bottom,
   444px of width, its centred heading, and the 65px above its button.

   Deliberately UNPREFIXED. post-5.css's `.elementor-5 .elementor-element.…` is
   (0,3,0) and beats these (0,2,0) rules whatever the load order, so the
   homepage cannot move; every other route gets them. Values are verbatim from
   post-5.css. A section reused on a new page needs nothing added here. */

/* AppointmentIntro — "Getting Care Started Is Simple" */
.elementor-element.elementor-element-cbc28b6 {
  --display: flex;
  --gap: 0px 0px;
  --row-gap: 0px;
  --column-gap: 0px;
  --padding-top: 100px;
  --padding-bottom: 100px;
  --padding-left: 12px;
  --padding-right: 12px;
}
/* Below 768px the Elementor kit drops --container-max-width to 767px and the
   template relies on that fallback, so this stays inside the media query. */
@media (min-width: 768px) {
  .elementor-element.elementor-element-cbc28b6 {
    --content-width: 1584px;
  }
}
.elementor-element.elementor-element-a39710c .prthalign {
  text-align: center;
}
.elementor-element.elementor-element-60db939 > .elementor-widget-container {
  padding: 65px 0px 0px 0px;
}
.elementor-element.elementor-element-60db939 .justify-content-center {
  justify-content: center !important;
}

/* AppointmentForm */
.elementor-element.elementor-element-dcb7198 {
  --display: flex;
  --padding-top: 0px;
  --padding-bottom: 0px;
  --padding-left: 0px;
  --padding-right: 0px;
}

/* Marquee — --overflow:hidden is part of its geometry, not decoration. */
.elementor-element.elementor-element-1e08017 {
  --display: flex;
  --overflow: hidden;
  --padding-top: 0px;
  --padding-bottom: 0px;
  --padding-left: 0px;
  --padding-right: 0px;
}

/* Testimonials. post-5.css writes --padding-bottom:0100px; browsers parse that
   as 100px, so 100px is the real value — the leading zero is a theme typo. */
.elementor-element.elementor-element-00d55f2 {
  --display: flex;
  --padding-top: 70px;
  --padding-bottom: 100px;
  --padding-left: 0px;
  --padding-right: 0px;
}

/* ---------------------------------------------------------------------------
   Video block  (mx-video-* is NEW markup — not a theme namespace)

   Added 2026-08-31 for app/_sections/VideoBlock.tsx: the client's own films on
   `/` (30s spot) and `/about-us` (85s brand film).

   Deliberately built on the theme's Bootstrap `.container` rather than an
   Elementor container, so none of these rules depend on a `.elementor-<id>`
   scope and the block renders identically on both routes. That is why there is
   no matching entry in the shared-sections block above.
   ------------------------------------------------------------------------- */

/* ASYMMETRIC padding, because the two neighbours are not the same kind of thing.
   Read this before "tidying" it into a symmetric value.

   ABOVE — `.mx-abt-sec pt-120 pb-100` on both routes, and it has a TRANSPARENT
   background. Its trailing 100px is therefore visible empty space, so its
   content edge is also its visual edge. Adding a band here just stacks on that:
   it produced a 200px gap against a measured site rhythm of 100/100/100/120/165
   across the homepage's other joins — the largest ordinary gap on the page, and
   the top-heaviness that was reported. So: no top padding.

   BELOW — the next section PAINTS its background (the navy Services band on `/`,
   the image-backed appointment block on `/about-us`) and it paints from its BOX
   TOP, not from its inner container. Its own leading 100px is inside that colour
   and is not empty space at all. With no padding here the language buttons ended
   up flush against the navy edge — a 0px visible gap. So: a full 100px band.

   The lesson for anything added next to this block: measure a gap to the
   neighbour's PAINTED edge, not its inner container. For a transparent section
   those are the same; for a painted one they differ by its whole top padding. */
.mx-video-sec {
  padding-top: 0;
  padding-bottom: 100px;
}

/* The theme centres a .mx-sec-title only via `.prthalign`, which post-<id>.css
   scopes to one element id per page — useless here by design, so centre it
   directly. margin-bottom matches the theme's .mx-sec-title-to-content gap. */
.mx-video-sec .mx-video-title {
  text-align: center;
  max-width: 720px;
  margin: 0 auto 45px;
}

/* 16:9 frame.

   max-width is load-bearing: at the theme's full 1584px content width a 16:9
   video is 891px tall, which swamps the viewport and dwarfs every neighbouring
   section. 1080px gives a 608px-tall frame, close to .mx-abt1-img's 505px.

   24px radius + overflow:hidden is the theme's own media language — the same
   pair used by .mx-abt1-img, .mx-abt1-img2 .item-img, .mx-hero2-video and
   .mx-ab3-top .item-img. Black ground so any letterboxing reads as intentional
   rather than as a broken poster. */
.mx-video-sec .mx-video-frame {
  max-width: 1080px;
  margin: 0 auto;
  border-radius: 24px;
  overflow: hidden;
  background: #000;
}

/* display:block kills the inline-element descender gap — the same 8px bug the
   Google Maps widget needed `.elementor-custom-embed { line-height: 0 }` for.
   aspect-ratio holds the 16:9 box before metadata loads, so preload="none"
   cannot cause a layout shift when the poster or video finally arrives.
   NOTE: the theme's `.img-cover video` rule carries height:100% !important — it
   is not applied here (this wrapper is not .img-cover) precisely because these
   videos must never be cropped; see the watermark note in VideoBlock.tsx. */
.mx-video-sec .mx-video-frame video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
}

/* Only ever seen if the browser can decode neither source (VP9/WebM predates
   Safari 14.1 / iOS 17.4). White on the frame's black ground. */
.mx-video-sec .mx-video-fallback {
  margin: 0;
  padding: 24px;
  color: #fff;
  text-align: center;
}
.mx-video-sec .mx-video-fallback a {
  color: #fff;
  text-decoration: underline;
}

/* EN/ES pills. 44px min height matches the touch-target floor already set for
   the mobile drawer's close button and social chips. The active state mirrors
   the desktop nav pill: brand blue fill, white label. */
.mx-video-sec .mx-video-lang {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-top: 24px;
}
.mx-video-sec .mx-video-lang-btn {
  min-height: 44px;
  padding: 0 24px;
  border-radius: 999px;
  border: 1px solid rgba(11, 31, 63, 0.15);
  background: transparent;
  color: var(--mx-prime-c2);
  font-weight: 600;
  cursor: pointer;
  transition: color 0.2s ease-in-out, background-color 0.2s ease-in-out,
    border-color 0.2s ease-in-out;
}
.mx-video-sec .mx-video-lang-btn:hover,
.mx-video-sec .mx-video-lang-btn:focus-visible {
  color: var(--mx-prime-c);
  border-color: var(--mx-prime-c);
}
.mx-video-sec .mx-video-lang-btn.is-active {
  background: var(--mx-prime-c);
  border-color: var(--mx-prime-c);
  color: #fff;
}

/* --- Play overlay -------------------------------------------------------- */

/* The overlay is positioned against the frame. */
.mx-video-sec .mx-video-frame {
  position: relative;
}

.mx-video-sec .mx-video-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Before first play the whole frame is the hit area — clicking the middle of
   the poster is the single most expected gesture on a video and previously did
   nothing. */
.mx-video-sec .mx-video-overlay.is-initial {
  cursor: pointer;
}
/* After playback has started the native control bar is showing underneath, so
   the overlay must not swallow clicks meant for it. Only the button stays live. */
.mx-video-sec .mx-video-overlay.is-resumable {
  pointer-events: none;
}
.mx-video-sec .mx-video-overlay.is-resumable button {
  pointer-events: auto;
}

/* The theme never gave .sn-vd5-play a position, but its .video-play-btn child is
   absolutely positioned — without this the button escapes to the frame corner. */
.mx-video-sec .sn-vd5-play {
  position: relative;
}

/* The theme styles `.video-play-btn a`. This is an action, not a link, so it is
   a real <button> for keyboard and screen-reader users — these declarations
   mirror the theme's own 108px circle rather than inventing a second look.
   Recoloured to brand blue: the theme's white circle was designed to sit on dark
   footage, and Alegria's poster is a light blue card where white would vanish. */
.mx-video-sec .sn-vd5-play .video-play-btn button {
  width: 108px;
  height: 108px;
  display: flex;
  margin: 0 auto;
  padding: 0;
  border: 0;
  border-radius: 100%;
  align-items: center;
  justify-content: center;
  position: relative;
  background-color: var(--mx-prime-c);
  color: #fff;
  cursor: pointer;
  box-shadow: 0 10px 30px rgba(11, 31, 63, 0.28);
  transition: background-color 0.2s ease-in-out, transform 0.2s ease-in-out;
}
.mx-video-sec .sn-vd5-play .video-play-btn button:hover {
  background-color: var(--mx-prime-c2);
  transform: scale(1.06);
}
.mx-video-sec .sn-vd5-play .video-play-btn button:focus-visible {
  outline: 3px solid #fff;
  outline-offset: 3px;
}
/* Theme rings are white at 15px, sized for a dark backdrop. Match the button. */
.mx-video-sec .sn-vd5-play .video-play-btn .video_btn_border {
  border-color: rgba(27, 79, 232, 0.45);
  border-width: 10px;
}

/* The ripple is decoration; honour a reduced-motion preference the way the hero
   entrance already does. */
@media (prefers-reduced-motion: reduce) {
  .mx-video-sec .sn-vd5-play .video-play-btn .video_btn_border {
    animation: none;
  }
  .mx-video-sec .sn-vd5-play .video-play-btn button {
    transition: none;
  }
}

@media (max-width: 767px) {
  /* Same asymmetry as desktop, one step tighter on the painted side. */
  .mx-video-sec {
    padding-bottom: 70px;
  }
  .mx-video-sec .mx-video-title {
    margin-bottom: 30px;
  }
  /* A 24px radius on a ~340px-wide frame reads as a heavy rounding; the theme
     makes the same reduction on its own media cards below 768px. */
  .mx-video-sec .mx-video-frame {
    border-radius: 16px;
  }
  /* 108px is over a third of a 360px-wide frame. Scale the whole ripple stage
     rather than the button alone, so the rings stay concentric. */
  .mx-video-sec .sn-vd5-play {
    transform: scale(0.62);
  }
}

/* Careers popup — app/_components/CareersModal.tsx.
   /join-our-team was retired in favour of this dialog, so the four CTAs that
   pointed at it are now real mailto: links (app/_careers.ts) that the component
   intercepts after hydration. The panel reuses `.mx-appoint-form.ver_2`, so the
   navy card, the field styling and the confirmation panel above all apply
   unchanged — no second set of form CSS. */
html:has(body.mx-modal-open),
body.mx-modal-open {
  overflow: hidden;
}
.mx-modal {
  position: fixed;
  inset: 0;
  /* 100dvh, not 100vh — the drawer already paid for this lesson: on iOS the
     address bar makes 100vh taller than the visible viewport. */
  height: 100dvh;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 16px;
  /* The PANEL scrolls, not this container. A flex item with `margin: auto`
     that outgrows its scroll container becomes partly unreachable: measured at
     414x742, the 986px panel sat at top:-16px with the resume note 196px below
     the fold and neither end scrollable to. Capping the panel at the viewport
     and scrolling INSIDE it keeps the dialog centred and always whole, and
     leaves this padding visible as backdrop so it reads as a card rather than
     as the whole screen. */
  overflow: hidden;
}
.mx-modal-backdrop {
  position: fixed;
  inset: 0;
  background-color: rgba(11, 31, 63, 0.6);
}
.mx-modal-panel {
  position: relative;
  display: flex;
  width: 100%;
  max-width: 676px;
  max-height: 100%;
  animation: mx-modal-in 0.25s ease-out both;
}
.mx-modal-panel:focus {
  outline: none;
}
.mx-modal-panel .mx-appoint-form {
  width: 100%;
  max-width: 100%;
  max-height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
}
@keyframes mx-modal-in {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .mx-modal-panel {
    animation: none;
  }
}
.mx-modal-close {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  font-size: 18px;
  color: #fff;
  background-color: rgba(255, 255, 255, 0.12);
  transition: background-color 0.2s ease-in-out;
}
.mx-modal-close:hover,
.mx-modal-close:focus-visible {
  background-color: rgba(255, 255, 255, 0.24);
}
/* The empty status line reserves 40px (min-height + margin) on every form,
   which on a phone is 40px of nothing between the button and the resume note.
   Keep the node — it is the aria-live region, and display:none would drop it
   out of the a11y tree — but stop it reserving space until it has something to
   say. */
.mx-form-status:empty {
  min-height: 0;
  margin-top: 0;
}

/* Phones. Trims scoped to .mx-modal so the three page-level forms and
   /contact-us keep the geometry they already ship with. Measured at 414x742:
   these take the card from 986px to comfortably under the viewport, so the
   whole application is visible without scrolling on a typical phone. */
@media only screen and (min-width: 481px) and (max-width: 575px), (max-width: 480px) {
  .mx-modal {
    padding: 16px 12px;
  }
  .mx-modal .mx-appoint-form {
    padding: 30px 18px 24px;
  }
  .mx-modal .form-title {
    margin-bottom: 22px;
  }
  .mx-modal .form-title h3 {
    font-size: 24px;
  }
  .mx-modal .form-title p {
    font-size: 15px;
  }
  .mx-modal .mx-form-input {
    gap: 12px;
  }
  .mx-modal .item-field textarea {
    height: 96px;
  }
  .mx-modal button[type="submit"] {
    margin-top: 0;
  }
  /* Pin the actions to the bottom of the card. Seven fields are taller than a
     phone viewport at any padding worth having, so rather than shrink the
     inputs below a comfortable touch target, let the FIELDS scroll and keep
     "Send Application" and the resume note permanently in view. The background
     is the card's own colour so fields pass cleanly underneath. */
  .mx-modal .mx-form-actions {
    position: sticky;
    bottom: 0;
    padding-top: 14px;
    background-color: var(--mx-prime-c2);
  }
  /* Fade the field above into the pinned bar rather than slicing it, so the
     cut edge reads as "there is more here" instead of as a clipping bug. */
  .mx-modal .mx-form-actions::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 100%;
    height: 28px;
    pointer-events: none;
    background: linear-gradient(to top, var(--mx-prime-c2), transparent);
  }
}

/* The resume line under the careers submit button. The relay is JSON-only and
   cannot take file uploads, so the note is load-bearing, not decoration. */
.mx-form-note {
  margin-top: 16px;
  margin-bottom: 0;
  text-align: center;
  font-size: 15px;
}
.mx-appoint-form:is(.ver_2) .mx-form-note {
  color: rgba(255, 255, 255, 0.75);
}
.mx-appoint-form:is(.ver_2) .mx-form-note a {
  color: #fff;
  font-weight: 600;
  text-decoration: underline;
}
