/*
 * Vira editorial property page — consolidated implementation (UX polish pass).
 *
 * The entire layer is scoped to data-ts-property="vira" and only styles the
 * markup produced by ts_property_vira_reference_page() / ts_property_booking_panel()
 * in includes/property-seo.php. It does not alter the shared listing template
 * used by the other properties, and it does not touch booking logic, pricing,
 * availability, Stripe or cancellation rules — those remain owned by the
 * shared booking markup/JS and are only restyled here.
 *
 * This file replaces ~10 stacked "generations" of overrides that previously
 * lived here (each appending new rules on top of the last, several of them
 * contradicting earlier ones). It is written as a single authoritative pass:
 * one width system, one typography scale, one booking-rail scroll behaviour.
 * Please extend sections in place rather than appending a new override layer.
 */

/* ==========================================================================
   1. Tokens, reset, base
   ========================================================================== */
.ts-vira-reference {
  /* Width system.
     - shell-wide: hero/gallery/related/footer ceiling — lets photography and
       the closing sections use noticeably more of very wide viewports.
     - shell: main two-column layout (editorial column + booking rail).
     - prose: long-form paragraph measure, kept narrow for readability even
       though the surrounding shell is wide.
     - rail: fixed comfortable width for the booking column. */
  --ts-vira-shell-wide: 1680px;
  --ts-vira-shell: 1480px;
  --ts-vira-prose: 740px;
  --ts-vira-rail: minmax(370px, 410px);
  --ts-vira-gutter: clamp(20px, 3vw, 64px);
  --ts-vira-row-label: clamp(160px, 13vw, 200px);
  --ts-vira-row-gap: clamp(28px, 3.4vw, 56px);

  /* Vira keeps its own token names, but they now resolve to the shared
     brand scale so the property page and the homepage round the same. */
  --ts-vira-radius-lg: var(--ts-r-panel, 20px);
  --ts-vira-radius-md: var(--ts-r-media, 14px);
  --ts-vira-radius-sm: var(--ts-r-control, 10px);
  --ts-vira-line: var(--ts-brand-line, rgba(21, 26, 23, .10));
  --ts-vira-mint: #e6eee9;
  --ts-vira-soft: #59645e;

  /* One type scale for the whole page.
     h1 is a single continuous clamp: the calc() mixes a fixed and a viewport
     part so the size only ever DECREASES as the viewport narrows
     (~86px @1440 → ~67px @1024 → ~56px @768 → 42px floor by ~450). There are
     deliberately no breakpoint-specific h1 font-size overrides below — an
     earlier 9vw tablet rule made the title grow again at 768. */
  --ts-vira-h1: clamp(42px, 1.4rem + 4.4vw, 98px);
  --ts-vira-h2: clamp(28px, 2.15vw, 34px);
  /* The brand display serif, shared with the homepage hero. Falls back to a
     high-contrast system Didone, then Georgia. Swap this one token if a
     licensed webface is added later. */
  --ts-vira-display: var(--ts-font-hero, "Didot", "Bodoni 72", "Bodoni MT", "Playfair Display", Georgia, serif);
  --ts-vira-eyebrow: 13px;
  --ts-vira-body: 17px;
  --ts-vira-body-lh: 1.66;
  --ts-vira-small: 14.5px;

  width: 100%;
  max-width: 100%;
  min-width: 0;
  overflow-x: clip;
  overflow-y: visible;
  color: var(--ts-ink, #151a17);
  background: var(--ts-paper, #f4f1ea);
  font-size: 16px;
  line-height: var(--ts-vira-body-lh);
}

.ts-vira-reference *,
.ts-vira-reference *::before,
.ts-vira-reference *::after { box-sizing: border-box; }

.ts-vira-reference button,
.ts-vira-reference summary,
.ts-vira-reference a { -webkit-tap-highlight-color: transparent; }
.ts-vira-reference button { cursor: pointer; }
/* <summary> has no UA pointer cursor, so every disclosure on the page showed
   the text I-beam instead of the hand and did not read as clickable. */
.ts-vira-reference summary { cursor: pointer; }
.ts-vira-reference summary > * { cursor: inherit; }

.ts-vira-reference svg:not(.leaflet-zoom-animated) {
  width: 22px;
  height: 22px;
  flex: 0 0 22px;
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 1.4;
}
.ts-vira-reference .leaflet-overlay-pane svg {
  width: auto;
  height: auto;
  max-width: none;
  max-height: none;
  flex: none;
}

.ts-vira-reference h1,
.ts-vira-reference h2,
.ts-vira-reference h3,
.ts-vira-reference p,
.ts-vira-reference li,
.ts-vira-reference summary,
.ts-vira-reference label,
.ts-vira-reference a { overflow-wrap: break-word; }

/* Sentence case everywhere on Vira except the small rust-coloured eyebrow
   labels, which are the one deliberate uppercase moment on the page. */
.ts-vira-reference .ts-kicker,
.ts-vira-hero-headline .ts-vira-location,
.ts-vira-related > .ts-vira-location {
  font-size: var(--ts-vira-eyebrow);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.ts-vira-reference .ts-kicker,
.ts-vira-related > .ts-vira-location { color: var(--ts-rust, #9f5034); }

body.ts-gallery-open { overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
  .ts-vira-reference *,
  .ts-vira-reference *::before,
  .ts-vira-reference *::after {
    scroll-behavior: auto !important;
    transition-duration: .01ms !important;
    animation-duration: .01ms !important;
  }
}

/* ==========================================================================
   2. Hero — the page's first panel, in the page's own column.

   Everything below the hero — the spec strip, the editorial column, the
   booking rail, the image break, the interlude, the related cards — sits on
   one measured column of rounded panels. Until .36 the hero was the single
   desktop element that obeyed neither: it ran to both browser edges with
   square corners, under a solid header bar. That is what made it read as a
   banner pasted above the page rather than its opening photograph.

   It now shares that column and that radius, so one left edge runs from the
   first photograph to the last related card. Below 1024 the gutter collapses
   and it bleeds square again — the same rule the break and interlude follow,
   so the full-bleed feel is kept exactly where the page is already full-bleed.
   ========================================================================== */
/* Photographic matte, property scale (see the brand layer for the homepage
   half of this signature). The hero panel is already inset by the page gutter
   horizontally and by its own top margin vertically, so the mount is simply
   the sand showing behind it -- matching that top margin at the foot gives an
   even surround. Full bleed at the sides, exactly like the property blocks. */
.ts-vira-hero {
  width: 100%;
  margin: 0;
  /* flow-root, or the panel's top margin collapses through this element and
     the mount opens at the foot only -- 0 above the photograph, 26 below. */
  display: flow-root;
  padding-bottom: clamp(14px, 1.8vw, 26px);
  background: var(--ts-brand-sand, #ebe3d6);
}

.ts-vira-hero-media {
  position: relative;
  width: min(var(--ts-vira-shell), calc(100% - (2 * var(--ts-vira-gutter))));
  height: min(74vh, 720px);
  min-height: 440px;
  margin: clamp(14px, 1.8vw, 26px) auto 0;
  overflow: hidden;
  border-radius: var(--ts-vira-radius-lg);
  background: #2b2a26;
}
.ts-vira-hero-media > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.ts-vira-hero-scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg, rgba(10, 14, 11, .64) 0%, rgba(10, 14, 11, .2) 46%, rgba(10, 14, 11, 0) 74%),
    linear-gradient(0deg, rgba(10, 14, 11, .62) 0%, rgba(10, 14, 11, .08) 46%, rgba(10, 14, 11, 0) 62%);
}
.ts-vira-hero-headline {
  position: absolute;
  z-index: 2;
  right: 0;
  bottom: clamp(24px, 3vw, 46px);
  left: 0;
  width: auto;
  margin: 0;
  padding-inline: clamp(22px, 2.6vw, 44px);
  color: #fffdf8;
}
/* No photograph: the headline is not inside a panel, so it carries the page
   column itself. */
.ts-vira-hero-headline--bare {
  position: static;
  width: min(var(--ts-vira-shell), calc(100% - (2 * var(--ts-vira-gutter))));
  margin: 0 auto;
  color: var(--ts-ink, #151a17);
  padding: clamp(48px, 7vw, 96px) 0 8px;
}
.ts-vira-hero-headline .ts-vira-location {
  margin: 0 0 14px;
  color: rgba(255, 253, 248, .82);
}
.ts-vira-hero-headline--bare .ts-vira-location { color: var(--ts-rust, #9f5034); }
.ts-vira-hero h1 {
  max-width: 15ch;
  margin: 0;
  color: inherit;
  font: 400 var(--ts-vira-h1)/.98 var(--ts-vira-display);
  letter-spacing: -.02em;
}
.ts-vira-mood {
  max-width: 32ch;
  margin: 14px 0 0;
  color: rgba(255, 253, 248, .9);
  font: italic 400 clamp(20px, 1.7vw, 27px)/1.3 var(--ts-vira-display);
}
.ts-vira-hero-headline--bare .ts-vira-mood { color: var(--ts-vira-soft); }

.ts-vira-hero-gallery {
  position: absolute;
  z-index: 2;
  right: clamp(14px, 3vw, 40px);
  bottom: clamp(14px, 3vw, 34px);
  min-height: 44px;
  padding: 0 16px;
  border: 1px solid rgba(255, 253, 248, .5);
  border-radius: var(--ts-vira-radius-sm);
  color: #fffdf8;
  background: rgba(16, 20, 17, .48);
  font-size: 13px;
  font-weight: 650;
  white-space: nowrap;
  backdrop-filter: blur(6px);
}
/* .ts-experience button { font: inherit } is 0,1,1 and beat the 0,1,0 rule
   above, so the pill rendered at the inherited 16px while the homepage chip
   (a <small>, unaffected by that reset) sat at 13px -- one affordance, two
   sizes. Scoped one class deeper so the family size wins. */
.ts-vira-reference .ts-vira-hero-gallery { color: #fffdf8; font-size: 13px; font-weight: 650; }
.ts-vira-hero-gallery:hover { background: rgba(16, 20, 17, .74); }
.ts-vira-hero-gallery span { margin-left: 6px; }

/* Slim strip that carries the summary line + hard facts + the one CTA. */
.ts-vira-spec {
  width: min(var(--ts-vira-shell), calc(100% - (2 * var(--ts-vira-gutter))));
  margin: 0 auto;
  padding: clamp(22px, 3vw, 36px) 0 clamp(24px, 3.4vw, 40px);
  border-bottom: 1px solid var(--ts-vira-line);
}
.ts-vira-hero-summary {
  max-width: 52ch;
  margin: 0 0 clamp(16px, 2vw, 24px);
  color: #2a332e;
  font: 400 clamp(18px, 1.5vw, 21px)/1.5 var(--ts-vira-display);
}
.ts-vira-spec-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px 30px;
  align-items: center;
}
.ts-vira-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 22px;
  margin: 0;
  padding: 0;
  list-style: none;
  color: #2a332e;
  font-size: 15px;
}
.ts-vira-facts li { display: inline-flex; gap: 8px; align-items: center; }
.ts-vira-facts li > i {
  display: inline-grid;
  width: 26px;
  height: 26px;
  flex: 0 0 26px;
  place-items: center;
  border-radius: 50%;
  color: var(--ts-forest, #1f3128);
  background: var(--ts-vira-mint);
  font-style: normal;
}
.ts-vira-facts li > i svg { width: 14px; height: 14px; flex: 0 0 14px; }

.ts-vira-rating {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin: 0;
  color: #38423c;
  font-size: 15px;
}
.ts-vira-rating a { display: inline-flex; min-height: 40px; align-items: center; border-bottom: 1px solid transparent; }
.ts-vira-rating a:hover { border-bottom-color: currentColor; }
.ts-vira-rating span {
  padding: 4px 10px;
  color: #fffdf8;
  background: var(--ts-forest, #1f3128);
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 650;
}

/* Vira's most prominent CTA now uses the shared primary geometry (brand §4)
   so the homepage's "Explore the stays" and this button are one family. */
.ts-vira-hero-cta {
  margin-left: auto;
  min-height: 48px;
  padding: 0 22px;
  border: 1px solid var(--ts-forest, #1f3128);
  border-radius: var(--ts-r-control, 10px);
  color: #fffdf8;
  background: var(--ts-forest, #1f3128);
  font-family: var(--ts-brand-sans, "Helvetica Neue", Helvetica, Arial, sans-serif);
  font-size: 15px;
  font-weight: 650;
  letter-spacing: 0;
  text-transform: none;
  transition: background .2s ease, border-color .2s ease;
}
.ts-vira-reference .ts-vira-hero-cta { color: #fffdf8; }
.ts-vira-reference .ts-vira-hero-cta:hover { color: #fffdf8; background: #18261a; border-color: #18261a; }

/* ==========================================================================
   3. Page shell — editorial column + booking rail
   ========================================================================== */
.ts-vira-page-layout {
  display: grid;
  width: min(var(--ts-vira-shell), calc(100% - (2 * var(--ts-vira-gutter))));
  grid-template-columns: minmax(0, 1fr) var(--ts-vira-rail);
  gap: clamp(40px, 4.4vw, 72px);
  align-items: start;
  margin: 0 auto;
  padding: 18px 0 clamp(70px, 8vw, 100px);
}

.ts-vira-details { width: auto; min-width: 0; margin: 0; border-top: 1px solid var(--ts-vira-line); }

.ts-vira-row {
  display: grid;
  grid-template-columns: var(--ts-vira-row-label) minmax(0, 1fr);
  gap: var(--ts-vira-row-gap);
  padding: clamp(34px, 3.4vw, 44px) 0;
  border-bottom: 1px solid var(--ts-vira-line);
}
.ts-vira-row > h2 {
  max-width: 12ch;
  margin: 0;
  color: var(--ts-ink, #151a17);
  font: 400 var(--ts-vira-h2)/1.08 var(--ts-font-heading, Georgia, serif);
  letter-spacing: -.02em;
}
/* Quiet editorial section index — echoes the numbered homepage. */
.ts-vira-index {
  display: block;
  margin-bottom: 8px;
  color: var(--ts-rust, #9f5034);
  font: 400 13px/1 var(--ts-font-body, Arial, sans-serif);
  font-feature-settings: "tnum";
  letter-spacing: .12em;
}
.ts-vira-coords {
  display: block;
  margin-top: 8px;
  color: var(--ts-vira-soft);
  font: 400 12px/1.3 var(--ts-font-body, Arial, sans-serif);
  letter-spacing: .04em;
  text-transform: none;
}
/* The location eyebrow class is reused as a section wrapper on this row —
   reset it back to a normal heading context there. */
.ts-vira-row.ts-vira-location {
  color: inherit;
  font: inherit;
  letter-spacing: normal;
  text-transform: none;
}

.ts-vira-row-content { min-width: 0; }

/* Long-form prose keeps a readable measure even though the shell is wide. */
.ts-vira-overview-copy,
.ts-vira-description-toggle > div,
.ts-vira-location-story {
  max-width: var(--ts-vira-prose);
}
.ts-vira-overview-copy { display: grid; gap: 14px; min-width: 0; }
.ts-vira-overview-copy p,
.ts-vira-description-toggle p,
.ts-vira-row details p,
.ts-vira-location-story p,
.ts-vira-know-grid p,
.ts-vira-policy > p,
.ts-vira-policy li {
  margin: 0;
  color: #35403a;
  font-size: var(--ts-vira-body);
  line-height: var(--ts-vira-body-lh);
}
.ts-vira-policy li { margin: 4px 0; }
.ts-vira-overview-copy p:first-child { color: #26312b; font-size: 19px; }

.ts-vira-description-toggle { margin-top: 18px !important; }
.ts-vira-description-toggle > summary {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  width: max-content;
  min-height: 44px;
  color: var(--ts-forest, #1f3128);
  font-size: 15px;
  font-weight: 700;
}
.ts-vira-description-toggle > summary::after { content: "+"; font-size: 18px; font-weight: 400; }
.ts-vira-description-toggle[open] > summary::after { content: "\2212"; }
.ts-vira-description-toggle .ts-vira-description-less { display: none; }
.ts-vira-description-toggle[open] .ts-vira-description-more { display: none; }
.ts-vira-description-toggle[open] .ts-vira-description-less { display: inline; }
.ts-vira-description-toggle > div { display: grid; gap: 14px; padding: 12px 0 2px; }

/* ==========================================================================
   4. At a glance — editorial columns, not boxed dashboard cards
   ========================================================================== */
/* Three columns left four highlights as 3 + 1 orphan, and squeezed each cell
   to ~77px of text beside the booking rail, which split words mid-syllable.
   Two columns give each highlight roughly double the measure and read as a
   balanced 2x2 block. The count is fixed rather than auto-fit so :nth-child
   can place the hairlines exactly: one rule between the columns, one between
   the rows. Still no cards -- the rules are the only framing. */
.ts-vira-highlights .ts-vira-feature-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0;
}
.ts-vira-highlights .ts-vira-feature-grid article {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr);
  gap: 13px;
  min-width: 0;
  align-content: start;
  padding: 20px 0;
}
.ts-vira-highlights .ts-vira-feature-grid article:nth-child(odd) { padding-right: clamp(20px, 2.2vw, 34px); }
.ts-vira-highlights .ts-vira-feature-grid article:nth-child(even) {
  padding-left: clamp(20px, 2.2vw, 34px);
  border-left: 1px solid var(--ts-vira-line);
}
.ts-vira-highlights .ts-vira-feature-grid article:nth-child(-n+2) { padding-top: 0; }
.ts-vira-highlights .ts-vira-feature-grid article:nth-child(n+3) { border-top: 1px solid var(--ts-vira-line); }
.ts-vira-highlights .ts-vira-feature-grid article > svg { color: var(--ts-rust, #9f5034); }
.ts-vira-feature-grid h3 { margin: 0 0 4px; color: #27312c; font: 650 16px/1.3 var(--ts-font-body, Arial, sans-serif); }
.ts-vira-feature-grid p { margin: 0; color: var(--ts-vira-soft); font-size: 16px; line-height: 1.55; }

/* ==========================================================================
   5. Where you'll sleep — compact divider rows, not empty boxed cards
   ========================================================================== */
.ts-vira-sleep-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 32px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.ts-vira-sleep-grid li {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
  padding: 17px 0;
  border-bottom: 1px solid var(--ts-vira-line);
}
.ts-vira-sleep-grid li:nth-child(-n+2) { border-top: 1px solid var(--ts-vira-line); }
.ts-vira-sleep-grid li svg { color: var(--ts-forest, #1f3128); }
.ts-vira-sleep-grid strong { display: block; margin: 0 0 2px; color: #27312c; font: 650 15.5px/1.3 var(--ts-font-body, Arial, sans-serif); }
.ts-vira-sleep-grid small { display: block; color: var(--ts-vira-soft); font-size: 16px; line-height: 1.5; }

/* Real-photography sleeping spaces (the primary path — the divider rows above
   are the no-photo fallback). Two Vira photos side by side in the content
   column: photo leads, label and detail sit beneath it. Clicking a photo
   reuses the existing property lightbox via data-ts-listing-gallery. */
.ts-vira-sleep-spaces {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 26px 28px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.ts-vira-sleep-spaces li { display: grid; gap: 3px; min-width: 0; }
.ts-vira-sleep-photo {
  display: block;
  width: 100%;
  margin: 0 0 10px;
  padding: 0;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  border-radius: var(--ts-vira-radius-md);
  background: #ded7cb;
}
.ts-vira-sleep-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .6s cubic-bezier(.16, 1, .3, 1);
}
button.ts-vira-sleep-photo:hover img { transform: scale(1.025); }
/* a room with no chosen photo — a calm placeholder, never a broken image */
.ts-vira-sleep-photo--empty {
  display: grid;
  place-items: center;
  color: var(--ts-vira-soft);
  background: rgba(230, 238, 233, .6);
}
.ts-vira-sleep-photo--empty svg { width: 30px; height: 30px; opacity: .55; }
.ts-vira-sleep-spaces strong { color: #27312c; font: 650 15.5px/1.3 var(--ts-font-body, Arial, sans-serif); }
.ts-vira-sleep-spaces small { display: block; color: var(--ts-vira-soft); font-size: 16px; line-height: 1.5; }
.ts-vira-sleep-spaces span { color: var(--ts-vira-soft); font-size: 13.5px; }

.ts-vira-sleep-intro { margin: 0 0 18px; color: #26312b; font-size: 16px; line-height: 1.55; }

/* ==========================================================================
   5b. Editorial full-bleed image break + one dark interlude — the two
   cinematic beats that keep photography and mood present down the page.
   ========================================================================== */
/* Both beats sit in the editorial column on desktop and go edge-to-edge on
   the single-column tablet/mobile layout (see the responsive block). */
.ts-vira-break {
  width: 100%;
  margin: clamp(10px, 2.4vw, 30px) 0;
  aspect-ratio: 16 / 7;
  max-height: 62vh;
  overflow: hidden;
  /* Hero, break and interlude are the same class of object -- a full-column
     cinematic panel -- so they share the panel radius. --ts-r-media stays for
     genuinely smaller media (portraits, room photos). */
  border-radius: var(--ts-vira-radius-lg);
  background: #ded7cb;
}
.ts-vira-break img { width: 100%; height: 100%; object-fit: cover; }

/* The ground, label and line are owned by the shared interlude (brand §6) so
   the homepage and the property speak in one voice. Vira previously used a
   dark centred band here; the dark moment on both pages is now the host, and
   the interlude is the quieter sand beat. Only the page's own rhythm stays. */
.ts-vira-reference .ts-vira-interlude {
  width: 100%;
  margin: clamp(10px, 2.4vw, 30px) 0;
  border-radius: var(--ts-vira-radius-lg);
}

/* ==========================================================================
   6. Amenities — scannable columns with dividers, not per-item boxes
   ========================================================================== */
.ts-vira-amenities {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0 28px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.ts-vira-amenities li {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  padding: 13px 0;
  border-bottom: 1px solid var(--ts-vira-line);
}
.ts-vira-amenities li svg { width: 18px; height: 18px; flex: 0 0 18px; color: var(--ts-forest, #1f3128); }
.ts-vira-amenities strong { display: block; color: #27312c; font: 650 14.5px/1.3 var(--ts-font-body, Arial, sans-serif); }
.ts-vira-amenities small { display: block; color: var(--ts-vira-soft); font-size: 15.5px; }

.ts-vira-all-amenities { margin-top: 6px; }
.ts-vira-all-amenities > summary {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 44px;
  color: var(--ts-forest, #1f3128);
  font-size: 15px;
  font-weight: 650;
  text-transform: none;
}
.ts-vira-all-amenities > div {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 22px;
  padding: 20px 0 4px;
}
.ts-vira-all-amenities h3 { margin: 0 0 10px; font: 400 17px/1.2 var(--ts-font-heading, Georgia, serif); }
.ts-vira-all-amenities ul { display: grid; gap: 7px; margin: 0; padding: 0; list-style: none; }
.ts-vira-all-amenities li { display: grid; grid-template-columns: 17px minmax(0, 1fr); gap: 8px; color: var(--ts-vira-soft); font-size: 15px; line-height: 1.5; }
.ts-vira-all-amenities li svg { width: 16px; height: 16px; flex: 0 0 16px; }

/* ==========================================================================
   7. Reviews
   ========================================================================== */
/* No enclosing card — the review sits in the editorial grid like every other
   row, told apart by the score typography and thin column rules alone. */
.ts-vira-review-grid {
  display: grid;
  grid-template-columns: 140px minmax(0, 1fr) minmax(190px, .62fr);
  gap: 0;
}
.ts-vira-review-grid > * { min-width: 0; padding: 0 24px; border-left: 1px solid var(--ts-vira-line); }
.ts-vira-review-grid > :first-child { padding-left: 0; border-left: 0; }
.ts-vira-review-score strong { display: block; font: 400 50px/.9 var(--ts-font-heading, Georgia, serif); }
.ts-vira-review-score > span { display: block; margin-top: 10px; font-size: 12px; letter-spacing: .07em; }
.ts-vira-review-score small { display: block; margin-top: 8px; color: var(--ts-vira-soft); font-size: 12.5px; line-height: 1.5; }
.ts-vira-review-summary p { margin: 0; max-width: 42ch; font: italic 400 18px/1.5 var(--ts-font-heading, Georgia, serif); }
.ts-vira-review-summary .ts-vira-review-source {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  align-items: center;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--ts-vira-line);
  color: var(--ts-vira-soft);
  font-size: 12.5px;
}
.ts-vira-review-source a { display: inline-flex; min-height: 32px; align-items: center; color: #495650; text-decoration: underline; text-underline-offset: 3px; }
.ts-vira-review-themes { display: grid; gap: 12px; margin: 0; padding: 0; list-style: none; }
.ts-vira-review-themes li { display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: 9px; align-items: center; font-size: 14px; }

/* ==========================================================================
   8. Location
   ========================================================================== */
.ts-vira-location-content { display: grid; gap: 22px; }
.ts-vira-reference .ts-property-map {
  position: relative;
  z-index: 0;
  width: 100%;
  /* Was min-height 400-480px, which rendered ~1.55:1 -- a tall slab for a map
     whose subject is a single point. It now uses the same 16:7 band as the
     editorial image break, so the two wide beats on the page rhyme. */
  aspect-ratio: 16 / 7;
  min-height: 240px;
  max-height: 60vh;
  overflow: hidden;
  border: 1px solid var(--ts-vira-line);
  border-radius: var(--ts-vira-radius-lg);
  background: #e7dfd3;
}
.ts-vira-reference .ts-property-map .leaflet-tile-pane {
  filter: grayscale(.25) sepia(.34) saturate(.68) hue-rotate(345deg) brightness(1.045) contrast(.86);
  opacity: .96;
}
.ts-vira-reference .ts-property-map .leaflet-marker-pane,
.ts-vira-reference .ts-property-map .leaflet-shadow-pane { display: none !important; }
.ts-vira-reference .ts-property-map .leaflet-control-attribution {
  max-width: calc(100% - 18px);
  margin: 0 6px 5px 0 !important;
  padding: 2px 5px !important;
  border-radius: 6px;
  color: #69706c;
  background: rgba(255, 253, 248, .78);
  box-shadow: none;
  font-size: 9px !important;
  line-height: 1.25;
  opacity: .78;
}
.ts-vira-reference .ts-map-fallback {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 24px;
  color: var(--ts-vira-soft);
  background: #e8eeeb;
  text-align: center;
  font-size: 12px;
}
.ts-vira-reference .ts-map-error-label { display: none; }

.ts-vira-location-story p { color: #303a35; font-size: 17px; line-height: 1.68; }

.ts-vira-location-notes { min-width: 0; }
.ts-vira-arrival-row {
  padding-top: 16px;
  border-top: 1px solid var(--ts-vira-line);
}
.ts-vira-arrival-row > summary {
  display: flex;
  min-height: 44px;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  color: #27312c;
  font-size: 15px;
  font-weight: 650;
  list-style: none;
}
.ts-vira-arrival-row > summary::-webkit-details-marker { display: none; }
.ts-vira-arrival-row > summary i { font-style: normal; transition: transform .2s ease; }
.ts-vira-arrival-row[open] > summary i { transform: rotate(45deg); }
.ts-vira-arrival-row > p { max-width: var(--ts-vira-prose); margin: 10px 0 0; }

/* ==========================================================================
   9. Good to know
   ========================================================================== */
/* Three real items → three balanced columns, separated by the same hairlines
   used in "At a glance". The registration number is a quiet note under the
   row, not a phantom fourth column. */
.ts-vira-know-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0;
}
.ts-vira-know-grid article {
  min-width: 0;
  padding: 0 26px;
  border-left: 1px solid var(--ts-vira-line);
}
.ts-vira-know-grid article:first-child { padding-left: 0; border-left: 0; }
.ts-vira-know-grid h3 {
  margin: 0 0 6px;
  color: var(--ts-rust, #9f5034);
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
}
.ts-vira-property-note {
  grid-column: 1 / -1;
  margin: 20px 0 0 !important;
  padding-top: 18px;
  border-top: 1px solid var(--ts-vira-line);
  color: var(--ts-vira-soft) !important;
  font-size: 15px !important;
}

/* ==========================================================================
   10. Policies — a normal editorial row: left heading, full-width disclosure
   rows on the content side. No enclosing card, no margin-left hack.
   ========================================================================== */
.ts-vira-policy-list { display: grid; }
.ts-vira-policy { border-top: 1px solid var(--ts-vira-line); }
.ts-vira-policy:last-child { border-bottom: 1px solid var(--ts-vira-line); }
.ts-vira-policy > summary {
  display: flex;
  min-height: 54px;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 8px 0;
  color: #27312c;
  font-size: 15px;
  font-weight: 650;
  list-style: none;
}
.ts-vira-policy > summary::-webkit-details-marker { display: none; }
.ts-vira-policy > summary i { font-style: normal; font-size: 17px; transition: transform .2s ease; }
.ts-vira-policy[open] > summary i { transform: rotate(45deg); }
.ts-vira-policy > p,
.ts-vira-policy > ul { max-width: var(--ts-vira-prose); margin: 0 0 16px; }
.ts-vira-policy > ul { padding-left: 20px; }
.ts-vira-policy > p:first-of-type,
.ts-vira-policy > ul:first-of-type { margin-top: 2px; }

/* ==========================================================================
   11. Host — a real person: portrait beside the statement, cream ground.
   ========================================================================== */
/* The host is the shared dark band (brand §7) at its compact scale — the same
   component the homepage uses at full scale, so "a real person" looks the
   same on both pages. Vira only releases the prose measure, because the band
   already constrains its own copy column. The old host CTA rules are gone:
   .ts-hostband__cta is 0,2,0 and clears the .ts-experience a{color:inherit}
   reset on its own, so there is nothing left to re-specify here. */
.ts-vira-reference .ts-vira-host-content { max-width: none; }
.ts-vira-reference .ts-vira-host-copy { max-width: none; }
.ts-vira-reference .ts-vira-host-portrait img { width: 100%; height: 100%; object-fit: cover; }

/* ==========================================================================
   12. More Ticino stays
   ========================================================================== */
.ts-vira-related {
  width: min(var(--ts-vira-shell), calc(100% - (2 * var(--ts-vira-gutter))));
  margin: 0 auto;
  padding: clamp(40px, 4.4vw, 60px) 0 clamp(56px, 6vw, 76px);
}
.ts-vira-related > .ts-vira-location { margin: 0 0 10px; }
.ts-vira-related > h2 {
  margin: 0 0 24px;
  color: var(--ts-ink, #151a17);
  font: 400 var(--ts-vira-h2)/1.1 var(--ts-font-heading, Georgia, serif);
  letter-spacing: -.02em;
}
/* These are the homepage's property blocks at a smaller density: same index
   rule, place, name and mood, read in the same order (brand §9). Dropping the
   bordered card lets the photograph carry the card, exactly as it does on the
   homepage. Only the grid and the crop stay property-page-specific. */
.ts-vira-related-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(20px, 2.2vw, 34px); }
.ts-vira-related-grid article,
.ts-vira-related-image { min-width: 0; }
.ts-vira-related-image { display: block; aspect-ratio: 4 / 3; }

/* The shared direct-booking strip (brand §8) stacks beside the panel instead of
   becoming a second full-width section — this is the restrained variant. */
.ts-vira-reference .ts-direct--rail { grid-template-columns: 1fr; margin: 16px 26px 0; }
.ts-vira-reference .ts-direct--rail li { padding: 12px 0; border-left: 0; border-top: 1px solid var(--ts-vira-line); }
.ts-vira-reference .ts-direct--rail li:first-child { border-top: 0; }

/* ==========================================================================
   13. Booking rail — shared markup, Vira presentation only.
   No internal scrollbar, ever: the drawer keeps its natural content height;
   only whether the whole rail is "sticky" changes with viewport size.
   ========================================================================== */
.ts-vira-booking-rail { min-width: 0; }

.ts-vira-booking-rail .ts-booking-backdrop.ts-booking-inline {
  position: static;
  inset: auto;
  display: block;
  width: 100%;
  opacity: 1;
  pointer-events: auto;
  background: transparent;
}
.ts-vira-booking-rail .ts-booking-inline .ts-booking-drawer {
  position: static;
  width: 100%;
  height: auto;
  min-height: 0;
  max-height: none;
  padding: 26px;
  overflow: visible;
  border: 1px solid rgba(21, 26, 23, .11);
  border-radius: var(--ts-vira-radius-lg);
  background: var(--ts-white, #fffdf8);
  box-shadow: 0 18px 46px rgba(21, 26, 23, .07);
  transform: none;
}
.ts-vira-booking-rail .ts-booking-close { display: none; }
.ts-vira-booking-rail .ts-booking-property { display: none !important; }

/* Not part of the Dates → Guests/pet → Rate → Total → Reserve hierarchy and
   already communicated elsewhere on the page — dropped entirely to reclaim
   vertical space rather than kept as a permanent micro-heading. */
.ts-vira-booking-rail .ts-kicker { display: none; }
.ts-vira-booking-rail > .ts-booking-drawer > h2,
.ts-vira-booking-rail .ts-booking-drawer > h2 { margin: 0 0 8px; color: #17201b; font: 400 28px/1.06 var(--ts-font-heading, Georgia, serif); letter-spacing: -.03em; }
.ts-vira-booking-rail .ts-booking-intro { display: none; margin: 0 0 18px; color: var(--ts-vira-soft); font-size: 13.5px; line-height: 1.48; }

.ts-vira-booking-rail .ts-booking-form { display: flex; flex-direction: column; }

.ts-vira-booking-rail .ts-date-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; border: 0; }
.ts-vira-booking-rail .ts-date-choice { padding: 0; border: 0; }
.ts-vira-booking-rail .ts-date-choice > span {
  display: block;
  margin-bottom: 4px;
  color: #5e6a64;
  font-size: 13px;
  font-weight: 650;
  letter-spacing: .02em;
  text-transform: none;
}
.ts-vira-booking-rail .ts-date-choice button {
  display: flex;
  width: 100%;
  min-height: 46px;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 0 13px;
  border: 1px solid var(--ts-vira-line);
  border-radius: var(--ts-vira-radius-md);
  background: rgba(244, 241, 234, .5);
  text-align: left;
}
.ts-vira-booking-rail .ts-date-choice strong { overflow: hidden; font: 400 16px/1.2 var(--ts-font-heading, Georgia, serif); white-space: nowrap; text-overflow: ellipsis; }
.ts-vira-booking-rail .ts-date-choice i { font-style: normal; }
.ts-vira-booking-rail .ts-arrival-times { display: none; margin: 8px 0 0; color: #68736d; font-size: 12.5px; line-height: 1.4; }

.ts-vira-booking-rail .ts-party-disclosure { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--ts-vira-line); }
.ts-vira-booking-rail .ts-party-disclosure > summary {
  display: grid;
  min-height: 44px;
  grid-template-columns: minmax(0, 1fr) auto 16px;
  gap: 10px;
  align-items: center;
  list-style: none;
}
.ts-vira-booking-rail .ts-party-disclosure > summary::-webkit-details-marker { display: none; }
.ts-vira-booking-rail .ts-party-disclosure > summary > span { margin: 0; color: #5e6a64; font-size: 13px; font-weight: 650; text-transform: none; }
.ts-vira-booking-rail .ts-party-disclosure > summary strong { font: 400 16px/1.2 var(--ts-font-heading, Georgia, serif); }
.ts-vira-booking-rail .ts-party-disclosure > summary i { font-style: normal; transition: transform .2s ease; }
.ts-vira-booking-rail .ts-party-disclosure[open] > summary i { transform: rotate(45deg); }
.ts-vira-booking-rail .ts-party-composition { margin: 0; padding: 12px 0 2px; border: 0; }
.ts-vira-booking-rail .ts-party-composition > p { margin: 0 0 10px; color: var(--ts-vira-soft); font-size: 14px; }
.ts-vira-booking-rail .ts-party-grid { display: grid; grid-template-columns: 1fr; gap: 8px; }
.ts-vira-booking-rail .ts-party-grid label {
  display: grid;
  gap: 4px;
  padding: 9px 12px;
  border: 1px solid var(--ts-vira-line);
  border-radius: 12px;
  background: rgba(244, 241, 234, .35);
}
.ts-vira-booking-rail .ts-party-grid label span { color: var(--ts-vira-soft); font-size: 13px; }
.ts-vira-booking-rail .ts-party-grid select { width: 100%; min-height: 28px; border: 0; background: transparent; font-size: 14px; }
.ts-vira-booking-rail .ts-party-status { margin: 8px 0 0; color: var(--ts-rust, #9f5034); font-size: 11.5px; }
.ts-vira-booking-rail .ts-infant-equipment { margin-top: 10px; }
.ts-vira-booking-rail .ts-infant-restriction { margin: 8px 0 0; color: var(--ts-vira-soft); font-size: 14px; }

.ts-vira-booking-rail .ts-pet-toggle {
  display: flex !important;
  min-height: 40px;
  align-items: center;
  gap: 10px;
  padding: 6px 0;
  border-top: 1px solid var(--ts-vira-line);
  font-size: 13.5px;
}
.ts-vira-booking-rail .ts-pet-toggle[hidden] { display: none !important; }
.ts-vira-booking-rail .ts-pet-toggle input { width: 16px; height: 16px; }

/* Cancellation options: kept as a real comparison card (this is content that
   genuinely benefits from containment), but visually quieter than the price
   box / CTA that follow it — selection uses a light tint, not a heavy rust
   outline competing with the Reserve button. */
.ts-vira-booking-rail .ts-rate-plan { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--ts-vira-line); }
.ts-vira-booking-rail .ts-rate-plan legend { margin-bottom: 6px; color: #5e6a64; font-size: 13px; font-weight: 650; text-transform: none; }
/* Two-column segmented selector (Flexible | Non-refundable · Save 10%)
   instead of two stacked full-width cards — the biggest single space saving
   in this compaction pass, since both options now share one row. */
.ts-vira-booking-rail .ts-rate-plan-options { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.ts-vira-booking-rail .ts-rate-plan-options label {
  display: grid;
  grid-template-columns: 15px minmax(0, 1fr);
  gap: 7px;
  padding: 8px 10px;
  border: 1px solid var(--ts-vira-line);
  border-radius: 12px;
  background: rgba(244, 241, 234, .3);
  transition: border-color .15s ease, background .15s ease;
}
.ts-vira-booking-rail .ts-rate-plan-options label:has(input:checked) {
  border-color: rgba(31, 49, 40, .35);
  background: rgba(31, 49, 40, .05);
}
.ts-vira-booking-rail .ts-rate-plan-options input { width: 15px; height: 15px; margin: 2px 0 0; }
.ts-vira-booking-rail .ts-rate-plan-options strong { display: block; font-size: 13.5px; }
.ts-vira-booking-rail .ts-rate-plan-options small { display: block; margin-top: 2px; color: var(--ts-vira-soft); font-size: 12px; line-height: 1.3; }

/* Compact rate treatment (Vira only): the full cancellation/grace-period
   wording lives in this small accessible disclosure instead of permanently
   expanded inline text, so the two rate options above stay one line each. */
.ts-vira-booking-rail .ts-rate-plan-note { margin-top: 6px; }
.ts-vira-booking-rail .ts-rate-plan-note summary { display: flex; min-height: 30px; align-items: center; justify-content: space-between; gap: 10px; color: var(--ts-vira-soft); list-style: none; font-size: 12.5px; font-weight: 650; }
.ts-vira-booking-rail .ts-rate-plan-note summary::-webkit-details-marker { display: none; }
.ts-vira-booking-rail .ts-rate-plan-note summary i { font-style: normal; transition: transform .2s ease; }
.ts-vira-booking-rail .ts-rate-plan-note[open] summary i { transform: rotate(45deg); }
.ts-vira-booking-rail .ts-rate-plan-note div { padding-top: 4px; }
.ts-vira-booking-rail .ts-rate-plan-note p { margin: 0 0 8px; color: var(--ts-vira-soft); font-size: 14px; line-height: 1.5; }
.ts-vira-booking-rail .ts-rate-plan-note p:last-child { margin-bottom: 0; }

.ts-vira-booking-rail .ts-guest-calendar { margin-top: 10px; padding: 16px; border: 1px solid var(--ts-vira-line); border-radius: var(--ts-vira-radius-md); background: var(--ts-white, #fffdf8); }
.ts-vira-booking-rail .ts-guest-calendar[hidden],
.ts-vira-booking-rail .ts-booking-extras[hidden],
.ts-vira-booking-rail .ts-weather-card[hidden] { display: none !important; }
.ts-vira-booking-rail .ts-availability-status,
.ts-vira-booking-rail .ts-booking-message { min-height: 0; margin: 8px 0 0; padding: 0; font-size: 13px; line-height: 1.4; }
.ts-vira-booking-rail .ts-availability-status:not(:empty),
.ts-vira-booking-rail .ts-booking-message:not(:empty) { padding: 9px 11px; border-radius: var(--ts-vira-radius-sm); }
.ts-vira-booking-rail .ts-availability-status { color: #456353; background: rgba(31, 49, 40, .05); }
.ts-vira-booking-rail .ts-booking-message { color: #7a3320; background: rgba(159, 80, 52, .08); }

/* Price + CTA: the visual climax of the card, deliberately heavier than the
   cancellation options above it. */
.ts-vira-booking-rail .ts-price-box {
  margin: 10px 0 0;
  padding: 13px;
  border: 1px solid var(--ts-vira-line);
  border-radius: var(--ts-vira-radius-md);
  background: rgba(244, 241, 234, .48);
}
/* The "Total" label inside .ts-price-total already identifies this row, so
   the separate "Your complete price" heading above it is a redundant line
   dropped for Vira only — no information lost. */
.ts-vira-booking-rail .ts-price-box > span:first-child { display: none; }
.ts-vira-booking-rail .ts-price-lines { display: grid; gap: 5px; margin: 8px 0; padding: 8px 0; border-top: 1px solid var(--ts-vira-line); border-bottom: 1px solid var(--ts-vira-line); }
.ts-vira-booking-rail .ts-price-lines:empty { display: none; }
.ts-vira-booking-rail .ts-price-lines div { display: flex; justify-content: space-between; gap: 10px; color: var(--ts-vira-soft); font-size: 13px; }
.ts-vira-booking-rail .ts-price-total { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.ts-vira-booking-rail .ts-price-total strong { color: var(--ts-ink); font: 400 32px/1 var(--ts-font-heading, Georgia, serif); }
.ts-vira-booking-rail .ts-price-box > small { display: block; margin-top: 6px; color: #68736c; font-size: 12px; line-height: 1.4; }

/* Ordered last (via flex `order`) so it trails the Reserve CTA instead of
   separating the price box from the button — Total and Reserve now read as
   one adjacent conversion unit, with the guarantee note as a quiet footnote. */
.ts-vira-booking-rail .ts-best-price-note { order: 5; margin-top: 6px; }
.ts-vira-booking-rail .ts-best-price-note summary { display: flex; min-height: 32px; align-items: center; justify-content: space-between; gap: 10px; color: var(--ts-vira-soft); list-style: none; font-size: 13px; }
.ts-vira-booking-rail .ts-best-price-note summary::-webkit-details-marker { display: none; }
.ts-vira-booking-rail .ts-best-price-note p,
.ts-vira-booking-rail .ts-best-price-note a { color: var(--ts-vira-soft); font-size: 12.5px; line-height: 1.5; }
.ts-vira-booking-rail .ts-best-price-note a { border-bottom: 1px solid currentColor; }

.ts-vira-booking-rail .ts-reserve-button {
  width: 100%;
  min-height: 54px;
  margin-top: 8px;
  padding: 12px 18px;
  /* Shared button family. The base rule is 9px uppercase with .09em tracking;
     the panel's primary action now reads in the same sentence case and control
     radius as every other CTA. Purely presentational -- the element, its type,
     its disabled state and its checkout action are untouched. */
  border-radius: var(--ts-r-control, 10px);
  color: #fff;
  background: var(--ts-forest, #1f3128);
  font-size: 15px;
  font-weight: 650;
  letter-spacing: 0;
  text-transform: none;
}
.ts-vira-booking-rail .ts-reserve-button:disabled { cursor: not-allowed; opacity: .46; }
.ts-vira-booking-rail .ts-reserve-note { margin: 6px 0 0; color: #68736d; font-size: 12.5px; line-height: 1.4; text-align: center; }
.ts-vira-booking-rail .ts-booking-contact { display: none; }
.ts-vira-booking-rail .ts-booking-completion { display: none !important; }

/* Desktop: rail is sticky only when the viewport is tall enough for it to
   behave naturally. On short laptop screens it stays in normal page flow —
   never gains an internal scrollbar, never clips its own content. */
@media (min-width: 1025px) {
  .ts-vira-booking-rail { align-self: start; height: max-content; }
}
@media (min-width: 1025px) and (min-height: 760px) {
  .ts-vira-booking-rail { position: sticky; top: 24px; }
}
@media (min-width: 1025px) and (max-height: 759px) {
  .ts-vira-booking-rail { position: static; }
}

/* ==========================================================================
   14. Gallery lightbox + mobile booking sheet
   (Mobile keeps its own scrollable sheet — that is expected sheet behaviour,
   not the sidebar nested-scroll defect being fixed above.)
   ========================================================================== */
/* Flex-centered rather than CSS-grid-auto-placed: the previous grid relied on
   exactly three non-absolute children auto-flowing into three explicit
   columns, but the shared base stylesheet (.ts-listing-lightbox button {
   position: absolute; ... }) silently pulled every button out of that flow,
   leaving the <img> as the sole grid item auto-placed into the first
   (56px) column — rendering it as a tiny thumbnail pinned to the left edge.
   Explicit flex centering plus fully-positioned controls removes that
   fragile dependency on sibling count/order entirely. */
.ts-vira-reference .ts-listing-lightbox {
  position: fixed;
  z-index: 100000;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 42px;
  color: #fff;
  background: rgba(8, 12, 9, .96);
}
.ts-vira-reference .ts-listing-lightbox[hidden] { display: none !important; }
.ts-vira-reference .ts-listing-lightbox img { display: block; width: auto; height: auto; max-width: min(1400px, 92vw); max-height: 88vh; object-fit: contain; }
.ts-vira-reference .ts-listing-lightbox button { position: absolute; z-index: 2; display: grid; width: 48px; height: 48px; place-items: center; border: 1px solid rgba(255, 255, 255, .45); border-radius: 50%; color: #fff; background: rgba(0, 0, 0, .25); font-size: 27px; }
.ts-vira-reference .ts-listing-lightbox [data-ts-listing-close] { top: 22px; right: 22px; }
.ts-vira-reference .ts-listing-lightbox [data-ts-listing-prev] { top: 50%; left: 22px; transform: translateY(-50%); }
.ts-vira-reference .ts-listing-lightbox [data-ts-listing-next] { top: 50%; right: 22px; transform: translateY(-50%); }
.ts-vira-reference .ts-listing-lightbox span { position: absolute; right: 26px; bottom: 20px; font-size: 11px; letter-spacing: .08em; }

.ts-vira-reference .ts-listing-mobile-bookbar { display: none; }

@media (max-width: 1024px) {
  .ts-vira-reference { padding-bottom: 92px; }
  .ts-vira-page-layout { display: block; width: min(var(--ts-vira-shell), calc(100% - (2 * var(--ts-vira-gutter)))); padding-bottom: 48px; }
  /* height:0 collapsed the rail so the booking panel took no space in the
     single-column layout. Both panel states already contribute nothing --
     :not(.is-open) is display:none and .is-open is position:fixed -- so the
     collapse only ever hid the ONE in-flow child the rail gained in .35, the
     direct-booking strip, which then overflowed 159px onto "More Ticino
     stays". Sizing to content restores the strip without giving the panel
     any height in either state. */
  .ts-vira-booking-rail { position: static !important; width: 100%; height: auto; overflow: visible; }
  /* The 26px inset aligned the strip with the panel's padding; with the panel
     gone it aligns with the page column instead. */
  .ts-vira-reference .ts-direct--rail { margin-inline: 0; }
  .ts-vira-booking-rail .ts-booking-inline:not(.is-open) { display: none !important; }
  .ts-vira-booking-rail .ts-booking-inline.is-open {
    position: fixed !important;
    z-index: 99999;
    inset: 0 !important;
    display: flex !important;
    width: 100% !important;
    height: 100dvh !important;
    align-items: flex-end;
    justify-content: center;
    background: rgba(12, 18, 14, .42) !important;
    backdrop-filter: blur(4px);
  }
  .ts-vira-booking-rail .ts-booking-inline.is-open .ts-booking-drawer {
    position: relative !important;
    width: min(680px, 100%) !important;
    height: auto !important;
    max-height: calc(100dvh - 12px) !important;
    padding: 18px 20px calc(24px + env(safe-area-inset-bottom)) !important;
    overflow-y: auto !important;
    overscroll-behavior: contain;
    border-radius: 22px 22px 0 0 !important;
  }
  .ts-vira-booking-rail .ts-booking-inline.is-open .ts-booking-close {
    position: sticky !important;
    z-index: 5;
    top: 0;
    display: grid !important;
    width: 40px;
    height: 40px;
    margin: 0 0 4px auto;
    place-items: center;
    border: 1px solid rgba(21, 26, 23, .12);
    border-radius: 50%;
    background: #fff;
  }
  .ts-vira-booking-rail .ts-booking-inline.is-open .ts-party-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .ts-vira-reference .ts-listing-mobile-bookbar {
    position: fixed;
    z-index: 9990;
    right: 14px;
    bottom: max(12px, env(safe-area-inset-bottom));
    left: 14px;
    display: flex;
    min-height: 66px;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    padding: 10px 10px 10px 16px;
    border: 1px solid rgba(21, 26, 23, .11);
    border-radius: 16px;
    background: rgba(255, 253, 248, .97);
    box-shadow: 0 14px 38px rgba(21, 26, 23, .18);
    backdrop-filter: blur(16px);
  }
  .ts-vira-reference .ts-listing-mobile-bookbar > div { display: grid; min-width: 0; gap: 2px; }
  .ts-vira-reference .ts-listing-mobile-bookbar strong { overflow: hidden; color: #17201b; font: 400 20px/1.05 var(--ts-font-heading, Georgia, serif); white-space: nowrap; text-overflow: ellipsis; }
  .ts-vira-reference .ts-listing-mobile-bookbar small { overflow: hidden; color: #66706a; font-size: 11px; white-space: nowrap; text-overflow: ellipsis; }
  .ts-vira-reference .ts-listing-mobile-bookbar button { min-height: 48px; flex: 0 0 auto; padding: 0 20px; border-radius: var(--ts-r-control, 10px); color: #fff; background: var(--ts-forest, #1f3128); font-size: 14px; font-weight: 650; }

  /* .is-managed is added by the script once it can watch the real booking
     controls; without it the bar stays visible exactly as before, so a script
     failure degrades to the old behaviour rather than to no booking CTA. */
  .ts-vira-reference .ts-listing-mobile-bookbar.is-managed {
    transform: translateY(calc(100% + 20px));
    opacity: 0;
    visibility: hidden;
    transition: transform .3s cubic-bezier(.16, 1, .3, 1), opacity .2s ease, visibility 0s linear .3s;
  }
  .ts-vira-reference .ts-listing-mobile-bookbar.is-managed.is-visible {
    transform: none;
    opacity: 1;
    visibility: visible;
    transition: transform .3s cubic-bezier(.16, 1, .3, 1), opacity .22s ease, visibility 0s;
  }
  /* The full-screen booking sheet is its own primary action. */
  body:has(.ts-booking-inline.is-open) .ts-vira-reference .ts-listing-mobile-bookbar {
    transform: translateY(calc(100% + 20px));
    opacity: 0;
    visibility: hidden;
  }
}

/* ==========================================================================
   15. Footer coordination (shared standalone footer template)
   ========================================================================== */
body:has(.ts-vira-reference) .ts-standalone-footer {
  width: min(var(--ts-vira-shell), calc(100% - (2 * clamp(20px, 3.2vw, 52px))));
  grid-template-columns: minmax(190px, .65fr) minmax(0, 1.35fr);
  gap: 12px 30px !important;
  margin: 30px auto 0 !important;
  padding: 30px clamp(24px, 4vw, 54px) 24px !important;
  border-radius: 22px 22px 0 0;
}
body:has(.ts-vira-reference) .ts-standalone-footer > a { font-size: 28px !important; }
body:has(.ts-vira-reference) .ts-standalone-footer > p {
  max-width: 680px;
  justify-self: end;
  font-size: clamp(22px, 2vw, 30px) !important;
  line-height: 1.08 !important;
  text-align: right;
}
body:has(.ts-vira-reference) .ts-standalone-footer nav,
body:has(.ts-vira-reference) .ts-standalone-footer .ts-standalone-seo-links {
  grid-column: 1 / -1;
  width: 100%;
  gap: 8px 20px !important;
  padding-block: 9px !important;
}
body:has(.ts-vira-reference) .ts-standalone-footer small { grid-column: 1 / -1; padding-top: 7px !important; font-size: 11px; }

/* ==========================================================================
   16. Responsive — one coherent set of steps:
       1180  row-label narrows
       1024  gutter tightens; the break + interlude go edge-to-edge (the page
              layout is a single column here, so a viewport-width bleed is safe)
        900  DESKTOP → TABLET: editorial rows stack; At a glance / Good to know
              / related drop a tier; host portrait moves above the copy
        620  TABLET → MOBILE: every remaining multi-column grid → 1 column;
              hero + spec tighten; footer stacks
        390  mobile book-bar sub-label
       There are deliberately NO h1 font-size rules here — the single
       --ts-vira-h1 clamp is monotonic on its own.
   ========================================================================== */
@media (max-width: 1180px) {
  .ts-vira-reference { --ts-vira-row-label: clamp(140px, 12vw, 170px); }
}

@media (max-width: 1024px) {
  .ts-vira-reference { --ts-vira-gutter: 30px; }
  /* The panel goes edge to edge here, so the mount has nothing to surround and
     would render as a stray beige strip under the photograph. */
  .ts-vira-reference .ts-vira-hero { padding-bottom: 0; background: none; }
  .ts-vira-reference .ts-vira-hero-media {
    width: 100%;
    height: min(64vh, 620px);
    margin-top: 0;
    border-radius: 0;
  }
  /* single-column page layout below 1024 — bleed the two cinematic beats to
     the screen edge for a true full-bleed feel on tablet + phone. */
  .ts-vira-reference .ts-vira-break,
  .ts-vira-reference .ts-vira-interlude {
    width: calc(100% + (2 * var(--ts-vira-gutter)));
    max-width: 100vw;
    margin-inline: calc(var(--ts-vira-gutter) * -1);
    border-radius: 0;
  }
}

@media (max-width: 900px) {
  .ts-vira-reference { --ts-vira-gutter: 24px; }
  .ts-vira-reference .ts-vira-hero-media { height: min(58vh, 520px); min-height: 380px; }
  .ts-vira-hero h1 { max-width: 14ch; }
  .ts-vira-mood { max-width: 34ch; }

  .ts-vira-row { grid-template-columns: 1fr; gap: 16px; }
  .ts-vira-row > h2 { max-width: 520px; }
  .ts-vira-index { margin-bottom: 4px; }

  .ts-vira-know-grid { grid-template-columns: 1fr; }
  .ts-vira-know-grid article { padding: 14px 0; border-left: 0; border-top: 1px solid var(--ts-vira-line); }
  .ts-vira-know-grid article:first-child { padding-top: 0; border-top: 0; }
  .ts-vira-property-note { margin-top: 4px !important; }


  .ts-vira-related-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ts-vira-related-grid article:nth-child(3) { grid-column: 1 / -1; }
  .ts-vira-related-grid article:nth-child(3) .ts-vira-related-image { aspect-ratio: 2.4 / 1; }
}

@media (max-width: 620px) {
  .ts-vira-reference { --ts-vira-gutter: 18px; }
  .ts-vira-reference .ts-vira-hero-media { height: min(58vh, 480px); min-height: 340px; }
  /* the headline owns the bottom of the hero on a phone — move the gallery
     pill to the top-right so the two never collide. */
  .ts-vira-hero-gallery { top: 14px; bottom: auto; }
  .ts-vira-hero h1 { max-width: 16ch; }
  .ts-vira-mood { font-size: 18px; }
  .ts-vira-hero-summary { max-width: none; }
  .ts-vira-facts { font-size: 14px; }
  .ts-vira-rating { font-size: 14px; }
  .ts-vira-hero-cta { margin-left: 0; width: 100%; justify-content: center; display: inline-flex; align-items: center; }
  .ts-vira-spec-row { gap: 14px 22px; }
  .ts-vira-break { aspect-ratio: 3 / 2; }
  .ts-vira-reference .ts-vira-interlude { padding-inline: 22px; }

  /* One column only on the phone -- 820 and 768 still have room for the 2x2. */
  .ts-vira-highlights .ts-vira-feature-grid { grid-template-columns: 1fr; }
  .ts-vira-highlights .ts-vira-feature-grid article,
  .ts-vira-highlights .ts-vira-feature-grid article:nth-child(odd),
  .ts-vira-highlights .ts-vira-feature-grid article:nth-child(even) {
    padding: 15px 0;
    border-left: 0;
    border-top: 1px solid var(--ts-vira-line);
  }
  .ts-vira-highlights .ts-vira-feature-grid article:first-child { padding-top: 0; border-top: 0; }

  .ts-vira-row { padding: 28px 0; }
  .ts-vira-row > h2 { max-width: none; }
  .ts-vira-overview-copy p:first-child { font-size: 17px; }

  .ts-vira-sleep-spaces { grid-template-columns: 1fr; gap: 22px; }
  .ts-vira-sleep-grid { grid-template-columns: 1fr; }
  .ts-vira-sleep-grid li:nth-child(-n+2) { border-top: 0; }
  .ts-vira-sleep-grid li:first-child { border-top: 1px solid var(--ts-vira-line); }
  .ts-vira-amenities,
  .ts-vira-all-amenities > div { grid-template-columns: 1fr; }
  .ts-vira-amenities { gap: 0; }

  .ts-vira-review-grid { grid-template-columns: 1fr; gap: 16px 0; }
  .ts-vira-review-grid > * { padding: 16px 0 0; border-left: 0; border-top: 1px solid var(--ts-vira-line); }
  .ts-vira-review-grid > :first-child { padding-top: 0; border-top: 0; }

  .ts-vira-reference .ts-property-map { min-height: 220px; border-radius: var(--ts-vira-radius-lg); }

  .ts-vira-related-grid { grid-template-columns: 1fr; }
  .ts-vira-related-grid article:nth-child(3) { grid-column: auto; }
  /* Shallower ratio for the stacked mobile cards so three recommendations
     don't run to ~1.5 screens — all three cards stay. */
  .ts-vira-related-image,
  .ts-vira-related-grid article:nth-child(3) .ts-vira-related-image { aspect-ratio: 3 / 2; }

  body:has(.ts-vira-reference) .ts-standalone-footer {
    grid-template-columns: 1fr;
    width: calc(100% - 28px);
    padding: 24px 20px calc(100px + env(safe-area-inset-bottom));
    gap: 10px !important;
  }
  body:has(.ts-vira-reference) .ts-standalone-footer > p { justify-self: start; text-align: left; font-size: 21px !important; }
  body:has(.ts-vira-reference) .ts-standalone-footer nav,
  body:has(.ts-vira-reference) .ts-standalone-footer .ts-standalone-seo-links,
  body:has(.ts-vira-reference) .ts-standalone-footer small { grid-column: 1; }
}

@media (max-width: 430px) {
  .ts-vira-reference { --ts-vira-gutter: 16px; }
}

@media (max-width: 390px) {
  .ts-vira-reference { --ts-vira-gutter: 14px; }
  .ts-vira-reference .ts-listing-mobile-bookbar small { display: none; }
}
