/* ============================================================================
 * wereno-products.css — shared base for the three AI-product surfaces:
 *   .rb        /renobot            (see wereno-renobot.css)
 *   .hm        /handyman           (see wereno-handyman.css)
 *   .wr-prod   homepage section    (see wereno-homeproducts.css)
 *
 * This file owns ONLY what all three share. Each surface's own rules live in
 * its own stylesheet under its own namespace, so the three can never collide.
 *
 * Four things here exist because the theme fights us:
 *
 *  1. Buttons. The theme's base rule is `.elementor-kit-8 .elementor-button
 *     .elementor-button` — specificity (0,4,0) — plus `.elementor-kit-8
 *     [type="submit"]` which paints ANY submit control #7CD656. So we never use
 *     .elementor-button; .wr-btn is scoped `body.elementor-kit-8` to outrank the
 *     submit rule regardless of source order. Geometry is copied from the
 *     theme's own measured desktop button so it still looks native.
 *
 *  2. Body copy is 16px in the theme (--uicore-typography--p-s), not 18px. The
 *     18px everybody samples off the homepage comes from per-element overrides
 *     inside post-136.css, which these pages deliberately do not link. So 18/1.8
 *     is set explicitly here or the product copy renders a size smaller than the
 *     section above it.
 *
 *  3. h2 line-height is 1.4, not the h1's 1.1. A 48px h2 at 1.1 reads as a
 *     different website.
 *
 *  4. Hard offset shadows, zero blur (0 8px 0 0 / 0 4px 0 0) and #000000E6
 *     borders are the theme's signature. Never a blurred shadow, never #000.
 * ========================================================================== */

/* ---------------------------------------------------------------- tokens -- */
:root{
  /* Renobot — sampled from the supplied logo artwork, not invented */
  --rb-amber:#FDC313;        /* robot hard hat — primary */
  --rb-yellow:#FEDC16;       /* wordmark */
  --rb-deep:#F7B001;         /* hat shadow — hover, rules */
  --rb-field:#FFF4D6;        /* pale band */
  /* Eyebrow only. #F7B001 handwriting on a pale ground measures 1.5:1 — Nanum Pen
     Script is a thin script face and at that ratio it is genuinely hard to read.
     #A66A00 is the lightest amber that clears 3:1 on all three grounds this page
     uses (#DEE8E8 / #FFF4D6 / #FFFFFF) and it keeps the hue. Handyman's eyebrow
     already passes everywhere, which is the precedent — the two pages should not
     differ in legibility. On the dark band the eyebrow reverts to --rb-amber,
     which has plenty of contrast there. */
  --rb-eyebrow:#A66A00;

  /* Handyman — olive-sage, from the robot body */
  /* Handyman is red. The four values keep sage's LUMINANCE positions exactly, so
     only the hue moves and every contrast relationship the design already relied
     on survives: primary 0.216 (sage 0.405 — see the note below), light 0.585
     against sage's 0.609, deep 0.049 against 0.116, field 0.851 against 0.855.
     --hm-red is renamed rather than left as --hm-green, because a token named for
     a hue it no longer holds is a trap; --light, --deep and --field are named for
     their position and stay correct. */
  --hm-red:#FF003F;          /* primary */
  --hm-light:#FFB3C4;        /* highlight, and eyebrow text on the dark bands */
  --hm-deep:#B3002C;         /* shadow — hover, rules */
  --hm-field:#FFE8ED;        /* pale band */

  /* shared */
  --wr-cream:#FBF6EF;        /* both robots' off-white — type on dark bands */
  /* The reader's own message, in the blue every phone uses for it. Deepened from
     iMessage's #007AFF, which carries white text at only 4.02:1; this is 5.27:1
     and still unmistakably that blue. */
  --wr-blue:#0B69D4;
  --wr-ink:#141414;
  --wr-body:rgba(20,20,20,.7);
  --wr-dark:#272727;
  --wr-ground:#DEE8E8;        /* WeReno's own, under the house green */
  --wr-prod-ground:#E2E2E2;   /* the product pages, see the note at the foot */
  --wr-line:#000000E6;
  --wr-green:#7CD656;        /* WeReno house green — underlines only, never a product button */
  --wr-shadow:0 8px 0 0 rgba(0,0,0,.9);
  --wr-shadow-sm:0 4px 0 0 rgba(0,0,0,.9);
}

/* ------------------------------------------------------------ typography -- */
.rb,.hm,.wr-prod{font-family:"Outfit",sans-serif;color:var(--wr-ink)}

.rb p,.hm p,.wr-prod p,
.rb .wr-body,.hm .wr-body,.wr-prod .wr-body{
  font-size:18px;line-height:1.8;color:var(--wr-body);margin:0 0 16px}
.rb p:last-child,.hm p:last-child,.wr-prod p:last-child{margin-bottom:0}

.rb h2,.hm h2,.wr-prod h2{
  font-family:"Outfit",sans-serif;font-size:48px;font-weight:500;line-height:1.4;
  letter-spacing:-.027em;color:var(--wr-ink);margin:0 0 16px}
.rb h3,.hm h3,.wr-prod h3{
  font-family:"Outfit",sans-serif;font-size:24px;font-weight:500;line-height:1.4;
  letter-spacing:-.022em;color:var(--wr-ink);margin:0}
.rb h1,.hm h1{
  font-family:"Outfit",sans-serif;font-size:72px;font-weight:500;line-height:1.1;
  letter-spacing:-.027em;color:var(--wr-ink);margin:0 0 24px}

/* The theme's handwriting eyebrow. Handyman also uses it for captions; Renobot
   uses it for eyebrows only — that split is part of the identity. */
.wr-eyebrow{
  font-family:"Nanum Pen Script",cursive;font-size:24px;line-height:1.2;
  font-weight:400;color:var(--wr-green);margin:0 0 8px;display:block}
.rb .wr-eyebrow{color:var(--rb-eyebrow)}
.hm .wr-eyebrow{color:var(--hm-deep)}
.wr-hand{font-family:"Nanum Pen Script",cursive;font-size:22px;line-height:1.3;
  color:var(--wr-body)}

/* Renobot's "command" register: 11px uppercase. Handyman never uses it for
   content labels — only the shared Example badge does. */
.wr-micro{
  font-family:"Outfit",sans-serif;font-size:11px;font-weight:500;line-height:1.4;
  text-transform:uppercase;letter-spacing:.08em;color:var(--wr-ink)}

@media(max-width:1024px){
  .rb h1,.hm h1{font-size:48px}
  .rb h2,.hm h2,.wr-prod h2{font-size:34px}
  .rb h3,.hm h3,.wr-prod h3{font-size:21px}
  .rb p,.hm p,.wr-prod p,.rb .wr-body,.hm .wr-body,.wr-prod .wr-body{font-size:17px}
}
@media(max-width:767px){
  .rb h1,.hm h1{font-size:40px}
  .rb h2,.hm h2,.wr-prod h2{font-size:26px}
  .rb p,.hm p,.wr-prod p,.rb .wr-body,.hm .wr-body,.wr-prod .wr-body{font-size:16px}
  .wr-eyebrow{font-size:21px}
}

/* --------------------------------------------------------------- layout -- */
.wr-inner{width:95%;max-width:1176px;margin-inline:auto}
.rb section,.hm section{padding:48px 0}
.rb .wr-sec--hero,.hm .wr-sec--hero{padding:110px 0 64px}
.rb .wr-sec--tight,.hm .wr-sec--tight{padding:28px 0}
@media(max-width:1024px){
  .rb section,.hm section{padding:36px 0}
  .rb .wr-sec--hero,.hm .wr-sec--hero{padding:88px 0 52px}
}
@media(max-width:767px){
  .rb section,.hm section{padding:26px 0}
  .rb .wr-sec--hero,.hm .wr-sec--hero{padding:64px 0 32px}
  .rb .wr-sec--tight,.hm .wr-sec--tight{padding:20px 0}
}

html{scroll-behavior:smooth}
.rb [id],.hm [id]{scroll-margin-top:100px}
@media(max-width:767px){.rb [id],.hm [id]{scroll-margin-top:80px}}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}}

/* Dark band. The 6px accent rule on the top edge replaces the hazard stripe
   that was cut — the theme has exactly two gradients and both are flat 180deg
   seam fades, so a 45deg barber pole would have been the most off-theme object
   on either page. */
.wr-band{background:var(--wr-dark);position:relative}
.wr-band::before{content:"";position:absolute;top:0;left:0;right:0;height:6px;z-index:0}
/* The accent rule is absolutely positioned, so without this it paints OVER any
   in-flow content — and the whole point of these bands is a card straddling the
   seam. It drew a 6px line straight through Handyman's early-access form. */
