/* ==========================================================================
   Hammam Sables d’Or — Elementor glue

   The static build hooked behaviour with data attributes. Elementor free
   cannot add arbitrary attributes to a widget, but Advanced → CSS Classes
   accepts any class name. This file makes the class forms behave exactly
   like the attribute forms, and stops Elementor's own defaults from winning
   against the design system.

   Loaded last, so it may raise specificity where it genuinely has to.
   Everything still resolves back to the tokens in style.css.
   ========================================================================== */

/* ---- Reveal, addressed by class -----------------------------------------
   Mirrors `.js [data-reveal]` in components.css. Gated behind .js so that
   content is never left invisible when scripting fails.
   -------------------------------------------------------------------------- */

.js .ht-reveal {
  opacity: 0;
  transform: translateY(1.5rem);
  transition: opacity var(--ht-dur) var(--ht-ease),
    transform var(--ht-dur) var(--ht-ease);
  transition-delay: var(--d, 0ms);
}

.js .ht-reveal.is-in {
  opacity: 1;
  transform: translateY(0);
}

/* ---- Hold the ground colour --------------------------------------------
   Hello Elementor ships a white body, and the Elementor Kit can set its own
   background and text colour. Losing the near-black ground would undo the
   entire art direction, so it is asserted here rather than left to the Kit.
   -------------------------------------------------------------------------- */

body,
body.elementor-page {
  background-color: var(--ht-ground);
  color: var(--ht-steam);
}

.elementor-section,
.elementor-container,
.e-con,
.e-con-inner {
  color: inherit;
}

/* Elementor headings inherit the display face rather than the Kit default. */
.elementor-widget-heading .elementor-heading-title {
  font-family: var(--ht-font-display);
  font-weight: 400;
  letter-spacing: var(--ht-track-display);
  color: var(--ht-steam);
}

.elementor-widget-text-editor,
.elementor-widget-text-editor p {
  color: var(--ht-muted);
}

/* ---- Buttons -------------------------------------------------------------
   Elementor's Advanced → CSS Classes field applies to the widget WRAPPER, not
   to the <a class="elementor-button"> inside it. So the wrapper-scoped rules
   below are the ones that actually fire; the .elementor-button.ht-btn form
   further down stays only for markup the theme renders itself.
   -------------------------------------------------------------------------- */

.ht-btn .elementor-button {
  border-radius: var(--ht-radius);
  font-family: var(--ht-font-body);
  font-size: var(--ht-t-sm);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0.95rem 1.9rem;
  line-height: 1;
  transition: background var(--ht-dur-fast) var(--ht-ease),
    color var(--ht-dur-fast) var(--ht-ease),
    border-color var(--ht-dur-fast) var(--ht-ease);
}

.ht-btn--small .elementor-button {
  padding: 0.7rem 1.35rem;
  font-size: var(--ht-t-xs);
}

.ht-btn--primary .elementor-button {
  background-color: var(--ht-brass);
  border: 1px solid var(--ht-brass);
  color: var(--ht-ground-deep);
}

.ht-btn--primary .elementor-button:hover,
.ht-btn--primary .elementor-button:focus {
  background-color: var(--ht-brass-lift);
  border-color: var(--ht-brass-lift);
  color: var(--ht-ground-deep);
}

.ht-btn--ghost .elementor-button {
  background-color: transparent;
  border: 1px solid var(--ht-line-brass);
  color: var(--ht-steam);
}

.ht-btn--ghost .elementor-button:hover,
.ht-btn--ghost .elementor-button:focus {
  border-color: var(--ht-brass);
  color: var(--ht-brass);
}

.elementor-button.ht-btn,
.elementor-button-wrapper .elementor-button.ht-btn {
  border-radius: var(--ht-radius);
  font-family: var(--ht-font-body);
  font-size: var(--ht-t-sm);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0.95rem 1.9rem;
  line-height: 1;
}

.elementor-button.ht-btn--primary {
  background-color: var(--ht-brass);
  border: 1px solid var(--ht-brass);
  color: var(--ht-ground-deep);
}

.elementor-button.ht-btn--primary:hover,
.elementor-button.ht-btn--primary:focus {
  background-color: var(--ht-brass-lift);
  border-color: var(--ht-brass-lift);
  color: var(--ht-ground-deep);
}

.elementor-button.ht-btn--ghost {
  background-color: transparent;
  border: 1px solid var(--ht-line-brass);
  color: var(--ht-steam);
}

.elementor-button.ht-btn--ghost:hover,
.elementor-button.ht-btn--ghost:focus {
  border-color: var(--ht-brass);
  color: var(--ht-brass);
}

/* ---- Images --------------------------------------------------------------
   .ht-photo on an image widget: the widget element becomes the frame, the
   nested <img> is graded, and ::after lays the vignette over it. Elementor
   wraps images in .elementor-widget-container, which must not clip.
   -------------------------------------------------------------------------- */

.ht-photo .elementor-widget-container,
.ht-photo figure,
.ht-photo .elementor-image {
  height: 100%;
  margin: 0;
  overflow: hidden;
}

.ht-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--pos, 50% 50%);
  filter: var(--ht-photo-filter);
}

/* Elementor rounds image corners by default in some kits. */
.ht-photo img,
.ht-photo .elementor-image img {
  border-radius: 0;
}

