/* ============================================================================
 * Eurore — real-estate layer on top of ecomus styles.css.
 * Loaded AFTER css/styles.css. Reuses ecomus tokens (--primary, --main, --text,
 * --line) and only adds property-portal specifics.
 * ==========================================================================*/
:root {
  --eu-sale: #1f7a4d;
  /* for-sale green  */
  --eu-rent: #1565c0;
  /* for-rent blue   */
  --eu-new: var(--primary);
  --eu-soft: #f6f6f6;
  --eu-radius: 8px;
  --eu-shadow: 0 6px 24px rgba(0, 0, 0, .08);
  --eu-shadow-sm: 0 2px 10px rgba(0, 0, 0, .06);
}

/* ----- Logo ----- */
.eurore-logo {
  display: inline-flex;
  align-items: center;
}

/* Scoped to .eurore-logo so it outranks the theme's `.logo-header img`, which
   pins a fixed width (110px, and 136px from 768px up, in styles.css). That width
   beat a bare .eurore-logo-img while this height won on the other axis, so the
   two were set independently and the logo rendered at whatever ratio they
   happened to form rather than its own — 110x34 squashed a 4.3:1 wordmark to
   3.2:1 on mobile.

   Height is the sizing axis, so every logo carries the same visual weight in the
   bar whatever its proportions; width follows from it. max-width and object-fit
   are headroom for whatever gets uploaded next — a logo too wide for its column
   scales down whole instead of squashing, so no future upload can repeat this. */
.eurore-logo .eurore-logo-img {
  height: 34px;
  width: auto;
  max-width: 100%;
  object-fit: contain;
  display: block;
}

/* ----- Language picker ----- */
.nav-language {
  position: relative;
}

.eu-lang-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: none;
  background: none;
  cursor: pointer;
  padding: 4px 2px;
  color: var(--main);
  font-weight: 600;
  font-size: 13px;
}

.eu-flag {
  width: 22px;
  height: 16px;
  border-radius: 3px;
  object-fit: cover;
  display: inline-block;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .1);
}

.eu-lang-toggle .icon-arrow-down {
  font-size: 8px;
  transition: transform .2s ease;
}

.nav-language.open .eu-lang-toggle .icon-arrow-down {
  transform: rotate(180deg);
}

.eu-lang-menu {
  position: absolute;
  top: calc(100% + 12px);
  right: 0;
  min-width: 184px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: var(--eu-shadow);
  list-style: none;
  margin: 0;
  padding: 6px;
  z-index: 1500;
  display: none;
}

.nav-language.open .eu-lang-menu {
  display: block;
}

.eu-lang-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 10px;
  border-radius: 6px;
  color: var(--main);
  font-size: 14px;
  white-space: nowrap;
}

.eu-lang-item:hover {
  background: var(--eu-soft);
}

/* ----- Mobile menu language picker -----
   The theme hides the top-bar switcher below 1200px, so this is the only locale
   control a phone gets. Structure and collapse behaviour come from .nav-ul-mb;
   only the flag/name pairing needs styling of its own. */
.eu-mb-language {
  border-top: 1px solid rgb(238, 238, 238);
  margin-bottom: 15px;
}

.eu-mb-language .eu-mb-language-current {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

/* .nav-ul-mb .sub-nav-link is space-between, which is right for the menu's own
   rows (label left, chevron right) but splits a flag from its language name.
   Pack them together instead. */
.eu-mb-language .eu-mb-language-item {
  justify-content: flex-start;
  gap: 8px;
}

.eu-mb-language .eu-mb-language-item[aria-current] {
  font-weight: 600;
}

/* The menu's 26px trailing gap is sized to separate nav groups; here it only
   pushes the account buttons down. */
.eu-mb-language .sub-nav-menu {
  margin-bottom: 10px;
}

/* ----- Account dropdown -----
   The signed-in menu under the header account icon. Same anchored-panel shape as
   the language picker above — .open on the parent flips an absolutely positioned
   panel — and EuroreDropdown.wire() drives both, so they open and close alike. */
.nav-account {
  position: relative;
}

.eu-account-toggle {
  border: none;
  background: none;
  cursor: pointer;
  padding: 0;
  color: inherit;
}

.eu-account-menu {
  position: absolute;
  top: calc(100% + 12px);
  right: 0;
  min-width: 200px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: var(--eu-shadow);
  padding: 6px;
  z-index: 1500;
  display: none;
  text-align: left;
}

.nav-account.open .eu-account-menu {
  display: block;
}

.eu-account-name {
  padding: 8px 10px 10px;
  font-weight: 700;
  color: var(--main);
  font-size: 14px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 4px;
}

.eu-account-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: 8px 10px;
  border-radius: 6px;
  color: var(--main);
  font-size: 14px;
  background: none;
  border: none;
  cursor: pointer;
}

.eu-account-item:hover {
  background: var(--eu-soft);
}

/* top bar (ecomus-style) */
.eu-topbar .tf-top-bar_wrap {
  padding: 7px 0;
}

.eu-topbar .top-bar-text {
  color: var(--text);
  margin: 0;
  font-size: 13px;
}

.eu-topbar .eu-lang-toggle {
  font-size: 13px;
}

/* Mobile announcement marquee. Only rendered when several top-bar texts are
   configured — with one text the bar stays static and this is absent. */
.eu-topbar-marquee {
  overflow: hidden;
  white-space: nowrap;
  min-width: 0;
}

.eu-topbar-marquee-inner {
  display: inline-flex;
  animation: eu-topbar-marquee-scroll 18s linear infinite;
}

.eu-topbar-marquee-inner .top-bar-text {
  padding: 0 1.5em;
}

@keyframes eu-topbar-marquee-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  .eu-topbar-marquee-inner {
    animation: none;
  }
}

@media (max-width: 767px) {

  /* Social icons only. .eu-topbar-promo must NOT be hidden here: it is the class
     on the single-text announcement, which has no marquee to fall back to, so
     hiding it emptied the whole top bar on mobile whenever exactly one text was
     configured. The multi-text swiper carries the same class but hides itself on
     mobile through its own .d-none .d-md-block, and the marquee takes over. */
  .eu-topbar .eu-topbar-social {
    display: none;
  }

  .eu-topbar .tf-top-bar_wrap {
    grid-template-columns: 1fr !important;
  }
}

/* ----- Top-bar accessibility toggle ----- */
/* The pcadmin accessibility button (#accessibility-toggle) sits in the top bar,
   just before the language switcher. Keep the person icon large and legible — the
   core accessibility.css sets an inline 24px on the <i>, so bumping the size needs
   !important. Neutral colour to sit with the language text; the core file's
   black-yellow contrast override still wins in high-contrast mode (it is !important). */
.eu-topbar #accessibility-toggle {
  padding: 0;
}

.eu-topbar #accessibility-toggle i {
  margin: 0 !important;
  font-size: 30px !important;
  line-height: 1;
  color: var(--primary);
}

/* ----- Header tweaks ----- */
.header-eurore .item-link {
  font-weight: 500;
}

/* The theme hides the wishlist, account and compare icons below 767px
   (styles.css, `@media only screen and (max-width: 767px)`). For a shop that is
   reasonable — a phone gets the cart and little else. Here it stranded the
   shortlist: the hearts on the listing cards still save, but the only link to
   /{lang}/favourites was that hidden icon, so a phone could fill the list and
   never open it. Bring the heart back, and only the heart — the account menu
   genuinely does live in the burger on mobile, and compare does not exist here.
   Same selector shape and specificity as the rule it answers; eurore.css loads
   after styles.css, so this wins on order. */
@media only screen and (max-width: 767px) {
  #header .nav-icon .nav-wishlist {
    display: flex;
  }
}

/* Anchor nav dropdowns to their item. ecomus's .submenu-default uses
   left:-110px to centre the dropdown under the item, which only resolves
   correctly when the item is the positioned containing block — without this
   the dropdown drifts off the left edge of the page on hover. */
.box-nav-ul .menu-item {
  position: relative;
}

.box-nav-ul .item-link {
  white-space: nowrap;
}

.header-eurore .box-nav-ul {
  gap: 16px;
}

.box-nav-ul .menu-item.current-menu>.item-link {
  color: var(--primary);
}

/* "Pages" mega-menu: a wide multi-column dropdown listing every page (prototype nav).
   Right-anchored to the item so the wide panel never overflows the viewport edge. */
.box-nav-ul .sub-menu.eu-mega {
  left: auto;
  right: 0;
  min-width: 0;
}

.eu-mega-inner {
  display: flex;
  gap: 36px;
}

.eu-mega-col {
  min-width: 152px;
}

.eu-mega-col .menu-heading {
  margin-bottom: 14px;
}

/* mobile offcanvas: section headings above each group of page links */
.nav-ul-mb .mb-menu-heading {
  display: block;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-2);
  padding: 14px 0 2px;
}

.mobile-menu-toggle {
  font-size: 22px;
  color: var(--main);
}

/* ============================================================================
 * Hero search (kv.ee-style)
 * ==========================================================================*/
.eu-hero {
  position: relative;
  background: #0d1b2a;
  color: #fff;
  overflow: hidden;
  border-radius: var(--eu-radius);
}

.eu-hero-media {
  position: absolute;
  inset: 0;
}

.eu-hero-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: .55;
}

.eu-hero-inner {
  position: relative;
  z-index: 2;
  max-width: 1100px;
  margin: 0 auto;
  padding: 86px 20px 96px;
  text-align: center;
}

.eu-hero h1 {
  color: #fff;
  font-size: clamp(30px, 4.4vw, 52px);
  font-weight: 800;
  letter-spacing: -.02em;
  margin: 0 0 12px;
}

.eu-hero p {
  color: rgba(255, 255, 255, .9);
  font-size: clamp(15px, 1.6vw, 19px);
  margin: 0 0 30px;
}

