/* ==========================================================================
   Dreamstay - own design system. No framework, no Elementor CSS.
   Tokens and base typography are the real values measured from the original
   site (Astra inline CSS + per-page Elementor CSS): palette
   #065a60 / #415a77 / #0F172A / #212245 / #eaf4f4, Montserrat body,
   Adamina headings (h1 88/700/1.4 uppercase, h2 46/700/1.3 uppercase),
   Astra container 1240px, Elementor content width 1140px.
   Normalized pages carry their own measured values as CSS custom properties
   (--fs / --pt / --gap / --dir ...); this file only provides the vocabulary.
   ========================================================================== */

@font-face { font-family: 'Montserrat'; font-weight: 400; font-style: normal; font-display: swap; src: url('/assets/fonts/montserrat-400.woff2') format('woff2'); }
@font-face { font-family: 'Montserrat'; font-weight: 500; font-style: normal; font-display: swap; src: url('/assets/fonts/montserrat-500.woff2') format('woff2'); }
@font-face { font-family: 'Montserrat'; font-weight: 600; font-style: normal; font-display: swap; src: url('/assets/fonts/montserrat-600.woff2') format('woff2'); }
@font-face { font-family: 'Montserrat'; font-weight: 700; font-style: normal; font-display: swap; src: url('/assets/fonts/montserrat-700.woff2') format('woff2'); }
/* Self-hosted like Montserrat: the Google Fonts stylesheet cost a cross-origin
   round trip before the font request could even start, so the display face always
   swapped in a beat after first paint. base.php preloads this exact URL. */
@font-face { font-family: 'Adamina'; font-weight: 400; font-style: normal; font-display: swap; src: local('Adamina'), url('/assets/fonts/adamina-400.woff2') format('woff2'); }
/* The preload puts Adamina in the first paint on any normal connection. On a slow
   one the fallback still shows first, so it is metric-matched to Adamina: at 100px
   Georgia measures 605 for "DREAMSTAY" against Adamina's 674 (ratio 1.114) and
   1724 vs 1980 for "PREMIUM APARTMENTS IN TALLINN" (1.149), so 113% splits the
   difference - the late swap then changes glyphs without moving the copy. */
@font-face { font-family: 'Adamina Fallback'; src: local('Georgia'), local('Times New Roman'), local('Liberation Serif'); size-adjust: 113%; }

