/* Responsive layer for the Fairmount bundle.
   The design ships its @media rules inside an inline <style>, but the dc-runtime
   does not activate inline media rules, so the intended responsive behaviour
   never applies. This linked stylesheet re-declares that intent through a normal
   <link> (parsed like the token sheets) so it actually takes effect.
   Breakpoints mirror the design: 1100px (drawer + 2-col) and 720px (1-col). */

/* --- Form control alignment (all widths) ---------------------------------
   The bundle's inputs/selects/textareas are content-box with no width, so a
   textarea sizes to its intrinsic `cols` (~796px at 25px font) and spills past
   its card, dragging the whole form out of alignment. Constrain every control
   to its container and let it fill the grid cell it sits in.
   Do NOT add min-width:0 to the wrappers, it collapses fields to 0 on mobile. */
body input:not([type="checkbox"]):not([type="radio"]),
body textarea,
body select {
  box-sizing: border-box;
  width: 100%;
  max-width: 100%;
}

/* --- Enquire edge tab ----------------------------------------------------
   No size override needed. The earlier export forced width:13px/height:154px,
   which the UA's border-box on <button> turned into a 26px-wide box with the
   vertical label clipped; we compensated with explicit sizes. The 2026-07-27
   export dropped width/height entirely (14px type, .24em tracking, 24px 12px
   padding, nowrap) so the tab sizes to its own content and needs nothing here.
   Do NOT set `transform`: the design parks the tab at translateX(110%) and
   slides it in on `body.fm-scrolled`; overriding that would pin it open. */

/* --- Drawer navigation ---------------------------------------------------
   The design's hamburger <button data-navtoggle> has no `display` of its own, so
   it would show at every width. Hide it on desktop; the 1100px tier turns it on
   and hides the inline nav links. */
[data-navtoggle] { display: none !important; }

/* --- 1100px: header switches to the drawer, dense grids go 2-up ---------- */
@media (max-width: 1100px) {
  body nav [data-navlinks] { display: none !important; }
  [data-navtoggle] { display: flex !important; }

  /* Logo to the left edge, flush with the page content (20px), instead of
     centred in the bar. The hamburger is position:absolute at left:12px and
     48px wide, so it has to move to the right for the logo to reach the edge, it lands on the same side as the drawer's own close button, which reads
     more consistently anyway. The nav keeps a 68px gutter on whichever side
     the hamburger occupies so the logo can never sit underneath it.
     Scoped with `:has(> [data-navtoggle])` because the drawer is a SECOND
     <nav> in the document: a position:fixed panel wider than the viewport that
     slides in on a transform. A bare `body nav` padding rule reshaped that
     panel too and pushed it 33px off-screen, clipping every menu item's first
     letter ("OME", "BOUT US"). Only the header nav holds the hamburger. */
  body nav:has(> [data-navtoggle]) {
    padding-left: 20px !important;
    padding-right: 68px !important;
  }

  body [data-navtoggle] {
    left: auto !important;
    right: 12px !important;
  }

  /* the logo wrapper is a flex column with align-items:center */
  body nav:has(> [data-navtoggle]) > div:nth-child(3) {
    align-items: flex-start !important;
    /* the wrapper carries its own side padding, which would leave the logo a
       few px shy of the content edge it is meant to line up with */
    padding-left: 0 !important;
  }

  body div[style*="repeat(3,1fr)"], body div[style*="repeat(3, 1fr)"],
  body div[style*="repeat(4,1fr)"], body div[style*="repeat(4, 1fr)"] { grid-template-columns: repeat(2, 1fr); }

  /* Inner-page top padding was trimmed here, at ≤1100px only. The same gap is
     on desktop for the same reason, so the rule moved to refresh.css section 12
     and the media query went away. */

  /* --- Gallery mosaic ------------------------------------------------------
     The grid is `repeat(4, 1fr)` on 220px rows and its feature tiles span
     2 x 2, so a feature tile is 460px tall, over half a phone screen. The
     720px blanket rule below collapses the grid to one column, which made it
     worse: the tile still spanned two rows but now filled the full width.
     Keep the two-column mosaic (hence the grid-auto-rows exemption in that
     rule) and halve the row height instead: a feature tile becomes full-width
     x 232px, a small tile ~169 x 110px. The row height is in vw so the tiles
     keep those proportions from a small phone up to a tablet (28vw = 109px at
     390, 215px at 768) rather than turning into letterboxes on the wider end.
     grid-auto-rows is unique to this grid in the export, so matching on it
     needs no further qualification. */
  body div[style*="grid-auto-rows: 220px"],
  body div[style*="grid-auto-rows:220px"] {
    grid-template-columns: repeat(2, 1fr) !important;
    grid-auto-rows: 28vw !important;
    gap: 12px !important;
  }
}