/* ---- Focus --------------------------------------------------------------
   Elementor removes outlines on several widgets. The brass ring is the only
   thing making the site keyboard-navigable on a near-black ground.
   -------------------------------------------------------------------------- */

.elementor a:focus-visible,
.elementor button:focus-visible,
.elementor .elementor-button:focus-visible {
  outline: 2px solid var(--ht-brass);
  outline-offset: 3px;
}

/* ---- Editor safety -------------------------------------------------------
   Inside the Elementor editor, elements waiting to be revealed would appear
   blank and look broken to whoever is editing. Show everything.
   -------------------------------------------------------------------------- */

.elementor-editor-active .js .ht-reveal,
.elementor-editor-active .ht-steam__w,
body.elementor-editor-active [data-reveal] {
  opacity: 1 !important;
  filter: none !important;
  transform: none !important;
}

/* ---- Reduced motion ------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  .js .ht-reveal {
    opacity: 1;
    transform: none;
  }
}

/* ==========================================================================
   Theme Builder — header and footer

   Written against the markup Elementor actually emits, not against what the
   static build used. Two differences drive everything here:

     · Advanced → CSS Classes lands on the widget WRAPPER, never on the inner
       <a>/<nav> that needs the styling.
     · The Nav Menu widget renders the menu twice — once as .--main for wide
       screens and once as .--dropdown behind .elementor-menu-toggle.

   Cancelling either would mean fighting the widget, so both are styled.
   ========================================================================== */

/* ---- The fixed bar ------------------------------------------------------- */

.elementor-location-header {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: var(--ht-z-header);
  background: transparent;
  border-block-end: 1px solid transparent;
  transition: background var(--ht-dur-fast) var(--ht-ease),
    border-color var(--ht-dur-fast) var(--ht-ease);
}

.elementor-location-header.is-scrolled {
  background: rgb(11 10 8 / 0.86);
  backdrop-filter: blur(14px) saturate(1.1);
  -webkit-backdrop-filter: blur(14px) saturate(1.1);
  border-block-end-color: var(--ht-line);
}

.ht-header__inner {
  min-height: var(--ht-header-h);
  padding-block: 0;
}

/* No global header-clearance rule lives here, deliberately.

   A rule targeting .site-main used to. It never applied: Hello Elementor's
   elementor_header_footer template — which every page uses — renders no
   .site-main element at all. Worse, .ht-hero-band then carried a negative
   margin to "cancel" that phantom padding, which dragged every hero page 76px
   up and put the eyebrow under the header at narrow widths.

   Each opening band clears the bar itself: heroes through
   .ht-*-hero > .e-con-inner padding, other bands through .ht-band-pad. This
   matches the static build, where <main> has no top padding either and the
   hero deliberately starts at y=0 so the photo runs under the bar. */

/* ---- Gutter -------------------------------------------------------------
   Elementor's containers default to a flat 10px inline padding. On desktop
   that is invisible, because the inner wrapper is capped at --content-width
   and centred, so the gutter never shows. Below that cap the padding IS the
   gutter — and 10px against a 400px screen reads as an error.

   The static build uses --ht-gutter: clamp(1.25rem, 5vw, 4rem) — 20px at
   400px, 64px at desktop. Feed the token into Elementor's own padding
   variables so every band inherits it and the two builds track each other at
   every width, rather than only where the cap happens to hide the difference.
   -------------------------------------------------------------------------- */

.e-con.e-parent {
  --padding-inline-start: var(--ht-gutter);
  --padding-inline-end: var(--ht-gutter);
}

/* Child containers take none of it. Elementor pads every container by 10px on
   all four sides; on a parent band that is the gutter, but on a child it is
   noise. Every static equivalent — .ht-hero__actions, .ht-shead, .ht-band,
   .ht-spaces, .ht-space, .ht-cta__actions, .ht-footer__col — is a plain
   flex/grid wrapper with gap and no padding whatsoever.

   Left in place it insets each widget 10px from its own container: buttons
   land 20px narrower than the measure they should fill, and section headings
   sit 10px off the grid the band below them uses. It also adds 20px of height
   per nested container, which is most of the residual height difference
   against the static build.

   Containers that genuinely need padding set it per-element in Elementor, and
   that rule is more specific, so it still wins — the footer grid's 64px
   bottom and the footer bar's 32px top both depend on that and are unaffected. */
.e-con.e-child {
  --padding-block-start: 0px;
  --padding-block-end: 0px;
  --padding-inline-start: 0px;
  --padding-inline-end: 0px;
}

/* The header sets its own padding per-element, which is more specific and
   still wins — correctly, since its inner wrapper is centred on the same
   content width and lands at the same x as the bands below it. */

/* ---- Header actions at narrow widths ------------------------------------
   860px, matching layout.css: below it the static header keeps only the
   wordmark and the burger. Leaving the reservation button in place crowds the
   bar into three competing elements — which is what the deployed build did.
   The CTA is not lost: it is the first item inside the open menu.

   The selector is deliberately .elementor-widget-button.ht-btn, not just
   .ht-btn: that exact rule sets display:block further down this file. Equal
   specificity, later source order, so the plainer selector loses silently. */

@media (max-width: 860px) {
  .elementor-location-header .elementor-widget-button.ht-btn {
    display: none;
  }
}