.eu-search {
  background: #fff;
  color: var(--main);
  border-radius: 14px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, .28);
  padding: 20px 20px 16px;
  text-align: left;
  max-width: 940px;
  margin: 0 auto;
}

.eu-search-tabs {
  display: inline-flex;
  gap: 4px;
  margin: 0 0 16px;
  background: var(--eu-soft);
  border-radius: 999px;
  padding: 4px;
}

.eu-tab {
  border: none;
  background: none;
  padding: 9px 24px;
  border-radius: 999px;
  font-weight: 600;
  font-size: 14px;
  color: var(--text);
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}

.eu-tab.active {
  background: var(--primary);
  color: #fff;
}

/* Hero search Buy/Rent toggle: black active tab (scoped so other .eu-tab uses are untouched). */
#eu-hero-form .eu-tab.active {
  background: var(--main);
}

/* ----- Auth pages: a darkened photo as a backdrop behind a centred card -----
   Same treatment as the hero's .eu-hero-media (cover, opacity .55 over #0d1b2a),
   but painted as a ::before rather than an <img>: the backdrop then comes from
   the shared .eu-auth section, so login, register, forgot-password and
   reset-password all get it without each page rendering its own markup. */
.eu-auth {
  position: relative;
  overflow: hidden;
  background: #0d1b2a;
  display: flex;
  align-items: center;
  min-height: 540px;
}

.eu-auth::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: url("../images/auth/background.avif");
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  opacity: .55;
}

.eu-auth-inner {
  position: relative;
  z-index: 2;
  width: 100%;
}

/* .eu-panel has no own background (it inherited the white page body) — make it opaque on the photo */
.eu-auth .eu-panel {
  background: #fff;
}

/* centre the heading and the full-width submit button's label across both auth pages (login + register) */
[data-page="auth"] .eu-panel h1 {
  text-align: center;
}

[data-page="auth"] .eu-panel form button[type="submit"] {
  justify-content: center;
}

/* centre the register-only Private/Business toggle pill (inline-flex needs block + auto margins to centre) */
[data-page="auth"] #rg-acct-tabs {
  display: flex;
  width: fit-content;
  margin: 0 auto 16px;
}

/* ----- Buttons: rounded-pill sitewide, filled ones red -----
   Overrides ecomus's boxy black .btn-fill / 3px .radius-3 here in the custom
   layer rather than editing the vendored styles.css or the shared .radius-3
   utility. The !important is only to beat .radius-3's own !important. */
.tf-btn.btn-fill,
.tf-btn.btn-outline {
  border-radius: 999px !important;
}

.tf-btn.btn-fill {
  background-color: var(--primary);
  border-color: var(--primary);
}

.tf-btn.btn-fill:hover {
  background-color: #b50f12;
  border-color: #b50f12;
}

.eu-search-row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr)) auto;
  gap: 12px;
  align-items: end;
}

.eu-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.eu-field>label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-2);
}

.eu-field select,
.eu-field input {
  width: 100%;
  height: 48px;
  border: 1px solid var(--line);
  border-radius: var(--eu-radius);
  padding: 0 12px;
  font: inherit;
  font-size: 14px;
  background: #fff;
  color: var(--main);
}

.eu-field .eu-range {
  display: flex;
  align-items: center;
  gap: 6px;
}

.eu-field .eu-range input {
  padding: 0 10px;
}

/* Styled native-select popups (Country / City / Property type, search filters,
   etc.). Uses the CSS "customizable select" API so the OPENED dropdown matches
   the site instead of the browser default. Wrapped in @supports so browsers
   without it keep the native popup. */
@supports (appearance: base-select) {

  .eu-field select,
  .eu-fselect,
  .eu-controls select,
  .eu-stats-bar select {
    appearance: base-select;
    display: inline-flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
  }

  .eu-field select::picker(select),
  .eu-fselect::picker(select),
  .eu-controls select::picker(select),
  .eu-stats-bar select::picker(select) {
    appearance: base-select;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: var(--eu-radius);
    padding: 6px;
    box-shadow: 0 10px 28px rgba(0, 0, 0, .12);
    font: 14px/1.3 inherit;
    color: var(--main);
    max-height: 320px;
    overflow-y: auto;
    /* Always open directly below the box (don't flip above). */
    position-area: none;
    top: anchor(bottom);
    left: anchor(left);
    right: auto;
    bottom: auto;
    margin-top: 6px;
    position-try-fallbacks: none;
  }

  .eu-field select option,
  .eu-fselect option,
  .eu-controls select option,
  .eu-stats-bar select option {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 12px;
    border-radius: 6px;
    cursor: pointer;
    transition: background-color .12s ease;
  }

  .eu-field select option:hover,
  .eu-field select option:focus,
  .eu-fselect option:hover,
  .eu-fselect option:focus,
  .eu-controls select option:hover,
  .eu-controls select option:focus,
  .eu-stats-bar select option:hover,
  .eu-stats-bar select option:focus {
    background: var(--eu-soft, #f5f5f5);
  }

  .eu-field select option:checked,
  .eu-fselect option:checked,
  .eu-controls select option:checked,
  .eu-stats-bar select option:checked {
    background: var(--primary);
    color: #fff;
  }

  .eu-field select option::checkmark,
  .eu-fselect option::checkmark,
  .eu-controls select option::checkmark,
  .eu-stats-bar select option::checkmark {
    display: none;
  }

  .eu-field select::picker-icon,
  .eu-fselect::picker-icon,
  .eu-controls select::picker-icon,
  .eu-stats-bar select::picker-icon {
    content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='11' height='7' viewBox='0 0 11 7'><path d='M1 1l4.5 4.5L10 1' stroke='%23545454' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>");
    transition: transform .2s ease;
  }

  .eu-field select:open::picker-icon,
  .eu-fselect:open::picker-icon,
  .eu-controls select:open::picker-icon,
  .eu-stats-bar select:open::picker-icon {
    transform: rotate(180deg);
  }
}

.eu-search .eu-submit {
  height: 48px;
  padding: 0 26px;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.eu-search-extra {
  display: flex;
  gap: 18px;
  padding: 12px 4px 4px;
  font-size: 13px;
}

.eu-search-extra a {
  color: var(--text);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.eu-search-extra a:hover {
  color: var(--primary);
}

@media (max-width: 991px) {
  .eu-search-row {
    grid-template-columns: 1fr 1fr;
  }

  .eu-search .eu-submit {
    grid-column: 1 / -1;
  }
}

@media (max-width: 575px) {
  .eu-search-row {
    grid-template-columns: 1fr;
  }
}

/* ============================================================================
 * Property card
 * ==========================================================================*/
.eu-card {
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--eu-radius);
  overflow: hidden;
  transition: box-shadow .25s ease, transform .25s ease;
  height: 100%;
}

.eu-card:hover {
  box-shadow: var(--eu-shadow);
  transform: translateY(-2px);
}

.eu-card-media {
  position: relative;
  aspect-ratio: 1920 / 1280;
  overflow: hidden;
  background: var(--eu-soft);
}

/* The image sits inside an <a>; make the link fill the media box so the image's
   height:100% + object-fit:cover resolve (otherwise the photo keeps its natural
   height and leaves a gray strip under shorter images). */
.eu-card-media a {
  display: block;
  width: 100%;
  height: 100%;
}

.eu-card-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .5s ease;
}

.eu-card:hover .eu-card-media img {
  transform: scale(1.05);
}

.eu-badges {
  position: absolute;
  top: 12px;
  left: 12px;
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.eu-badge {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .02em;
  color: var(--main);
  line-height: 1.25;
  padding: 4px 11px;
  border-radius: 999px;
  background: #fff;
  border: 1px solid var(--line);
  box-shadow: 0 1px 4px rgba(0, 0, 0, .12);
}

.eu-badge.sale,
.eu-badge.rent,
.eu-badge.new {
  background: #fff;
  color: var(--main);
}

/* .eu-fav is the BEHAVIOUR hook — eurore-storefront.js selects on it, and it sits
   on two very different controls: the round heart overlaying a card, and the
   labelled "Save" pill in the property page's breadcrumb toolbar.
   The overlay LAYOUT below therefore has to be scoped to the card, not attached to
   the hook. Unscoped, it made the toolbar pill position:absolute with <body> as its
   offset parent, so the Save button flew to the top-right corner of the page. */
.eu-card-media .eu-fav {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 36px;
  height: 36px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, .92);
  display: grid;
  place-items: center;
  cursor: pointer;
  box-shadow: var(--eu-shadow-sm);
}

.eu-fav i {
  font-size: 15px;
  color: var(--main);
}

.eu-fav.is-fav i {
  color: var(--primary);
}

.eu-card-media .eu-fav.is-fav {
  background: #fff;
}

/* Signed out, the card heart is an <a> to the login page rather than a toggle
   (#45), and an anchor brings its own colour and underline. Scoped to the card for
   the same reason as the layout above: the toolbar pill is styled by
   .eu-crumb-btn and must keep its own colour. */
.eu-card-media .eu-fav,
.eu-card-media .eu-fav:hover,
.eu-card-media .eu-fav:focus {
  text-decoration: none;
  color: inherit;
}

/* In flight: the click already painted the new state optimistically, so the button
   is disabled for the round trip to stop a second click racing the first. Keep it
   legible rather than greying it out — the state it shows is the state it expects
   to end in. */
.eu-fav[disabled] {
  cursor: default;
  opacity: .7;
}

/* A favourite whose listing has been withdrawn or sold (#45). It carries no photo,
   price or link by design; .eu-card-media already holds the aspect ratio and
   .eu-card-noimage already fills it, so the card keeps its neighbours' height in
   the grid without any sizing here. Muted so it reads as past-tense beside the
   live cards, but not so faint that the title stops being legible. */
.eu-card-unavailable {
  opacity: .8;
}

/* The heart stays fully opaque: removing the card is the one action still
   available here, so it must not look disabled along with the rest. */
.eu-card-unavailable .eu-fav {
  opacity: 1;
}

.eu-card-body {
  padding: 14px 16px 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1;
}

.eu-card-price {
  font-size: 20px;
  font-weight: 800;
  color: var(--main);
  line-height: 1.1;
}

.eu-card-price .per {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-2);
  margin-left: 6px;
}

