/*
 * Post-port fixes. Loaded AFTER the captured Bricks CSS and after salt-forms.css, so it
 * wins the cascade without !important.
 *
 * Every rule here fixes a defect found by driving the built site across eight viewports on
 * 13/08/26. Each carries the measurement that justifies it. Nothing here is a preference.
 *
 * These are deliberately in their own file rather than edited into the captured WordPress
 * CSS, because that CSS is regenerated by the port scripts and any edit to it is lost on the
 * next run.
 */

/* ---------------------------------------------------------------------------
 * 1. MAJOR. The estate masterplan strip was visibly squashed on phone and tablet.
 *
 * The image is 3508x1521 (ratio 2.306) and the rule was object-fit: fill, which stretches
 * non-uniformly to whatever box it lands in instead of cropping. Measured distortion:
 * -15.4% at 320px, -13.3% at 390px, -12.6% at 414px, -9.2% at 768px. It self-corrects
 * above 1024px, which is exactly why it survived a desktop-only review.
 *
 * cover preserves the aspect ratio and crops the overflow. An estate map crops acceptably;
 * a stretched one reads as a broken image.
 * ------------------------------------------------------------------------- */
img[src*="/assets/lot-masterplans/"],
img[src*="/assets/estate/"] {
  object-fit: cover;
  object-position: center;
}

/* The estate map is the same defect at a different path. The original rule matched only
   /assets/lot-masterplans/, so when the Stage 3 estate map landed at /assets/estate/ it
   arrived stretched: box ratio 1.94 against a natural 2.31 at 390px. A path-scoped selector
   silently stops covering the case the moment someone adds a folder. Both paths are listed
   above rather than broadening to every img, because cover on an arbitrary image would crop
   things that should letterbox. */

/* ---------------------------------------------------------------------------
 * 2. MAJOR. The header wordmark was squashed through a whole breakpoint band.
 *
 * Natural 300x130 (ratio 2.308). In the ~900px to 1099px band the logo's flex wrapper
 * narrows to as little as 88px while the image height stays pinned at the desktop 62px,
 * giving 110x62 (ratio 1.774, -23.3%) at 1024px. Clean at <=768px and >=1100px, so it is a
 * gap between two breakpoints rather than a global bug: precisely the kind of thing testing
 * one phone width and one desktop width cannot see.
 *
 * contain keeps the ratio inside whatever box the flex layout gives it.
 * ------------------------------------------------------------------------- */
img.bricks-site-logo {
  object-fit: contain;
  object-position: left center;
  max-width: 100%;
}

/* ---------------------------------------------------------------------------
 * 3 and 4. MAJOR. Tap targets below the 44px minimum on touch.
 *
 * Scoped to coarse pointers and phone widths so desktop rendering is untouched. The
 * measurements were taken at 320, 390 and 414.
 * ------------------------------------------------------------------------- */
@media (max-width: 768px), (pointer: coarse) {

  /* The mobile nav toggle measured 34x16 with zero padding. It is the ONLY way to open
     navigation on a phone, so 16px of height is the worst target on the site. */
  button.bricks-mobile-menu-toggle {
    min-width: 44px;
    min-height: 44px;
    padding: 14px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* Primary CTAs measured 36 to 37px tall: "REQUEST OFFER FORM" (the primary conversion
     action on every lot page), the BEP download, "find More land selling now", plus the
     header and footer Register and Brochure buttons. Widths were already fine at 98 to
     346px; only height fell short. Vertical padding was 10.465px. */
  .brxe-ripplebutton.btn,
  a.brxe-ripplebutton,
  .salt-form button {
    min-height: 44px;
    padding-top: 13px;
    padding-bottom: 13px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* MINOR. Footer contact links measured 20 to 21px: address, suburb, phone, email.
     Inline text links rather than buttons, so they get vertical breathing room instead of
     a box, which keeps the footer looking like a footer. */

  /* MINOR. Header social icons measured 32x27. Secondary nav, but still finger targets. */
  .backdrop a:has(> i.brxe-icon),
  a:has(> i.ti-instagram),
  a:has(> i.ti-facebook) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
  }
}

/* ---------------------------------------------------------------------------
 * 5. The three "VIP access" register buttons on /now-selling/ carry a captured
 * display:none from the WordPress export (ID-keyed in pagemeta, so it predates the port).
 * They are now wired to a working form, so hiding them throws away three CTAs on the page
 * where a buyer is furthest down the funnel.
 * ------------------------------------------------------------------------- */
#brxe-tjafua,
#brxe-zzkffr,
#brxe-osscrc {
  display: inline-flex !important; /* beats the captured inline-ID rule, which is itself an override */
}