/* ---- Stacked action rows -------------------------------------------------
   At <=640px the static build stretches the buttons so the stack has one
   clean edge — "ragged button widths read as sloppy once they stack", per
   pages.css. It does that with .ht-btn { flex: 1 1 100% }, where .ht-btn is
   the <a> itself.

   In Elementor .ht-btn is the widget wrapper and the <a> inside is an
   inline-block sized to its label. Stretching the wrapper alone therefore
   changes nothing visible: the wrappers reach 345px while the buttons stay at
   256px and 247px, which is exactly the ragged stack this rule exists to
   prevent. The width has to go on the anchor.

   Same 640px breakpoint as the static build, same three rows.
   -------------------------------------------------------------------------- */

@media (max-width: 640px) {
  .ht-hero__actions .ht-btn .elementor-button,
  .ht-contact__actions .ht-btn .elementor-button,
  .ht-cta__actions .ht-btn .elementor-button {
    width: 100%;
  }
}

/* ---- Wordmark ------------------------------------------------------------ */

.ht-brand .elementor-heading-title,
.ht-brand .elementor-heading-title a {
  font-family: var(--ht-font-display);
  font-size: 1.02rem;
  font-weight: 400;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ht-steam);
  text-decoration: none;
  white-space: nowrap;
  line-height: 1;
}

.ht-brand .elementor-heading-title a:hover {
  color: var(--ht-brass);
}

/* ---- Navigation ---------------------------------------------------------- */

.ht-nav .elementor-nav-menu--main .elementor-item {
  font-family: var(--ht-font-body);
  font-size: var(--ht-t-sm);
  font-weight: 400;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ht-steam);
  fill: var(--ht-steam);
  padding: 0.4rem 0;
  position: relative;
}

/* Elementor lays the <ul> out with flex, so spacing must be a gap on the list
   — margin on the <a> collapses and the items run together. */
.ht-nav .elementor-nav-menu--main ul.elementor-nav-menu {
  gap: clamp(1.25rem, 2.4vw, 2.5rem);
}

/* Elementor draws its own underline/overline states; replace them with the
   brass rule that grows from the left, as on the static site. */
.ht-nav .elementor-nav-menu--main .elementor-item::after,
.ht-nav .elementor-nav-menu--main .elementor-item::before {
  content: "";
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: 0;
  width: 100%;
  height: 1px;
  background: var(--ht-brass);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--ht-dur-fast) var(--ht-ease);
  opacity: 1;
  border: 0;
}

.ht-nav .elementor-nav-menu--main .elementor-item::before {
  display: none;
}

.ht-nav .elementor-nav-menu--main .elementor-item:hover::after,
.ht-nav .elementor-nav-menu--main .elementor-item:focus::after,
.ht-nav .elementor-nav-menu--main .elementor-item.elementor-item-active::after {
  transform: scaleX(1);
}

.ht-nav .elementor-nav-menu--main .elementor-item:hover,
.ht-nav .elementor-nav-menu--main .elementor-item.elementor-item-active {
  color: var(--ht-brass);
}

/* ---- Mobile toggle and dropdown ------------------------------------------ */

.elementor-menu-toggle {
  color: var(--ht-steam);
  background: transparent;
  border: 0;
}

.elementor-menu-toggle:hover {
  color: var(--ht-brass);
  background: transparent;
}

.elementor-nav-menu--dropdown {
  background-color: var(--ht-ground-deep);
  border-block-start: 1px solid var(--ht-line-brass);
}

.elementor-nav-menu--dropdown .elementor-item {
  font-family: var(--ht-font-display);
  font-size: var(--ht-t-md);
  letter-spacing: 0.04em;
  color: var(--ht-steam);
  border-block-end: 1px solid var(--ht-line);
}

.elementor-nav-menu--dropdown .elementor-item:hover,
.elementor-nav-menu--dropdown .elementor-item.elementor-item-active {
  background-color: var(--ht-surface);
  color: var(--ht-brass);
}

/* ---- Footer -------------------------------------------------------------- */

.elementor-location-footer {
  background: var(--ht-ground-deep);
  border-block-start: 1px solid var(--ht-line-brass);
  color: var(--ht-muted);
  font-size: var(--ht-t-sm);
}

.ht-footer__wrap {
  padding-block: var(--ht-s-7) var(--ht-s-4);
}

.ht-footer__grid {
  gap: var(--ht-s-6) var(--ht-s-5);
  padding-block-end: var(--ht-s-6);
}

.ht-footer__col {
  flex: 1 1 12rem;
  min-width: 11rem;
}

.ht-footer__col--brand {
  flex: 1.6 1 18rem;
}

.ht-footer__title p {
  font-size: var(--ht-t-xs);
  font-weight: 500;
  letter-spacing: var(--ht-track-eyebrow);
  text-transform: uppercase;
  color: var(--ht-brass);
  margin-block-end: var(--ht-s-1);
}

.ht-footer__brand .ht-brand {
  font-family: var(--ht-font-display);
  font-size: 1.02rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ht-steam);
}

.ht-footer__brand .ht-brand__mark {
  color: var(--ht-brass);
}

.elementor-location-footer a {
  color: var(--ht-muted);
  text-decoration: none;
}

.elementor-location-footer a:hover {
  color: var(--ht-brass);
}