.eu-card-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--main);
  margin: 0;
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.eu-card-loc {
  font-size: 13px;
  color: var(--text-2);
  display: flex;
  align-items: center;
  gap: 6px;
}

.eu-card-loc i {
  font-size: 13px;
}

.eu-specs {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: auto;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  font-size: 13px;
  color: var(--text);
}

.eu-specs .spec {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.eu-specs .spec b {
  font-weight: 700;
  color: var(--main);
}

/* list layout (search "list" view) */
.eu-grid.is-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.eu-grid.is-list .eu-card {
  flex-direction: row;
}

.eu-grid.is-list .eu-card-media {
  width: 320px;
  flex-shrink: 0;
  aspect-ratio: 1920 / 1280;
}

.eu-grid.is-list .eu-card-body {
  padding: 18px 20px;
}

.eu-grid.is-list .eu-card-price {
  font-size: 22px;
}

@media (max-width: 767px) {
  /* There is no room for a side-by-side row on a phone, so list view drops back
     to the same stacked card grid view already renders. */
  .eu-grid.is-list .eu-card {
    flex-direction: column;
  }

  .eu-grid.is-list .eu-card-media {
    width: 100%;
  }
}

/* grid container */
.eu-grid {
  display: grid;
  gap: 24px;
  grid-template-columns: repeat(4, 1fr);
}

.eu-grid.cols-3 {
  grid-template-columns: repeat(3, 1fr);
}

@media (max-width: 1200px) {

  .eu-grid,
  .eu-grid.cols-3 {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (max-width: 991px) {

  .eu-grid,
  .eu-grid.cols-3 {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 575px) {

  .eu-grid,
  .eu-grid.cols-3 {
    grid-template-columns: 1fr;
  }
}

/* ============================================================================
 * Section helpers
 * ==========================================================================*/
.eu-section {
  padding: 56px 0;
}

.eu-section-sm {
  padding: 36px 0;
}

.eu-section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 26px;
}

.eu-section-head h1,
.eu-section-head h2 {
  font-size: 28px;
  font-weight: 800;
  letter-spacing: -.01em;
  margin: 0;
}

.eu-section-head p {
  margin: 4px 0 0;
  color: var(--text-2);
}

.eu-section-head a:not(.tf-btn) {
  font-weight: 600;
  color: var(--primary);
  white-space: nowrap;
}

/* CTA banner */
.eu-cta {
  border-radius: 14px;
  overflow: hidden;
  position: relative;
  min-height: 320px;
  display: flex;
  align-items: center;
  color: #fff;
}

.eu-cta img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.eu-cta::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(0, 0, 0, .65), rgba(0, 0, 0, .15));
}

.eu-cta-content {
  position: relative;
  z-index: 2;
  padding: 44px;
  max-width: 520px;
}

.eu-cta-content h2 {
  color: #fff;
  font-size: clamp(24px, 3vw, 36px);
  font-weight: 800;
  margin: 0 0 12px;
}

.eu-cta-content p {
  color: rgba(255, 255, 255, .92);
  margin: 0 0 22px;
}

/* popular locations */
.eu-loc-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
}

.eu-loc {
  position: relative;
  border-radius: var(--eu-radius);
  overflow: hidden;
  aspect-ratio: 3/2;
  display: block;
}

.eu-loc img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .5s ease;
}

.eu-loc:hover img {
  transform: scale(1.06);
}

.eu-loc span {
  position: absolute;
  left: 14px;
  bottom: 12px;
  z-index: 2;
  color: #fff;
  font-weight: 700;
  font-size: 17px;
  text-shadow: 0 1px 8px rgba(0, 0, 0, .5);
}

.eu-loc::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 40%, rgba(0, 0, 0, .55));
}

@media (max-width: 991px) {
  .eu-loc-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* ============================================================================
 * Search page
 * ==========================================================================*/
.eu-search-layout {
  display: grid;
  grid-template-columns: 300px 1fr;
  gap: 32px;
  align-items: start;
}

@media (max-width: 991px) {
  .eu-search-layout {
    grid-template-columns: 1fr;
  }
}

.eu-sidebar {
  position: sticky;
  top: 100px;
}

@media (max-width: 991px) {
  .eu-sidebar {
    position: static;
    display: none;
  }

  .eu-sidebar.open {
    display: block;
  }
}

.eu-facet {
  padding: 18px 0;
  border-bottom: 1px solid var(--line);
}

.eu-facet:last-child {
  border-bottom: none;
}

.eu-facet h3 {
  font-size: 14px;
  font-weight: 700;
  margin: 0 0 12px;
}

.eu-facet .eu-range {
  display: flex;
  gap: 8px;
  align-items: center;
}

.eu-facet .eu-range input {
  width: 100%;
  height: 40px;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 0 10px;
  font: inherit;
}

.eu-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.eu-pill {
  border: 1px solid var(--line);
  background: #fff;
  border-radius: 999px;
  padding: 7px 14px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
}

.eu-pill:hover {
  border-color: var(--main);
}

.eu-pill.active {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}

.eu-check {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 0;
  font-size: 14px;
  color: var(--text);
  cursor: pointer;
}

/* Location facet: the country and city selects stack, so space them the way the
   mock does. The mock got its gap incidentally from inline leading; here a
   visually-hidden <label> sits between the two, so a general sibling combinator
   is needed — `select + select` never matches across it. */
.eu-sidebar .eu-fselect ~ .eu-fselect {
  margin-top: 10px;
}

/* Search sidebar (#35) — the price box holds a real input so the pair still
   filters with JS off. The theme draws the border and the currency on .price-val
   itself, so the input inside is stripped bare. Spinners would blow out the 68px
   box, hence the appearance resets. */
.widget-price .caption-price .price-val input {
  width: 100%;
  min-width: 0;
  border: 0;
  padding: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: right;
  -moz-appearance: textfield;
  appearance: textfield;
}

.widget-price .caption-price .price-val input:focus {
  outline: none;
}

.widget-price .caption-price .price-val input::-webkit-outer-spin-button,
.widget-price .caption-price .price-val input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* The chip row's own reset — a link, not a removable filter, so it inverts. */
.eu-chip-clear {
  background: none;
  border: 1px solid var(--line);
  color: var(--text-2);
  padding: 6px 14px;
}

.eu-chip-clear:hover {
  border-color: var(--main);
  color: var(--main);
}

.eu-results-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.eu-results-bar h1 {
  font-size: 22px;
  font-weight: 800;
  margin: 0;
}

.eu-results-bar .count {
  color: var(--text-2);
  font-weight: 500;
  font-size: 14px;
}

.eu-controls {
  display: flex;
  align-items: center;
  gap: 10px;
}

.eu-controls select {
  height: 42px;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 0 12px;
  font: inherit;
  font-weight: 600;
}

.eu-view-toggle {
  display: inline-flex;
  border: 1px solid var(--line);
  border-radius: 6px;
  overflow: hidden;
}

/* Below 767px list view falls back to the same stacked card grid view already
   renders (see .eu-grid.is-list above), so this switch has nothing left to switch
   between — both modes paint an identical single column. A control that visibly
   does nothing reads as broken, so hide it rather than leave it inert.

   Must sit after the rule above, not up with the .eu-grid.is-list media block:
   both selectors are one class, a media query adds no specificity, and the later
   declaration wins. Restore a distinct mobile list layout and this is the rule to
   drop. `view` stays a URL parameter either way, so nobody is stranded in a mode
   they cannot leave — widening the screen brings the switch back. */
@media (max-width: 767px) {
  .eu-view-toggle {
    display: none;
  }
}

/* The mock's toggle was a pair of <button>s driven by JS. The search page uses
   real links so the view survives in the URL and works without JS, so both tags
   are matched — an <a> otherwise inherits none of this and collapses to a bare
   icon. */
.eu-view-toggle button,
.eu-view-toggle a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 42px;
  border: none;
  background: #fff;
  cursor: pointer;
  color: var(--text-2);
}

.eu-view-toggle button.active,
.eu-view-toggle a.active {
  background: var(--main);
  color: #fff;
}

.eu-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 18px;
}

.eu-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--eu-soft);
  border-radius: 999px;
  padding: 6px 8px 6px 14px;
  font-size: 13px;
  font-weight: 600;
}

.eu-chip button {
  border: none;
  background: none;
  cursor: pointer;
  color: var(--text-2);
  line-height: 1;
  font-size: 16px;
}

.eu-filter-toggle {
  display: none;
}

@media (max-width: 991px) {
  .eu-filter-toggle {
    display: inline-flex;
  }
}

.eu-empty {
  text-align: center;
  padding: 60px 20px;
  color: var(--text-2);
}

/* ecomus filter widgets inside the sidebar */
.eu-sidebar .eu-fselect,
.eu-sidebar .eu-finput {
  width: 100%;
  height: 44px;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 0 12px;
  font: inherit;
  font-size: 14px;
  background: #fff;
  color: var(--main);
}

.eu-sidebar .eu-fselect+.eu-fselect {
  margin-top: 10px;
}

/* price caption: fit long euro values (ecomus box is sized for small numbers) */
.eu-sidebar .widget-price .caption-price .price-val {
  width: auto;
  min-width: 64px;
  justify-content: center;
}

.eu-sidebar .widget-price .caption-price .price-val::after {
  position: static;
  transform: none;
  left: auto;
  margin-left: 3px;
}