/* ---------------------------------------------------------------------------
 * 6. MAJOR. Button labels clipped mid-word on phones.
 *
 * Measured at 390px on a lot page: the INNER span overflows its own box under
 * overflow:hidden; white-space:nowrap, so the label is silently truncated:
 *   "Block 96 BUILDING ENVELOPE PLAN"  needs 290px, had 269
 *   "Register your interest"            needs 207px, had 171  -> "REGISTER YOUR INTEF"
 *   "Brochure"                          needs  86px, had  69  -> "BROCHUI"
 *
 * Both automated clip checks missed this because they measured the OUTER element, which
 * fits fine. The clipping happens one level in. It was visible in their own screenshots.
 *
 * Fix: on phones and tablets, let the label wrap and give it back the horizontal room the
 * generous desktop padding was eating. The button is already min-height 44px and centred, so
 * a two-line label sits correctly rather than overflowing.
 *
 * ⚠ Breakpoint corrected from 640px to 768px. The first version of this rule stopped at 640
 * while the tap-target rule above used 768, so the 641 to 768 band got the taller button and
 * NOT the wrapping, and the header Register and Brochure labels stayed clipped on every route
 * at iPad-portrait width. The full-matrix run caught it: 79 of 80 cells clean, and the one
 * failing column was 768 on all ten routes. Two rules fixing one symptom must share a
 * breakpoint, or the gap between them becomes its own defect.
 * ------------------------------------------------------------------------- */
/* ⚠ REVISED 13/08/26. The version above traded one defect for another.
 *
 * Letting the label wrap at EVERY width removed the clipping, but a label wraps whenever its
 * box is narrow — not only when the viewport is. The header CTA is boxed at 179px on desktop,
 * so "Register your interest" came apart over THREE lines at 75px tall next to a 44px
 * "Brochure", on every route from 1024 to 1920. Keith caught it on the deployed build:
 * "buttons look odd, dont align with design or existing website". Measured 179x75, 3 lines.
 *
 * Wrapping was the wrong lever. The real defect was never "the label cannot wrap", it was
 * "the BOX is narrower than its own label" — and the fix for that is to size the box to its
 * content, not to break the content to fit the box.
 *
 *   min-width: max-content  the button is never narrower than its own label, so on desktop
 *                           the label sits on one line exactly as designed and cannot clip
 *   overflow: visible       the truncation mechanism itself stays gone
 *
 * Below 769px the room genuinely is not there, so wrapping is allowed — that band is where
 * the original clipping was found, and a two-line label on a phone is correct rather than a
 * compromise. Both sides of the 768/769 boundary are covered by different means, which is
 * what the earlier breakpoint chase kept getting wrong: it moved one threshold and left the
 * other side bare.
 *
 * Verified across 320/390/414/768/1024/1280/1440/1920 on the homepage, the listing page and a
 * lot page: no label clipped at any width, none on more than one line at or above 1024, and
 * document scrollWidth never exceeds the viewport (max-content can widen a button, so header
 * overflow was the risk this rule had to be checked against). Held by scripts/gate-layout.mjs.
 */
/* ⚠ REVISED TWICE. The min-width/breakpoint version below is kept as a comment because its
 * failure is the useful part.
 *
 * First attempt at THIS fix was `min-width: max-content` above 769px and wrapping below it.
 * It fixed the header and broke the page: min-width is a FLOOR the box may not go under, so
 * on a lot page the "Block NN BUILDING ENVELOPE PLAN" button refused to shrink and pushed the
 * document sideways. Measured horizontal overflow of 58px at 769, 45px at 800, 32px at 831,
 * 20px at 860, 3px at 900, gone by 950 — a band, invisible at both 768 and 1024, which are
 * the two widths the first cut of the gate happened to test either side of the boundary.
 *
 * That is the third time this one defect has been chased across breakpoints, so stop picking
 * widths and state the actual requirement instead:
 *
 *   the button is as wide as its label, UNLESS that would exceed the space available,
 *   in which case it takes the space available and the label wraps inside it
 *
 * which is three declarations and no media query:
 *
 *   width: max-content     size to the label, so where there is room it sits on one line
 *   max-width: 100%        never wider than the container, so the page can never overflow
 *   white-space: normal    if capped, wrap inside the box rather than spill out of it
 *
 * Every viewport gets the same rule and the layout decides the outcome. There is no boundary
 * left to get wrong, which is the only version of this fix that has not since failed.
 *
 * ⚠ `white-space: nowrap` on the label was tried here and reverted. It passed the gate 321/321
 * and was visibly broken: at 320px "BLOCK 96 BUILDING ENVELOPE PLAN" ran straight out through
 * both ends of its button. The clip check could not see it, because with overflow:visible the
 * label element is as wide as its own text, so scrollWidth == clientWidth and the check was
 * incapable of failing. The detector now measures the label against the BUTTON's content box,
 * which is the thing that is actually too narrow. A screenshot found this in seconds after a
 * green suite had signed it off.
 */