/* Footer menus are lists, not a nav bar — strip the widget's inline layout. */
.ht-footer__nav .elementor-nav-menu .elementor-item,
.ht-footer__legal .elementor-nav-menu .elementor-item {
  padding: 0.18rem 0;
  font-size: var(--ht-t-sm);
  color: var(--ht-muted);
  text-transform: none;
  letter-spacing: 0;
}

.ht-footer__nav .elementor-nav-menu .elementor-item:hover,
.ht-footer__legal .elementor-nav-menu .elementor-item:hover {
  color: var(--ht-brass);
  background: transparent;
}

.ht-footer__legal .elementor-nav-menu {
  gap: var(--ht-s-3);
}

.ht-footer__bottom {
  padding-block-start: var(--ht-s-4);
  border-block-start: 1px solid var(--ht-line);
  font-size: var(--ht-t-xs);
  gap: var(--ht-s-2) var(--ht-s-4);
}

.ht-footer__bottom p {
  margin: 0;
}

/* ---- Fixes found by rendering -------------------------------------------
   Elementor sizes every container from a --width custom property, so a plain
   `flex` shorthand on .ht-footer__col never wins. Overriding --width is what
   actually turns the footer into a row.
   -------------------------------------------------------------------------- */

.ht-footer__grid.e-con > .e-con {
  --width: auto;
  flex: 1 1 12rem;
  min-width: 11rem;
}

.ht-footer__grid.e-con > .ht-footer__col--brand.e-con {
  flex: 1.6 1 18rem;
}

.ht-footer__bottom.e-con > .e-con,
.ht-footer__bottom.e-con > .elementor-widget {
  --width: auto;
}

/* The footer menus are plain lists; cancel the horizontal flex the widget
   applies so "Visiter" stacks. */
.ht-footer__nav .elementor-nav-menu {
  display: block;
}

.ht-footer__legal .elementor-nav-menu {
  display: flex;
  gap: var(--ht-s-3);
}

/* ---- Header at phone widths ---------------------------------------------
   Brand, burger and button share one row. At 390px the tracked wordmark runs
   into the burger, so it tightens rather than the row wrapping.
   -------------------------------------------------------------------------- */

@media (max-width: 767px) {
  .ht-header__inner {
    gap: var(--ht-s-2);
  }

  .ht-brand .elementor-heading-title,
  .ht-brand .elementor-heading-title a {
    font-size: 0.8rem;
    letter-spacing: 0.16em;
  }

  .ht-btn--small .elementor-button {
    padding: 0.6rem 1rem;
  }
}

/* ==========================================================================
   Home page bands

   The static build styled semantic sections. Elementor emits .e-con
   containers sized from a --width custom property, so every multi-column row
   here has to override --width as well as set flex — setting flex alone loses.
   ========================================================================== */

.ht-band-pad {
  padding-block: var(--ht-section);
}

.ht-band-tight {
  padding-block: calc(var(--ht-section) * 0.58);
}

.ht-band-surface {
  background-color: var(--ht-surface);
}

/* ---- Hero ----------------------------------------------------------------
   .ht-hero-band carries no offset. It is kept as a marker class only.

   It previously pulled the band up by --ht-header-h to cancel .site-main's top
   padding — padding that does not exist under this template (see above). The
   pull-up was therefore unopposed: the band sat at -76px, and at 400px wide
   the eyebrow landed at y=24 beneath a 77px header. Desktop hid it, because
   the home hero is 100svh with its content bottom-aligned.

   Correct behaviour, matching the static build: band top = 0, content held
   clear by .ht-*-hero > .e-con-inner padding-block-start.
   -------------------------------------------------------------------------- */

.ht-home-hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-height: 100svh;
}

/* One layer does both jobs: backdrop-filter grades the container's own
   background image (CSS cannot filter a background directly), and the
   gradients are the legibility scrims from the static hero. */
.ht-home-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  backdrop-filter: saturate(0.34) contrast(1.1) brightness(0.68) sepia(0.26);
  -webkit-backdrop-filter: saturate(0.34) contrast(1.1) brightness(0.68) sepia(0.26);
  background: linear-gradient(
      180deg,
      rgb(11 10 8 / 0.6) 0%,
      rgb(11 10 8 / 0.12) 36%,
      rgb(11 10 8 / 0.66) 86%,
      rgb(18 16 14 / 0.94) 100%
    ),
    linear-gradient(90deg, rgb(11 10 8 / 0.6) 0%, rgb(11 10 8 / 0) 58%);
}

.ht-home-hero > .e-con-inner {
  position: relative;
  z-index: 1;
  padding-block: calc(var(--ht-header-h) + var(--ht-s-3)) clamp(3.5rem, 10vh, 8rem);
  align-items: flex-start;
  gap: var(--ht-s-3);
}

.ht-hero__title .elementor-heading-title {
  font-size: var(--ht-t-3xl);
  line-height: 1.02;
  max-width: 15ch;
}

.ht-hero__lead p {
  font-size: var(--ht-t-md);
  color: var(--ht-steam);
  max-width: 44ch;
  line-height: 1.6;
}

.ht-hero__actions.e-con,
.ht-cta__actions.e-con {
  --width: auto;
  gap: var(--ht-s-2);
}

/* ---- Le seuil ------------------------------------------------------------ */

.ht-seuil-band .ht-seuil__line .elementor-heading-title {
  font-family: var(--ht-font-quote);
  font-style: italic;
  font-weight: 300;
  font-size: var(--ht-t-xl);
  line-height: 1.34;
  max-width: 24ch;
  margin-inline: auto;
  text-align: center;
}

