/* =========================================================================
   MS Production — Elementor layer

   style.css is a straight copy of the static build's stylesheet and is
   deliberately never edited here, so the two stay in sync. Everything that
   exists only because the sections are Elementor widgets lives in this file,
   which loads after it and only when Elementor is active.

   Four things:
     1. Elementor's own wrappers, taken out of the way
     2. stacked service rows, spaced like the single static section
     3. .factor-from — the "starting from" line, a widget-only control
     4. .svc-icon-frame--photo — the photo variant of the service-row frame
   ========================================================================= */

/* ---------------------------------------------------------------- 1. resets
   Every one of these widgets renders a complete <section class="sec"> with its
   own vertical rhythm and a .wrap for the measure. Elementor adds a 10px
   column padding and a boxed 1140px container on top, which double-pads the
   sections and breaks the full-bleed backgrounds. The imported pages already
   set full-width layout and zero padding per section; these rules do the same
   for a widget dropped into a column by hand. */
[class*="elementor-widget-msp-"] > .elementor-widget-container{margin:0;padding:0}
.elementor-section-full_width > .elementor-container{max-width:none}
.elementor-widget-wrap:has(> [class*="elementor-widget-msp-"]){padding:0}
.elementor-element-populated:has(> .elementor-widget-wrap > [class*="elementor-widget-msp-"]){padding:0}

/* ------------------------------------------------------ 2. stacked svc rows
   In the static pages every row lives inside ONE <section class="sec
   sec-svcrows">, so the space between rows is the .svc-rows gap. As widgets
   each row is its own section, which would stack two lots of section padding
   between them — 230px instead of 96px at desktop width. These two rules put
   the original rhythm back: a row that follows another loses its top padding,
   and a row followed by another is spaced by the .svc-rows gap. Without :has
   support the rows simply sit further apart, which is a spacing difference
   rather than a broken page. */
.elementor-widget-msp-service-row + .elementor-widget-msp-service-row .sec-svcrows{padding-top:0}
.elementor-widget-msp-service-row:has(+ .elementor-widget-msp-service-row) .sec-svcrows{padding-bottom:clamp(56px,8vw,96px)}

/* ------------------------------------------------------------ 3. price line
   The static pages carry the starting figure inside the section sub-heading.
   As a widget it is a control of its own, so it needs a rule of its own. */
.factor-from{
  max-width:1000px;margin:22px auto 0;text-align:center;
  color:var(--muted);font-size:.95rem;line-height:1.6;
}
.factor-from b, .factor-from strong{color:var(--yellow);font-weight:700}

/* ----------------------------------------------------------- 4. photo frame
   The icon frame centres a small SVG in a padded box; a photograph has to
   fill the same box instead, so the grid track goes and the image is cropped
   to the frame's radius. The inner glow is switched off — over a photo it
   reads as a smear. */
.svc-icon-frame--photo{display:block;overflow:hidden;padding:0}
.svc-icon-frame--photo::before{display:none}
.svc-icon-frame--photo img{
  width:100%;height:100%;object-fit:cover;display:block;border-radius:inherit;
}
/* The number chip sits over the photo, so it has to stay above it and stay
   legible against whatever is underneath. */
.svc-icon-frame--photo .svc-icon-tag{z-index:2;box-shadow:0 6px 18px rgba(0,0,0,.45)}

/* ------------------------------------------------------- 5. photo in a slot
   Every empty image slot in this design is drawn in CSS (.ph plus a tone
   class). As widgets those slots take real uploads, so an uploaded photo has
   to fill the same shape and the CSS pattern has to get out of its way. */
.ph.has-img{background-image:none !important}
.ph.has-img img{
  width:100%;height:100%;object-fit:cover;display:block;border-radius:inherit;
}

/* --------------------------------------------------- 6. article blocks
   A post's body is several widgets rather than one, so the images between
   them can be replaced and moved on their own. Only the first and last block
   carry the section's outer spacing; the blocks between sit flush, so the
   column reads as one article instead of a stack of boxes. */
.sec-article--pad-none{padding-block:0}
.sec-article--pad-top{padding-block:clamp(64px,9vw,120px) 0}
.sec-article--pad-bottom{padding-block:0 clamp(64px,9vw,120px)}

