/* BAND GATING — hand-written, and deliberately OUTSIDE site/public/styles/.
 *
 * tools/port-css.mjs begins with `rm -rf site/public/styles`, which is correct (a
 * re-run must not leave stale hashed sheets behind) and which silently deletes any
 * hand-written sheet placed in the same folder. On one site that removed the very
 * sheet that hides the inactive device bands, and ALL THREE headers then rendered
 * at every width with no error anywhere (gotcha 49). Hence /gm/.
 *
 * ---------------------------------------------------------------------------
 * 1. HIDING THE INACTIVE BANDS
 *
 * Duda emits a PER-WIDGET `!important` display rule for every widget on the site:
 *     #dm .dmBody div.u_1213107879 { display: block !important }
 * A gate written `.mg-only-t { display:none !important }` is (0,1,0) and LOSES to
 * that (1,2,1) — both are !important, so specificity decides, and all three
 * variants paint at once (measured elsewhere at 77.4% of a page, +10,458px).
 *
 * So the class is REPEATED behind #dm to clear it on class count without depending
 * on source order, and only the INACTIVE bands are hidden, inside the media
 * queries. Hiding all three and restoring one with `display: revert` would revert
 * past the author cascade to the UA default and replace the widget's real display
 * value with a plain `block` (gotcha 70).
 *
 * NOTE: band elements are PRUNED from the DOM by __mg.band_prune() before paint,
 * so these rules are a belt-and-braces guard for the window before that runs and
 * for any element the prune cannot remove. They are not the primary mechanism.
 */
@media (max-width: 767px) {
  #dm .mg-only-d.mg-only-d.mg-only-d,
  #dm .mg-only-t.mg-only-t.mg-only-t { display: none !important; }
}
@media (min-width: 768px) and (max-width: 1024px) {
  #dm .mg-only-d.mg-only-d.mg-only-d,
  #dm .mg-only-m.mg-only-m.mg-only-m { display: none !important; }
}
@media (min-width: 1025px) {
  #dm .mg-only-t.mg-only-t.mg-only-t,
  #dm .mg-only-m.mg-only-m.mg-only-m { display: none !important; }
}

/* ---------------------------------------------------------------------------
 * 2. THE WRAPPER CHAIN FORKS BY DEPTH ON THIS SITE, AND THAT IS WHY THIS EXISTS.
 *
 * Censused over all 57 pages x 3 devices, every count 0/57 or 57/57:
 *
 *   desktop : .dmLayoutWrapper > div > #iscrollBody > #site_content > [content]
 *   tablet  : .dmLayoutWrapper > #site_content > .site_content > [content]
 *   mobile  : .dmLayoutWrapper > #site_content > .site_content > [content]
 *
 * #iscrollBody is 57/0/0 and .site_content is 0/57/57. So desktop has TWO levels
 * the hamburger bands do not, and they have ONE that desktop does not. We serve
 * ONE document, so the union has to be emitted and the surplus neutralised.
 *
 * `display: contents` is used rather than a bare pass-through div because a
 * pass-through STILL GENERATES A BOX, and gotcha 21's addendum is a measured case
 * of exactly that costing 1/64 px: an extra level above the content holder made
 * `.site_content`'s margin resolve one LayoutUnit lower than live's and flipped
 * glyph rounding for the whole document below it. An element with
 * `display: contents` generates NO box, so its children's margins interact
 * directly with the grandparent — which is precisely "as if the element were not
 * there", and is what makes the depth fork exactly reproducible instead of
 * approximately.
 *
 * The band attribute is set on <html> by the first inline script in <head>, so
 * these rules match before the wrapper chain is even parsed.
 */
html[data-mg-band="t"] .mg-chain-d,
html[data-mg-band="m"] .mg-chain-d { display: contents !important; }

html[data-mg-band="d"] .mg-chain-tm { display: contents !important; }