.ht-seuil__rule {
  width: 1px;
  height: 4rem;
  margin-inline: auto;
  background: linear-gradient(180deg, var(--ht-brass), transparent);
  border: 0;
}

/* ---- Alternating editorial band ------------------------------------------ */

.ht-band.e-con {
  gap: clamp(2rem, 6vw, 5.5rem);
  align-items: center;
}

.ht-band.e-con > .e-con {
  --width: auto;
  flex: 1 1 20rem;
}

/* ---- Space cards ---------------------------------------------------------
   Deliberately unequal offsets: three identical boxes is what makes a card
   row read as templated.
   -------------------------------------------------------------------------- */

.ht-spaces.e-con {
  gap: var(--ht-s-5);
  align-items: flex-start;
}

.ht-spaces.e-con > .e-con {
  --width: auto;
  flex: 1 1 14rem;
  gap: var(--ht-s-3);
}

@media (min-width: 901px) {
  .ht-spaces.e-con > .e-con:nth-child(2) {
    margin-block-start: var(--ht-s-7);
  }
  .ht-spaces.e-con > .e-con:nth-child(3) {
    margin-block-start: var(--ht-s-3);
  }
}

.ht-space__photo.ht-photo--portrait {
  aspect-ratio: 2 / 3;
  width: 100%;
}

.ht-space__name {
  display: block;
  font-family: var(--ht-font-display);
  font-size: var(--ht-t-lg);
  color: var(--ht-steam);
  margin-block-end: var(--ht-s-1);
}

.ht-space__text {
  display: block;
  font-size: var(--ht-t-sm);
  color: var(--ht-muted);
}

/* ---- Section headers and links ------------------------------------------- */

.ht-shead.e-con {
  --width: auto;
  max-width: var(--ht-measure);
  gap: var(--ht-s-3);
  margin-block-end: var(--ht-s-6);
}

.ht-link {
  margin-block-start: var(--ht-s-5);
}

/* ---- Booking band --------------------------------------------------------- */

.ht-cta-band {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  text-align: center;
}

.ht-cta-band::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  backdrop-filter: saturate(0.3) contrast(1.06) brightness(0.56) sepia(0.26);
  -webkit-backdrop-filter: saturate(0.3) contrast(1.06) brightness(0.56) sepia(0.26);
  background: linear-gradient(
    180deg,
    rgb(11 10 8 / 0.74) 0%,
    rgb(11 10 8 / 0.5) 50%,
    rgb(11 10 8 / 0.8) 100%
  );
}

.ht-cta-band > .e-con-inner {
  position: relative;
  z-index: 1;
  padding-block: var(--ht-section);
  align-items: center;
  gap: var(--ht-s-3);
}

.ht-cta-band .ht-lead p {
  text-align: center;
  margin-inline: auto;
}

/* ---- Testimonial ---------------------------------------------------------- */

.ht-testimonial__quote .elementor-heading-title {
  font-family: var(--ht-font-quote);
  font-style: italic;
  font-weight: 300;
  font-size: var(--ht-t-xl);
  line-height: 1.34;
  max-width: 26ch;
  margin-inline: auto;
  text-align: center;
}

.ht-testimonial__who {
  text-align: center;
  font-size: var(--ht-t-xs);
  letter-spacing: var(--ht-track-eyebrow);
  text-transform: uppercase;
  color: var(--ht-muted);
}

@media (max-width: 900px) {
  .ht-band.e-con > .e-con {
    flex: 1 1 100%;
  }
}

/* ---- Button wrapper reset ------------------------------------------------
   components.css styles ANY element carrying .ht-btn — written for the static
   build, where the class sat on the <a> itself. In Elementor the class lands
   on the widget wrapper, so the wrapper picked up the padding, border and
   background as well as the inner <a>, rendering every button twice over.
   The wrapper is only a positioning box here; the button is the button.
   -------------------------------------------------------------------------- */

.elementor-widget-button.ht-btn {
  display: block;
  padding: 0;
  border: 0;
  background: none;
  line-height: inherit;
  letter-spacing: normal;
  text-transform: none;
  width: auto;
}

/* ---- Mobile menu icon ----------------------------------------------------
   With the e_font_icon_svg feature on, Elementor renders the burger as an
   inline <svg> carrying its own fill (#33373d). `color` does not reach it, so
   on the near-black header the toggle was invisible and the mobile menu was
   unreachable. Fill has to be set explicitly.
   -------------------------------------------------------------------------- */

.elementor-menu-toggle svg,
.elementor-menu-toggle .e-font-icon-svg {
  fill: var(--ht-steam);
  width: 24px;
  height: 24px;
}

.elementor-menu-toggle:hover svg,
.elementor-menu-toggle:focus-visible svg,
.elementor-menu-toggle[aria-expanded="true"] svg {
  fill: var(--ht-brass);
}

/* ---- Mobile dropdown panel ----------------------------------------------
   Elementor anchors the dropdown to the toggle widget, which is ~35px wide,
   so every label wrapped onto two lines. Pin it to the viewport under the
   header instead, matching the full-width drawer the static build used.

   860px, not 767: the burger shows for the whole range below the tablet
   breakpoint (now also 860, set on the kit to match layout.css). A pin that
   stopped at 767 left 768-860 rendering as a 199px panel floating under the
   toggle — styled nowhere, and unlike either build.

   No width declaration, deliberately. position:fixed with inset-inline:0
   already sizes the panel to the client area. The width:100vw that used to be
   here overrode that with a value which INCLUDES the scrollbar, pushing the
   panel 15px off-screen wherever a classic scrollbar is shown.
   -------------------------------------------------------------------------- */