/* balanced facet spacing so divider lines aren't cramped against inputs */
.eu-sidebar .widget-facet {
  margin-bottom: 22px;
}

.eu-sidebar .widget-facet .facet-title {
  padding-bottom: 16px;
}

.eu-sidebar .widget-facet .collapse {
  padding-bottom: 22px;
}

.eu-sidebar .widget-price {
  margin-top: 8px;
  margin-bottom: 0;
}

/* Single-choice facets must LOOK single-choice.
   The theme's .tf-check (styles.css) is a square with a tick glyph, and the sidebar
   puts that one class on radios and checkboxes alike — so "Rooms", where only one
   option can be picked, was drawn identically to the multi-pick facets above it.
   The shape is the only thing telling a visitor which rule applies, so radios get
   the round-with-a-dot idiom back.

   Drawn with an inset box-shadow rather than ::before: the theme's ::before is an
   icomoon tick animated by transform: scale(), and the :checked rule that drives
   that animation would fight any transform used to centre a dot. */
.eu-sidebar input[type="radio"].tf-check {
  border-radius: 50%;
}

.eu-sidebar input[type="radio"].tf-check::before {
  content: none;
}

.eu-sidebar input[type="radio"].tf-check:checked {
  box-shadow: inset 0 0 0 3px var(--white);
}

/* Full-width sidebar buttons ("Clear filters", and the noscript submit above it).
   The theme's .tf-btn is an inline-flex sized to its label, so w-100 stretches the
   box but leaves the label parked at the left edge. justify-content, not
   text-align: the label is a flex ITEM, so text-align on the button does nothing. */
.eu-sidebar .tf-btn.w-100 {
  justify-content: center;
}

/* pagination reuse ecomus .wg-pagination; minor spacing */
.eu-pagination-wrap {
  margin-top: 36px;
  display: flex;
  justify-content: center;
}

/* ============================================================================
 * Homepage "More ways to search" — ecomus tf-icon-box cards in a row
 * ==========================================================================*/
.eu-explore {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}

.eu-explore .tf-icon-box {
  height: 100%;
}

.eu-explore .tf-icon-box>.icon {
  margin-bottom: 16px;
  color: var(--main);
  line-height: 0;
}

.eu-explore .tf-icon-box>.icon svg {
  width: 40px;
  height: 40px;
}

.eu-explore .tf-icon-box .content p {
  color: var(--text-2);
  font-size: 14px;
  margin: 0 0 14px;
}

.eu-explore-link {
  font-weight: 600;
  color: var(--primary);
}

.eu-explore-link:hover {
  color: #b50f12;
}

@media (max-width: 991px) {
  .eu-explore {
    grid-template-columns: 1fr;
  }
}

/* ============================================================================
 * Breadcrumb bar (between header and page content; every page except home)
 * ==========================================================================*/
.eu-crumbbar {
  border-bottom: 1px solid var(--line);
  background: var(--eu-soft);
}

/* keep the container's responsive horizontal gutter (50px desktop / 15px mobile);
   only set the vertical padding so the bar stays aligned with page content at every width */
.eu-crumbbar-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding-top: 12px;
  padding-bottom: 12px;
}

.eu-crumbs ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 7px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.eu-crumbs li {
  display: flex;
  align-items: center;
  font-size: 13px;
  color: var(--text-2);
}

.eu-crumbs li+li::before {
  content: "/";
  margin-right: 7px;
  color: var(--text-2);
  opacity: .6;
}

.eu-crumbs a {
  color: var(--text-2);
}

.eu-crumbs a:hover {
  color: var(--primary);
}

.eu-crumb-current {
  color: var(--main);
  font-weight: 600;
  max-width: 320px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* listing action buttons (kv.ee object-header style) */
.eu-crumb-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.eu-crumb-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 36px;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: #fff;
  color: var(--main);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}

.eu-crumb-btn:hover {
  border-color: var(--main);
}

.eu-crumb-btn .material-icons {
  font-size: 18px;
}

.eu-crumb-btn.is-active {
  color: var(--primary);
  border-color: var(--primary);
}

.eu-crumb-btn-primary {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}

.eu-crumb-btn-primary:hover {
  background: #b50f12;
  border-color: #b50f12;
  color: #fff;
}

@media (max-width: 767px) {
  .eu-crumb-btn {
    padding: 0 10px;
    gap: 0;
  }

  .eu-crumb-btn:not(.eu-crumb-btn-primary) .eu-crumb-label {
    display: none;
  }
}

/* "Back to …" links lead with the arrow, so the theme's trailing-icon spacing
   (.btn-line .icon { margin-inline-start: 8px }) lands on the wrong side and the
   arrow touches the text — move the gap to the arrow's trailing edge instead */
.eu-back .icon {
  margin-inline-start: 0;
  margin-inline-end: 8px;
}

/* ============================================================================
 * Property detail
 * ==========================================================================*/
/* head sits at the top of the left content column (Rightmove-style): price → title → address */
.eu-detail-head {
  margin-bottom: 24px;
  padding-bottom: 20px;
  border-bottom: 1px solid var(--line);
}

.eu-detail-head h1 {
  font-size: 24px;
  font-weight: 800;
  margin: 0 0 8px;
  letter-spacing: -.01em;
}

.eu-detail-sub {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  color: var(--text-2);
}

.eu-detail-price {
  font-size: 34px;
  font-weight: 800;
  color: var(--main);
  margin-bottom: 10px;
  line-height: 1.1;
}

.eu-detail-price .per {
  font-size: 15px;
  font-weight: 500;
  color: var(--text-2);
  margin-left: 8px;
}

.eu-detail-body {
  display: grid;
  grid-template-columns: 1fr 360px;
  gap: 40px;
  align-items: start;
  margin-top: 22px;
}

/* Rightmove-style sliding-window collage: large main image + preview thumbnails,
   paged inline with Prev/Next arrows. */
.eu-gallery {
  position: relative;
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 8px;
  height: 460px;
}

.eu-gallery.eu-gallery-single {
  grid-template-columns: 1fr;
}

.eu-gallery .eu-gallery-main {
  grid-row: 1 / -1;
}

.eu-gallery .eu-gallery-main,
.eu-gallery .eu-gallery-thumb {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  margin: 0;
  cursor: pointer;
  overflow: hidden;
  border-radius: 8px;
  background: var(--eu-soft);
}

.eu-gallery img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform .45s ease;
}

.eu-gallery .eu-gallery-main:hover img,
.eu-gallery .eu-gallery-thumb:hover img {
  transform: scale(1.04);
}

.eu-gallery-side {
  display: grid;
  grid-template-rows: 1fr 1fr;
  gap: 8px;
  min-height: 0;
}

/* inline paging arrows (revealed on hover) */
.eu-gallery-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .92);
  color: var(--main);
  font-size: 15px;
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .18);
  opacity: 0;
  transition: opacity .2s ease, background .2s ease;
}

.eu-gallery:hover .eu-gallery-nav {
  opacity: 1;
}

.eu-gallery-nav:hover {
  background: #fff;
}

.eu-gallery-prev {
  left: 12px;
}

.eu-gallery-next {
  right: 12px;
}

/* photo counter (bottom-right) */
.eu-gallery-count {
  position: absolute;
  right: 12px;
  bottom: 12px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: rgba(0, 0, 0, .62);
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  padding: 6px 11px;
  border-radius: 999px;
  pointer-events: none;
}

.eu-gallery-count i {
  font-size: 15px;
}

@media (max-width: 767px) {

  .eu-gallery,
  .eu-gallery.eu-gallery-single {
    grid-template-columns: 1fr;
    height: 300px;
  }

  .eu-gallery .eu-gallery-side {
    display: none;
  }

  .eu-gallery-nav {
    opacity: 1;
    width: 40px;
    height: 40px;
  }
}

@media (hover: none) {
  .eu-gallery-nav {
    opacity: 1;
  }
}

/* fullscreen lightbox carousel */
.eu-lightbox {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 48px;
  background: rgba(0, 0, 0, .92);
}

.eu-lightbox[hidden] {
  display: none;
}

.eu-lightbox-swiper {
  width: 100%;
  max-width: 1120px;
  height: 100%;
}

.eu-lightbox-swiper .swiper-slide {
  display: flex;
  align-items: center;
  justify-content: center;
}

.eu-lightbox-swiper .swiper-slide img {
  max-width: 100%;
  max-height: 84vh;
  object-fit: contain;
  border-radius: 8px;
}

.eu-lightbox-close {
  position: absolute;
  top: 20px;
  right: 24px;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .16);
  color: #fff;
  font-size: 16px;
  cursor: pointer;
}

.eu-lightbox-close:hover {
  background: rgba(255, 255, 255, .3);
}

.eu-lightbox .swiper-button-next,
.eu-lightbox .swiper-button-prev {
  color: #fff;
}

.eu-lightbox .swiper-pagination {
  color: #fff;
}

.eu-lightbox .swiper-pagination-bullet {
  background: #fff;
}

@media (max-width: 767px) {
  .eu-lightbox {
    padding: 16px;
  }
}

@media (max-width: 991px) {
  .eu-detail-body {
    grid-template-columns: 1fr;
  }
}

/* Material Icons (self-hosted) — used for the property key-spec cards. */
@font-face {
  font-display: swap;
  font-family: 'Material Icons';
  font-style: normal;
  font-weight: 400;
  src: url('../fonts/material-icons-regular.woff2') format('woff2');
}

.material-icons {
  font-family: 'Material Icons';
  font-weight: normal;
  font-style: normal;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  display: inline-block;
  white-space: nowrap;
  word-wrap: normal;
  direction: ltr;
  -webkit-font-feature-settings: 'liga';
  -webkit-font-smoothing: antialiased;
}

.eu-keyspecs {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
  margin: 8px 0 28px;
}

.eu-keyspec {
  border: 1px solid var(--line);
  border-radius: var(--eu-radius);
  padding: 14px;
  text-align: center;
}

