/* ============================================================================
   beds24-brand.css — makes the Beds24 booking page a visual twin of delphius.co /stays/.

   NORTH STAR (ROADMAP_PAYPAL_LIVE_AND_BRANDING_20260802.md): one funnel, two mirrored halves.
   A guest arriving from Google Hotels lands here; a guest arriving from delphius.co sees the site.
   They must not be able to tell the two are different systems.

   HOW IT IS LOADED: Beds24 control panel → Property Booking Page → Developer → "Insert in HTML HEAD
   bottom", and IDENTICALLY on Multi Booking Page → Developer (Google Hotels can land on either):
       <link rel="stylesheet" href="https://delphius.co/assets/fonts.css">
       <link rel="stylesheet" href="https://delphius.co/assets/beds24-brand.css">
   Both are served with Access-Control-Allow-Origin by worker/index.js — without that header the
   cross-origin Cinzel fetch is blocked and the mirror loses its most recognisable element.
   The exact strings pasted into the panel are mirrored in docs/beds24-inserts/ (the panel is not
   versioned and is not a reliable read surface).

   TOKENS: copied from assets/brand/brand.css + the [data-brand="knickerbocker"] override in
   assets/styles.css. This is a Knickerbocker surface, so the accent is the WARM BRASS (#9a7b2e),
   not the Delphius bronze (#8B6B43). Keep all three surfaces (site, worker/pay.js, this file) on
   one token set.

   TARGETS ARE REAL, NOT GUESSED. Verified in-browser 2026-08-02 against
   booking2.php?propid=343414 — Bootstrap 3.3.4 + Beds24's own booking3.css, with module classes
   .b24-module / .b24-room-module / .b24-offer-module / .b24-bookingstrip, price spans
   .bookingpagedollars / .bookingpagecents / .bookingpagecurrency, and #topofthebookingpage.
   Beds24 ships heavy inline styles and id-scoped rules, so several rules below legitimately need
   !important; they are marked. Do not add !important anywhere it is not required.
   ============================================================================ */

/* Cinzel, fetched through the Worker-served /brand/ path so it carries an allow-origin header.
   NOT /assets/fonts/... : Cloudflare answers static-asset paths without invoking the Worker, so the
   header can never be attached there and the face fails silently to Georgia. See worker/index.js. */
@font-face{
  font-family:"Cinzel";
  src:url("https://delphius.co/brand/cinzel.ttf") format("truetype-variations"),
      url("https://delphius.co/brand/cinzel.ttf") format("truetype");
  font-weight:400 900;
  font-style:normal;
  font-display:swap;
}

:root{
  /* Load sentinel. The HEAD insert's masthead script reads this and injects NOTHING unless this
     stylesheet actually arrived — so the insert can be pasted into the panel BEFORE this file is
     deployed without ever showing an unstyled masthead on a live page guests can reach. */
  --dlp-brand-loaded:1;

  /* NO rem UNITS ANYWHERE IN THIS FILE. Bootstrap 3 sets html{font-size:10px} on the Beds24 page,
     while delphius.co uses the browser default 16px — so an identical rem value renders at 62.5%
     here and the whole mirror comes out systematically too small (verified 2026-08-02: the price
     computed 15px instead of 24px). px keeps both surfaces on one scale; em is self-relative and
     is safe. If you add a rule, use px. */
  --delphius-obsidian:#121212;
  --delphius-charcoal:#242424;
  --delphius-ivory:#F4F0E8;
  --delphius-stone:#D8D1C4;
  --delphius-brass:#9a7b2e;        /* Knickerbocker accent */
  --delphius-brass-deep:#6f5816;
  /* The site names Manrope first but never self-hosts it (assets/fonts.css ships Cinzel only), so
     the site actually renders body copy in system-ui. Repeat the stack EXACTLY so both surfaces
     resolve to the same face. If Manrope is ever self-hosted on the site, self-host it here too or
     the mirror breaks. */
  --delphius-sans:Manrope,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --delphius-display:Cinzel,"Trajan Pro",Georgia,serif;
}

/* ---------- page canvas ---------- */
body{
  background:var(--delphius-ivory) !important;   /* Beds24 sets body bg inline */
  color:var(--delphius-obsidian) !important;
  font-family:var(--delphius-sans) !important;
  font-size:17px !important;   /* beats Beds24's .colorbody{16px} */
  line-height:1.65 !important;
  -webkit-font-smoothing:antialiased;
}

/* Beds24 wraps content in Bootstrap containers; widen to the site's measure (.wrap). */
.b24fullcontainer,.container,.container2{width:min(1140px,92vw) !important;margin-inline:auto !important;float:none !important}

/* ---------- type ---------- */
h1,h2,h3,h4,.b24-module h1,.b24-module h2,.b24-module h3{
  font-family:var(--delphius-display) !important;
  font-weight:600;
  letter-spacing:.06em;
  line-height:1.18;
  text-transform:uppercase;
  color:var(--delphius-obsidian);
}
h1{letter-spacing:.08em;font-size:clamp(24px,3.4vw,32px)}
h2{font-size:clamp(20px,2.6vw,24px)}
h3{font-size:16.8px}
a{color:inherit}
a:hover{color:var(--delphius-brass-deep)}

/* ---------- the delphius masthead (injected via BODY-top; see docs/beds24-inserts/) ---------- */
.dlp-mast{
  /* z-index outranks the booking strip's 1200 ON PURPOSE. The strip only sticks for ~20px (its
     parent #b24scroller-container is 134px tall, and sticky travel is bounded by the parent), so it
     then scrolls up past the masthead. At z-index:100 it painted OVER the brand bar from y=150 on —
     measured: strip top 53 against masthead bottom 75 — which is the "menu is too tight to the top"
     symptom. The masthead is the one element that must never be covered, so it sits above
     everything and the strip scrolls underneath it. */
  position:sticky;top:0;z-index:1500;
  background:rgba(244,240,232,.92);
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
  border-bottom:1px solid var(--delphius-stone);
  margin-bottom:24px;
}
.dlp-mast__inner{
  width:min(1140px,92vw);margin-inline:auto;
  display:flex;align-items:center;gap:9.6px;min-height:74px;
}
/* The mark is nested INSIDE the anchor (see docs/beds24-inserts/body-top.html), so the anchor is
   the flex container — not .dlp-mast__inner's direct-child axis. */
.dlp-mast__word{
  display:flex;align-items:center;gap:9.6px;
  font-family:var(--delphius-display);text-transform:uppercase;letter-spacing:.2em;
  font-size:16.8px;font-weight:600;color:var(--delphius-obsidian);text-decoration:none;
}
.dlp-mast__word:hover{color:var(--delphius-obsidian)}
.dlp-mast__mark{display:block;width:42px;height:42px;flex:0 0 auto;
  background:url("https://delphius.co/assets/img/delphius-mark-15.png") center/contain no-repeat}
.dlp-mast__sub{
  font-family:var(--delphius-display);letter-spacing:.14em;text-transform:uppercase;
  font-size:12.5px;color:var(--delphius-brass);margin-left:3.2px;
}
@media(max-width:600px){
  .dlp-mast__inner{min-height:60px}
  .dlp-mast__word{font-size:14.4px;letter-spacing:.16em}
  /* "The Knickerbocker" is NOT hidden on mobile. It was, until a 375px measurement showed the
     masthead occupying only 153px of 375 — so there was never a space problem, and dropping the
     property name from a Knickerbocker booking page was a real loss of identity on the surface
     where most Google Hotels traffic actually lands. */
  .dlp-mast__sub{font-size:11px;letter-spacing:.12em;margin-left:0}
  .dlp-mast__mark{width:34px;height:34px}
}


