/*
 * New-UI LAYOUT OFFSETS — make the site's hardcoded header clearances follow an
 * author-set header height. Scoped entirely under `.new-ui-branded`, the class
 * <Layout> puts on `<main id="middle">` ONLY for flagged projects whose landing
 * payload is brandable (useNewLanding → brandingActive). Non-flagged projects
 * never get the class and never fetch this sheet, so they are untouched.
 *
 * THE PROBLEM
 * The site header is `position: fixed` (globals.css `.fix-nav`) and its bar is
 * pinned at 90px by TWO rules — `.nav-bar { height: 90px }` (globals.css:1083)
 * and the inner `.navbar { height: 90px }` (:1063) — plus a ~35px `.notice-bar`
 * while the project is not yet Selling. So the live header is 125px, or 90px on
 * a Selling project. Roughly 25 rules across globals.css hardcode a clearance
 * against those two numbers (`.banner` margin-top: 130px, `.inner-gap`
 * padding-top: 145px, `.top-gap` padding: 103px…, `.banner-space` margin-top:
 * 94px, `.mt-83px`, `.not-found`, `.policy-banner`, `.change-password
 * .profile-form`, and their many breakpoint variants). Let an author make the
 * bar taller and every one of them is short by the difference, so the top of
 * each page slides under the header.
 *
 * THE CONTRACT
 * <Header> measures the bar and publishes, on `document.documentElement`:
 *
 *     --nu-header-delta   =  round(measured .nav-bar height - 90)
 *
 * i.e. how far the bar departs from the height globals.css assumes (see
 * headerDeltaPx in NewLanding/headerOptions.ts). It is measured off `.nav-bar`
 * rather than the whole header, so the notice bar — which is not part of the
 * 90px baseline — never leaks into it. Published only for branded projects and
 * removed on unmount, exactly like its sibling `--nu-header-height`.
 *
 * PLUS THE DRAFT-PREVIEW BANNER. When a `?preview=` token is in play,
 * Home/NewLanding/PreviewBanner renders a `position: fixed` strip across the
 * top of the viewport and the header stacks below it (`.fix-nav` takes
 * `top: var(--nu-preview-banner-height)`). Its height is added to the delta —
 * see headerChromeVars — because it is extra distance of exactly the kind this
 * scheme exists to absorb: every rule below then clears the banner as well,
 * with no change to any of them. It is added to `--nu-header-height` too, and
 * the two cancel correctly in `.lp-landing`'s subtraction (see the NOTE in (a)).
 * With no banner on screen the variable is unset, both additions are 0px, and
 * the NO-OP AT ZERO guarantee below is untouched.
 *
 * NO-OP AT ZERO — the guarantee this whole scheme rests on. Every rule below
 * ADDS the delta to the value that is already there; it never restates a
 * measurement. So on a project where nobody touched the header height the bar
 * measures 90px, the delta is `0px`, and every declaration computes precisely
 * what it computes today: `calc(125px + 0px)` is `125px`, and a `padding-top`
 * of `0px` is indistinguishable from no padding at all (notably it does NOT
 * suppress margin collapsing, which a non-zero padding would — so a first child
 * with a top margin behaves identically). The `var(…, 0px)` fallback extends the
 * same guarantee to any page where the variable is never set at all.
 *
 * WHY TWO KINDS OF RULE
 * The ~25 hardcoded clearances are all normal-flow offsets (margin/padding) that
 * push content DOWN the page, so a single `padding-top` on the common content
 * wrapper shifts all of them at once — see (a). Sticky/fixed `top` offsets are
 * NOT movable that way: `top` resolves against the viewport (or the scrollport),
 * which an ancestor's padding does not change. Those must each be restated —
 * see (b).
 */

