/*
 * Behaviours that used to need JavaScript, done in CSS.
 *
 * Loaded LAST, after every other stylesheet, so these rules win without
 * !important except where noted.
 *
 * Every value here was measured on the rendered page — the carousel's 4/2/1
 * slides and 10px gap, the menu rules, the sticky offsets. Nothing is guessed.
 *
 * Breakpoints: tablet <=1024px, mobile <=767px.
 */

/* ---------------------------------------------------------------------------
 * 1. Sticky header
 *
 * The header container .elementor-element-f12ec12 — logo, nav, search — pins to
 * the top of the viewport on scroll, while the promo strip above it scrolls
 * away. Measured on the reference rendering: position fixed, top 0, z-index 99.
 *
 * position:sticky ON THAT CONTAINER DOES NOT WORK, which is what shipped here
 * and why the header scrolled away instead of pinning. A sticky element is
 * clamped to its parent's padding box, and its parent is <header>, whose height
 * is exactly the header's own height — so there is zero distance to travel. It
 * was correctly computed as position:sticky and still scrolled off, measured at
 * top:-1467px after a 1500px scroll. No overflow ancestor involved.
 *
 * The fix is to stick the <header> itself, which is a child of <body> and so has
 * the whole document to travel, and to offset it upwards by the height of the
 * promo strip. The strip slides out of view and the nav bar comes to rest at
 * top:0 — the same result, without script.
 *
 * <header> is a bare wrapper: transparent, no padding, margin, border or
 * background of its own (all of that lives on the two inner containers), so
 * making it the positioned element changes nothing but the stacking.
 *
 * The two offsets are the strip's measured height, not guesses: 33px from 768px
 * up, 36px below it — the mobile breakpoint. Verified at 14 viewport widths.
 *
 * Known limit: below ~345px the strip's own text wraps to two lines and grows to
 * 69px, leaving a sliver of it visible while pinned. Not worth a third
 * breakpoint — the wrap point moves whenever that copy is edited, so the media
 * query would silently go stale. Cosmetic, and only on viewports narrower than
 * an iPhone SE.
 * ------------------------------------------------------------------------- */
.elementor-location-header {
  position: sticky;
  top: -33px;
  z-index: 100;
}

@media (max-width: 767px) {
  .elementor-location-header {
    top: -36px;
  }
}

/* Same deal in the single-post sidebar: the "Search for apartments" widget carries
 * {"sticky":"top","sticky_offset":130,"sticky_parent":"yes"}, so it rides down
 * with the article until the sidebar column ends. */
.elementor-33185 .elementor-element-7d178ad {
  position: sticky;
  top: 130px;
}

/* ---------------------------------------------------------------------------
 * 2. Mobile menu toggle
 *
 * The nav has NO submenus — three flat items — so smartmenus was only ever
 * opening the burger menu. Elementor's CSS already does the animation; its JS
 * merely adds .elementor-active to the toggle. extract-chrome.mjs rewrites the
 * toggle into <input type=checkbox> + <label>, so :checked drives the same
 * rules. The general sibling combinator is used because the checkbox sits
 * before the label, which sits before the menu container.
 * ------------------------------------------------------------------------- */
.hl-nav-toggle-input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
  pointer-events: none;
}

.elementor-nav-menu--toggle .hl-nav-toggle-input:checked ~ .elementor-nav-menu__container {
  max-height: var(--menu-height, 100vh);
  overflow-y: auto;
  transform: scaleY(1);
}

/* Icon swap: Elementor shows --close only while .elementor-active is set. */
.elementor-menu-toggle .elementor-menu-toggle__icon--close { display: none; }
.hl-nav-toggle-input:checked ~ .elementor-menu-toggle .elementor-menu-toggle__icon--close { display: block; }
.hl-nav-toggle-input:checked ~ .elementor-menu-toggle .elementor-menu-toggle__icon--open { display: none; }

/* The label replaced a div[role=button]; keep it behaving like a button. */
label.elementor-menu-toggle { cursor: pointer; }