/* ---------- SCOPE WARNING — read before adding any rule below ----------
   Beds24 reuses .b24room for the CHECKOUT page's guest-details panel, not just room-list cards.
   An unscoped rule here therefore lands on the booking form. This actually happened on 2026-08-03:
   the "hide the empty trailing .row" rule matched every .row.questionrow, so all 14 guest fields
   rendered with display:none, Guest Details appeared blank and Confirm Booking submitted nothing.
   Live checkout was broken by a cosmetic rule.

   EVERY layout/display rule for room cards must be scoped to [id^="roomid"], which exists only on
   the room list. Style-only rules (colour, font) are safe unscoped. When in doubt, scope it. */

/* ---------- room / offer modules → the site's .roomcard ---------- */
.b24-room-module,.b24-offer-module{
  background:#fff;
  border:1px solid var(--delphius-stone);
  border-radius:0 !important;                    /* the site is square-cornered throughout */
  transition:box-shadow .25s ease;
}
.b24-room-module:hover,.b24-offer-module:hover{box-shadow:0 14px 40px rgba(18,18,18,.10)}
.b24-module{border-radius:0 !important}

/* Beds24's utility borders — retone from its greys to the site's stone. */
.border,.bb,.bt,.bl,.rrr,.bbb{border-color:var(--delphius-stone) !important}

/* ---------- prices → the site's .roomcard__rate (Cinzel 24px) ---------- */
.bookingpagedollars{
  font-family:var(--delphius-display) !important;
  font-size:24px !important;
  letter-spacing:.02em;
  color:var(--delphius-obsidian) !important;
  font-weight:600;
}
.bookingpagecents,.bookingpagecurrency{
  font-family:var(--delphius-display) !important;
  color:var(--delphius-obsidian) !important;
  font-size:14.4px !important;
}
.at_pricetd{color:var(--delphius-obsidian)}

/* ---------- EDITION "RATES FROM" eyebrow ----------
   EDITION stacks a small letter-spaced label above a large rate; Beds24 instead emits one flat
   line, "from USD 469.00 per night", where the word "from" is a BARE TEXT NODE — not an element,
   so there is nothing to select and restyle. Zeroing the container's font-size is what kills that
   text node, and every real child then has its size restored explicitly below.

   The restore list is therefore load-bearing: any child of .at_offerfromdiv that is NOT given a
   size here renders at 0 and vanishes. The `> *` catch-all is the safety net for markup Beds24
   adds later — without it a new span would silently disappear rather than merely look wrong.

   Scoped to [id^="roomid"] on purpose. Beds24 reuses these class names in the checkout column,
   and an unscoped layout rule in this file previously hid all 14 guest-detail fields on the live
   page. Anything that zeroes a font-size stays inside the room list. */
[id^="roomid"] .at_offerfromdiv{font-size:0 !important;line-height:1.2 !important}
[id^="roomid"] .at_offerfromdiv > *{font-size:13px !important}      /* safety net — see above */
[id^="roomid"] .at_offerfromdiv::before{
  content:"Rates from";
  display:block;
  font-family:var(--delphius-body,inherit);
  font-size:10px !important;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:#6b6256;
  margin:0 0 2px;
}
/* Beds24 shows ONE of two price blocks per room and swaps between them: `.at_offerfromdiv` (the
   "from" summary) while the room is collapsed, and `.ajaxroomprice` once the offer block expands —
   at which point it puts Bootstrap's `.hidden` on the from-div. Measured on the live page: 3 rooms
   were showing the eyebrow and 2 were not, which is the visible inconsistency in the price column.
   Both blocks now carry the same small-caps label so every room reads the same.

   BOTH READ "Rates from" — owner ruling 2026-08-03: "They should all say rates from". An earlier
   revision here labelled `.ajaxroomprice` "Rate" on the reasoning that it is the rate for the
   current selection rather than a floor across offers. The owner overrode that, and he is right on
   the facts that matter: with one rate plan per room the two blocks render the SAME number, so the
   distinction was invisible to a guest and bought nothing but an inconsistent price column.

   Scoped to the room list — `.ajaxroomprice` occurs 5 times and all 5 are inside `[id^="roomid"]`
   (verified), but the scope stays for the same reason every rule in this file carries one. */
[id^="roomid"] .ajaxroomprice::before{
  content:"Rates from";
  display:block;
  font-family:var(--delphius-body,inherit);
  font-size:10px !important;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:#6b6256;
  margin:0 0 2px;
}
[id^="roomid"] .at_offerfromdiv .bookingpagedollars{font-size:24px !important}
[id^="roomid"] .at_offerfromdiv .bookingpagecents,
[id^="roomid"] .at_offerfromdiv .bookingpagecurrency{font-size:14.4px !important}
[id^="roomid"] .at_offerfromdiv .perpersonperday{font-size:13px !important}

/* The 90-day floor line injected by beds24-brand.js. It lands INSIDE .at_offerfromdiv, whose
   font-size is zeroed to kill Beds24's stray "from" text node — so without an explicit size here it
   would render at 0px and look like the script silently failed. Deliberately quiet: a flexibility
   prompt beneath the real rate, not a second price competing with it. */
[id^="roomid"] .dlp-floor{
  font-size:11px !important;
  line-height:1.35 !important;
  letter-spacing:.02em;
  color:#6b6256;
  margin:4px 0 0;
  white-space:normal;
}

/* ---------- buttons → the site's .btn / .btn--solid ---------- */
.btn,button,input[type="submit"],input[type="button"],.fakelink{
  font-family:var(--delphius-display) !important;
  text-transform:uppercase !important;
  letter-spacing:.14em !important;
  font-size:11.8px !important;
  border-radius:0 !important;
  transition:.2s;
}
.btn-primary,.btn-success,input[type="submit"]{
  background:var(--delphius-obsidian) !important;
  border:1px solid var(--delphius-obsidian) !important;
  color:var(--delphius-ivory) !important;
  padding:13.6px 24px !important;
  min-height:48px;                                /* mobile tap target */
  box-shadow:none !important;
  text-shadow:none !important;
}
.btn-primary:hover,.btn-success:hover,input[type="submit"]:hover{
  background:var(--delphius-brass-deep) !important;
  border-color:var(--delphius-brass-deep) !important;
  color:var(--delphius-ivory) !important;
}
.btn-default{
  background:transparent !important;
  border:1px solid var(--delphius-obsidian) !important;
  color:var(--delphius-obsidian) !important;
}
.btn-default:hover{background:var(--delphius-obsidian) !important;color:var(--delphius-ivory) !important}
.fakelink{color:var(--delphius-brass-deep) !important;cursor:pointer}


/* ---------- DO NOT style .at_checkout as a button ----------
   It is a <td> inside the date-picker table (the CHECK OUT column), not a control. Treating it as
   a primary button set ivory text on a white cell — invisible labels — and added 24px horizontal
   padding, which broke check-out date selection on the live booking page 2026-08-02. Only ever
   target it as a table cell, and never set its colour to the button foreground. */
td.at_checkout{color:var(--delphius-obsidian) !important;text-transform:none !important;
  min-height:0 !important;padding:6px 8px !important;background:transparent !important}