@media (max-width: 860px) {
  .ht-nav .elementor-nav-menu--dropdown {
    position: fixed;
    inset-inline: 0;
    inset-block-start: var(--ht-header-h);
    max-height: calc(100svh - var(--ht-header-h));
    overflow-y: auto;
    padding-block: var(--ht-s-2);
  }

  .ht-nav .elementor-nav-menu--dropdown .elementor-item {
    padding-inline: var(--ht-gutter);
    padding-block: var(--ht-s-3);
    white-space: nowrap;
  }
}

/* ==========================================================================
   Inner-page hero + narrow bands
   ========================================================================== */

.ht-page-hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}

/* Same one-layer trick as the home hero: backdrop-filter grades the
   container's background image, the gradient does legibility.

   Unlike the home hero this takes ONE scrim, not two. The home headline sits
   lower-left over a bright tile joint and needs the horizontal wash; the inner
   pages set their title against the vertical fall-off alone. Adding the
   horizontal layer here darkened the band by ~20% against the static build —
   values below are copied verbatim from .ht-phero__media::after. */
.ht-page-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  backdrop-filter: saturate(0.34) contrast(1.08) brightness(0.66) sepia(0.26);
  -webkit-backdrop-filter: saturate(0.34) contrast(1.08) brightness(0.66) sepia(0.26);
  background: linear-gradient(
    180deg,
    rgb(11 10 8 / 0.58) 0%,
    rgb(11 10 8 / 0.16) 42%,
    rgb(18 16 14 / 0.95) 100%
  );
}

.ht-page-hero > .e-con-inner {
  position: relative;
  z-index: 1;
  padding-block: calc(var(--ht-header-h) + var(--ht-s-3)) clamp(2.5rem, 7vh, 4.5rem);
  align-items: flex-start;
  gap: var(--ht-s-2);
}

.ht-phero__title .elementor-heading-title {
  font-size: var(--ht-t-2xl);
  max-width: 18ch;
}

.ht-phero__lead p {
  color: var(--ht-steam);
  font-size: var(--ht-t-md);
  max-width: 52ch;
}

/* ---- Narrow reading band -------------------------------------------------
   Elementor sizes a boxed container from --content-width, so max-width on the
   container itself is ignored; the inner wrapper is what has to be capped.

   732px, NOT the 860px written on .ht-wrap--narrow. That 860 is a border-box
   outer width carrying padding-inline: 4rem, so the static text measure is
   860 - 128 = 732. Elementor's inner wrapper has no padding, so its max-width
   IS the measure — copying 860 across widened every inner-page reading band by
   128px and shifted its left edge 64px out.
   -------------------------------------------------------------------------- */

.ht-band-narrow > .e-con-inner {
  max-width: 732px;
  margin-inline: auto;
}

/* Two stacked paragraphs in one text-editor need rhythm between them. */
.ht-lead p + p {
  margin-block-start: var(--ht-s-2);
}

/* ==========================================================================
   Les espaces — alternating rooms + full-bleed frames
   ========================================================================== */

.ht-band--reverse.e-con {
  flex-direction: row-reverse;
}

/* Four rooms in a row, each with a full section's padding, would read as four
   isolated pages. Collapsing the gap between consecutive bands makes them a
   single traversal — which is what the copy claims the building is. */
.ht-band-flush + .ht-band-flush {
  padding-block-start: 0;
}

/* ---- Full-bleed frame ----------------------------------------------------- */

.ht-bleed-band {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}

.ht-bleed-band::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  backdrop-filter: saturate(0.4) contrast(1.09) brightness(0.84) sepia(0.24);
  -webkit-backdrop-filter: saturate(0.4) contrast(1.09) brightness(0.84) sepia(0.24);
  background: radial-gradient(
      ellipse 130% 100% at 50% 45%,
      transparent 40%,
      rgb(11 10 8 / 0.4) 86%,
      rgb(11 10 8 / 0.72) 100%
    ),
    linear-gradient(
      180deg,
      rgb(11 10 8 / 0.3) 0%,
      rgb(11 10 8 / 0) 28%,
      rgb(11 10 8 / 0) 52%,
      rgb(11 10 8 / 0.72) 100%
    );
}

.ht-bleed-band > .e-con-inner {
  position: relative;
  z-index: 1;
  padding-block-end: clamp(1.5rem, 4vw, 3rem);
  align-items: flex-start;
}

.ht-bleed__label {
  display: flex;
  flex-direction: column;
  gap: var(--ht-s-1);
}

/* The second frame carries no caption; do not leave an empty box behind. */
.ht-bleed__label .ht-eyebrow:empty,
.ht-bleed__label .ht-bleed__name:empty {
  display: none;
}

.ht-bleed__name {
  font-family: var(--ht-font-display);
  font-size: var(--ht-t-lg);
  color: var(--ht-steam);
  margin: 0;
}

@media (max-width: 900px) {
  .ht-band--reverse.e-con {
    flex-direction: column;
  }
}