.bc-ripple-button__text,
.bc-ripple-button__pseudo {
  white-space: normal;
  overflow: visible;
  text-align: center;
  line-height: 1.25;
}

.brxe-ripplebutton.btn,
a.brxe-ripplebutton {
  width: max-content;
  max-width: 100%;
  min-width: min-content; /* never narrower than the longest word the label cannot break */
}

/* Rows holding these buttons wrap instead of crushing them.
 *
 * flex-shrink:0 was tried here first and overflowed the page by 78px at 320px: refusing to
 * shrink at all means a long label has nowhere to go. min-width:min-content is the precise
 * version of the same intent, a floor at the longest UNBREAKABLE word rather than at the whole
 * label, so a multi-word label still shrinks and wraps while a single word cannot be crushed.
 *
 * The row wrap remains because it is what gives two side-by-side buttons somewhere to go once
 * neither will shrink below its own word.
 *
 * Found by the fixed clip detector: at 769px the header "Brochure" painted 86px of text inside
 * an 84px button. Two pixels, one unbreakable word, in a band about twenty pixels wide. The
 * previous detector reported it clean. */
.brxe-block:has(> .brxe-ripplebutton):not(.bm-header-7-cta),
.brxe-container:has(> .brxe-ripplebutton) {
  flex-wrap: wrap;
}

/* ⚠ The header CTA row is EXCLUDED from the wrap above.
 *
 * Unscoped, that rule let the header's own row wrap and it broke the header outright: the nav
 * took its natural 460px, both buttons dropped to a second row, the bar grew to two rows tall,
 * and the SALT wordmark clipped at the left edge. Caught by comparing the built page against
 * MJ's Desktop comp, which shows nav and both buttons on ONE row. A rule written to stop a
 * button being crushed at 769px had quietly restructured the masthead at every width. */

@media (max-width: 768px) {
  .brxe-ripplebutton.btn,
  a.brxe-ripplebutton {
    padding-left: 14px;
    padding-right: 14px;
    height: auto;
  }
}

/* ---------------------------------------------------------------------------
 * 7. MAJOR. The homepage video rendered at ZERO width.
 *
 * "Time for your sea change" on / and /home/ carries a video block. It measured 0x650: an
 * invisible sliver, with the section's background showing through where the video belongs.
 * Keith flagged it as "Video missing?".
 *
 * Nothing was wrong with the video. The file loads from R2, readyState 4, no failed request,
 * no media error — which is why it survived every check that asked whether the asset was
 * there. Only the painted box was wrong, and only in one dimension.
 *
 * The cause is a specificity collision in the captured Bricks CSS:
 *
 *   :where(.brxe-video) { width: 100% }   <- specificity 0,0,0. :where() zeroes it out.
 *   #brxe-c7b130        { width: auto }   <- specificity 1,0,0. Wins by a mile.
 *
 * width:auto would normally still fill, because a flex item stretches on the cross axis. But
 * the parent is flex-direction:column with align-items:flex-start, so items size to content
 * instead of stretching — and the only child is position:absolute, which contributes nothing
 * to intrinsic width. Content width 0, so the box is 0. The height survived because the ID
 * rule sets it explicitly (65vh = 650px), which is what makes the result so odd-looking: full
 * height, no width.
 *
 * ⚠ This is NOT a port defect. The live WordPress site measures 0x650 on the same element for
 * the same reason, so the port reproduced it faithfully and Keith noticed it here first. It is
 * fixed rather than matched, on the same basis as the card CTA below.
 *
 * align-self overrides the parent's align-items for this item alone, restoring the stretch the
 * ID rule's width:auto is written to expect. Chosen over #brxe-c7b130{width:100%} because the
 * ID differs per page (#brxe-c7b130 on /, #brxe-afygoc on /home/) and per rebuild, so an
 * ID-keyed fix silently stops covering the case the moment the export is regenerated — the
 * same trap as the path-scoped object-fit rule in section 1.
 * ------------------------------------------------------------------------- */
.brxe-video {
  align-self: stretch;
}