/* The widget carries elementor-nav-menu--stretch (full_width: stretch), which
 * widget-nav-menu.css only takes as far as position:absolute — Elementor's JS
 * measures the page and writes the inline width/left that make the panel span
 * the viewport (live site: "width: 500px; left: -447px" at a 500px viewport).
 *
 * Same result without the measuring: drop the two positioned ancestors between
 * the dropdown and the full-width sticky header container, so the header
 * becomes its containing block and left/right:0 reaches both edges. Scoped to
 * the breakpoint where the burger exists (elementor-nav-menu--dropdown-tablet)
 * so the desktop menu is untouched. */
@media (max-width: 1024px) {
  .elementor-nav-menu--stretch.elementor-widget-nav-menu,
  .elementor-location-header .e-con.e-child:has(> .elementor-nav-menu--stretch) {
    position: static;
  }

  .elementor-nav-menu--stretch .elementor-nav-menu__container.elementor-nav-menu--dropdown {
    top: 100%;
    left: 0;
    right: 0;
    width: auto;
  }
}

/* ---------------------------------------------------------------------------
 * 2a. Header layout in the burger range
 *
 * DELIBERATE DIVERGENCE from the reference rendering — delete this block to go
 * back to matching it exactly.
 *
 * Between 768px and 1024px the burger appears but the header keeps its desktop
 * arrangement: the burger sits first in the row, which lands it near the middle
 * of the bar, and the "Sign in" button is still shown, wrapping onto two lines
 * in the space left over. Below 768px neither happens.
 *
 * Nothing here is invented. Those are the two rules the stylesheet already
 * applies below 768px — order:99999 on the menu widget so it falls last in a
 * flex-end row, and display:none on the Sign in button — extended up to cover
 * the whole range where the burger exists. Result across the band: logo left,
 * search then burger hard right, no wrapped button.
 *
 * Bounded at BOTH ends on purpose. Below 768px the stylesheet already produces
 * this layout and matches the reference rendering to the pixel; letting these
 * rules reach down there moved the burger 9px and broke that match. This band is
 * exactly the range that is wrong, and nothing else.
 * ------------------------------------------------------------------------- */
@media (min-width: 768px) and (max-width: 1024px) {
  /* Menu widget last in the row, so the burger is the right-most control. */
  .elementor-location-header .elementor-element-c22b653 {
    order: 99999;
  }

  /* ...and the burger hard against the end of that widget. The widget keeps a
   * width sized for the horizontal menu it is no longer showing (590px at
   * 900px, against the 43px it collapses to below 768px), and the toggle sits
   * inside it under `margin: 0 auto` — so it centres in that leftover box,
   * which is what strands it mid-bar. Dropping the right margin lets the auto
   * left margin push it all the way over. Shrinking the widget instead does not
   * work: it stretches to the row rather than to its contents.
   *
   * Four classes, not the three this file usually needs: the rule being
   * overridden is itself four classes deep, so a shorter selector loses on
   * specificity no matter that this file loads last. */
  .elementor-32997 .elementor-element.elementor-element-c22b653 .elementor-menu-toggle {
    margin-left: auto;
    margin-right: 0;
  }

  /* Sign in is reachable from the burger menu; showing it here only forces a
   * two-line button into a row that has no width for it. */
  .elementor-location-header .elementor-element-dedfb11 {
    display: none;
  }
}

/* ---------------------------------------------------------------------------
 * 2b. Search widget
 *
 * widget-search.css ships it as .e-search.hidden {opacity:0;visibility:hidden}
 * and Elementor's JS drops the class on load, so with no JS the field is
 * invisible on every page — including inside the open burger menu, where the
 * live site shows it. Reveal it here.
 *
 * The live-results dropdown was JS; what remains is the plain GET form the
 * markup already carries (action="/blog", name="s").
 * ------------------------------------------------------------------------- */
.e-search.hidden { opacity: 1; visibility: visible; }

/* The input's padding is calc() over two variables Elementor's JS writes after
 * measuring the icons — with them unset the whole calc is invalid and the
 * padding collapses to 0, so the placeholder sits under the magnifier. These
 * are the widths the live site measures at this icon size (12px): 12px for the
 * label icon, 8.25px for the clear icon. */
.elementor-widget-search .e-search-input {
  --e-search-icon-label-absolute-width: 12px;
  --e-search-icon-clear-absolute-width: 8.25px;
}