/* ------------------------------------------------------- 7. the drone flyway
   The drones were crossing in 30 seconds, which reads as traffic. At 82 they
   read as sky — which is what an ambient layer has to do, because a drone is a
   recognisable shape and the eye follows a shape in a way it never follows a
   texture. Behind a heading that is a cost, so the opacity comes down with the
   speed. style.css is a straight copy of the static build and is never edited,
   so the new timing lives here, where it loads after it. */
.bg-flyway{opacity:.15}
.bg-flyway .drone-track{animation-duration:82s}

/* ------------------------------------------------------------------ 8. maps
   The map starts as a card, not as a Google iframe — see widgets/map.php for
   why. Both states occupy the same box, so nothing on the page moves when the
   real map arrives; the height comes from the widget's own control. */
.sec-map{background:var(--bg-2)}
.msp-map{
  position:relative;height:420px;border-radius:var(--r);overflow:hidden;
  border:1px solid var(--line);background:var(--bg-1);
}
.msp-map iframe{width:100%;height:100%;border:0;display:block;filter:saturate(.85)}

/* The card. The faint grid behind it is the same diagonal weave the rest of
   the site uses for an empty slot, so an unopened map reads as part of the
   design rather than as something that failed to load. */
.msp-map--facade{
  display:grid;place-items:center;text-align:center;
  background-image:
    linear-gradient(135deg,rgba(255,255,255,.035) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.035) 50%,rgba(255,255,255,.035) 75%,transparent 75%);
  background-size:14px 14px;
}
.msp-map-card{padding:clamp(22px,4vw,40px);max-width:52ch}
.msp-map-pin{width:34px;height:34px;color:var(--yellow);display:block;margin:0 auto 14px}
.msp-map-address{
  font-family:var(--f-head);font-weight:600;
  font-size:clamp(1.02rem,2vw,1.2rem);line-height:1.5;margin:0;
}
.msp-map-note{color:var(--muted);font-size:.92rem;margin:10px 0 0}
.msp-map-actions{
  display:flex;flex-wrap:wrap;gap:14px 22px;
  align-items:center;justify-content:center;margin-top:22px;
}
.msp-map-load{cursor:pointer;border:0;font:inherit}
.msp-map-open{
  display:inline-flex;align-items:center;gap:7px;
  color:var(--muted);font-weight:600;font-size:.93rem;text-decoration:none;
}
.msp-map-open:hover{color:var(--yellow)}
.msp-map-open svg{width:14px;height:14px}

/* -------------------------------------------------- 9. a person's accounts
   Under the role in the team grid. They are small and quiet on purpose: the
   name and the face are what the grid is for, and six bright icons per person
   would turn it into a directory of other websites. */
.member-social{
  list-style:none;display:flex;gap:12px;justify-content:center;
  margin:12px 0 0;padding:0;
}
.member-social a{
  display:grid;place-items:center;width:30px;height:30px;
  border-radius:50%;color:var(--dim);
  border:1px solid var(--line);
  transition:color .18s ease,border-color .18s ease,transform .18s ease;
}
.member-social a:hover,.member-social a:focus-visible{
  color:var(--yellow);border-color:rgba(255,192,29,.45);transform:translateY(-2px);
}
.member-social svg{width:15px;height:15px}
.member.todo .member-social{display:none}

/* ------------------------------------------------------------ 10. the rail
   Fixed to the side of the window, vertically centred. It is a small target
   sitting over the page, so it stays narrow, keeps clear of the WhatsApp and
   back-to-top buttons on the right, and disappears on a phone. */
.msp-rail{
  position:fixed;top:50%;transform:translateY(-50%);z-index:40;
  display:flex;flex-direction:column;align-items:center;gap:14px;
  pointer-events:none;
}
.msp-rail--left{left:clamp(10px,1.6vw,22px)}
.msp-rail--right{right:clamp(10px,1.6vw,22px)}
.msp-rail-label{
  writing-mode:vertical-rl;text-orientation:mixed;
  font-family:var(--f-head);font-size:11px;font-weight:700;
  letter-spacing:.22em;text-transform:uppercase;color:var(--dim);
}
.msp-rail-line{width:1px;height:38px;background:var(--line)}
.msp-rail ul{
  list-style:none;margin:0;padding:0;pointer-events:auto;
  display:flex;flex-direction:column;gap:10px;
}
.msp-rail a{
  display:grid;place-items:center;width:34px;height:34px;
  border-radius:50%;color:var(--muted);
  background:rgba(20,20,20,.6);border:1px solid var(--line);
  backdrop-filter:blur(6px);
  transition:color .18s ease,border-color .18s ease,transform .18s ease;
}
.msp-rail a:hover,.msp-rail a:focus-visible{
  color:var(--yellow);border-color:rgba(255,192,29,.45);transform:scale(1.08);
}
.msp-rail svg{width:16px;height:16px}
@media (max-width:900px){
  .msp-rail:not(.msp-rail--mobile){display:none}
  .msp-rail--mobile .msp-rail-label,.msp-rail--mobile .msp-rail-line{display:none}
}