/* ---------------------------------------------------------------------------
 * 8. The listing-card CTA did not line up with anything in its own card.
 *
 * Every detail row in a card is a 1fr/3fr grid — label left, value right — so Size, Frontage,
 * Depth and Status all share one left edge at 25% and one right edge at the card's padding
 * box. The CTA sat in a sibling block with justify-content:center instead, landing 17px left
 * of the value column and 67px narrower: at 1440, button 230px at x=1079 against a value
 * column of 297px at x=1096. Keith: "Fix these buttons, the misalignment looks crap".
 *
 * ⚠ Also NOT a port defect — live measures the identical 17px offset (bar 297 at x=147,
 * button 230 at x=130). It is corrected because Keith asked for it corrected.
 *
 * The CTA takes the full content width: its left edge meets the label column, its right edge
 * meets the value column, so both edges land on something already in the card.
 *
 * Matching the VALUE column instead — same left and right as the SOLD bar — was tried first
 * and rejected on measurement: that column is 202px at 1024 while the widest label needs
 * 230px, so it would have forced exactly the wrap section 6 just removed. Full width clears
 * the label at every viewport (269px of column against 230px of label at the tightest).
 *
 * Selected structurally rather than by the generated class .brxe-zmirer. Both currently match
 * all 31 cards, but the class is export-generated and appears 26 times in the captured source
 * — "the block that holds the CTA" is what the rule actually means, and it cannot drift.
 * ------------------------------------------------------------------------- */
.brxe-block.rounded .brxe-block:has(> .brxe-ripplebutton) {
  display: block;
}

.brxe-block.rounded .brxe-block:has(> .brxe-ripplebutton) > .brxe-ripplebutton {
  width: 100%; /* beats section 6's width:max-content — here the column, not the label, sets it */
}

/* ---------------------------------------------------------------------------
 * 9. "Marketing by Cluse & Co." in the footer.
 *
 * Keith is adding the agency credit across all client comms and the sites as he goes. It went
 * out at the bottom of the Walter eDM on 10/08 as two image slices, both linked to
 * cluseco.com.au, reading "MARKETING BY" over the wordmark.
 *
 * On the site it is live text rather than an image, so it stays crisp at any zoom, is
 * selectable, and carries a real link. It sits beside the copyright and Privacy links and
 * inherits their type, which is why there is almost nothing to style here.
 *
 * Inserted into all SIX body templates. The privacy page needed a second pass because its own
 * Privacy link carries aria-current="page", so the exact-string anchor that matched the other
 * five missed it — the same shape of near-miss as the redirect map that covered 26 block pages
 * and not the 5 new ones. Coverage is now asserted at build time by gate:credit.
 * ------------------------------------------------------------------------- */
.salt-agency-credit a {
  opacity: 0.75;
}

.salt-agency-credit a:hover,
.salt-agency-credit a:focus-visible {
  opacity: 1;
}

/* ---------------------------------------------------------------------------
 * 11. Header alignment against MJ's Desktop comp (job 2648, 13/08).
 *
 * Measured 1:1 by pixel-scanning the comp rendered at its native 1366pt against the built page
 * at 1366px:
 *
 *                        COMP          BUILD (before)
 *   olive band           y 30..134     y 30..118
 *   logo left edge       117px         0px          <- wordmark clipped at the viewport edge
 *   logo width           99px          143px        <- 44% oversized
 *   last button right    1252px        1366px       <- ran off the right edge
 *   hero image inset     34px          55px
 *
 * The cause of all three header items is one thing: `.bm-header-7__container` carries ZERO
 * horizontal padding while every other section on the site uses `--space-xl`. So the header
 * content ran edge to edge, clipping the "S" of SALT on the left and pushing REGISTER YOUR
 * INTEREST off the right.
 *
 * ⚠ Not caused by this session's button work. Verified by blocking salt-fixes.css entirely and
 * re-measuring: logo left 0px and identical child geometry with the stylesheet disabled. The
 * flex-wrap rule was suspected first and cleared by that test.
 *
 * The inset is expressed as a clamp rather than a fixed 117px so the 769 to 950 band, where the
 * header is already tight, gets a proportionally smaller inset instead of being squeezed: 66px
 * at 768, 88px at 1024, 117px at 1366 and above. The header content needs about 883px, so at
 * the tightest tested width there is still room.
 *
 * The hero's own 55px inset is left alone. It is 21px wider than the comp's 34px, which is
 * within the tolerance of a full-bleed photograph and not worth destabilising the hero for.
 * ------------------------------------------------------------------------- */
.bm-header-7__container.brxe-container {
  /* The inset grows with the space available but can never squeeze the header content below the
     ~900px it needs. A plain `clamp(20px, 8.57vw, 117px)` was tried first and overflowed the
     document by 35px at 1024 and 16px at 1100, because 8.57vw takes 88px a side from a viewport
     that only has 848px to give. A 900px floor still overflowed by 64px at 992 and a 980px floor by 34px, because the
     desktop header renders in a viewport barely wider than its own min-content just above the
     991px mobile breakpoint. Subtracting 1040px yields ZERO inset through that band, which is
     exactly the ported behaviour and overflows nothing, then grows to the comp's 117px from
     1274px up. Deriving the inset FROM the leftover space cannot do that:
     62px at 1024, 100px at 1100, and the comp's 117px from 1134 upward. */
  padding-inline: clamp(0px, calc((100vw - 1040px) / 2), 117px);
}