/* The clear icon only appears once there is text to clear — the JS toggles
 * .hidden on it. Nothing types into it here, so hold the hidden state (and
 * with it the space the padding above reserves, exactly as the live site does).
 */
.elementor-widget-search .e-search-input-wrapper > svg.e-fas-times {
  opacity: 0;
  visibility: hidden;
}

/* ---------------------------------------------------------------------------
 * 2c. Sidebar city search
 *
 * static/js/city-search.js filters the city list by setting [hidden] on rows,
 * but an earlier stylesheet declares `display: flex !important` on those rows,
 * which beats the hidden attribute's UA rule — so the filter had no visible
 * effect. Restate it with the same weight. The empty-state line is ours; the
 * reference rendering re-fetched the panel and simply returned nothing.
 * ------------------------------------------------------------------------- */
.hellolanding-sidebar-city-search-wrapper .search-result-list ul li[hidden] {
  display: none !important;
}

.hellolanding-sidebar-city-search-wrapper .search-result-list .hl-city-search-empty {
  font-size: 14px;
  color: #787573;
  margin: 0;
}

/* ---------------------------------------------------------------------------
 * 3. Loop carousel  (replaces swiper + elementor loop-carousel handlers)
 *
 * swiper.css is written for JS to take over, so on its own it renders nothing
 * usable:
 *     .swiper         { overflow: hidden }        -> cannot scroll
 *     .swiper-wrapper { flex-direction: column }  -> JS adds .swiper-horizontal
 *     .swiper-slide   { width: 100% }             -> JS sets per-slide widths
 *
 * Native scroll-snap gives the same affordance: swipe on touch, trackpad
 * scroll, keyboard arrows, and it degrades to a plain scrollable row.
 * slides_to_show from data-settings: 4 desktop / 2 tablet / 1 mobile, gap 10px.
 * ------------------------------------------------------------------------- */
.elementor-widget-loop-carousel .swiper {
  /* The carousel container also carries .elementor-grid (display: grid), which
   * makes .swiper-wrapper a grid item sized to its max-content — so the
   * wrapper grows with the slide count and the per-slide percentage widths
   * resolve against that inflated width instead of the visible viewport.
   * Block layout pins the wrapper to the container width. */
  display: block;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;            /* Firefox */
  -ms-overflow-style: none;         /* legacy Edge */
}
.elementor-widget-loop-carousel .swiper::-webkit-scrollbar { display: none; }

/* Selector shape is copied from widget-loop-carousel.css deliberately: its
 * `.swiper:not(.swiper-initialized) > .swiper-wrapper` rule sets
 * `overflow: hidden` plus its own gap, and outranks any two-class selector.
 * That overflow is what broke arrow and touch scrolling — the wrapper is
 * 100% of .swiper, so it clipped every slide past the first view and left
 * .swiper with no overflow to scroll. */
.elementor-widget-loop-carousel .swiper-wrapper,
.elementor-widget-loop-carousel .swiper:not(.swiper-initialized) > .swiper-wrapper {
  flex-direction: row;
  gap: var(--hl-slide-gap, 10px);
  overflow: visible;
}

/* Slides-per-view comes from each widget's OWN settings, injected as
 * --hl-slides / --hl-slides-tablet / --hl-slides-mobile by annotateCarousels()
 * in scripts/build-content.mjs, which reproduces Elementor's algorithm from
 * frontend-modules.js (default 3 desktop, 2 tablet, 1 mobile).
 *
 * This must not be a single hardcoded number: the hub has three carousels
 * declaring 4/2/1 and a featured one declaring nothing, which Elementor renders
 * at 3/2/1. Forcing 4 on the featured card collapsed its two-column layout into
 * a ~90px column of one-word-per-line text.
 *
 * N slides means N-1 gaps to subtract. */
.elementor-widget-loop-carousel .swiper-slide {
  scroll-snap-align: start;
  height: auto;                     /* swiper.css sets 100%, which collapses */
  width: calc(
    (100% - (var(--hl-slides, 3) - 1) * var(--hl-slide-gap, 10px)) / var(--hl-slides, 3)
  );
}