/* ---------- room lead photo (EDITION shape) ----------
   The Room Picture Slider module is set to "Desktop show: Mobile show" with width auto, so the
   photo leads the card the way marriott.com/EDITION does. Left unconstrained it renders at the
   image's natural size — measured 1076x809 per room, which pushed the page from 1825px to 6582px
   and buried the price and CTA below the fold. Constrain to the site's own card ratio
   (.roomcard .media is aspect-ratio 3/2) so both surfaces crop identically. */
.b24-room-module .carousel,.b24-room-module .carousel-inner,.b24-room-module .item{width:100% !important}
.bootstrap-carousel-img,.b24-room-module .carousel img,.b24-room-module .item img{
  width:100% !important;
  aspect-ratio:3/2;
  max-height:340px;
  height:auto !important;
  object-fit:cover;
  display:block;
}
/* The prev/next controls were the real height driver: measured 1603px each, stretching the
   carousel even after the image itself was capped at 340px. Bootstrap expects them absolutely
   positioned; pinning them back collapses the card from 1085px to 616px and the page from
   6582px to 3438px. Capping only the <img> is not enough — verified live before committing. */
.b24-room-module .carousel.slide{height:auto !important}
.b24-room-module .carousel-control{position:absolute !important;top:0 !important;bottom:0 !important;height:auto !important}
.b24-room-module .carousel-indicators{bottom:4px !important}

@media(max-width:760px){
  .bootstrap-carousel-img,.b24-room-module .carousel img,.b24-room-module .item img{max-height:220px}
}


/* ---------- EDITION-shaped room grid ----------
   Measured against marriott.com The Tampa EDITION rooms page 2026-08-02: its .room-card sits in a
   two-column grid at 554x312, the image fills nearly the whole card, the title is 22px/400 sentence
   case and the detail is ONE short line. Ours was a single full-width column at 616px per card with
   a 450-500 character paragraph — the "too much going on" the owner reported.

   Matched here to 544x292 in two columns. The grid parent is an unclassed div that Beds24 emits, so
   it is selected structurally with :has() rather than by adding JS to the panel insert — nothing
   here may touch the booking flow.

   The description is CLAMPED, not rewritten: the full text stays in the DOM for search engines and
   for the room-name keywords deliberately preserved there, while the card shows two lines like
   EDITION. Trimming the copy itself would have thrown away the SEO terms. */


/* the whole-home unit is the feature row, full width */