/* Logo scaled to the comp. Natural ratio is 2.306 (300x130), so 43px of height gives the
   comp's 99px width without touching the aspect ratio. object-fit:contain from section 2
   keeps it honest if the flex box ever hands it a different box. */
/* ⚠ `height: 43px` was tried here and collapsed the logo to ZERO width at 1024, inside the
   same 992-1099 band where the flex wrapper narrows to 88px. max-width leaves the height to the
   existing object-fit:contain and the natural 2.306 ratio, which cannot collapse the box. */
@media (min-width: 992px) {
  img.bricks-site-logo {
    max-width: 99px;
  }
}

/* The 992 to 1039 band: the desktop header renders in a viewport barely wider than its own
 * content, and section 6's `min-width: min-content` floor stops the two buttons shrinking as far
 * as the ported build let them, which overflowed the document by exactly 18px at 992. Attributed
 * by blocking this stylesheet and re-measuring: 18px with, 0px without.
 *
 * Shaving the header buttons' horizontal padding in that band alone buys back more than the 18px
 * without letting a label be crushed, which is what the min-content floor exists to prevent. The
 * header takes no inset through this band either, so nothing else is competing for the space. */
@media (min-width: 992px) and (max-width: 1039px) {
  .bm-header-7-cta .brxe-ripplebutton.btn,
  .bm-header-7-cta a.brxe-ripplebutton {
    padding-left: 10px;
    padding-right: 10px;
  }
}

/* ---------------------------------------------------------------------------
 * 12. Section 3's right column is a static photograph, not a carousel.
 *
 * Keith, 13/08: "1 - static". MJ's comps put a single barbecue photograph where the build carried
 * a splide carousel, and the carousel is what shipped from the WordPress capture.
 *
 * The height mirrors the carousel's own splide config exactly (`height: 65vh`, dropping to 50vh
 * under 991px) so the section keeps the proportions it had and nothing below it moves. cover
 * crops a 2:3 portrait source into a landscape slot, which is what the comp shows.
 * ------------------------------------------------------------------------- */
.salt-static-feature {
  display: block;
  width: 100%;
  height: 65vh;
  object-fit: cover;
  object-position: center;
}

@media (max-width: 991px) {
  .salt-static-feature {
    height: 50vh;
  }
}

/* ---------------------------------------------------------------------------
 * 13. Images no longer fade in as they scroll into view.
 *
 * Keith, 13/08: "remove the images fading as they come up."
 *
 * The effect is a GSAP ScrollTrigger bound to `.brxe-imagereveal` wrappers captured from
 * WordPress (`data-duration="1.4"`, `data-ease="power4"`, direction from top). Two things were
 * done rather than one, because either alone is fragile:
 *
 *   1. `data-script-id` stripped from every image-reveal wrapper, so the Bricks initialiser never
 *      binds a trigger to it. The captured markup already carries the SETTLED state inline
 *      (opacity 1, transform none), so with nothing bound the image simply renders.
 *   2. this rule, as a guard, in case a future re-capture reinstates the binding.
 *
 * Scoped to the image reveal. The hero headline's letter blur-in is a different component
 * (`next_blur_reveal`) and Keith asked specifically about images, so it is left alone.
 * ------------------------------------------------------------------------- */
.bc-img-reveal__element,
.bc-img-reveal__img {
  opacity: 1 !important;
  visibility: visible !important;
  transform: none !important;
  filter: none !important;
  clip-path: none !important;
}

/* ============================================================================
 * MOBILE DEFECTS — Keith, 18/08/26.
 *
 * Every rule below carries the measurement that justifies it, taken with
 * Playwright against the BUILT site at the stated viewport. None of it is
 * deduced from the markup: the first attempt at issue 6 had a plausible and
 * completely wrong cause, and only a computed-style read settled it.
 * ==========================================================================*/

/* ISSUE 1 — the logo and the hamburger sit hard against the viewport edges.
 * Measured at 320, 360, 375, 390, 414 and 428: the logo is at x=0 at EVERY
 * width (no gap at all) and the toggle is 5px from the right at every width.
 * Both live in the captured header, so this is identical on every page. */
@media (max-width: 767px) {
  .brxe-logo { margin-left: 16px; }
  .bricks-mobile-menu-toggle { margin-right: 12px; }
}

/* ISSUE 3 — the footer CTAs are not centred.
 * The column holding them IS centred (x=22, width=346, centre=195 at 390px),
 * but its flex row is justify-content:normal, so the buttons pack to the left:
 * "Register your interest" centre 158 and "Brochure" centre 98 against a
 * viewport centre of 195. Both stayed at exactly 158 and 98 from 320px right
 * through 428px — they never tracked the viewport at all, which is the tell
 * that this is alignment and not a width problem. */