@media (max-width: 1024px) {
  .elementor-widget-loop-carousel .swiper-slide {
    width: calc(
      (100% - (var(--hl-slides-tablet, 2) - 1) * var(--hl-slide-gap, 10px)) / var(--hl-slides-tablet, 2)
    );
  }
}

@media (max-width: 767px) {
  .elementor-widget-loop-carousel .swiper-slide {
    width: calc(
      (100% - (var(--hl-slides-mobile, 1) - 1) * var(--hl-slide-gap, 10px)) / var(--hl-slides-mobile, 1)
    );
  }
}

/* Arrows keep Elementor's own styling and positioning; static/js/carousel.js
 * gives them their click behaviour back by scrolling the row above.
 * Pagination bullets stay hidden — they need per-slide state to be meaningful,
 * and nothing here tracks it. */
.elementor-widget-loop-carousel .swiper-pagination { display: none; }

/* ---------------------------------------------------------------------------
 * 3b. Nested tabs  (/blog/hosts/, /blog/careers/)
 *
 * Elementor's widget flips aria-selected on <button> titles and moves .e-active
 * between panels from JS. build-content.mjs rewrites that markup into radios +
 * <label> titles (see nestedTabsToRadios), and :checked does the switching:
 *
 *   .e-n-tabs > input.hl-tab-input.hl-tab-N   one per tab, first one checked
 *   label.e-n-tab-title[data-tab-index="N"]   the title
 *   .e-n-tabs-content > .e-con[data-tab-index="N"]  the panel
 *
 * widget-nested-tabs.css already hides every panel without .e-active, so only
 * the reveal and the active-title styling are needed here. The active
 * declarations are the ones that stylesheet applies at [aria-selected=true]:
 * background-color-active and title-color-active.
 * ------------------------------------------------------------------------- */
.e-n-tabs > .hl-tab-input {
  position: absolute;
  width: 0;
  height: 0;
  opacity: 0;
  pointer-events: none;
}

label.e-n-tab-title { cursor: pointer; }

/* An inactive title. The per-page stylesheets paint this themselves, but their
 * rule keys off [aria-selected=false] which a <label> cannot honestly carry —
 * both pages that use the widget (post-9114, post-33868) set the same
 * --e-global-color-text, so it is restated once here. */
.elementor-widget-n-tabs label.e-n-tab-title {
  background-color: var(--e-global-color-text, var(--n-tabs-title-background-color));
  color: var(--n-tabs-title-color);
}

/* Six is more tabs than any page here has (three is the most: /blog/careers/),
 * and CSS cannot express "the nth radio matches the nth label" generically. */
.hl-tab-1:checked ~ .e-n-tabs-heading > label[data-tab-index="1"],
.hl-tab-2:checked ~ .e-n-tabs-heading > label[data-tab-index="2"],
.hl-tab-3:checked ~ .e-n-tabs-heading > label[data-tab-index="3"],
.hl-tab-4:checked ~ .e-n-tabs-heading > label[data-tab-index="4"],
.hl-tab-5:checked ~ .e-n-tabs-heading > label[data-tab-index="5"],
.hl-tab-6:checked ~ .e-n-tabs-heading > label[data-tab-index="6"] {
  background-color: var(--n-tabs-title-background-color-active);
  color: var(--n-tabs-title-color-active);
}

.hl-tab-1:checked ~ .e-n-tabs-content > [data-tab-index="1"],
.hl-tab-2:checked ~ .e-n-tabs-content > [data-tab-index="2"],
.hl-tab-3:checked ~ .e-n-tabs-content > [data-tab-index="3"],
.hl-tab-4:checked ~ .e-n-tabs-content > [data-tab-index="4"],
.hl-tab-5:checked ~ .e-n-tabs-content > [data-tab-index="5"],
.hl-tab-6:checked ~ .e-n-tabs-content > [data-tab-index="6"] {
  display: var(--display, flex);
}

/* Keyboard focus lands on the radio, which is invisible — put the ring on its
 * own label the way a real tab would show it. Arrow keys move between radios in
 * the group, which is the same interaction the widget's JS implemented. */