.wr-band > *{position:relative;z-index:1}
.rb .wr-band::before{background:var(--rb-amber)}
.hm .wr-band::before{background:var(--hm-red)}
.wr-band h2,.wr-band h3{color:#fff}
.wr-band p,.wr-band .wr-body{color:rgba(251,246,239,.7)}
.rb .wr-band .wr-eyebrow{color:var(--rb-amber)}
.hm .wr-band .wr-eyebrow{color:var(--hm-light)}
.wr-band .wr-micro{color:var(--wr-cream)}

/* Pale identity band. */
.rb .wr-field{background:var(--rb-field)}
.hm .wr-field{background:var(--hm-field)}

/* ---------------------------------------------------------------- cards -- */
.wr-card{
  background:#fff;border:3px solid var(--wr-line);border-radius:16px;
  box-shadow:var(--wr-shadow)}
.wr-card--sm{border-width:2px;border-radius:12px;box-shadow:var(--wr-shadow-sm)}
@media(max-width:1024px){.wr-card{border-radius:14px}}
@media(max-width:767px){.wr-card{border-radius:12px}}
/* Cards never respond to hover: the theme's card hover is a colour change and
   a lift would fight the hard shadow. Buttons and links hover; cards don't. */

/* --------------------------------------------------------------- buttons -- */
body.elementor-kit-8 .wr-btn{
  display:inline-block;font-family:"Outfit",sans-serif;font-size:16px;
  font-weight:500;line-height:1em;color:var(--wr-ink);padding:16px 24px;
  border:1px solid rgba(194,194,194,.15);border-radius:8px;text-decoration:none;
  cursor:pointer;transition:background-color .2s ease;text-align:center}
body.elementor-kit-8 .rb .wr-btn,body.elementor-kit-8 .wr-btn--rb{background:var(--rb-amber)}
body.elementor-kit-8 .rb .wr-btn:hover,body.elementor-kit-8 .rb .wr-btn:focus,
body.elementor-kit-8 .wr-btn--rb:hover,body.elementor-kit-8 .wr-btn--rb:focus{background:var(--rb-deep)}
body.elementor-kit-8 .hm .wr-btn,body.elementor-kit-8 .wr-btn--hm{background:var(--hm-red)}
/* Opsonic. The orange is sampled from the supplied logo art, and it carries ink
   at 5.81:1; the deep shade does not, so hover flips to cream the same way
   Handyman's and Renobot's do. */
body.elementor-kit-8 .wr-btn--op{background:#FD6E00}
body.elementor-kit-8 .wr-btn--op:hover,
body.elementor-kit-8 .wr-btn--op:focus{background:#9A3E00;color:var(--wr-cream)}
body.elementor-kit-8 .hm .wr-btn:hover,body.elementor-kit-8 .hm .wr-btn:focus,
body.elementor-kit-8 .wr-btn--hm:hover,body.elementor-kit-8 .wr-btn--hm:focus{
  background:var(--hm-deep);color:var(--wr-cream)}
@media(max-width:1024px){body.elementor-kit-8 .wr-btn{font-size:15px;padding:15px 22px}}
@media(max-width:767px){body.elementor-kit-8 .wr-btn{font-size:14px;padding:14px 20px}}

/* Text link with the house green underline. Reserved for WeReno-level actions
   (case studies, talk to WeReno) so green never becomes a product colour. */
.wr-link{
  display:inline-block;font-size:16px;font-weight:500;color:var(--wr-ink);
  text-decoration:none;border-bottom:2px solid var(--wr-green);padding-bottom:2px;
  transition:border-color .2s ease}
.wr-link:hover,.wr-link:focus{color:var(--wr-ink);border-bottom-color:var(--wr-ink)}
/* In-page navigation, charcoal underline — not a WeReno-level action. */
.wr-link--ink{border-bottom-color:var(--wr-ink)}
.rb .wr-link--ink:hover,.rb .wr-link--ink:focus{border-bottom-color:var(--rb-deep)}
.hm .wr-link--ink:hover,.hm .wr-link--ink:focus{border-bottom-color:var(--hm-deep)}
.wr-band .wr-link{color:#fff;border-bottom-color:var(--wr-green)}
.wr-band .wr-link:hover,.wr-band .wr-link:focus{color:#fff;border-bottom-color:#fff}
/* ⚠ A card or an Example frame sitting ON the dark band is still a LIGHT surface —
   the band's white type must not leak into it. Both the Renobot console's
   early-access CTA and Handyman's "Talk to WeReno" link rendered white-on-white
   before this: invisible, and invisible in a way no layout check can see. */
.wr-band .wr-card .wr-link,.wr-band .wr-ex .wr-link,
.wr-band .wr-card .wr-body,.wr-band .wr-ex .wr-body{color:var(--wr-ink)}
.wr-band .wr-card .wr-link,.wr-band .wr-ex .wr-link{border-bottom-color:var(--wr-ink)}
.rb .wr-band .wr-card .wr-link:hover,.rb .wr-band .wr-ex .wr-link:hover,
.rb .wr-band .wr-card .wr-link:focus,.rb .wr-band .wr-ex .wr-link:focus{
  color:var(--wr-ink);border-bottom-color:var(--rb-deep)}
.hm .wr-band .wr-card .wr-link:hover,.hm .wr-band .wr-ex .wr-link:hover,
.hm .wr-band .wr-card .wr-link:focus,.hm .wr-band .wr-ex .wr-link:focus{
  color:var(--wr-ink);border-bottom-color:var(--hm-deep)}

/* ----------------------------------------------------------------- pills -- */
/* Fresh class on purpose. .wr-bo-pill (the BuiltOS/YC badges on the homepage)
   is 'Inter Tight' — a font this site never loads, so it falls back to
   system-ui — plus a blurred shadow and a hover translate. Four overrides
   versus eight fresh lines. It stays untouched on the homepage.
   Always a <span>: a clickable "In development" promises a status page that
   does not exist. */
.wr-pill{
  display:inline-block;font-family:"Outfit",sans-serif;font-size:13px;
  font-weight:500;line-height:1;color:var(--wr-ink);background:#fff;
  border:2px solid var(--wr-line);border-radius:999px;padding:7px 14px;
  box-shadow:var(--wr-shadow-sm);white-space:nowrap}
.rb .wr-pill{background:var(--rb-field)}
.hm .wr-pill{background:var(--hm-field)}
.wr-band .wr-pill{background:#fff}

/* Question/label chip. Deliberately NOT border-radius:999px — the theme's
   rotated label chip geometry, un-rotated. That one substitution is what keeps
   these pages off the generic-SaaS pile. */
.wr-chip{
  display:inline-block;font-family:"Outfit",sans-serif;font-size:14px;
  font-weight:500;line-height:1.5;color:var(--wr-ink);background:#fff;
  border:3px solid var(--wr-line);border-radius:12px;padding:6px 14px;
  box-shadow:var(--wr-shadow-sm)}

/* ---------------------------------------------------- illustration fence -- */
/* Every simulated product surface carries this badge INSIDE its frame, never as
   a caption beneath it — captions do not survive a screenshot crop, and a
   cropped phone mock with no in-frame badge is indistinguishable from a
   shipping app. See the WR_EXAMPLE comment fences in the HTML. */
.wr-ex{position:relative}
.wr-ex-badge{
  position:absolute;top:12px;right:12px;z-index:3;
  font-family:"Outfit",sans-serif;font-size:11px;line-height:1;font-weight:500;
  text-transform:uppercase;letter-spacing:.08em;color:var(--wr-ink);
  background:#fff;border:2px solid var(--wr-line);border-radius:6px;
  padding:4px 8px;box-shadow:0 2px 0 0 rgba(0,0,0,.9);pointer-events:none}
.rb .wr-ex--dark .wr-ex-badge{background:var(--rb-amber)}
.hm .wr-ex--dark .wr-ex-badge{background:var(--hm-light)}

/* Label for the real, published case-study work — the opposite marker. */
.wr-real-label{margin:0 0 16px}

/* The pair line — "Renovate with Renobot. Maintain with Handyman." — breaks after
   the first sentence on purpose, so the two products stack one above the other
   instead of wrapping wherever the column happens to run out. A <br> would do it
   at one width and be wrong at every other; a block span is the same break at all
   of them, and it collapses back to normal flow if the rule ever goes missing. */
.wr-twoline > span{display:block}

/* ------------------------------------------------------------- wordmarks -- */
/* ⚠ SPECIFICITY TRAP — read before adding any image rule to a surface sheet.
   The theme ships `.elementor img{height:auto;max-width:100%}`. That is (0,1,1),
   so it beats ANY single-class rule on an image. The homepage section sits inside
   `.elementor elementor-136`, so a bare `.my-logo{height:28px}` there is silently
   ignored and the image renders at its intrinsic size — a 597px wordmark in a
   104px band, clipped by the card's overflow:hidden, which is exactly how it
   presents: not as a broken layout, as a truncated one.
   Every image rule in a surface sheet must therefore be written scoped
   (`.wr-prod .my-logo`, `.rb .my-logo`) to reach (0,2,0). The product pages have
   no `.elementor` ancestor, but scoping costs nothing and keeps the three sheets
   interchangeable. */
.wr-prod .wr-mark,.rb .wr-mark,.hm .wr-mark{display:block;width:auto;height:42px}
.wr-prod .wr-mark--lg,.rb .wr-mark--lg,.hm .wr-mark--lg{height:60px}
@media(max-width:1024px){
  .wr-prod .wr-mark,.rb .wr-mark,.hm .wr-mark{height:36px}
  .wr-prod .wr-mark--lg,.rb .wr-mark--lg,.hm .wr-mark--lg{height:50px}}
@media(max-width:767px){
  .wr-prod .wr-mark,.rb .wr-mark,.hm .wr-mark{height:32px}
  .wr-prod .wr-mark--lg,.rb .wr-mark--lg,.hm .wr-mark--lg{height:42px}}

/* ----------------------------------------------- highlighted-text underline */
/* The theme's #2 signature. Copied from the homepage h1 WITHOUT ui-e-a-animate
   and elementor-invisible, so the path paints at full length with no
   stroke-dasharray and no jQuery is required. */
.rb .ui-e-headline-text svg path{stroke:var(--rb-amber);stroke-width:30}
.hm .ui-e-headline-text svg path{stroke:var(--hm-red);stroke-width:30}

/* ---------------------------------------------------------------- shared -- */
/* Plain two-column "what it does / what people do" split, used on both pages. */
.wr-split{display:grid;grid-template-columns:1fr 1fr;gap:0}
.wr-split__col{padding:0 40px}
.wr-split__col:first-child{padding-left:0}
.wr-split__col:last-child{padding-right:0;border-left:3px solid var(--rb-amber)}
.hm .wr-split__col:last-child{border-left-color:var(--hm-red)}
.wr-split h4{font-size:18px;font-weight:500;letter-spacing:-.015em;margin:0 0 16px}
.wr-split ul{list-style:none;margin:0;padding:0}
.wr-split li{font-size:18px;line-height:1.8;color:var(--wr-body);
  padding-left:22px;position:relative}
/* Each item can carry a sub-note saying what it actually means — what gets chased,
   what gets decided. The term keeps the list's scale so the column still scans as
   a list; the note sits under it at body size. */
.wr-split li b{display:block;font-weight:500;color:var(--wr-ink)}
.wr-split li span{display:block;font-size:15.5px;line-height:1.65;color:var(--wr-body);
  margin:1px 0 0;max-width:46ch}
.wr-split li:has(span){margin-bottom:18px}
.wr-split li:has(span):last-child{margin-bottom:0}
@media(max-width:767px){
  .wr-split li span{font-size:14.5px;max-width:none}
  .wr-split li:has(span){margin-bottom:15px}
}
.wr-split li::before{content:"";position:absolute;left:0;top:13px;
  width:10px;height:10px;background:var(--rb-amber)}
.hm .wr-split li::before{background:var(--hm-red)}
@media(max-width:767px){
  .wr-split{grid-template-columns:1fr;gap:32px}
  .wr-split__col{padding:0}
  .wr-split__col:last-child{border-left:0;border-top:3px solid var(--rb-amber);padding-top:32px}
  .hm .wr-split__col:last-child{border-top-color:var(--hm-red)}
  .wr-split li{font-size:16px}
}

/* Real case-study card grid (3-up) — identical on both product pages. These
   carry no Example badge; that is the entire point of them. */
.wr-cases{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
.wr-case{background:#fff;border:3px solid var(--wr-line);border-radius:16px;
  box-shadow:var(--wr-shadow);overflow:hidden;text-decoration:none;display:block}
.wr-prod .wr-case img,.rb .wr-case img,.hm .wr-case img{
  display:block;width:100%;height:150px;object-fit:cover;
  border-bottom:3px solid var(--wr-line)}
.wr-case__b{display:block;padding:16px}
.wr-case__tag{display:inline-block;font-family:"Outfit",sans-serif;font-size:11px;
  font-weight:500;text-transform:uppercase;letter-spacing:.08em;color:var(--wr-ink);
  background:var(--rb-amber);border-radius:4px;padding:3px 7px;margin-bottom:8px}
.hm .wr-case__tag{background:var(--hm-light)}
.wr-case__n{display:block;font-size:18px;font-weight:500;letter-spacing:-.015em;color:var(--wr-ink);
  margin:0;line-height:1.35}
@media(max-width:1024px){
  .wr-cases{gap:16px}
  .wr-prod .wr-case img,.rb .wr-case img,.hm .wr-case img{height:120px}}
@media(max-width:767px){
  .wr-cases{grid-template-columns:1fr}
  .wr-prod .wr-case img,.rb .wr-case img,.hm .wr-case img{height:180px}}

/* Wide content scrolls inside its own box rather than widening the page. The
   Renobot ledger and decision log are five columns and a 390px phone is not — at
   that width the table keeps its structure and the reader swipes it. */
.wr-scroll-x{overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:100%}
.rb table,.hm table{border-collapse:collapse;width:100%}
@media(max-width:767px){
  .rb .wr-scroll-x table,.hm .wr-scroll-x table{min-width:520px}
}

/* Nav breathing room. The desktop menu only exists above 1025px and the
   container is 95%/1176px; eight items fit at 1176 but are tight at 1026. */
@media(min-width:1026px) and (max-width:1150px){
  .uicore-navbar{--uicore-header--menu-spaceing:12px}
}

/* Entrance motion, if any, is plain CSS — never elementor-invisible, which
   hides content until Elementor's frontend JS runs. These are the sections
   that must never fail to appear. */
@media(prefers-reduced-motion:no-preference){
  .wr-rise{animation:wr-rise .5s cubic-bezier(.2,.7,.3,1) both}
  @keyframes wr-rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
}

/* ── Floating robots ────────────────────────────────────────────────────
   Decorative robot art parked in the page margins beside the 1176px
   container. Three motions stack, on two nested elements so they can't
   fight over `transform`:

     .wr-float      outer — JS writes the mouse-parallax spring here
     .wr-float__i   inner — CSS keyframes run the idle bob here

   Everything is transform-only (never top/left), so no float can reflow
   the page; pointer-events are off, so no float can eat a click.

   Width is derived from the margin itself: half the leftover viewport,
   less 36px of breathing room, capped at 152. The anchor then parks the
   robot's inner edge 14px outside the container. Below 1440px there is
   no margin to park in and they are simply not rendered — which is also
   why the JS parallax stays under ±6px horizontally, so a float at the
   narrow end of the range can never travel past the viewport edge.      */
.wr-float-host .wr-float{
  display:none;position:absolute;z-index:0;pointer-events:none;
  -webkit-user-select:none;user-select:none;
  width:var(--f-w);
  top:var(--f-t,0px);
  /* --f-s varies the size per float so the group never reads as one
     stamped asset repeated down the page. The inner edge stays pinned
     14px off the container either way, because the anchor is written
     in terms of --f-w. */
  --f-w:calc(clamp(84px,calc((100vw - 1176px) / 2 - 36px),194px) * var(--f-s,1));
}
/* The section a float is parked in has to be the containing block, or the
   float resolves against the page and lands somewhere else entirely. A missing
   compound selector here once left the homepage products section static, and
   its three mascots resolved against the page and rendered ~950px above where
   they were placed. floats.mjs guards the margins horizontally and never reads
   vertical position, so nothing caught it.

   EVERY float rule above and below is scoped on this one class, and on nothing
   else. It used to be the triple `.rb X, .hm X, .wr-prod X`, which was never
   doing scoping work this class was not already doing -- all 50 floats across
   the 13 pages sit inside a host -- but which silently excluded anywhere that
   carried none of the three. The homepage hero is an Elementor section, so a
   float placed there matched no rule at all and rendered as a raw 640px inline
   image in the flow. Declaring the host is now the whole contract. */
.wr-float-host{position:relative}
.wr-float-host .wr-float--l{left:calc(50% - 588px - var(--f-w) - 14px)}
.wr-float-host .wr-float--r{right:calc(50% - 588px - var(--f-w) - 14px)}

/* <picture> is an inline box by default, and the image inside it is block and
   width:100%. Left inline, the picture shrink-wraps to its content and that
   100% resolves against a box the image is itself sizing: circular, and the
   float collapses to nothing. Block hands the img the float's own --f-w, which
   is exactly what it resolved against when it was a direct child. */
.wr-float-host .wr-float__p{display:block}

.wr-float-host .wr-float__i{
  display:block;width:100%;height:auto;
  opacity:var(--f-o,.92);
  transform-origin:50% 85%;
  animation:wr-bob var(--f-dur,5.4s) ease-in-out var(--f-delay,0s) infinite;
  filter:drop-shadow(0 10px 18px rgba(0,0,0,.13));
}

/* A bob, not a bounce loop: it rises, tips a little, and comes back.
   The tilt is what keeps it from reading as a lift in a lift shaft. */
@keyframes wr-bob{
  0%,100%{transform:translate3d(0,0,0) rotate(var(--f-rot,0deg))}
  50%    {transform:translate3d(0,var(--f-lift,-13px),0) rotate(calc(var(--f-rot,0deg) + var(--f-tilt,3.5deg)))}
}

@media(min-width:1440px){
  .wr-float-host .wr-float{display:block}
}

/* Hover lives on the <img>, never on .wr-float: the wrapper is as wide as the
   margin and on the mascots it also holds a speech bubble that overhangs
   inward, so making the wrapper hoverable would put an invisible catcher over
   the edge of the content column. The art itself sits outside the 1176px
   container, so nothing it covers is clickable.

   Only filter and opacity change here. The transform on this element belongs
   to the bob keyframes and the one on its parent belongs to the parallax
   spring, and a hover rule written on either would silently win or lose
   against an animation instead of composing with it. The hop is JS, applied
   as velocity into the spring that is already running. */
@media(min-width:1440px){
  .wr-float-host .wr-float__i{
    pointer-events:auto;
    transition:opacity .25s ease, filter .25s ease}
  .wr-float-host .wr-float.is-perked .wr-float__i{
    opacity:1;
    filter:drop-shadow(0 14px 22px rgba(0,0,0,.2))}
  /* The bubble is what the robot is for, so it leads a little when hovered. */
  .wr-float-host .wr-float--mascot.is-perked .wr-bub{
    box-shadow:0 6px 0 0 rgba(0,0,0,.9);
    transform:translateY(-3px)}
}
@media(prefers-reduced-motion:reduce){
  .wr-float-host .wr-float--mascot.is-perked .wr-bub{transform:none;transition:none}
}
/* Reduced motion keeps the robots and drops every movement — the art is
   the point, the bobbing is the flourish. JS checks the same query. */
/* Reduced motion stops every loop. The art stays, the movement goes: that is
   the point of the preference, and the blink patches must go to zero opacity
   rather than freeze wherever their cycle happened to be. */
@media(prefers-reduced-motion:reduce){
  .wr-float-host .wr-float__i,
  .wr-float-host .wr-float--mascot .wr-float__m,
  .wr-float-host .wr-float--mascot .wr-float__i{animation:none}
  .wr-float-host .wr-float--mascot .wr-blink{animation:none;opacity:0}
  .wr-float-host .wr-float--mascot .wr-float__m{transition:none}
}

/* The hero eyebrow is the product's wordmark rather than its name set in the
   handwriting face. Scoped, because .elementor img{height:auto;max-width:100%}
   is (0,1,1) and would otherwise render these at their intrinsic 597px. */
.rb .wr-eyemark,.hm .wr-eyemark{height:76px;margin:0 0 18px}
@media(max-width:1024px){ .rb .wr-eyemark,.hm .wr-eyemark{height:64px;margin-bottom:15px} }
@media(max-width:767px){ .rb .wr-eyemark,.hm .wr-eyemark{height:56px;margin-bottom:12px} }

/* ── Subpage furniture ──────────────────────────────────────────────────
   A subpage opens smaller than an overview: it has already been chosen,
   so the hero states what the page is and gets out of the way. Same
   typography and the same bands as everywhere else. */
/* The theme header is out of flow and overlays the page, so a section at the
   top of the document starts underneath it. The product heroes clear it with
   their own 110px; the subheroes need the same treatment. The selector carries
   an attribute so it outranks .wr-sec--tight, which set 28px and was winning
   on source order. */
.rb section[class*="-subhero"],.hm section[class*="-subhero"]{padding-top:132px}
@media(max-width:1024px){
  .rb section[class*="-subhero"],.hm section[class*="-subhero"]{padding-top:112px}
}
@media(max-width:767px){
  .rb section[class*="-subhero"],.hm section[class*="-subhero"]{padding-top:92px}
}
/* Height deliberately NOT set here. This rule used to pin every Handyman and
   Renobot subpage wordmark to a flat 44px with no breakpoint steps, against
   76/64/56 on their own home pages -- the same mark at a little over half size
   on six of the eight pages it appears on. Only the margin is the subhero's to
   decide. Capital is unaffected either way: its src-keyed rule below ties this
   one at (0,3,0) and is written later, so it wins the tie. */
.rb [class*="-subhero"] .wr-eyemark,.hm [class*="-subhero"] .wr-eyemark{margin-bottom:12px}
.rb [class*="-subhero__h"],.hm [class*="-subhero__h"]{
  font-family:"Outfit",sans-serif;font-size:clamp(30px,3.4vw,48px);font-weight:600;
  line-height:1.12;letter-spacing:-.028em;color:var(--wr-ink);margin:0 0 14px;
  max-width:20ch;text-wrap:balance}
.rb [class*="-subhero__s"],.hm [class*="-subhero__s"]{margin:0;max-width:62ch}

/* the provenance credit that travels with every route carrying a panel */
.rb [class*="-subnote"],.hm [class*="-subnote"]{padding-top:0}
.rb [class*="-subnote__p"],.hm [class*="-subnote__p"]{
  margin:0;max-width:78ch;text-transform:none;letter-spacing:0;
  font-size:13.5px;line-height:1.6;color:var(--wr-body);
  border-top:1px solid rgba(20,20,20,.16);padding-top:16px}

/* the closing offer, the same on every route */
.rb [class*="-subcta"] .wr-inner,.hm [class*="-subcta"] .wr-inner{text-align:center}
.rb [class*="-subcta"] h2,.hm [class*="-subcta"] h2{margin:12px 0 12px}
.rb [class*="-subcta"] p,.hm [class*="-subcta"] p{max-width:56ch;margin:0 auto 24px}


/* ── Overview previews ──────────────────────────────────────────────────
   The sections that replaced the explanation the subpages took with them.
   Each one states an idea, shows a little, and points at the route that
   carries the rest. */
.rb [class*="__grid"].rb-disc__grid,.rb .rb-proof__grid,.rb .rb-rules__grid,
.hm .hm-halves__grid,.hm .hm-mprev__row{display:grid;gap:20px;margin:26px 0 0}
.hm .hm-halves__grid{grid-template-columns:1fr 1fr;gap:26px}
.rb .rb-disc__grid{grid-template-columns:repeat(3,1fr)}
.rb .rb-proof__grid{grid-template-columns:repeat(4,1fr)}
.rb .rb-rules__grid{grid-template-columns:1fr 1fr}
.hm .hm-mprev__row{grid-template-columns:repeat(3,1fr)}

.hm .hm-half{min-width:0;display:flex;flex-direction:column;gap:12px;
  background:#fff;border:3px solid var(--wr-line);border-radius:18px;
  box-shadow:var(--wr-shadow);padding:26px 26px 28px}
.hm .hm-half__k{display:block}
.hm .hm-half h3{margin:0}
.hm .hm-half p{margin:0}
.hm .hm-half__l{margin:4px 0 14px;padding:0;list-style:none;display:grid;gap:9px}
.hm .hm-half__l li{position:relative;padding-left:20px;font-size:15.5px;
  line-height:1.55;color:var(--wr-body)}
.hm .hm-half__l li::before{content:"";position:absolute;left:0;top:9px;
  width:8px;height:8px;border-radius:2px;background:var(--hm-red)}
.hm .hm-half .wr-link{margin-top:auto;align-self:flex-start}

.rb .rb-disc__i,.rb .rb-proof__i,.rb .rb-rules__i,.hm .hm-mprev__i{min-width:0}
.rb .rb-disc__i b,.hm .hm-mprev__i b{display:block;font-family:"Outfit",sans-serif;
  font-size:19px;font-weight:600;letter-spacing:-.018em;color:var(--wr-ink);margin-bottom:5px}
.rb .rb-disc__i span,.rb .rb-rules__i span,.hm .hm-mprev__i span{display:block;
  font-size:15px;line-height:1.6;color:var(--wr-body)}
.rb .rb-disc__i{border-top:3px solid var(--rb-amber);padding-top:14px}
.hm .hm-mprev__i{border-top:3px solid var(--hm-red);padding-top:14px}
.rb .rb-disc__links{display:flex;flex-wrap:wrap;gap:12px 26px;margin-top:26px}

.rb .rb-proof__i{background:#fff;border:3px solid var(--wr-line);border-radius:16px;
  box-shadow:var(--wr-shadow);padding:20px 18px 22px}
.rb .rb-proof__i b{display:block;font-family:"Outfit",sans-serif;
  font-size:clamp(26px,2.6vw,38px);font-weight:600;line-height:1;
  letter-spacing:-.03em;color:var(--wr-ink);font-variant-numeric:tabular-nums;
  margin-bottom:9px}
.rb .rb-proof__i span{display:block;font-size:14px;line-height:1.55;color:var(--wr-body)}
.rb .rb-proof__note{margin-top:22px;max-width:78ch}

.rb .rb-rules__i b{display:block;font-family:"Outfit",sans-serif;font-size:17px;
  font-weight:600;line-height:1.35;color:#fff;margin-bottom:6px}
.rb .rb-rules__i span{color:rgba(255,255,255,.76)}
.rb .rb-rules__line{margin:28px 0 0;font-family:"Outfit",sans-serif;
  font-size:clamp(18px,2vw,25px);font-weight:500;letter-spacing:-.02em;
  color:var(--rb-amber)}

@media(max-width:1024px){
  .rb .rb-proof__grid{grid-template-columns:1fr 1fr}
  .rb .rb-disc__grid{grid-template-columns:1fr 1fr}
}
@media(max-width:767px){
  .hm .hm-halves__grid,.rb .rb-disc__grid,.rb .rb-rules__grid,
  .hm .hm-mprev__row,.rb .rb-proof__grid{grid-template-columns:1fr}
  .hm .hm-half{padding:20px 20px 22px}
}

/* ── Capital's mark ─────────────────────────────────────────────────────────
 * Typeset, not drawn. Capital is the enterprise product and it sits in the same
 * header as two cartoon robots, so a third drawn wordmark would have read as a
 * third mascot. Direction C: wide-tracked caps over a rule, byline beneath.
 *
 * Sized off one custom property per context, because a span cannot be sized by
 * `height` the way the two <img> marks it replaces are: the type has to be told
 * how big to be. Everything inside derives from --h, so one number moves the
 * whole lockup.
 *
 * The rule stays amber. Capital keeps the amber it already had, on the grounds
 * that amber reads commercial and this is the commercial product; the consumer
 * Renobot is the one getting a new colour.
 */
.rb .wr-capmark,.hm .wr-capmark,.wr-prod .wr-capmark{
  --h:42px;
  /* height is set, not merely implied: --h drives the child sizes, and without
     this the box collapsed to its content (66px where the <img> it replaces was
     76px) and justify-content had nothing to centre the lockup inside. */
  height:var(--h);
  display:inline-flex;flex-direction:column;align-items:stretch;justify-content:center;
  font-family:"Outfit",system-ui,-apple-system,sans-serif;line-height:1;
  /* .wr-band paints a dark ground but only colours h2/h3/p, so a bare span in
     there inherits body ink and all but disappears. The mark states its own
     colour rather than trusting currentColor. */
  color:var(--wr-ink)}
.rb .wr-band .wr-capmark,.hm .wr-band .wr-capmark{color:#fff}
/* The homepage card's band is NOT dark, it is the amber one, and it carries the
   ink-on-white Early access pill. White lettering on #FDC313 measures 1.62:1, so
   the mark is ink here and its rule goes ink with it, since amber-on-amber is
   invisible. The drawn wordmark this replaces was white and got away with it only
   because an image is never contrast-checked. */
.wr-prod .wr-prod-band .wr-capmark{color:var(--wr-ink)}
.wr-prod .wr-prod-band .wr-capmark .wr-capmark__r{background:var(--wr-ink);opacity:.85}

.rb .wr-capmark__n,.hm .wr-capmark__n,.wr-prod .wr-capmark__n{
  font-size:calc(var(--h) * .47);font-weight:500;letter-spacing:.3em;
  text-transform:uppercase;white-space:nowrap;
  /* tracking is added to the RIGHT of every glyph including the last, so the
     lockup optically sits left of where it should without this */
  padding-left:.3em}
.rb .wr-capmark__r,.hm .wr-capmark__r,.wr-prod .wr-capmark__r{
  display:block;height:2px;background:var(--rb-amber);border-radius:1px;
  margin:calc(var(--h) * .11) 0 calc(var(--h) * .08)}
.rb .wr-capmark__b,.hm .wr-capmark__b,.wr-prod .wr-capmark__b{
  font-size:max(9px, calc(var(--h) * .185));font-weight:500;letter-spacing:.22em;
  text-transform:uppercase;white-space:nowrap;opacity:.72;
  /* centred under the word above it. The left padding stays because the tracking
     adds a full letter-space after the final glyph, so without it the line sits
     visibly left of centre even when the box is centred. */
  text-align:center;padding-left:.22em}

/* Inline uses track the plain .wr-mark heights. These come FIRST: .wr-capmark
   and .wr-capmark--hero are both (0,2,0), so source order is the only thing
   separating them. With the generic rules last, a hero mark on a tablet took
   --h:36px off this block instead of its own 64px and shrank by half. */
@media(max-width:1024px){ .rb .wr-capmark,.hm .wr-capmark,.wr-prod .wr-capmark{--h:36px} }
@media(max-width:767px){  .rb .wr-capmark,.hm .wr-capmark,.wr-prod .wr-capmark{--h:32px} }

/* Hero. Mirrors what .wr-eyemark gave the <img>: 76/64/56 with its margin. */
.rb .wr-capmark--hero,.hm .wr-capmark--hero{--h:76px;margin:0 0 18px}
@media(max-width:1024px){ .rb .wr-capmark--hero,.hm .wr-capmark--hero{--h:64px;margin-bottom:15px} }
@media(max-width:767px){  .rb .wr-capmark--hero,.hm .wr-capmark--hero{--h:56px;margin-bottom:12px} }
/* Subhero sits smaller, as the <img> did. Specificity (0,3,0) beats both. */
.rb [class*="-subhero"] .wr-capmark--hero{--h:44px;margin-bottom:12px}

/* Homepage product card. Mirrors wereno-homeproducts.css's .wr-prod-band .wr-mark
   heights, which is where the drawn mark got its size on that page. */
.wr-prod .wr-prod-band .wr-capmark{--h:60px;flex:0 0 auto}
/* The byline is BACK, and the caps go back to their default size with it. The
   drawn Capital wordmark this replaces is much lighter in weight than the
   Handyman and Renobot wordmarks on the cards beside it -- they are solid
   lettering, it is a thin outline lockup -- so it read as the quiet one of the
   three. Setting "CAPITAL / BY WERENO" in Outfit beside the mascot gives it the
   same density as its neighbours.

   .wr-capmark has a fixed height:var(--h) and the children share it, so
   restoring the byline does not grow the box: at --h:56 the stack measures
   26.3 + 6.2 + 2 + 4.5 + 10.4 = 49.4px inside 56. The rotated "Projects" chip
   is absolutely positioned at top:88px, below the band's 104px midline, and
   the lockup ends at 80, so the collision that hid this line is gone. */
.wr-prod .wr-prod-band .wr-prod-lock{
  display:flex;align-items:center;gap:11px;flex:0 0 auto}
/* (0,3,0), which it has to be: `.elementor img{height:auto;max-width:100%}` is
   (0,1,1) and beats any single-class rule on an image in this theme. */
.wr-prod .wr-prod-band .wr-prod-lock__i{flex:0 0 auto;height:66px;width:auto}
@media(max-width:1024px){.wr-prod .wr-prod-band .wr-prod-lock__i{height:56px}}
@media(max-width:767px){.wr-prod .wr-prod-band .wr-prod-lock__i{height:46px}}
@media(max-width:1024px){ .wr-prod .wr-prod-band .wr-capmark{--h:46px} }
@media(max-width:767px){  .wr-prod .wr-prod-band .wr-capmark{--h:38px} }
/* Handyman's comparison tile, where the drawn mark was a plain .wr-mark. */
.hm .hm-tile .wr-capmark{--h:42px}


/* ── the alternating ground, on product pages only ──────────────────────────
 * Sections alternate between a product's own pale field and whatever
 * .content-area paints behind them. That was #DEE8E8, a green-grey, which is
 * WeReno's own ground and reads correctly under the house green. It does not
 * work under amber, blue or red, and on Renobot it barely works at all: the
 * green-grey sits dE00 4 from the pale blue field, so the two alternating
 * bands were very nearly the same colour.
 *
 * #E2E2E2 is a true neutral: R, G and B are equal, so there is no green in it at
 * all and it takes no side between amber, blue and red. It sits 12 / 8 / 10 from
 * the Capital, Renobot and Handyman fields where the old green ground managed
 * 14 / 4 / 16, and that 4 is why Renobot's two bands used to read as one
 * continuous colour.
 *
 * HOW DARK THIS IS ALLOWED TO GET is set by Capital's eyebrow, --rb-eyebrow
 * #A66A00, which is 24px and therefore judged at the 3:1 large-text threshold.
 * A mid grey at #D0D0D0 put it at 2.91:1 and failed. #E2E2E2 gives 3.46:1.
 * Note that #A66A00 can never reach 4.5:1 on anything: it would need a ground
 * brighter than white. It lives on the large-text threshold by design, so any
 * future darkening of this ground has to check it first.
 *
 * Everything else is comfortable: ink 14.2:1, and the 70%-opacity body ink
 * composites to 6.03:1.
 *
 * Scoped to .wr-product, which build_shell stamps on the product pages, so
 * WeReno's own pages keep the green ground their palette was built around.
 */
body.wr-product .content-area{background:var(--wr-prod-ground)}

/* The hero's product list was removed but its HEIGHT was not: the four mascots
   are positioned against this section and their spacing was budgeted against a
   paragraph four lines deep. This tagline stands in that slot, and the
   min-height holds the floor when it wraps to fewer lines than the budget, so
   the two mascots down each side cannot close on each other. */
.wr-hero-tag{min-height:105px;margin:0;max-width:37em}
@media(max-width:1279.98px){ .wr-hero-tag{min-height:96px} }

/* ── the mascots are quietly alive ──────────────────────────────────────────
 * TWO layers, and only two, because every extra one is another fight over
 * `transform`:
 *
 *   .wr-float      the mouse-parallax spring, written from JS
 *   .wr-float__m   everything else: the idle float, the character's own
 *                  gesture, and the hover scale, in ONE animation
 *
 * The blink patches live INSIDE that layer, so they turn with the art. Built
 * the obvious way, with the gesture on the <img> and the patches as its
 * siblings, a blink that landed mid-gesture would have sat several pixels off
 * the eyes: a 2 degree turn about a point 150px away moves the face by 5.
 *
 * The bob and the gesture share one loop rather than running as two animations,
 * for the same reason. Three bob cycles and one gesture per loop, so the float
 * still reads as ~6s while the character only does something every ~18s. That
 * ratio is what keeps four mascots from feeling busy.
 *
 * Hover is a scale INSIDE the keyframes, driven by --wr-hov. A plain
 * `transform` declaration on hover would have lost to the animation outright,
 * which is exactly what the first attempt did: measured, the wrapper went from
 * 0.997 to 0.998 on hover instead of to 1.025.
 *
 * Everything is transform and opacity. Nothing animates a filter, nothing
 * changes layout: measured CLS contribution is 0.00000.
 */
.wr-float-host .wr-float--mascot .wr-float__m{display:block;position:relative}
.wr-float-host .wr-float--mascot .wr-float__i{animation:none}
.wr-float-host .wr-float--mascot.is-perked .wr-float__m{--wr-hov:1.025}

@keyframes wr-mascot-hm{
  0%     {transform:translateY(0) rotate(var(--f-rot,0deg)) scale(var(--wr-hov,1))}
  16.7%  {transform:translateY(var(--f-lift,-9px)) rotate(calc(var(--f-rot,0deg) + var(--f-tilt,1.6deg))) scale(var(--wr-hov,1))}
  33.3%  {transform:translateY(0) rotate(var(--f-rot,0deg)) scale(var(--wr-hov,1))}
  50%    {transform:translateY(var(--f-lift,-9px)) rotate(calc(var(--f-rot,0deg) + var(--f-tilt,1.6deg))) scale(var(--wr-hov,1))}
  66.7%  {transform:translateY(0) rotate(var(--f-rot,0deg)) scale(var(--wr-hov,1))}
  74%    {transform:translateY(-6px) rotate(calc(var(--f-rot,0deg) - 1.3deg)) scale(var(--wr-hov,1))}
  78%    {transform:translateY(-8px) rotate(calc(var(--f-rot,0deg) - 0.4deg)) scale(var(--wr-hov,1))}
  82%    {transform:translateY(-7px) rotate(calc(var(--f-rot,0deg) - 1.1deg)) scale(var(--wr-hov,1))}
  90%    {transform:translateY(-4px) rotate(calc(var(--f-rot,0deg) + 0.5deg)) scale(var(--wr-hov,1))}
  100%   {transform:translateY(0) rotate(var(--f-rot,0deg)) scale(var(--wr-hov,1))}
}
@keyframes wr-mascot-rb{
  0%     {transform:translateY(0) rotate(var(--f-rot,0deg)) scale(var(--wr-hov,1))}
  16.7%  {transform:translateY(var(--f-lift,-9px)) rotate(calc(var(--f-rot,0deg) + var(--f-tilt,1.6deg))) scale(var(--wr-hov,1))}
  33.3%  {transform:translateY(0) rotate(var(--f-rot,0deg)) scale(var(--wr-hov,1))}
  50%    {transform:translateY(var(--f-lift,-9px)) rotate(calc(var(--f-rot,0deg) + var(--f-tilt,1.6deg))) scale(var(--wr-hov,1))}
  66.7%  {transform:translateY(0) rotate(var(--f-rot,0deg)) scale(var(--wr-hov,1))}
  76%    {transform:translateY(-6px) rotate(calc(var(--f-rot,0deg) + 1.5deg)) scale(var(--wr-hov,1))}
  81%    {transform:translateY(-3px) rotate(calc(var(--f-rot,0deg) + 0.4deg)) scale(var(--wr-hov,1))}
  86%    {transform:translateY(-6px) rotate(calc(var(--f-rot,0deg) + 1.1deg)) scale(var(--wr-hov,1))}
  100%   {transform:translateY(0) rotate(var(--f-rot,0deg)) scale(var(--wr-hov,1))}
}
@keyframes wr-mascot-cap{
  0%     {transform:translateY(0) rotate(var(--f-rot,0deg)) scale(var(--wr-hov,1))}
  16.7%  {transform:translateY(var(--f-lift,-9px)) rotate(calc(var(--f-rot,0deg) + var(--f-tilt,1.6deg))) scale(var(--wr-hov,1))}
  33.3%  {transform:translateY(0) rotate(var(--f-rot,0deg)) scale(var(--wr-hov,1))}
  50%    {transform:translateY(var(--f-lift,-9px)) rotate(calc(var(--f-rot,0deg) + var(--f-tilt,1.6deg))) scale(var(--wr-hov,1))}
  66.7%  {transform:translateY(0) rotate(var(--f-rot,0deg)) scale(var(--wr-hov,1))}
  73%    {transform:translateY(-6px) rotate(calc(var(--f-rot,0deg) - 1.2deg)) scale(var(--wr-hov,1))}
  80%    {transform:translateY(-8px) rotate(calc(var(--f-rot,0deg) - 0.5deg)) scale(var(--wr-hov,1))}
  88%    {transform:translateY(-4px) rotate(calc(var(--f-rot,0deg) - 0.9deg)) scale(var(--wr-hov,1))}
  100%   {transform:translateY(0) rotate(var(--f-rot,0deg)) scale(var(--wr-hov,1))}
}
@keyframes wr-mascot-op{
  0%     {transform:translateY(0) rotate(var(--f-rot,0deg)) scale(var(--wr-hov,1))}
  16.7%  {transform:translateY(var(--f-lift,-9px)) rotate(calc(var(--f-rot,0deg) + var(--f-tilt,1.6deg))) scale(var(--wr-hov,1))}
  33.3%  {transform:translateY(0) rotate(var(--f-rot,0deg)) scale(var(--wr-hov,1))}
  50%    {transform:translateY(var(--f-lift,-9px)) rotate(calc(var(--f-rot,0deg) + var(--f-tilt,1.6deg))) scale(var(--wr-hov,1))}
  66.7%  {transform:translateY(0) rotate(var(--f-rot,0deg)) scale(var(--wr-hov,1))}
  72%    {transform:translateY(-7px) rotate(calc(var(--f-rot,0deg) + 1.4deg)) scale(var(--wr-hov,1))}
  77%    {transform:translateY(-8px) rotate(calc(var(--f-rot,0deg) + 1.0deg)) scale(var(--wr-hov,1))}
  84%    {transform:translateY(-4px) rotate(calc(var(--f-rot,0deg) + 0.6deg)) scale(var(--wr-hov,1))}
  100%   {transform:translateY(0) rotate(var(--f-rot,0deg)) scale(var(--wr-hov,1))}
}

/* ---- blink ----------------------------------------------------------------
 * These robots already have curved, happy eyes, so there is no open state to
 * close. What reads right on a character whose face IS a screen is the eye
 * winking out for a moment, so each patch is that screen's own colour, taken
 * from the median of its dark pixels: sampling beside an arc picks up the
 * arc's bleed and comes back mauve. The soft edge is load bearing, because a
 * hard rectangle would have to match the screen's gradient exactly.
 *
 * Both eyes go together. One eye alone is a wink, and a wink is a joke.
 */
.wr-float-host .wr-float--mascot .wr-blink{
  position:absolute;display:block;pointer-events:none;opacity:0;
  background:radial-gradient(closest-side, var(--eye-c,#10161A) 68%, transparent 100%)}
.wr-float-host .wr-float--mascot .wr-blink--l{
  left:var(--eye-lx);top:var(--eye-ly);width:var(--eye-lw);height:var(--eye-lh)}
.wr-float-host .wr-float--mascot .wr-blink--r{
  left:var(--eye-rx);top:var(--eye-ry);width:var(--eye-rw);height:var(--eye-rh)}

/* One long cycle, nearly all of it at rest; the blink itself is about 150ms. */
@keyframes wr-blink{ 0%,88.4%{opacity:0} 89%{opacity:1} 91%{opacity:0} 100%{opacity:0} }
/* the same with a second beat, for two of the four */
@keyframes wr-blink2{
  0%,84.4%{opacity:0} 85%{opacity:1} 86.6%{opacity:0}
  88.4%{opacity:0} 89%{opacity:1} 90.8%{opacity:0} 100%{opacity:0} }

/* Per mascot. No two durations match, and none is a multiple of another, so the
   four never drift into step. */
.wr-float-host [data-chat="hm"] .wr-float__m{animation:wr-mascot-hm 17.4s ease-in-out .2s infinite both}
.wr-float-host [data-chat="hm"] .wr-blink{animation:wr-blink 6.7s linear .9s infinite both}
.wr-float-host [data-chat="rb"] .wr-float__m{animation:wr-mascot-rb 19.3s ease-in-out 1.1s infinite both}
.wr-float-host [data-chat="rb"] .wr-blink{animation:wr-blink2 8.9s linear 2.3s infinite both}
.wr-float-host [data-chat="cap"] .wr-float__m{animation:wr-mascot-cap 18.1s ease-in-out .6s infinite both}
.wr-float-host [data-chat="cap"] .wr-blink{animation:wr-blink 7.6s linear .3s infinite both}
.wr-float-host [data-chat="op"] .wr-float__m{animation:wr-mascot-op 20.2s ease-in-out 1.6s infinite both}
.wr-float-host [data-chat="op"] .wr-blink{animation:wr-blink2 10.3s linear 4.1s infinite both}

/* ---- the speech bubble breathes ------------------------------------------- */
@keyframes wr-bub-breathe{
  0%,86%{transform:translateY(0) scale(1)}
  91%{transform:translateY(-1.5px) scale(1.012)}
  96%,100%{transform:translateY(0) scale(1)}
}

/* Reduced motion stops every loop dead. This sits AFTER the rules it overrides
   on purpose: the setters above are (0,3,0) and so is this, so source order is
   the only thing deciding it, and the first attempt lost that race silently. */
@media(prefers-reduced-motion:reduce){
  .wr-float-host .wr-float--mascot .wr-float__m,
  .wr-float-host .wr-float--mascot .wr-float__i,
  .wr-float-host [data-chat] .wr-float__m{animation:none}
  /* The blink deliberately survives here, and it is the only thing that does.
     Reduced motion is the branch that gets the static webp instead of the GIF
     (see the <source media> on every mascot), so without the eyelids the robot
     would be a dead sticker -- and the eyelids are a 150ms opacity fade on a
     patch a few pixels across, not the travel, parallax or scaling the
     preference is asking us to stop. Everything that MOVES is still off. */
}

/* The GIF blinks on its own, so the painted eyelids would fire a second,
   unrelated blink on top of it. This query is character-for-character the pair
   carried by the <source media> on every mascot, so the patches go dark in
   precisely the viewports the GIF is served into and stay live in the ones left
   on the webp. That equality IS the contract: loosen either side and a mascot
   either blinks twice or never blinks at all. */
@media (min-width:1560px) and (prefers-reduced-motion:no-preference){
  .wr-float-host .wr-float--mascot .wr-blink,
  .wr-float-host [data-chat] .wr-blink{animation:none;opacity:0}
}

/* ── product names underlined in running text ───────────────────────────────
 * The same hand-drawn stroke the header's "you are on X" label and the Capital
 * hero both use: the theme's own highlighted-text SVG path, stretched to the
 * word with preserveAspectRatio="none". A border-bottom would be a straight
 * line, which is the one thing this device is not.
 *
 * The stroke is thinner here than in the header (2.5 against 3) because it sits
 * in a 17px paragraph rather than under a 15px label with room around it.
 * vector-effect keeps it that weight however far the path is stretched, so a
 * long name and a short one get the same line.
 */
.wr-nameu{position:relative;display:inline-block;white-space:nowrap}
.wr-nameu__l{
  /* 5px up from the bottom of the inline box, not 0. The span is an
     inline-block, so its box is the full line box: 32.4px against a 23px glyph
     run in this paragraph, which leaves 5.4px of dead leading underneath. A
     stroke at bottom:0 hangs in that gap and reads as a rule under the line
     rather than an underline on the word. */
  position:absolute;left:-2px;right:-2px;bottom:5px;width:calc(100% + 4px);
  height:7px;overflow:visible;pointer-events:none}
.wr-nameu__l path{fill:none;stroke-linecap:round;stroke-width:2.5;
  vector-effect:non-scaling-stroke}
.wr-nameu--hm  .wr-nameu__l path{stroke:#FF003F}
.wr-nameu--rb  .wr-nameu__l path{stroke:#35C4F0}
.wr-nameu--cap .wr-nameu__l path{stroke:#FDC313}
.wr-nameu--op  .wr-nameu__l path{stroke:#FD6E00}

/* ── the homepage mascots and their speech bubbles ──────────────────────────
 * Three robots in the page margins, one per product, each with a bubble that
 * cycles through things that product can actually do.
 *
 * The bubble lives INSIDE .wr-float on purpose. getBoundingClientRect returns an
 * element's own border box and ignores overflowing children, so the float's
 * measured box is unchanged and the margin guard in test/browser/floats.mjs
 * still means what it says.
 *
 * Bubbles only appear at 1560px and up. The margin is derived from the viewport,
 * so below that there is no room for one and the robot bobs on its own rather
 * than a speech bubble reaching across into the copy.
 */
.wr-float-host .wr-float--mascot .wr-bub{display:none}
@media(min-width:1560px){
  /* WIDTH HUGS THE TEXT, and grows OUTWARD, away from the content column.
     It used to be width:max(100%,152px), which is the float's own width with a
     floor under it: a fixed box that every line had to wrap inside regardless
     of length, so "hey, I'm Renobot" sat on one short line in a wide box and
     "I get a WeReno expert on the hard calls" wrapped to four.

     Which edge is anchored matters more than it looks. A float in the LEFT
     margin has 14px between it and the content column and the whole rest of the
     margin to its left, so a bubble anchored left:0 grows in the one direction
     with no room. Each side is now anchored on its INNER edge and grows toward
     the viewport, which is where the space actually is.

     The cap is the margin itself: (100vw - 1176px)/2 is the margin width, less
     40px, which leaves ~26px of gutter at the viewport edge once a vertical
     scrollbar is counted inside 100vw. */
  .wr-float-host .wr-float--mascot .wr-bub{
    display:block;position:absolute;bottom:calc(100% - 6px);
    left:auto;right:0;
    width:max-content;min-width:118px;
    max-width:calc((100vw - 1176px) / 2 - 40px);
    background:#fff;color:var(--wr-ink);
    border:2.5px solid var(--wr-line);border-radius:14px;
    box-shadow:0 4px 0 0 rgba(0,0,0,.9);
    padding:10px 13px 11px;
    font-family:"Outfit",sans-serif;font-size:13.5px;line-height:1.35;font-weight:500;
    text-align:left;
    transition:transform .25s ease, box-shadow .25s ease;
    /* one slow breath every eleven seconds, staggered off the mascot's own
       float delay so the bubbles do not pulse in unison either */
    animation:wr-bub-breathe 11s ease-in-out var(--f-delay,0s) infinite;
  }
  /* hovering hands the transform back to .is-perked, which carries the lift
     through a transition an animation would otherwise outrank */
  .wr-float-host .wr-float--mascot.is-perked .wr-bub{animation:none}
  @media(prefers-reduced-motion:reduce){
    .wr-float-host .wr-float--mascot .wr-bub{animation:none}
  }
  /* the tail, drawn as a rotated square so it inherits the border and the fill.
     It sits over the robot, so it is pinned to the anchored edge rather than to
     the bubble's own centre, which moves as the line length changes. */
  .wr-float-host .wr-float--mascot .wr-bub::after{
    content:"";position:absolute;right:26px;bottom:-8px;width:12px;height:12px;
    background:#fff;border-right:2.5px solid var(--wr-line);
    border-bottom:2.5px solid var(--wr-line);transform:rotate(45deg)}
  .wr-float-host .wr-float--r .wr-bub{right:auto;left:0}
  .wr-float-host .wr-float--r .wr-bub::after{right:auto;left:26px}

  /* each line fades out and the next fades in, so the bubble never looks like
     it is retyping itself */
  .wr-float-host .wr-float--mascot .wr-bub__t{
    display:block;transition:opacity .28s ease, transform .28s ease}
  .wr-float-host .wr-float--mascot .wr-bub.is-swapping .wr-bub__t{
    opacity:0;transform:translateY(-3px)}
}
@media(prefers-reduced-motion:reduce){
  .wr-float-host .wr-float--mascot .wr-bub__t{transition:none}
}

/* ── the standing name under each robot ──────────────────────────────────────
 * The bubble above cycles through what the product does; this does not change.
 * The introduction used to be the first line of the cycle, which meant that for
 * most of any given minute none of the three robots was telling you who it was.
 *
 * Shown from 1440px, the same floor as the robots themselves, and NOT gated
 * behind the bubble's 1560px: the name is the part that has to be there, and it
 * is narrower than the robot it sits under. Pointer events stay off so it can
 * never intercept a click, while the <img> above it stays hoverable. */
/* It takes its fill, radius, border and type from .wr-btn, the same block the
   hero's own Get a Quote button uses, plus the product modifier for the colour.
   Only geometry is set here.

   pointer-events go back ON. .wr-float turns them off for the whole wrapper so
   nothing decorative can swallow a click; this is the one child that is not
   decorative. The <img> above it re-enables them too, for hover.

   NOT the handwriting face, and .wr-btn settles that for free: Nanum Pen
   Script's capital C is barely taller than its lowercase, so "Capital" renders
   as "capital" -- the same font, not the same string, that bit the Capital
   wordmark earlier. A control whose whole job is to name a product cannot set
   one of the three names wrong. */
.wr-float-host .wr-float--mascot .wr-float__cta{display:none}
@media(min-width:1440px){
  body.elementor-kit-8 .wr-float-host .wr-float--mascot .wr-float__cta{
    /* The art does not reach the bottom of its own frame, so 100% is the
       frame's edge and not the robot's feet. --f-pad is that waste as a
       fraction of the image height, measured per asset (0.099 / 0.034 /
       0.052), and the image is square so its rendered height is --f-w. */
    display:block;position:absolute;left:50%;
    top:calc(100% - (var(--f-w) * var(--f-pad, 0)) + 2px);
    transform:translateX(-50%);
    width:max-content;max-width:calc(var(--f-w) + 34px);
    text-align:center;pointer-events:auto;white-space:nowrap;
    font-size:14px;padding:11px 18px;
    box-shadow:0 3px 0 0 rgba(0,0,0,.85)}
  body.elementor-kit-8 .wr-float-host .wr-float--mascot .wr-float__cta:hover,
  body.elementor-kit-8 .wr-float-host .wr-float--mascot .wr-float__cta:focus-visible{
    transform:translateX(-50%) translateY(-3px);
    box-shadow:0 5px 0 0 rgba(0,0,0,.85)}
  body.elementor-kit-8 .wr-float-host .wr-float--mascot .wr-float__cta:focus-visible{
    outline:3px solid var(--wr-ink);outline-offset:3px}
  /* The line under the button, in the same handwriting the hero's own
     "Hey, we're WeReno!" uses. Every string is lowercase, which is what keeps
     it clear of Nanum Pen Script's short capital C -- the flaw that put
     "capital" on the button above it until that moved to Outfit. */
  .wr-float-host .wr-float--mascot .wr-float__note{
    display:block;position:absolute;left:50%;transform:translateX(-50%);
    top:calc(100% - (var(--f-w) * var(--f-pad, 0)) + 50px);
    /* WRAPS. It used to be nowrap under a max-width, which does not constrain
       anything: the box clamped to 92px at 1440 while the text ran on to 187
       and spilled 79px into the copy column and 24px off the screen. The box
       was the only thing measured, so it looked contained and was not. */
    width:max-content;max-width:calc(var(--f-w) - 8px);
    text-align:center;pointer-events:none;
    font-family:"Nanum Pen Script",cursive;font-size:19px;line-height:1.22;
    color:var(--wr-body);opacity:.95}
  /* Below 1560 the margin cannot hold the component at all. The caption would
     break into five lines against a 92px cap, and the button, which cannot
     wrap, leaned 16px into the copy column and 8px off the screen. The bubble
     was already gated here; the mascot now goes with it, so the group appears
     whole or not at all rather than as a robot with its parts spilling. */
  @media(max-width:1559.98px){
    .wr-float-host .wr-float--mascot{display:none}
  }
  @media(prefers-reduced-motion:no-preference){
    body.elementor-kit-8 .wr-float-host .wr-float--mascot .wr-float__cta{
      transition:transform .18s ease, box-shadow .18s ease, background-color .2s ease}
  }
}

/* Capital's wordmark is 1.78:1 where Handyman's is 2.67:1, so at a shared height
   it renders 100px wide against Handyman's 149 and reads as the smaller brand on
   a card sitting right beside it. Height is nudged up so the two carry the same
   visual weight; the images are still sized by height, never stretched. */
.wr-prod .wr-prod-band .wr-mark[src*="capital-wordmark"]{height:84px}
@media(max-width:1024px){.wr-prod .wr-prod-band .wr-mark[src*="capital-wordmark"]{height:70px}}
@media(max-width:767px){.wr-prod .wr-prod-band .wr-mark[src*="capital-wordmark"]{height:58px}}
/* the same on the product pages, where Capital's mark leads the hero */
.rb .wr-eyemark[src*="capital-wordmark"]{height:126px}
@media(max-width:1024px){.rb .wr-eyemark[src*="capital-wordmark"]{height:106px}}
@media(max-width:767px){.rb .wr-eyemark[src*="capital-wordmark"]{height:92px}}

/* ══════════════════════════════════════════════════════════════════════════
   THE FOUR-PRODUCT KIT

   Handyman, Renobot, Capital and Opsonic are four products from one company,
   and a visitor who lands on the second one should recognise the shape of the
   first. Three blocks were missing from that shape and are defined once here:

     .wr-figs   the proof band -- the stat each product has earned
     .wr-ask    what you can actually ask it, as the exchange it would be
     .wr-how    the four steps from your message to the thing being done

   ONE accent, resolved per wrapper. Everything below reads --wr-acc and never
   a product's own colour, so the same rule renders pink on Handyman, blue on
   Renobot, orange on Opsonic and amber on Capital with no duplicated selector.
   The consumer three all wrap in .hm and repaint --hm-red on the SAME element
   (.rbc/.opc), and a custom property resolves against the element that uses
   it, so .hm reading var(--hm-red) picks up whichever repaint is present.
   ══════════════════════════════════════════════════════════════════════════ */
.hm{--wr-acc:var(--hm-red);--wr-acc-deep:var(--hm-deep);--wr-acc-field:var(--hm-field)}
.rb{--wr-acc:var(--rb-amber);--wr-acc-deep:var(--rb-deep);--wr-acc-field:var(--rb-field)}

/* ── the proof band ──────────────────────────────────────────────────────── */
/* Capital had this and the other three did not, which is the whole reason its
   numbers read as the serious ones. Promoted out of wereno-capital.css so all
   four carry their figure in the same frame in the same position. */
.hm .wr-figs,.rb .wr-figs,.wwd-figs{
  display:grid;grid-template-columns:repeat(4,1fr);gap:20px;
  margin:26px 0 0;align-items:stretch}
.hm .wr-figs--3,.rb .wr-figs--3{grid-template-columns:repeat(3,1fr)}
.hm .wr-fig,.rb .wr-fig,.wwd-figs .wr-fig{
  min-width:0;display:flex;flex-direction:column;gap:10px;
  background:#fff;border:3px solid var(--wr-line);border-radius:16px;
  box-shadow:var(--wr-shadow);padding:22px 20px 24px}
.hm .wr-fig__n,.rb .wr-fig__n,.wwd-figs .wr-fig__n{
  font-family:"Outfit",sans-serif;font-size:clamp(30px,3vw,44px);
  font-weight:600;line-height:1;letter-spacing:-.03em;color:var(--wr-ink);
  font-variant-numeric:tabular-nums}
.hm .wr-fig__s,.rb .wr-fig__s,.wwd-figs .wr-fig__s{margin:0;font-size:14.5px;line-height:1.55;color:var(--wr-body)}
/* the accent rule under each figure ties the row to the product it belongs to */
.hm .wr-fig::after,.rb .wr-fig::after{
  content:"";display:block;width:34px;height:4px;border-radius:2px;
  background:var(--wr-acc);margin-top:auto}
/* The band centres its type, so the rule centres with it. Left-aligning a 34px
   dash under a centred figure reads as a mistake rather than a device. */
.hm .wr-nums .wr-fig::after,.rb .wr-nums .wr-fig::after{margin-inline:auto}

/* The band the figures sit in: full-bleed pale field, accent rule across the
   top, centred. Lifted from Capital's rb-status, which is the one all four are
   now copying. */
.hm .wr-nums,.rb .wr-nums{position:relative;text-align:center;border-top:6px solid var(--wr-acc)}
.hm .wr-nums__note,.rb .wr-nums__note{
  margin:24px auto 0;max-width:760px;font-size:16px;line-height:1.7;color:var(--wr-body)}

/* ── what you can ask ────────────────────────────────────────────────────── */
/* The single most load-bearing block on a product page: it is where an abstract
   claim becomes a thing you can picture yourself typing. Each item is a two-line
   exchange rather than a feature, because the exchange IS the product -- you
   send a sentence, something comes back. Documentary colours, same as every
   other transcript on the site: your message is iMessage blue, the reply is
   white. The accent shows up only on the rule, so twelve of these do not turn
   the page into a colour field. */
.hm .wr-askgrid,.rb .wr-askgrid{
  display:grid;grid-template-columns:repeat(3,1fr);gap:22px 20px;margin-top:36px}
.hm .wr-askgrid--2,.rb .wr-askgrid--2{grid-template-columns:repeat(2,1fr)}
.hm .wr-ask,.rb .wr-ask{
  display:flex;flex-direction:column;gap:12px;min-width:0;
  background:#fff;border:3px solid var(--wr-line);border-radius:18px;
  box-shadow:var(--wr-shadow);padding:20px 20px 22px}
.hm .wr-ask__q,.rb .wr-ask__q{
  align-self:flex-start;margin:0;max-width:100%;
  font-family:"Outfit",sans-serif;font-size:16px;line-height:1.5;font-weight:500;
  color:#fff;background:var(--wr-blue);
  border-radius:16px;border-bottom-right-radius:4px;padding:10px 14px}
.hm .wr-ask__a,.rb .wr-ask__a{
  margin:0;padding-top:12px;border-top:3px solid var(--wr-acc);
  font-family:"Outfit",sans-serif;font-size:15.5px;line-height:1.6;color:var(--wr-body)}
.hm .wr-ask__a b,.rb .wr-ask__a b{font-weight:600;color:var(--wr-ink)}

/* ── how it works ────────────────────────────────────────────────────────── */
/* Four steps, and the count is the point: it is short enough to read without
   deciding to. The connector is an ::after on the step rather than a separate
   node, so the markup stays four <li> and the arrow cannot survive a wrap into
   a column where it would point at nothing (the rule turns it off below 1024). */
.hm .wr-how,.rb .wr-how{
  list-style:none;margin:36px 0 0;padding:0;
  display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.hm .wr-how__s,.rb .wr-how__s{
  position:relative;min-width:0;
  background:#fff;border:3px solid var(--wr-line);border-radius:18px;
  box-shadow:var(--wr-shadow);padding:20px 20px 22px}
.hm .wr-how__s::after,.rb .wr-how__s::after{
  content:"";position:absolute;top:50%;right:-19px;z-index:2;
  width:0;height:0;margin-top:-9px;
  border:9px solid transparent;border-left-color:var(--wr-line)}
.hm .wr-how__s:last-child::after,.rb .wr-how__s:last-child::after{display:none}
.hm .wr-how__n,.rb .wr-how__n{
  display:flex;align-items:center;justify-content:center;
  width:34px;height:34px;margin-bottom:14px;
  background:var(--wr-acc);border:3px solid var(--wr-line);border-radius:10px;
  font-family:"Outfit",sans-serif;font-size:16px;font-weight:700;color:var(--wr-ink);
  font-variant-numeric:tabular-nums}
.hm .wr-how__h,.rb .wr-how__h{
  display:block;margin:0 0 6px;
  font-family:"Outfit",sans-serif;font-size:18px;font-weight:500;
  line-height:1.35;letter-spacing:-.012em;color:var(--wr-ink)}
.hm .wr-how__d,.rb .wr-how__d{
  display:block;margin:0;
  font-family:"Outfit",sans-serif;font-size:15px;line-height:1.6;color:var(--wr-body)}

/* ── jot notes ───────────────────────────────────────────────────────────── */
/* The replacement for a paragraph that was carrying four facts. Accent square
   markers, the same device the versus block already uses, available anywhere. */
.hm .wr-jots,.rb .wr-jots{list-style:none;margin:18px 0 0;padding:0}
.hm .wr-jots li,.rb .wr-jots li{
  position:relative;margin:0 0 10px;padding-left:20px;
  font-family:"Outfit",sans-serif;font-size:16px;line-height:1.6;color:var(--wr-body)}
.hm .wr-jots li:last-child,.rb .wr-jots li:last-child{margin-bottom:0}
.hm .wr-jots li::before,.rb .wr-jots li::before{
  content:"";position:absolute;left:0;top:.62em;width:8px;height:8px;
  border-radius:2px;background:var(--wr-acc)}
.hm .wr-jots li b,.rb .wr-jots li b{font-weight:600;color:var(--wr-ink)}

@media(max-width:1024px){
  .hm .wr-figs,.rb .wr-figs,.hm .wr-figs--3,.rb .wr-figs--3,.wwd-figs{grid-template-columns:1fr 1fr;gap:16px}
  .hm .wr-fig,.rb .wr-fig,.wwd-figs .wr-fig{padding:18px 16px 20px}
  .hm .wr-askgrid,.rb .wr-askgrid{grid-template-columns:1fr 1fr;gap:18px 16px}
  .hm .wr-how,.rb .wr-how{grid-template-columns:1fr 1fr;gap:14px}
  /* the arrow points into the gutter once the row wraps, so it comes off */
  .hm .wr-how__s::after,.rb .wr-how__s::after{display:none}
}
@media(max-width:767px){
  .hm .wr-figs,.rb .wr-figs,.hm .wr-figs--3,.rb .wr-figs--3,.wwd-figs,
  .hm .wr-askgrid,.rb .wr-askgrid,.hm .wr-askgrid--2,.rb .wr-askgrid--2,
  .hm .wr-how,.rb .wr-how{grid-template-columns:1fr}
  .hm .wr-ask,.rb .wr-ask{padding:16px 16px 18px;border-radius:16px}
  .hm .wr-how__s,.rb .wr-how__s{padding:16px 16px 18px;border-radius:16px}
  .hm .wr-fig,.rb .wr-fig,.wwd-figs .wr-fig{border-radius:16px}
}

/* The one-line settlement under the ask grid: what the product does by itself,
   and what a person at WeReno does. It belongs directly under the twelve asks
   because that is where a reader starts wondering how much of it is automatic. */
.hm .hm-can__foot,.rb .rb-can__foot{
  margin:36px auto 0;max-width:900px;text-align:center;
  font-size:16px;line-height:1.7;color:var(--wr-body)}
.wr-band .hm-can__foot,.wr-band .rb-can__foot{color:rgba(251,246,239,.72)}

/* ══════════════════════════════════════════════════════════════════════════
   THE HERO AGENTS AT NARROW WIDTHS

   Above 1560px the four agents live in page MARGIN: .wr-float--l anchors to
   `50% - 588px - --f-w - 14px`, which is outside the 1176px container. That
   margin stops existing below 1560, which is why the whole group was hidden
   there and the hero was left as illustrations and arrows around a headline.

   Two replacement layouts, and the decoration gives up its place to them:

     1200-1559   two agents per side column, where the illustrations were
     below 1200  a 2x2 grid under Get a Quote and above the client logos

   Nothing above 1560 changes. .wr-float-pack is display:contents there, which
   takes it out of the box tree entirely, so every absolute position still
   resolves against .wr-float-host exactly as it did before the wrapper
   existed: same anchoring, same parallax, same GIFs.
   ══════════════════════════════════════════════════════════════════════════ */
.wr-float-pack{display:contents}

@media(max-width:1559.98px){
  /* ── the decoration comes off ────────────────────────────────────────────
     EMPTIED, not collapsed. The three columns are elementor-col-33 and carry
     their width as a percentage, so display:none on the outer two leaves the
     copy column sitting at 33% of the container and hard against the left
     edge. Hiding what is INSIDE them keeps the three-column geometry, and the
     headline does not move by a pixel. The rule walks the structure rather
     than naming elementor-element-061f020 and its fifteen siblings, because
     those ids are generated and the next theme export renumbers them. */
  .wr-hero-host > .elementor-container > .elementor-column:first-child .elementor-widget-wrap > *,
  .wr-hero-host > .elementor-container > .elementor-column:last-child  .elementor-widget-wrap > *{
    display:none}

  /* ── and the agents come back ──────────────────────────────────────────── */
  .wr-float-host .wr-hero-host .wr-float--mascot,
  .wr-hero-host .wr-float-pack .wr-float--mascot{display:block}

  /* Both layouts below put the agent in normal flow, so every part of it that
     was absolutely positioned around the robot goes static and simply stacks:
     bubble, robot, button, caption, in that DOM order already. This is much
     less fragile than re-deriving four sets of top/left offsets, and it is
     what makes the component self-sizing inside a grid cell.

     position:relative rather than static on the wrapper and the bubble: both
     have absolutely positioned descendants (the blink patches, the bubble's
     tail) that must keep resolving against them. The inset properties have to
     be cleared by hand because relative HONOURS them, and --f-t is 190px to
     562px depending on the agent. */
  .wr-hero-host .wr-float-pack .wr-float--mascot{
    position:relative;top:auto;left:auto;right:auto;bottom:auto;
    display:flex;flex-direction:column;align-items:center;
    margin-inline:auto}
  .wr-hero-host .wr-float-pack .wr-bub{
    position:relative;top:auto;left:auto;right:auto;bottom:auto;
    max-width:100%;margin-bottom:10px}
  .wr-hero-host .wr-float-pack .wr-float__m{width:100%}
  /* body.elementor-kit-8 IS LOAD-BEARING, and it is the whole bug this line
     fixes. The rule that makes this button absolute is written
     `body.elementor-kit-8 .wr-float-host .wr-float--mascot .wr-float__cta`,
     which is (0,4,1). A plain `.wr-hero-host .wr-float-pack .wr-float__cta` is
     (0,3,0) and loses outright no matter what order the blocks are in, so
     between 1440 and 1559 the caption flowed under the robot while the button
     stayed pinned by top:calc(100% - ...) and rendered BELOW it: the two
     swapped places, on that band of widths only. Below 1440 the other rule is
     not in play at all, which is why every check at 1280 came back clean. */
  body.elementor-kit-8 .wr-hero-host .wr-float-pack .wr-float--mascot .wr-float__cta{
    position:relative;top:auto;left:auto;right:auto;
    max-width:100%;margin:12px auto 0;
    text-align:center;transform:none}
  /* same treatment, for the same reason: the note's own absolute rule is only
     (0,3,0) so source order settles it today, but it sits in the same block as
     the button's and the two should not be one refactor apart from disagreeing */
  body.elementor-kit-8 .wr-hero-host .wr-float-pack .wr-float--mascot .wr-float__note{
    position:relative;top:auto;left:auto;right:auto;
    max-width:100%;margin:8px auto 0;transform:none}
}

/* ── 1200 to 1559: two agents per emptied side column ──────────────────────
   The pack becomes an overlay on the container's own three-column rhythm, so
   the agents land where the illustrations were rather than near where they
   were. pointer-events are off across the pack and back on for the button,
   which is the same arrangement .wr-float already uses at full width. */
@media(min-width:1200px) and (max-width:1559.98px){
  .wr-hero-host .wr-float-pack{
    display:grid;position:absolute;z-index:2;pointer-events:none;
    /* NOT top:0. The theme header is fixed and its two rows overlap this
       section's first 53px, so an agent centred in the full height puts its
       speech bubble under the navigation. Measured: the bubble landed at
       viewport y77 against a header that ends at 110. */
    top:110px;bottom:28px;left:50%;transform:translateX(-50%);
    width:min(1176px,95vw);
    grid-template-columns:23% 1fr 23%;column-gap:2%;padding:0 2%;
    /* start, not centre. Centring makes the top edge a function of the section
       height minus the content height, and BOTH of those move: the section
       grows with the headline's wrap and the content grows with whichever
       bubble line is showing. It landed 2px under the navigation at 1280 and
       cleared it by 5px at 1440, off the same rule. Anchored to the top, the
       clearance is the number written here and nothing else. */
    align-content:start;row-gap:26px}
  /* 195, not the 270 the column could hold: the agent is not just its robot,
     and bubble, art, button and caption come to art plus about 200px. */
  /* One line, stated rather than inherited. The base nowrap for this button
     lives inside a min-width:1440px block, so between 1200 and 1439 it was
     silently wrapping to two lines: the agent grew 23px, which is more than
     the reserve below had spare, and the bottom of the caption pushed out of
     it. The button needs 172px with the .ai on it and the agent is 195px, so
     one line fits with room; only the 2x2 on a phone genuinely cannot. */
  body.elementor-kit-8 .wr-hero-host .wr-float-pack .wr-float--mascot .wr-float__cta{
    white-space:nowrap}
  .wr-hero-host .wr-float-pack .wr-float--mascot{
    --f-w:min(100%,195px);width:var(--f-w);
    /* A FIXED height, not a minimum, and bottom-aligned inside it. The bubble
       cycles through four lines of very different lengths, so in normal flow
       the agent's own height moved with whichever sentence was showing, and
       because grid rows size to their tallest item, one agent's longer line
       pushed the entire second row down the page. Measured over twelve cycles
       the bottom row wandered 40px at 1024 and 24px at 390.

       min-height did not fix it: content taller than the minimum still grows
       the box. A fixed height set to the measured worst case does, and
       justify-content:flex-end decides which end absorbs the difference. The
       robot, the button and the caption never move; a longer line grows upward
       into space that was already empty above the bubble.

       404 is the worst case at this width plus a little: every line of all four
       agents measured, the tallest came to 398. */
    height:404px;justify-content:flex-end}
  /* and the section reserves room for two of them plus the header clearance,
     rather than letting the pack overflow into the band underneath:
     110 top + 404 + 26 gap + 404 + 28 bottom = 972. */
  .wr-hero-host{min-height:980px}
  .wr-hero-host .wr-float-pack [data-chat="hm"] {grid-column:1;grid-row:1}
  .wr-hero-host .wr-float-pack [data-chat="rb"] {grid-column:1;grid-row:2}
  .wr-hero-host .wr-float-pack [data-chat="cap"]{grid-column:3;grid-row:1}
  .wr-hero-host .wr-float-pack [data-chat="op"] {grid-column:3;grid-row:2}
  .wr-hero-host .wr-float-pack .wr-float__cta,
  .wr-hero-host .wr-float-pack .wr-float__i{pointer-events:auto}
}

/* ── below 1200: a 2x2 grid under the button ───────────────────────────────
   The pack leaves the overlay and joins the flow. order:2 puts it after the
   copy and before the section ends, which is the gap between Get a Quote and
   the client logos: those are a separate section, so "after the hero" is the
   same place as "above the carousel". */
@media(max-width:1199.98px){
  .wr-hero-host{display:flex;flex-direction:column}
  .wr-hero-host > .elementor-container{order:1}
  .wr-hero-host > .wr-float-pack{order:2}
  .wr-hero-host .wr-float-pack{
    display:grid;grid-template-columns:1fr 1fr;
    /* 14px, not 40. The four agents sit under Get Started on a phone and the
       button already carries 30px of its own container tail below it, so 40
       on top of that read as a hole between the two halves of the hero. */
    gap:34px 18px;width:min(1176px,90%);margin:14px auto 0;
    position:static;transform:none;pointer-events:auto}
  .wr-hero-host .wr-float-pack .wr-float--mascot{
    --f-w:min(100%,240px);width:var(--f-w);
    /* fixed and bottom-aligned, for the same reason as the flanking layout and
       with the same measurement behind it: 435 was the tallest any of the four
       reached at this width, across every line each of them cycles. */
    /* Measured across every line the four cycle: the tallest any of them
       reaches at this width is 384, so 400 is the fixed height with headroom
       rather than a number with 58px of dead air at the top of every cell. */
    height:400px;justify-content:flex-end}
  /* HERE it wraps. "hey, I am Handyman" is nowrap and measures 182px at every
     width, which does not fit a 2x2 cell on a 390px phone. Two lines keeps all
     four agents on the smallest screen, which is worth more than one line. */
  body.elementor-kit-8 .wr-hero-host .wr-float-pack .wr-float--mascot .wr-float__cta{white-space:normal}
  /* Handyman and Renobot on the top row, Capital and Opsonic underneath: the
     two a homeowner is looking for first, then the two they are not. That is
     also plain DOM order, so there is no explicit placement here at all and
     the grid cannot disagree with the markup the way a hand-placed set can. */
}
@media(max-width:560px){
  .wr-hero-host .wr-float-pack{gap:26px 12px;width:94%}
  /* Same measurement on a phone: 354 is the tallest of the four across the
     whole cycle at 360 and 390, so 368 leaves headroom and takes 18px of dead
     air off the top of the grid. */
  .wr-hero-host .wr-float-pack .wr-float--mascot{--f-w:min(100%,168px);height:368px}
  /* NEGATIVE, and it is not a fudge. The hero column ends 30px below the Get
     Started button (10px of widget padding, 20px of container tail) and that
     tail is theme markup this file does not own. Pulling the grid up by 10
     lands the agents about 55px under the button, which is a section break
     rather than the hole a phone showed before. */
  .wr-hero-host .wr-float-pack{margin-top:-10px}
}
/* The cell height cannot be ONE number across this whole range. The bubble
   lines wrap harder the narrower the cell gets, so the tallest of the four
   runs 354 at 360px and 297 at 767px: a single value tuned for a phone leaves
   57px of dead air at the top of a small tablet, which is exactly what the
   gap under Get Started was made of. Each step is the measured worst case
   across the full cycle, plus about 15px of headroom. */
@media(min-width:481px) and (max-width:620px){
  .wr-hero-host .wr-float-pack .wr-float--mascot{height:352px}
}
@media(min-width:621px) and (max-width:767px){
  .wr-hero-host .wr-float-pack .wr-float--mascot{height:330px}
}
@media(max-width:767px){
}

/* ── the parts that were gated to the margin layout ────────────────────────
 * The bubble, the button and the caption are each hidden by default and
 * revealed by a min-width query (1560 for the bubble, 1440 for the other two),
 * because all three were sized against the page margin: the bubble's max-width
 * is literally `(100vw - 1176px)/2 - 40px`, the margin's own width. None of
 * that survives a layout where the agent sits in a 270px column or a 168px grid
 * cell, so the pack re-states what it needs rather than inheriting a cap that
 * would compute to a negative number here.
 *
 * Scoped to .wr-float-pack throughout, so the agents on the four product pages
 * keep the old behaviour exactly: they are still display:none below 1560 and
 * nothing in this block can reach them.
 */
@media(max-width:1559.98px){
  .wr-hero-host .wr-float-pack .wr-bub{
    display:block;width:auto;min-width:0;max-width:100%;
    background:#fff;color:var(--wr-ink);
    border:2.5px solid var(--wr-line);border-radius:14px;
    box-shadow:0 4px 0 0 rgba(0,0,0,.9);
    padding:9px 12px 10px;
    font-family:"Outfit",sans-serif;font-size:13px;line-height:1.35;font-weight:500;
    text-align:center;
    animation:wr-bub-breathe 11s ease-in-out var(--f-delay,0s) infinite}
  /* The tail, drawn here rather than inherited: the base rule for it lives
     inside the 1560 query with the rest of the margin bubble, so below that
     the ::after had a position and no box and rendered nothing at all.
     It centres, because in a grid cell there is no inner edge for it to point
     away from: left and right are arbitrary here in a way they are not when the
     agent is parked in a page margin and the bubble grows outward. */
  .wr-hero-host .wr-float-pack .wr-bub::after,
  .wr-hero-host .wr-float-pack .wr-float--r .wr-bub::after{
    content:"";position:absolute;left:50%;right:auto;margin-left:-6px;
    bottom:-8px;width:12px;height:12px;background:#fff;
    border-right:2.5px solid var(--wr-line);
    border-bottom:2.5px solid var(--wr-line);transform:rotate(45deg)}

  body.elementor-kit-8 .wr-hero-host .wr-float-pack .wr-float--mascot .wr-float__cta{display:block}

  .wr-hero-host .wr-float-pack .wr-float__note{
    display:block;width:auto;text-align:center;pointer-events:none;
    font-family:"Nanum Pen Script",cursive;font-size:18px;line-height:1.22;
    color:var(--wr-body);opacity:.95}

  /* hover still lifts the art, which is off below 1440 with everything else */
  .wr-hero-host .wr-float-pack .wr-float__i{
    pointer-events:auto;transition:opacity .25s ease, filter .25s ease}
  .wr-hero-host .wr-float-pack .wr-float.is-perked .wr-float__i{
    opacity:1;filter:drop-shadow(0 14px 22px rgba(0,0,0,.2))}
}
@media(max-width:1559.98px) and (prefers-reduced-motion:reduce){
  .wr-hero-host .wr-float-pack .wr-bub{animation:none}
}

/* ── attachments in a message ──────────────────────────────────────────────
 * A photo or a voice note in a thread used to be written "[photo of a
 * receipt]", which is stage direction: it describes the message instead of
 * being one. Phones show an attachment as a file, so these do too, and the
 * filename carries the detail the bracket used to spell out.
 *
 * The chip inverts with the bubble it sits in. Everything currently in the
 * site sits in an outgoing blue one, but a white bubble is one edit away and a
 * white-on-white chip would simply vanish, so the light case is the default
 * and the blue case is the override.
 */
.hm .wr-att,.rb .wr-att{
  display:inline-flex;align-items:center;gap:5px;vertical-align:-3px;
  max-width:100%;
  background:rgba(20,20,20,.07);border:1px solid rgba(20,20,20,.24);
  border-radius:7px;padding:2px 7px 2px 5px;margin-right:5px;
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:.84em;font-weight:500;letter-spacing:-.01em;white-space:nowrap}
.hm .wr-att__i,.rb .wr-att__i{flex:0 0 auto;width:13px;height:13px;opacity:.92}
.hm .wr-ask__q .wr-att,.rb .wr-ask__q .wr-att,
.hm .hm-bub--you .wr-att,.rb .hm-bub--you .wr-att{
  background:rgba(255,255,255,.18);border-color:rgba(255,255,255,.52)}

/* ══════════════════════════════════════════════════════════════════════════
   THE AGENT BUTTON: one line, pressable, and it has an edge

   Three faults, all of them only visible once the agents started rendering
   below 1560 where they had never been seen before:

     1. IT WRAPPED. "hey, I am Handyman.ai" took four lines in a 168px cell on
        a 390px phone. white-space:nowrap and pointer-events live in the
        min-width:1440px block with the rest of the margin layout, so below
        that the button had neither.
     2. IT WAS NOT CLICKABLE. .wr-float turns pointer-events off for the whole
        wrapper so nothing decorative can swallow a click, and the one rule
        that turns them back on for this button was inside the same 1440 block.
        Measured with elementFromPoint: the centre of every agent button on
        every narrow width returned the wrapper, not the link.
     3. IT HAD NO EDGE. Every other button in this system carries the hard
        black offset: the context bar's pills, the footer CTA, the early-access
        card. This one was flat, which made the one control the agents actually
        offer look like a label rather than something you press.
   ══════════════════════════════════════════════════════════════════════════ */
body.elementor-kit-8 .wr-float-host .wr-float--mascot .wr-float__cta{
  border:2px solid var(--wr-line);
  box-shadow:0 4px 0 0 rgba(0,0,0,.9);
  pointer-events:auto;
  white-space:nowrap}

/* Hover and press. The desktop button is centred with translateX(-50%), so its
   lift has to compose with that rather than replace it; the narrow layouts sit
   in normal flow and take a plain translateY. Writing one rule for both would
   silently un-centre the desktop one, which is the kind of thing that only
   shows up on the width nobody screenshots. */
@media(min-width:1560px){
  body.elementor-kit-8 .wr-float-host .wr-float--mascot .wr-float__cta:hover,
  body.elementor-kit-8 .wr-float-host .wr-float--mascot .wr-float__cta:focus-visible{
    transform:translate(-50%,-2px);box-shadow:0 6px 0 0 rgba(0,0,0,.9)}
  body.elementor-kit-8 .wr-float-host .wr-float--mascot .wr-float__cta:active{
    transform:translate(-50%,2px);box-shadow:0 1px 0 0 rgba(0,0,0,.9)}
}
@media(max-width:1559.98px){
  body.elementor-kit-8 .wr-hero-host .wr-float-pack .wr-float--mascot .wr-float__cta:hover,
  body.elementor-kit-8 .wr-hero-host .wr-float-pack .wr-float--mascot .wr-float__cta:focus-visible{
    transform:translateY(-2px);box-shadow:0 6px 0 0 rgba(0,0,0,.9)}
  body.elementor-kit-8 .wr-hero-host .wr-float-pack .wr-float--mascot .wr-float__cta:active{
    transform:translateY(2px);box-shadow:0 1px 0 0 rgba(0,0,0,.9)}
}

/* ── the 2x2 on a phone: the component fills the cell, the robot does not ──
   The button is the widest part of an agent, not the art, so the art is what
   gets capped. Making --f-w the full cell gives the button the whole column to
   sit on one line in, and .wr-float__m keeps the robot at the size it should
   be. Sizing the component to the ART and then asking the button to fit inside
   it is what forced four lines. */
@media(max-width:1199.98px){
  .wr-hero-host .wr-float-pack .wr-float--mascot{--f-w:100%;width:100%}
  .wr-hero-host .wr-float-pack .wr-float__m{width:100%;max-width:240px;margin-inline:auto}
  body.elementor-kit-8 .wr-hero-host .wr-float-pack .wr-float--mascot .wr-float__cta{
    width:max-content;max-width:100%;white-space:nowrap}
}
@media(max-width:767px){
  .wr-hero-host .wr-float-pack .wr-float__m{max-width:168px}
  /* 12.5px and tight padding is what makes the longest of the four names,
     "hey, I am Handyman.ai", fit one line inside the narrowest cell a 2x2
     grid leaves on a 360px phone. Measured, not guessed. */
  body.elementor-kit-8 .wr-hero-host .wr-float-pack .wr-float--mascot .wr-float__cta{
    font-size:12.5px;padding:9px 13px;border-radius:7px}
}

/* ══════════════════════════════════════════════════════════════════════════
   /what-we-do : PAST -> LESSON -> NOW

   The page used to be four AI feature sections (copilot, dashboard,
   compliance, predictive analytics) and said almost nothing about the four
   products WeReno actually sells. It is now the bridge between the two halves
   of the company: a decade of running the work, what that decade taught us,
   and the four agents it turned into.

   The bands reuse .wr-inner, .wr-eyebrow and the .wr-fig numbers kit rather
   than inventing a second set, so they inherit the section rhythm the rest of
   the site already has.
   ══════════════════════════════════════════════════════════════════════════ */
.wwd-past, .wwd-lesson, .wwd-now, .wwd-under{position:relative;padding:86px 0}
.wwd-past{background:var(--wr-ground,#DEE8E8)}
.wwd-lesson{background:#141414;color:#FBF6EF}
.wwd-now{background:#FBF6EF}
.wwd-under{background:#fff}
.wwd-past h2, .wwd-now h2, .wwd-under h2{
  margin:6px 0 14px;font-family:"Outfit",sans-serif;font-size:clamp(28px,3.4vw,44px);
  font-weight:600;letter-spacing:-.03em;line-height:1.08;color:#141414;text-wrap:balance}
.wwd-lesson h2{
  margin:6px 0 30px;font-family:"Outfit",sans-serif;font-size:clamp(28px,3.4vw,44px);
  font-weight:600;letter-spacing:-.03em;line-height:1.08;color:#FBF6EF;text-wrap:balance}
.wwd-lesson .wr-eyebrow{color:#7CD656}
.wwd-lede{max-width:70ch;margin:0 0 34px;font-family:"Outfit",sans-serif;
  font-size:clamp(16px,1.35vw,18px);line-height:1.6;color:rgba(20,20,20,.7)}
.wwd-figs{margin-top:12px}

/* ---- LESSON: the four frictions, then the turn -------------------------- */
.wwd-lesson__grid{display:grid;grid-template-columns:1.05fr .95fr;gap:38px 54px;align-items:start}
.wwd-lesson__l{list-style:none;margin:0;padding:0}
.wwd-lesson__l li{
  padding:16px 0;border-top:2px solid rgba(251,246,239,.18);
  font-family:"Outfit",sans-serif}
.wwd-lesson__l li:first-child{border-top:0;padding-top:0}
.wwd-lesson__l b{display:block;font-size:18px;font-weight:600;letter-spacing:-.02em;color:#FBF6EF}
.wwd-lesson__l span{display:block;margin-top:4px;font-size:15.5px;line-height:1.55;color:rgba(251,246,239,.66)}
.wwd-lesson__turn{
  background:#7CD656;border:3px solid #000000E6;border-radius:20px;
  box-shadow:0 10px 0 0 rgba(0,0,0,.9);padding:30px 30px 32px}
.wwd-turn__k{margin:0 0 10px;font-family:"Outfit",sans-serif;font-size:14px;font-weight:700;
  letter-spacing:.06em;text-transform:uppercase;color:rgba(20,20,20,.62)}
.wwd-turn__big{margin:0;font-family:"Outfit",sans-serif;font-size:clamp(20px,2.1vw,26px);
  font-weight:600;letter-spacing:-.02em;line-height:1.25;color:#141414;text-wrap:balance}

/* ---- NOW: the four agents ----------------------------------------------- */
.wwd-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:24px}
.wwd-card{
  display:flex;flex-direction:column;min-width:0;overflow:hidden;
  background:#fff;border:3px solid #000000E6;border-radius:20px;
  box-shadow:0 8px 0 0 rgba(0,0,0,.9);
  transition:transform .16s ease, box-shadow .16s ease}
.wwd-card:hover{transform:translateY(-3px);box-shadow:0 11px 0 0 rgba(0,0,0,.9)}
.wwd-card__band{
  position:relative;display:flex;align-items:center;min-height:124px;
  padding:20px 172px 20px 26px;border-bottom:3px solid #000000E6}
.wwd-card--handyman .wwd-card__band{background:#FF003F}
.wwd-card--renobot .wwd-card__band{background:#35C4F0}
.wwd-card--opsonic .wwd-card__band{background:#FD6E00}
.wwd-card--capital .wwd-card__band{background:#FDC313}
.wwd-card__mark{width:auto;height:38px;max-width:100%;filter:drop-shadow(0 3px 6px rgba(0,0,0,.18))}
.wwd-card__bot{
  position:absolute;right:-6px;bottom:-12px;width:158px;height:auto;
  filter:drop-shadow(0 8px 14px rgba(0,0,0,.24))}
.wwd-card__in{display:flex;flex-direction:column;flex:1 1 auto;gap:9px;padding:24px 26px 26px}
.wwd-card__n{margin:0;font-family:"Outfit",sans-serif;font-size:22px;font-weight:600;
  letter-spacing:-.025em;line-height:1.1;color:#141414}
.wwd-card__role{margin:0;font-family:"Outfit",sans-serif;font-size:14px;font-weight:700;
  letter-spacing:.03em;text-transform:uppercase;color:rgba(20,20,20,.5)}
.wwd-card__p{margin:0;font-family:"Outfit",sans-serif;font-size:15.5px;line-height:1.58;
  color:rgba(20,20,20,.78)}
.wwd-card__who{margin:0;font-family:"Outfit",sans-serif;font-size:13.5px;font-weight:600;
  letter-spacing:.01em;color:rgba(20,20,20,.5)}
.wwd-card__go{
  align-self:flex-start;margin-top:auto;padding:10px 18px;
  border:2.5px solid #000000E6;border-radius:999px;background:#FBF6EF;
  font-family:"Outfit",sans-serif;font-size:14.5px;font-weight:600;color:#141414;
  text-decoration:none;box-shadow:0 3px 0 0 rgba(0,0,0,.9);
  transition:transform .14s ease, box-shadow .14s ease, background .14s ease}
.wwd-card__go::after{content:" \2192"}
.wwd-card--handyman .wwd-card__go:hover{background:#FF003F}
.wwd-card--renobot .wwd-card__go:hover{background:#35C4F0}
.wwd-card--opsonic .wwd-card__go:hover{background:#FD6E00}
.wwd-card--capital .wwd-card__go:hover{background:#FDC313}
.wwd-card__go:hover{transform:translateY(-2px);box-shadow:0 5px 0 0 rgba(0,0,0,.9);color:#141414}
.wwd-card__go:active{transform:translateY(2px);box-shadow:0 1px 0 0 rgba(0,0,0,.9)}
.wwd-card__go:focus-visible{outline:3px solid #141414;outline-offset:3px}

/* ---- UNDER: what the agents run on -------------------------------------- */
.wwd-under__grid{display:grid;grid-template-columns:repeat(4,1fr);gap:20px}
.wwd-under__c{background:#FBF6EF;border:2.5px solid #000000E6;border-radius:16px;
  box-shadow:0 5px 0 0 rgba(0,0,0,.9);padding:22px 20px 24px}
.wwd-under__c h3{margin:0 0 8px;font-family:"Outfit",sans-serif;font-size:18px;font-weight:600;
  letter-spacing:-.02em;color:#141414}
.wwd-under__c p{margin:0;font-family:"Outfit",sans-serif;font-size:14.5px;line-height:1.55;
  color:rgba(20,20,20,.72)}

@media(max-width:1024px){
  .wwd-lesson__grid{grid-template-columns:1fr;gap:30px}
  .wwd-under__grid{grid-template-columns:repeat(2,1fr)}
}
@media(max-width:820px){
  .wwd-grid{grid-template-columns:1fr}
  .wwd-card__band{padding-right:150px}
}
@media(max-width:767px){
  .wwd-past,.wwd-lesson,.wwd-now,.wwd-under{padding:58px 0}
  .wwd-under__grid{grid-template-columns:1fr}
  .wwd-card__band{min-height:104px;padding:16px 132px 16px 20px}
  .wwd-card__mark{height:31px}
  .wwd-card__bot{width:130px;right:-4px;bottom:-10px}
  .wwd-card__in{padding:20px 20px 22px}
  .wwd-lesson__turn{padding:24px 22px 26px}
}
@media(prefers-reduced-motion:reduce){
  .wwd-card,.wwd-card__go{transition:none}
}

/* ---- /what-we-do : the four client quotes ------------------------------- */
.wwd-quotes{padding:86px 0;background:var(--wr-ground,#DEE8E8)}
.wwd-quotes h2{margin:6px 0 30px;font-family:"Outfit",sans-serif;
  font-size:clamp(28px,3.4vw,44px);font-weight:600;letter-spacing:-.03em;
  line-height:1.08;color:#141414;text-wrap:balance}
.wwd-quotes__grid{display:grid;grid-template-columns:repeat(2,1fr);gap:22px}
.wwd-q{margin:0;display:flex;flex-direction:column;gap:16px;
  background:#fff;border:3px solid #000000E6;border-radius:18px;
  box-shadow:0 6px 0 0 rgba(0,0,0,.9);padding:26px 26px 24px}
.wwd-q blockquote{margin:0;font-family:"Outfit",sans-serif;font-size:16.5px;
  line-height:1.6;color:rgba(20,20,20,.82)}
.wwd-q blockquote::before{content:"\201C"}
.wwd-q blockquote::after{content:"\201D"}
.wwd-q figcaption{margin-top:auto;font-family:"Outfit",sans-serif;font-size:15px;
  font-weight:600;letter-spacing:-.01em;color:#141414}
.wwd-q figcaption span{display:block;font-weight:400;font-size:13.5px;
  color:rgba(20,20,20,.55)}
@media(max-width:767px){
  .wwd-quotes{padding:58px 0}
  .wwd-quotes__grid{grid-template-columns:1fr;gap:16px}
  .wwd-q{padding:22px 20px 20px;border-radius:16px}
  .wwd-q blockquote{font-size:15.5px}
}