:root {
  --ds-primary: #065a60;
  --ds-primary-dark: #04494f;
  --ds-accent: #415a77;
  --ds-navy: #212245;
  --ds-text: #212245;
  --ds-muted: #415a77;
  --ds-soft: #eaf4f4;
  --ds-border: #e0e1dd;
  --ds-bg: #ffffff;
  --ds-bg-soft: #f6f9fa;
  --ds-radius: 14px;
  --ds-radius-sm: 9px;
  --ds-shadow: 0 1px 3px rgba(15, 23, 42, .07), 0 4px 16px rgba(15, 23, 42, .06);
  --ds-shadow-lg: 0 12px 40px rgba(15, 23, 42, .16);
  --ds-container: 1140px;
  --ds-container-wide: 1240px;
  --ds-gutter: clamp(20px, 4.5vw, 40px);
  --ds-header-h: 114px;
  --ds-font: 'Montserrat', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --ds-serif: 'Adamina', 'Adamina Fallback', Georgia, 'Times New Roman', serif;
  --ds-whatsapp: #49e670;
  --ds-sec-pad: clamp(44px, 6vw, 80px);
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body { margin: 0; font-family: var(--ds-font); color: var(--ds-text); background: var(--ds-bg); font-size: 16px; line-height: 1.65; -webkit-font-smoothing: antialiased; }
img { max-width: 100%; height: auto; display: block; }
a { color: var(--ds-primary); text-decoration: none; }
a:hover { color: var(--ds-accent); }
h1, h2, h3, h4, h5, h6 { line-height: 1.22; margin: 0 0 .55em; font-weight: 600; }
p { margin: 0 0 1em; }
hr { border: 0; border-top: 1px solid var(--ds-border); margin: 2em 0; }
ul, ol { padding-left: 1.3em; }
.skip-link { position: absolute; left: -9999px; }
.skip-link:focus { left: 8px; top: 8px; background: #fff; padding: 8px 14px; z-index: 999; border-radius: 6px; }
[hidden] { display: none !important; }
@media (max-width: 921px) { html { font-size: 91.2%; } }

.ds-btn { display: inline-block; padding: 13px 28px; border-radius: var(--ds-radius-sm); font-weight: 600; font-size: .95rem; border: 1px solid transparent; cursor: pointer; font-family: inherit; transition: all .18s ease; }
.ds-btn-primary { background: var(--ds-primary); color: #fff; }
.ds-btn-primary:hover { background: var(--ds-primary-dark); color: #fff; }
.ds-btn-ghost { background: transparent; color: var(--ds-primary); border-color: var(--ds-primary); }
.ds-btn-ghost:hover { background: var(--ds-primary); color: #fff; }

/* ==========================================================================
   Header / nav
   ========================================================================== */
.ds-header { position: sticky; top: 0; z-index: 100; background: #fff; box-shadow: 0 1px 0 var(--ds-border), 0 2px 12px rgba(15,23,42,.05); }
.ds-header-inner { max-width: 1310px; margin: 0 auto; padding: 0 var(--ds-gutter); height: var(--ds-header-h); display: flex; align-items: center; gap: 12px; }
.ds-logo { flex-shrink: 0; }
.ds-logo img { height: 44px; width: auto; }
.ds-nav { flex: 1 1 auto; min-width: 0; }
.ds-menu, .ds-submenu { list-style: none; margin: 0; padding: 0; display: flex; }
.ds-menu { justify-content: center; flex-wrap: nowrap; }
.ds-menu-item { position: relative; }
.ds-menu-item > a { display: block; padding: 9px 5px; font-size: .86rem; font-weight: 500; color: var(--ds-text); border-radius: 6px; white-space: nowrap; }
.ds-menu-item > a:hover { color: var(--ds-primary); background: var(--ds-bg-soft); }
.ds-menu-item.has-children > a::after { content: ''; display: inline-block; margin-left: 5px; border: 4px solid transparent; border-top-color: currentColor; transform: translateY(2px); }
.ds-submenu { position: absolute; top: 100%; left: 0; min-width: 215px; flex-direction: column; background: #fff; border: 1px solid var(--ds-border); border-radius: var(--ds-radius-sm); box-shadow: var(--ds-shadow); padding: 6px; opacity: 0; visibility: hidden; transform: translateY(6px); transition: all .18s ease; z-index: 20; }
.ds-menu-item:hover > .ds-submenu, .ds-menu-item:focus-within > .ds-submenu { opacity: 1; visibility: visible; transform: translateY(0); }
.ds-submenu a { display: block; padding: 9px 12px; font-size: .93rem; color: var(--ds-text); border-radius: 6px; white-space: nowrap; }
.ds-submenu a:hover { background: var(--ds-bg-soft); color: var(--ds-primary); }

.ds-header-tools { display: flex; align-items: center; gap: 10px; flex-shrink: 0; margin-left: auto; }
.ds-lang-switch { display: flex; gap: 4px; }
.ds-lang-switch a, .ds-lang-switch span { font-size: .8rem; font-weight: 600; padding: 8px 9px; border-radius: 6px; color: var(--ds-muted); border: 1px solid var(--ds-border); line-height: 1; letter-spacing: .04em; }
.ds-lang-switch a:hover { color: var(--ds-primary); border-color: var(--ds-primary); }
.ds-lang-switch .active { background: var(--ds-primary); color: #fff; border-color: var(--ds-primary); }
/* one line at every width (the old theme's fixed 116px box wrapped the label at 1440px) */
.ds-book-now { background: var(--ds-primary); color: #fff; font-weight: 600; font-size: 1rem; line-height: 1.2; padding: 13px 18px; border-radius: 8px; white-space: nowrap; text-align: center; }
.ds-book-now:hover { background: var(--ds-primary-dark); color: #fff; }
.ds-burger { display: none; background: none; border: 0; cursor: pointer; padding: 8px; }
.ds-burger span { display: block; width: 24px; height: 2.5px; background: var(--ds-text); margin: 5px 0; border-radius: 2px; }
.ds-mobile-nav { display: none; }

/* Six top-level labels + logo + language switcher + Book now. The row grew again on
   2026-10-28: "Rental apartments" -> "Short-term Rentals" and "For sale" ->
   "Apartments for Sale" (and the Estonian/Finnish names with them), ~92px of extra
   label, so the type, the paddings, the header gaps and the Book now button are all
   a step smaller than they were. That keeps one row - with the last tab clear of the
   language pills - down to 1080px; the measurements live in the session notes.
   Below ~1220px the row genuinely does not fit any more, and .ds-menu is
   justify-content: center, so an overflowing row would run out under BOTH the logo
   and the tools instead of clipping (that is how "Corporate Requests" ended up
   printed straight through the EN/FI/ET pills once). Those widths wrap to a second
   line instead - the header is tall enough for it. */
@media (max-width: 1280px) {
  .ds-menu { flex-wrap: wrap; row-gap: 0; }
  .ds-menu-item > a { padding: 6px 4px; font-size: .82rem; }
  .ds-book-now { font-size: .92rem; padding: 11px 14px; }
}
@media (max-width: 1150px) {
  .ds-menu-item > a { padding: 8px 4px; font-size: .78rem; }
  .ds-logo img { height: 36px; }
  .ds-header-tools { gap: 8px; }
  .ds-lang-switch a, .ds-lang-switch span { padding: 7px 6px; font-size: .72rem; }
  .ds-book-now { font-size: .82rem; padding: 9px 11px; }
}
@media (max-width: 1080px) {
  .ds-menu-item > a { padding: 5px 4px; }
  .ds-header-inner { align-items: center; }
}
@media (max-width: 990px) {
  :root { --ds-header-h: 80px; }
  .ds-nav, .ds-lang-switch, .ds-book-now { display: none; }
  .ds-burger { display: block; }
  .ds-mobile-nav { display: block; position: absolute; top: 100%; left: 0; right: 0; background: #fff; border-bottom: 1px solid var(--ds-border); box-shadow: var(--ds-shadow-lg); padding: 14px 20px 22px; max-height: calc(100vh - var(--ds-header-h)); overflow: auto; }
  .ds-mobile-nav a { display: block; padding: 11px 4px; border-bottom: 1px solid var(--ds-bg-soft); color: var(--ds-text); font-weight: 500; }
  .ds-mobile-nav a.sub { padding-left: 22px; font-weight: 400; color: var(--ds-muted); }
  .ds-mobile-langs { display: flex; gap: 10px; margin-top: 14px; }
  .ds-mobile-langs a { flex: 1; text-align: center; border: 1px solid var(--ds-border); border-radius: var(--ds-radius-sm); }
  .ds-mobile-book { display: block; margin-top: 14px; text-align: center; background: var(--ds-primary); color: #fff !important; font-weight: 600; border-radius: var(--ds-radius-sm); padding: 13px !important; border: 0 !important; }
}

/* Pages with a search band right under the hero (home, area pages): a shorter
   hero puts the check-in/check-out fields above the fold on 768-900px-tall
   laptop viewports, so nobody has to scroll to find where to book. */
/* !important: the mirrored inline style="--p-*" on the section would otherwise win */
.pc-hero--search { --p-mh: clamp(460px, calc(100vh - var(--ds-header-h) - 130px), 775px) !important; --p-pt: clamp(70px, 9vh, 250px) !important; --p-pb: clamp(60px, 7vh, 150px) !important; }
.pc-hero--search h1.pc-h { font-size: clamp(44px, 5vw, 76px); line-height: 1.12; }
.pc-hero--search h2.pc-h { font-size: clamp(22px, 2.2vw, 34px); }
@media (max-width: 990px) {
  .pc-hero--search { --p-mh-m: clamp(360px, calc(100vh - var(--ds-header-h) - 190px), 581px) !important; --p-pt-m: 64px !important; --p-pb-m: 56px !important; }
  .pc-hero--search h1.pc-h { font-size: clamp(34px, 9.5vw, 44px); }
  .pc-hero--search h2.pc-h { font-size: 22px; }
}

/* ==========================================================================
   Normalized content (pc-*) - structure + measured values
   ========================================================================== */
.ds-main { min-height: 40vh; }
.pc-sec {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: var(--p-pt, var(--ds-sec-pad)) var(--p-pr, var(--ds-gutter)) var(--p-pb, var(--ds-sec-pad)) var(--p-pl, var(--ds-gutter));
  margin-top: var(--p-mt, 0);
  margin-bottom: var(--p-mb, 0);
  min-height: var(--p-mh, auto);
  background-color: var(--p-bgc, transparent);
  background-image: var(--p-bgi, none);
  background-size: var(--p-bgsz, cover);
  background-position: var(--p-bgpos, center);
  background-repeat: no-repeat;
  text-align: var(--p-ta, inherit);
}
@media (min-width: 1025px) { .pc-sec { background-attachment: var(--p-bgatt, scroll); } }
.pc-sec[style*="--p-bgfixed"] { --p-bgatt: fixed; }
.pc-sec::before { content: ''; position: absolute; inset: 0; background: var(--p-ovbg, transparent); opacity: var(--p-ov, 0); pointer-events: none; }
.pc-sec > * { position: relative; z-index: 1; }

.pc-wrap {
  width: 100%;
  max-width: var(--p-cw, var(--ds-container));
  margin-inline: auto;
  flex: 1 1 auto;
  display: flex;
  flex-direction: var(--p-dir, column);
  flex-wrap: var(--p-fxw, nowrap);
  justify-content: var(--p-jc, normal);
  align-items: var(--p-ai, normal);
  gap: var(--p-gap, normal);
}
.pc-col {
  display: flex;
  flex-direction: var(--p-dir, column);
  flex-wrap: var(--p-fxw, nowrap);
  justify-content: var(--p-jc, normal);
  align-items: var(--p-ai, normal);
  gap: var(--p-gap, normal);
  flex: 0 1 auto;
  width: var(--p-w, 100%);
  max-width: var(--p-cw, none);
  min-width: 0;
}
.pc-item { max-width: var(--p-mw, none); min-width: 0; }
/* measured box values are consumed only by the element that owns them */
.pc-box {
  padding: var(--p-pt, 0) var(--p-pr, 0) var(--p-pb, 0) var(--p-pl, 0);
  margin: var(--p-mt, 0) var(--p-mr, 0) var(--p-mb, 0) var(--p-ml, 0);
}

/* measured typography: the element that owns the values applies them, children inherit */
.pc-sec, .pc-wrap, .pc-col, .pc-item, .pc-text, .pc-h, .pc-btn,
.pc-banner-title, .pc-banner-text, .pc-acc-q, .pc-acc-a, .pc-list li {
  font-family: var(--p-ff, inherit);
  font-weight: var(--p-fw, inherit);
  letter-spacing: var(--p-ls, normal);
  text-transform: var(--p-tt, none);
  color: var(--p-c, inherit);
  line-height: var(--p-lh, inherit);
  text-align: var(--p-ta, inherit);
}
.pc-item, .pc-text, .pc-banner-title, .pc-banner-text, .pc-acc-a, .pc-list li { font-size: var(--p-fs, inherit); }
h1.pc-h { font-family: var(--p-ff, var(--ds-serif)); font-size: var(--p-fs, 88px); font-weight: var(--p-fw, 700); line-height: var(--p-lh, 1.4); text-transform: var(--p-tt, uppercase); }
h2.pc-h { font-family: var(--p-ff, var(--ds-serif)); font-size: var(--p-fs, 46px); font-weight: var(--p-fw, 700); line-height: var(--p-lh, 1.3); text-transform: var(--p-tt, uppercase); }
h3.pc-h { font-family: var(--p-ff, var(--ds-serif)); font-size: var(--p-fs, 46px); font-weight: var(--p-fw, 400); line-height: var(--p-lh, 1.3); text-transform: var(--p-tt, uppercase); }
h4.pc-h { font-family: var(--p-ff, var(--ds-serif)); font-size: var(--p-fs, 20px); font-weight: var(--p-fw, 700); line-height: var(--p-lh, 1.2); text-transform: var(--p-tt, none); }
h5.pc-h { font-family: var(--p-ff, var(--ds-serif)); font-size: var(--p-fs, 18px); line-height: var(--p-lh, 1.2); }
h6.pc-h { font-family: var(--p-ff, var(--ds-serif)); font-size: var(--p-fs, 15px); line-height: var(--p-lh, 1.25); }

@media (max-width: 1024px) {
  .pc-sec { padding-top: var(--p-pt-t, var(--p-pt, var(--ds-sec-pad))); padding-right: var(--p-pr-t, var(--p-pr, var(--ds-gutter))); padding-bottom: var(--p-pb-t, var(--p-pb, var(--ds-sec-pad))); padding-left: var(--p-pl-t, var(--p-pl, var(--ds-gutter))); margin-top: var(--p-mt-t, var(--p-mt, 0)); margin-bottom: var(--p-mb-t, var(--p-mb, 0)); min-height: var(--p-mh-t, var(--p-mh, auto)); }
  .pc-wrap, .pc-col { flex-direction: var(--p-dir-t, var(--p-dir, column)); gap: var(--p-gap-t, var(--p-gap, normal)); justify-content: var(--p-jc-t, var(--p-jc, normal)); }
  .pc-wrap { max-width: var(--p-cw-t, var(--p-cw, var(--ds-container))); }
  .pc-col { width: var(--p-w-t, var(--p-w, 100%)); }
  .pc-box { padding: var(--p-pt-t, var(--p-pt, 0)) var(--p-pr-t, var(--p-pr, 0)) var(--p-pb-t, var(--p-pb, 0)) var(--p-pl-t, var(--p-pl, 0)); margin-bottom: var(--p-mb-t, var(--p-mb, 0)); }
  h1.pc-h { font-size: var(--p-fs-t, var(--p-fs, 72px)); }
  h2.pc-h { font-size: var(--p-fs-t, var(--p-fs, 34px)); }
  h3.pc-h { font-size: var(--p-fs-t, var(--p-fs, 34px)); }
  .pc-item, .pc-text, .pc-banner-title, .pc-banner-text, .pc-acc-a { font-size: var(--p-fs-t, var(--p-fs, inherit)); }
}
@media (max-width: 767px) {
  .pc-sec { padding-top: var(--p-pt-m, var(--p-pt, var(--ds-sec-pad))); padding-bottom: var(--p-pb-m, var(--p-pb, var(--ds-sec-pad))); margin-top: var(--p-mt-m, var(--p-mt, 0)); margin-bottom: var(--p-mb-m, var(--p-mb, 0)); min-height: var(--p-mh-m, var(--p-mh, auto)); }
  .pc-wrap, .pc-col { flex-wrap: wrap; flex-direction: var(--p-dir-m, var(--p-dir, column)); gap: var(--p-gap-m, var(--p-gap, normal)); }
  .pc-wrap { max-width: var(--p-cw-m, var(--p-cw, var(--ds-container))); }
  .pc-col { width: var(--p-w-m, var(--p-w, 100%)); }
  .pc-box { padding: var(--p-pt-m, var(--p-pt, 0)) var(--p-pr-m, var(--p-pr, 0)) var(--p-pb-m, var(--p-pb, 0)) var(--p-pl-m, var(--p-pl, 0)); margin-bottom: var(--p-mb-m, var(--p-mb, 0)); }
  h1.pc-h { font-size: var(--p-fs-m, var(--p-fs, 40px)); }
  h2.pc-h { font-size: var(--p-fs-m, var(--p-fs, 27px)); }
  h3.pc-h { font-size: var(--p-fs-m, var(--p-fs, 27px)); }
  .pc-item, .pc-text, .pc-banner-title, .pc-banner-text, .pc-acc-a { font-size: var(--p-fs-m, var(--p-fs, inherit)); }
}

/* responsive visibility (Elementor breakpoints) */
@media (min-width: 1025px) { .pc-hd { display: none !important; } }
@media (min-width: 768px) and (max-width: 1024px) { .pc-ht { display: none !important; } }
@media (max-width: 767px) { .pc-hm { display: none !important; } }

.pc-text { font-size: var(--p-fs, 1rem); }
.pc-text p { margin: 0 0 1.1em; }
.pc-text img { border-radius: var(--ds-radius); margin: 1.2em 0; }
.pc-text a { text-decoration: underline; text-underline-offset: 2px; }
.pc-btn { display: inline-block; align-self: flex-start; background: var(--p-btnbg, var(--ds-primary)); color: var(--p-btnc, #fff); padding: var(--p-btnpad, 13px 28px); border-radius: var(--p-btnbr, var(--ds-radius-sm)); border: var(--p-btnbd, 0); font-weight: var(--p-btnfw, 600); font-size: var(--p-btnfs, .95rem); letter-spacing: var(--p-btnls, normal); text-transform: var(--p-btntt, none); margin: 4px 0; }
.pc-btn:hover { background: var(--ds-primary-dark); color: #fff; }
.pc-list { list-style: none; padding: 0; margin: 0 0 1.2em; display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 6px 22px; }
.pc-list li { padding: 7px 0 7px 26px; position: relative; font-size: .95rem; border-bottom: 1px dashed var(--ds-border); }
.pc-list li::before { content: ''; position: absolute; left: 4px; top: 14px; width: 7px; height: 7px; border-radius: 50%; background: var(--ds-primary); }
.pc-ol li { margin-bottom: .5em; }
.pc-table { width: 100%; border-collapse: collapse; }
.pc-table td, .pc-table th { padding: 8px 10px; border: 1px solid var(--ds-border); }
.pc-hr { border: 0; border-top: 1px solid var(--ds-border); margin: 2em 0; }
.pc-quote { border-left: 3px solid var(--ds-primary); margin: 1.5em 0; padding: 4px 0 4px 18px; color: var(--ds-accent); font-style: italic; }

/* category / photo banner cards */
/* The live widget put the photo at 60% opacity over black, which greys the image out.
   A scrim over the full-colour photo keeps the contrast without the wash-out. */
.pc-banner { position: relative; display: block; overflow: hidden; background: var(--ds-navy); color: #fff; }
.pc-banner img { display: block; width: 100%; height: 475px; object-fit: cover; }
.pc-banner::after { content: ''; position: absolute; inset: 0; z-index: 1; background: rgba(14, 22, 32, .26); transition: background .3s ease; }
.pc-banner:hover::after { background: rgba(14, 22, 32, .52); }
.pc-banner-body { position: absolute; inset: 0; z-index: 2; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; padding: 30px; text-align: center; }
.pc-banner-title { text-shadow: 0 1px 14px rgba(0, 0, 0, .45); }
.pc-banner-text { text-shadow: 0 1px 10px rgba(0, 0, 0, .5); }
.pc-banner-title { font-family: var(--ds-serif); font-weight: 400; font-size: 34px; line-height: 1.2; color: #fff; margin: 0; text-transform: none; }
.pc-banner-text { color: #fff; font-size: 1rem; }

/* accordion (Elementor nested-accordion -> details/summary) */
.pc-acc-item { border: 1px solid var(--ds-border); border-radius: var(--ds-radius-sm); background: #fff; }
.pc-acc-item + .pc-acc-item { margin-top: 10px; }
.pc-acc-q { cursor: pointer; list-style: none; padding: 18px 22px; display: flex; align-items: center; justify-content: space-between; gap: 16px; font-family: var(--ds-font); font-weight: 600; font-size: 1.05rem; color: var(--ds-navy); }
.pc-acc-q::-webkit-details-marker { display: none; }
.pc-acc-q::after { content: '+'; flex: 0 0 auto; font-size: 1.5rem; line-height: 1; color: var(--ds-primary); font-weight: 400; }
.pc-acc-item[open] .pc-acc-q::after { content: '\2212'; }
.pc-acc-item[open] .pc-acc-q { color: var(--ds-primary); }
.pc-acc-a { padding: 0 22px 18px; color: var(--ds-text); }
.pc-acc-a > :last-child { margin-bottom: 0; }

/* search card (own implementation of the original Lodgix widget) */
.pc-search { width: 100%; max-width: var(--ds-container); margin: 0 auto; }
.pc-search form { display: flex; flex-wrap: wrap; gap: 10px; align-items: stretch; }
.pc-search-field { flex: 1 1 190px; min-width: 0; display: block; }
.pc-search-field input { font-family: inherit; font-size: 16px; height: 55px; width: 100%; padding: 0 16px; border: 0; border-radius: 5px; background: #fff; color: #000; }
.pc-search-field input::placeholder { color: #6b7280; }
.pc-search-go { flex: 1 1 150px; height: 55px; border: 0; border-radius: 5px; background: #fff; color: var(--ds-primary); font-family: inherit; font-weight: 600; font-size: 16px; cursor: pointer; transition: background .18s ease; }
.pc-search-go:hover { background: var(--ds-soft); }
.pc-sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* reviews band (replaces the Trustindex widget) */
.pc-reviews { max-width: var(--ds-container); margin: 34px auto 0; text-align: center; }
.pc-reviews-badge { display: inline-flex; align-items: center; gap: 12px; font-weight: 700; font-size: 1.35rem; letter-spacing: .04em; color: var(--ds-navy); }
.pc-stars { color: #f5a623; font-size: 1.15rem; letter-spacing: 2px; }
.pc-reviews-note { margin: 10px 0 0; color: var(--ds-muted); }
/* Host for the frozen Trustindex markup. Its carousel progress line is wider
   than the container, which made the whole document scroll sideways on phones
   (and dragged any position:fixed widget out past the right edge with it).
   `clip` trims it horizontally while leaving vertical overflow - the widget's
   tooltips - visible. The width caps matter now that the host sits INSIDE the
   Testimonials .pc-wrap: as a column-flex item its automatic minimum size was
   the slider's own width (1844px), which stretched every sibling and pushed the
   document to 1894px on a 390px phone. min-width: 0 lets the item shrink back to
   the container and clip, as it did when the widget sat at the end of the page. */
.pc-ti-host { overflow-x: clip; max-width: 100%; min-width: 0; }
/* The frozen Trustindex markup is the desktop "ti-col-4" layout (245px rating
   column + reviews strip); the live widget's JS re-lays it out on phones, ours
   does not, so below 700px the rating stacks above a one-column review strip. */
@media (max-width: 700px) {
  .pc-ti-host .ti-widget.ti-book .ti-widget-container { flex-wrap: wrap !important; }
  /* specificity beats trustindex.css's ".ti-widget-container:not(.ti-col-1)" rules, which load later */
  .pc-ti-host .ti-widget.ti-book .ti-widget-container.ti-widget-container .ti-footer { flex: 0 0 100% !important; max-width: 100% !important; margin: 0 0 18px !important; }
  .pc-ti-host .ti-widget.ti-book .ti-widget-container.ti-widget-container .ti-reviews-container { flex: 0 0 100% !important; max-width: 100% !important; }
  .pc-ti-host .ti-widget.ti-book .ti-review-item { flex: 0 0 100% !important; max-width: 100% !important; }
  .pc-ti-host .ti-widget.ti-book .ti-controls { display: none !important; }
  .pc-ti-host .ti-widget.ti-book .ti-review-content { height: auto !important; min-height: 44px; }
}

/* ==========================================================================
   Listing
   ========================================================================== */
.ds-listing { max-width: var(--ds-container-wide); margin: 0 auto; padding: 44px var(--ds-gutter) 70px; }
.ds-listing-head { display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: 10px; margin-bottom: 22px; }
.ds-count { color: var(--ds-muted); }
.ds-filters { display: flex; flex-wrap: wrap; gap: 12px; align-items: end; background: var(--ds-bg-soft); border: 1px solid var(--ds-border); border-radius: var(--ds-radius); padding: 16px 18px; margin-bottom: 30px; }
.ds-filters label { display: flex; flex-direction: column; gap: 5px; font-size: .8rem; font-weight: 600; color: var(--ds-muted); }
.ds-filters select, .ds-filters input { font-family: inherit; font-size: .95rem; padding: 10px 12px; border: 1px solid var(--ds-border); border-radius: var(--ds-radius-sm); background: #fff; min-width: 170px; width: 100%; color: var(--ds-text); }
.ds-filters input::placeholder { color: #94a3b8; }
/* amenity chips: a full-width row of toggles under the filter fields (listing) */
.ds-filter-amenities { flex: 1 1 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 2px 0 0; }
.ds-filter-amenities-label { font-size: .8rem; font-weight: 600; color: var(--ds-muted); margin-right: 2px; }
/* .ds-filters label styles every field caption (column, flex 1 1 150px) - the chips are labels
   too, so they have to opt out of that before they can be pills */
.ds-filter-amenities .ds-filter-amenity { position: relative; display: inline-flex; flex: 0 0 auto; flex-direction: row; align-items: center; gap: 0; min-width: 0; font-size: inherit; font-weight: inherit; color: inherit; }
.ds-filter-amenities .ds-filter-amenity input { position: absolute; width: 1px; height: 1px; min-width: 0; padding: 0; border: 0; opacity: 0; margin: 0; }
.ds-filter-amenities .ds-filter-amenity span { display: inline-block; padding: 7px 13px; border: 1px solid var(--ds-border); border-radius: 999px; background: #fff; color: var(--ds-text); font-size: .85rem; font-weight: 500; line-height: 1.2; cursor: pointer; transition: background .12s ease, border-color .12s ease, color .12s ease; }
.ds-filter-amenities .ds-filter-amenity:hover span { border-color: var(--ds-primary); }
.ds-filter-amenities .ds-filter-amenity input:checked + span { background: var(--ds-primary); border-color: var(--ds-primary); color: #fff; }
.ds-filter-amenities .ds-filter-amenity input:focus-visible + span { outline: 2px solid var(--ds-primary); outline-offset: 2px; }
.ds-filters label { flex: 1 1 150px; min-width: 0; }
.ds-filters label:has(input[name="guests"]), .ds-filters label:has(input[name="bedrooms"]) { flex: 0 1 130px; }
.ds-filters label:has(input[name="guests"]) input, .ds-filters label:has(input[name="bedrooms"]) input { min-width: 0; }
.ds-filters .ds-btn { flex: 0 0 auto; }
@media (max-width: 700px) {
  .ds-filters { padding: 14px; gap: 10px; }
  .ds-filters label { flex: 1 1 calc(50% - 5px); }
  .ds-filters select, .ds-filters input { min-width: 0; }
  .ds-filters .ds-btn { flex: 1 1 calc(50% - 5px); text-align: center; }
}

/* Sort pills. Plain links (see templates/listing.php): they apply without JavaScript,
   each choice is one URL the edge can cache, and stay.js adds the remembered dates. */
.ds-sort { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 0 0 22px; }
.ds-sort-label { font-size: .78rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--ds-muted); }
.ds-sort-opts { display: flex; flex-wrap: wrap; gap: 6px; }
.ds-sort-opt { display: inline-block; padding: 6px 13px; border: 1px solid var(--ds-border); border-radius: 999px; background: #fff; color: var(--ds-text); font-size: .82rem; line-height: 1.3; text-decoration: none; transition: border-color .15s ease, color .15s ease, background-color .15s ease; }
.ds-sort-opt:hover { border-color: var(--ds-primary); color: var(--ds-primary); }
.ds-sort-opt.is-active { background: var(--ds-primary); border-color: var(--ds-primary); color: #fff; }
.ds-sort-opt:focus-visible { outline: 2px solid var(--ds-primary); outline-offset: 2px; }
@media (max-width: 700px) {
  .ds-sort { gap: 6px; }
  .ds-sort-opt { padding: 6px 11px; font-size: .8rem; }
}

.ds-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr)); gap: 26px; }
/* Property card, laid out like the Lodgix card the old site rendered: photo with
   the favourite button, the address line, the "<Type> in <area>, Harjumaa" line, a
   row of round amenity chips, and the nightly rate pushed to the right of that
   same row.  Only the typeface differs (site fonts). */
.ds-card { position: relative; display: flex; flex-direction: column; background: #fff; border: 1px solid var(--ds-border); border-radius: var(--ds-radius); overflow: hidden; box-shadow: var(--ds-shadow); transition: transform .18s ease, box-shadow .18s ease; }
.ds-card:hover { transform: translateY(-3px); box-shadow: var(--ds-shadow-lg); }
.ds-card-media { position: relative; display: block; }
.ds-card-media-link { display: block; }
.ds-card-media img { display: block; width: 100%; aspect-ratio: 3 / 2; object-fit: cover; }
.ds-card-body { display: flex; flex: 1; flex-direction: column; justify-content: space-between; gap: 12px; padding: 14px 15px 16px; }
.ds-card-head { display: block; color: inherit; text-decoration: none; }
.ds-card-title { margin: 0; font-family: var(--ds-serif); font-weight: 400; font-size: 1.02rem; line-height: 1.25; letter-spacing: .015em; text-transform: uppercase; color: #1f2937; }
.ds-card-loc { display: block; margin-top: 3px; font-size: .78rem; line-height: 1.4; color: var(--ds-muted); }
/* chips on one row, price always on its own bottom row - every card in a row then
   shares the same baseline whatever chips it has or how long its address is */
.ds-card-end { display: flex; flex-direction: column; align-items: stretch; gap: 8px; margin-top: auto; }
.ds-card-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin: 0; padding: 0; list-style: none; }
.ds-card-chips li { border: 1px solid #cbd5e1; border-radius: 999px; padding: 3px 8px; font-size: 11px; line-height: 1.3; color: #334155; background: #fff; }
/* margin-left:auto keeps the rate at the right edge both when it shares the row
   with the chips and when it wraps below them - as on the old card */
.ds-card-rate { margin: 0; font-size: 13px; line-height: 1.35; white-space: nowrap; color: var(--ds-text); text-align: right; padding-top: 8px; border-top: 1px solid var(--ds-bg-soft); }
.ds-card-rate strong { font-weight: 700; }
/* searched stay: the real Lodgix total for those dates (rent + cleaning fee + taxes), so
   the number the guest sees here is the one the checkout asks for. Wraps instead of
   nowrap: "Yhteensä €1 236.10 · 14 yötä" is longer than any from-price. */
.ds-card-rate-total { white-space: normal; }
.ds-card-rate-total strong { font-size: 1.05rem; color: var(--ds-primary); }
.ds-card-rate-total .ds-card-nights { color: var(--ds-muted); }
/* kept: templates/property.php still prints these two blocks */
.ds-card-meta { padding: 0 16px; margin: 0; font-size: .82rem; color: var(--ds-muted); }
.ds-card-price { padding: 8px 16px 0; margin: 0; font-weight: 700; color: var(--ds-primary); }
/* stay-rule pill (old Lodgix .ldx-criteria-alert: red-100 pill, top-left over the photo) */
.ds-card-rule { position: absolute; top: 14px; left: 14px; z-index: 2; max-width: 64%; padding: 4px 14px; border-radius: 999px; background: #fee2e2; color: #111827; font-size: .82rem; font-weight: 600; line-height: 1.3; box-shadow: var(--ds-shadow); }
.ds-card.is-rule .ds-card-media img { opacity: .72; }
.ds-fav { position: absolute; top: 10px; right: 10px; z-index: 2; width: 38px; height: 38px; border-radius: 50%; border: none; background: rgba(255,255,255,.92); color: var(--ds-muted); font-size: 1.2rem; cursor: pointer; box-shadow: var(--ds-shadow); }
.ds-fav.active { color: #e11d48; }
/* Apartment size, bottom right of the photo. pointer-events:none keeps the whole photo
   one link (the favourite button sits top right, the stay-rule pill top left). */
.ds-card-size { position: absolute; right: 10px; bottom: 10px; z-index: 2; padding: 3px 9px; border-radius: 999px; background: rgba(255,255,255,.94); color: #1f2937; font-size: 11px; font-weight: 600; line-height: 1.35; letter-spacing: .01em; box-shadow: var(--ds-shadow); pointer-events: none; }

.ds-pagination { display: flex; justify-content: center; align-items: center; gap: 22px; margin-top: 40px; }
.ds-pagination span { color: var(--ds-muted); font-size: .9rem; }

/* ==========================================================================
   Apartments FOR SALE (/apartments-for-sale/ and /apartments-for-sale/<slug>/)
   --------------------------------------------------------------------------
   Same cards, same sort pills, same page skeleton as the apartment listing -
   what differs is the number (an asking price, not a nightly rate) and the
   sidebar, which carries an enquiry form instead of "Book now". Anything that
   can be inherited from the listing/property styles above IS inherited; only
   the sale-specific pieces are declared here.
   ========================================================================== */
.ds-sale-intro { max-width: 62ch; margin: -8px 0 26px; color: var(--ds-muted); font-size: .95rem; line-height: 1.55; }
/* status pill over the card photo, top-left - the same place the apartment card
   puts its stay-rule pill, so the two listings read identically */
.ds-card-sale-badge { position: absolute; top: 14px; left: 14px; z-index: 2; padding: 4px 12px; border-radius: 999px; font-size: .78rem; font-weight: 600; line-height: 1.3; box-shadow: var(--ds-shadow); }
.ds-sale-badge-available { background: var(--ds-primary); color: #fff; }
.ds-sale-badge-reserved { background: #fef3c7; color: #92400e; }
.ds-sale-badge-sold { background: #e2e8f0; color: #475569; }
.ds-sale-card.is-sold .ds-card-media img { opacity: .62; }
/* asking price: the same row as the apartment card's rate, but it wraps - "€180 000
   plus 24% VAT" is longer than any "From €51 / night" and must not push the card */
.ds-card-sale-rate { white-space: normal; text-align: right; }
.ds-card-sale-rate strong { font-size: 1.12rem; color: var(--ds-primary); }
.ds-card-sale-note { display: block; font-size: 11.5px; font-weight: 500; color: var(--ds-muted); }
/* A for-sale card with no photo yet: keeps the 3:2 block of the grid and says what
   the property is, instead of collapsing the card to a strip. */
.ds-card-media-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; aspect-ratio: 3 / 2; padding: 18px; background: linear-gradient(135deg, #eef4f5 0%, #dde8ea 100%); color: var(--ds-muted); text-align: center; }
.ds-card-media-empty-type { font-family: var(--ds-serif); font-size: 1.05rem; letter-spacing: .06em; text-transform: uppercase; }
.ds-card-media-empty-place { font-size: .8rem; letter-spacing: .03em; text-transform: uppercase; opacity: .8; }

/* Yield pill, bottom-left of the photo (operator's placement). The status pill owns
   the top-left, the m2 badge the bottom-right - the same 10px inset as that badge -
   so a card can carry all three without collisions. */
.ds-card-roi { position: absolute; left: 10px; bottom: 10px; z-index: 2; padding: 4px 11px; border-radius: 999px; background: var(--ds-navy); color: #fff; font-size: .78rem; font-weight: 700; line-height: 1.3; letter-spacing: .02em; white-space: nowrap; box-shadow: var(--ds-shadow); }
/* the same figure in the property page's price block, and its footnote */
/* the yield line in the price block */
.ds-sale-roi { font-weight: 700; color: var(--ds-primary); }
/* 'For the investor': the official appraisal as one quiet highlighted row, then the
   'what is included' list (marker differs from .ds-sale-highlights on purpose - these
   are terms of the deal, not features of the apartment) */
.ds-sale-appraisal { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; margin: 0 0 16px; padding: 12px 16px; border: 1px solid var(--ds-border); border-left: 3px solid var(--ds-primary); border-radius: var(--ds-radius-sm); background: var(--ds-bg-soft); }
.ds-sale-appraisal-label { font-size: .82rem; font-weight: 600; letter-spacing: .02em; text-transform: uppercase; color: var(--ds-muted); }
.ds-sale-appraisal strong { font-size: 1.15rem; color: var(--ds-primary); }
.ds-sale-appraisal-date { font-size: .86rem; color: var(--ds-muted); }
.ds-sale-investor { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.ds-sale-investor li { position: relative; padding: 0 0 0 22px; font-size: .95rem; line-height: 1.5; }
.ds-sale-investor li::before { content: '\2192'; position: absolute; left: 0; top: 0; color: var(--ds-primary); font-weight: 700; }
.ds-sale-roi-note { margin: 6px 0 0; font-size: .74rem; line-height: 1.45; color: var(--ds-muted); }

/* the badge also appears in the detail page's chip row, where there is no photo
   behind it and no absolute positioning */
.ds-prop-chips .ds-sale-status { position: static; box-shadow: none; padding: 4px 12px; }
.ds-sale-subtitle { margin: 2px 0 10px; color: var(--ds-muted); font-size: 1.02rem; line-height: 1.5; }
.ds-sale-highlights { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px 22px; }
.ds-sale-highlights li { position: relative; padding: 2px 0 2px 24px; font-size: .95rem; line-height: 1.45; }
.ds-sale-highlights li::before { content: '\2713'; position: absolute; left: 2px; top: 1px; color: var(--ds-primary); font-weight: 700; }
/* price block at the top of the sidebar card (before the form) */
.ds-sale-price { margin: 0 0 16px; padding-bottom: 14px; border-bottom: 1px solid var(--ds-bg-soft); }
.ds-sale-price-amount { margin: 0; font-size: 1.7rem; line-height: 1.15; font-weight: 700; color: var(--ds-primary); }
.ds-sale-price-note { display: block; margin-top: 2px; font-size: .82rem; font-weight: 500; color: var(--ds-muted); }
.ds-sale-price-meta { display: flex; flex-wrap: wrap; gap: 4px 14px; margin: 8px 0 0; font-size: .82rem; color: var(--ds-muted); }
.ds-sale-price-meta span:first-child { font-weight: 600; color: var(--ds-text); }
/* the enquiry form */
.ds-sale-form-title { margin: 0 0 6px; font-family: var(--ds-serif); font-weight: 400; font-size: 1.15rem; letter-spacing: .015em; text-transform: uppercase; color: #1f2937; }
.ds-sale-form-intro { margin: 0 0 16px; font-size: .86rem; line-height: 1.5; color: var(--ds-muted); }
.ds-sale-form .ds-field-label .ds-req { color: #b91c1c; font-weight: 700; }
.ds-sale-form .ds-field textarea { min-height: 104px; resize: vertical; }
.ds-sale-send { width: 100%; text-align: center; font-size: 1.02rem; padding: 14px; margin-top: 2px; }
.ds-sale-form-note { margin: 10px 0 0; font-size: .74rem; line-height: 1.45; color: var(--ds-muted); }
.ds-form-error { margin: 0 0 14px; padding: 11px 14px; border: 1px solid #fecaca; border-radius: var(--ds-radius-sm); background: #fef2f2; color: #991b1b; font-size: .86rem; line-height: 1.45; }
.ds-sale-success { max-width: none; margin: 0; }
.ds-sale-success-title { margin: 0 0 4px; font-size: 1.05rem; }
.ds-sale-side { scroll-margin-top: calc(var(--ds-header-h) + 14px); }

/* ==========================================================================
   Property page
   ========================================================================== */
.ds-property { max-width: var(--ds-container-wide); margin: 0 auto; padding: 34px var(--ds-gutter) 80px; }
.ds-prop-title h1 { margin-bottom: 4px; }
.ds-prop-location { color: var(--ds-muted); margin-bottom: 20px; }
.ds-gallery-hero { width: 100%; aspect-ratio: 1448 / 710; object-fit: cover; border-radius: var(--ds-radius); box-shadow: var(--ds-shadow); }
/* Crossfade layer stacked on the hero. The hero itself never changes opacity: fading the
   only image out showed the white page behind it mid-transition (which is what it did).
   The incoming photo fades in here, on top of the current one. */
.ds-gallery-hero-top {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  border-radius: var(--ds-radius); opacity: 0; pointer-events: none;
  transition: opacity 150ms ease;
}
.ds-gallery-hero-top.is-visible { opacity: 1; }
.ds-gallery-hero-top.no-transition { transition: none; }
@media (prefers-reduced-motion: reduce) { .ds-gallery-hero-top { transition: none; } }
/* Hover zones over the big photo: a soft scrim plus an arrow, so the photos can be
   stepped through without opening the lightbox. Kept out of the way of the counter,
   the "view all" pill and (on touch devices, where there is no hover) of everything. */
.ds-gallery-nav {
  position: absolute; top: 0; bottom: 0; z-index: 1; width: 16%; min-width: 70px; max-width: 150px;
  display: flex; align-items: center; justify-content: center; padding: 0; border: 0; cursor: pointer;
  color: #fff; font-size: 2.6rem; line-height: 1; opacity: 0; transition: opacity 160ms ease;
}
.ds-gallery-nav-prev { left: 0; border-radius: var(--ds-radius) 0 0 var(--ds-radius); background: linear-gradient(to right, rgba(8, 24, 27, .45), rgba(8, 24, 27, 0)); }
.ds-gallery-nav-next { right: 0; border-radius: 0 var(--ds-radius) var(--ds-radius) 0; background: linear-gradient(to left, rgba(8, 24, 27, .45), rgba(8, 24, 27, 0)); }
.ds-gallery-frame:hover .ds-gallery-nav,
.ds-gallery-nav:hover { opacity: 1; }
.ds-gallery-nav:focus-visible { opacity: 1; outline: 2px solid #fff; outline-offset: -4px; }
@media (hover: none) { .ds-gallery-nav { display: none; } }
.ds-gallery-thumbs { display: flex; gap: 10px; margin-top: 10px; flex-wrap: wrap; }
.ds-gallery-thumbs button { border: 2px solid transparent; border-radius: var(--ds-radius-sm); overflow: hidden; padding: 0; cursor: pointer; background: none; width: 110px; }
/* Ten tiles (nine thumbnails + the "+N" tile) do not fit a 1160px strip at 110px each, so
   the tile used to drop onto its own line on wide screens. A fixed ten-column grid keeps
   the whole set on one row at desktop widths; below that the fixed-size thumbs wrap. */
@media (min-width: 1100px) {
  .ds-gallery-thumbs.has-more { display: grid; grid-template-columns: repeat(10, minmax(0, 1fr)); }
  .ds-gallery-thumbs.has-more button { width: auto; }
}
.ds-gallery-thumbs button:hover { border-color: var(--ds-primary); }
.ds-gallery-thumbs button.is-current { border-color: var(--ds-primary); }
.ds-gallery-thumbs img { width: 100%; height: 74px; object-fit: cover; }
/* Thumbnails past the ninth are rendered hidden and revealed by the tile below. */
.ds-gallery-thumbs button[hidden] { display: none; }
/* The "+N" tile. The selector needs the .ds-gallery-thumbs prefix: as a bare
   .ds-gallery-all (0,1,0) it LOST to `.ds-gallery-thumbs button` (0,1,1) background:none,
   so the white label was painted white-on-white and the tile looked empty. */
.ds-gallery-thumbs .ds-gallery-all {
  position: relative; display: flex; align-items: center; justify-content: center;
  background: var(--ds-primary); color: #fff; font-weight: 700; font-size: 1.05rem;
  height: 74px; letter-spacing: .01em;
}
.ds-gallery-thumbs .ds-gallery-all:hover { border-color: var(--ds-primary); }
.ds-gallery-thumbs .ds-gallery-all::after { content: ''; position: absolute; inset: 0; background: rgba(5, 34, 38, .5); }
.ds-gallery-mosaic { position: absolute; inset: 0; display: grid; grid-template-columns: 2fr 1fr; grid-template-rows: 1fr 1fr; gap: 2px; }
.ds-gallery-thumbs .ds-gallery-mosaic img { width: 100%; height: 100%; object-fit: cover; }
.ds-gallery-thumbs .ds-gallery-mosaic img:first-child { grid-row: span 2; }
/* Fewer than three photos behind the tile: one or two cells, no blank teal corners. */
.ds-gallery-mosaic-1 { grid-template-columns: 1fr; }
.ds-gallery-mosaic-2 { grid-template-columns: 1fr 1fr; }
.ds-gallery-thumbs .ds-gallery-mosaic-2 img:first-child,
.ds-gallery-thumbs .ds-gallery-mosaic-1 img:first-child { grid-row: auto; }
.ds-gallery-all-label { position: relative; z-index: 1; display: block; line-height: 1.1; text-align: center; text-shadow: 0 1px 3px rgba(0,0,0,.55); }
.ds-gallery-all-sub { display: block; margin-top: 2px; font-size: .6rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; opacity: .92; }
.ds-gallery-count {
  position: absolute; left: 16px; bottom: 12px; z-index: 2; display: inline-flex; align-items: center;
  height: 32px; padding: 0 12px; border-radius: 100px; background: rgba(10, 20, 24, .62);
  color: #fff; font-size: .8rem; font-weight: 600;
}

.ds-prop-columns { display: grid; grid-template-columns: minmax(0, 1fr) 350px; gap: 44px; margin-top: 34px; }
/* minmax(0, 1fr): a bare 1fr track sizes to the content's min-content width, and the
   sleeping-arrangement grid made the column 457px wide on a 390px phone */
@media (max-width: 960px) { .ds-prop-columns { grid-template-columns: minmax(0, 1fr); } }
.ds-prop-facts { list-style: none; padding: 0; margin: 0 0 24px; display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px 22px; font-size: .95rem; }
.ds-prop-description { color: var(--ds-text); overflow-wrap: break-word; }
.ds-amenities { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 8px 18px; }
.ds-amenities li { padding: 8px 0 8px 26px; border-bottom: 1px dashed var(--ds-border); position: relative; font-size: .93rem; }
.ds-amenities li::before { content: ''; position: absolute; left: 4px; top: 13px; width: 7px; height: 7px; border-radius: 50%; background: var(--ds-primary); }

.ds-prop-side { display: flex; flex-direction: column; gap: 22px; }
.ds-book-card { position: sticky; top: calc(var(--ds-header-h) + 14px); min-width: 0; overflow-wrap: anywhere; background: #fff; border: 1px solid var(--ds-border); border-radius: var(--ds-radius); box-shadow: var(--ds-shadow-lg); padding: 22px; }
.ds-book-dates { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; }
.ds-book-dates input { flex: 1 1 0; width: 0; min-width: 0; font-family: inherit; font-size: .92rem; padding: 11px 8px; border: 1px solid var(--ds-border); border-radius: var(--ds-radius-sm); cursor: pointer; text-align: center; color: var(--ds-text); }
.ds-book-dates input::placeholder { color: #94a3b8; }
.ds-book-dates span { color: var(--ds-muted); }
.ds-book-btn { width: 100%; text-align: center; font-size: 1.05rem; padding: 15px; }
.ds-book-price { font-size: 1.35rem; font-weight: 700; color: var(--ds-primary); margin: 0 0 4px; }
/* searched stay: the Lodgix total (rent + cleaning fee + taxes) the checkout will ask for */
.ds-book-price-total .ds-book-nights { font-size: .95rem; font-weight: 600; color: var(--ds-muted); }
.ds-book-hint { font-size: .84rem; color: var(--ds-muted); margin: 12px 0 0; text-align: center; }
.ds-book-hint.is-warn { color: #b45309; font-weight: 600; }
.ds-map { height: 260px; border-radius: var(--ds-radius); overflow: hidden; border: 1px solid var(--ds-border); background: var(--ds-bg-soft); }

/* the live property page has no separate availability-calendar section */

/* ==========================================================================
   Date-range picker / calendar
   ========================================================================== */
.ds-dp { position: fixed; top: 0; left: 0; z-index: 90; max-width: calc(100vw - 24px); overflow: auto; background: #fff; border: 1px solid var(--ds-border); border-radius: var(--ds-radius); box-shadow: var(--ds-shadow-lg); padding: 16px; width: min(680px, calc(100vw - 24px)); }
@media (max-width: 640px) { .ds-dp { position: fixed; left: 0; right: 0; bottom: 0; top: auto; width: 100%; border-radius: 16px 16px 0 0; max-height: 82vh; overflow: auto; } }
/* desktop: datepicker.js place() sets top/left/max-height from the date fields' viewport rect (below them, flipped above or clamped when short of room); the panel lives on <body> */
@media (max-width: 640px) {
  .ds-dp { z-index: 300; box-shadow: 0 -8px 30px rgba(0,0,0,.25); padding-bottom: max(16px, env(safe-area-inset-bottom)); }
  .ds-dp-month { width: 100%; }
  .ds-dp-actions { position: sticky; bottom: 0; background: #fff; padding-top: 10px; }
}
/* read-only text fields that stand in for the native date inputs (datepicker.js mountRangePicker) */
.ds-date-field { cursor: pointer; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23415a77' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2'/%3E%3Cpath d='M16 2v4M8 2v4M3 10h18'/%3E%3C/svg%3E") !important; background-repeat: no-repeat !important; background-position: right 12px center !important; padding-right: 36px !important; }
.ds-dp-months { display: flex; gap: 30px; flex-wrap: wrap; }
@media (max-width: 640px) { .ds-dp-months { flex-direction: column; gap: 18px; } }
.ds-dp-month { width: 295px; }
.ds-dp-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; font-weight: 600; }
.ds-dp-nav { background: none; border: 1px solid var(--ds-border); border-radius: 6px; width: 32px; height: 32px; cursor: pointer; color: var(--ds-primary); font-size: 1rem; line-height: 1; }
.ds-dp-nav:disabled { opacity: .35; cursor: default; }
/* both arrows sit in one cluster when the panel shows a single month (phones) */
.ds-dp-navs { display: inline-flex; gap: 6px; }
@media (max-width: 640px) { .ds-dp-nav { width: 40px; height: 40px; font-size: 1.15rem; } }
.ds-dp-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; text-align: center; font-size: .8rem; }
.ds-dp-grid .dow { color: var(--ds-muted); font-weight: 600; padding: 6px 0; }
.ds-dp-grid .day { padding: 0; height: 36px; display: flex; align-items: center; justify-content: center; border: none; background: none; border-radius: 6px; cursor: pointer; font-family: inherit; font-size: .82rem; color: var(--ds-text); }
.ds-dp-grid .day:hover { background: var(--ds-bg-soft); }
.ds-dp-grid .day.empty { cursor: default; }
.ds-dp-grid .day.booked { color: #cbd5e1; text-decoration: line-through; cursor: not-allowed; background: repeating-linear-gradient(45deg, #f8fafc, #f8fafc 4px, #eef2f7 4px, #eef2f7 8px); }
.ds-dp-grid .day.in-range { background: rgba(6,90,96,.12); border-radius: 0; }
.ds-dp-grid .day.selected { background: var(--ds-primary); color: #fff; font-weight: 700; }
.ds-dp-grid .day.today { outline: 1.5px solid var(--ds-accent); }
.ds-dp-actions { display: flex; justify-content: space-between; align-items: center; margin-top: 12px; gap: 10px; }
.ds-dp-hint { font-size: .82rem; color: var(--ds-muted); }
.ds-dp-hint.warn { color: #b45309; }

.ds-cal-month { min-width: 295px; border: 1px solid var(--ds-border); border-radius: var(--ds-radius); padding: 14px; }
.ds-cal-month h4 { margin: 0 0 10px; text-align: center; font-size: .95rem; }

/* ==========================================================================
   Lightbox
   ========================================================================== */
/* Solid, not translucent: at .92 the page text showed through behind the caption and
   the counter, which reads as a rendering artefact in a full-screen photo view. */
.ds-lightbox { position: fixed; inset: 0; z-index: 300; background: #0a0f14; display: flex; align-items: center; justify-content: center; }
.ds-lightbox img { max-width: 92vw; max-height: 86vh; border-radius: var(--ds-radius-sm); }
.ds-lightbox .ds-lb-close { position: absolute; top: 18px; right: 22px; background: none; border: none; color: #fff; font-size: 2.4rem; cursor: pointer; line-height: 1; }
.ds-lightbox .ds-lb-nav { position: absolute; top: 50%; transform: translateY(-50%); font-size: 2.6rem; color: #fff; background: none; border: none; cursor: pointer; padding: 20px; }
.ds-lightbox .ds-lb-prev { left: 10px; right: auto; }
.ds-lightbox .ds-lb-next { right: 10px; left: auto; }
/* Lightbox chrome added with the "show all photos" work: caption, counter, thumbnail rail. */
.ds-lightbox .ds-lb-stage { margin: 0; display: flex; flex-direction: column; align-items: center; gap: 10px; max-width: 92vw; }
.ds-lightbox .ds-lb-stage img { max-width: 92vw; max-height: 76vh; display: block; }
.ds-lightbox .ds-lb-stage figcaption { color: rgba(255,255,255,.88); font-size: .86rem; line-height: 1.4; text-align: center; max-width: 720px; }
.ds-lightbox .ds-lb-bar { position: absolute; top: 16px; left: 20px; right: 20px; display: flex; align-items: center; justify-content: space-between; pointer-events: none; }
.ds-lightbox .ds-lb-bar .ds-lb-close { position: static; pointer-events: auto; }
.ds-lightbox .ds-lb-count { color: #fff; font-size: .88rem; font-weight: 600; font-variant-numeric: tabular-nums; text-shadow: 0 1px 3px rgba(0,0,0,.5); }
.ds-lightbox .ds-lb-rail { position: absolute; left: 0; right: 0; bottom: 0; display: flex; gap: 6px; padding: 12px 14px; overflow-x: auto; background: linear-gradient(to top, rgba(0,0,0,.6), rgba(0,0,0,0)); scrollbar-width: thin; }
.ds-lightbox .ds-lb-rail button { flex: 0 0 auto; width: 84px; height: 56px; padding: 0; border: 2px solid transparent; border-radius: 6px; overflow: hidden; background: none; cursor: pointer; opacity: .6; }
.ds-lightbox .ds-lb-rail button:hover { opacity: .9; }
.ds-lightbox .ds-lb-rail button.is-current { opacity: 1; border-color: #fff; }
.ds-lightbox .ds-lb-rail img { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: 0; }
/* Position-fixed body, not just overflow:hidden: iOS Safari scrolls the page behind a
   full-screen overlay otherwise. The scroll offset is kept in body.style.top by main.js
   and restored on close. */
body.ds-noscroll { position: fixed; top: 0; left: 0; right: 0; width: 100%; overflow: hidden; }
/* The Chaty WhatsApp bubble is z-index 99999 and floats over the bottom-right corner,
   which is where the lightbox thumbnail rail now lives: it swallowed clicks on the last
   thumbnails. Hide the floating widgets while the gallery is open. */
body.ds-noscroll .chaty,
body.ds-noscroll .chaty-outer-forms { display: none !important; }
@media (max-width: 640px) {
  .ds-lightbox .ds-lb-rail button { width: 64px; height: 44px; }
  .ds-lightbox .ds-lb-stage img { max-height: 68vh; }
}

/* ==========================================================================
   Footer
   ========================================================================== */
.ds-footer { background: var(--ds-primary-dark); color: #dbe7e8; margin-top: 60px; }
.ds-footer-inner { max-width: var(--ds-container-wide); margin: 0 auto; padding: 46px var(--ds-gutter) 26px; display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 34px; }
@media (max-width: 800px) { .ds-footer-inner { grid-template-columns: 1fr; } }
.ds-footer a { color: #fff; }
.ds-footer a:hover { color: #9fd4d8; }
.ds-footer ul { list-style: none; margin: 0; padding: 0; }
.ds-footer-menu li { padding: 5px 0; font-size: .93rem; }
.ds-company { font-size: .93rem; line-height: 1.9; margin: 0; }
.ds-footer-legal ul { margin-bottom: 16px; }
.ds-footer-legal li { padding: 5px 0; font-size: .93rem; }
.ds-footer-langs { display: flex; gap: 8px; flex-wrap: wrap; }
.ds-footer-langs li { padding: 0 !important; }
.ds-footer-langs a { display: inline-block; padding: 6px 12px; border: 1px solid rgba(255,255,255,.28); border-radius: 999px; font-size: .85rem; }
.ds-footer-langs a.active { background: #fff; color: var(--ds-primary-dark); border-color: #fff; pointer-events: none; }
.ds-socials { display: flex; gap: 14px; }
.ds-socials a { color: #bcd9db; }
.ds-socials a:hover { color: #fff; }
.ds-copyright { border-top: 1px solid rgba(255,255,255,.14); text-align: center; font-size: .82rem; padding: 16px; color: #9fc3c6; }

/* ==========================================================================
   Floating widgets / cookie
   ========================================================================== */
/* No-JS fallback for the Chaty widget (see src/Chaty.php): with JavaScript on,
   Chaty renders its own floating icon and this markup is never in the DOM. */
.ds-whatsapp { position: fixed; right: 20px; bottom: 20px; z-index: 120; width: 58px; height: 58px; border-radius: 50%; background: var(--ds-whatsapp); color: #053d10; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 22px rgba(0,0,0,.24); transition: transform .18s ease; }
.ds-whatsapp:hover { transform: scale(1.08); color: #053d10; }
/* Chaty (WhatsApp) on phones: the permanent "Contact us" label covered card CTAs
   and the search button; keep the icon, drop the label there. */
@media (max-width: 700px) {
  .chaty-channel .on-hover-text, .chaty-channel .chaty-hover-text { display: none !important; }
}

.ds-cookie { position: fixed; left: 50%; transform: translateX(-50%); bottom: 18px; z-index: 200; background: #fff; border: 1px solid var(--ds-border); border-radius: var(--ds-radius); box-shadow: var(--ds-shadow-lg); padding: 18px 22px; max-width: min(560px, calc(100vw - 32px)); }
.ds-cookie p { margin: 0 0 12px; font-size: .9rem; }
.ds-cookie-actions { display: flex; gap: 10px; justify-content: flex-end; }

/* ==========================================================================
   Forms
   ========================================================================== */
.ds-form-card { max-width: 640px; margin: 30px auto; background: #fff; border: 1px solid var(--ds-border); border-radius: var(--ds-radius); box-shadow: var(--ds-shadow); padding: 28px; }

/* Fields carry their caption INSIDE the box (templates/formpage.php): it rests
   where a placeholder would sit and floats to the top of the field on focus or
   as soon as there is a value. The caption is therefore always drawn on the
   input's own white surface - which is the point, because the contact form also
   renders on photo sections, where a caption printed straight onto the photo was
   unreadable. It stays a real <label>, so it never disappears the way a
   placeholder does.
   `placeholder=" "` is what makes :placeholder-shown usable as the "still empty"
   test. Controls that have no placeholder of their own - date, file, select -
   float their caption permanently, because they always show a value (dd.mm.yyyy,
   Choose file, the default option). */
.ds-form .ds-field { position: relative; display: block; margin-bottom: 14px; font-weight: 400; }
.ds-form .ds-field > input,
.ds-form .ds-field > textarea { padding: 22px 14px 8px; }
.ds-form .ds-field-label {
  position: absolute; left: 15px; right: 15px; top: 15px;
  color: #6b7280; font-size: .95rem; line-height: 1.3; font-weight: 400;
  pointer-events: none;
  transition: top .14s ease, font-size .14s ease, color .14s ease;
}
.ds-form .ds-field > input + .ds-field-label { top: 50%; transform: translateY(-50%); }
.ds-form .ds-field > input:focus + .ds-field-label,
.ds-form .ds-field > input:not(:placeholder-shown) + .ds-field-label,
.ds-form .ds-field > input[type="date"] + .ds-field-label,
.ds-form .ds-field > input[type="file"] + .ds-field-label,
.ds-form .ds-field > select + .ds-field-label,
.ds-form .ds-field > textarea:focus + .ds-field-label,
.ds-form .ds-field > textarea:not(:placeholder-shown) + .ds-field-label {
  top: 7px; transform: none; font-size: .7rem; font-weight: 600;
  letter-spacing: .03em; color: var(--ds-primary);
}
.ds-form .ds-field > input[type="file"] { padding-top: 25px; }
.ds-form .ds-field > input::placeholder,
.ds-form .ds-field > textarea::placeholder { color: transparent; }

/* WebKit draws <select> (and, on iOS, input[type=date]) as its own native widget
   (appearance: menulist): vertical padding is IGNORED there and the value is
   vertically centred, so it landed on the floated caption ("Purpose of stay"
   printed over "Leisure") and the control came out shorter than the text inputs
   beside it. Taking over the appearance makes every engine honour the padding -
   the value sits below the caption again - and one shared min-height + pinned
   line-height keep every .ds-field control the same height on every engine.
   The native chevron disappears with the widget, so the select carries its own
   (SVG, caption gray) one. Scoped to .ds-form on purpose: the listing filters
   (.ds-filters) and the .pc-search fields keep their native widgets. */
.ds-form .ds-field > input,
.ds-form .ds-field > select {
  min-height: 51px; /* 22 + 8px padding, 19px line, 2px border */
  line-height: 1.25;
}
.ds-form .ds-field > select {
  -webkit-appearance: none;
  appearance: none;
  padding: 22px 40px 8px 14px; /* right side leaves room for the own chevron */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1.5 1.5 6 6l4.5-4.5' fill='none' stroke='%236b7280' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px top 27px;
  background-size: 12px 8px;
}
/* iOS also centres input[type=date]'s value while it may draw its own widget;
   as a plain box the 22px top padding puts dd.mm.yyyy below the caption. The
   calendar-picker indicator keeps rendering in Blink (it is its own
   pseudo-element). */
.ds-form .ds-field > input[type="date"] {
  -webkit-appearance: none;
  appearance: none;
}

.ds-form input, .ds-form textarea, .ds-form select { font-family: inherit; font-size: .95rem; border: 1px solid var(--ds-border); border-radius: var(--ds-radius-sm); width: 100%; color: var(--ds-text); background: #fff; }
.ds-form input:focus, .ds-form textarea:focus, .ds-form select:focus { outline: 2px solid rgba(6, 90, 96, .35); outline-offset: 1px; border-color: var(--ds-primary); }
.ds-form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 560px) { .ds-form-row { grid-template-columns: 1fr; } }
.ds-form-check { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 14px; font-size: .85rem; font-weight: 400; color: var(--ds-text); }
.ds-form-check input[type="checkbox"] { width: auto; padding: 0; margin-top: 4px; flex: 0 0 auto; }
/* hidden fields must not become flex items */
.ds-form > input[type="hidden"].ds-honeypot,
.ds-honeypot { position: absolute; left: -9999px; }

/* ==========================================================================
   The contact block: ONE design, two surfaces
   --------------------------------------------------------------------------
   App\ContactBlock turns every "Contact us!" block into the same shape - the
   copy column (.ds-contact-body: title, intro, contact rows with an icon each)
   beside the form column, inside .ds-contact-wrap. Only the SURFACE differs:

     .ds-contact--photo   the section keeps its background photo; the copy
                          column is the frosted card the other photo sections
                          get from the .pc-photo rules above, and every line of
                          copy is white (the pages themselves measured dark ink
                          for the contact lines, which is what made them
                          unreadable there)
     .ds-contact--plain   no photo: the same card in a light, quiet dressing,
                          with the site's teal / ink copy

   The form column stays bare on both surfaces: its captions live inside its own
   white inputs, so it needs no card to be readable.
   ========================================================================== */
.ds-contact-wrap { flex-direction: row; column-gap: clamp(24px, 3.5vw, 48px); }
/* Two equal columns that share the row exactly: flex-basis 0 + grow 1 subtracts
   the wrapper's gap before the split, so the pair can never overflow it (the
   normalizer's own --p-dir / --p-w values for this block do not add up to a
   usable row, so the block states the row itself). */
.ds-contact-wrap > .ds-contact-body,
.ds-contact-wrap > .ds-form-slot { flex: 1 1 0; width: auto; min-width: 0; }
/* only the FORM is unboxed in its column (its captions live inside its own white
   inputs). The success box keeps its card: stripped of it, the one-line
   confirmation was green ink on a photo - the same unreadable state as the
   captions, one state further along. */
.ds-contact-wrap > .ds-form-slot > .ds-form-card { max-width: none; margin: 0; background: none; border: 0; box-shadow: none; padding: 0; }
.ds-contact-wrap > .ds-form-slot > .ds-form-success { max-width: none; margin: 0; }
@media (max-width: 1024px) {
  .ds-contact-wrap { flex-direction: column; column-gap: normal; row-gap: 28px; }
  .ds-contact-wrap > .ds-contact-body,
  .ds-contact-wrap > .ds-form-slot { flex: 0 0 auto; width: auto; }
}

/* The contact card is a touch darker than the section cards above - .48 against
   .38. It is the one photo surface that also carries the two contact lines and a
   paragraph of 15px copy, and on the brightest photos (et/kkk) the .38 card left
   that white body text at 2.8:1 - exactly the unreadable state the operator
   reported. Measured over the photo pages (scripts/check-contact.js) the worst
   case is 4.9:1 for the paragraph and 5.1:1 for the contact lines; the About us
   and Visit Tallinn cards keep the value they were asked to keep. */
/* the extra class is not decoration: the .pc-photo > .pc-wrap > .pc-col rule
   above paints the section card with three classes, so this needs the same
   three plus one to win - at equal weight the card falls back to .38 */
.ds-contact.ds-contact--photo > .ds-contact-wrap > .ds-contact-body { background: rgba(12, 22, 30, .48); }

/* the plain surface: the same card, light dressing */
.ds-contact--plain .ds-contact-body {
  background: #fff; border: 1px solid var(--ds-border); border-radius: 16px;
  padding: clamp(20px, 2.6vw, 34px); box-shadow: var(--ds-shadow);
}
@media (max-width: 1024px) { .ds-contact--plain .ds-contact-body { padding: clamp(18px, 3.4vw, 26px); } }

.ds-contact-title { margin-bottom: .5em; }
.ds-contact-intro { margin-bottom: 1.1em; }
.ds-contact-rows { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.ds-contact-row { display: flex; align-items: center; gap: 12px; font-size: .95rem; line-height: 1.45; }
.ds-contact-ico { flex: 0 0 auto; width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.ds-contact-row a { text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }

.ds-contact--photo .ds-contact-title,
.ds-contact--photo .ds-contact-intro,
.ds-contact--photo .ds-contact-intro p,
.ds-contact--photo .ds-contact-row,
.ds-contact--photo .ds-contact-row a { color: #fff; }
.ds-contact--photo .ds-contact-row a:hover { color: var(--ds-soft); }
.ds-contact--plain .ds-contact-title,
.ds-contact--plain .ds-contact-row,
.ds-contact--plain .ds-contact-row a { color: var(--ds-primary); }
.ds-contact--plain .ds-contact-intro,
.ds-contact--plain .ds-contact-intro p { color: var(--ds-text); }
.ds-contact--plain .ds-contact-row a:hover { color: var(--ds-primary-dark); }
.ds-form-success { max-width: 640px; margin: 30px auto; background: #ecfdf5; border: 1px solid #a7f3d0; border-radius: var(--ds-radius); padding: 18px; color: #065f46; }
.ds-404, .ds-confirmation { max-width: 640px; margin: 0 auto; padding: 80px var(--ds-gutter); text-align: center; }
.ds-404 h1 { font-family: var(--ds-serif); font-size: clamp(64px, 10vw, 110px); line-height: 1; color: var(--ds-primary); margin-bottom: 10px; }
.ds-404 p { font-size: 1.05rem; color: var(--ds-muted); }
.ds-404-links { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin-top: 22px; }
.ds-page { font-size: 1rem; }
.ds-page img { border-radius: var(--ds-radius); }

/* ---------- form additions from the 2026-09-18 feedback round ---------- */
/* The guest form's "whose details are these?" line, above the fields. */
.ds-form-intro { margin: 0 0 18px; font-size: .9rem; line-height: 1.55; color: var(--ds-text); }
/* Additional guest names: a repeatable block, not one more anonymous field. */
.ds-repeat { border: 0; margin: 0 0 14px; padding: 0; min-width: 0; }
.ds-repeat-legend { padding: 0; font-size: .95rem; font-weight: 600; color: var(--ds-text); }
.ds-repeat-hint { margin: 4px 0 10px; font-size: .8rem; line-height: 1.45; color: var(--ds-muted); }
.ds-repeat-row { position: relative; }
.ds-repeat-row .ds-field { margin-bottom: 10px; }
.ds-repeat-add { padding: 9px 18px; font-size: .85rem; }
.ds-repeat-remove {
  position: absolute; top: 8px; right: 8px; z-index: 2; width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center; padding: 0;
  font: inherit; font-size: 1.1rem; line-height: 1; cursor: pointer;
  color: var(--ds-muted); background: #fff; border: 1px solid var(--ds-border); border-radius: 50%;
}
.ds-repeat-remove:hover { color: #b91c1c; border-color: #fca5a5; }
.ds-repeat-row .ds-field > input { padding-right: 44px; }
/* Stay dates on the corporate form: a legend instead of two mystery date boxes. */
.ds-fieldset { border: 0; margin: 0 0 14px; padding: 0; min-width: 0; }
.ds-fieldset-legend { padding: 0 0 6px; font-size: .95rem; font-weight: 600; color: var(--ds-text); }
.ds-field-hint { margin: -6px 0 14px; font-size: .8rem; line-height: 1.45; color: var(--ds-muted); }
/* The house-rules link has to read as a link, not as coloured body copy. */
.ds-form-check a { color: var(--ds-primary); text-decoration: underline; text-underline-offset: 2px; }
.ds-form-check a:hover { color: var(--ds-primary-dark); }


/* rotating hero background (background_slideshow) */
.pc-sec[data-bgslideshow] { overflow: hidden; }
.pc-sec[data-bgslideshow] > .pc-bglayer { position: absolute !important; inset: 0 !important; z-index: 0 !important; background-size: cover; background-position: center; opacity: 0; transition: opacity 1.4s ease; }
.pc-sec[data-bgslideshow] .pc-bglayer.on { opacity: 1; }

/* ==========================================================================
   Property page additions (gallery pill, chips, quick nav, places, policies,
   reviews, related, booking sidebar extras)
   ========================================================================== */
.ds-prop-chips { display: flex; flex-wrap: wrap; gap: 6px 10px; margin: 6px 0 20px; color: var(--ds-muted); font-size: .95rem; }
.ds-prop-chips span + span::before { content: '\2022'; margin-right: 10px; color: var(--ds-border); }

.ds-gallery-frame { position: relative; }
.ds-gallery-viewall { position: absolute; right: 16px; bottom: 12px; z-index: 2; height: 40px; padding: 0 20px; border: 0; border-radius: 5px; background: rgba(255,255,255,.94); color: var(--ds-primary); font-family: inherit; font-weight: 600; font-size: .88rem; cursor: pointer; box-shadow: var(--ds-shadow); }
.ds-gallery-viewall:hover { background: #fff; }

.ds-prop-nav { margin: 22px 0 0; border-top: 1px solid var(--ds-border); border-bottom: 1px solid var(--ds-border); }
.ds-prop-nav ul { list-style: none; display: flex; flex-wrap: wrap; gap: 4px 22px; margin: 0; padding: 10px 0; }
.ds-prop-nav a { font-size: .82rem; font-weight: 700; letter-spacing: .03em; text-transform: uppercase; color: var(--ds-text); padding: 4px 0; border-bottom: 2px solid transparent; }
.ds-prop-nav a:hover { color: var(--ds-primary); border-bottom-color: var(--ds-primary); }

.ds-prop-main section, .ds-prop-location, .ds-prop-policies, .ds-prop-reviews, .ds-related { scroll-margin-top: calc(var(--ds-header-h) + 16px); }
.ds-prop-main section { margin-bottom: 44px; }
.ds-prop-main section:last-child { margin-bottom: 0; }
.ds-prop-main h2 { margin-bottom: 18px; }
.ds-prop-main h3 { font-size: 1rem; font-weight: 600; font-family: var(--ds-font); margin: 0 0 4px; }

.ds-places { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(210px, 100%), 1fr)); gap: 16px; }
.ds-place { border: 1px solid var(--ds-border); border-radius: var(--ds-radius-sm); padding: 16px; background: #fff; }
.ds-place-bed { margin: 0 0 2px; font-weight: 600; color: var(--ds-text); }

.ds-amenity-group { margin-bottom: 22px; }
.ds-amenities { grid-template-columns: repeat(auto-fill, minmax(min(200px, 100%), 1fr)); }

.ds-map-wide { height: 520px; }
@media (max-width: 767px) { .ds-map-wide { height: 320px; } }

.ds-prop-location, .ds-prop-policies, .ds-prop-reviews, .ds-related { margin-top: 48px; }
.ds-policy { margin-bottom: 18px; }
.ds-policy h3 { font-size: 1rem; }
.ds-review-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr)); gap: 18px; }
.ds-review { border: 1px solid var(--ds-border); border-radius: var(--ds-radius-sm); padding: 16px 18px; background: #fff; }
.ds-review-head { display: flex; justify-content: space-between; gap: 10px; margin: 0 0 6px; }
.ds-review-stars { color: #f5a623; letter-spacing: 1px; }
.ds-reviews-count { color: var(--ds-muted); margin-top: -10px; }

.ds-book-guests { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: .9rem; font-weight: 600; color: var(--ds-muted); margin-bottom: 12px; }
.ds-book-guests input { width: 84px; font-family: inherit; font-size: .95rem; padding: 9px 10px; border: 1px solid var(--ds-border); border-radius: var(--ds-radius-sm); }
.ds-book-fees { list-style: none; padding: 10px 0 0; margin: 10px 0 0; border-top: 1px solid var(--ds-border); font-size: .85rem; color: var(--ds-muted); }
.ds-book-note { font-size: .78rem; color: var(--ds-muted); margin: 8px 0 0; text-align: center; }

.ds-related .ds-cards { grid-template-columns: repeat(auto-fill, minmax(235px, 1fr)); gap: 18px; }
.ds-related .ds-card-title { font-size: .95rem; }

/* measured text alignment also positions block-level images in a widget wrapper */
.pc-item[style*="--p-ta:end"], .pc-item[style*="--p-ta: right"] { display: flex; justify-content: flex-end; }
.pc-item[style*="--p-ta:center"] { display: flex; justify-content: center; }

/* ==========================================================================
   Legibility for copy sitting directly on a photo (operator request):
   a frosted card behind the copy COLUMN of split/band photo sections, and a
   plain text shadow for hero copy that sits on the photo itself.
   ========================================================================== */
.pc-photo > .pc-wrap > .pc-col {
  background: rgba(12, 22, 30, .38);
  -webkit-backdrop-filter: blur(7px) saturate(1.15);
  backdrop-filter: blur(7px) saturate(1.15);
  border: 1px solid rgba(255, 255, 255, .14);
  border-radius: 16px;
  padding: clamp(20px, 2.6vw, 34px);
  box-shadow: 0 10px 34px rgba(0, 0, 0, .18);
}
.pc-photo > .pc-wrap > .pc-col.pc-spacer { background: none; border: 0; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; padding: 0; }
.pc-photo > .pc-wrap > .pc-col .pc-btn { margin-top: 6px; }
@media (max-width: 1024px) {
  .pc-photo > .pc-wrap > .pc-col { padding: clamp(18px, 3.4vw, 26px); }
}
/* Hero copy (the wrap holds the text widgets directly) keeps the white text the
   pages measure; text-shadow inherits, so one rule on the wrap covers every
   heading and paragraph inside it. Recipe picked by measurement (see
   scripts/check-hero-text-shadow.js): a wide even halo plus a soft drop beat the
   old 0 1px 12px shadow on the glyph edge - ring contrast around the strokes
   goes from 1.2:1 (no shadow) to 1.8:1 at p95 and 3.4:1 on average. */
.pc-photo > .pc-wrap:not(:has(> .pc-col)) { text-shadow: 0 0 4px rgba(0, 0, 0, .9), 0 2px 22px rgba(0, 0, 0, .6); }
.pc-photo > .pc-wrap:not(:has(> .pc-col)) > .pc-btn { text-shadow: none; }

/* ==========================================================================
   Photo cards: rounded, separated, no black placeholder while images load
   ========================================================================== */
.pc-banner { border-radius: 12px; }
.pc-banner img { border-radius: 12px; }
/* The four area banners come in two shapes: on the area pages each card is a
   direct child of the wrap (a row of four), while on the home / articles / guide
   pages the card sits one level deeper in its own wrap (a column of full-width
   cards).  Only the first shape matched, so the stacked bands had gap:0 and the
   cards touched each other - both shapes get the separation now. */
.pc-wrap:has(> .pc-col > .pc-banner),
.pc-wrap:has(> .pc-col > .pc-wrap > .pc-banner) { gap: 16px; }
@media (max-width: 1024px) {
  .pc-wrap:has(> .pc-col > .pc-banner),
  .pc-wrap:has(> .pc-col > .pc-wrap > .pc-banner) { gap: 14px; }
}
.pc-photo > .pc-wrap:has(> .pc-col > .pc-banner) > .pc-col { background: none; border: 0; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; padding: 0; }

/* the listing filter is a booking search: dates first, and they wrap nicely */
.ds-filters input[type="date"] { font-family: inherit; min-width: 160px; cursor: pointer; }
.ds-count-dates { display: block; font-size: .9rem; color: var(--ds-text); font-weight: 600; }
/* the dated listing explains what the card totals include (Lodgix quote = rent + fees + taxes) */
.ds-count-note { display: block; margin-top: 4px; font-size: .85rem; color: var(--ds-muted); }
/* a date range that already started cannot be searched or priced - say so instead of
   quietly showing a listing that claims availability for past nights */
.ds-count-warn { color: #b45309; }
.ds-empty { text-align: center; padding: 60px 20px; border: 1px dashed var(--ds-border); border-radius: var(--ds-radius); background: var(--ds-bg-soft); }
.ds-empty h2 { margin-bottom: 8px; }
.ds-empty p { color: var(--ds-muted); }

/* ---------------------------------------------------------------- property band
   Rendered where the old WordPress site had a Lodgix "featured properties"
   widget: the area landing pages (/north-tallinn-apartments/ ...) and the small
   cross-sell strips on the guide pages. Uses the listing's card grid so a card
   looks the same everywhere. */
/* The band is a child of the page's .pc-wrap flex column, where an auto margin
   would shrink it to fit-content - width:100% makes it fill the measured
   container, and the card grid is left to the listing's own .ds-cards rules so a
   card looks the same on every page. */
.ds-props { width: 100%; max-width: var(--ds-container-wide); margin: 0 auto; padding: 0 0 56px; }
.ds-props-head { display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: 10px; margin-bottom: 18px; }
.ds-props-head h2 { margin: 0; font-size: clamp(1.4rem, 2.4vw, 1.95rem); color: var(--ds-primary); }
.ds-props .ds-count { margin: 0; color: var(--ds-muted); }
.ds-props .ds-cards { margin-top: 4px; }
.ds-props-more { margin: 26px 0 0; text-align: center; }
.ds-filters--band { margin-bottom: 26px; }
.ds-props-reset { margin: -6px 0 18px; }
.pc-sec--props { --p-mt-m: 12px; --p-pt: 24px; }
.ds-props { scroll-margin-top: calc(var(--ds-header-h) + 16px); }
@media (max-width: 700px) {
  .ds-props { padding-bottom: 36px; }
}


/* Area tiles (old Lodgix "categories" widget on /tallinn-accommodation/): four
   photo tiles with the live apartment count per area. */
.ds-area-tiles { width: 100%; display: grid; grid-template-columns: repeat(4, 1fr); gap: 22px; }
.ds-area-tile { position: relative; display: block; border-radius: var(--ds-radius); overflow: hidden; background: #fff; box-shadow: var(--ds-shadow); color: inherit; text-decoration: none; transition: transform .18s ease, box-shadow .18s ease; }
.ds-area-tile:hover { transform: translateY(-3px); box-shadow: var(--ds-shadow-lg); }
.ds-area-tile img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; display: block; }
.ds-area-tile-body { display: block; padding: 14px 16px 16px; }
.ds-area-tile-name { display: block; font-weight: 700; color: var(--ds-primary); }
.ds-area-tile-count { display: block; font-size: .85rem; color: var(--ds-muted); }
@media (max-width: 1000px) { .ds-area-tiles { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .ds-area-tiles { grid-template-columns: 1fr; gap: 16px; } }


/* ==========================================================================
   Blog archive: the old Unlimited Elements "post filter" + "post blocks"
   widgets on /articles/, /category/* and the FI/ET artikkelit pages,
   rebuilt by the normalizer as a category pill bar and a responsive card grid.
   ========================================================================== */
.pc-cats { display: flex; flex-wrap: wrap; gap: 10px; margin: 0 0 28px; }
.pc-cat { display: inline-block; padding: 7px 18px; border: 1px solid var(--ds-border); border-radius: 999px; background: var(--ds-bg); color: var(--ds-text); font-size: .92rem; font-weight: 500; line-height: 1.25; transition: background-color .15s ease, border-color .15s ease, color .15s ease; }
.pc-cat:hover { border-color: var(--ds-primary); color: var(--ds-primary); }
.pc-cat.is-active, .pc-cat.is-active:hover { background: var(--ds-primary); border-color: var(--ds-primary); color: #fff; }

.pc-posts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 26px; width: 100%; }
.pc-post { display: flex; flex-direction: column; min-width: 0; background: var(--ds-bg); border-radius: var(--ds-radius); box-shadow: var(--ds-shadow); overflow: hidden; }
.pc-post-media { display: block; }
/* border-radius 0: .ds-page img rounds every image, which would notch the card
   body seam - the card's own overflow hidden does the rounding */
.pc-post-media img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; display: block; border-radius: 0; }
.pc-post-body { display: flex; flex-direction: column; gap: 8px; flex: 1 1 auto; padding: 18px 20px 20px; }
.pc-post-title { margin: 0; font-family: var(--ds-font); font-weight: 600; font-size: 1.05rem; line-height: 1.35; }
.pc-post-title a { color: var(--ds-text); }
.pc-post-title a:hover { color: var(--ds-primary); }
.pc-post-excerpt { margin: 0; color: var(--ds-muted); font-size: .95rem; }
.pc-post-more { margin-top: auto; align-self: flex-start; padding-top: 6px; color: var(--ds-primary); font-weight: 600; font-size: .95rem; }
.pc-post-more:hover { color: var(--ds-accent); }
@media (max-width: 1024px) { .pc-posts { grid-template-columns: repeat(2, 1fr); gap: 20px; } }
@media (max-width: 700px) { .pc-posts { grid-template-columns: 1fr; gap: 18px; } }

/* The /category/* archives ship no section chrome: nav and grid are the whole
   page body, so here they carry the container and gutters themselves. On the
   listing pages they sit inside a .pc-wrap and stay untouched by this. */
.ds-page > .pc-cats, .ds-page > .pc-posts { max-width: var(--ds-container); margin-left: auto; margin-right: auto; padding-left: var(--ds-gutter); padding-right: var(--ds-gutter); }
.ds-page > .pc-cats { margin-top: clamp(30px, 5vw, 56px); }
/* the mirrored archive section carried 150px margins top and bottom - a hole under the hero */
.pc-sec:has(> .pc-wrap > .pc-cats) { --p-mt: 48px; --p-mb: 48px; --p-mt-m: 12px; --p-mb-m: 12px; }
.ds-page > .pc-posts { margin-bottom: clamp(44px, 6vw, 80px); }