/* ---- Tarifs -------------------------------------------------------------
   A note that qualifies the table above it should sit closer to that table
   than to the next section, or it reads as an orphan.
   -------------------------------------------------------------------------- */

.ht-note-after {
  margin-block-start: var(--ht-s-4);
}

/* .ht-band-surface is a full-bleed colour band; .ht-band-narrow caps the
   reading width. No combined rule is needed: .ht-band-surface only paints a
   background-color on the container, and .ht-band-narrow already caps the
   inner wrapper, so the background runs edge to edge either way.

   A combined rule used to live here repeating max-width: 860px. Being more
   specific, it silently overrode the narrow cap and left "Les options" on
   tarifs 128px wider than the static build. Two rules declaring the same
   measure is how they drift apart — keep it in one place. */

/* ---- Per-photo crops -----------------------------------------------------
   The static build set object-position inline per image; Elementor widgets
   cannot carry it. These classes restore those curation decisions — each one
   exists to keep something specific out of frame, not for composition.

   .ht-photo img already reads --pos, so setting the property on the widget
   wrapper is enough; it inherits down to the <img>.
   -------------------------------------------------------------------------- */

/* Keeps the sofa, glass table and red rug out; leaves the slatted wall. */
.ht-crop-tasseaux {
  --pos: 55% 16%;
}

/* Pushes the green front door out of frame, keeps the path and planting. */
.ht-crop-jardin {
  --pos: 68% 58%;
}

/* Crops to the window and planting, away from the red rug. */
.ht-crop-salon {
  --pos: 62% 26%;
}

/* Excludes the doorway and the stray chair at the right edge. */
.ht-crop-transats {
  --pos: 28% 52%;
}

/* ==========================================================================
   Contact
   ========================================================================== */

.ht-contact-grid.e-con {
  gap: clamp(2.5rem, 6vw, 5rem);
  align-items: flex-start;
}

.ht-contact-grid.e-con > .e-con {
  --width: auto;
  flex: 1 1 20rem;
  gap: var(--ht-s-4);
}

/* An eyebrow that starts a new block inside a column needs air above it,
   otherwise "Horaires" reads as part of the address list. */
.ht-eyebrow-spaced {
  margin-block-start: var(--ht-s-4);
}

.ht-contact__actions.e-con {
  --width: auto;
  gap: var(--ht-s-2);
}

/* ---- Consent-gated map ---------------------------------------------------
   The iframe is absent from the markup entirely; map.js injects it on click.
   Styling the placeholder properly matters — it is what most visitors see.
   -------------------------------------------------------------------------- */

.ht-map-wrap {
  width: 100%;
}

.ht-map__aside {
  font-size: var(--ht-t-xs);
}

@media (max-width: 900px) {
  .ht-contact-grid.e-con > .e-con {
    flex: 1 1 100%;
  }
}

/* ---- Legal pages ---------------------------------------------------------
   No hero, so the section padding alone separates the title from the fixed
   header. The placeholder warning needs to read as a warning, not as body
   copy, and must sit clear of the prose below it.
   -------------------------------------------------------------------------- */

.ht-legal-band .ht-notice {
  display: block;
  margin-block-end: var(--ht-s-6);
}

.ht-legal-band .ht-prose h2:first-child {
  margin-block-start: 0;
}

/* The static legal pages are NOT narrow bands. They sit on the full 1192
   measure, left-aligned with every other page, and cap each block at
   --ht-measure instead. Because 62ch resolves against each element's own font,
   one token produces three different widths — 651 for the heading, 640 for the
   notice, 756 for the prose — and that variation is the design.

   Porting them as centred 732px columns replaced all three with one number and
   pushed the text 230px right. Cancel the narrow cap; put the measure back on
   the text. .ht-shead already carries --ht-measure, so it needs nothing. */
/* var(--content-width), not none: the inner wrapper's max-width IS the site
   measure, so removing it lets the band run the full viewport rather than
   falling back to 1192. This cancels only .ht-band-narrow's override. */
.ht-legal-band > .e-con-inner {
  max-width: var(--content-width);
  margin-inline: auto;
}

.ht-legal-band .ht-notice {
  max-width: var(--ht-measure);
}

/* Elementor defends widget width with a deliberately doubled selector —
   .e-con.e-con > .e-con-inner > .elementor-widget { max-width: 100% } — which
   scores (0,4,0). A plainer rule loses silently: the declaration is live, the
   cascade just never reaches it. Double .ht-legal-band to outrank it rather
   than reaching for !important, which would only move the war one step on. */
/* 72ch, not --ht-measure. Legal prose is the one place the static build
   deliberately runs wider than the 62ch reading ceiling: it is reference text
   to be scanned, not narrative to be read. See .ht-prose in pages.css. */
.ht-legal-band.ht-legal-band > .e-con-inner > .ht-prose.elementor-widget {
  max-width: 72ch;
}

/* ---- Booking without JavaScript -----------------------------------------
   A <dialog> with no `open` attribute is display:none per the UA stylesheet,
   and every call to action is a link to #reservation. With scripting off the
   primary button would therefore do nothing at all — which reads as broken,
   not as a missing enhancement. Render the panel inline instead, so the
   anchor lands on real, readable contact details.
   -------------------------------------------------------------------------- */