.hl-tab-1:focus-visible ~ .e-n-tabs-heading > label[data-tab-index="1"],
.hl-tab-2:focus-visible ~ .e-n-tabs-heading > label[data-tab-index="2"],
.hl-tab-3:focus-visible ~ .e-n-tabs-heading > label[data-tab-index="3"],
.hl-tab-4:focus-visible ~ .e-n-tabs-heading > label[data-tab-index="4"],
.hl-tab-5:focus-visible ~ .e-n-tabs-heading > label[data-tab-index="5"],
.hl-tab-6:focus-visible ~ .e-n-tabs-heading > label[data-tab-index="6"] {
  outline: 2px solid var(--n-tabs-title-color-active, currentColor);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
 * 3c. Featured images in generated markup
 *
 * The source markup carried width/height attributes on every featured image,
 * and that width attribute is a presentational hint — a real `width: 987px` that
 * max-width: 100% then clamps to the container. The card CSS pins the height
 * (250px desktop, 199px mobile) and leaves width auto, so WITHOUT the
 * attribute the used width comes from the aspect ratio instead: 332px inside a
 * 387px card on a phone, which is the gap that showed up in search results and
 * on every archive card.
 *
 * These <img> tags are generated and have no dimensions to put on them (the
 * media is served from object storage, not processed at build time), so state
 * the effective result instead. Same width the attribute produced, one rule.
 * ------------------------------------------------------------------------- */
.elementor-widget-theme-post-featured-image img { width: 100%; }

/* ---------------------------------------------------------------------------
 * 4. Video overlay  (1 page: /blog/travel-nurse-housing/)
 *
 * Elementor renders a poster image over the iframe and its JS swaps it out on
 * click. With no JS the overlay would permanently block the player, so drop it
 * and let the iframe show its own poster and controls.
 * ------------------------------------------------------------------------- */
.elementor-custom-embed-image-overlay { display: none; }

/* ---------------------------------------------------------------------------
 * 5. Table of contents
 *
 * Elementor's JS builds the list client-side into an empty .elementor-toc__body.
 * We now render it at build time in layouts/_default/single.html using the same
 * class names, so the widget's existing CSS applies unchanged. Two leftovers to
 * neutralise: the loading spinner, and the collapse toggle (JS-driven).
 * ------------------------------------------------------------------------- */
.elementor-toc__spinner-container { display: none; }
.elementor-toc__header .elementor-toc__toggle-button { display: none; }
.elementor-toc__body { max-height: none; }

/* ---------------------------------------------------------------------------
 * 6. Footer column count
 *
 * The footer link groups are aligned to the marketing home page, which has four
 * of them where this shell was built for three. The compiled stylesheet
 * declares the track list per breakpoint and cannot be edited — it is mirrored
 * from the origin and an edit is reverted on the next pull — so the extra track
 * is added here.
 *
 * Only the track list changes. Everything else about the grid — gaps, padding,
 * background, the 3fr brand column — stays as the compiled stylesheet sets it.
 *
 *   desktop   3fr + 4 equal columns (was 3fr + 3)
 *   tablet    4 across, one row, so the groups stay side by side
 *   mobile    2 across, unchanged in shape; the extra group adds a third row
 * ------------------------------------------------------------------------- */
.elementor-33022 .elementor-element.elementor-element-ae6b41e {
  --e-con-grid-template-columns: 3fr 1fr 1fr 1fr 1fr;
}

@media (max-width: 1024px) {
  .elementor-33022 .elementor-element.elementor-element-ae6b41e {
    --e-con-grid-template-columns: repeat(4, 1fr);
    --e-con-grid-template-rows: auto;
    --grid-auto-flow: row;
  }

  /* Brand block on a row of its own. Without this it takes three of the four
   * tracks and leaves the first link group marooned beside it, with the other
   * three wrapping to the next row. */
  .elementor-33022 .elementor-element.elementor-element-c3e1f5e {
    grid-column: 1 / -1;
  }
}

@media (max-width: 767px) {
  .elementor-33022 .elementor-element.elementor-element-ae6b41e {
    --e-con-grid-template-columns: repeat(2, 1fr);
    --e-con-grid-template-rows: auto;
  }
}