/* ---------------------------------------------------------------------------
 * 3. THE WITHHELD BLOG CARDS
 *
 * Duda's blog widget serves ONE page of posts and fetches the rest from its
 * backend: measured here, `data-paginate-total-elements="29"` against
 * `visible-items="10"`, so 19 of 29 posts are unreachable from a static build
 * (gotcha 83). The same is true of every POST's related-posts grid — 30 pages
 * withhold cards on this site, not one. build-pages.py therefore drives live's own
 * numbered pager, ships every card, and stamps the ones live does not paint
 * initially with `mg-blog-hidden` + `data-mg-blog-page="N"`; runtime.js reveals
 * them a page at a time, in live's own batch size.
 *
 * THE RULE THAT ACTUALLY HIDES THEM WAS MISSING, and nothing said so. The class
 * was added by the builder and toggled by the runtime, but it is OUR invention —
 * it appears in no ported Duda sheet, and the previous client's hand-written
 * override sheet is not in this repo. So all 29 cards painted on every one of the
 * 30 pages. Measured: the built /blog carried 116 .postArticle against live's 10,
 * and the first gate sweep scored /blog 61.1% / 75.9% / 56.9% at 375/768/1440 and
 * every blog POST ~34-38% at 1440, while service pages were at 0.000%.
 *
 * SPECIFICITY IS DELIBERATE, not decorative. Duda emits a per-widget
 * `#dm .dmBody div.u_NNNNNN{display:block!important}` for every widget on the
 * site, which is (1,2,1) and !important — a plain `.mg-blog-hidden{display:none
 * !important}` is (0,1,0) and LOSES, leaving every card painted with nothing in
 * the console (gotcha 70). The class is repeated behind #dm to reach (1,3,0) and
 * win on class count without depending on source order.
 */
#dm .mg-blog-hidden.mg-blog-hidden.mg-blog-hidden { display: none !important; }

/* GOTCHA 69 DOES NOT FIRE ON THIS SITE, AND THAT IS MEASURED RATHER THAN ASSUMED.
 *
 * Shipping hidden siblings after the last visible card breaks any positional
 * selector Duda hangs off the list. Every such rule in the ported cascade is
 * `#dm [blog-posts-feature-flag=true][list-layout=recent_posts][posts-padding="N"]
 * .postArticle:not(:last-child){padding-bottom:Npx}` — scoped to the
 * `recent_posts` layout. This site's widget declares `list-layout="layout4"` and
 * `posts-padding="10"`, so none of them can match, and a search for any
 * :last-child / :first-child / :nth-child rule reaching a layout4 card returns
 * nothing.
 *
 * `.lastArticle{margin-bottom:0!important}` DOES apply. Live stamps it on the
 * 10th card — the last one it paints — and our build stamps it in the same place,
 * because the extra cards are appended AFTER it. So the initial render is correct
 * without an override; runtime.js moves the stamp as each batch is revealed, which
 * is what Duda's own runtime does.
 */

/* ---------------------------------------------------------------------------
 * 4. THE HONEYPOT
 *
 * Duda sites rely on reCAPTCHA for spam protection and we REMOVE that widget
 * (gotcha 17 — the keys are Duda's own and domain-restricted, so they cannot work
 * on the client's domain), which would leave every migrated form with no
 * protection at all. build-pages.py therefore adds one hidden decoy input per
 * form; site/functions/api/lead.ts drops any submission that fills it, ahead of
 * the webhook forwarding, and returns 200 so a bot does not learn to retry.
 *
 * IT MUST COST ZERO LAYOUT, AND WITHOUT THIS RULE IT DID NOT. `.mg-hp` is our own
 * class and no ported Duda sheet styles it, so the input rendered as an ordinary
 * 40px text field inside the form. Measured on /contact-us @375: our form was
 * 546px against live's 500px and the document 2286 against 2240 — a +46px surplus
 * that read as a layout defect and was our own spam trap.
 *
 * position:absolute, NOT display:none: bots skip obviously-hidden fields, and
 * taking it out of flow is what makes it free. The markup already carries
 * tabindex="-1", autocomplete="off" and aria-hidden="true", so it is not
 * reachable by keyboard, not autofilled and not announced.
 */
.mg-hp {
  position: absolute !important;
  left: -9999px !important;
  top: auto !important;
  width: 1px !important;
  height: 1px !important;
  overflow: hidden !important;
  opacity: 0 !important;
  pointer-events: none !important;
  margin: 0 !important;
  padding: 0 !important;
  border: 0 !important;
}