html.no-js .ht-dialog {
  display: block;
  position: static;
  width: min(560px, calc(100vw - 2rem));
  max-height: none;
  margin: 0 auto var(--ht-s-7);
  scroll-margin-block-start: calc(var(--ht-header-h) + 1rem);
}

html.no-js .ht-dialog__close {
  display: none;
}

/* ==========================================================================
   Spacing parity with the static build

   Elementor gives every container a default `gap: 20px` between children. The
   design system never used gaps at this level — vertical rhythm comes from
   explicit margins (.ht-shead margin-block-end, .ht-link margin-block-start).
   Leaving Elementor's gap in place stacks an extra 20px onto every child
   boundary, which is why the ported pages ran ~10% taller than the original.

   Zeroing it here makes the design system the single source of spacing truth.
   Containers that genuinely need a gap (.ht-shead, .ht-spaces, .ht-band,
   .ht-hero__actions, .ht-footer__grid) set their own and are unaffected.
   ========================================================================== */

.ht-band-pad > .e-con-inner,
.ht-legal-band > .e-con-inner,
.ht-cta-band > .e-con-inner {
  --gap: 0px;
}

/* The quote flows straight into the argument that answers it — they are one
   thought, not two sections. This was ht-section--top-flush in the static
   build and was lost in the port. */
.ht-band-flush-top {
  padding-block-start: 0;
}

/* ---- Margin reset inside HTML-widget components --------------------------
   base.css uses `* { margin: 0 }`, which has zero specificity — Elementor and
   Hello Elementor both set real h3/p margin rules that outrank it. In the
   static build nothing competed, so the reset held; here it silently lost,
   adding ~30px inside every step, formula, claim and option row.

   Scoped to the components that are laid out with gap/grid. Prose (.ht-prose,
   .ht-acc__a) deliberately keeps its paragraph rhythm and is excluded.
   -------------------------------------------------------------------------- */

.ht-steps :is(h1, h2, h3, h4, p),
.ht-formulas :is(h1, h2, h3, h4, p),
.ht-claims :is(p, span),
.ht-options :is(p, span),
.ht-bleed__label p,
.ht-testimonial__who,
.ht-footer__title p,
.ht-space__name,
.ht-space__text {
  margin: 0;
}

/* ---- Eyebrow inside a heading widget -------------------------------------
   The eyebrows are built as heading widgets, so the blanket rule that gives
   Elementor headings the Marcellus display face was also claiming them —
   rendering them in serif steam-white instead of Inter 500 brass with wide
   tracking. The eyebrow is a signature element of the art direction; it must
   win against the generic heading rule.
   -------------------------------------------------------------------------- */

.ht-eyebrow .elementor-heading-title,
.ht-eyebrow.elementor-widget-heading .elementor-heading-title {
  font-family: var(--ht-font-body);
  font-size: var(--ht-t-xs);
  font-weight: 500;
  letter-spacing: var(--ht-track-eyebrow);
  text-transform: uppercase;
  color: var(--ht-brass);
  line-height: 1.4;
}

/* The wordmark's second half is brass — in the header widget and anywhere
   else the mark is rendered. */
.ht-brand .elementor-heading-title .ht-brand__mark,
.ht-brand__mark {
  color: var(--ht-brass);
}

/* ---- Brand lockup vs Elementor's image normalise --------------------------
   Elementor ships `.elementor img { height: auto }` — specificity (0,1,1),
   which outscores .ht-brand__logo (0,1,0) in layout.css. The header lockup was
   therefore rendering at its intrinsic height: 97px inside a 76px bar. Raising
   specificity here is exactly what this file exists for.
   -------------------------------------------------------------------------- */

.elementor img.ht-brand__logo {
  height: var(--brand-h, 3.25rem);
  width: auto;
}

/* The footer lockup is the taller stacked one. On WordPress the footer is an
   Elementor template carrying none of our classes, so this keys off the brand
   widget's own class rather than .ht-footer. */
.elementor .ht-footer__brand img.ht-brand__logo {
  --brand-h: 9.375rem;
}

@media (max-width: 640px) {
  .elementor img.ht-brand__logo {
    --brand-h: 2.75rem;
  }

  .elementor .ht-footer__brand img.ht-brand__logo {
    --brand-h: 7rem;
  }
}

/* ---- Plate bands inside an Elementor container -----------------------------
   .ht-bleed carries its own padding-inline so the plate never touches the
   screen edge on the static build. Elementor's parent container already
   applies that same gutter, so the two stacked and the plate came out 1009px
   wide against 1137px locally. Drop ours where Elementor is already padding.
   -------------------------------------------------------------------------- */

.e-con .ht-bleed {
  padding-inline: 0;
}

/* ---- Mobile menu toggle: tap target ----------------------------------------
   Elementor renders the toggle at 35x35 (22px glyph + 5.5px padding). Below the
   860px breakpoint it is the only way to navigate the site, and 35px is under
   the 44x44 minimum for a touch target. The static build's own burger is 44x44.

   Safe to widen: the dropdown is position:fixed with inset-inline:0 (see the
   panel rule above), so it is pinned to the viewport, not anchored to the
   toggle's width.
   -------------------------------------------------------------------------- */

/* Scoped to the range where the toggle is meant to exist. Unscoped, the
   display: inline-flex below outscored Elementor's own display:none and left
   the burger showing next to the desktop nav, doubling the header height. */
@media (max-width: 860px) {
  .elementor .elementor-menu-toggle {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
}