/* --- 860px: overflow guards + spacing trims ------------------------------ */
@media (max-width: 860px) {
  /* The overflow-x correction that used to live here now applies at every
     width, see "the body scroll container" in refresh.css. It was mobile-only,
     which is why position:sticky worked on a phone and silently did nothing on
     desktop. */
  html, body { max-width: 100%; }
  body img { max-width: 100%; height: auto; }

  /* Top utility bar is a 3-col grid (phone | email | CTA) that measures ~835px.
     One row cannot hold all three on a phone: 342px of usable width against
     phone 136 + email 191 (even at 11px) + CTA 119 = 462. So the email drops to
     a second line under the phone and the CTA spans both rows.
     Padding comes down from 13px to 7px deliberately: the header must stay
     ~134px tall, because the pinned decks (Signature Developments, Milestones)
     stick at top:146px and would slide under a taller header. */
  body [data-cursor="gold"] > div {
    grid-template-columns: 1fr auto !important;
    column-gap: 10px !important;
    row-gap: 0 !important;
    padding: 7px 12px !important;
  }

  /* phone, first line */
  body [data-cursor="gold"] > div > span:nth-of-type(1) {
    grid-area: 1 / 1 !important;
    font-size: 14px !important;
  }

  /* email, second line to 12px keeps it at 206px, inside the 215px column */
  body [data-cursor="gold"] > div > span:nth-of-type(2) {
    display: flex !important;
    grid-area: 2 / 1 !important;
    font-size: 12px !important;
    /* the export centres this block, which is right for the middle column of
       the desktop three-column bar but leaves it adrift once it is stacked
       under the phone number */
    justify-content: flex-start !important;
    justify-self: start !important;
  }

  body [data-cursor="gold"] > div > span:nth-of-type(2) * {
    font-size: 12px !important;
  }

  /* CTA sits beside both lines */
  body [data-cursor="gold"] > div > a {
    grid-area: 1 / 2 / span 2 / 3 !important;
    align-self: center !important;
  }
  body [data-cursor="gold"] { white-space: normal !important; }
  /* Compact the CTA so it fits inside 390px without clipping.
     Nothing is hidden inside the phone block: an earlier version of this rule
     dropped its first child on the assumption it was an "ENQUIRIES" label, but
     that child is the phone icon, the same structure the email block uses for
     its envelope. Hiding it left the phone as bare text while the email kept
     its icon. */
  body [data-cursor="gold"] a[style*="border-radius: 999px"] { font-size: 11px !important; padding: 5px 12px !important; letter-spacing: .08em !important; }

  /* About / partner: unstick the left column once the grid has stacked.
     Both spellings, because the dc-runtime re-serialises every style attribute
     through the CSSOM ("top: 190px"), while the export source has no space, and the importer now pins these at 190px, not the old 140px. */
  body div[style*="top:190px"], body div[style*="top: 190px"],
  body div[style*="top:140px"], body div[style*="top: 140px"] { position: static !important; }

  /* Section side padding tightens */
  body section { padding-left: 20px !important; padding-right: 20px !important; }

  /* Partner marquee tiles slightly smaller */
  /* Trusted Partners cards. The design sizes them 280x150, so barely one and a
     half fit a 390px screen and each logo reads as clipped. Shrink the card and
     let the logo art inside fill it.
     Both spellings are needed: the raw export has no space after the colon, the
     dc-runtime re-writes the attribute through React, which adds one. */
  /* Three cards per marquee row, at any mobile width. The track spans ~90-95%
     of the viewport and each card carries a right margin, so the pitch must be
     a third of that: 30vw - 8px card + 8px gap.
     The card is deliberately squarer than the design's 280x150 (20vw tall, not
     16vw): most of these logos are near-square artwork, and `background-size:
     contain` sizes them off the shorter side, so card height, not width, is
     what caps how large a logo reads. Height is an explicit length rather than
     aspect-ratio because the card is a flex item and the row's default
     align-items:stretch resolves its cross size first. */
  body div[style*="width: 280px"][style*="height: 150px"],
  body div[style*="width:280px"][style*="height:150px"] {
    width: calc(30vw - 8px) !important;
    height: 20vw !important;
    padding: 6px !important;
    margin-right: 8px !important;
  }

  /* the logo inside carries its own 420x223 box; make it fit the smaller card */
  body div[style*="width: 280px"] > [style*="background-image"],
  body div[style*="width:280px"] > [style*="background-image"] {
    width: 100% !important;
    height: 100% !important;
    background-size: contain !important;
    background-repeat: no-repeat !important;
    background-position: center !important;
  }

  /* --- Enquiry slide-out panel -------------------------------------------
     The panel is `right:64px; width:380px` with 28px of padding and no
     border-box, so its real width is 436px: on any phone the left edge lands
     off-screen and the form is clipped. `width: calc(100vw - 84px)` alone did
     not fix it, the padding is still added on top. Pin both edges instead and
     let the width fall out of that, and cap the height so a long form scrolls
     inside the sheet rather than running off the top and bottom.

     Do NOT touch `transform`: the open animation (fm-unfold) ends at
     `translateY(-50%) rotateY(0)`, which is what centres the panel. */
  body [data-enquiry="panel"] {
    left: 12px !important;
    right: 12px !important;
    width: auto !important;
    box-sizing: border-box !important;
    padding: 22px 18px 20px !important;
    max-height: 86vh !important;
    overflow-y: auto !important;
  }

  /* The panel only exists in the DOM while open, so this hides the edge tab
     that would otherwise sit on top of the sheet's right-hand edge. */
  body:has([data-enquiry="panel"]) [data-edge-tab] { display: none !important; }
}

/* --- 720px: everything stacks to a single column -------------------------
   This used to list column patterns one by one (`repeat(3,1fr)`, `1.15fr`…),
   which quietly missed every value nobody thought to add, `1fr 1fr`,
   `1fr 1.35fr`, `1fr 1fr 1fr`, `1fr auto`. Those grids stayed multi-column on a
   390px screen and their right-hand column was cut off: the Careers "Why Join /
   Who Thrives" pair, the partner "How It Works" steps, Contact, the footer, and
   the job cards whose Apply Now button ran off the edge.

   Match any inline grid instead, and name the few that must stay side by side:
     96px 1fr                            icon + text rows (fits, and reads better)
     1fr 72px 1fr / minmax(0,1fr) auto…  the header logo row
     1fr auto 1fr                        top utility bar, the 860px rule turns
                                         it into `1fr auto` (phone + CTA), and
                                         each :not() below adds specificity, so
                                         without this exception the blanket rule
                                         would outrank it and stack the header. */