.b24room{border:1px solid var(--delphius-stone);background:#fff}

/* In a 544px-wide grid cell a 300px photo made the card 520px tall against EDITION's 312px.
   Sized so photo + text lands near their proportions; the full-width feature row can take more. */
.bootstrap-carousel-img,.b24-room-module .carousel img,.b24-room-module .item img{max-height:160px !important}
.b24-room-module .carousel,.b24-room-module .carousel-inner,.b24-room-module .item{height:160px !important}

/* On booking.php the description is a BARE TEXT NODE directly inside .b24-room-desc — there is no
   .at_roomdesctext wrapper like booking2.php has — so the clamp must sit on the module itself or
   that surface renders the full 408px paragraph. Three lines, hard height cap as belt-and-braces. */
.b24-room-desc,.at_roomdesctext,[id^="roomdesctext"]{
  display:-webkit-box !important;-webkit-line-clamp:6;-webkit-box-orient:vertical;overflow:hidden;
  font-size:14px !important;line-height:1.5 !important;color:#4a443b;max-height:126px;
}
/* EDITION titles are 22px/400 sentence case. Cinzel is ours and stays, but the shout comes down:
   smaller, tighter tracking, no forced uppercase. */
.at_roomnametext,[id^="roomnametext"]{
  font-size:18px !important;letter-spacing:.04em !important;text-transform:none !important;font-weight:600;
}
.panel-heading,.b24-roompanel-heading{padding:10px 14px !important}
.panel-body,.b24panel{padding:0 14px 14px !important}

/* (the old two-column grid's mobile block was removed here: it targeted a grid that no longer
   exists and its max-height cap fought the row layout's photo sizing) */


/* ---------- EDITION rate-row order + density ----------
   Verified against the live DOM, not the panel: Beds24 renders the offer block (price + Book)
   BEFORE the photo, and its JS writes an inline height of 1603px on every carousel — which is the
   single root cause behind every oversized card and the large white void reported on the page.

   Three corrections:
   1. Reorder to photo -> description -> price/CTA. EDITION leads with the image; we were leading
      with the price block.
   2. Lay the price and Book button side by side. Stacked (price 74 + per-night 31 + button 68)
      they cost 152px for two pieces of information.
   3. No hero. The whole-home unit is a normal grid card like every other row — EDITION's rate rows
      are uniform, and the oversized lead carousel was ours, not theirs. */
[id^="roomid"] .panel-body.b24panel{display:flex !important;flex-direction:column !important}
[id^="roomid"] .panel-body.b24panel > .row:has(.b24-room-slider){order:1}
[id^="roomid"] .panel-body.b24panel > .row:has(.b24-room-desc){order:2}
[id^="roomid"] .panel-body.b24panel > .offer{order:3}
[id^="roomid"] .panel-body.b24panel > .clearfix,
[id^="roomid"] .panel-body.b24panel > .hidden{display:none !important}
[id^="roomid"] .offer{padding:0 !important}

.b24-offer-select{padding:4px 10px !important}
/* Scoped AND :not(.hidden) — this rule predates the pink-alert bug but carried the same two latent
   faults: it forced display on a generic child selector (un-hiding whatever Beds24 hid with
   Bootstrap's .hidden) and it was not scoped to the room list, so it also reached the checkout step
   where these class names recur. Found by the guard, not by a symptom. */
[id^="roomid"] .b24-offer-select .multiroomhide > div:not(.hidden){
  display:flex !important;align-items:center !important;justify-content:space-between !important;
  gap:14px !important;flex-wrap:nowrap !important}
.b24-offer-select .text-right{text-align:left !important;flex:0 0 auto;display:flex;align-items:baseline;gap:4px}
.b24-offer-select .perpersonperday{flex:1 1 auto;font-size:13px !important;color:#6b6256;margin:0 !important}
.b24-offer-select .b24-roombuttondiv{flex:0 0 auto;margin:0 !important;padding:0 !important}
.b24-offer-select .b24-roombuttondiv .btn{margin:0 !important}


/* ---------- carousel chrome + even cards ----------
   Each room carries 44-70 photos, so Bootstrap renders 44-70 indicator dots which wrap into
   several rows straight across the image — measured 70 on the Garden Wing. That, not the crop,
   was what made the cards look broken. EDITION shows a clean photo with no indicator chrome. */
/* EDITION shows about five small dots bottom-left ON the image. We carry 44-70 photos per room,
   which rendered 44-70 dots wrapping in rows across the picture — the defect visible in the
   owner's screenshot. Capped at five and restyled to match. */
/* EDITION puts the dots in a TRANSLUCENT PILL, centred on the image — not loose in the corner.
   From EDITION_MOBILE_REFERENCE.md, captured from the live page: "dot indicators on a translucent
   pill INSIDE the image, bottom-centre". Ours sat bottom-left with no pill, which reads as chrome
   dropped on the photo rather than part of it, and low-contrast dots vanished against pale images. */
[id^="roomid"] .carousel-indicators{
  display:inline-flex !important;align-items:center !important;gap:6px !important;
  left:50% !important;right:auto !important;bottom:12px !important;
  transform:translateX(-50%) !important;
  width:auto !important;margin:0 !important;padding:6px 10px !important;
  background:rgba(18,18,18,.42) !important;
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  border-radius:999px !important;   /* the ONE rounded element — a pill of dots reads as a control,
                                       not as brand geometry; cards and buttons stay square */
  text-align:center !important}
[id^="roomid"] .carousel-indicators li{
  width:8px !important;height:8px !important;margin:0 5px 0 0 !important;
  background:rgba(255,255,255,.55) !important;border:0 !important;border-radius:50% !important}
[id^="roomid"] .carousel-indicators li.active{background:#fff !important;width:8px !important;height:8px !important}
[id^="roomid"] .carousel-indicators li:nth-child(n+6){display:none !important}
/* Arrows in translucent circles (EDITION trait), and they FADE IN on hover rather than sitting on
   the photo permanently — the photo is the product, the chrome should recede until wanted. Kept
   visible at all times on touch, where there is no hover to reveal them. */
[id^="roomid"] .carousel-control{
  width:44px !important;background:none !important;
  opacity:0;transition:opacity .18s ease}
[id^="roomid"] .b24-room-slider:hover .carousel-control,
[id^="roomid"] .carousel-control:focus{opacity:1}
[id^="roomid"] .carousel-control .glyphicon{
  display:flex !important;align-items:center !important;justify-content:center !important;
  width:34px !important;height:34px !important;border-radius:50% !important;
  background:rgba(18,18,18,.42) !important;
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  text-shadow:none !important}
@media(hover:none){
  [id^="roomid"] .carousel-control{opacity:.85}
}
[id^="roomid"] .carousel-control .glyphicon{color:#fff !important;font-size:20px !important}

/* ---------- the pinned booking strip must sit ABOVE the cards and BELOW the masthead ----------
   Two separate bugs, one block.

   (1) STACKING. Beds24 gives the strip z-index:1000 and .panel-heading z-index:1000, and leaves
   BOTH at position:static — where z-index is inert. Painting therefore fell back to DOM order, and
   since the strip precedes the room list, every room title painted straight through it: the owner's
   screenshot shows "Historic Oakview Room at The Knickerbocker" sitting on top of the NIGHTS field.
   Giving the strip a real position makes its z-index count, and pinning each card into its own
   stacking context at z-index:0 means nothing inside a card can ever climb over the strip again —
   that is the durable half of the fix, since it holds for any future child Beds24 adds.

   (2) TOP OFFSET. Pinned at top:0 the strip covered the masthead, leaving a ~33px sliver of it
   showing. It now parks below the masthead instead. --dlp-mast-h is the measured masthead height;
   change it in one place if the masthead is ever resized.

   NOTE this is deliberately positioning-agnostic. The strip pins on the owner's viewport but stayed
   position:static on mine at 1280px even scrolled to y=1200, so Beds24 is switching it somewhere I
   could not reproduce. Rather than guess at their trigger, sticky+top is asserted here so the
   behaviour is the same on every viewport, and the z-index fix is correct either way.

   (3) SCOPED TO #b24scroller, AND THAT IS LOAD-BEARING. `.colorbookingstrip` / `.b24-bookingstrip`
   are NOT the booking strip — Beds24 hangs them on 47 elements per page: the strip itself, EVERY
   room panel heading (`panel-heading b24-roompanel-heading colorbookingstrip bb`), every date-picker
   cell (`at_checkin` / `at_checkout` / `pthead1-*`), and the shopping cart (`#b24bookshoppingcart`).
   The first version of this block used the bare classes, so all five room titles became
   `position:sticky; top:61px; z-index:1200` and pinned themselves under the masthead one after
   another as the guest scrolled — the owner's "titles" complaint. This is the SAME failure as the
   unscoped `.b24room` rule that hid all 14 checkout fields: a class name Beds24 reuses, styled
   without a scope. `#b24scroller` is the strip's id and it exists on BOTH booking.php and
   booking2.php (verified on each before scoping to it). Do not widen these selectors back to the
   bare class.

   (4) IT HAS TO ACTUALLY TRAVEL. A sticky element can only move within its PARENT's box, and the
   strip's parent (#b24scroller-container) is ~134px tall — so it unstuck almost immediately and
   scrolled away, which is the owner's "dates selector does not float when you scroll". Collapsing
   the two wrappers with display:contents promotes the strip into the tall room-list container, so
   it can stay pinned for the length of the page. display:contents removes those wrappers' boxes,
   which is why the strip is given its own width/centering below — without that it would go
   full-bleed once the .container box disappears. */
:root{--dlp-mast-h:75px}
#b24scroller-fullcontainer,#b24scroller-container{display:contents !important}
#b24scroller{
  position:sticky !important;
  top:var(--dlp-mast-h) !important;
  z-index:1200 !important;
  background:var(--delphius-ivory,#F4F0E8) !important;
  width:min(1140px,92vw) !important;
  margin-inline:auto !important;
}
[id^="roomid"] > .panel{position:relative;z-index:0}

/* ---------- motion: restrained, and only on real affordances ----------
   The card lifts slightly on hover so a guest can see which row they are on in a long list, and the
   photo warms very slightly. Everything is short (.18-.25s) and eased — a booking page should feel
   quiet, not animated.

   NOTE ON PROVENANCE: these are brand-appropriate additions, NOT measured EDITION behaviour. The
   live rateListMenu could not be reached to inspect its hover/scroll work (it expires on deep-link
   and needs a real search session), so nothing here is claimed as a match. The dot pill and arrow
   circles above ARE documented EDITION traits, captured while the page was reachable.

   prefers-reduced-motion is honoured: transitions are dropped entirely for guests who ask for that,
   which on a payment-adjacent page is a courtesy worth the four lines. */
[id^="roomid"] > .panel{transition:box-shadow .22s ease, transform .22s ease}
@media(hover:hover){
  [id^="roomid"]:hover > .panel{
    box-shadow:0 10px 30px rgba(18,18,18,.10);
    transform:translateY(-2px);
  }
  [id^="roomid"] .bootstrap-carousel-img{transition:filter .25s ease}
  [id^="roomid"]:hover .bootstrap-carousel-img{filter:saturate(1.04) brightness(1.02)}
  /* Underline the room name on card hover — signals the whole card is a target. */
  [id^="roomid"] [id^="roomnametext"]{transition:color .18s ease}
  [id^="roomid"]:hover [id^="roomnametext"]{color:var(--delphius-brass-deep) !important}
}
[name="bookmult"],.dlp-cart-remove,[id^="roomid"] .carousel-control{
  transition:background .18s ease,color .18s ease,opacity .18s ease}
@media(prefers-reduced-motion:reduce){
  [id^="roomid"] > .panel,[id^="roomid"] .bootstrap-carousel-img,
  [id^="roomid"] [id^="roomnametext"],[name="bookmult"],.dlp-cart-remove,
  [id^="roomid"] .carousel-control{transition:none !important}
  [id^="roomid"]:hover > .panel{transform:none !important}
}

/* The Update control was removed on owner instruction 2026-08-03 ("Remove the update button, it's
   not needed"). Beds24's datepicker already re-queries rates on change, so it was a second way to do
   something the page did anyway. Its styles are gone with it rather than left as dead CSS. */

/* ---------- room order: most expensive first, via flex `order` ----------
   The room list container is made a flex column ONLY so beds24-brand.js can re-sequence cards with
   `order` instead of insertBefore(). Moving DOM nodes while the guest scrolls changes the height of
   content above the viewport, and the browser's scroll anchoring then yanks the page — that was the
   "jumps back up as you scroll down" glitch. `order` re-sequences with no DOM mutation at all.

   flex-direction:column keeps the existing stacked layout; the cards were already full-width block
   children, so nothing else about the layout changes. If this rule is removed, `order` stops
   applying and the list quietly reverts to Beds24's own sequence. */
[id^="ajaxroomoffer"]:has(> [id^="roomid"]){display:flex !important;flex-direction:column !important}

/* even card heights, CTA pinned to the bottom so the grid reads as a row of equals */

[id^="roomid"] > .panel{display:flex;flex-direction:column;flex:1;margin:0 !important}
[id^="roomid"] .panel-body.b24panel{flex:1}
[id^="roomid"] .panel-body.b24panel > .offer{margin-top:auto}

[id^="roomid"] .b24-room-106,[id^="roomid"] .fakelink{font-size:11px !important;opacity:.7}
[id^="roomid"] .alert,[id^="roomid"] .at_offerwarndiv{margin:0 0 8px !important;padding:6px 10px !important;font-size:12px !important}
[id^="roomid"] .at_offerwarndiv:empty{display:none !important}


/* ---------- EDITION rate-row layout ----------
   Matched to marriott.com/reservation/rateListMenu.mi, measured live: ONE column of horizontal
   rows at 1140x322, photo ~458px on the left, name/details/price/CTA stacked on the right.
   Ours previously stacked everything vertically in a two-column card grid, which is what read as
   clunky next to it.

   The photo lives inside .panel-body while the room name lives in .panel-heading, a sibling, so a
   plain flex row could never put them side by side. display:contents promotes panel-body's
   children into the .panel grid, which lets the photo occupy column 1 across all rows while the
   heading, description and offer stack in column 2. No JS, no DOM rewriting. */
[id^="roomid"]{margin:0 0 20px !important;display:block !important}
[id^="roomid"] > .panel{
  display:grid !important;
  grid-template-columns:38% 62% !important;
  grid-template-rows:auto 1fr auto !important;
  margin:0 !important;border:1px solid var(--delphius-stone);background:#fff;overflow:hidden}
[id^="roomid"] .panel-heading{grid-column:2 !important;grid-row:1 !important;
  border:0 !important;background:transparent !important;padding:26px 26px 6px !important}
[id^="roomid"] .panel-body.b24panel{display:contents !important}
[id^="roomid"] .panel-body.b24panel > .row:has(.b24-room-slider){grid-column:1 !important;grid-row:1 / -1 !important}
[id^="roomid"] .panel-body.b24panel > .row:has(.b24-room-desc){grid-column:2 !important;grid-row:2 !important;padding:0 26px !important}
[id^="roomid"] .panel-body.b24panel > .offer{grid-column:2 !important;grid-row:3 !important;padding:0 26px 26px !important}
[id^="roomid"] .panel-body.b24panel > .clearfix,
[id^="roomid"] .panel-body.b24panel > .hidden,
[id^="roomid"] .panel-body.b24panel > script{display:none !important}

.b24-room-slider{padding:0 !important;border:0 !important}
[id^="roomid"] .carousel,[id^="roomid"] .carousel-inner,.b24room .item{height:100% !important;min-height:322px}
.bootstrap-carousel-img{width:100% !important;height:100% !important;min-height:322px;
  max-height:none !important;object-fit:cover !important}

/* The photo must fill the FULL height of the carousel box, not just its 322px floor.
   Why this repeats the rule above with a longer selector: measured live on the first card, the
   chain .b24-room-slider / .carousel / .carousel-inner / .item all computed to 395.4px while the
   <img> stayed at exactly 322px — its min-height — so `height:100%` was not winning despite
   !important. Bootstrap ships `.carousel-inner > .item > img{height:auto}` and Beds24's booking3.css
   adds `.colorbody img{height:auto}`; matching their child-combinator shape is what actually took.
   (I could not reproduce the override in a rule-dump because /brand/ is cross-origin to beds24.com
   and cssRules throws, so this is an empirically verified fix, not a derived one.)

   THIS IS WHAT PUTS THE CAROUSEL DOTS BACK. The indicators are absolutely positioned against
   .carousel with bottom:12px. When the image is shorter than .carousel, the dots land in the gap
   BELOW the photo instead of on it — measured on the first card: image ended at y=711, dots at
   y=744. Only the first card showed it, because only the tallest row stretched that far, which is
   why it read as "the Oakview photo lacks the dots" rather than as a layout bug. */
[id^="roomid"] .carousel-inner > .item > img.bootstrap-carousel-img,
[id^="roomid"] .carousel-inner > .item > a > img.bootstrap-carousel-img{
  height:100% !important;min-height:0 !important;max-height:none !important;object-fit:cover !important}

/* THE PHOTO MUST NOT GROW WITH THE CARD. Selecting a quantity expands the offer block, which makes
   the card taller — and because the slider column stretches and the image is height:100% of it, the
   PHOTO grew too. Measured at 1280: card 379 -> 477 and the image 377 -> 475 on a single quantity
   change. The owner saw exactly that ("when you adjust the quantity on a room, it changes the photo
   size").
   Fixing the slider column to a set height and top-aligning it decouples the two: the card can grow
   for its own content while the photo stays put. The height is applied to ALL FOUR levels
   (.b24-room-slider / .carousel / .carousel-inner / .item) plus the img, because the carousel dots
   are positioned against .carousel — if that box stays taller than the image, the dots drop into the
   gap below the photo, which was a separate bug earlier today. Same number everywhere, on purpose. */
@media(min-width:821px){
  [id^="roomid"] .panel-body.b24panel > .row:has(.b24-room-slider){align-self:start !important}
  [id^="roomid"] .b24-room-slider,
  [id^="roomid"] .b24-room-slider .carousel,
  [id^="roomid"] .b24-room-slider .carousel-inner,
  [id^="roomid"] .b24-room-slider .item,
  [id^="roomid"] .b24-room-slider .bootstrap-carousel-img{
    height:322px !important;min-height:322px !important;max-height:322px !important}
}

@media(max-width:820px){
  [id^="roomid"] > .panel{grid-template-columns:1fr !important;grid-template-rows:auto auto auto auto !important}
  [id^="roomid"] .panel-heading{grid-column:1 !important;grid-row:2 !important}
  [id^="roomid"] .panel-body.b24panel > .row:has(.b24-room-slider){grid-column:1 !important;grid-row:1 !important}
  [id^="roomid"] .panel-body.b24panel > .row:has(.b24-room-desc){grid-column:1 !important;grid-row:3 !important}
  [id^="roomid"] .panel-body.b24panel > .offer{grid-column:1 !important;grid-row:4 !important}
  /* display:contents promotes the slider and description into the panel grid, so THEY are the grid
     items, not the .row wrappers above. Without repositioning them here, the desc rule's
     grid-column:2 creates an implicit SECOND column and the card never collapses on a phone —
     measured 176.8px + 141.7px at 375px instead of one full-width column. */
  [id^="roomid"] .b24-room-slider{grid-column:1 !important;grid-row:1 !important}
  [id^="roomid"] .b24-room-desc{grid-column:1 !important;grid-row:3 !important;padding:0 18px !important}
  [id^="roomid"] .carousel,[id^="roomid"] .carousel-inner,.b24room .item,.bootstrap-carousel-img{min-height:200px !important}
}




/* ---------- surface guard: EVERY layout slot renders the EDITION shape ----------
   booking.php (the Google Hotels landing, referer=google) renders from a DIFFERENT layout slot
   than booking2.php — there are SIX slots and only Layout 4 was cleaned in the panel. That slot
   still carried the property picture slider, per-room calendar, price table, offer picture and
   amenities list: 14,325px of page, 2,500px cards, the giant hot-tub carousel on top.

   Rather than chase six panel slots (the fifth "second surface I didn't know about" today), this
   guard makes the stylesheet itself enforce the shape: whatever a slot emits, only the room
   slider, room description and offer select (price + Book) render per room, and the
   property-level carousel never shows. Panel cleanup of the other slots is still worthwhile for
   DOM weight, but the LOOK no longer depends on it. */
[id^="carousel-generic-p"]{display:none !important}
.row:has(> div > [id^="carousel-generic-p"]){display:none !important}
[id^="roomid"] .b24-room-module:not(.b24-room-slider):not(.b24-room-desc){display:none !important}
[id^="roomid"] .b24-offer-module:not(.b24-offer-select){display:none !important}


/* ---------- booking.php (Google landing) packs slider+desc into ONE row ----------
   booking2.php emits the photo and the description as SEPARATE .row children, which the grid rules
   above place into column 1 and column 2. booking.php emits them as col-sm-6 siblings inside a
   SINGLE .row — so both of the rules above matched that one row, the later (desc) rule won, and the
   photo was pushed into column 2 while an empty trailing .row auto-placed into column 1. That is
   the misalignment the owner reported: a blank left gutter with the description overlapping the
   photo's top-right.

   Fix: promote that combined row with display:contents as well, so the slider and the description
   become direct grid items and can be placed independently. Their Bootstrap col-sm-6 width must
   also be released or the photo renders at 210px inside a 420px column. */
[id^="roomid"] .panel-body.b24panel > .row:has(.b24-room-slider):has(.b24-room-desc){display:contents !important}
[id^="roomid"] .b24-room-slider{grid-column:1 !important;grid-row:1 / -1 !important;padding:0 !important}
[id^="roomid"] .b24-room-desc{grid-column:2 !important;grid-row:2 !important;padding:0 26px !important}
[id^="roomid"] .b24-room-slider,[id^="roomid"] .b24-room-desc{
  width:100% !important;max-width:100% !important;float:none !important}
[id^="roomid"] .b24-room-slider .carousel,
[id^="roomid"] .b24-room-slider .carousel-inner,
[id^="roomid"] .b24-room-slider .item{height:100% !important;min-height:322px}
[id^="roomid"] .b24-room-slider .bootstrap-carousel-img{
  width:100% !important;height:100% !important;min-height:322px;object-fit:cover !important}
/* the trailing empty .row auto-places into column 1 and creates the gutter */
[id^="roomid"] .panel-body.b24panel > .row:not(:has(.b24-room-slider)):not(:has(.b24-room-desc)){display:none !important}


/* ---------- multi-room mode: the strip BOOK button ----------
   bookpageallowmulti = Enabled turns the per-room Book buttons into quantity selectors plus a
   single BOOK in the booking strip. Booking still works, but that button ships at 73x36 — under
   the 44px tap target — and unstyled. Branded and sized here so the funnel is correct in EITHER
   mode. (Per-room CTAs are closer to EDITION, which puts a View Rates button on every row; that
   is an owner decision, not a styling one — see the note in the handoff.) */
[name="bookmult"]{
  background:var(--delphius-obsidian) !important;
  border:1px solid var(--delphius-obsidian) !important;
  color:var(--delphius-ivory) !important;
  font-family:var(--delphius-display) !important;
  text-transform:uppercase !important;letter-spacing:.14em !important;font-size:11.8px !important;
  border-radius:0 !important;min-height:44px !important;padding:12px 26px !important;
  box-shadow:none !important;text-shadow:none !important;
}
[name="bookmult"]:hover{
  background:var(--delphius-brass-deep) !important;border-color:var(--delphius-brass-deep) !important}
@media(max-width:760px){[name="bookmult"]{width:100% !important;min-height:48px !important}}


/* ---------- sticky booking strip: breathing room on scroll ----------
   The strip pins under the masthead when the guest scrolls and sat flush against it, with the
   date/night fields tight to the top edge (owner screenshot 2026-08-03). EDITION's rate bar gives
   its controls real vertical padding and separates itself from the header with a hairline. */
#b24scroller{
  padding:14px 18px !important;
  border-top:0 !important;
  border-bottom:1px solid var(--delphius-stone) !important;
  box-shadow:0 6px 18px rgba(18,18,18,.06) !important;
}
#b24scroller-fullcontainer{padding-top:8px !important}
#b24scroller .row{margin-top:0 !important;margin-bottom:0 !important}
#b24scroller label,#b24scroller .bookingstriplabel{margin-bottom:4px !important;display:block}
#b24scroller input,#b24scroller select{margin-bottom:0 !important}

/* ---------- booking strip + shopping cart chrome ----------
   These two DO share a look, so they share a rule — but by id, not by the reused class. The cart
   (#b24bookshoppingcart) is a normal-flow summary at the foot of the page: it takes the white card
   treatment and must NEVER take the sticky/z-index block above, or it pins itself over the room
   list. Room headings and date-picker cells carry .colorbookingstrip too and want none of this. */
#b24scroller{
  background:#fff !important;
  border:1px solid var(--delphius-stone) !important;
  border-radius:0 !important;
  box-shadow:0 6px 24px rgba(18,18,18,.05);
}

/* The shopping cart is hidden on owner instruction 2026-08-03: it renders a stray room row beneath
   the map ("still has an oakview spot at the bottom, out of place, shouldn't be there"). It is
   Beds24's selected-rooms summary, so it only appears once a quantity is set and it duplicates
   information already in the card the guest just used.
   SAFE ONLY BECAUSE THE STRIP KEEPS ITS BOOK BUTTON. This cart carries the SECOND of the page's two
   [name="bookmult"] submits; hiding it removes one booking control, and with bookpageallowmulti on
   the strip's is the only other one. Verified after this change that a visible BOOK remains. If the
   strip is ever restyled away, un-hide this first. */
#b24bookshoppingcart{display:none !important}

/* ---------- the offer block lays out ACROSS, not down ----------
   Selecting a quantity makes Beds24 reveal the guest selects, and it stacks the whole control group
   — Quantity, RATES FROM, price, Guests, Children — inside a Bootstrap `col-sm-2`. Measured live:
   109px wide by 300px TALL. That is what pushed the card from 379px to 526px, and since the photo is
   now correctly pinned at 322px, the extra height showed up as a slab of empty white beside it.
   The owner saw both symptoms at once ("white space appearing and stuff moving").

   Widening that column and flowing its controls horizontally fixes the cause rather than the
   symptom: the group becomes short and wide, the card barely grows, and there is no void to fill.
   align-items:flex-end keeps the selects sitting on the price baseline instead of floating. */
[id^="roomid"] .offer .row > [class*="col-"]{width:100% !important;float:none !important}

/* `:not(.hidden)` IS LOAD-BEARING. The first version of this rule said
   `.multiroomshow > div{display:flex !important}`, which matched Beds24's HIDDEN children too --
   `.hidden.ajaxroomwarn` and the "Not available for this selection" alert -- and `!important`
   overrode Bootstrap's own `.hidden{display:none}`. The result was a pink alert bar appearing across
   every room card. Never blanket-set display on a container's children when the framework uses a
   utility class to hide some of them. */
[id^="roomid"] .offer .multiroomshow > div:not(.hidden){
  display:flex !important;
  flex-wrap:wrap !important;
  align-items:flex-end !important;
  gap:14px !important;
}
[id^="roomid"] .offer .multiroomshow > div:not(.hidden) > *:not(.hidden){margin:0 !important}
/* Keep the price and the selects on ONE line: without this the price box claims the full row and
   the selects wrap beneath it, which is most of the height the owner is still seeing. */
[id^="roomid"] .offer .b24-multipricebox{flex:0 0 auto !important;width:auto !important}
[id^="roomid"] .offer .form-inline{display:flex !important;gap:10px !important;align-items:flex-end !important}
[id^="roomid"] .offer .b24-multipricebox{float:none !important;text-align:left !important}
[id^="roomid"] .offer select{width:auto !important;min-width:92px !important}

/* ---------- remove control on each cart line ----------
   Beds24's cart has NO remove affordance — verified by enumerating its controls: a room list and one
   Book button, nothing else. A guest who added a room by mistake, or who arrived with one already
   selected from a Google deep-link, could only undo it by scrolling back to that specific card and
   finding its quantity select. The button is injected by beds24-brand.js and sets that room's
   quantity back to 0 through Beds24's own select, so its ajax stays authoritative. */
.dlp-cart-remove{
  appearance:none;border:0;background:none;cursor:pointer;
  font-family:var(--delphius-sans);font-size:11px;letter-spacing:.08em;text-transform:uppercase;
  color:#6b6256;padding:2px 0 0;margin:0;text-decoration:underline;
}
.dlp-cart-remove:hover,.dlp-cart-remove:focus{color:var(--delphius-obsidian)}

/* ---------- the cart as a labelled floating panel (EDITION-style) ----------
   Owner 2026-08-03: label it clearly, float it to the right while shopping, hide it when empty.

   It is FIXED, not sticky: the cart lives near the foot of the document, so sticky would only pin it
   once the guest had already scrolled past everything it is meant to help them with. Fixed keeps it
   in view for the whole browse, which is the point of a cart.

   Desktop only. On a phone a fixed right-hand panel would cover the room cards it is summarising, so
   below 820px it returns to normal flow at the foot of the list (see the mobile block). */
.dlp-cart-head{
  font-family:var(--delphius-display);
  font-size:11px;letter-spacing:.16em;text-transform:uppercase;
  color:#6b6256;
  padding:0 0 8px;margin:0 0 10px;
  border-bottom:1px solid var(--delphius-stone);
}
@media(min-width:821px){
  #b24bookshoppingcart.dlp-cart-show{
    position:fixed !important;
    top:calc(var(--dlp-mast-h) + 24px) !important;
    right:24px !important;
    width:300px !important;
    max-height:calc(100vh - var(--dlp-mast-h) - 48px) !important;
    overflow-y:auto !important;
    z-index:1300 !important;          /* above cards (0) and the strip (1200), below the masthead (1500) */
    margin:0 !important;
    padding:16px 18px !important;
    box-shadow:0 14px 40px rgba(18,18,18,.14) !important;
  }
  /* Beds24 lays the cart out as Bootstrap columns for a full-width bar; at 300px they must stack. */
  #b24bookshoppingcart.dlp-cart-show .row > [class*="col-"]{width:100% !important;float:none !important}
  #b24bookshoppingcart.dlp-cart-show table{width:100% !important}
  #b24bookshoppingcart.dlp-cart-show [name="bookmult"]{width:100% !important;margin-top:10px !important}
}
/* ...but shown whenever it holds anything, toggled by beds24-brand.js. Owner ruling: the cart should
   always be there, because an element that appears and disappears on a threshold is itself the
   confusing thing. It stays hidden only when EMPTY (Beds24 renders 0 rows then, and an empty
   bordered box summarises nothing). The cart is also the only place a guest can see they are
   carrying more than one room -- selection persists server-side across page loads and there are no
   remove controls -- so hiding it outright produced a dead end at checkout. */
#b24bookshoppingcart.dlp-cart-show{display:block !important}

/* ---------- form controls → the site's .bookbar inputs ---------- */
input[type="text"],input[type="email"],input[type="tel"],input[type="date"],input[type="number"],
select,textarea,.form-control{
  font-family:var(--delphius-sans) !important;
  font-size:16px !important;
  border:1px solid var(--delphius-stone) !important;
  border-radius:0 !important;
  background:var(--delphius-ivory) !important;
  color:var(--delphius-obsidian) !important;
  box-shadow:none !important;
  min-height:48px;
}
input:focus,select:focus,textarea:focus,.form-control:focus{
  outline:2px solid var(--delphius-brass) !important;
  outline-offset:1px;
  border-color:var(--delphius-brass) !important;
  box-shadow:none !important;
}
label{font-family:var(--delphius-display);text-transform:uppercase;letter-spacing:.12em;
  font-size:10.9px;color:#4a443b}

/* ---------- availability / calendar accents ---------- */
.dateavail,.datestay{border-color:var(--delphius-stone) !important}
.atcolor,.active{color:var(--delphius-brass-deep)}

/* ---------- de-emphasise Beds24 chrome that adds nothing for our guest ----------
   Footer branding is a Private-Label (paid) feature and CANNOT be removed by CSS; we only
   de-emphasise what is legitimately ours to restyle. If the residual Beds24 branding still reads
   "separate site" after this, THAT is the moment to revisit white-label — not before. */
#b24scroller-anchor,#b24scroller-fullcontainer{background:transparent !important}
.glyphicon{color:var(--delphius-brass)}

/* ---------- mobile ----------
   Measured on a real 375x812 viewport 2026-08-02, not assumed. Findings that drove these rules:
   - 13 tap targets were under 44px. min-height:48px had only been applied to the primary/checkout
     buttons, so generic .btn came out at 30px and the "pictures"/"more details" .fakelink rows at
     19px — both well under a thumb.
   - The 7-day availability table renders 559px wide inside a 375px viewport. That is NOT a defect
     and must not be "fixed": its parent (.ajaxroomofferpricetable) is overflow-x:auto, so it
     scrolls within its own container and the page itself has zero horizontal overflow (document
     scrollWidth measured exactly 375). Forcing that table narrower would squash the price grid.
   - Submit buttons sit at 11.8px to match the site's .btn, which is correct: iOS zoom-on-focus
     applies to text-entry fields, and those are pinned at 16px above. */
@media(max-width:760px){
  body{font-size:16px !important}
  .b24fullcontainer,.container,.container2{width:94vw !important}
  .bookingpagedollars{font-size:20.8px !important}

  /* thumb-sized targets */
  .btn,.btn-default,button{min-height:44px}
  .btn-primary,.btn-success,input[type="submit"]{min-height:48px;width:100%}
  .fakelink{display:inline-flex;align-items:center;min-height:44px}
}

/* ---------- print / motion ---------- */
@media(prefers-reduced-motion:reduce){*{transition:none !important}}

/* ============================================================================
   MOBILE OVERRIDES — MUST STAY LAST IN THIS FILE
   These lost to the desktop rules purely on document order, not specificity: the 820px block sits
   earlier in the file than the later-added base rules, and with equal specificity and !important on
   both sides, the last one wins. The card therefore never collapsed on a phone — measured
   176.8px + 141.7px at 375px, one explicit track plus an implicit one created by the description
   still being pinned to column 2.

   Anything mobile goes HERE, at the bottom. Do not append new desktop rules after this block.
   ============================================================================ */
@media(max-width:820px){
  [id^="roomid"] > .panel{grid-template-columns:1fr !important;grid-template-rows:auto auto auto auto !important}
  [id^="roomid"] .b24-room-slider{grid-column:1 !important;grid-row:1 !important;max-width:100% !important}
  [id^="roomid"] .b24-room-desc{grid-column:1 !important;grid-row:3 !important;max-width:100% !important;padding:0 18px !important}
  [id^="roomid"] .panel-heading{grid-column:1 !important;grid-row:2 !important}
  [id^="roomid"] .panel-body.b24panel > .offer{grid-column:1 !important;grid-row:4 !important}
  [id^="roomid"] .carousel,[id^="roomid"] .carousel-inner,[id^="roomid"] .item,
  [id^="roomid"] .bootstrap-carousel-img{min-height:200px !important;height:200px !important}

  /* Trim the two fat blocks on a phone. Measured on a 530px card: the heading took 91px for a
     single line of room name (26px of top padding inherited from the desktop rule) and the offer
     block 170px, of which the price/CTA row is only part. Desktop spacing on a 375px screen is
     just wasted scroll. */
  [id^="roomid"] .panel-heading{padding:12px 18px 2px !important}
  [id^="roomid"] [id^="roomnametext"],[id^="roomid"] .at_roomnametext{font-size:17px !important;line-height:1.25 !important}
  [id^="roomid"] .panel-body.b24panel > .offer{padding:0 18px 14px !important}
  [id^="roomid"] .b24-offer-select{padding:2px 0 !important}
  [id^="roomid"] .b24-offer-select .multiroomhide > div{gap:10px !important}
  [id^="roomid"] .b24-offer-select .perpersonperday{font-size:12px !important}

  /* The "Rates from" block is scoped [id^="roomid"] .at_offerfromdiv .x — three classes' worth of
     specificity, so the plain `.bookingpagedollars{20.8px}` mobile rule further up cannot reach it
     no matter where it sits in the file. Match the specificity here or the phone renders the
     desktop 24px rate. */
  [id^="roomid"] .at_offerfromdiv .bookingpagedollars{font-size:20.8px !important}
  [id^="roomid"] .at_offerfromdiv::before,
  [id^="roomid"] .ajaxroomprice::before{font-size:9px !important;letter-spacing:.12em}
  [id^="roomid"] .dlp-floor{font-size:10px !important}

  /* FLOATING ON MOBILE TOO — owner: "it should be floating only". An earlier revision dropped it
     back into normal flow here, which left a cart sitting at the foot of the page on phones, i.e.
     exactly the stray panel the owner objected to in the first place.
     A right-hand panel would cover the cards at 375px, so on mobile it docks to the BOTTOM edge
     instead: full width, capped at 40vh and scrollable so a multi-room selection can never swallow
     the screen. Body gets matching bottom padding so the last card is still reachable behind it. */
  #b24bookshoppingcart.dlp-cart-show{
    position:fixed !important;
    left:0 !important;right:0 !important;bottom:0 !important;top:auto !important;
    width:auto !important;
    max-height:40vh !important;overflow-y:auto !important;
    z-index:1300 !important;
    margin:0 !important;padding:12px 14px !important;
    border-left:0 !important;border-right:0 !important;border-bottom:0 !important;
    box-shadow:0 -8px 26px rgba(18,18,18,.16) !important;
  }
  #b24bookshoppingcart.dlp-cart-show .row > [class*="col-"]{width:100% !important;float:none !important}
  #b24bookshoppingcart.dlp-cart-show [name="bookmult"]{width:100% !important;margin-top:8px !important}
  /* Only reserve space when the cart is actually there. */
  body:has(#b24bookshoppingcart.dlp-cart-show){padding-bottom:44vh !important}

  /* The desktop clamp went 3 lines -> 6 because the two-column card has dead space to the right of
     the price box, so clamping there was throwing away copy to save room nothing needed. A phone
     card is a single column and every line is real scroll, so 3 stands here. */
  [id^="roomid"] .b24-room-desc,[id^="roomid"] .at_roomdesctext,[id^="roomid"] [id^="roomdesctext"]{
    -webkit-line-clamp:3 !important;max-height:84px !important}

  /* The masthead is shorter on a phone; keep the strip parked directly under it, not over it.
     MEASURED, not guessed: 61px at 375px (75px at desktop). An earlier 56px here was an estimate
     and left the strip tucked 5px behind the masthead — invisible rather than wrong, because the
     masthead outranks it at z-index:1500, but it clipped the strip's top edge. If the masthead's
     padding or type size changes, re-measure .dlp-mast and update this. */
  :root{--dlp-mast-h:61px}

  /* ---- sticky bar: stop it covering the content it floats over ----
     EDITION pins a ~90px read-only summary (dates, guests, one chevron). Ours pins the whole
     editor plus a BOOK button, so on a phone it overlays the property title — the owner's
     screenshot shows "The Knickerbocker by Delphius" sliced in half behind it — and parks a
     booking CTA under the thumb mid-scroll.
     Until the markup can be reshaped, make it behave: compact it and keep it clear of the content
     below. */
  #b24scroller{
    padding:8px 12px !important;
    box-shadow:0 4px 14px rgba(18,18,18,.10) !important;
  }

  /* NEVER hide [name="bookmult"]. A previous revision here did, on the reasoning that "the per-room
     CTA is the real conversion path" — that reasoning is FALSE on this property. bookpageallowmulti
     is ON, and in multi-room mode Beds24 replaces every per-room Book button with a quantity
     selector and leaves ONE strip BOOK as the only way to submit. Measured live at 375px:
     zero elements matching input[name^="br1-"], so hiding the strip BOOK leaves a phone guest with
     no bookable control anywhere on the page. That rule shipped and did no damage only because its
     selector never matched (bookmult sits in .multiplebookbutton, not inside .b24-bookingstrip) —
     luck, not design. If the per-room CTA is ever wanted back, turn bookpageallowmulti OFF in
     Beds24 first and confirm the per-room buttons render; do not reach for display:none. */
  /* #b24scroller, not the class: .b24-bookingstrip also lands on every room heading and every
     date-picker cell, so a bare-class font-size here shrinks the room titles too. */
  #b24scroller label,#b24scroller .bookingstriplabel{
    font-size:9px !important;letter-spacing:.10em !important;margin:0 0 2px !important}
  #b24scroller input,#b24scroller select{
    min-height:38px !important;font-size:14px !important;padding:4px 8px !important}
  /* the strip is position:sticky; give the content beneath it somewhere to land */
  #b24scroller-fullcontainer{margin-bottom:10px !important}
  [id^="ajaxroomofferprop"] > .b24fullcontainer:first-of-type{padding-top:4px !important}
}