.eu-keyspec i {
  font-size: 20px;
  color: var(--primary);
}

.eu-keyspec .eu-keyspec-ic {
  font-size: 26px;
  color: var(--primary);
  line-height: 1;
  vertical-align: middle;
}

.eu-keyspec b {
  display: block;
  font-size: 18px;
  margin-top: 6px;
}

.eu-keyspec span {
  font-size: 12px;
  color: var(--text-2);
}

@media (max-width: 575px) {
  .eu-keyspecs {
    grid-template-columns: repeat(2, 1fr);
  }
}

.eu-spec-table {
  width: 100%;
  border-collapse: collapse;
}

.eu-spec-table th,
.eu-spec-table td {
  text-align: left;
  padding: 11px 0;
  border-bottom: 1px solid var(--line);
  font-size: 14px;
}

.eu-spec-table th {
  color: var(--text-2);
  font-weight: 500;
  width: 45%;
}

.eu-amenities {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px 20px;
}

.eu-amenities .am {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
}

.eu-amenities .am i {
  color: var(--primary);
}

@media (max-width: 575px) {
  .eu-amenities {
    grid-template-columns: repeat(2, 1fr);
  }
}

.eu-map {
  border-radius: var(--eu-radius);
  overflow: hidden;
  border: 1px solid var(--line);
}

.eu-map iframe {
  display: block;
  width: 100%;
  height: 380px;
  border: 0;
}

/* compact map preview inside the listing form */
.eu-map-sm iframe {
  height: 260px;
}

.eu-map-label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-2);
  margin-bottom: 4px;
}

.eu-map-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 160px;
  padding: 0 20px;
  text-align: center;
  color: var(--text-2);
  font-size: 14px;
}

/* land/building registry + street-view links under Details / Location */
.eu-registry-links {
  display: flex;
  flex-wrap: wrap;
  gap: 18px 28px;
  margin-top: 16px;
}

/* tabbed "Additional info" feature checkboxes (add-listing form) */
.eu-ftabs {
  margin-top: 6px;
}

.eu-ftab-btns {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 14px;
  background: var(--eu-soft);
  border-radius: 999px;
  padding: 4px;
}

.eu-ftab-panel {
  display: none;
}

.eu-ftab-panel.active {
  display: block;
}

.eu-ftab-lead {
  margin-bottom: 12px;
}

.eu-ftab-checks {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 4px 20px;
}

@media (max-width: 767px) {
  .eu-ftab-checks {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* contact agent + notary (sticky aside) */
.eu-aside {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.eu-panel {
  border: 1px solid var(--line);
  border-radius: var(--eu-radius);
  padding: 20px;
  box-shadow: var(--eu-shadow-sm);
}

.eu-agent {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 14px;
}

.eu-agent img {
  width: 54px;
  height: 54px;
  border-radius: 50%;
  object-fit: cover;
}

.eu-agent b {
  display: block;
}

.eu-agent span {
  font-size: 13px;
  color: var(--text-2);
}

.eu-panel h3 {
  font-size: 16px;
  font-weight: 700;
  margin: 0 0 14px;
}

.eu-field-row {
  margin-bottom: 12px;
}

.eu-field-row label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-2);
  margin-bottom: 4px;
}

/* color is an override, not a default: styles.css paints every input --text-2, the
   same grey it gives placeholders, so what the user typed read as washed-out as the
   hint it replaced. Placeholders keep that grey through their own ::placeholder rule
   and are unaffected. */
.eu-field-row input:not([type="checkbox"]):not([type="radio"]),
.eu-field-row textarea,
.eu-field-row select {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 10px 12px;
  font: inherit;
  color: var(--main);
}

.eu-field-row select {
  height: 44px;
  padding: 0 12px;
  background: #fff;
  cursor: pointer;
}

.eu-field-row input:focus,
.eu-field-row textarea:focus,
.eu-field-row select:focus {
  outline: none;
  border-color: var(--main);
}

/* The enquiry form's submit button. .tf-btn is inline-flex with align-items only —
   sized for auto-width buttons, so adding w-100 stretches the box while leaving the
   label parked at flex-start: 25px of space on its left and 126px on its right.
   Centre it at both widths; the button is already full-width, so this is the label,
   not the box. Same fix the mobile menu's w-100 buttons carry in navbar.php. */
#eu-pd-contact-form > button {
  justify-content: center;
}

/* Password reveal control. eurore-forms.js wraps an [data-password-toggle] input in
   .eu-password and appends the button, so the markup below only exists where JS ran. */
.eu-password {
  position: relative;
}

/* Room for the button. The :not() pair is not decoration — it matches the specificity
   of the .eu-field-row input rule above, which would otherwise reset the padding. */
.eu-field-row .eu-password input:not([type="checkbox"]):not([type="radio"]) {
  padding-right: 44px;
}

/* Edge/IE draw their own reveal control; two eyes in one field is one too many. */
.eu-password input::-ms-reveal,
.eu-password input::-ms-clear {
  display: none;
}

.eu-password-toggle {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  padding: 0;
  border: 0;
  border-radius: 0 6px 6px 0;
  background: none;
  color: var(--text-2);
  cursor: pointer;
}

.eu-password-toggle:hover {
  color: var(--main);
}

.eu-password-toggle:focus-visible {
  outline: 2px solid var(--main);
  outline-offset: -2px;
}

/* a per-field "show on listing" toggle nested under its input — keep the label inline
   (not the block field-label style); the checkbox keeps its own .tf-check sizing */
.eu-field-row .eu-check {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-2);
  margin: 8px 0 0;
  padding: 0;
}

.eu-notary-list {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
}

.eu-notary-list li {
  font-size: 14px;
  color: var(--main);
  padding: 5px 0;
  border-top: 1px solid var(--line);
}

.eu-notary-list li span {
  display: inline-block;
  min-width: 64px;
  color: var(--text-2);
  font-size: 12px;
}

.eu-notary-list a {
  color: var(--primary);
}

/* ============================================================================
 * Brokers
 * ==========================================================================*/
/* The placeholder for a card with no image — without it the empty span collapses
   the media box. */
.eu-card-noimage {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--eu-soft);
}

.eu-broker-card {
  display: flex;
  flex-direction: column;
  text-align: center;
  border: 1px solid var(--line);
  border-radius: var(--eu-radius);
  padding: 24px;
}

/* .eu-grid already stretches every card in a row to the tallest, but the button
   followed whatever content the broker happened to have — a missing agency line or
   a one-line meta left it floating mid-card, up to 74px adrift of its neighbours.
   margin-top:auto inside the column flex box above parks it on the card's floor, so
   a row's buttons share a line whichever fields are filled in.

   justify-content because .tf-btn is inline-flex with align-items only: w-100
   stretches the box and leaves the label at flex-start (25px of space on its left
   against 158px on its right). Same fix the enquiry form's submit carries. */
.eu-broker-card .tf-btn {
  margin-top: auto;
  justify-content: center;
}

.eu-broker-card img {
  width: 96px;
  height: 96px;
  border-radius: 50%;
  object-fit: cover;
  margin: 0 auto 14px;
}

.eu-broker-card b {
  display: block;
  font-size: 17px;
}

.eu-broker-card .agency {
  color: var(--text-2);
  font-size: 14px;
}

.eu-broker-card .meta {
  margin: 12px 0;
  font-size: 13px;
  color: var(--text);
}

.eu-broker-profile {
  display: grid;
  grid-template-columns: 320px 1fr;
  gap: 32px;
  align-items: start;
}

@media (max-width: 767px) {
  .eu-broker-profile {
    grid-template-columns: 1fr;
  }
}

/* Photoless broker avatar — initials on a tinted circle, so a broker with no
   uploaded photo gets a real placeholder rather than a broken image (#39). Sized
   to match .eu-broker-card img (directory) and .eu-bp-photo (profile). */
.eu-broker-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 96px;
  height: 96px;
  margin: 0 auto 14px;
  border-radius: 50%;
  background: var(--eu-soft, #eef1f4);
  color: var(--text-2, #6b7280);
  font-size: 30px;
  font-weight: 700;
  line-height: 1;
}

/* The profile's photo/avatar is larger than the directory card's (the prototype
   used inline styles for these). */
.eu-bp-photo {
  width: 140px;
  height: 140px;
  border-radius: 50%;
  margin: 0 auto 16px;
}

img.eu-bp-photo {
  display: block;
  object-fit: cover;
}

.eu-broker-avatar.eu-bp-photo {
  font-size: 44px;
}

.eu-bp-name {
  font-size: 22px;
  margin: 0 0 4px;
}

.eu-bp-meta {
  margin: 12px 0;
  font-size: 13px;
}

/* ============================================================================
 * Dashboard content (rendered inside ecomus .my-account-content)
 * ==========================================================================*/
.eu-stat-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 18px;
}

@media (max-width: 991px) {
  .eu-stat-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

.eu-stat {
  border: 1px solid var(--line);
  border-radius: var(--eu-radius);
  padding: 20px;
}

.eu-stat .num {
  font-size: 30px;
  font-weight: 800;
}

.eu-stat .lbl {
  color: var(--text-2);
  font-size: 13px;
}

.eu-table {
  width: 100%;
  border-collapse: collapse;
}

.eu-table th,
.eu-table td {
  padding: 14px 12px;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: middle;
  font-size: 14px;
}

.eu-table th {
  color: var(--text-2);
  font-weight: 600;
}

/* center the Actions column so the icon buttons line up under the header */
.eu-table th:last-child,
.eu-table td:last-child {
  text-align: center;
}

/* listing row image + id */
.eu-row-thumb {
  width: 64px;
  height: 44px;
  object-fit: cover;
  border-radius: 6px;
  display: block;
}

.eu-row-id {
  color: var(--text-2);
  font-size: 13px;
  white-space: nowrap;
}

.eu-tag {
  font-size: 11px;
  font-weight: 700;
  line-height: 1.25;
  padding: 2px 11px;
  border-radius: 999px;
  color: var(--main);
  background: #fff;
  border: 1px solid var(--line);
}

.eu-tag.draft,
.eu-tag.rent {
  background: #fff;
  color: var(--main);
}

/* row action icon buttons (edit / delete) */
.eu-row-actions {
  display: inline-flex;
  gap: 4px;
}

.eu-action-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 6px;
  color: var(--text-2);
}