@media (max-width: 720px) {
  body [style*="grid-template-columns"]:not([style*="grid-template-columns:96px"]):not([style*="grid-template-columns: 96px"]):not([style*="grid-template-columns:1fr 72px"]):not([style*="grid-template-columns:minmax"]):not([style*="grid-template-columns: 1fr auto 1fr"]):not([style*="grid-auto-rows"]):not([style*="grid-template-rows: 260px"]):not([style*="grid-template-rows:260px"]):not([style*="1fr 72px 1fr"]),
  body .fm-s-b88d5f {
    grid-template-columns: 1fr !important;
    direction: ltr !important;
  }

  /* --- Partner Application form --------------------------------------------
     Collapsing the track list above is NOT enough on its own. Several fields
     carry `grid-column: span 2`, and a two-column span inside a one-column
     grid makes the grid generate an *implicit* second column, sized to its
     content, which is why the form still rendered as two ragged columns of
     117px and 145px, with labels wrapping onto three lines. Every child has to
     be pinned back to a single column.
     (The admin has the same note in assets/css/app.css; the public form needed
     it too.) */
  body .fm-s-b88d5f > * {
    grid-column: span 1 !important;
    min-width: 0 !important;
  }

  /* The card around it pads by clamp(32px, 5vw, 56px) = 32px on a phone, which
     with the page's own 24px leaves fields only 278 of 390px. */
  body div[style*="max-width: 680px"][style*="border-radius: 10px"],
  body div[style*="max-width:680px"][style*="border-radius:10px"] {
    padding: 20px !important;
  }

  /* --- Enquiry form field rows -------------------------------------------
     Full Name / Phone sit in a `1fr 1fr` row. The blanket selector above
     matches this element (verified in the browser) but does not win, so the
     row stayed two columns: the phone input's min-content is ~206px, which
     starves the name column down to 54px and wraps its label onto three lines.
     Target the row by the field wrapper it contains, and take the grid out of
     the equation entirely: as a block container each field wrapper is simply a
     full-width box, which no track-sizing rule can starve.
     Scoped to that wrapper alone. It used to also match any grid with an 18px
     gap, which silently caught the Projects filter panel: as a block container
     its `gap` stopped applying, so the three field groups butted together with
     no space at all between a select and the next group's label. */
  body div:has(> .fm-s-5ba2fd) {
    display: block !important;
  }

  body .fm-s-5ba2fd {
    width: 100% !important;
    margin-bottom: 18px !important;
  }

  /* --- Baked-in measurements ---------------------------------------------
     The export writes the *measured* size onto text blocks, `max-width:680px; width:697px; height:202px` on a single <p>. The width
     overflows a phone (so the sentence is cut off mid-word) and the fixed
     height clips the text once it reflows onto more lines. Let both go. */
  body p[style*="width"],
  body p[style*="height"] {
    width: auto !important;
    max-width: 100% !important;
    height: auto !important;
  }

  /* Fixed-width cards and image tiles: the 420px gallery tiles, the 400px
     highlight card and the 360x480 stack card all exceed the viewport. */
  body [style*="width: 420px"],
  body [style*="width:420px"],
  body [style*="width:400px"],
  body [style*="width: 400px"],
  body [style*="width:360px"],
  body [style*="width: 360px"] {
    width: 100% !important;
    max-width: 100% !important;
  }

  body [style*="height: 480px"], body [style*="height:480px"] { height: auto !important; min-height: 320px !important; }
  body [style*="height: 223px"], body [style*="height:223px"] { height: 200px !important; }

  /* --- Trusted Partners ---------------------------------------------------
     A tile is 280 x 150 with a 420 x 223 picture inside it, and the rule above
     only cut the picture down to the tile. On a 360px screen that is one logo
     across 78% of the width, so the marquee read as a slideshow rather than a
     row of partners. Sized so three tiles are on screen at 360px and the
     scroll is legible as a scroll. Desktop is untouched. */
  body .fm-s-e8d928 {
    width: 148px !important;
    height: 82px !important;
    padding: 6px !important;
    margin-right: 6px !important;
  }

  /* The three marquee rows sit in one column with the desktop's 24px between
     them, which on a phone reads as three separate bands rather than one
     scrolling wall of names. Halved, along with the tile padding and the gap
     between tiles above, so the logos read as a group (2026-09-04). The
     container is matched by its own inline style, in both the spelling the
     export writes and the one the runtime re-serialises it to. */
  body div[style*="flex-direction:column"][style*="gap:24px"][style*="overflow:hidden"],
  body div[style*="flex-direction: column"][style*="gap: 24px"][style*="overflow: hidden"] {
    gap: 12px !important;
  }

  /* The picture fills the smaller tile; `background-size: contain` on the
     element itself keeps every logo inside its own box whatever its shape. */
  body .fm-s-e8d928 > [role="img"] {
    width: 100% !important;
    height: 100% !important;
  }

  /* --- The project page's own photograph -----------------------------------
     `height:70vh; min-height:520px` is a portrait frame on a phone: about
     320 x 520 on a 360px screen. The render inside it is the 4:3 landscape
     the admin asks for, and it fills with `cover`, so both sides of the
     building were thrown away and what was left was a tall slice through the
     middle of it (2026-09-06).

     The frame takes the picture's own shape instead. Nothing is cropped, and
     nothing is padded either, because the shape is the one the upload hint
     already specifies. Desktop keeps its 70vh hero. */
  body div[style*="height:70vh"][style*="min-height:520px"],
  body div[style*="height: 70vh"][style*="min-height: 520px"] {
    height: auto !important;
    min-height: 0 !important;
    /* The same 2:1 the desktop frame uses, so the one uploaded photograph is
       whole on a phone too. A different shape here would crop the thing this
       was fixing, just on the other axis. */
    aspect-ratio: 2 / 1 !important;
  }

  /* The identity card below hangs up into that frame. 96px is a sixth of a
     520px hero and nearly half of a 240px one, so it went from an overlap to
     a lid. Enough to still read as one composition, not enough to cover the
     building. */
  body div[style*="margin-top: -96px"],
  body div[style*="margin-top:-96px"] {
    /* -20px against a 2:1 frame, which is about 160px tall on a phone. -40 was
       measured against the 240px the 4:3 frame gave and would now cover a
       quarter of the picture. */
    margin-top: -20px !important;
  }

  /* Nothing should be able to push the page wider than the screen. */
  body section, body footer, body main, body article { max-width: 100vw !important; }

  

  /* --- Residential / Commercial toggle -----------------------------------
     Measured at 360px wide (two buttons at `padding:9px 30px` plus the pill's
     own 4px padding and border), so it ran 14px past a 390px screen and 44px
     past a 360px one, the only element on the whole site still doing that.
     Let the pill fill the width and share it between the two buttons. */
  body div[style*="inline-flex"][style*="999px"] {
    display: flex !important;
    max-width: 100% !important;
  }

  body div[style*="inline-flex"][style*="999px"] > button {
    flex: 1 1 0 !important;
    min-width: 0 !important;
    padding: 9px 12px !important;
    letter-spacing: .1em !important;
  }
}

/* --- Enquiry form label colour ------------------------------------------
   Requested 2026-07-27: every enquiry form's field labels read grey, not gold
   or burgundy. These class names are hashes of the design's own declarations,
   so overriding here (rather than editing the generated site.css) keeps the
   hash, and therefore this override, valid across a design re-export.

     .fm-s-fddb7e  Download Brochure modal        (was gold)
     .fm-s-c1fdbf  Register Your Interest + Contact "Send Us a Message"
     .fm-s-c2a652  Enquiry page "Submit Enquiry" form
*/
.fm-s-fddb7e,
.fm-s-c1fdbf,
.fm-s-c2a652 { color: var(--gray-mid) !important; }

/* --- Footer (mobile) ------------------------------------------------------
   The footer's three columns are declared as a literal `1fr 1fr 1fr`, not the
   `repeat(3,1fr)` the 720px rule above matches, so it stayed three columns all
   the way down and each one squeezed to ~100px. Stack it, and cut the desktop
   padding (88px/80px) and 88px gap, which alone filled most of a phone screen.
   Desktop is untouched, everything here is inside the media query. */