/* ────────────────────────────────────────────────────────────────────────────
 * (a) NORMAL-FLOW OFFSETS — all of them, in one declaration.
 *
 * `<main id="middle">` is the routed content wrapper: <Layout> renders
 * `<Header /> <main id="middle"> {children} </main> <Footer />`, so every page
 * that sits beneath the fixed header — the landing/property list, unit detail,
 * shortlist, myprofile, changepassword, details/[sectionSlug] — is inside it.
 * (The auth routes in constants.UNGUARD_PAGES bypass <Layout> altogether and so
 * render no <Header> at all; with no fixed header to clear, and no variable
 * published, there is nothing for them to absorb.)
 *
 * Padding rather than margin: margin on `<main>` would collapse with the
 * children's own top margins and swallow the shift.
 *
 * Selector specificity (1,1,1): `.new-ui-branded` alone would be (0,1,0) and
 * could be out-ranked by a per-project `/assets/styles/<slug>.css` rule on
 * `main` or `.bg-color` — those sheets are also appended at runtime, so source
 * order between them and this file is not guaranteed. Pinning the id + element
 * takes order out of it. It is written as one selector (not a bare `.new-ui-
 * branded`) partly to document that this class only ever lands on that element.
 *
 * NOTE .lp-landing (NewLanding.tsx) offsets ITSELF by the full measured
 * `--nu-header-height` and therefore SUBTRACTS the delta again, precisely
 * because this padding is on its ancestor — measured height minus delta, plus
 * this padding, is the measured height. Do not "fix" one without the other.
 * The preview banner rides through that arithmetic untouched: it is in both
 * variables, so it cancels in the subtraction and survives in the sum, leaving
 * the landing exactly one header below the banner.
 * ──────────────────────────────────────────────────────────────────────────── */
main#middle.new-ui-branded {
  padding-top: var(--nu-header-delta, 0px);
}

/* ────────────────────────────────────────────────────────────────────────────
 * (b) STICKY `top` OFFSETS — restated one by one.
 *
 * Each of these is a `position: sticky` element whose `top` is a header-derived
 * constant, so it parks itself just below the fixed header while the page
 * scrolls. (a)'s padding cannot move them, so each adds the delta itself. The
 * literal in every `calc()` is the value globals.css already has, which is what
 * keeps the delta-zero case byte-identical.
 *
 * Verified complete: these are the only `position: sticky|fixed` rules in
 * globals.css whose `top` is header-derived. Deliberately left on their literal
 * values: `.fix-nav` (`top: 0` — it IS the header), `#root .page-spinner`
 * (`top: 0`, full-viewport overlay), `#root .img-flex-btn-grp` (`top: 20px` —
 * the fullscreen-image close button, which sits OVER the header at z-index
 * 11111 rather than clearing it), and `#root .custom-toast` (no `top`).
 *
 * WHY `:where(.new-ui-branded)` AND NOT `.new-ui-branded`. Unlike (a), which adds
 * a declaration nothing else sets, each rule below OVERRIDES a `top` that
 * globals.css already declares — and that a project's own
 * `/assets/styles/<slug>.css` may already override too. `:where()` contributes
 * zero specificity, so these stay exactly as specific as the globals rules they
 * shadow ((0,1,0), and (1,1,0) for the `#root` one) and win only on source order,
 * this sheet being appended at runtime and therefore later than the bundled
 * globals.css. That keeps the existing cascade intact rather than raising these
 * rules above a project's own customisation.
 *
 * One honest caveat: a per-project `/assets/styles/<slug>.css` is appended by a
 * DIFFERENT async effect (src/app/template.tsx, on the project fetch) than this
 * sheet (Layout.tsx, on the flag), so which lands later is a race, not a
 * guarantee. Equal specificity means the loser of that race loses the tie. In
 * practice no audited slug sheet touches these four selectors, and the risk is
 * strictly smaller than it would be had these rules been given higher specificity
 * — but it is a race, and this comment previously claimed otherwise. Raising the specificity instead would
 * silently steal `top` back from any project that had customised it, which is the
 * one thing this change must not do.
 *
 * This is the one place these sheets diverge from their three siblings, which do
 * scope with a plain class: those only ADD brand colour, so out-ranking a project
 * sheet was never a risk. On a browser without `:where()` (pre-Safari 14) the rule
 * is dropped wholesale and the sticky element keeps its literal offset — i.e. it
 * degrades to exactly today's behaviour, which is the safe direction to fail.
 * ──────────────────────────────────────────────────────────────────────────── */

