/* ============================================================================
 * engine-surface.css - material, seams, control grammar, brand
 * ---------------------------------------------------------------------------
 * The finish pass: the split header, the stone texture and gradients that stop
 * surfaces reading as flat blocks, both column seams, the shared control grammar,
 * the active-state ember, and the logo mark.
 *
 * LOAD ORDER: 5 of 5. LAST - this is the override layer and must win.
 *
 * This is where live-review decisions land. It is last on purpose so a refinement
 * never has to fight for specificity; it wins on order instead.
 * ==========================================================================*/

/* ── SPLIT HEADER: Details left, name centred, Book Now right ──────────────
         Every tab rule that was written for the right-hand group is mirrored onto the
         left one, so the lift onto the top border, the flare and the deck stacking all
         behave identically on both sides rather than being reimplemented. */
      .browse-detail .modal-header-left { display:flex; align-items:flex-end; flex:0 0 auto; }
      .browse-detail .modal-header-left .modal-tabs {
        margin-bottom:0; gap:0; flex-wrap:nowrap; align-items:flex-end; margin-top:-19px; }
      /* The name takes the space between the two tabs and centres in it. `min-width:0`
         is load-bearing: without it a long property name refuses to shrink below its
         content width and shoves a tab off the pane instead of wrapping. */
      .browse-detail .modal-title {
        flex:1 1 auto; min-width:0; text-align:center; padding:0 1rem; }
      /* The active tab is a state, not an action — see the click guard in
         browse.js. pointer-events also stops the hover styling implying it
         still does something. */
      .browse-detail .modal-tab.active { pointer-events:none; cursor:default; }
      /* Elec 2026-08-16: the buttons alternate WITH the panes — "swell and
         brighten to cover as the other fades and shrinks back. smooth and
         even." The swell runs at the deck's 0.55s so button and pane move as
         one gesture; colour keeps its own quicker 0.28s so hovering an
         inactive tab still feels responsive. */
      .browse-detail .modal-tab {
        transition:color 0.28s, border-color 0.28s, background 0.28s,
                   transform 0.55s var(--ease-out), filter 0.55s var(--ease-out);
        /* ⛑ THE SCALE SWELL IS REMOVED (2026-08-16). Dropping the 3px padding
           did NOT equalise the tabs — they still measured 33 vs 36 — because
           the remaining difference was this: active scaled 1.06, inactive 0.97,
           a 1.09 ratio that matches the heights exactly. The swell was mine;
           Elec's "swell and brighten" was about the PANES covering each other,
           and those still do it. On the tabs it fought the shared geometry the
           flare depends on, so brightness carries the alternation alone and the
           two tabs are now dimensionally identical. */
        filter:brightness(0.9); }
      .browse-detail .modal-tab.active { filter:brightness(1.06); }
      .browse-detail .bd-rev-text { font-size:0.88rem; color:#F5F1E9; }
      .browse-detail .bd-meta { color:#D6DDE3; font-weight:600; }
      /* Elec: once a property is selected (showing in the center), every OTHER
         list card reads DESELECTED — greyed, partially translucent, slightly
         shrunken. Hover / pin-linked cards pop back to full presence. */
      .browse-section .prop-card { display:grid; grid-template-columns:112px 1fr; align-items:stretch;
        transition:transform 0.35s var(--ease-out), border-color 0.35s, box-shadow 0.35s, opacity 0.3s ease, filter 0.3s ease; }
      .browse-section.sel-locked:has(.prop-card.selected) .prop-card:not(.selected):not(:hover):not(.map-hi) {
        opacity:0.55; filter:grayscale(0.55) brightness(0.9); transform:scale(0.965); }
      /* (Reverted 2026-08-15: hiding the FIRST CARD's top border was a misread
         of "the shorter gold bar" — Elec wants the card border intact.) */
      /* Elec: hovering EITHER the pin or the list row slightly expands and
         emphasizes the list card — one shared state shows the relation. */
      /* scale REMOVED 2026-08-19 (Elec, second instance tonight: "on hover..
         causes growth that pushes them out of screen, stop growth on hover" -
         the base-file scale was removed earlier; THIS higher-specificity
         engine rule was the survivor). Glow + border emphasis stay. */
      .browse-section .prop-card:hover, .browse-section .prop-card.map-hi {
        border-color:var(--gold); z-index:3;
        box-shadow:0 0 22px rgba(201,169,110,0.3), 0 10px 30px rgba(5,29,64,0.55); }
      /* pin-linked card breathes in time with its pin */
      .browse-section .prop-card.map-hi,
      .browse-section .prop-card:hover { animation:cardBeat 2.6s ease-in-out infinite; }
      /* the clicked card holds its highlight but stops beating */
      .browse-section .prop-card.selected:not(:hover):not(.map-hi) { animation:none; }
      
      /* GROUP 2 (Elec 2026-08-15): compact LIST cards — photo scaled down to a
         side thumbnail so the basic info + upfront pricing reads as a list. */
      .browse-section .card-img { aspect-ratio:auto; height:100%; min-height:104px; }
      .browse-section .card-badges { display:none; }
      .browse-section .card-body { padding:0.5rem 0.7rem 0.55rem; }
      .browse-section .card-name { font-size:1rem; margin-bottom:0.2rem; color:#FFFFFF; }
      .browse-section .card-desc { display:none; }
      .browse-section .card-location-row { margin-bottom:0.1rem; }
      .browse-section .card-location { font-size:0.75rem; }
      .browse-section .card-meta { font-size:0.75rem; font-weight:600; color:#D6DDE3; }
      /* GROUP 2: "less gold line breaks across middle booking column modals" —
         keep the modal header's rule and the quote's money-total rule; the
         bk-from / stepper-row / quote-top gradients go. */
      /* Elec: "date bar to calendar looks good from header, do not repeat in
         central column" — the panel's date line is hidden; dates are set from
         the HEADER search bar only and flow into the panel's quote. (The
         calOverlay machinery stays mounted but unreachable — one CSS line to
         reverse.) */
      .browse-detail .bk-dateline { display:none; }
      /* GROUP 4 (Elec): the center NEVER shows the base single-night price —
         only the booking total + breakdown. The module's FROM $X/night row is
         hidden on this surface. */
      .browse-detail .bk-from { display:none; }
      .browse-detail .bk-quote:not(:empty) { border-top:none; border-image:none; padding-top:0.4rem; }
      /* Quote state must also fit the locked pane (was 82px over): tighter
         itemized rows, total row, and CTA spacing. */
      /* ⛑ Elec 2026-08-16: the deposit line "did not move and stay aligned with
         the rest of the receipt." It was full-width (499px) and text-align:right,
         so its text hugged the PANE's right edge at 996 while the receipt now
         ends at 909 — 87px adrift. Giving it the receipt's own 20.4rem box with
         auto margins puts its right edge on the price column, where the Total
         above it sits; text-align:right is kept, that part was always correct. */
      .browse-detail .bk-q-dep { margin:0.15rem auto 0; width:20.4rem; }
      /* Center column: less padding, less wasted space — it must flow. */
      .modal-header { padding:0.65rem 1rem; background:var(--pine); }
      .modal-body { padding:0.8rem 1rem 0.9rem; }
      .modal-tabs { margin-bottom:0.6rem; }
      /* (Group-2 note: the inline-calendar compression rules that lived here
         are GONE — the calendar is overlay-only now, full-size cells inside
         the pop-open. Only the general tightening below remains.) */
      /* Elec: the centre booking modal takes the SAME ground as the list cards
         (var(--pine)) instead of its old flat #232B36, so the selected
         property reads as one surface across the two columns. */
      /* ⛑ AMENDED 2026-08-28 (Elec: "the booking page is ugly here the
         background is wrong, solid block of color. makes me cringe"). The note
         above still holds in intent - the sheet should share the cards' ground -
         but `var(--pine)` is ONE flat translucent wash over a surface that is
         now ~3000px of scrolling content, so it read as a slab rather than a
         material. This is the same rule, given the depth the rest of the page
         has: the pine wash stays as the base so the card kinship is kept, with
         the calendar overlay's own gradient (his approved
         `#0A2247 -> forest` family) laid over the top few hundred pixels and
         the page's mottle grain across the whole thing. Pixel stops, not
         percentages - a percentage stop finishes in the first inch on a sheet
         this tall and flattens out again, which is the very thing he flagged.
         ⚠ This selector (0,2,0) is why the generic `.bd-modal` ground further
         down this file did not show: it outranks it. Amended HERE, at the
         deciding rule. */
      .browse-detail .bd-modal {
        background-color: var(--pine);
        background-image:
          linear-gradient(168deg, rgba(10,34,71,0.90) 0px, rgba(10,34,71,0.32) 340px, rgba(10,34,71,0) 620px),
          var(--mottle);
        background-repeat: no-repeat, repeat;
      }
      .browse-detail .tab-pane { padding-top:0; }
      /* GROUP 3: the no-dates state — the center is ONLY a date-selector
         calendar (two-month spread, shared dr- grammar), centered in the pane. */
      /* GROUP 4 (Elec): calendar + title scaled UP to fill the column — no
         dead space on first load. */
      .cd-wrap { height:100%; display:flex; flex-direction:column; align-items:center; justify-content:center; padding:0.8rem 1.2rem; }
      /* Elec 2026-08-17: "central first load calendar title should be gold text… too much
   white there." It was parchment at ~2.7rem — the single largest light mass on the
   page, and on first load it is the first thing the eye lands on. Gold makes it read
   as the invitation it is rather than as a block of white. */
.cd-title { font-family:var(--display); font-size:clamp(2rem, 2.6vw, 2.7rem); font-weight:600; color:var(--gold); margin:0 0 0.45rem; }
      .cd-sub { font-size:1rem; color:var(--sage); margin:0 0 1.8rem; text-align:center; }
      .cd-cols { display:flex; gap:2.8rem; justify-content:center; width:100%; }
      .cd-wrap .dr-cal { width:min(330px, 46%); }
      .cd-wrap .dr-month { font-size:1.35rem; white-space:nowrap; }
      .cd-wrap .dr-dow { font-size:0.72rem; margin-bottom:0.45rem; }
      .cd-wrap .dr-cell { font-size:0.95rem; }
      /* Elec: no vertical jump between 5-row and 6-row months — every month
         reserves a six-row box (7 cols : 6 rows), rows pinned to the top. */
      .cd-wrap .dr-grid { aspect-ratio:7/6; align-content:start; }
      /* Elec: a chosen day was a solid gold block. Now it's a 2px gold RING —
         the same weight as the gold rules and double borders used throughout —
         over a far more translucent fill, so the date reads through it. */
      .cd-wrap .dr-cell.sel,
      .cd-wrap .dr-cell.sel-start,
      .cd-wrap .dr-cell.sel-end {
        border-radius:50%;
        background:rgba(201,169,110,0.18);
        box-shadow:inset 0 0 0 2px var(--gold);
        color:var(--parchment);
        font-weight:700;
      }
      .cd-wrap .dr-cell.sel.tdy::after { background:var(--gold); }
      .cd-monthrow { display:flex; align-items:center; justify-content:space-between; margin-bottom:0.55rem; }
      .cd-arrow { position:static; width:2.2rem; height:2.2rem; font-size:1.25rem; }
      .cd-arrow-spacer { width:2.2rem; }
      .cd-wrap .dr-hint { margin-top:1.4rem; width:100%; font-size:0.85rem; }
      /* ── PROPERTY-MODE CELLS (Elec 2026-08-27: no-dates click on the
         three-pane → these two months become the property's own calendar,
         "daily rates included per day". His style ruling, same session,
         verbatim: "i like the style of the base calendar more, i just like
         the date and price from the individual calendar" — so the cells KEEP
         the base dr-cell dress (grounds, hover, ring selection, the plain
         dimmed :disabled for dead days — no slate cloud) and gain only the
         gold rate line under the date. Dead days carry no rate by markup. */
      .cd-wrap .dr-cell.cdp-cell { display:flex; flex-direction:column; align-items:center; justify-content:center; line-height:1.1; gap:1px; }
      .cd-wrap .cdp-px { font-size:0.58em; color:var(--gold); font-weight:400; line-height:1; white-space:nowrap; }
    /* (a lone orphan close-brace sat here - removed 2026-08-21. The indentation
       below records an intended wrapper that never existed; the rules were
       always top-level and Chrome recovered silently. Same defect class as the
       engine-responsive orphans of 08-20: assert before writing.) */

    /* ══ MATERIAL, NOT PAINT ══════════════════════════════════════════════════
       Elec 2026-08-16, three notes in a row: "doesnt read navy to me… maybe add a
       little darker in", "keep the texturing effects that were present earlier just
       with this colors", "i dont care for solid blocks of color" — all in regard to
       background and fill colours.
       ⚑ WHY THE TEXTURE HAD VANISHED, and it was never deleted: shared.css puts
       `--mottle` (the stone-noise turbulence) on BODY only, and its own comment says
       the v4 palette works because "panels carry ALPHA so the navy base blends
       through". The engine's columns paint at 0.97 — effectively opaque — so they
       covered the very texture the palette was designed around. Every large surface
       therefore looked like a flat chip of colour.
       THE FIX IS THE PALETTE'S OWN INTENT, not a new effect: put the stone back on
       the surfaces themselves, and add a shallow vertical gradient so a tall column
       is never one uniform value top to bottom.
       This block sits LAST on purpose — several of these surfaces set `background`
       as a shorthand earlier in this file, which would wipe a background-image
       declared before it. Cascade order is doing real work here; do not move it up. */
    body { background-color:var(--forest); background-image:var(--mottle); }

    /* nav was the one surface the restoration missed - Elec caught it on the
       tablet review 2026-08-21: "the mottling.. seems to be nonexistent in the
       top header section." Same treatment as every other 0.97-alpha surface. */
    #nav, .browse-grid, .browse-detail, .browse-map-panel, .filter-bar, .engine-footer {
      background-image:var(--mottle); background-repeat:repeat; }

    /* The columns: a barely-there top-to-bottom fall, ~4% either side of the base.
       Enough that the eye reads depth; not enough to notice as a gradient. */
    .browse-grid, .browse-detail {
      background-image:linear-gradient(180deg, rgba(10,34,71,0.55) 0%, rgba(4,20,46,0.55) 100%), var(--mottle); }

    /* ── LIST → CENTRE SEAM (Elec 2026-08-17: "now do the same fade between list and
       center column"). Same construction as the map seam, mirrored.
       ⚑ But the two seams are NOT the same problem, and the difference decides the fix:
       the map is a live canvas painting its own colours, so there the overlay had to
       impersonate the CENTRE column. Here both sides already share one background stack,
       so there is no colour step to hide — what makes the join read hard is the LIST's
       content: card edges stopping dead on a straight vertical. So this softens the
       CARDS as they approach the centre, not the panel behind them.
       The list is the scrolling column, so the mask is applied to it and the cards fade
       out toward the gutter as they pass under it. `pointer-events` is untouched — a mask
       does not intercept clicks, so cards near the edge stay fully clickable. */
    .browse-grid {
      -webkit-mask-image:linear-gradient(90deg, #000 0%, #000 72%, rgba(0,0,0,0.72) 88%, rgba(0,0,0,0.35) 100%);
      mask-image:linear-gradient(90deg, #000 0%, #000 72%, rgba(0,0,0,0.72) 88%, rgba(0,0,0,0.35) 100%); }

    /* The booking pane was a solid #182E51 slab — the largest flat area on the page
       and the one directly behind the money. Same treatment, kept a touch lighter
       than the column so it still reads as lifted. */
    .browse-detail .bd-deck .bd-pane.active {
      background-image:linear-gradient(170deg, rgba(26,48,84,0.92) 0%, rgba(12,30,60,0.92) 100%), var(--mottle);
      background-blend-mode:normal; }

    /* Property cards: same idea at small scale, so a scrolling list is not a stack
       of identical rectangles. */
    .prop-card { background-image:var(--mottle); }

    /* ══ ONE HEADER GRAMMAR ═══════════════════════════════════════════════════
       Elec 2026-08-16: "get all the buttons and chips and toggles boxes more uniform.
       the stay date and guests boxes are nice color and style, good for the rest of
       the header boxes, just do not copy the gold pulse."
       The reference boxes, measured off the live page rather than read off a rule:
         ground  var(--forest) SOLID      border  1px FULL gold (not the 35% gold-line)
         radius  10px                     text    parchment @ 0.82, 12.48px/600, 0.09em
         height  35px (8.8px vertical padding)
       The chips were the odd ones out on three counts at once — transparent ground,
       35%-gold border, sage text — which is why the header read as two families of
       control sitting next to each other.
       ⚠ THE PULSE IS DELIBERATELY NOT COPIED. `dateBeatSoft`/`dateBeatStrong` stay on
       the date and guest fields alone: they carry the funnel (bright until dates are
       chosen, then guests stays bright until a count is set). Putting that beat on ten
       more boxes would destroy the signal it exists to send. Style only, no animation. */
    .filter-bar .filter-btn {
      background-color:var(--forest);
      border-color:var(--gold);
      color:rgba(245,240,232,0.82);
      padding-top:8.8px; padding-bottom:8.8px; }

    /* The ON state keeps the gold wash so "selected" still reads at a glance — same
       box, one clear difference, which is what uniform is supposed to buy. */
    .filter-bar .filter-btn.active {
      background-color:rgba(201,169,110,0.14);
      color:var(--parchment); }

    /* ══ THE ACTIVE EMBER ═════════════════════════════════════════════════════
       Elec 2026-08-16: "any selected button or toggle in header whatever is active
       should have an internal golden glow pulse, subtle.. almost a sparkle.. lets you
       know whats active."
       An INSET shadow, so the light lives inside the box rather than haloing it — a
       coal under the glass, not a lamp behind it. It breathes between a barely-there
       ember and a soft bloom, and never touches the border or the layout.
       ★ 2.6s, because that is THE tempo. Every pulse on this page already runs at
       2.6s — the header dates, the guests box, the pin/card pair, Book & Pay —
       under the rule that intensity varies by state but frequency never does. A
       sparkle on its own clock would break the one thing holding the motion together.
       ⚠ Distinct from `dateBeatSoft`/`dateBeatStrong` by design: those are a FUNNEL
       beat on the boxes that still need an answer. This is a STATE mark on the ones
       already answered — which is why it glows inward instead of outward. */
    
    .filter-bar .filter-btn.active,
    .filter-bar .filter-btn.locked {
      animation:chipEmber 2.6s ease-in-out infinite; }

    @media (prefers-reduced-motion:reduce) {
      .filter-bar .filter-btn.active,
      .filter-bar .filter-btn.locked {
        animation:none; box-shadow:inset 0 0 10px rgba(201,169,110,0.24); } }

    .filter-bar .filter-btn:hover:not(.active) {
      background-color:rgba(201,169,110,0.08);
      color:var(--parchment); }

    /* ══ GUEST SUPPORT JOINS THE SAME GRAMMAR ═════════════════════════════════
       Elec 2026-08-16: "Guest support needs the same all cap font and style as other
       header buttons, same colors and hover style with sparkle while pop open is up.
       can have some additional letter spacing and horizontal stretch to fill a little
       more space."
       ⚑ This SUPERSEDES the earlier ruling that left it wearing the ACTIVE-chip look
       (gold wash) — that was his call at the time ("took too much away" when I first
       toned it down), and this instruction is newer and explicit. Recorded rather than
       silently flipped, so the older note is not "restored" later by someone reading
       only the ledger.
       It now rests as a normal header box — solid navy, full gold border, parchment at
       82% — with MORE tracking (0.16em vs the chips' 0.09em) and wider padding, which is
       the "stretch to fill a little more space" without making it a different shape.
       ⚠ `color` needs !important: shared.css declares `.nav-cta{color:var(--parchment)
       !important}`, so an ordinary declaration here loses regardless of specificity. */
    /* Elec 2026-08-19: the header Map button "should match guest support.
       back ground and hover" - one rule styles both, so they cannot drift. */
    #gsBtn.nav-cta, #mapToggle.nav-cta {
      background-color:var(--forest);
      border:1px solid var(--gold);
      border-radius:var(--radius-sm);
      color:rgba(245,240,232,0.82) !important;
      font-family:var(--body); font-size:0.78rem; font-weight:600;
      text-transform:uppercase; letter-spacing:0.16em;
      padding:8.8px 2.1rem; }
    #gsBtn.nav-cta:hover, #mapToggle.nav-cta:hover {
      background-color:rgba(201,169,110,0.08);
      color:var(--parchment) !important; }

    /* The sparkle, but ONLY while the pop-out is up — same inset ember and the same
       2.6s tempo as a selected chip, because "open" is exactly the active state the
       ember was invented to mark. The existing body.gs-open rule already joins the
       button to the pop-out visually; this adds the pulse on top of it. */
    body.gs-open #gsBtn.nav-cta { animation:chipEmber 2.6s ease-in-out infinite; }
    @media (prefers-reduced-motion:reduce) {
      body.gs-open #gsBtn.nav-cta {
        animation:none; box-shadow:inset 0 0 10px rgba(201,169,110,0.24); } }

    /* The secondary mark, stamped on the map (Elec: "like the key"). The map panel is
       position:sticky, which makes it the containing block, so the mark can be pinned
       to its top-left — the only corner Google leaves free.
       Treatment copies .nav-mark exactly (8px radius + the same gold hairline ring), so
       the header mark and this one read as the same object rather than two logos. */
    /* ⚠ The panel must be positioned or the mark escapes to the page corner and hides
       behind the header — which is exactly what happened first time. browse.css sets
       `position:sticky` here, but the ≥1280 locked layout overrides it back to static,
       so the computed value is what matters, not the stylesheet it came from. */
    /* ══ MAP / CENTRE SEAM ════════════════════════════════════════════════════
       Elec 2026-08-16: "remove gold vertical bar between map and central, but want
       some fade and blend between the 2 areas."
       The hard rule goes. In its place the map's own left edge dissolves into the
       centre column: a 72px gradient from the page ground to fully transparent, so
       the two areas meet without a seam to point at. This only works BECAUSE the
       palette moved to navy earlier — against the old charcoal the map would have
       faded into a different colour and read as a smudge rather than a blend.
       `pointer-events:none` matters: without it the strip would eat map drags along
       the whole left edge. Sits under the SH mark (z 4 vs 5) so the mark stays clean. */
    .browse-map-panel { position:relative; border-left:none; }
    /* ⚑ REBUILT 2026-08-17 (Elec: "pretty hard line right now"). The first version faded
       from `var(--forest)` — but the centre column is NOT --forest at that edge: it carries
       its own vertical gradient and sits LIGHTER than the flat base. So the overlay stepped
       DARKER at the boundary and only then ramped up, painting a dark band down the map's
       left edge — two visible edges where there had been one. Measured first: neither panel
       has any border, so the line was always a colour step, never a rule.
       The fix is to give the overlay the SAME background stack as `.browse-detail`, so at
       the seam it is exactly the centre column's colour at every height, and then fade only
       its ALPHA across with a mask. No step to see, because both sides start identical. */
    .browse-map-panel::before {
      content:""; position:absolute; top:0; left:0; bottom:0; width:132px; z-index:4;
      pointer-events:none;
      background-color:var(--forest);
      background-image:linear-gradient(180deg, rgba(10,34,71,0.55) 0%, rgba(4,20,46,0.55) 100%), var(--mottle);
      /* ★ THE BLEND MUST CLEAR GOOGLE'S ATTRIBUTION (Elec: "looks strange half covered in
         blend"). It is also not optional: the Google logo and the Map Data / Terms strip
         are required by the Maps Platform terms and may not be hidden or obscured, so a
         gradient sitting over them is a compliance problem as much as an ugly one — and
         the logo cannot simply be moved, its position is Google's to decide.
         So the overlay is masked on BOTH axes and the two are intersected: it fades out
         horizontally as before, AND fades away over the bottom ~86px, leaving the whole
         attribution row untouched. `mask-composite: intersect` is the standard keyword;
         `-webkit-mask-composite: source-in` is the legacy WebKit spelling of the same
         thing, and both are set because Chrome still honours the old one. */
      -webkit-mask-image:
        linear-gradient(90deg, #000 0%, rgba(0,0,0,0.86) 22%, rgba(0,0,0,0.52) 48%, rgba(0,0,0,0.20) 74%, transparent 100%),
        linear-gradient(180deg, #000 0%, #000 calc(100% - 86px), transparent calc(100% - 26px));
      -webkit-mask-composite:source-in;
      mask-image:
        linear-gradient(90deg, #000 0%, rgba(0,0,0,0.86) 22%, rgba(0,0,0,0.52) 48%, rgba(0,0,0,0.20) 74%, transparent 100%),
        linear-gradient(180deg, #000 0%, #000 calc(100% - 86px), transparent calc(100% - 26px));
      mask-composite:intersect; }
    /* Elec 2026-08-16: moved top-LEFT → top-RIGHT. Also gets it out of the 72px blend
       strip on the left edge, where it was sitting in the darkest part of the fade. */
    .map-brand { position:absolute; top:12px; right:12px; z-index:5;
      width:34px; height:34px; border-radius:8px;
      box-shadow:0 0 0 1px rgba(201,169,110,0.35), 0 2px 12px rgba(4,20,46,0.55);
      opacity:0.78; pointer-events:none; }

    /* ══ THE DATE LABEL ROW: CLOSER TO ITS BOX, AND DRAWN INWARD ═══════════════
       Elec 2026-08-17: "shift the label text 'stay dates' down reducing the padding
       between dates text and box, same with 'x All dates'. both labels should move in
       towards each other an equal amount as they moved down toward box."
       Measured first, so the two movements are genuinely equal rather than eyeballed:
         label row  y 66-85      date box top  y 94   =>  a 9px gap
         "Stay dates"   x  24 -> flush with the box's LEFT edge (24)
         "x All dates"  x 178-239 -> flush with the box's RIGHT edge (239)
       Both move 4px DOWN (gap 9 -> 5) and 4px INWARD - the same 4px, which is the
       symmetry he asked for: the pair closes on each other by exactly what it drops.
       ⚑ RELATIVE offsets, not margins or padding. The label row's height feeds the
       header's height, and the header's height is what positions the columns beneath
       it - a margin here would drag the whole engine down by 4px. A relative shift
       paints the labels in their new place and reflows nothing. Same reason the
       wordmark and the Instagram mark are offset rather than re-flowed.
       `right:4px` on a relatively-positioned element moves it LEFT, which is the
       inward direction for the right-hand label. */
    /* 2026-08-23, the hug law reaches desktop (Elec: "stay dates and xAll
       dates should be closer to date box, minimal padding between like top
       boarder of box is an underline for the labels") — same 1.3px endpoint
       the tablet header landed on. Measured before changing: gap was 15.9px
       with the 4px offsets above active, so both drop a further 14.6px.
       Same RELATIVE mechanism as the original rule — paints lower, reflows
       nothing, the no-push law holds. */
    /* ⛑ 2026-08-23 LEAK FOUND AND FIXED (Elec: "what ever width im at
       currently broke it into peices"): this rule has NO width scope — it
       predates the bands — and the whole night's desktop hug tuning
       (18.6 -> 9 -> 15 -> 7px) rode through it into the PANEL band and the
       LOCKED tablet header. The un-scoped base returns to the ORIGINAL
       2026-08-17 approved 4px (panel + tablet restored to their reviewed
       state); tonight's desktop value lives in the >=1280 override below. */
    .filter-bar.has-dates .fb-datelabel { position:relative; top:4px; left:4px; }
    .filter-bar.has-dates .date-clear   { position:relative; top:4px; right:4px; }
    @media (min-width:1280px) {
      /* the top-anchored desktop header's hug, measured to land 1.3px */
      .filter-bar.has-dates .fb-datelabel { top:7px; }
      .filter-bar.has-dates .date-clear   { top:7px; }
      /* IDLE count block centered in its zone like the approved dated one:
         measured 33px above / 15px below (GS bottom -> border, 2-line
         block); -17.5 evens it (~24/24). The dated state has its own
         centering via the fixed-height box in the file foot. */
      body:not(.dates-set) .filter-bar .filter-count { margin-top:-6px; }
      /* -17.5 overshot (measured 2.9/25.9); -6 lands ~14/14. */
    }
    @media (min-width:1025px) and (max-width:1279.98px) {
      /* 2026-08-23 width sweep: the PANEL band read hug 20.1 / amenities 5.6
         against the 1.3 signature every other band carries. Measured at
         1276/1152/1028 — uniform across the band, so one offset each:
         4 + 18.8 and +4.3. Same relative-paint mechanism, no reflow. */
      /* ⛑ RESET 2026-08-23 after four coupled-offset rounds (the stacking
         trap, caught): the chips lift, the amenities-label hide and their
         retunes are ALL retired — each fix re-sized the collapsed rows and
         moved every other anchor (the hide also killed STAY DATES, which
         shares .filter-label). This block returns to the VERIFIED v1 state:
         natural rows, hug offsets that measured 1.3/1.3 at 1247, plus only
         the decoupled wins (count, padding, body anchor below). The one
         remaining uniformity delta — chips bottom ~15px past the boxes'
         line — needs a grid restructure, not offsets: Elec's call. */
      /* ⛑ THE MID GAP, KILLED AT THE ROOT 2026-08-23 (Elec: "drop that mid gap
         between nav and header, it seems to be giving repeated issue" — and it
         WAS the night's repeat offender). Measured anatomy: AMENITIES painted
         68-87, only 6px under the nav, but it forced the chips to start at 89,
         which forced the box to 120 (his lower-chip-line alignment), which
         forced STAY DATES to 100 — leaving a 38px void on the left column.
         Nothing above the chips could rise while that label sat there.
         ⇒ The AMENITIES label is retired AT THIS BAND ONLY, which is also what
         the LOWER LOCK (tablet) does — his uniformity ruling. Scoped to
         .fb-labelrow so STAY DATES (which shares .filter-label) is untouched:
         the earlier blanket hide killed both, recorded so it is not repeated.
         Row 1 then stops charging height and the whole controls block rises
         under the nav. */
      .filter-bar .fb-labelrow .filter-label { display:none; }
      .filter-bar.has-dates .fb-datelabelrow,
      .filter-bar.has-dates .fb-labelrow { margin-bottom:-19.4px; }
      /* hug retuned to the risen box (was 35.8 against the low box) */
      .filter-bar.has-dates .fb-datelabel { top:16.4px; }
      .filter-bar.has-dates .date-clear   { top:16.4px; }
      .filter-bar .filter-label { position:relative; top:4.3px; }
      /* 2026-08-23 second pass (Elec at this width: "several things header
         and body.. things you have already fixed at other widths") — the
         desktop grammar items that never crossed 1280, applied band-scoped.
         The chips-into-nav move is deliberately NOT transplanted: MAP +
         Guest Support own this band's nav right, there is no room.
         (a) count block: tight leading, no gap before the price line, and a
             negative top margin so it hugs up under the chips row instead of
             floating in its own slack — the row above it stops charging
             ~14px of dead band. */
      /* -14 (desktop's number) collided the count into the GARAGE chip by
         8.4px here — panel's own slack is smaller. -2 leaves ~4px clear. */
      .filter-bar.has-dates .filter-count { line-height:1.15; margin-top:-2px; }
      .filter-bar.has-dates .filter-count .fc-low { margin-top:0; }
      /* (b) the same bottom breath as desktop (was still the old 13.6px+). */
      .filter-bar.has-dates, .filter-bar:not(.has-dates) { padding-bottom:10px; }
      /* (c) BODY: the idle centre pane floated "When's your stay?" mid-void
         (title measured 109px below the bar at 1276) — top-anchor the wrap
         so the prompt rises to the content, dead space falls below. */
      /* column flex: the vertical centering is justify-content, not
         align-items (first attempt moved the wrong axis, measured). */
      .cd-wrap { justify-content:flex-start; padding-top:2.2rem; }
      /* COUNT BLOCK IN THE NAV at this band (Elec 2026-08-23: "it should go
         above [the chips], to the left of map button") — browse.js relocates
         the node; these style it for nav life. fc-low's base absolute
         (top:100%) would hang it below the nav bar: static, two-line right
         block beside the MAP button. */
      #nav .filter-count { text-align:right; margin-right:0.9rem;
        align-self:center; line-height:1.35; position:relative; }
      #nav .filter-count .fc-low { position:static; display:block; margin-top:0.1rem; }
      /* Elec 2026-08-23: "the dates box line, should be in alignment with the
         lower amenities chip line." Grid alignment, not offsets: the fields
         cell bottoms out on the controls row, whose floor IS the lower chip
         row. Label hug offsets below re-measured to the moved box. */
      .filter-bar.has-dates .fb-datecell { align-self:end; }
    }
  

    /* ── THE SHELF ENDS AT THE TABS (Elec 2026-08-17) ──────────────────────
       "its the last section off each end if its one bar. the removed part would end
        at the end each side."
       The gold bar is .modal-header's border-bottom and it spanned the whole modal,
       so beyond each OUTER flare it ran on to the corner as a stub. Against the tab
       that is behind and half covered, that stub is the line that looks like it
       should have stopped at the curve.
       ⚠ THE BORDER IS KEPT AND MADE TRANSPARENT, never removed: its width is one of
       three coupled values (tab margin-bottom, tab padding-bottom, .mt-outline
       stroke-width — see engine-base.css). Dropping it would unseat every tab. Only
       the paint moves to ::after, so layout is identical by construction.
       --shelf-l / --shelf-r are written by paintTabShapes() from the tab SVGs' own
       flare geometry on every paint, so this tracks tab width, zoom and font changes.
       Fallback 0px = the old full-width bar, i.e. it degrades to the previous look
       if the script has not run yet. */
    .browse-detail .modal-header { border-bottom-color:transparent; }
    .browse-detail .modal-header::after {
      content:""; position:absolute; pointer-events:none;
      left:var(--shelf-l, 0px); right:var(--shelf-r, 0px);
      /* ⛑ top:100%, NOT bottom:-Npx. The border this replaces occupies the strip
         immediately BELOW the padding box (measured 217.76 -> 218.61). Offsetting
         from `bottom` put the replacement at 218.63 -> 219.62 - a shade under 1px
         too low, so it no longer coincided with the tab's own foot line (.mt-base,
         y 217.90) and the two rendered as TWO adjacent bars: doubled under the tab,
         single past it. `top:100%` starts exactly at the padding-box edge, which is
         where a border-bottom starts, so the two lines land on each other again. */
      top:100%; height:var(--shelf-w, 1px);
      background:#C9A96E; }

    /* ⛑ REVERTED 2026-08-17: a rule here used to trim .bd-modal's TOP BORDER to the
       tab flares. Elec: "you removed the top of the modal but the stray line is still
       there" - it was never in his red boxes, it sits ~15px ABOVE the tabs, and cutting
       its corners changed the modal's frame for nothing. The stray line he is pointing at
       is at the TAB FOOT level, outboard of each end flare, and is still unidentified.
       Do not re-trim the modal border while hunting it. */


/* == DATED COUNT BLOCK FILLS THE VOID, UPWARD ONLY (Elec 2026-08-23) ==========
   "theres so much space above the text lines and below guest support. it would
   be better to cause another line break and fill up into the void, but not
   pushing other itesm at the same time" + "the homes availible line jumps
   under the chips once it gets tight."
   browse.js breaks the desktop dated line after the count (3 rows total).
   MEASURED before this rule: the third line grew the block 19.4px up but still
   pushed everything below by 3.8px. The fix is zero-push BY CONSTRUCTION: the
   box is frozen at its settled two-line height (55px, constant 1280-1645,
   measured both ends) and content bottom-anchors inside it - extra lines can
   only spill out the TOP, into the genuinely empty zone under Guest Support.
   Same law as the tablet dated count (absolute, grows up); different mechanism
   because the freeze-band recentring makes a fixed right-offset unreliable.
   The narrower broken line also stops forcing the track wide - the
   jump-under-chips at tight desktop was the nowrap line's width. */
@media (min-width:1280px) {
  body.dates-set .filter-bar.has-dates .filter-count {
    display:flex; flex-direction:column; justify-content:flex-start;
    align-items:flex-end; height:55px; overflow:visible;
    /* Elec 2026-08-23 "shring spacing on the text lines" + the third line was
       crossing the bar's bottom border (measured 15px overhang after the
       chips lift): tighter leading, no gap before the price line, and the
       block rides up under Guest Support. */
    /* -14 -> -5 (Elec, zoomed screenshot: "text lines should move down to
       center vertically between button and line"): zone is GS bottom 54 to
       bar border 138 = 84px, text block 52px -> 16px above and below. */
    /* 1.15 -> 1.35 (Elec zoom, same night: "seems tight and bumched for how
       much space is availble around it") — the tight leading was for the
       cramped zone; with air around, the block breathes. Margin re-tuned to
       keep the equal-gaps centering with the taller block. */
    line-height:1.35; margin-top:-10.5px; /* measured 11.4/8.3 -> ~9.9/9.9 */
  }
  body.dates-set .filter-bar.has-dates .filter-count .fc-low { margin-top:3px; }
  /* flex-end -> flex-start with the top-anchored header: the block hangs from
     the top under Guest Support and extra lines spill DOWN into the freed
     space; the fixed height still guarantees zero push. */
}

/* == HEADER COMPACTION, DESKTOP (Elec 2026-08-23: "theres still a large amount
   of vertical dead space in the header between the the two layers. the spacing
   and padding shoudl be minimized to bring everything up some" + "amenities
   label should be closer to all box, like stay dates").
   Measured knobs at 1360 before changing: bar padding-bottom 13.6, row-gap 5.6,
   AMENITIES label -> ALL chip gap 10.4. The baseline law holds (boxes and chips
   stay bottom-flush - they share the grid rows); the whole bar just gets
   shorter, so everything below rises. Label hug offsets are re-tuned to the
   new box positions by measurement, 1.3px endpoint, relative paint only. */
/* FIRST ATTEMPT LOST THE CASCADE and is replaced here, recorded not deleted:
   `.filter-bar { padding-bottom:4px; row-gap:3px; }` computed to no change -
   the winning declarations carry `.filter-bar.has-dates` (0,2,0), which a
   single class can never beat. Selectors below match that weight; this file
   loads after every earlier bar rule, so same-weight wins by order.
   The `.filter-label top:9.1px` amenities hug is also RETIRED: with row 2
   rising 9.6px the chips meet the label's natural position (predicted gap
   ~1.4px) - an offset kept on top of that would overlap. Verified after. */
@media (min-width:1280px) {
  /* padding-bottom 4 -> 10 (Elec: "you made it way too tight on the
     underside") - breathing room back under the chips/boxes line. */
  .filter-bar.has-dates, .filter-bar:not(.has-dates) { padding-bottom:10px; row-gap:2px; }
  /* Row 1 trims 6px via the label rows' own contribution (the tablet
     negative-margin mechanism) - labels paint where they are, the row
     charges less, everything beneath rises. */
  .filter-bar.has-dates .fb-datelabelrow, .filter-bar .fb-labelrow { margin-bottom:-6px; }
  /* Post-compaction measurements: amenities gap read 6.8, date hug 7.3 — the
     predicted meet-in-the-middle was wrong by ~5.5 (rows rose less than the
     padding shrank). Tuned to the measured numbers; both land 1.3px. */
  .filter-bar .filter-label { position:relative; top:5.5px; }
}
/* ── THE SHEET'S GROUND (Elec 2026-08-28: "the booking page is ugly here the
   background is wrong, solid block of color. makes me cringe").
   It was `#232B36` — a flat grey-slate carried over from the pre-v4 palette,
   the only surface on the page still wearing it. Everything around it moved on:
   the page ground is `var(--forest)` + the mottle texture, and the property
   calendar he approved earlier tonight is
   `linear-gradient(165deg, #0A2247 0%, var(--forest) 55%)` over a gold hairline.
   The slab read as a hole punched in the page.
   ⚑ NOT A NEW LOOK - the same grammar, fitted to a TALL surface. On the little
   calendar overlay a 55% stop is right; this sheet's content runs ~3000px, so a
   percentage stop would finish in the first inch and flatten out again. The wash
   is therefore given a PIXEL length: it lifts the top of the sheet where the
   title and photo sit and settles into the page ground below, and because the
   scroll happens in .modal-body INSIDE this element, the ground stays put while
   the content travels over it - depth without parallax. Mottle carries the same
   grain as the page so the two read as one material. */
.bd-modal{
  background-color: var(--forest);
  background-image:
    linear-gradient(168deg, rgba(10,34,71,0.92) 0px, rgba(10,34,71,0.34) 340px, rgba(10,34,71,0) 620px),
    var(--mottle);
  background-repeat: no-repeat, repeat;
  box-shadow: 0 1px 0 rgba(201,169,110,0.16) inset, 0 18px 55px rgba(0,0,0,0.55);
}

/* THE THREE CHECKMARK LINES, CENTRED (Elec 2026-08-28: "also booking page the
   3 checkmarked lines of text should be centered"). They were left-aligned
   paragraphs under a centred receipt, so the block hung off the sheet's axis.
   The check stays attached to the head of its own line rather than forming a
   left rail - with centred text a hanging rail would sit at a different x on
   every line, which is worse than none. Text-wrap:balance keeps the wrapped
   lines from ending in a lone short word now that they are centred; the
   punctuation-first law still governs where the break lands. */
.bk-trust-full { text-align: center; }
.bk-trust-full .bk-t-line { text-wrap: balance; }

/* ── THE BOOKING SHEET'S GROUND, AT THE LAYER THAT ACTUALLY PAINTS IT
   (Elec 2026-08-28: "the booking page is ugly here the background is wrong,
   solid block of color. makes me cringe" -> "still flat slab to me and i
   reloaded" -> "no date booking page").
   ⛑ TWO WRONG LAYERS BEFORE THIS ONE, and that is the lesson worth keeping.
   First I dressed `.bd-modal`; probing his own screen showed the topmost
   painted ground under the text is the PANE (`.tab-pane.bd-pane`, opaque
   rgb(24,46,81)), which covers the modal completely - so the work was real but
   invisible. Then I amended the pane rule in engine-layout, which sits inside
   `@media(min-width:1280px)` and therefore never applied at the tablet band he
   was looking at. Probe the element that paints, then confirm the rule that
   wins AT THE VIEWPORT IN QUESTION - a rule can be the right rule and the
   wrong band.
   ID-anchored so it cannot be outranked by the 1280 rule's (0,4,0) selector,
   and the opaque base is preserved deliberately: the pane must stay opaque or
   the pane behind shows through the text (the reason #182E51 was chosen in the
   first place - it is --pine composited over the page ground, same tone, no
   transparency). The depth is layered ON the base: a lift at the head where
   the title and CTA sit, a settle along the bottom edge, and the page's own
   mottle grain so the sheet reads as the same material as everything else.
   Verified by applying it to the live element first, then wiring it here. */
#detailPanel .bd-modal .bd-pane.active,
#detailPanel .bd-modal .bd-pane-book {
  background-color:#182E51;
  background-image:
    linear-gradient(168deg, rgba(32,70,124,0.55) 0px, rgba(24,46,81,0) 340px),
    linear-gradient(0deg, rgba(5,17,38,0.55) 0px, rgba(5,17,38,0) 280px),
    var(--mottle);
  background-repeat:no-repeat, no-repeat, repeat;
}