@media (max-width: 720px) {
  body footer div[style*="1fr 1fr 1fr"] {
    grid-template-columns: 1fr !important;
    gap: 34px !important;
  }

  body footer {
    padding: 48px 20px 40px !important;
  }

  /* the logo block's 48px bottom margin on top of the new gap is too much */
  body footer > div:first-child {
    margin-bottom: 28px !important;
  }

  body footer img[alt="Fairmount Builders"] {
    height: 40px !important;
  }

  /* "POWERED BY nexprop.ai" sits outside <footer>; its right padding is
     clamp(56px,10vw,160px), which pushed the logo off a narrow screen. */
  body footer + div {
    padding: 16px 20px !important;
    justify-content: center !important;
  }
}

/* --- Enquire edge tab (mobile) -------------------------------------------
   Fixed to the right edge at 14px/.24em with 24px 12px padding, the tab runs
   about 200px tall on a phone and covers a real slice of the content. Shrink
   the type, tracking and padding; the design's slide-in transform is left
   alone (see the note at the top of this file). */
@media (max-width: 720px) {
  body [data-edge-tab] {
    font-size: 10px !important;
    letter-spacing: .14em !important;
    padding: 14px 7px !important;

    /* At `top:50%` the tab lands in the middle of the right edge, which on a
       phone is the middle of a line of body text, it was covering words
       outright ("...considered f▮r the Fairmount channel partner network").
       Drop it to the corner, just above the round button, where the text
       column has already ended.

       Only `top`/`bottom` are touched: the design slides the tab in with
       translateX on scroll, so overriding `transform` would pin it open. */
    top: auto !important;
    /* The WhatsApp disc owns 84-136px off the floor (refresh.css §6), so 104px
       parked the tab's foot inside it, the two overlapped in the corner
       (2026-08-19). 148px clears the disc by 12. */
    bottom: 148px !important;

    /* ...and rides the same colophon lift as the discs, or they climb into it
       when the footer reaches this corner. `translate`, not `transform`: the
       design slides the tab in with translateX on scroll. */
    translate: 0 calc(-1 * var(--fm-corner-lift, 0px)) !important;
  }
}

/* --- Project identity card ------------------------------------------------
   The card carries a 360px content floor so project logos have room to fill it.
   Below ~520px that floor plus its 96px of padding would exceed the viewport,
   so let it shrink and tighten the padding. */
@media (max-width: 520px) {
  body div[style*="margin-top: -96px"],
  body div[style*="margin-top:-96px"] {
    min-width: 0 !important;
    padding: 24px 20px !important;
  }
}

/* --- Let the document scroll, not <body> ---------------------------------
   The design runtime (support.js) injects its preview-mode FULL_PAGE_CSS:

       html,body{height:100%;margin:0}
       #dc-root,#dc-root>.sc-host{height:100%}

   Pinning html+body to the viewport makes <body> the scroll container, so the
   window never scrolls. Three things break as a result:
     * window.scrollTo(0,0) in nav()/openDetail() does nothing, so changing page
       keeps the previous scroll position (reported 2026-07-28)
     * window.scrollY is always 0, so `body.fm-scrolled` never applies and the
       Enquire edge tab never slides in
     * the sticky sub-nav scroll-spy reads the same always-0 value

   Restore native document scrolling. min-height keeps full-viewport sections
   working. !important is required: the runtime injects its <style> after this
   sheet loads. */
html,
body {
  height: auto !important;
  min-height: 100% !important;
  overflow-y: visible !important;
}

#dc-root,
#dc-root > .sc-host {
  height: auto !important;
  min-height: 100% !important;
}

/* --- Header must not sit on top of the hero ------------------------------
   The export wraps the top bar + nav in `position:fixed; top:0; z-index:50`,
   which takes it out of flow, so every page's first section (the home hero
   video, project hero photos) starts at y=0 and its top ~145px is hidden behind
   the navbar. Requested 2026-07-28: the media should begin below the navbar.

   Sticky rather than a padding offset: the header keeps its space in normal
   flow, so content starts below it at every width (measured 134 to 150px across
   390 to 1920px) with no magic number to keep in sync, and it still pins on scroll.

   The dc-runtime re-writes inline styles through React, which normalises them
   with spaces, match both forms. */
body div[style*="position: fixed"][style*="z-index: 50"],
body div[style*="position:fixed"][style*="z-index:50"] {
  position: sticky !important;
}

/* Full-height hero sections measured 100vh from y=0; now that they start below
   the header, take its height off so they still fit one screen. */
body section[style*="height: 100vh"],
body section[style*="height:100vh"] {
  height: auto !important;
  min-height: calc(100vh - 145px) !important;
}

/* --- Hero video must fill its section ------------------------------------
   The export nudges the hero video `left:1px; top:-10px` while also giving it
   `height:100%`, so the box ends 10px short of the section and a thin strip of
   whatever is behind (the video's poster edge / page background) shows below the
   footage. object-fit:cover means squaring it up costs no cropping quality. */
[data-screen-label="Home hero"] video {
  top: 0 !important;
  left: 0 !important;
}

/* --- Chat ------------------------------------------------------------------
   The site runs one chat: the Nexprop widget loaded at the end of index.html.
   The design export ships its own mock, a floating button whose answers are a
   handful of hardcoded regexes and which sends nothing anywhere, and it sits
   in the same corner. Hidden rather than deleted so a re-export cannot bring
   back a second bubble. */
body [data-mock-chat] { display: none !important; }

/* --- Chat launcher ---------------------------------------------------------
   Size, colour, resting shadow and the pulse all live in refresh.css section 6
   now. The size and shadow that used to be set here were doing real damage: the
   `box-shadow: ... !important` outranked the pulse keyframes, an !important
   declaration beats a CSS animation, so the ring ran and was overruled on
   every frame, and the launcher never appeared to wave at all.

   Only the hover lift is left, which nothing else sets. */
body > button:has(> img[src^="data:image/svg"]) {
  transition: transform .35s cubic-bezier(.25, .1, .25, 1);
}

body > button:has(> img[src^="data:image/svg"]):hover {
  transform: translateY(-4px);
}

/* --- Mobile: hero must match the footage's shape -------------------------
   The hero fills the screen height, so on a phone its box is portrait (390x699,
   ratio 0.56) while the video is 1920x1080 (ratio 1.78). object-fit:cover then
   fills the height and discards ~69% of the frame's width, so the hero crops the
   footage badly, reported 2026-07-28 as the video looking cut.

   Give the hero the video's own 16:9 ratio at narrow widths: cover then has
   nothing to crop, the whole scene is visible, and there are no letterbox bars.
   Desktop is already wider than 16:9 and stays as it is. */