/* ----------------------------------------------------------- 11. the popup
   Nothing here is painted until the script unsets [hidden], so the markup
   sitting in the page costs a visitor who never sees it nothing at all. The
   box is centred by grid rather than by transform, so the opening animation
   is free to use transform without fighting the centring. */
.msp-pop{position:fixed;inset:0;z-index:120;display:grid;place-items:center;padding:20px}
.msp-pop[hidden]{display:none}
.msp-pop-backdrop{
  position:absolute;inset:0;background:rgba(8,8,8,.72);
  backdrop-filter:blur(3px);opacity:0;transition:opacity .22s ease;
}
.msp-pop-box{
  position:relative;width:min(760px,100%);max-height:88vh;overflow:auto;
  display:grid;grid-template-columns:minmax(0,1fr);
  background:var(--bg-2);border:1px solid var(--line);
  border-radius:var(--r);box-shadow:0 30px 80px rgba(0,0,0,.6);
  opacity:0;transform:translateY(14px) scale(.985);
  transition:opacity .22s ease,transform .22s ease;
}
.msp-pop.is-open .msp-pop-backdrop{opacity:1}
.msp-pop.is-open .msp-pop-box{opacity:1;transform:none}
.msp-pop-art{display:none}
/* Two columns only when there is actually a picture to put in one. Without
   :has the box stays a single column, which is the correct layout for the
   no-picture case anyway — so the fallback is never wrong, only less clever. */
@media (min-width:760px){
  .msp-pop-box:has(.msp-pop-art){grid-template-columns:minmax(0,.8fr) minmax(0,1fr)}
  .msp-pop-art{display:block}
}
/* With no picture the box does not need to be as wide as a two-column one. */
.msp-pop-box:not(:has(.msp-pop-art)){width:min(520px,100%)}
.msp-pop-art img{width:100%;height:100%;object-fit:cover;display:block}
.msp-pop-body{padding:clamp(24px,4vw,40px)}
.msp-pop-body h2{
  font-family:var(--f-head);font-weight:800;letter-spacing:-.02em;
  font-size:clamp(1.35rem,3vw,1.85rem);line-height:1.18;margin:0;
}
.msp-pop-body h2 em{font-style:normal;color:var(--yellow)}
.msp-pop-text{color:var(--muted);margin:14px 0 0;font-size:.97rem}
.msp-pop-actions{display:flex;flex-wrap:wrap;align-items:center;gap:12px 20px;margin-top:24px}
.msp-pop-no{
  background:none;border:0;padding:0;cursor:pointer;font:inherit;
  color:var(--dim);text-decoration:underline;text-underline-offset:3px;
}
.msp-pop-no:hover{color:var(--muted)}
.msp-pop-close{
  position:absolute;top:12px;right:12px;z-index:2;
  width:34px;height:34px;display:grid;place-items:center;cursor:pointer;
  border-radius:50%;color:var(--muted);
  background:rgba(12,12,12,.6);border:1px solid var(--line);
}
.msp-pop-close:hover{color:var(--white)}
.msp-pop-close svg{width:16px;height:16px}

@media (prefers-reduced-motion: reduce){
  .msp-pop-backdrop,.msp-pop-box{transition:none}
  .msp-pop-box{transform:none}
  .member-social a:hover,.msp-rail a:hover{transform:none}
}

/* ------------------------------------------------- 12. an uploaded icon
   The "Other" network takes the network's own icon file rather than a mark
   drawn here. It has to sit in the same box as the inline ones, and take the
   same muted-to-yellow treatment — so it is masked to its own shape and
   coloured from the link, which works for any single-colour PNG or SVG. */
.social-img{
  width:15px;height:15px;object-fit:contain;display:block;
}
.msp-rail .social-img{width:16px;height:16px}
.foot-social .social-img{width:18px;height:18px}