/* The unit-listing filter/sort bar and the unit-detail header row
 * (UnitListing.tsx, UnitLeftInfo.tsx). globals.css:3433 — `top: 125px`, the
 * full header WITH the notice bar. globals only ever varies its `display` per
 * breakpoint, never its `position` or `top`, so this needs no media gate: the
 * mobile variant (`#root .fixed { display: block }` below 991px) is sticky under
 * the same fixed header and wants the same delta. */
:where(.new-ui-branded) .fixed {
  top: calc(125px + var(--nu-header-delta, 0px));
}

/* MOBILE: the delta is not enough. `--nu-header-delta` tracks `.nav-bar` alone
 * (see THE CONTRACT above), so a taller `.notice-bar` is never absorbed and the
 * sticky filter/sort row keeps its hardcoded 125px and slides under the header.
 * Below 991px that row is the only thing sitting under the bar (`#root .fixed
 * { display: block }`, globals.css:9095), so here we can use the measured FULL
 * header height, notice bar included, instead of the literal-plus-delta form.
 * `--nu-header-height` is published on <html> by <Header> off the `.fix-nav`
 * root, which wraps BOTH `.notice-bar` and `.nav-bar`; the 125px fallback keeps
 * the pre-change value if it is ever unset.
 *
 * `.fixed.unit-gap` is restated because `:where(.new-ui-branded) .unit-gap`
 * below is equally specific and comes later, so it would otherwise win on a
 * Selling project. Those have no notice bar, so the measured height there is
 * the bar height and the outcome is unchanged. Still `:where()` for the scope,
 * for the reason documented above. */
@media (max-width: 991.98px) {
  :where(.new-ui-branded) .fixed,
  :where(.new-ui-branded) .fixed.unit-gap {
    top: var(--nu-header-height, 125px);
  }
}

/* SOURCE ORDER MATTERS from here on. `.top-filter` and `.unit-gap` are modifier
 * classes added ALONGSIDE `.fixed` on Selling projects (which have no notice
 * bar, hence ~90px instead of 125px); in globals.css they win over `.fixed`
 * purely by coming later at equal specificity (:5156 / :5160 vs :3433). The
 * scoped selectors here are equal to each other too, so they must appear in the
 * same order to preserve the same outcome. */

/* Unit-detail header row on a Selling project — UnitLeftInfo.tsx adds
 * `.top-filter` next to `.fixed`. globals.css:5156 — `top: 89px`. */
:where(.new-ui-branded) .top-filter {
  top: calc(89px + var(--nu-header-delta, 0px));
}

/* Unit-listing filter bar on a Selling project — UnitListing.tsx adds
 * `.unit-gap` next to `.fixed`. globals.css:5160 — `top: 90px`. */
:where(.new-ui-branded) .unit-gap {
  top: calc(90px + var(--nu-header-delta, 0px));
}

/* Unit-detail sticky sidebar column (UnitLeftInfo.tsx `.sticky-postion-div`).
 * globals.css:4854 — `#root .sticky-postion-div { position: sticky; top: 150px }`.
 *
 * GATED ON min-width: 1200px, and it must be: globals unsticks this element on
 * smaller viewports — `position: unset` below 1199px (:8621) and
 * `position: relative; top: 0` below 991px (:8900). This selector is (1,2,0) and
 * would out-rank that (1,1,0) `top: 0` regardless of source order, shoving the
 * column 150px down the mobile layout. Restricting the rule to the range where
 * the sticky `top` is actually live leaves both smaller ranges exactly as they
 * are. */
@media (min-width: 1200px) {
  #root :where(.new-ui-branded) .sticky-postion-div {
    top: calc(150px + var(--nu-header-delta, 0px));
  }
}