@media (max-width: 860px) {
  /* the [style] term outweighs the section[style*="height:100vh"] rule above,
     which would otherwise keep min-height at calc(100vh - 145px) */
  body section[data-screen-label="Home hero"][style] {
    min-height: 0 !important;
    /* 56.25vw == 9/16 of the viewport width, i.e. exactly the video's 16:9.
       An explicit height rather than aspect-ratio: the hero is a flex item, and
       flex sizing was resolving its height before aspect-ratio could apply. */
    height: 56.25vw !important;
  }
}

/* The hero video has no poster (see the "hero poster dropped" patch in
   mix site.import), so give the section a dark ground rather than letting the
   page's white show through for the second or two before the first frame. */
body section[data-screen-label="Home hero"] { background: #14100f; }

/* --- 720px: Signature Developments deck ----------------------------------
   Only where the grid is a single column. Between 721 and 860px it is still
   two columns wide, and pinning a two-up row would just stack pairs. */
@media (max-width: 720px) {
  /* --- Happy Moments mosaic ------------------------------------------------
     A 1.4fr/1fr/1fr mosaic on 260px rows: one tile spans two rows, another
     spans two columns. Flattened to a single column by the blanket rule above
     it became four full-width 260-540px images, a long stack, not a grid.
     Keep it a grid at two columns and shrink the rows to fit, so the mosaic
     shape survives: tall tile down the left, two stacked beside it, wide tile
     across the bottom. `grid-template-rows: 260px 260px` occurs exactly once
     in the export, so it is a safe anchor (and the reason for the two new
     exclusions in the rule above). */
  body div[style*="grid-template-rows: 260px 260px"],
  body div[style*="grid-template-rows:260px 260px"] {
    grid-template-columns: 1fr 1fr !important;
    grid-template-rows: 34vw 34vw !important;
    grid-auto-rows: 34vw !important;
    gap: 10px !important;
  }

  /* --- Detail pages: top gap ------------------------------------------------
     A fourth route for the same oversized header gap. The list pages pad via a
     section or the screen wrapper; the three *detail* screens each carry their
     own inline padding instead, and all three differ:
       project-detail   padding-top: 150px
       article-detail   padding: 150px 0 88px
       job-detail       padding: 170px 0 100px
     Under the 134px mobile header that is a blank screen above the breadcrumb.
     24px, not the 40px used on list pages: these open with a small breadcrumb
     rather than a centred eyebrow + heading block. */
  body div[style*="padding-top: 150px"],
  body div[style*="padding-top:150px"],
  body div[style*="padding: 150px 0px 88px"],
  body div[style*="padding:150px 0 88px"],
  body div[style*="padding: 170px 0px 100px"],
  body div[style*="padding:170px 0 100px"] {
    padding-top: 24px !important;
  }

  /* --- Segmented toggles: even halves ---------------------------------------
     Overview / Floor Plans on a project, and Residential / Commercial on the
     projects list. The pill is an inline-flex sized to its content, so at phone
     width "FLOOR PLANS" wrapped onto two lines while "OVERVIEW" stayed on one:
     the two halves rendered at different text heights and read as lopsided.
     Full width with equal flex halves gives each label ~167px instead of 99px,
     which is enough to keep both on one line, centred. */
  body div[style*="inline-flex"][style*="border-radius: 999px"],
  body div[style*="inline-flex"][style*="border-radius:999px"] {
    display: flex !important;
    width: 100% !important;
  }

  body div[style*="inline-flex"][style*="border-radius: 999px"] > button,
  body div[style*="inline-flex"][style*="border-radius:999px"] > button {
    flex: 1 1 0 !important;
    white-space: nowrap !important;
    text-align: center !important;
    padding: 11px 8px !important;
  }

  /* --- News & Blogs: one card at a time -------------------------------------
     News ran 20 cards x 486px = 10,028px (~14 screens); Blogs ran 49 cards for
     31,437px (~35 screens). Both tracks become horizontal scroll-snap strips:
     one card fills the viewport width, swiping moves card to card. Native
     scroll-snap does the gesture; the only script involved builds the arrows
     and the "n / total" counter (see the carousel script in index.html and
     mix site.import).
     Anchored on the `repeat(3, 1fr)` cards grid, which is unique inside each of
     these two screens. Not `max-width: 1160px`: on Blogs that matches an outer
     wrapper holding the featured post *and* the grid, which would have swept
     the featured post into the carousel. Both spellings, since the runtime
     re-writes inline styles through React. */
  body [data-screen-label="News & Media"] div[style*="grid-template-columns: repeat(3, 1fr)"],
  body [data-screen-label="News & Media"] div[style*="grid-template-columns:repeat(3,1fr)"],
  body [data-screen-label="Blogs"] div[style*="grid-template-columns: repeat(3, 1fr)"],
  body [data-screen-label="Blogs"] div[style*="grid-template-columns:repeat(3,1fr)"] {
    display: flex !important;
    grid-template-columns: none !important;
    gap: 14px !important;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }

  body [data-screen-label="News & Media"] div[style*="grid-template-columns: repeat(3, 1fr)"]::-webkit-scrollbar,
  body [data-screen-label="Blogs"] div[style*="grid-template-columns: repeat(3, 1fr)"]::-webkit-scrollbar {
    display: none;
  }

  /* one card per screen; flex stretch also evens out their ragged heights */
  body [data-screen-label="News & Media"] div[style*="grid-template-columns: repeat(3, 1fr)"] > *,
  body [data-screen-label="Blogs"] div[style*="grid-template-columns: repeat(3, 1fr)"] > * {
    flex: 0 0 100% !important;
    scroll-snap-align: center !important;
  }

  /* arrows + counter, injected under the track by the carousel script */
  [data-fm-carousel-nav] {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 18px;
    margin-top: 20px;
  }

  [data-fm-carousel-nav] button {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    border: 1px solid var(--gold);
    background: var(--white);
    color: var(--burgundy);
    font-size: 22px;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
  }

  [data-fm-carousel-nav] button[disabled] { opacity: 0.3; }

  [data-fm-carousel-nav] span {
    font-family: var(--font-display);
    font-size: 14px;
    letter-spacing: 0.14em;
    color: var(--gray-mid);
    min-width: 68px;
    text-align: center;
  }

  /* --- Projects filter panel: breathing room --------------------------------
     The heading is 24px on a 1.15 line-height, wraps to two lines on a phone,
     and carries only 12px below it, so "Units" all but touches the
     Residential/Commercial pill. The eyebrow is desktop-sized too (18px at
     0.24em tracking fills the full 302px content width).
     Retune the vertical rhythm rather than move anything: looser heading
     leading, more space under it, less under the controls, and a Search button
     that fills the width instead of floating at 164px.
     Panel is identified by its own inline background + radius; the other
     `max-width: 1060px` element in the export is a plain grid. */
  body div[style*="max-width: 1060px"][style*="border-radius: 10px"],
  body div[style*="max-width:1060px"][style*="border-radius:10px"] {
    padding: 26px 18px !important;
  }

  /* eyebrow */
  body div[style*="max-width: 1060px"][style*="border-radius: 10px"] > div:first-child {
    font-size: 13px !important;
    letter-spacing: 0.18em !important;
    margin-bottom: 6px !important;
  }

  /* heading: 1.15 leading is a desktop single-line setting */
  body div[style*="max-width: 1060px"][style*="border-radius: 10px"] > h2 {
    line-height: 1.32 !important;
    margin-bottom: 22px !important;
  }

  /* the toggle and the field grid give back what the heading takes */
  body div[style*="max-width: 1060px"][style*="border-radius: 10px"] > div:nth-child(3),
  body div[style*="max-width: 1060px"][style*="border-radius: 10px"] > div:nth-child(4) {
    margin-bottom: 22px !important;
  }

  body div[style*="max-width: 1060px"][style*="border-radius: 10px"] > button {
    width: 100% !important;
  }

  /* Field groups: the grid's 18px row gap sat too close to the 7px label-to-
     select gap inside each group, so "Looking For" and "Available Sizes" read
     as captions on the select above them rather than labels for the one below.
     Widen the gap between groups; the label keeps its own tight 7px. */
  body div[style*="max-width: 1060px"][style*="border-radius: 10px"] > div:nth-child(4) {
    row-gap: 28px !important;
  }

  /* --- Milestones: pinned deck ----------------------------------------------
     Moved to refresh.css and applied at every width, the 2026-08 feedback
     asked for the About "Our Journey" section to use the phone's card-deck
     treatment on desktop too. Nothing width-specific is left here. */


  /* --- Vision, Mission & Ethos: timeline -----------------------------------
     Each item is a `96px 1fr` grid: icon column with a dashed connector line,
     copy beside it. The blanket single-column rule was flattening it, which
     centred the icon over left-aligned text and left the connector dangling in
     mid-page (the rule's own `96px` exception above never matched, because it
     was spelled without the space the runtime renders). Keep the two columns
     and scale the furniture down: 48px icon column, 46px circle, 22px glyph. */
  body div[style*="grid-template-columns: 96px"],
  body div[style*="grid-template-columns:96px"] {
    grid-template-columns: 48px 1fr !important;
    gap: 16px !important;
  }

  body div[style*="width: 65px"][style*="border-radius: 50%"],
  body div[style*="width:65px"][style*="border-radius:50%"] {
    width: 46px !important;
    height: 46px !important;
  }

  body div[style*="width: 65px"][style*="border-radius: 50%"] svg,
  body div[style*="width:65px"][style*="border-radius:50%"] svg {
    width: 22px !important;
    height: 22px !important;
  }

  /* the copy column's desktop 40-60px bottom gutter is most of a phone screen */
  body div[style*="grid-template-columns: 96px"] > div:last-child,
  body div[style*="grid-template-columns:96px"] > div:last-child {
    padding-bottom: 26px !important;
  }

  /* section intro: 22px body copy and a 21px 0.3em-tracked eyebrow are desktop
     sizes, they wrap to four and two lines respectively on a phone */
  body section:has(div[style*="grid-template-columns: 96px"]) p[style*="font-size: 22px"] {
    font-size: 17px !important;
    line-height: 1.65 !important;
  }

  body section:has(div[style*="grid-template-columns: 96px"]) span[style*="letter-spacing: 0.3em"] {
    font-size: 14px !important;
  }

  /* --- Leadership cards ----------------------------------------------------
     Three portrait cards stacked vertically ran ~1800px, two and a half
     screens for three people. Turn each card on its side instead: a small
     portrait beside the name, so the whole section fits one screen.
     Anchored on the portrait wrapper's `aspect-ratio: 4/5`, which appears
     exactly once in the export, so it needs no page or nth-child scoping.
     Both spellings: the raw export writes `4/5`, the runtime re-writes inline
     styles through React, which spaces it to `4 / 5`. */
  body div[style*="aspect-ratio: 4 / 5"],
  body div[style*="aspect-ratio:4/5"] {
    flex: 0 0 128px !important;
    width: 128px !important;
    border-radius: 10px !important;
  }

  body div:has(> div[style*="aspect-ratio: 4 / 5"]),
  body div:has(> div[style*="aspect-ratio:4/5"]) {
    flex-direction: row !important;
    align-items: center !important;
    gap: 14px !important;
    padding: 10px !important;
  }

  /* the name/role block: left-aligned now that it sits beside the portrait
     rather than centred beneath it */
  body div:has(> div[style*="aspect-ratio: 4 / 5"]) > div:last-child,
  body div:has(> div[style*="aspect-ratio:4/5"]) > div:last-child {
    align-items: flex-start !important;
    text-align: left !important;
    padding: 0 4px 0 0 !important;
  }

  /* --- Signature Developments: one card at a time -------------------------
     Each project card is pinned just below the sticky 134px header, so it
     holds its place while the next card scrolls up over it, the deck stays
     put and the projects change, rather than the page running past a list.
     Plain `position: sticky` rather than scroll-driven JS: it is symmetric
     going back up for free, needs no scroll hijacking, and cannot desync.
     Later siblings paint over earlier ones at the same z-index, so DOM order
     already gives the incoming card the top layer. The cards are opaque white
     with `overflow: hidden`, so nothing shows through the one underneath. */
  /* A sticky grid item is clamped to its own grid area, and the export's rows
     are exactly one card tall, so sticky alone did nothing. Give each row
     room to scroll through: one screen (100vh) per project, ~513px card, so a
     card holds the slot alone for ~330px of scrolling before the next slides
     up over it.
     align-self is mandatory: a grid item defaults to stretch, which would
     inflate the card itself to the full 88vh row. */
  body [data-screen-label="Home"] div:has(> a.fm-s-7334c5) {
    grid-auto-rows: 100vh !important;
    gap: 0 !important;
  }

  body [data-screen-label="Home"] a.fm-s-7334c5 {
    position: sticky !important;
    top: 146px;
    align-self: start !important;
    /* the export's shadow is barely there (5% alpha); lift it so the incoming
       card reads as sliding *over* the pinned one rather than merging with it */
    box-shadow: 0 -6px 18px rgba(44, 44, 44, 0.10), 0 2px 10px rgba(44, 44, 44, 0.06) !important;
  }

  /* --- Built on Purpose: the same deck -------------------------------------
     Vision / Mission / Ethos are three tall cards, image, heading, statement
     and a paragraph each. Stacked one under the other on a phone that is well
     over 2,000px of scrolling for three ideas, and the section reads as a list
     rather than three equal statements.

     Same treatment as Signature Developments above: one screen per card, each
     pinned under the header while the next slides over it, and symmetric on the
     way back up because it is plain `position: sticky` rather than scroll JS.

     Matched on the card's own shape, `grid-row: span 3` with a subgrid, which
     only these three cards use, since neither the grid nor the cards carry a
     class of their own. The dc-runtime rewrites inline styles through React and
     normalises the spacing, so both spellings are listed. */
  body div:has(> sc-for > div[style*="grid-row:span 3"]),
  body div:has(> sc-for > div[style*="grid-row: span 3"]),
  body div:has(> div[style*="grid-row:span 3"][style*="subgrid"]),
  body div:has(> div[style*="grid-row: span 3"][style*="subgrid"]) {
    grid-auto-rows: 100vh !important;
    gap: 0 !important;
  }

  body div[style*="grid-row:span 3"][style*="subgrid"],
  body div[style*="grid-row: span 3"][style*="subgrid"] {
    position: sticky !important;
    top: 146px;
    align-self: start !important;
    /* the cards are white on an off-white band, so without a lift the incoming
       card merges into the pinned one instead of sliding over it */
    box-shadow: 0 -6px 18px rgba(44, 44, 44, 0.10), 0 2px 10px rgba(44, 44, 44, 0.06) !important;
  }

  /* The card's own rows are a subgrid of a container we have just turned into
     100vh rows, which would stretch each card to a full screen. Give the card
     back its natural height. */
  body div[style*="grid-row:span 3"][style*="subgrid"],
  body div[style*="grid-row: span 3"][style*="subgrid"] {
    grid-template-rows: auto auto auto !important;
    grid-row: auto !important;
  }
}

/* --- About → Leading the Vision ------------------------------------------
   The design's three 4:5 portrait cards, stacked full-width by the blanket
   single-column rule above, ran ~550px each, the section became a wall you
   scroll past rather than read. Kept one-per-row as asked, but at the smaller
   card size: 78% of the screen, centred, with a square crop, so a whole card
   (portrait, name, role) lands inside one screen and the next one is already
   showing at the fold. */
@media (max-width: 720px) {
  body [data-founders] {
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    grid-template-columns: none !important;
    gap: 20px !important;
  }

  body [data-founders] > div {
    width: 78%;
    max-width: 340px;
  }

  body [data-founders] > div > div:first-child { aspect-ratio: 1 / 1 !important; }

  /* the name is 20px display type with .12em tracking, at this card width
     "Nagender Reddy" wrapped mid-name */
  body [data-founders] > div > div:last-child { padding: 20px 16px 24px !important; }
  body [data-founders] > div > div:last-child > div:nth-child(2) { font-size: 18px !important; }
  body [data-founders] > div > div:last-child > div:last-child { font-size: 13px !important; }
}

/* --- 720px: the page banner ------------------------------------------------
   Added with the banners themselves (2026-08-13). At 390px the design's
   `min-height: clamp(420px,52vh,560px)` plus its bottom padding filled the whole
   first screen: under a 134px header, the breadcrumb landed at the halfway mark
   and the reader met a photograph and nothing else. It also sets its own type
   sizes to 76px headline, 20px standfirst, which are desktop figures.

   Everything here is a size, not a rearrangement: same breadcrumb, eyebrow,
   headline, rule and standfirst, in the same order, at phone scale. */
@media (max-width: 720px) {
  body [data-page-banner] {
    min-height: 300px !important;
  }

  body [data-page-banner] > div:last-child {
    padding: 0 20px 34px !important;
    gap: 12px !important;
  }

  /* the breadcrumb: 15px tracked .16em is most of a line at this width */
  body [data-page-banner] > div:last-child > div:first-child {
    font-size: 12px !important;
    letter-spacing: 0.12em !important;
  }

  /* the eyebrow */
  body [data-page-banner] > div:last-child > div:nth-child(2) {
    font-size: 13px !important;
    letter-spacing: 0.2em !important;
  }

  body [data-page-banner] h1 {
    font-size: clamp(28px, 8.4vw, 40px) !important;
    line-height: 1.14 !important;
  }

  body [data-page-banner] p {
    font-size: 15px !important;
    line-height: 1.6 !important;
  }
}

/* The scrim. The design's mid-stop is rgba(44,44,44,.46), tuned for a banner
   560px tall where the copy sits in the dark lower third. At 264px the whole
   block sits in that mid band, and "GET IN TOUCH", gold, on a photograph of a
   sunlit facade, could not be read at all. Deeper here only: the desktop
   banner is unchanged. */
@media (max-width: 720px) {
  body [data-page-banner] > div:nth-child(2) {
    background: linear-gradient(
      180deg,
      rgba(28, 28, 28, 0.62) 0%,
      rgba(28, 28, 28, 0.58) 45%,
      rgba(28, 28, 28, 0.88) 100%
    ) !important;
  }
}

/* --- 720px: the space a banner page opens with -----------------------------
   Those pages carry `padding: 96px … 112px` inline, a desktop rhythm. Under a
   264px banner it reads as a blank screen between the header and the first
   words. Halved top and bottom; the horizontal padding is a clamp that already
   resolves to 24px here and is left alone. */
@media (max-width: 720px) {
  body div[style*="padding:96px clamp(24px,4vw,56px) 112px"],
  body div[style*="padding: 96px clamp(24px, 4vw, 56px) 112px"],
  body section[style*="padding:96px clamp(24px,4vw,56px) 128px"],
  body section[style*="padding: 96px clamp(24px, 4vw, 56px) 128px"],
  body section[style*="padding:96px 24px 112px"],
  body section[style*="padding: 96px 24px 112px"],
  body section[style*="padding:96px 0 112px"],
  body section[style*="padding: 96px 0px 112px"] {
    padding-top: 40px !important;
    padding-bottom: 56px !important;
  }
}

@media (max-width: 480px) {
  body [data-page-banner] {
    min-height: 264px !important;
  }
}

/* --- 720px: page intro blocks ----------------------------------------------
   Careers and Contact open on a centred heading and a standfirst sized for a
   1,440px column, a 44px heading and 22px body. On a 390px screen "Build Your
   Career With Fairmount Builders" ran to four lines of 44px type and the
   paragraph below it to eight, so the page read a size larger than every other
   one. The desktop figures are untouched; these are the phone equivalents.

   The `width`/`height` pair the design tool wrote on those paragraphs also goes
   here: a fixed width is a horizontal scrollbar waiting to happen at 390px, and
   the height became a min-height in the markup so editable copy can grow. */
@media (max-width: 720px) {
  /* Any section heading, not only one that is a direct child of its section
     (2026-09-02). `section > h2` missed the two that sit a wrapper deeper: the
     milestone band's "Before a portfolio, there was a promise, and we kept it
     fast." and "Built on Purpose". Both stayed at the clamp's 32px floor while
     every other heading came down to 6.6vw, and on a 390px screen that sentence
     ran to six lines and read a size larger than the page around it. */
  /* The magazine flipbook, which had 223px of height to work in (2026-09-02).
     The embed is 16/11, which at the desktop band's 1134px is a comfortable
     two-page spread. On a 390px screen the same shape is 324x223, and Heyzine
     responds by drawing one tiny portrait page plus its own toolbar and a
     scrollbar inside that strip: the reported "this got fucked up".

     A magazine page is portrait, and a phone gets one page rather than a spread,
     so the box is portrait here. 3/4 gives 324x432, enough for the page and the
     viewer's own chrome under it. The desktop 16/10 rule lives in refresh.css
     under `min-width: 861px`, so the two cannot fight. */
  body section[data-magazine] [style*="aspect-ratio:16/11"],
  body section[data-magazine] [style*="aspect-ratio: 16/11"],
  body section[data-magazine] [style*="aspect-ratio: 16 / 11"] {
    aspect-ratio: 3 / 4 !important;
  }

  /* The F-Desk lead story's picture, which was cropping half its own artwork
     (2026-09-02). The frame carries an inline `min-height:340px`: at the desktop
     card's 607px that is a 16:9 box, but the card narrows to ~324px on a phone
     while the 340px stays, so the box becomes 0.95 and `cover` threw away 46.7%
     of the width. The reported symptom was "THE NEXT BIG BET" reading as "E NEXT
     BIG BE".

     The shape is stated rather than the height, so it holds at any width, and it
     is the same 16:9 the grid cards below it already use. Only one element in the
     export carries that min-height, so this cannot reach anything else. */
  body div[style*="min-height:340px"],
  body div[style*="min-height: 340px"] {
    min-height: 0 !important;
    aspect-ratio: 16 / 9 !important;
  }

  body h2.fm-s-577089,
  body section > .fm-s-56fed7 > h2 {
    font-size: clamp(24px, 6.6vw, 30px) !important;
    line-height: 1.24 !important;
  }

  body p[style*="width: 697px"],
  body p[style*="width:697px"],
  body p[style*="width: 712px"],
  body p[style*="width:712px"] {
    width: auto !important;
    min-height: 0 !important;
    font-size: 15px !important;
    line-height: 1.65 !important;
    margin-top: 14px !important;
  }
}

/* --- Touch: a hover state that sticks ---------------------------------------
   On a phone `:hover` latches after a tap and stays until you tap elsewhere.
   The runtime writes each `style-hover` attribute out as a real `:hover` rule,
   and several of them change only the background, the foreground is left to the
   element's own inline style. Burgundy on burgundy: "View All Projects" lost its
   type, and the footer's WhatsApp badge lost its icon, both of them after an
   ordinary tap.

   Keyed on `(hover: none)`, so a mouse keeps every hover state exactly as it is.
   The runtime's rules carry `!important`, hence the same here plus a `body`
   prefix to outrank them. */
@media (hover: none) {
  /* the round social badges, header and footer */
  body .fm-s-76db03:hover,
  body [data-top-socials] a:hover {
    background: var(--white) !important;
    border-color: var(--light-gray) !important;
    color: var(--burgundy) !important;
  }

  body .fm-s-76db03:hover svg,
  body [data-top-socials] a:hover svg {
    color: var(--burgundy) !important;
  }

  /* outline buttons: burgundy type inside a burgundy hairline, on nothing */
  body a[style*="border:1px solid var(--burgundy)"]:hover,
  body button[style*="border:1px solid var(--burgundy)"]:hover,
  body a[style*="border: 1px solid var(--burgundy)"]:hover,
  body button[style*="border: 1px solid var(--burgundy)"]:hover {
    background: transparent !important;
    color: var(--burgundy) !important;
  }
}

/* --- 720px: what runs while you scroll -------------------------------------
   Reported as lag on a phone (2026-08-13). Measured with the CPU throttled 4x:
   Home's median frame was 300ms against Privacy's 33ms, so the cost was in what
   Home renders, not in the site's scripts.

   Two things, both animating for ever:

     * three Trusted Partners marquee tracks, each 10,944px wide and 112px tall.
       That is 33,000px of strip being composited continuously behind a 390px
       viewport. The rows are already stacked into a grid at this width, so the
       travel is not even visible, it was pure cost.
     * a 24s zoom on the hero, which on a phone is applied to a *playing video*:
       every frame the decoder produces has to be re-composited through a
       changing transform.

   Both are desktop flourishes. The partner logos still scroll by hand.
   `will-change: transform` goes with them: it pins a compositing layer for each
   of a dozen cards, which is memory a phone would rather spend on the page. */
/* The Trusted Partners marquee keeps running on a phone. It was stopped here as
   part of the scroll-cost pass above, and then stopped from 860px as well when
   "in the mobile view they are moving" read as unwanted motion, it was not
   (clarified 2026-08-19: "they should scroll right"). The band is the one place
   on the site where continuous movement is the point, so it travels at every
   width and pays the frames; `will-change` is still dropped below, which is the
   part of that cost a phone can do without.

   Nothing else needs saying: the design's own animation is left alone, and the
   wrapper keeps its overflow and mask, which is what makes the loop seamless. */

@media (max-width: 720px) {
  body video {
    animation: none !important;
  }

  body [style*="will-change"],
  body [data-ms-card],
  body [data-ms-pin] {
    will-change: auto !important;
  }
}