.eu-action-icon:hover {
  background: var(--eu-soft);
  color: var(--main);
}

.eu-action-icon.js-del:hover {
  color: var(--primary);
}

.eu-action-icon i {
  font-size: 16px;
}

.eu-action-icon .material-icons {
  font-size: 18px;
}

/* dashboard sidebar nav — compact, borderless list like the search filter menu */
/* size the nav to its widest item (plus a little breathing room) so the hover/active
   highlight hugs the labels instead of stretching across the full sidebar column */
.my-account-nav {
  gap: 2px;
  width: fit-content;
  min-width: 180px;
  max-width: 100%;
}

.my-account-nav .my-account-nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  border: 0;
  border-radius: 6px;
  padding: 9px 12px;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.4;
  color: var(--main);
}

.my-account-nav .my-account-nav-item::before {
  display: none;
}

/* The logout item is a <button> (#42) — reset it to match the anchor nav items. */
.my-account-nav button.my-account-nav-item {
  width: 100%;
  background: none;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
}

/* My-listings management table (#43) */
.eu-table-wrap {
  padding: 0;
  overflow-x: auto;
}

.eu-listings-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}

.eu-listings-table th {
  text-align: left;
  padding: 12px 14px;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-2);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}

.eu-listings-table td {
  padding: 12px 14px;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
}

.eu-listings-table tr:last-child td {
  border-bottom: 0;
}

/* 64px thumbnail + the 14px cell padding on each side. Sized to the content box,
   because the img's max-width:100% otherwise clamps it to whatever is left. */
.eu-col-thumb {
  width: 92px;
}

/* .eu-row-thumb is defined once, above, at the reference's 64x44. A second
   definition used to sit here at 56x42 and — equal specificity, later in the
   file — silently won, shrinking every dashboard thumbnail below the mock. */

.eu-row-thumb-empty {
  background: var(--eu-soft);
}

.eu-row-title {
  font-weight: 600;
  color: var(--main);
}

.eu-row-id {
  display: block;
  font-size: 12px;
  color: var(--text-2);
}

/* The dashboard tables give the listing id its own column (as the reference
   does), rather than stacking it under the title like .eu-row-id. */
.eu-col-id {
  font-size: 13px;
  color: var(--text-2);
  white-space: nowrap;
}

.eu-row-price {
  white-space: nowrap;
  font-weight: 600;
}

.eu-status-badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

.eu-status-active { background: #e5f6ec; color: #1a7f43; }
.eu-status-draft { background: #eef1f6; color: #5a6b85; }
.eu-status-reserved { background: #fff3e0; color: #a35b00; }
.eu-status-sold { background: #fdeaea; color: #b3261e; }
.eu-status-archived { background: #eeeeee; color: #777777; }

/* The th is listed explicitly: `.eu-listings-table th` sets text-align:left and
   outranks a lone `.eu-col-actions` on specificity (0,1,1 vs 0,1,0), which left
   the "Actions" heading aligned to the left of the buttons it labels. */
.eu-col-actions,
.eu-listings-table th.eu-col-actions {
  text-align: right;
  white-space: nowrap;
}

.eu-row-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: #fff;
  color: var(--text-2);
  cursor: pointer;
  margin-left: 6px;
}

.eu-row-action:hover {
  background: var(--eu-soft);
  color: var(--main);
}

.eu-row-action .material-icons {
  font-size: 18px;
}

.eu-listing-delete:hover {
  color: #b3261e;
  border-color: #f0caca;
}

.my-account-nav .my-account-nav-item .eu-nav-ic {
  font-size: 19px;
  color: var(--text-2);
  flex-shrink: 0;
}

.my-account-nav .my-account-nav-item:hover {
  background: var(--eu-soft);
  color: var(--main);
}

.my-account-nav .my-account-nav-item.active {
  background: var(--eu-soft);
  color: var(--primary);
  font-weight: 600;
}

.my-account-nav .my-account-nav-item:hover .eu-nav-ic,
.my-account-nav .my-account-nav-item.active .eu-nav-ic {
  color: var(--primary);
}

/* the nav now hugs its labels, so shrink the account sidebar column to it and give
   the freed width to the content column (all dashboard pages share this row layout) */
@media (min-width: 992px) {
  .row:has(> .col-lg-3 > .wrap-sidebar-account)>.col-lg-3 {
    flex: 0 0 auto;
    width: auto;
  }

  .row:has(> .col-lg-3 > .wrap-sidebar-account)>.col-lg-9 {
    flex: 1 1 0%;
    max-width: none;
  }
}

/* Listing statistics (Statistics tab) */
.eu-stats-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 18px;
  font-size: 14px;
  color: var(--text-2);
}

.eu-stats-bar select {
  height: 38px;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 0 10px;
  font: inherit;
  font-weight: 600;
  color: var(--main);
  background: #fff;
}

.eu-row-sub {
  font-size: 12px;
  color: var(--text-2);
  margin-top: 3px;
}

.eu-stat-mini {
  width: 100%;
  border-collapse: collapse;
}

.eu-stat-mini th,
.eu-stat-mini td {
  padding: 11px 10px;
  border-bottom: 1px solid var(--line);
  font-size: 14px;
  text-align: right;
}

.eu-stat-mini tr:last-child td {
  border-bottom: none;
}

.eu-stat-mini th:first-child,
.eu-stat-mini td:first-child {
  text-align: left;
  color: var(--text-2);
  font-weight: 500;
}

.eu-stat-mini th {
  font-size: 12px;
  color: var(--text-2);
  font-weight: 600;
}

.eu-stat-mini td {
  font-weight: 700;
  color: var(--main);
}

.eu-chart-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 26px;
  margin-bottom: 4px;
  flex-wrap: wrap;
}

.eu-chart-title {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-2);
  text-transform: uppercase;
  letter-spacing: .03em;
}

.eu-chart-tabs {
  display: inline-flex;
  gap: 4px;
  background: var(--eu-soft);
  border-radius: 999px;
  padding: 4px;
}

.eu-chart-tabs button {
  border: none;
  background: none;
  padding: 5px 12px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
}

.eu-chart-tabs button.active {
  background: var(--primary);
  color: #fff;
}

.eu-chart-scroll {
  overflow-x: auto;
  padding-bottom: 4px;
}

.eu-chart-inner {
  display: flex;
  gap: 5px;
  align-items: flex-end;
  min-width: 100%;
  padding-top: 10px;
}

.eu-bar-col {
  flex: 1 0 30px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.eu-bar-track {
  position: relative;
  height: 150px;
  width: 100%;
  max-width: 46px;
  display: flex;
  align-items: flex-end;
}

.eu-bar {
  width: 100%;
  background: var(--primary);
  opacity: .85;
  border-radius: 3px 3px 0 0;
  min-height: 3px;
  transition: opacity .15s ease;
}

.eu-bar-col:hover .eu-bar {
  opacity: 1;
}

.eu-bar-val {
  position: absolute;
  left: 50%;
  transform: translate(-50%, -4px);
  font-size: 10px;
  font-weight: 700;
  color: var(--main);
  white-space: nowrap;
  line-height: 1;
}

.eu-bar-date {
  font-size: 10px;
  color: var(--text-2);
  white-space: nowrap;
}

.eu-form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

@media (max-width: 575px) {
  .eu-form-grid {
    grid-template-columns: 1fr;
  }
}

.eu-form-grid .full {
  grid-column: 1 / -1;
}

/* Owner add/edit form: compact auto-fitting fields so short inputs aren't full-width
   (long fields like Title/Address/Description keep .full to span the whole row). */
#eu-listing-form .eu-form-grid {
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

/* Owner add/edit form — the per-language Content pane (title + description).

   Hidden by CLASS, deliberately not by the `hidden` attribute:
   EuroreForms.pickLive() skips any control inside a [hidden] ancestor, so a
   validation error on the inactive language would resolve to the wrong input and
   mark a field the owner can see for a value they cannot. */
.eu-lang-tabs {
  margin-bottom: 10px;
}

.eu-lang-tabs .eu-tab {
  padding: 6px 16px;
  font-size: 13px;
}

.eu-lang-pane {
  display: none;
}

.eu-lang-pane.is-active {
  display: block;
}

/* Owner add/edit form — amenity checkbox groups (#43/#44): a group heading over a
   compact, auto-fitting grid of checkboxes (not the mock's JS pill-tabs). */
.eu-amenity-group {
  margin-bottom: 14px;
}

.eu-amenity-legend {
  font-size: 14px;
  font-weight: 700;
  margin: 12px 0 8px;
}

.eu-amenity-checks {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 6px 16px;
}

.eu-form-submit {
  margin-top: 20px;
}

/* A field that should not stretch to the full grid column (e.g. the short Status
   select), so it doesn't read as a huge input. */
.eu-field-narrow {
  max-width: 220px;
}

/* Country + City searchable dropdowns (#43/#44): a combobox <input> carrying a caret
   (so it reads as a dropdown) over an absolutely-positioned results list anchored to
   the combo wrapper. */
.eu-combo {
  position: relative;
}

.eu-combo-input {
  cursor: pointer; /* readonly display field that opens the dropdown */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none' stroke='%23666' stroke-width='1.5'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 34px;
}

.eu-combo-input:disabled {
  opacity: .6;
  cursor: not-allowed;
}

/* The dropdown: a search box over a scrollable option list. */
.eu-combo-panel {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 20;
  margin-top: 2px;
  overflow: hidden;
  background: var(--eu-surface, #fff);
  border: 1px solid var(--line);
  border-radius: var(--eu-radius, 8px);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .12);
}

.eu-combo-panel[hidden] {
  display: none;
}

.eu-combo-search {
  display: block;
  box-sizing: border-box;
  width: calc(100% - 16px);
  margin: 8px;
  padding: 7px 10px;
  font-size: 14px;
  border: 1px solid var(--line);
  border-radius: 6px;
}

.eu-combo-list {
  margin: 0;
  padding: 4px 0;
  list-style: none;
  max-height: 240px;
  overflow-y: auto;
}

.eu-combo-option {
  padding: 8px 14px;
  cursor: pointer;
  font-size: 14px;
}

.eu-combo-option:hover,
.eu-combo-option.is-active {
  background: var(--eu-soft, #f4f5f7);
}

.eu-uploader {
  border: 2px dashed var(--line);
  border-radius: var(--eu-radius);
  padding: 34px;
  text-align: center;
  color: var(--text-2);
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}

.eu-uploader:hover,
.eu-uploader:focus-visible,
.eu-uploader.is-dragover {
  border-color: var(--primary);
  background: var(--eu-soft);
  outline: none;
}

.eu-photo-previews {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 10px;
  margin-top: 14px;
}

.eu-photo-previews:empty {
  display: none;
}

.eu-photo-thumb {
  position: relative;
  aspect-ratio: 4 / 3;
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid var(--line);
}

.eu-photo-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* The profile picture's preview (#48) — the round broker avatar carrying the same
   delete control a listing thumb does. It exists only to give .eu-photo-remove
   something to anchor to: the width matches .eu-bp-photo, so the button lands on
   the circle's edge rather than at the far side of the form row. */
.eu-photo-avatar {
  position: relative;
  width: 140px;
  margin: 0 auto 16px;
}

/* .eu-bp-photo carries its own centring margin for the broker page; inside the
   wrapper the wrapper owns that, or the two stack up. */
.eu-photo-avatar .eu-bp-photo {
  margin: 0;
}

/* Delete control on an owner photo thumb (#43/#44) and on the profile picture (#48). */
.eu-photo-remove {
  position: absolute;
  top: 4px;
  right: 4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, .6);
  color: #fff;
  cursor: pointer;
  transition: background .15s ease;
}

.eu-photo-remove:hover,
.eu-photo-remove:focus-visible {
  background: #db1215;
  outline: none;
}

.eu-photo-remove .material-icons {
  font-size: 16px;
}

/* small utilities */
.eu-muted {
  color: var(--text-2);
}

.eu-mt-0 {
  margin-top: 0;
}

/* ---- property detail (#36) ---------------------------------------------- */

/* Amenity group heading. pc_get_listing_features() groups the features the way
   the admin grouped them, so the headings come along; the prototype rendered one
   flat list. */
.eu-amenities-group {
  font-size: 15px;
  font-weight: 700;
  margin: 18px 0 10px;
}

.eu-amenities-group:first-child {
  margin-top: 0;
}

/* An in-flow status line that belongs beside the thing it describes rather than in
   the toast layer: the photo dropzone's running summary ("2 photos ready — uploaded
   when you publish."), and the static confirmation panels on register/reset-password.
   Transient form outcomes are toasts (.eu-toast below), not this. */
.eu-form-status {
  font-size: 13px;
  margin: 10px 0 0;
}

/* A resolved outcome reads as a notification, not as a stray line of text: the
   box is attached to the state classes rather than the base, so transient
   progress messages ("Signing in…") stay plain and only success/failure get the
   weight. Every form on the site shares .eu-form-status, so error messages that
   were previously bare red text pick this up too. */
.eu-form-status.is-error,
.eu-form-status.is-success {
  padding: 10px 12px;
  border-radius: 6px;
  border: 1px solid transparent;
  font-weight: 500;
}

.eu-form-status.is-error {
  color: #b3261e;
  background: #fdeaea;
  border-color: #f3c9c9;
}

.eu-form-status.is-success {
  color: #1e7b34;
  background: #e9f6ed;
  border-color: #c2e3cd;
}

/* ---- "How was this listing sold?" ---------------------------------------- *
 * Opened by eurore-dashboard.js when the listing form's status is set to Sold.
 * Hand-rolled rather than borrowed: the dashboard carries no Bootstrap JS, and
 * this is the only dialog on the storefront side.
 *
 * z-index sits below the toast layer (10000) on purpose — a save that fails
 * while the dialog is somehow still open must not have its message hidden by it.
 * -------------------------------------------------------------------------- */
.eu-sold-modal {
  position: fixed;
  inset: 0;
  z-index: 9990;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

/* [hidden] loses to the display:flex above — every browser resolves the more
   specific rule, not the attribute. Restate it. */
.eu-sold-modal[hidden] {
  display: none;
}

.eu-sold-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, .45);
}

.eu-sold-modal-dialog {
  position: relative;
  width: 100%;
  max-width: 420px;
  padding: 24px;
  border-radius: var(--eu-radius);
  background: #fff;
  box-shadow: var(--eu-shadow);
  text-align: center;
}

.eu-sold-modal-dialog h3 {
  margin: 0 0 8px;
  font-size: 18px;
}

.eu-sold-modal-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 18px 0 12px;
}