@media (max-width: 767px) {
  #salt-footer [data-footer-cta] { justify-content: center; }
}

/* ISSUE 4 — the Privacy link is stranded.
 * home's bottom bar is a three-column grid (1fr auto 1fr) and the link carries
 * justify-self:end, so it sat a constant 46px from the right edge at every
 * width (centre 274 at 320px, 344 at 390px) while the copyright sat far left.
 * The captured footer on the other pages has the mirror-image problem, with
 * Privacy at centre 47. One centred column on mobile fixes both. */
@media (max-width: 767px) {
  /* ⚠ !important is load-bearing here and nowhere else in this file. The grid is
   * declared in an INLINE style attribute on the element
   * (style="… display: grid; grid-template-columns: 1fr auto 1fr …"), and an
   * inline declaration outranks any stylesheet rule regardless of cascade order
   * or specificity. The first attempt at this rule was written without it, and
   * measured EXACTLY the same 46px-from-the-right position afterwards. */
  #salt-footer [data-grid3] {
    grid-template-columns: 1fr !important;
    justify-items: center !important;
    text-align: center !important;
  }
  #salt-footer [data-grid3] > a { justify-self: center !important; }

  /* The captured footer needs the CHILD blocks centred too, not just their
   * container. #brxe-nutcux took align-items:center correctly, but its child
   * #brxe-cnnvkh is itself a full-width flex column with align-items:flex-start,
   * so the Privacy link inside it still measured x=17 on a 390px viewport. */
}

/* ISSUE 6 — the Building Envelope Plan button rendered as INVISIBLE TEXT (mint on mint),
 * because the port captured Bricks' PER-ELEMENT css keyed by id and the second document button
 * was given an invented id, brxe-xptpst-bep, that no captured rule matched.
 *
 * The rule that fixed it is REMOVED: that second button no longer exists — Keith, 18/08, "this
 * isn't two different buttons" — so the CSS styled nothing. The lesson it taught is the part
 * worth keeping: any NEW element given a fresh brxe-* id inherits none of the captured
 * per-element styling and will come out unstyled or invisible.
 */

/* ISSUE 5 — click a plan to enlarge it. See public/js/salt-lightbox.js for why
 * this also retires the home page's dead amenity-map button. */
[data-salt-zoom] { cursor: zoom-in; }
.salt-lb {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(2, 41, 56, 0.94);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}
.salt-lb__img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  display: block;
}
.salt-lb__close {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 44px;   /* 44px is the tap target the agent card is already held to */
  height: 44px;
  font-size: 30px;
  line-height: 1;
  color: #f5efe4;
  background: rgba(2, 41, 56, 0.65);
  border: 1px solid rgba(245, 239, 228, 0.5);
  cursor: pointer;
}

/* HEADER PROPORTIONS ON MOBILE — Keith, 18/08: "logo, brochure download,
 * hamburger icon are disproportionate."
 *
 * Screenshotted at 320 and 390 rather than judged from numbers, because the
 * complaint is a visual one. What the pictures showed:
 *
 *  - the BROCHURE button is the heaviest thing in the header. At 390 it measured
 *    138x44 against a logo image of 83x36, so the CTA outweighed the brand.
 *  - at 320 it is not merely heavy, it BREAKS: the CTA block is 209px wide, the
 *    button plus the toggle do not fit, so the toggle wraps onto a second row
 *    (button at y=68, toggle at y=113) and the button runs to the viewport edge.
 *    The header block grows to 103px to hold two rows.
 *  - the toggle is a 3-line rule at 44x44 and reads as flimsy beside the button.
 *
 * So: one row, vertically centred, with the button pulled back to a size that
 * sits under the logo rather than over it. Tap targets stay at 44px — the site
 * already holds that standard and shrinking the height to balance the width
 * would trade one defect for a worse one. */