/* ---------------------------------------------- 13. play a card's video
   The button sits over the whole frame, but only the centred card's button
   takes the pointer — everywhere else the click falls through to the card and
   does what it always did, which is bring that card to the middle. So the
   strip still works the way people have learnt it, and the middle card gains
   one more thing it can do. Side cards keep a dimmed badge, which is how you
   can tell at a glance which cards have a film behind them. */
.cov-play{
  position:absolute;inset:0;z-index:3;
  display:grid;place-items:center;
  background:none;border:0;padding:0;margin:0;
  color:#fff;cursor:pointer;
  pointer-events:none;
  text-decoration:none;
}
.cov-play svg{
  width:clamp(44px,5.2vw,64px);height:clamp(44px,5.2vw,64px);
  opacity:.55;transform:scale(.94);
  filter:drop-shadow(0 6px 20px rgba(0,0,0,.55));
  transition:opacity .22s ease,transform .22s ease;
}
.cov[data-pos="0"] .cov-play{pointer-events:auto}
.cov[data-pos="0"] .cov-play svg{opacity:.9;transform:scale(1)}
.cov[data-pos="0"] .cov-play:hover svg,
.cov[data-pos="0"] .cov-play:focus-visible svg{opacity:1;transform:scale(1.07);color:var(--yellow)}
.cov-play:focus-visible{outline:2px solid var(--yellow);outline-offset:-6px;border-radius:inherit}

/* ------------------------------------------------------ 14. the lightbox
   Shared by anything that plays a video. The frame keeps the provider's own
   shape — 16:9 for YouTube, portrait for a Reel — so neither one is letterboxed
   inside the other's box. The iframe is built on the click and removed on the
   close, which is the only reliable way to stop a third-party player's sound. */
.msp-lb{position:fixed;inset:0;z-index:140;display:grid;place-items:center;padding:clamp(14px,3vw,36px)}
.msp-lb[hidden]{display:none}
.msp-lb-backdrop{
  position:absolute;inset:0;background:rgba(6,6,6,.86);
  backdrop-filter:blur(4px);opacity:0;transition:opacity .22s ease;
}
.msp-lb-box{
  position:relative;width:min(1100px,100%);
  opacity:0;transform:scale(.985);
  transition:opacity .22s ease,transform .22s ease;
}
.msp-lb.is-open .msp-lb-backdrop{opacity:1}
.msp-lb.is-open .msp-lb-box{opacity:1;transform:none}
.msp-lb-frame{
  aspect-ratio:16 / 9;width:100%;max-height:82vh;
  margin-inline:auto;
  background:#000;border-radius:var(--r);overflow:hidden;
  border:1px solid var(--line);
}
/* A Reel is portrait, so it gets a portrait box rather than black bars. */
.msp-lb-frame[data-provider="instagram"]{width:min(420px,100%);background:var(--bg-1)}
.msp-lb-frame iframe{width:100%;height:100%;border:0;display:block}
.msp-lb-close{
  position:absolute;top:-46px;right:0;
  width:38px;height:38px;display:grid;place-items:center;cursor:pointer;
  border-radius:50%;color:var(--muted);
  background:rgba(20,20,20,.75);border:1px solid var(--line);
}
.msp-lb-close:hover{color:var(--white)}
.msp-lb-close svg{width:17px;height:17px}
@media (max-width:640px){
  .msp-lb-close{top:auto;bottom:-48px;right:50%;transform:translateX(50%)}
}
@media (prefers-reduced-motion: reduce){
  .msp-lb-backdrop,.msp-lb-box,.cov-play svg{transition:none}
  .msp-lb-box{transform:none}
}

/* ------------------------------------------------------------ 15. the logo
   An uploaded logo file has no size of its own here — the header is a fixed
   height and the file could be any dimensions, so without this a large upload
   would push the whole bar open. These are the starting sizes; the widget's
   own control overrides them, per screen size. width:auto keeps the logo's
   proportions whatever height it is set to, so it can never stretch. */
.logo-img{height:52px;width:auto;max-width:200px;display:block;object-fit:contain}
.foot-logo .logo-img{height:76px;max-width:260px}
@media (max-width:720px){
  .logo-img{height:42px;max-width:150px}
}

/* ------------------------------------------------- 16. zoomed pictures
   The Pictures controls can push a photo past the edge of its frame. Most
   frames already clip — .ph has overflow:hidden, and so does the service
   row's photo frame — but the popup's picture column did not, and a scaled
   image there would have pushed a scrollbar into the dialog. */
.msp-pop-art{overflow:hidden}