/* The theme's .tf-btn is itself display:flex with no justification, so the
   text-align on the dialog above cannot reach the label — it lands at the flex
   start instead. These two answers are full-width by design (they stack), which is
   exactly the case where that shows, so they centre themselves. */
.eu-sold-modal-actions .tf-btn {
  justify-content: center;
  align-items: center;
}

/* A skip that reads as a way out, not as a third answer sitting beside the two
   real ones — the question is optional and the control should look it. */
.eu-sold-modal-skip {
  border: 0;
  background: none;
  padding: 4px;
  font-size: 13px;
  text-decoration: underline;
  color: #6b6b6b;
  cursor: pointer;
}

/* ---- toasts -------------------------------------------------------------- *
 * Form outcomes, pinned to the top of the viewport. Inline they were unreliable:
 * the add-listing form is ~4,000px tall, so a message rendered at the top of the
 * form sat three screens above the submit button that produced it.
 *
 * The bar deliberately matches the platform's alert style (core's .pc-alert, as
 * used on rawedge): full width at the very top, centred white text on a solid
 * success/error fill. The behaviour differs on purpose — each message owns its own
 * timer, errors stay until they are dismissed, and every bar carries a close
 * control — none of which .pc-alert supports.
 *
 * z-index clears everything it can land on top of — the sticky header (888), core's
 * own #pc-alert bar (1050) and the property lightbox (9999).
 * -------------------------------------------------------------------------- */
.eu-toasts {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 10000;
  display: flex;
  flex-direction: column;
  /* The empty layer spans the full width and would otherwise swallow clicks on the
     header beneath it; each bar takes its own back. */
  pointer-events: none;
}

.eu-toast {
  pointer-events: auto;
  position: relative;
  padding: .6rem 44px;
  color: #fff;
  text-align: center;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.5;
  animation: eu-toast-in .18s ease-out;
}