@media (max-width: 767px) {
  /* One row, centred, and never wrapping. */
  #brxe-dce17a.bm-header-7 { align-items: center; }
  #brxe-21f8c1.bm-header-7-cta {
    flex-wrap: nowrap;
    align-items: center;
    gap: 10px;
  }
  /* The captured side-by-side margin fights the gap above and pushes the button
   * into the toggle. Same margin that offset the footer Brochure button. */
  #brxe-21f8c1.bm-header-7-cta > * { margin-left: 0; }

  /* The button, pulled back. 138px wide was 35% of a 390px viewport. */
  #brxe-21f8c1.bm-header-7-cta .brxe-ripplebutton {
    padding: 12px 14px;
    font-size: 11px;
    letter-spacing: 0.1em;
    white-space: nowrap;
  }

  /* The logo leads. The image was 36px tall against a 44px button. */
  #brx-header .bricks-site-logo { height: 42px; width: auto; }

  /* The toggle, given enough weight to sit beside the button rather than under it.
   *
   * Keith, 18/08, after the first pass: "Hamburger icon looks too small next to
   * button?" He is right and the numbers say why — the bars measured 34x3 inside a
   * 44x44 box, sitting next to a 125x44 button. The BOX was already a legal tap
   * target; the MARK inside it was the thin part, so it read as small.
   *
   * Bars go to 40x4 in a 48x48 box. Tap target grows rather than shrinks. */
  /* ⚠ The captured Bricks CSS sets these widths with !important:
   *     #brxe-gvpniw .bricks-mobile-menu-toggle .bar-top {width: 34px !important}
   * Cascade order cannot beat !important, so this has to match it. The first pass
   * without !important measured 34px bars afterwards, unchanged. */
  #brxe-gvpniw .bricks-mobile-menu-toggle,
  .bricks-mobile-menu-toggle {
    width: 48px !important;
    height: 48px;
    padding: 8px;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    justify-content: center;
    gap: 7px;
  }
  #brxe-gvpniw .bricks-mobile-menu-toggle .bar-top,
  #brxe-gvpniw .bricks-mobile-menu-toggle .bar-center,
  #brxe-gvpniw .bricks-mobile-menu-toggle .bar-bottom,
  .bricks-mobile-menu-toggle span,
  .bricks-mobile-menu-toggle .bar {
    width: 40px !important;
    height: 4px;
    margin: 0;
  }
}

/* TAP TARGETS — every CTA to 44px.
 *
 * A site-wide audit at 390px found two that fell short, both because they are
 * inline-styled and carry no min-height: the footer's "Register your interest"
 * at 43.8px, and the captured WS Form submit at 42.8px. Under a pixel each, but
 * 44 is the standard the rest of the site is already held to (the agent card has
 * a measured 44px assertion), and a rule that is nearly kept is not kept.
 *
 * min-height rather than height: these buttons wrap their label on narrow
 * screens and a fixed height would clip the second line. */
#salt-footer button,
#salt-lower button,
/* ⚠ The captured WS Form CSS sets min-height:0 at a specificity a bare class cannot
 * beat, so the submit needs the form id in the selector. Measured 42.8px before,
 * with computed min-height 0px, after a plain `.wsf-button` rule had been added. */
form.wsf-form .wsf-button,
#ws-form-1 .wsf-button,
.salt-form button[type='submit'] {
  min-height: 44px;
}

/* ============================================================================
 * PLAYWRIGHT SWEEP — job 2648, 19/08/26. Three defects, confirmed by hand against
 * a served dist/ build (not deduced from source) before each fix, then re-measured
 * after. Neighbouring breakpoints checked both sides on every one.
 * ==========================================================================*/

/* ---------------------------------------------------------------------------
 * DEFECT 1. MAJOR. /appointment/ overflowed horizontally at 320px.
 *
 * Measured before: .salt-form.v-spray.is-wide rendered 311px wide at x=22, right
 * edge 333px against a 320px viewport — document.scrollWidth 333 vs innerWidth
 * 320, and the page could be dragged 13px sideways. Clean at 360px (0 overflow).
 * /vip/ and /offer/ share the same .salt-form component WITHOUT is-wide and were
 * never affected (276px wide at 320, matching the container exactly).
 *
 * Cause: the captured .brxe-container this page mounts into is
 * `display:flex; flex-direction:column; align-items:flex-start` — every ported
 * section wrapper is one of these. align-items:flex-start means the child does
 * NOT stretch to the container's width; it sizes itself via shrink-to-fit, which
 * can never go narrower than its own content's preferred width. At 320px the
 * container's content box is 276px (320 minus the page's own 22px insets), and
 * the is-wide card's preferred width — driven by its two-column field grid, which
 * only collapses to one column below 640px but still carries the grid's own
 * unbreakable content — computed to ~311px. Preferred width did not shrink with
 * the viewport, so once the viewport got narrow enough to be less than 311px the
 * box simply refused to fit and the document overflowed instead.
 *
 * Not visible above ~340px because from there the container is wider than the
 * card's preferred width, so shrink-to-fit already lands under the max-width
 * cap and nothing needed to change — confirmed by diffing every tested width
 * 320-1440 before and after this rule: identical at every width except 320.
 *
 * Fix: width:100% makes the box fill whatever the flex column hands it, up to
 * its own max-width (920px, section "is-wide" above), instead of shrinking to
 * its preferred content size and refusing to go smaller. Scoped to the exact
 * .v-spray.is-wide combination — currently only /appointment/ — because a bare
 * `.salt-form{width:100%}` changes /offer/'s rendering: that form's plain
 * .salt-form card sits at a NARROWER natural width (385-407px) than its own
 * 520px cap from ~478px up, and forcing width:100% there stretches it out to
 * 520px, a visual change nobody asked for. Verified: with the fix scoped this
 * way, /vip/ and /offer/ measure byte-for-byte identical at every width 320
 * through 1440 versus before the fix; only /appointment/ at 320px changes,
 * from 311px/13px-overflow to 276px/0-overflow.
 * ------------------------------------------------------------------------- */
.salt-form.v-spray.is-wide {
  width: 100%;
}

/* ---------------------------------------------------------------------------
 * DEFECT 2. The header CTA overflowed the viewport, but ONLY from 479 to 482px
 * — a four-pixel-wide band, clean on both sides.
 *
 * Measured before: at 478px the CTA (#brxe-21f8c1.bm-header-7-cta) is 201px wide
 * (hamburger toggle + "Brochure" only) and the document does not overflow. At
 * 479px it jumps to 414px wide and the document overflows by 4px; at 480px,
 * 481px and 482px the overflow shrinks to 3, 2 and 1px; at 483px it is back to
 * 0 overflow with the CTA still 414px wide (right edge lands exactly on the
 * viewport edge).
 *
 * Cause: #brxe-ugmlvu — the "Register your interest" button — lives INSIDE
 * #brxe-21f8c1 alongside the nav toggle and "Brochure", and the captured Bricks
 * CSS hides it with `@media (max-width: 478px) { #brxe-ugmlvu { display: none } }`.
 * That rule stops applying the instant the viewport passes 478px, so the button
 * reappears at 479px — at its compact mobile size (padding and font-size from
 * the "HEADER PROPORTIONS ON MOBILE" rule above, which is already active because
 * it covers the whole max-width:767px band), but "Register your interest" is
 * still 203px of unbreakable text at that size (white-space:nowrap is
 * deliberate there, so it cannot shrink further without wrapping to two lines,
 * which is the defect that rule exists to prevent). Toggle + Brochure + the
 * reappeared Register + gaps need 414px, and the viewport does not have 414px
 * of room again until 483px — a captured breakpoint and this file's own mobile
 * CTA treatment disagreeing about exactly where "enough room" starts, the same
 * shape of gap as Issue 4 and the earlier button-clip chase above.
 *
 * Fix: hold #brxe-ugmlvu hidden 4px further, to 482px, so it only reappears
 * where the CTA has already been measured to fit (483px). !important is
 * load-bearing: it has to beat the captured `#brxe-ugmlvu{...}` ID rule's own
 * specificity at 479-482, the same reason section "ISSUE 4" needed it.
 *
 * Verified 320-1024 both with and without this rule: identical at every width
 * except 479-482, which go from 4/3/2/1px of overflow to 0; 478 and below stay
 * hidden exactly as before, 483 and above stay visible exactly as before.
 * ------------------------------------------------------------------------- */
@media (max-width: 482px) {
  #brxe-ugmlvu {
    display: none !important;
  }
}

/* ---------------------------------------------------------------------------
 * DEFECT 3. MINOR. Footer contact links were under the tap-target bar on mobile,
 * on every page (the footer is one component, rendered once — see SiteFooter.astro).
 *
 * This is the rule the earlier "MINOR. Footer contact links measured 20 to 21px"
 * comment above (section 3/4) promised and never shipped — measured again here
 * rather than trusted: the click-to-call link (tel:+61447346523) is 111x20px and
 * the email link (mailto:) is 251x20px, both under the 44px bar this site holds
 * everything else to and under the WCAG 24px floor.
 *
 * Both sit on their own line already (the markup separates "Email:" and "Call:"
 * with <br>, not inline running text), so growing them does not need to fight
 * neighbouring text on the same line the way the footer CTAs did. padding: 12px
 * 0 on an inline-block turns the ~20px of glyph height into 44px without
 * touching font-size, keeping them as plain text links rather than turning them
 * into boxed buttons — same "vertical breathing room instead of a box" intent
 * the earlier comment described.
 *
 * Scoped to touch (max-width:768px or pointer:coarse), matching every other
 * tap-target rule in this file, so desktop mouse rendering is untouched.
 *
 * Verified 320-768: both links measure 54px tall (comfortably clear of 44) with
 * no change in width or wrapping; at 769px and above both are back to their
 * original 20px, byte-for-byte unchanged from before this rule.
 * ------------------------------------------------------------------------- */
@media (max-width: 768px), (pointer: coarse) {
  #salt-footer a[href^='tel:'],
  #salt-footer a[href^='mailto:'] {
    display: inline-block;
    padding: 12px 0;
  }
}