.eu-toast.is-error {
  background-color: var(--bs-danger, #dc3545);
}

.eu-toast.is-success {
  background-color: var(--bs-success, #198754);
}

/* Transient progress ("Sending…", "Signing in…"). Core's alert has no such state;
   a neutral dark bar keeps it from reading as an outcome either way. */
.eu-toast.is-info {
  background-color: var(--bs-dark, #212529);
}

/* Absolute so the message stays optically centred in the bar regardless of the
   button. 24x24 minimum hit area, per WCAG 2.2 target size. */
.eu-toast-close {
  position: absolute;
  top: 50%;
  right: 12px;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: inherit;
  opacity: .8;
  cursor: pointer;
}

.eu-toast-close:hover,
.eu-toast-close:focus-visible {
  opacity: 1;
}

@keyframes eu-toast-in {
  from { opacity: 0; transform: translateY(-100%); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .eu-toast {
    animation: none;
  }
}

/* Required marker, derived from the control rather than typed into the label.
   Hand-written asterisks drift the moment a rule changes — three labels carried
   one and a dozen equally-required fields did not — so the mark follows the
   `required` attribute and cannot disagree with the form.
   aria-hidden is not needed: generated content is not exposed as text, and the
   control's own `required` is what a screen reader announces.
   The combos (country, city) are deliberately absent: both are `nullable` in
   StoreListingRequest, so a marker on those rows would promise a rule the server
   does not enforce. */
.eu-field-row:has(input[required], select[required], textarea[required]) > label::after {
  content: " *";
  color: #db1215;
}

/* Required marker on a section heading, for requirements the browser cannot show
   natively — a photo grid has no input to hang `required` off. Same red as the
   error state, so "this is missing" reads consistently across the form. */
.eu-required {
  margin-left: 2px;
  color: #b3261e;
}

/* Per-field validation errors (#48). Each .eu-field-row can carry one slot,
   which EuroreForms unhides and fills from Laravel's errors map, so a submit
   that breaks three fields marks all three instead of naming one. */
.eu-field-error {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  color: #db1215;
}

/* The offending control has to be findable at a glance on a form with sixty of
   them, so the mark is a ring and a tint, not just a recoloured hairline border —
   at 1px against --line it was nearly invisible. box-shadow rather than a wider
   border so nothing reflows when the mark appears.
                        ↓ mirrors the :not() pair on the base .eu-field-row input
   rule above. Without them that rule is the more specific of the two and keeps its
   grey border, so the field showed a red ring around a grey box. */
.eu-field-row input.is-invalid:not([type="checkbox"]):not([type="radio"]),
.eu-field-row textarea.is-invalid,
.eu-field-row select.is-invalid,
.eu-field-row .eu-combo-input.is-invalid {
  border-color: #db1215;
  background-color: #fff6f6;
  box-shadow: 0 0 0 3px rgba(219, 18, 21, .16);
}

/* The invalid ring must survive focus, or clicking into the field to fix it
   removes the only marker saying which field was wrong. */
.eu-field-row input.is-invalid:not([type="checkbox"]):not([type="radio"]):focus,
.eu-field-row textarea.is-invalid:focus,
.eu-field-row select.is-invalid:focus,
.eu-field-row .eu-combo-input.is-invalid:focus {
  border-color: #db1215;
}

/* Its label goes red too — the pairing is what makes the field scannable when the
   ring itself is off to the side of a two-column grid. */
.eu-field-row:has(.is-invalid) > label {
  color: #db1215;
}

/* A heading that divides one form into labelled groups (profile: details vs
   password), sitting inside .eu-panel rather than above it. */
.eu-form-section-title {
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .03em;
  color: var(--text-2);
  margin: 26px 0 4px;
}

.eu-logout-panel {
  margin-top: 18px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}

/* ---- My notaries --------------------------------------------------------- *
 * A management table, not a stack of forms: the per-owner cap is a setting and
 * is expected to grow, so the book has to stay scannable at fifty rows, and
 * adding or editing one is a page of its own (dashboard/add-notary,
 * dashboard/notaries/{id}/edit) rather than a row that expands in place.
 *
 * The table furniture is shared with My listings (.eu-listings-table) so the two
 * management screens read as one surface; what is left here is the head row, the
 * filter, the notices, and the form page's own bits.
 * -------------------------------------------------------------------------- */

/* Quota counter + the Add button, together at the right of the section head. */
.eu-notary-head-actions {
  display: flex;
  align-items: center;
  gap: 16px;
  flex: 0 0 auto;
}

/* The theme gives .tf-btn a 20px top margin, which this row already spaces. */
.eu-notary-head-actions .tf-btn { margin: 0; }

/* The filter hides rows with the `hidden` attribute. On a table row the UA's
   [hidden] { display: none } is a weak rule that the theme's own display rules
   can outrank, so the intent is stated here rather than assumed. */
.eu-listings-table tr[hidden] { display: none; }

/* The "used on N listings" cell — a count, never worth wrapping. */
.eu-notary-usage {
  white-space: nowrap;
  color: var(--text-2, #6b6b6b);
}

/* Warns, above the fields, that saving is not local to this record. */
.eu-notary-hint {
  font-size: 13px;
  color: var(--text-2, #6b6b6b);
  margin: 0 0 18px;
}

.eu-notary-actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  align-items: center;
  margin-top: 18px;
}

/* The theme gives .tf-btn a 20px top margin, which the row already provides. */
.eu-notary-actions .tf-btn { margin: 0; }

.eu-notary-filter {
  margin-bottom: 14px;
}

.eu-notary-filter input {
  width: 100%;
  padding: 10px 14px;
  border: 1px solid var(--line, #e6e6e6);
  border-radius: 8px;
  font-size: 14px;
}

.eu-notary-empty {
  font-size: 13px;
  color: var(--text-2, #6b6b6b);
  margin: 10px 0 0;
}

.eu-notary-blank {
  margin-bottom: 18px;
}

/* Screen-reader-only label for the filter, which is placeholder-labelled visually. */
.eu-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Narrow screens: the counter sits above the button instead of beside it, so the
   pair stops squeezing the intro next to it. The table itself scrolls sideways
   inside .eu-table-wrap, exactly as My listings already does. */
@media (max-width: 767px) {
  .eu-notary-head-actions {
    flex-direction: column;
    align-items: flex-end;
    gap: 8px;
  }
}

/* The saved-notary picker on the listing form, and the line that appears when
   typing detaches a listing from one. */
.eu-notary-picker-note {
  font-size: 13px;
  color: var(--text-2);
  margin: 6px 0 0;
}

.eu-notary-picker-note.is-detached {
  color: var(--brand, #1c6ea4);
}

/* ---- print (#36) --------------------------------------------------------- *
 * The prototype shipped a print button with no print stylesheet, so it printed
 * the nav, the footer, the toolbar and a hidden lightbox over the top. A printed
 * listing is a leave-behind: the photo, the facts and the agent, plus the URL to
 * get back to it (paper carries no hyperlinks).
 * -------------------------------------------------------------------------- */
@media print {
  /* The real storefront skeleton, not the prototype's: it used #site-header /
     #site-footer placeholders that JS replaced, and neither id exists here. */
  .eu-topbar,
  #header,
  #mobileMenu,
  .eu-crumbbar,
  #footer,
  #pc-alert,
  .eu-toasts,
  .eu-lightbox,
  .eu-gallery-nav,
  .eu-gallery-count,
  .eu-back,
  .eu-aside form,
  .eu-section .eu-section-head,
  #eu-pd-similar {
    display: none !important;
  }

  /* The map is a cross-origin iframe: it prints as an empty grey box at best. */
  .eu-map {
    display: none !important;
  }

  body {
    background: #fff;
    color: #000;
  }

  /* Side by side wastes the page; the aside becomes a footer block. */
  .eu-detail-body {
    display: block;
  }

  .eu-gallery {
    grid-template-columns: 1fr;
  }

  .eu-gallery-side {
    display: none;
  }

  .eu-keyspecs {
    grid-template-columns: repeat(4, 1fr);
  }

  /* Keep rows and cards whole across a page break. */
  .eu-spec-table tr,
  .eu-panel,
  .eu-keyspec {
    break-inside: avoid;
  }

  /* Paper has no address bar — print the URL so the sheet is traceable back. */
  .eu-detail-head h1::after {
    content: " (" attr(data-eu-url) ")";
    font-size: 12px;
    font-weight: 400;
    word-break: break-all;
  }
}

/* ----- Cookie consent banner -----
   Core's Silktide component ships its own consent.css, injected by
   pc_render_consent() in the footer — so it loads AFTER this file and wins on
   equal specificity. Every rule below therefore carries both wrapper ids to
   out-specify it. Core stays untouched: the component already exposes CSS
   custom properties and stable class names, which is the seam this uses. */
html #silktide-wrapper {
  --fontFamily: "Albert Sans", sans-serif;
  --primaryColor: var(--primary);
  --textColor: var(--text);
  --backgroundColor: var(--white);
  --cookieIconColor: var(--primary);
  /* consent.js focuses the accept button the moment the banner opens, so core's
     white/black/white ring is painted before anyone has touched a key and reads
     as a stray border. Suppressed by request. Restore a keyboard cue by giving
     this token a shadow again, e.g.
     --focus: 0 0 0 2px var(--white), 0 0 0 4px var(--primary); */
  --focus: none;
}

/* Shared pill geometry, copied from .tf-btn so the consent actions measure the
   same as every other button on the page. */
#silktide-wrapper #silktide-banner .st-button,
#silktide-wrapper #silktide-modal .st-button {
  font-family: "Albert Sans", sans-serif;
  font-size: 14px;
  line-height: 16px;
  font-weight: 500;
  padding: 14px 24px;
  border: 1px solid transparent;
  border-radius: 999px;
  transition: all 0.3s ease;
}

/* Core marks accept AND reject as .st-button--primary, so both render as the
   same solid block. The site's language is one filled action beside one
   outline, so they are split here by their functional classes. */
#silktide-wrapper #silktide-banner .accept-all,
#silktide-wrapper #silktide-modal .preferences-accept-all {
  background-color: var(--primary);
  border-color: var(--primary);
  color: var(--white);
}

#silktide-wrapper #silktide-banner .accept-all:hover,
#silktide-wrapper #silktide-modal .preferences-accept-all:hover {
  background-color: #b50f12;
  border-color: #b50f12;
}

/* Reject reads as .btn-outline: black hairline on white, red on hover. */
#silktide-wrapper #silktide-banner .reject-all,
#silktide-wrapper #silktide-modal .preferences-reject-all {
  background-color: var(--white);
  border-color: var(--main);
  color: var(--main);
}

#silktide-wrapper #silktide-banner .reject-all:hover,
#silktide-wrapper #silktide-modal .preferences-reject-all:hover {
  background-color: var(--white);
  border-color: var(--primary);
  color: var(--primary);
}

/* Core rounds the focus ring to 5px, which clips the corners off a pill. */
#silktide-wrapper #silktide-banner .st-button:focus,
#silktide-wrapper #silktide-modal .st-button:focus {
  border-radius: 999px;
}

/* Preferences is a text action, not a third button — .btn-line's underlined
   black label going red on hover. */
#silktide-wrapper #silktide-banner .preferences {
  font-family: "Albert Sans", sans-serif;
  font-size: 14px;
  font-weight: 500;
  color: var(--main);
}

#silktide-wrapper #silktide-banner .preferences span:hover {
  color: var(--primary);
}
/* ----- reCAPTCHA badge ----------------------------------------------------
   Google's floating "protected by reCAPTCHA" widget, hidden site-wide by
   request. It is injected into the body by api.js on every page that loads
   the script (the property enquiry form and the CMS contact-form section).

   .grecaptcha-badge is the only handle we have: the visible chrome inside it
   (.rc-anchor, .rc-anchor-normal-footer) lives in a cross-origin iframe served
   from google.com/recaptcha/api2/anchor, so no rule here can reach it.

   visibility, not display: api.js keeps measuring and repositioning the badge
   (note the inline `transition: right` it sets), and display:none has been
   known to upset that. Hidden either way, and the widget still works —
   verification is unaffected, only the badge is invisible.

   NOTE: Google's terms allow hiding the badge ONLY if the form instead shows
   the "protected by reCAPTCHA / Privacy Policy / Terms of Service" wording.
   That text is NOT on the forms yet. */
.grecaptcha-badge {
  visibility: hidden;
}
