/* ==================================================================
   0. FONTS, self-hosted Inter, the four weights the design uses.
      Never Google's CDN: a German court held that loading fonts from it
      transmits visitor IPs without consent, and these pages sell GDPR
      and NIS2 compliance. Served here from the site so the proof renders
      with the same metrics as the frame.
   ================================================================== */
@font-face{font-family:"Inter";font-style:normal;font-weight:400;font-display:swap;
  src:url("../fonts/Inter-Regular.woff2") format("woff2")}
@font-face{font-family:"Inter";font-style:normal;font-weight:500;font-display:swap;
  src:url("../fonts/Inter-Medium.woff2") format("woff2")}
@font-face{font-family:"Inter";font-style:normal;font-weight:600;font-display:swap;
  src:url("../fonts/Inter-SemiBold.woff2") format("woff2")}
@font-face{font-family:"Inter";font-style:normal;font-weight:700;font-display:swap;
  src:url("../fonts/Inter-Bold.woff2") format("woff2")}

/* ==================================================================
   1. TOKENS, from Figma variable collections "1. Primitive" / "2. Semantic"
      (get_variable_defs on 95:472). These map 1:1 to theme.json.
   ================================================================== */
:root{
  --ls-text-primary:#1F2937;
  --ls-text-brand:#005653;
  --ls-text-secondary:#5B5B5B;
  /* Darkened from #8A9199 on 18 Aug 2026. At the old value this sat at
     2.94:1 on the subtle surface and 3.19:1 on white, under the 4.5:1
     WCAG AA minimum for body text. It carries the solution group labels,
     the mobile menu label and the footer legal line. #6C7177 measures
     4.54:1 and 4.92:1, and stays lighter than --ls-text-secondary so the
     hierarchy is unchanged. */
  --ls-text-muted:#6C7177;
  --ls-text-inverse:#FFFFFF;
  --ls-text-link:#016E6A;
  --ls-text-accent-on-dark:#D4E9BA;
  --ls-accent-marker:#80BE35;
  --ls-accent-on-accent:#1F2937;
  /* Lime, for accent type and hairlines ON DARK only. Raw hex in Figma
     (no variable binding), nodes 90:390 line 3 and 90:559-561. */
  --ls-accent-lime:#A8E06A;
  --ls-action-primary:#005653;
  --ls-action-primary-text:#FFFFFF;
  --ls-surface-page:#FFFFFF;
  --ls-surface-subtle:#F4F6F7;
  --ls-surface-accent:#F2F8EC;
  --ls-border-default:#DDE1E4;
  /* Error state, transcribed from the Input component's State=Error
     variant: field stroke and helper text, nodes 52:16 and 52:18. */
  --ls-text-error:#B3261E;
  --ls-radius-sm:4px;
  --ls-container:1200px;
  --ls-gutter:120px;
  --ls-font:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;

  /* Section photography, Figma's own source bitmaps, pulled from the
     frames' image fills via download_assets (NOT re-exports of the frame,
     and NOT substitutes from the sourcing notes).
     breather 2400x1600 · approach 2400x1600 · hero 2400x1380 */
  --ls-hero-image:url("/wp-content/uploads/2026/08/logicsure-hero-cyber-security-2400.jpg");
  --ls-breather-image:url("/wp-content/uploads/2026/08/logicsure-breather-cyber-security.jpg");
  --ls-approach-image:url("/wp-content/uploads/2026/08/logicsure-approach-cyber-security.jpg");
}

/* ==================================================================
   2. RESET + BASE
   ================================================================== */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;
  font-family:var(--ls-font);
  font-size:15px;line-height:1.65;letter-spacing:0;font-weight:400;
  color:var(--ls-text-secondary);
  background:var(--ls-surface-page);
  -webkit-font-smoothing:antialiased;
}
h1,h2,h3,h4,p,ul,li,figure{margin:0;padding:0}
ul{list-style:none}
a{color:inherit;text-decoration:none}
img,svg{display:block;max-width:100%}

/* Keyboard focus. The theme already rings the capability cards, form fields,
   the burger, the mega menu, the mobile panel and the back to top control.
   These are the interactive elements that were left to the browser's own
   ring, which differs between browsers and does not match the brand. Same
   2px teal everywhere, on :focus-visible only, so a mouse click never
   shows it. On the dark bands the teal would disappear into the background,
   so those switch to white. */
.ls-btn:focus-visible,
.ls-nav__link:focus-visible,
.ls-anchors a:focus-visible,
.ls-footer a:focus-visible,
.ls-link:focus-visible,
.ls-crumbs a:focus-visible{
  outline:2px solid var(--ls-text-link);
  outline-offset:2px;
  border-radius:2px;
}
.ls-hero .ls-btn:focus-visible,
.ls-hero a:focus-visible,
.ls-cta .ls-btn:focus-visible{outline-color:#FFFFFF}

/* Shared: the 1200 container inside a 120 gutter */
.ls-container{
  width:100%;max-width:var(--ls-container);
  margin-inline:auto;
}
.ls-section{padding-inline:var(--ls-gutter)}

/* Type roles, straight off the Figma text styles */
.ls-eyebrow{                     /* Label/Eyebrow 600 11 / 1.3 / +1.6 */
  display:flex;align-items:center;gap:10px;
  font-size:11px;font-weight:600;line-height:1.3;letter-spacing:1.6px;
  text-transform:uppercase;color:var(--ls-text-brand);
}
.ls-eyebrow::before{content:"";width:24px;height:2px;background:var(--ls-accent-marker);flex:none}
.ls-eyebrow--on-dark{color:var(--ls-text-accent-on-dark)}

.ls-h2{                          /* 700 34 / 1.2 / -0.3 */
  font-size:34px;font-weight:700;line-height:1.2;letter-spacing:-.3px;
  color:var(--ls-text-brand);
}
.ls-h2--on-dark{color:var(--ls-text-inverse)}
.ls-h4{font-size:17px;font-weight:600;line-height:1.35;letter-spacing:0;color:var(--ls-text-brand)}
.ls-body-lg{font-size:17px;font-weight:400;line-height:1.6}
.ls-body{font-size:15px;font-weight:400;line-height:1.65}
.ls-body-sm{font-size:13.5px;font-weight:400;line-height:1.6}

/* Button, component 51:33. Accent is the only sanctioned green-behind-text
   use (label #1F2937 on #80BE35 = 8.39:1), for dark teal bands only. */
.ls-btn{
  display:inline-flex;align-items:center;
  font-size:15px;font-weight:600;line-height:1.2;letter-spacing:.1px;
  padding:14px 24px;border-radius:var(--ls-radius-sm);border:0;
  cursor:pointer;white-space:nowrap;
}
.ls-btn--primary{background:var(--ls-action-primary);color:var(--ls-action-primary-text)}
.ls-btn--accent{background:var(--ls-accent-marker);color:var(--ls-accent-on-accent)}
.ls-btn--ghost{
  background:transparent;color:var(--ls-text-inverse);
  border:1px solid rgba(255,255,255,.55);
}

/* ==================================================================
   3. HEADER, node 95:473 (master 54:2), 1440x84
   ================================================================== */
.ls-header{
  height:84px;background:var(--ls-surface-page);
  border-bottom:1px solid var(--ls-border-default);
  display:flex;align-items:center;padding-inline:var(--ls-gutter);
  /* positioned so the mega menu and the mobile panel can hang beneath it
     without becoming flex children and stretching the 84px bar. */
  position:relative;
}
.ls-header__inner{display:flex;align-items:center;gap:40px;width:100%;max-width:var(--ls-container);margin-inline:auto}
/* The designer's lockup carries the tagline on one wide line, so it is
   3.553:1 against the plain wordmark's 4.626:1, at 220px it stands 62px
   tall and still clears the 84px header with 11px either side. The header
   height is unchanged, which is what keeps all 15 frame heights valid.
   The chevron mark was tried alongside this on 17 Aug 2026 and reverted on
   18 Aug: the lockup carries the name and the tagline on its own. */
.ls-header__logo{width:220px;height:62px;object-fit:contain;flex:none}
.ls-header__spacer{flex:1}
.ls-nav{display:flex;align-items:center;gap:32px}
.ls-nav__link{
  display:flex;flex-direction:column;align-items:center;gap:6px;
  padding:8px 0;font-size:15px;line-height:1.65;color:var(--ls-text-primary);
}
.ls-nav__link.is-active{color:var(--ls-text-brand)}
/* active is marked by a green rule, never by green text.
   Every link carries the rule so all the boxes are the same height, the
   active one just colours it in. Without this the active item is 8px taller
   (6px gap + 2px rule) and, because .ls-nav centres its children, its label
   sits about 4px above its neighbours. Which link carries the class is
   decided at render time in functions.php, not written into the markup. */
.ls-nav__link::after{content:"";display:block;width:100%;height:2px;background:transparent}
.ls-nav__link.is-active::after{background:var(--ls-accent-marker)}
.ls-header .ls-btn{flex:none}

/* ==================================================================
   4. HERO, node 95:474, 1440x480
   Scrim runs LIGHT to DARK left to right: the photo reads on the left,
   the type sits over the dark end. (The Divi build had this reversed.)
   ================================================================== */
.ls-hero{
  min-height:480px;display:flex;align-items:center;
  padding-inline:var(--ls-gutter);
  background-color:var(--ls-teal-900,#003D3B);
  background-image:
    linear-gradient(90deg,rgba(0,61,59,.34) 0%,rgba(0,61,59,.62) 32%,rgba(0,49,47,.86) 62%,rgba(0,49,47,.95) 100%),
    var(--ls-hero-src);
  background-repeat:no-repeat,no-repeat;
  background-size:cover,cover;
  /* The frames crop the hero photo to a band of its height rather than
     centring it, AI Solutions shows 20%, 78%, Salesforce 34%, 84%. The
     equivalent CSS focal point is ty/(1-d), emitted per page as
     --ls-hero-focus by logicsure_page_images(). */
  background-position:center center,center var(--ls-hero-focus,50%);
}
.ls-hero__inner{position:relative;width:100%;max-width:var(--ls-container);margin-inline:auto}
/* Decorative shield, node 95:661, 120x120, x1130/y180, opacity .85.
   Dead-centre vertically (180+60 = 240 of 480), 70px inside the container
   right edge, so it is pinned to the container not a 1440 canvas. */
.ls-hero__mark{
  position:absolute;right:70px;top:50%;transform:translateY(-50%);
  width:120px;height:120px;pointer-events:none;
}
.ls-hero__copy{display:flex;flex-direction:column;gap:18px;width:640px;max-width:100%}
.ls-hero__crumb{
  font-size:12px;font-weight:500;line-height:1.4;letter-spacing:.4px;
  color:var(--ls-text-inverse);opacity:.73;
}
/* .73 not .60, over this photo and scrim .60 measures 3.6:1, under the
   4.5:1 AA floor for 12px. Figma nodes 95:476 and 177:944-1038 were
   raised to .73 (4.53:1) on 2026-08-05 so frame and build agree. */
.ls-hero__crumb a:hover{opacity:1;text-decoration:underline}
.ls-hero__title{
  font-size:46px;font-weight:700;line-height:1.14;letter-spacing:-.8px;
  color:var(--ls-text-inverse);max-width:640px;
}
.ls-hero__lead{
  font-size:17px;font-weight:400;line-height:1.6;
  color:var(--ls-text-inverse);opacity:.82;width:580px;max-width:100%;
}
.ls-hero__actions{display:flex;gap:14px;padding-top:6px;flex-wrap:wrap}

/* ==================================================================
   5. ANCHOR ROW, node 95:510 (master 54:17), 1440x64, sticky
   ================================================================== */
.ls-anchors{
  position:sticky;top:0;z-index:20;
  height:64px;background:var(--ls-surface-subtle);
  border-top:1px solid var(--ls-border-default);
  border-bottom:1px solid var(--ls-border-default);
  display:flex;align-items:center;padding-inline:var(--ls-gutter);
}
.ls-anchors__list{display:flex;align-items:center;gap:36px;width:100%;max-width:var(--ls-container);margin-inline:auto}
.ls-anchors__link{
  display:flex;flex-direction:column;align-items:center;gap:6px;padding:8px 0;
  font-size:15px;line-height:1.65;color:var(--ls-text-primary);
}
.ls-anchors__link.is-active{color:var(--ls-text-brand)}
.ls-anchors__link.is-active::after{content:"";display:block;width:56px;height:2px;background:var(--ls-accent-marker)}
[id]{scroll-margin-top:112px}

/* ==================================================================
   6. OVERVIEW, node 95:511, 1440x567
   Two columns: eyebrow left (300), copy right (820). The 26px teal lead
   IS the section headline, there is no separate H2.
   ================================================================== */
.ls-overview{background:var(--ls-surface-page);padding-block:100px}
.ls-overview__inner{display:flex;align-items:flex-start;gap:72px}
.ls-overview__aside{width:300px;flex:none}
.ls-overview__body{width:820px;max-width:100%;display:flex;flex-direction:column;gap:20px}
.ls-overview__lead{
  font-size:26px;font-weight:600;line-height:1.32;letter-spacing:-.1px;
  color:var(--ls-text-brand);max-width:760px;
}
.ls-overview__body p:not(.ls-overview__lead){color:var(--ls-text-secondary);max-width:760px}

/* ==================================================================
   7. IMAGE BREATHER, node 103:537, 1440x360
   ================================================================== */
.ls-breather{
  height:360px;display:flex;align-items:flex-end;
  padding:0 0 36px;
  background-color:var(--ls-teal-950,#00312F);
  background-image:
    linear-gradient(180deg,rgba(0,49,47,0) 0%,rgba(0,49,47,.2) 42%,rgba(0,49,47,.7) 78%,rgba(0,49,47,.88) 100%),
    var(--ls-breather-src);
  background-repeat:no-repeat,no-repeat;
  background-size:cover,cover;
  /* Frame crops this photo to 30%, 67.5% of its height on every page. */
  background-position:center center,center 48%;
}
.ls-breather__caption{
  width:560px;display:flex;flex-direction:column;gap:8px;
  padding-left:var(--ls-gutter);
}
.ls-breather__rule{width:40px;height:3px;background:var(--ls-accent-marker)}
.ls-breather__text{font-size:24px;font-weight:600;line-height:1.28;color:var(--ls-text-inverse)}

/* ==================================================================
   8. SOLUTIONS, node 95:520, 1440x1334
   Background is #F4F6F7 (surface/subtle), a cool grey, NOT a green tint.
   ================================================================== */
.ls-solutions{
  position:relative;overflow:hidden;
  background:var(--ls-surface-subtle);
  padding-block:100px 110px;
}
/* Deliberately NOT positioned, the watermark below anchors to the section
   so its bleed stays constant as the viewport grows. */
.ls-solutions__inner{display:flex;flex-direction:column;gap:16px}
/* Ghost watermark, node 95:521, 150px/700, tracking -4, #E6E9EB.
   Frame puts it at x=-50, y=28 relative to the SECTION, so it bleeds 50px
   off the left edge of the canvas. Anchoring it to the 1200 container
   instead makes the bleed shrink as the window widens and disappear
   entirely past ~1540, which is not what the frame shows. */
.ls-solutions__watermark{
  position:absolute;left:-50px;top:28px;
  font-size:150px;font-weight:700;letter-spacing:-4px;line-height:1.21;
  color:#E6E9EB;pointer-events:none;user-select:none;z-index:0;
}
/* lift real content above the watermark without pulling the watermark
   back into the flex flow, it is absolute and must stay that way, or it
   adds its own 182px line box to the column and the section grows ~199px */
.ls-solutions__inner > *:not(.ls-solutions__watermark){position:relative;z-index:1}
.ls-solutions__intro{color:var(--ls-text-secondary);max-width:760px}
.ls-solutions .ls-h2{max-width:900px}

/* AI band, node 147:903, 1200x113, #005653, square corners */
.ls-aiband{
  position:relative;overflow:hidden;
  display:flex;align-items:center;gap:32px;
  min-height:113px;padding:28px 32px;
  background:var(--ls-action-primary);
}
/* Orb, node 147:904, 420x420 at band-local x880/y-180,
   #80BE35 at 30%, Figma LAYER_BLUR 130 (CSS blur ≈ radius/2). */
.ls-aiband__orb{
  position:absolute;left:880px;top:-180px;width:420px;height:420px;
  border-radius:50%;background:var(--ls-accent-marker);opacity:.3;
  filter:blur(65px);pointer-events:none;
}
.ls-aiband > *:not(.ls-aiband__orb){position:relative;z-index:1}
.ls-aiband__chip{
  width:52px;height:52px;flex:none;border-radius:0;
  background:var(--ls-accent-marker);color:var(--ls-accent-on-accent);
  display:flex;align-items:center;justify-content:center;
}
.ls-aiband__copy{flex:1;min-width:0}
.ls-aiband__title{font-size:19px;font-weight:600;line-height:1.35;color:var(--ls-text-inverse)}
.ls-aiband__desc{font-size:15px;line-height:1.65;color:var(--ls-text-inverse);opacity:.84}
.ls-aiband__cta{flex:none;font-size:15px;line-height:1.65;color:var(--ls-text-accent-on-dark);white-space:nowrap}
.ls-aiband__cta:hover{text-decoration:underline}

.ls-group{display:flex;flex-direction:column;gap:14px;padding-top:26px}
.ls-group__label{
  font-size:11px;font-weight:600;line-height:1.3;letter-spacing:1.6px;
  text-transform:uppercase;color:var(--ls-text-muted);
}
.ls-cards{display:flex;flex-wrap:wrap;gap:20px}
/* Cards: 285 wide, gap 20, pitch 305, 285x4 + 20x3 = 1200 exactly.
   Square corners with a single 1px bottom rule. Not rounded cards. */
.ls-card{
  width:285px;flex:none;display:flex;flex-direction:column;gap:12px;
  padding:24px;background:var(--ls-surface-page);
  border-radius:0;border-bottom:1px solid var(--ls-border-default);
}
/* Card height is content-driven, exactly as in the frames: 24 padding,
   24 icon, 12, 23 title, 12, body, 24 padding. A three-line body gives
   185, four lines 207, five lines 230, the numbers the frames show.
   Cards in a row equalise through the flex row's default stretch, so a
   longer body in one card lifts its neighbours rather than leaving a
   hardcoded height that is only right on the page it was measured on. */
.ls-cards{align-items:stretch}
.ls-card__icon{width:24px;height:24px;color:var(--ls-text-brand);flex:none}
.ls-card__title{font-size:17px;font-weight:600;line-height:1.35;color:var(--ls-text-brand)}
.ls-card__body{font-size:13.5px;line-height:1.6;color:var(--ls-text-secondary)}

/* ==================================================================
   9. WHERE TO START, node 124:631, 1440x162
   ================================================================== */
.ls-strip{
  background:var(--ls-surface-accent);
  border-top:4px solid var(--ls-accent-marker);
  /* Figma's 4px rule is an INSIDE stroke, so it sits within the 162px
     band rather than adding to it. Padding-top drops to 40 so content
     still starts 44 from the top edge: 4 + 40 + 74 + 44 = 162. */
  padding-block:40px 44px;
}
.ls-strip__inner{display:flex;align-items:center;gap:48px}
.ls-strip__copy{flex:1;display:flex;flex-direction:column;gap:6px;min-width:0}
.ls-strip__label{
  font-size:11px;font-weight:600;line-height:1.3;letter-spacing:1.6px;
  text-transform:uppercase;color:var(--ls-text-brand);
}
.ls-strip__body{color:var(--ls-text-secondary);max-width:760px}
/* No width. Every Button instance in the frames hugs its label with 24px
   of side padding, 172 for "Talk to an Expert", 124 for "Talk To Us".
   The 225/228 that used to sit here were measured off Cyber's longer
   original labels and left behind when they were standardised. */
.ls-strip .ls-btn{flex:none}

/* ==================================================================
   10. SERVICES, node 95:569, 1440x1037
   Five full-width rows, each 1200x135, no gap, 1px top rule on every row
   (so there is a rule above row 1 and none below row 5).
   ================================================================== */
.ls-services{background:var(--ls-surface-page);padding-block:100px 110px}
.ls-services__inner{display:flex;flex-direction:column;gap:16px}
.ls-services .ls-h2{max-width:900px}
.ls-services__intro{color:var(--ls-text-secondary);max-width:780px}
/* Rows size to their own content, which is what the frames do: Cloud
   Technologies runs 135/112/135/135/112 because two of its bodies wrap
   to two lines rather than three. Do not equalise them, a uniform pitch
   is a coincidence of the copy on most pages, not a rule. */
.ls-services__list{display:flex;flex-direction:column;gap:0;padding-top:22px}
.ls-service{
  display:flex;align-items:flex-start;gap:32px;
  padding:30px 0;border-top:1px solid var(--ls-border-default);
  /* Row height is content-driven: 30 padding, the taller of the 52 chip
     and the body, 30 padding. That yields 112 where the body runs to two
     lines and 135 where it runs to three, matching each frame, instead
     of holding one page's pitch across all of them. */
}
.ls-service__chip{
  width:52px;height:52px;flex:none;border-radius:0;
  background:var(--ls-surface-accent);color:var(--ls-text-brand);
  display:flex;align-items:center;justify-content:center;
}
.ls-service__title{width:320px;flex:none;font-size:17px;font-weight:600;line-height:1.35;color:var(--ls-text-brand)}
.ls-service__body{flex:1;min-width:0;color:var(--ls-text-secondary)}

/* ==================================================================
   11. OUR APPROACH, node 95:591, 1440x483
   ================================================================== */
.ls-approach{
  background-color:var(--ls-teal-900,#003D3B);
  background-image:
    linear-gradient(90deg,rgba(0,86,83,.72) 0%,rgba(0,61,59,.86) 50%,rgba(0,61,59,.93) 100%),
    var(--ls-approach-src);
  background-repeat:no-repeat,no-repeat;
  background-size:cover,cover;
  background-position:center center,center center;
  padding-block:100px 110px;
}
.ls-approach__inner{display:flex;flex-direction:column;gap:16px}
.ls-approach .ls-h2{max-width:1000px}
.ls-approach__steps{display:flex;align-items:flex-start;gap:24px;padding-top:34px}
.ls-step{
  flex:1;min-width:0;display:flex;flex-direction:column;gap:8px;
  border-top:1px solid rgba(255,255,255,.22);padding-top:18px;
}
.ls-step__num{font-size:44px;font-weight:700;line-height:1.15;letter-spacing:-1px;color:var(--ls-text-accent-on-dark)}
.ls-step__title{font-size:17px;font-weight:600;line-height:1.35;color:var(--ls-text-inverse)}
.ls-step__body{font-size:13.5px;line-height:1.6;color:var(--ls-text-inverse);opacity:.75}

/* ==================================================================
   12. WHY LOGICSURE, node 95:618, 1440x499
   ================================================================== */
.ls-why{background:var(--ls-surface-page);padding-block:100px 110px}
.ls-why__inner{display:flex;flex-direction:column;gap:16px}
.ls-why .ls-h2{max-width:900px}
.ls-why__pillars{display:flex;align-items:flex-start;gap:24px;padding-top:30px}
.ls-pillar{
  flex:1;min-width:0;display:flex;flex-direction:column;gap:10px;
  border-top:1px solid var(--ls-border-default);padding-top:18px;
}
.ls-pillar__rule{width:28px;height:3px;background:var(--ls-accent-marker)}
.ls-pillar__title{font-size:17px;font-weight:600;line-height:1.35;color:var(--ls-text-brand)}
.ls-pillar__body{font-size:13.5px;line-height:1.6;color:var(--ls-text-secondary)}

/* ==================================================================
   13. CTA, node 95:640, 1440x245, flat #005653, no image
   ================================================================== */
.ls-cta{background:var(--ls-action-primary);padding-block:72px}
.ls-cta__inner{display:flex;align-items:center;gap:60px}
.ls-cta__copy{flex:1;min-width:0;display:flex;flex-direction:column;gap:10px}
.ls-cta__body{font-size:15px;line-height:1.65;color:var(--ls-text-inverse);opacity:.8;max-width:640px}
.ls-cta .ls-btn{flex:none}

/* ==================================================================
   14. FOOTER, node 95:645 (master 58:5), 1440x373
   ================================================================== */
.ls-footer{
  background:var(--ls-surface-subtle);
  border-top:1px solid var(--ls-border-default);
  padding:64px var(--ls-gutter) 28px;
}
.ls-footer__inner{display:flex;flex-direction:column;gap:32px}
/* The four columns are 330 + 400 + 180 + 210 = 1120 inside a 1200
   container. Keeping the widths exact and letting space-between hand the
   remaining 80px out as three gaps of 26.67 is what the frame does now
   too. It was drawn with 40px gaps, which came to 1240 and clipped the
   fourth column, and was corrected to 26.67 on 17 Aug 2026 when the
   longer Chennai address made that clip visible. */
.ls-footer__cols{display:flex;align-items:flex-start;justify-content:space-between;gap:24px}
.ls-footer__col{display:flex;flex-direction:column;gap:9px;flex:none}
.ls-footer__col--brand{width:330px}
.ls-footer__col--caps{width:400px}
.ls-footer__caps-grid{display:flex;gap:24px}
.ls-footer__subcol{width:188px;display:flex;flex-direction:column;gap:9px}
.ls-footer__col--company{width:180px}
.ls-footer__col--contact{width:210px}
/* Brand column leads with the lockup instead of a text "LogicSure"
   heading. Sized to match the header so the mark reads as one asset
   across the page. The 4px inset aligns the wordmark's optical left edge
   with the column text below it, the PNG has no bearing of its own. */
.ls-footer__brand{display:block;margin-bottom:5px}
.ls-footer__logo{width:220px;height:62px;object-fit:contain;display:block;margin-left:-4px}
.ls-footer h4{font-size:17px;font-weight:600;line-height:1.35;color:var(--ls-text-brand)}
.ls-footer p,.ls-footer a{font-size:13.5px;line-height:1.6;color:var(--ls-text-secondary)}
/* Country line in each address block, matched to the contact page rule
   .ls-details strong, 600 rather than the browser default 700, and on
   primary rather than secondary, so both blocks read identically. */
.ls-footer p strong{font-weight:600;color:var(--ls-text-primary)}
.ls-footer a:hover{text-decoration:underline}
.ls-footer .ls-link{color:var(--ls-text-link)}
.ls-footer__legal{
  display:flex;align-items:center;
  padding-top:18px;border-top:1px solid var(--ls-border-default);
}
.ls-footer__legal p{flex:1;font-size:13.5px;color:var(--ls-text-muted)}
.ls-footer__legal p:last-child{flex:none;text-align:right}

/* ==================================================================
   15. RESPONSIVE, matches the frame at >=1440, fluid above, stacks below.
   Confirmed requirement: never a locked 1440 canvas, never empty side
   margins on large monitors, never clipped content on phones.
   ================================================================== */
@media (max-width:1360px){
  :root{--ls-gutter:64px}
}
@media (max-width:1200px){
  .ls-hero__mark{display:none}
  .ls-cards{justify-content:flex-start}
  .ls-card{width:calc(50% - 10px)}
  .ls-approach__steps{flex-wrap:wrap}
  .ls-step{flex:1 1 calc(33.333% - 16px)}
  .ls-why__pillars{flex-wrap:wrap}
  .ls-pillar{flex:1 1 calc(50% - 12px)}
  .ls-footer__cols{flex-wrap:wrap}
}
@media (max-width:1000px){
  :root{--ls-gutter:40px}
  .ls-overview__inner{flex-direction:column;gap:24px}
  .ls-overview__aside,.ls-overview__body{width:100%}
  .ls-hero__title{font-size:38px}
  .ls-h2{font-size:28px}
  .ls-aiband{flex-wrap:wrap;gap:20px}
  .ls-aiband__cta{width:100%}
  .ls-strip__inner{flex-direction:column;align-items:flex-start;gap:20px}
  .ls-cta__inner{flex-direction:column;align-items:flex-start;gap:28px}
  .ls-nav,.ls-header__spacer{display:none}
}
@media (max-width:720px){
  :root{--ls-gutter:20px}
  .ls-hero{min-height:0;padding-block:56px}
  .ls-hero__title{font-size:30px;letter-spacing:-.4px}
  .ls-hero__copy,.ls-hero__lead{width:100%}
  .ls-card{width:100%}
  .ls-step{flex:1 1 100%}
  .ls-pillar{flex:1 1 100%}
  .ls-service{flex-direction:column;gap:16px}
  .ls-service__title{width:100%}
  .ls-anchors{overflow-x:auto}
  .ls-anchors__list{gap:24px}
  .ls-solutions__watermark{font-size:96px;left:-32px;top:20px}
  .ls-footer__col,.ls-footer__subcol{width:100%}
  .ls-footer__legal{flex-direction:column;align-items:flex-start;gap:6px}
  .ls-footer__legal p:last-child{text-align:left}
}

/* ==================================================================
   16. WORDPRESS BLOCK SCAFFOLDING
   Core injects margin-block-start: var(--wp--style--block-gap) (24px)
   on every block after the first inside a flow container. Our sections
   already space themselves with flex gap values taken from the frame,
   so the injected margin is additive, it pushed the page from 5688px
   to 7030px. Cleared inside the ls- namespace only, so core blocks used
   anywhere else keep their normal behaviour.
   ================================================================== */
.ls-container > *,
.ls-hero__inner > *, .ls-hero__copy > *,
.ls-overview__inner > *, .ls-overview__aside > *, .ls-overview__body > *,
.ls-breather > *, .ls-breather__caption > *,
.ls-solutions__inner > *, .ls-group > *, .ls-cards > *, .ls-card > *, .ls-aiband > *,
.ls-strip__inner > *, .ls-strip__copy > *,
.ls-services__inner > *, .ls-services__list > *, .ls-service > *,
.ls-approach__inner > *, .ls-approach__steps > *, .ls-step > *,
.ls-why__inner > *, .ls-why__pillars > *, .ls-pillar > *,
.ls-cta__inner > *, .ls-cta__copy > *,
.ls-footer__inner > *, .ls-footer__cols > *, .ls-footer__col > *, .ls-footer__subcol > * {
  margin-block-start: 0;
  margin-block-end: 0;
}

/* Core wraps some blocks in extra flow containers; make those transparent
   to layout so a wrapper never becomes an unintended flex item. */
.ls-hero__copy > .wp-block-group,
.ls-card > .wp-block-group,
.ls-step > .wp-block-group,
.ls-pillar > .wp-block-group { display: contents; }

/* Sections butt directly against each other, the frame has no gaps
   between bands. Core's post-content flow container was adding 24px
   between each of the ten sections (240px over the page). */
.entry-content.wp-block-post-content > * { margin-block-start: 0; margin-block-end: 0; }

/* Same bug one level up, and the one this reset originally missed.
   .wp-site-blocks is itself a flow container, so core gives <main> and the
   footer template-part a 24px margin-block-start each, a band of dead
   space under the header and another above the footer, on EVERY page.
   Invisible to a check that sums .entry-content's children, because both
   gaps fall outside .entry-content. Reset at the root so header, main and
   footer stack flush, exactly as the frames have them. */
.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }

/* Editor-only: Custom HTML blocks render on a white card in the editing
   canvas, which makes the hero breadcrumb and buttons look like errors.
   Front end is unaffected. */
.editor-styles-wrapper .wp-block-html { background: transparent; }

/* Image breather height on wide monitors.
   The frame pins this band at 360px while the page is fluid, so a wider
   viewport scales the photo up and shows a thinner horizontal slice of
   it, at 2545px you see the bottom 21% instead of the bottom 37%, which
   crops the people out of the meeting-room shot entirely.
   25vw resolves to exactly 360px at the 1440 design width, so parity with
   Figma is unchanged; above that the band grows and keeps its subject. */
.ls-breather { height: clamp(360px, 25vw, 520px); }

/* Solutions grid: three-up pages.
   The card is 285px because the grid is four-across, 285×4 + 20×3 = 1200
   exactly. A three-card row therefore stops at 895 and leaves a 305px
   hole, a full quarter of the container. On AI Solutions, Application
   Development, QA & Testing and Digital Transformation every group is
   three-up, so that hole repeats down the whole section and reads as a
   fault rather than a trailing partial row.
   Those four pages carry .ls-solutions--3up and stretch their cards to
   386.67 so each row fills. Pages containing a four-card row (Cyber,
   Data, Salesforce, Cloud) keep 285, so card width stays consistent
   within any single page.
   Scoped above 1200 only, so the responsive stacking below is untouched. */
@media (min-width: 1201px) {
  .ls-solutions--3up .ls-card { width: calc((100% - 40px) / 3); }
}

/* ==================================================================
   17. LANDING AND MARKETING PAGES
   Sections that appear on Capabilities landing, About Us and Home
   rather than on a capability page.
   ================================================================== */

/* Hero variant, node 139:697, 1440x470. No shield mark, a 660 copy
   column rather than 640, and a slightly heavier scrim (40→96 against
   the capability hero's 34→95). */
.ls-hero--landing{
  min-height:470px;
  background-image:
    linear-gradient(90deg,rgba(0,61,59,.40) 0%,rgba(0,61,59,.66) 30%,rgba(0,61,59,.86) 58%,rgba(0,49,47,.96) 100%),
    var(--ls-hero-src);
}
.ls-hero--landing .ls-hero__copy{width:660px}
/* About Us is NOT on the same scrim as the Capabilities landing: node
   142:798 opens two points lighter (.38) and darkens two points harder at
   the 58% stop (.88). Small, but it is a different paint. */
.ls-hero--about{
  background-image:
    linear-gradient(90deg,rgba(0,61,59,.38) 0%,rgba(0,61,59,.66) 30%,rgba(0,61,59,.88) 58%,rgba(0,49,47,.96) 100%),
    var(--ls-hero-src);
}

/* What We Do, node 139:699, 1440x884. Eight capability cards, 285 wide
   on a 20 gap, four to a row. Row one runs 233 and row two 211 because
   the bodies differ; that falls out of the flex row's default stretch. */
.ls-whatwedo{position:relative;overflow:hidden;background:var(--ls-surface-subtle);padding-block:100px 110px}
.ls-whatwedo__inner{display:flex;flex-direction:column;gap:16px}
.ls-whatwedo__watermark{
  position:absolute;left:-60px;top:30px;
  font-size:150px;font-weight:700;letter-spacing:-4px;line-height:1.21;
  color:#E6E9EB;pointer-events:none;user-select:none;z-index:0;
}
.ls-whatwedo__inner > *:not(.ls-whatwedo__watermark){position:relative;z-index:1}
.ls-whatwedo__intro{font-size:17px;line-height:1.6;color:var(--ls-text-secondary);max-width:820px}
.ls-capgrid{display:flex;flex-wrap:wrap;align-items:stretch;gap:20px;padding-top:26px}
.ls-capcard{
  width:285px;flex:none;display:flex;flex-direction:column;gap:12px;
  padding:26px;background:var(--ls-surface-page);
  border-radius:0;border-bottom:1px solid var(--ls-border-default);
}
/* The two lead practices carry a 3px accent rule instead of the 1px grey
   one, nodes 90:432/90:436 on Home, 139:715/139:718 on the landing page.
   Every other card in both grids keeps #DDE1E4 at 1px. */
.ls-capcard--lead{border-bottom:3px solid var(--ls-accent-marker)}
.ls-capcard__icon{width:24px;height:24px;color:var(--ls-text-brand);flex:none}
.ls-capcard__title{font-size:17px;font-weight:600;line-height:1.35;color:var(--ls-text-brand)}
.ls-capcard__body{font-size:13.5px;line-height:1.6;color:var(--ls-text-secondary)}

/* Ways to work, node 139:735, 1440x474. Three tiles on the accent
   surface, 384 wide with a 24 gap. */
.ls-ways{background:var(--ls-surface-page);padding-block:100px 110px}
.ls-ways__inner{display:flex;flex-direction:column;gap:16px}
.ls-ways__grid{display:flex;align-items:stretch;gap:24px;padding-top:26px}
.ls-way{
  flex:1;min-width:0;padding:26px;background:var(--ls-surface-accent);
  display:flex;flex-direction:column;gap:10px;
  /* 3px accent rule along the top, nodes 141:756/759/762, INSIDE stroke. */
  border-top:3px solid var(--ls-accent-marker);
}
.ls-way__title{font-size:17px;font-weight:600;line-height:1.35;color:var(--ls-text-brand)}
.ls-way__body{font-size:13.5px;line-height:1.6;color:var(--ls-text-secondary)}

/* Approach band, orb variant, the landing page drops the photograph for
   a single soft ellipse in the top-right corner, 680x680 at x=1000 in a
   1440 frame, so it bleeds 240 past the right edge. */
.ls-approach--orb{position:relative;overflow:hidden;background-image:none;background-color:var(--ls-teal-900,#003D3B)}
.ls-approach__orb{
  position:absolute;right:-240px;top:-250px;width:680px;height:680px;
  border-radius:50%;background:rgba(4,131,124,.45);
  /* Figma LAYER_BLUR 150 on node 141:724. CSS blur takes half the Figma
     radius, the same conversion the AI band orb uses. */
  filter:blur(75px);
  pointer-events:none;z-index:0;
}
.ls-approach--orb .ls-approach__inner{position:relative;z-index:1}

@media (max-width:1200px){
  .ls-capcard{width:calc(50% - 10px)}
  .ls-ways__grid{flex-wrap:wrap}
  .ls-way{flex:1 1 100%}
}
@media (max-width:900px){
  .ls-hero--landing .ls-hero__copy{width:100%}
  .ls-capcard{width:100%}
  .ls-whatwedo__watermark{font-size:96px;left:-32px;top:22px}
}

/* The frame does not mark these cards as links, but a capabilities index
   whose cards do not reach the capability pages is broken, so the whole
   card is a target. Hover is the one thing invented here: an unstyled
   link with no affordance is worse than a small departure from the frame. */
.ls-capcard{position:relative;transition:border-color .15s ease}
.ls-capcard__link{position:absolute;inset:0;z-index:2}
.ls-capcard:not(.ls-capcard--lead):hover{border-bottom-color:var(--ls-accent-marker)}
.ls-capcard:focus-within{outline:2px solid var(--ls-text-link);outline-offset:2px}

/* ------------------------------------------------------------------
   Block-gap reset, generalised. Section 16 lists containers one by one,
   which meant every new section silently reintroduced core's 24px
   margin-block-start on its children, the landing page's cards came out
   95px tall over the frame before this. Spacing in this design is always
   flex gap, never margin, so zero it across the whole ls- namespace and
   stop rediscovering the same bug on each new template.
   ------------------------------------------------------------------ */
.entry-content [class^="ls-"] > *,
.entry-content [class*=" ls-"] > *{margin-block-start:0;margin-block-end:0}

/* ==================================================================
   18. ABOUT US
   ================================================================== */

/* Who We Are, node 142:798, 1440x492. Two columns: a bare eyebrow on
   the left, the argument on the right. Same shape as the capability
   Overview but on a 300/820 split rather than 372/820. */
.ls-whoweare{background:var(--ls-surface-page);padding-block:100px}
.ls-whoweare__inner{display:flex;gap:80px}
.ls-whoweare__aside{width:300px;flex:none}
.ls-whoweare__body{flex:1;min-width:0;display:flex;flex-direction:column;gap:20px}
.ls-whoweare__body p{max-width:760px}
.ls-whoweare__lead{font-size:26px;font-weight:600;line-height:1.3;color:var(--ls-text-brand)}

/* Mission and Vision, node 142:806, 1440x280. Brand teal, with the same
   corner ellipse the Capabilities approach band uses, at 560 rather
   than 680 and half-opacity rather than 45%. */
.ls-missionvision{
  position:relative;overflow:hidden;
  background:var(--ls-text-brand);padding-block:90px 96px;
}
.ls-missionvision__orb{
  position:absolute;right:-170px;top:-200px;width:560px;height:560px;
  border-radius:50%;background:rgba(4,131,124,.5);
  filter:blur(70px);                    /* LAYER_BLUR 140 on node 142:816 */
  pointer-events:none;z-index:0;
}
.ls-missionvision__inner{position:relative;z-index:1;display:flex;gap:80px}
.ls-mv{flex:1;min-width:0;display:flex;flex-direction:column;gap:14px}
.ls-mv__text{font-size:24px;font-weight:600;line-height:1.375;color:var(--ls-text-inverse)}

/* Technologies, node 142:816, 1440x604. Six domain tiles, 247 wide on a
   28 column gap and a 30 row gap, each hung under a 1px top rule. */
.ls-tech{background:var(--ls-surface-page);padding-block:100px 110px}
.ls-tech__inner{display:flex;gap:72px}
.ls-tech__aside{width:330px;flex:none;display:flex;flex-direction:column;gap:18px}
.ls-tech__intro{color:var(--ls-text-secondary)}
/* flex-start, not the default stretch: the frame lets the AI tile stop at
   155 while its row-mates run 182, rather than padding it out. */
.ls-tech__grid{flex:1;min-width:0;display:flex;flex-wrap:wrap;align-items:flex-start;gap:30px 28px}
.ls-domain{
  width:247px;flex:none;padding-top:18px;
  border-top:1px solid var(--ls-border-default);
  display:flex;flex-direction:column;gap:10px;
}
.ls-domain__head{display:flex;align-items:center;gap:10px}
.ls-domain__icon{width:24px;height:24px;color:var(--ls-text-brand);flex:none}
.ls-domain__title{font-size:15px;font-weight:600;line-height:1.6;color:var(--ls-text-brand)}
.ls-domain__list{display:flex;flex-direction:column;gap:5px}
.ls-domain__list li{font-size:13.5px;line-height:1.6;color:var(--ls-text-secondary)}

@media (max-width:1200px){
  .ls-whoweare__inner,.ls-tech__inner{flex-direction:column;gap:36px}
  .ls-whoweare__aside,.ls-tech__aside{width:100%}
  .ls-domain{width:calc(50% - 14px)}
}
@media (max-width:900px){
  .ls-missionvision__inner{flex-direction:column;gap:36px}
  .ls-domain{width:100%}
}

/* ==================================================================
   19. HOME
   ================================================================== */

/* Hero / Home, node 90:385, 1440x620. Taller than the inner-page heroes
   and the photo is used whole (scaleMode FILL, identity transform), so no
   focal point is needed here. */
.ls-hero--home{
  min-height:620px;background-position:center center,center center;
  /* Home has its own scrim (node 90:558), NOT the capability one (95:660):
     heavier at the left edge (.40 vs .34) and it stays on #003D3B all the
     way to 58% before dropping to #00312F. */
  background-image:
    linear-gradient(90deg,rgba(0,61,59,.40) 0%,rgba(0,61,59,.66) 30%,rgba(0,61,59,.85) 58%,rgba(0,49,47,.96) 100%),
    var(--ls-hero-src);
}
.ls-hero--home .ls-hero__copy{width:640px;gap:20px}
.ls-hero--home .ls-hero__title{font-size:56px;line-height:1.125;letter-spacing:-1px}
/* Third line of the H1 is lime, node 90:390 carries two text segments. */
.ls-hero__title .ls-accent{color:var(--ls-accent-lime)}
.ls-hero--home .ls-hero__lead{max-width:560px}
/* Actions sit 8 off the lead here; the capability heroes use 6 (95:482). */
.ls-hero--home .ls-hero__actions{padding-top:8px}
/* Eyebrow variant: a 6px dot rather than the 24x2 rule used everywhere else. */
.ls-eyebrow--dot::before{width:6px;height:6px;border-radius:50%}
/* Three rings sharing a left edge and a vertical centre, nested, not
   concentric. Anchored 640 into the container, which is where x=760 lands
   in a 1440 frame with a 120 gutter. */
.ls-hero__ring{
  position:absolute;left:640px;top:50%;transform:translateY(-50%);
  border:1px solid var(--ls-accent-lime);border-radius:50%;pointer-events:none;
}
.ls-hero__ring--1{width:240px;height:240px;opacity:.22}
.ls-hero__ring--2{width:380px;height:380px;opacity:.15}
.ls-hero__ring--3{width:540px;height:540px;opacity:.09}

/* Shared link-out. The frames wrap these in a taller box than the text,
   so the padding is what reproduces the frame, not the line height. */
.ls-more{display:inline-block;font-size:15px;line-height:1.65;color:var(--ls-text-link)}
.ls-more--tight{padding-top:8px}
.ls-more--pad{padding-block:12px}
.ls-more--on-dark{color:var(--ls-text-accent-on-dark);padding-top:6px}

/* Pill chips, 36 tall, 13px side padding, fully rounded. */
.ls-chips{display:flex;flex-wrap:wrap;gap:8px}
/* On dark the chip border is white at .38 and the label sits at .88,
   nodes 153:868-875. (.55 is the ghost BUTTON's border, not the chip's.) */
.ls-chip{
  border:1px solid rgba(255,255,255,.38);border-radius:999px;
  padding:7px 13px;font-size:13.5px;line-height:1.6;
  color:var(--ls-text-inverse);opacity:.88;
}
.ls-chip--light{
  border-color:var(--ls-border-default);background:var(--ls-surface-page);
  color:var(--ls-text-secondary);opacity:1;
}

/* Positioning, node 90:399, 1440x620. Copy left, photo right with a
   caption plate hanging 52 off its left edge. */
.ls-positioning{background:var(--ls-surface-page);padding-block:110px}
.ls-positioning__inner{display:flex;gap:64px;align-items:flex-start}
.ls-positioning__copy{width:660px;flex:none;padding-top:8px;display:flex;flex-direction:column;gap:24px}
.ls-positioning__h{font-size:44px;font-weight:700;line-height:1.18;letter-spacing:-.6px;color:var(--ls-text-brand)}
.ls-positioning__body{font-size:17px;line-height:1.6;color:var(--ls-text-secondary);max-width:620px}
.ls-positioning__photo{
  position:relative;width:470px;height:400px;flex:none;
  background-image:var(--ls-home-positioning-src);
  /* Node 118:538 is scaleMode CROP with imageTransform [[.66,0,.17],[0,1,0]]:
     the middle 66% of the width, full height. That was written as a
     non-uniform 151.515% 100%, which only holds at this exact 470x400 box,
     because background-size percentages resolve against the box rather than
     the image. Measured 2026-08-08 on a real handset: at 335px wide the
     photograph drew 508x400 against its natural 1.78 aspect, squashing the
     people in it by 29%; at 673px it stretched 43% the other way.
     cover reproduces the frame here and stays undistorted at every width.
     The source is 2400x1350, so covering 470x400 scales it to 711x400 and
     shows 66.1% of the width, the same crop, arrived at honestly rather
     than hardcoded. The older note claiming cover would show 78% was
     measured against a 2400x1600 original that has since been replaced. */
  background-size:cover;background-position:50% 50%;
  background-repeat:no-repeat;
}
/* Not a boxed plate: node 118:539 has a single 5px accent rule on its LEFT
   edge and a soft drop shadow, no border on the other three sides. */
.ls-positioning__plate{
  position:absolute;left:-52px;top:286px;width:322px;
  background:var(--ls-surface-page);
  border-left:5px solid var(--ls-accent-marker);
  box-shadow:0 10px 28px rgba(18,28,36,.16);
  padding:22px 26px 22px 24px;
}
.ls-positioning__plate p{font-size:16px;font-weight:600;line-height:1.375;color:var(--ls-text-brand)}

/* AI band, node 90:437, 1440x520. Full-bleed photo, accent edge rule. */
.ls-homeai{display:flex;background:var(--ls-text-brand)}
.ls-homeai__photo{
  width:560px;flex:none;position:relative;min-height:520px;
  background-image:var(--ls-home-ai-src);background-size:cover;background-position:center center;
}
.ls-homeai__photo::after,.ls-homesec__photo::after{
  content:"";position:absolute;right:0;top:0;width:5px;height:100%;
  background:var(--ls-accent-marker);
}
.ls-homeai__copy{
  flex:1;min-width:0;padding:51px 72px 50px;max-width:772px;
  display:flex;flex-direction:column;gap:18px;
}
.ls-homeai__h{font-size:40px;font-weight:700;line-height:1.15;letter-spacing:-.4px;color:var(--ls-text-inverse)}
.ls-homeai__body{font-size:17px;line-height:1.6;color:var(--ls-text-inverse);max-width:600px}

/* Security, node 90:452, 1440x642. Three full-bleed columns: photograph,
   teal headline panel, white body. */
.ls-homesec{display:flex;align-items:stretch}
.ls-homesec__photo{
  width:400px;flex:none;position:relative;min-height:642px;
  background-image:var(--ls-home-security-src);background-size:cover;background-position:center center;
}
.ls-homesec__panel{
  width:440px;flex:none;background:var(--ls-text-brand);
  padding:100px 48px;display:flex;flex-direction:column;gap:18px;
}
.ls-homesec__h{font-size:34px;font-weight:700;line-height:1.2;letter-spacing:-.3px;color:var(--ls-text-inverse);max-width:348px}
.ls-homesec__body{
  flex:1;min-width:0;background:var(--ls-surface-page);
  padding:100px 56px;display:flex;flex-direction:column;gap:18px;
}
.ls-homesec__body p{font-size:17px;line-height:1.6;color:var(--ls-text-secondary);max-width:424px}

@media (max-width:1360px){
  .ls-hero__ring{display:none}
}
@media (max-width:1200px){
  .ls-positioning__inner{flex-direction:column;gap:48px}
  .ls-positioning__copy{width:100%}
  .ls-homeai,.ls-homesec{flex-wrap:wrap}
  .ls-homeai__photo,.ls-homesec__photo{width:100%;min-height:320px}
  .ls-homesec__panel{width:100%}
  .ls-homeai__copy,.ls-homesec__body{padding:56px var(--ls-gutter)}
  .ls-homesec__panel{padding:56px var(--ls-gutter)}
}
@media (max-width:900px){
  .ls-hero--home .ls-hero__title{font-size:38px;letter-spacing:-.5px}
  .ls-hero--home .ls-hero__copy{width:100%}
  .ls-positioning__photo{width:100%}
  .ls-positioning__plate{left:0;top:auto;bottom:-24px;width:auto;max-width:322px}
}

/* Responsive type for the three home feature headings. These carry their
   own sizes rather than .ls-h2, so without this they hold 44 / 40 / 34 all
   the way down and end up larger than the 30px page h1 on a phone. The
   blocks must sit after the base rules above, not up in the global type
   scale, or the later base declaration wins on source order. */
@media (max-width:1000px){
  .ls-positioning__h{font-size:36px}
  .ls-homeai__h{font-size:32px}
  .ls-homesec__h{font-size:28px}
}
@media (max-width:720px){
  /* Flat: every section heading reads at 28px, under the h1. Emphasis on
     these three comes from the photograph and the colour panel, which type
     size cannot add to in a 335px column. */
  .ls-positioning__h,.ls-homeai__h{font-size:28px}
}

/* ==================================================================
   20. CONTACT AND LEGAL
   ================================================================== */

/* Hero / Contact, node 143:860, 1440x350. Solid teal with the corner
   ellipse, no photograph. */
.ls-cthero{
  position:relative;overflow:hidden;
  background:var(--ls-teal-900,#003D3B);padding-block:84px;
}
.ls-cthero__orb{
  position:absolute;right:-190px;top:-260px;width:620px;height:620px;
  border-radius:50%;background:rgba(4,131,124,.5);
  filter:blur(75px);                    /* LAYER_BLUR 150 on node 143:861 */
  pointer-events:none;z-index:0;
}
.ls-cthero__inner{position:relative;z-index:1;display:flex;flex-direction:column;gap:16px}
.ls-cthero__title{font-size:42px;font-weight:700;line-height:1.16;letter-spacing:-.7px;color:var(--ls-text-inverse)}
.ls-cthero__lead{font-size:17px;line-height:1.6;color:var(--ls-text-inverse);max-width:680px}

/* Section / Contact, node 143:868, 1440x946. Form left on 680, sidebar
   right on 400. Section height is set by the sidebar, not the form. */
.ls-contact{background:var(--ls-surface-page);padding-block:90px 100px}
.ls-contact__inner{display:flex;gap:80px;align-items:flex-start}
.ls-form{width:680px;flex:none;display:flex;flex-direction:column;gap:20px}
.ls-form__note{font-size:15px;line-height:1.65;color:var(--ls-text-secondary)}
.ls-form__fields{display:flex;flex-direction:column;gap:20px}
.ls-form__row{display:flex;gap:20px}
.ls-field{flex:1;min-width:0;display:flex;flex-direction:column;gap:6px}
.ls-field label{font-size:12px;font-weight:500;line-height:1.4;color:var(--ls-text-secondary)}
.ls-field input,.ls-field textarea,.ls-field select{
  font-family:inherit;font-size:15px;line-height:1.65;color:var(--ls-text-primary);
  background:var(--ls-surface-page);border:1px solid var(--ls-border-default);
  border-radius:var(--ls-radius-sm);padding:12px 14px;width:100%;
}
.ls-field input,.ls-field select{height:51px}
.ls-field textarea{height:132px;resize:vertical}
.ls-field ::placeholder{color:var(--ls-text-muted)}
.ls-field :focus-visible{outline:2px solid var(--ls-text-link);outline-offset:1px;border-color:var(--ls-text-link)}
.ls-form__actions{padding-top:6px}

.ls-aside{
  width:400px;flex:none;background:var(--ls-surface-subtle);
  border-top:4px solid var(--ls-accent-marker);padding:32px;  /* 143:877 */
  display:flex;flex-direction:column;gap:32px;
}
/* No rule or top inset: this is the aside's only block, and a hairline
   would sit directly under its 4px accent bar. */
.ls-details{display:flex;flex-direction:column;gap:14px}
.ls-details p{font-size:13.5px;line-height:1.6;color:var(--ls-text-secondary)}
.ls-details strong{font-weight:600;color:var(--ls-text-primary)}
/* The one actionable line in the block, so it leads it and carries both
   the link colour and a phone glyph. The icon is inline rather than added
   to the header sprite: it appears once, on one page, while the sprite
   exists for the ten capability marks that repeat across both menus. */
.ls-details__tel{
  display:inline-flex;align-items:center;gap:8px;
  color:var(--ls-text-link);font-weight:600;text-decoration:none;
}
.ls-details__tel:hover,.ls-details__tel:focus-visible{text-decoration:underline}
.ls-details__tel svg{
  width:17px;height:17px;flex:none;fill:none;stroke:currentColor;
  stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;
}

/* Hero / Legal, node 144:902, 1440x269. Quiet, on the subtle surface. */
.ls-lghero{
  background:var(--ls-surface-subtle);border-bottom:1px solid var(--ls-border-default);
  padding-block:72px 56px;
}
.ls-lghero__inner{display:flex;flex-direction:column;gap:14px}
.ls-lghero__crumb{font-size:12px;font-weight:500;line-height:1.4;letter-spacing:.4px;color:var(--ls-text-muted)}
.ls-lghero__title{font-size:40px;font-weight:700;line-height:1.15;letter-spacing:-.6px;color:var(--ls-text-brand)}
.ls-lghero__meta{font-size:13.5px;line-height:1.6;color:var(--ls-text-muted)}

/* 404, no Figma frame exists for this state, so it borrows the Legal hero
   shell (same surface, same title scale) rather than inventing a new one.
   Added 2026-08-07: the theme had no 404 template at all, so a bad URL
   rendered header and footer with nothing between them. */
/* .ls-btn--ghost is white-on-transparent and only legible over the dark
   heroes. On the 404's light surface it disappeared, so this is the
   light-background equivalent: brand text on a hairline border. */
.ls-btn--outline{
  background:transparent;color:var(--ls-text-brand);
  border:1px solid var(--ls-border-default);
}
.ls-btn--outline:hover{border-color:var(--ls-text-brand)}
.ls-404{padding-block:96px 104px}
.ls-404__lead{font-size:16px;line-height:1.65;color:var(--ls-text-secondary);max-width:560px}
.ls-404__actions{display:flex;gap:12px;padding-top:10px}

/* Section / Legal body, node 144:908. Sticky contents left, prose right. */
.ls-legal{background:var(--ls-surface-page);padding-block:72px 96px}
.ls-legal__inner{display:flex;gap:80px;align-items:flex-start}
.ls-toc{
  width:280px;flex:none;position:sticky;top:96px;
  border-left:1px solid var(--ls-border-default);padding:4px 0 4px 20px;
  display:flex;flex-direction:column;gap:12px;
}
.ls-toc__label{font-size:11px;font-weight:600;line-height:1.3;letter-spacing:1.6px;text-transform:uppercase;color:var(--ls-text-muted)}
.ls-toc a{font-size:13.5px;line-height:1.6;color:var(--ls-text-secondary)}
.ls-toc a:hover,.ls-toc a:focus-visible{color:var(--ls-text-brand)}
.ls-prose{flex:1;min-width:0;max-width:760px;display:flex;flex-direction:column;gap:18px}
.ls-prose h2{
  font-size:22px;font-weight:600;line-height:1.3;color:var(--ls-text-brand);
  padding-top:18px;
}
.ls-prose h2::after{content:"";display:block;width:28px;height:3px;background:var(--ls-accent-marker);margin-top:6px}
.ls-prose p,.ls-prose li{font-size:15px;line-height:1.65;color:var(--ls-text-secondary)}
.ls-prose ul{display:flex;flex-direction:column;gap:8px;padding-left:20px;list-style:disc}
.ls-prose strong{font-weight:600;color:var(--ls-text-primary)}
/* The drafts author their category grids as markdown pipe tables. Until
   2026-08-06 the converter had no table branch, so those rows reached the
   page as literal "| Category | Purpose |" paragraphs. Same type scale as
   .ls-prose p so the table reads as part of the prose column, with the
   header row on the accent hairline the h2 rules already use. */
.ls-prose table{
  width:100%;border-collapse:collapse;
  font-size:15px;line-height:1.65;color:var(--ls-text-secondary);
}
.ls-prose th{
  text-align:left;font-weight:600;color:var(--ls-text-primary);
  padding:10px 16px 10px 0;
  border-bottom:2px solid var(--ls-accent-marker);
}
.ls-prose td{
  padding:12px 16px 12px 0;vertical-align:top;
  border-bottom:1px solid var(--ls-border-default);
}
.ls-prose th:last-child,.ls-prose td:last-child{padding-right:0}
.ls-prose tbody tr:last-child td{border-bottom:0}
.ls-prose code{
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px;
  background:var(--ls-surface-subtle);border:1px solid var(--ls-border-default);
  border-radius:3px;padding:1px 5px;color:var(--ls-text-primary);
}
/* Designed into the frame: the pre-publish warning stays until a lawyer
   has signed the copy off and the bracketed placeholders are filled. */
/* Node 144:922 rules the LEFT edge at 4px only, same treatment as the
   Positioning caption plate, not a full box. */
.ls-draftnote{
  background:var(--ls-surface-accent);
  border-left:4px solid var(--ls-accent-marker);
  padding:18px 22px;display:flex;flex-direction:column;gap:6px;
}
.ls-draftnote__label{font-size:11px;font-weight:600;line-height:1.3;letter-spacing:1.6px;text-transform:uppercase;color:var(--ls-text-brand)}
.ls-draftnote p{font-size:13.5px;line-height:1.6;color:var(--ls-text-secondary)}

@media (max-width:1200px){
  .ls-contact__inner,.ls-legal__inner{flex-direction:column;gap:48px}
  .ls-form,.ls-aside,.ls-toc{width:100%}
  .ls-toc{position:static;border-left:0;border-top:1px solid var(--ls-border-default);padding:20px 0 0}
}
@media (max-width:720px){
  .ls-form__row{flex-direction:column}
}

/* ==================================================================
   21. CONTACT FORM 7, plugin behaviour, designed geometry
   ================================================================== */
/* Two things in CF7's output disturb the designed geometry; both are fixed here.
   1. CF7 runs WordPress autop over the form template, so the label and the
      control inside each .ls-field end up wrapped in a <p>. That <p> becomes
      the single flex child, collapsing .ls-field's 6px column: the label's line
      box grows to the 24.75px strut and the 6px gap disappears, a net +2.0px
      per field. Restoring the column on the <p> reproduces the original box.
      If a future CF7 drops autop this rule simply stops matching and
      .ls-field's own flex column takes over unchanged.
   2. Each control sat in an inline context inside the wrap span, leaving
      descender space beneath it, +9.7px on the textarea. Blocking both out
      removes it. Measured back to 73.8 / 154.8 per field, 414.4 for the form. */
.ls-field > p{display:flex;flex-direction:column;gap:6px}
/* The wrap is a column too, not just a block: CF7 renders the validation tip
   as a sibling of the control *inside* this span, and State=Error (node 52:14)
   puts 6px between the field and its helper. Empty at rest, so a gap-less
   column measures exactly 51 / 132 and the resting form is unaffected. */
.ls-field .wpcf7-form-control-wrap{display:flex;flex-direction:column;gap:6px;width:100%}
.ls-field input,.ls-field select,.ls-field textarea{display:block}

/* The submit spinner is visibility:hidden but still occupies 24px plus 24px
   margins in normal flow. Taking it out of flow keeps the actions row at the
   designed 52px while leaving it visible during submission. */
.ls-form__actions{position:relative}
.ls-form__actions .wpcf7-spinner{position:absolute}

/* Validation styling from the Input State=Error variant (node 52:14, 360x97 =
   17 label + 6 + 51 field + 6 + 17 helper). CF7 emits the tip as a sibling of
   the control, so .ls-field's existing 6px gap already places it correctly. */
/* CF7 ships its own stylesheet whose selectors (.wpcf7 form .x) outweigh a bare
   class, so the rules below carry the .wpcf7 ancestor to win on specificity
   rather than resorting to !important. Without it CF7's stock notice styling
   applied: a 2px #00a0d2 border, 0.2em padding and 2em/1em margins, which added
   about 100px to the form the moment a message appeared. */
.wpcf7 form .ls-field input.wpcf7-not-valid,
.wpcf7 form .ls-field select.wpcf7-not-valid,
.wpcf7 form .ls-field textarea.wpcf7-not-valid{border-color:var(--ls-text-error)}
.wpcf7 form .ls-field .wpcf7-not-valid-tip{
  font-size:12px;font-weight:500;line-height:1.4;color:var(--ls-text-error);
}
/* The email field carries two validation rules, required and email format, and
   CF7 appends one tip span per failing rule. Both read "Please enter an email
   address", so an empty or malformed address printed the same line twice under
   the field. Verified on the live form 18 Aug 2026. The tips are aria-hidden
   and the wording reaches screen readers once through the response region, so
   hiding the duplicate changes nothing an assistive tech user hears. */
.wpcf7 form .ls-field .wpcf7-not-valid-tip ~ .wpcf7-not-valid-tip{display:none}

/* Response box, restyled to the palette. It is display:none at rest, so it
   costs no height until a message shows; then it is one 20px gap plus the box. */
.wpcf7 form.ls-form__fields .wpcf7-response-output{
  margin:0;padding:12px 14px;
  border:1px solid var(--ls-border-default);border-radius:var(--ls-radius-sm);
  font-size:15px;line-height:1.65;color:var(--ls-text-secondary);
}
.wpcf7 form.ls-form__fields.sent .wpcf7-response-output{
  border-color:var(--ls-accent-marker);background:var(--ls-surface-accent);
  color:var(--ls-text-primary);
}
.wpcf7 form.ls-form__fields.invalid .wpcf7-response-output,
.wpcf7 form.ls-form__fields.unaccepted .wpcf7-response-output,
.wpcf7 form.ls-form__fields.failed .wpcf7-response-output{
  border-color:var(--ls-text-error);color:var(--ls-text-error);
}

/* ==================================================================
   22. NAVIGATION, mega menu, mobile and tablet panel
   ================================================================== */
/* Until 2026-08-08 the nav was simply display:none below 1000px with nothing
   in its place, so tablet and phone visitors had no menu at all and could only
   reach pages from the footer. Desktop had the opposite problem: the chevron on
   "Capabilities" promised a dropdown that had never been built. Both are here.
   Mobile and tablet frames: nodes 318:43 / 318:50 / 318:83. Mega menu: 59:34. */

/* The icon sprite is markup, not layout, keep it out of the flex row. */
.ls-iconsprite{position:absolute;width:0;height:0;overflow:hidden}

/* Chevron mirrors the panel state so the header reports what it is doing. */
.ls-nav__cv{display:inline-block;transition:transform .18s ease}
.ls-header.is-mega-open .ls-nav__link[data-ls-mega] .ls-nav__cv{transform:rotate(180deg)}

/* Burger. 44px box around a 24px glyph so the target meets the 44px guideline
   while the mark itself stays on the icon set's 24px grid. */
.ls-burger{
  display:none;width:44px;height:44px;margin-left:auto;margin-right:-10px;
  align-items:center;justify-content:center;padding:0;border:0;background:none;
  cursor:pointer;border-radius:var(--ls-radius-sm);color:var(--ls-text-brand);
}
.ls-burger svg{
  width:24px;height:24px;fill:none;stroke:currentColor;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round;
}
.ls-burger__close{display:none}
.ls-header.is-mobile-open .ls-burger__close{display:block}
.ls-header.is-mobile-open .ls-burger__open{display:none}
.ls-burger:focus-visible{outline:2px solid var(--ls-text-link);outline-offset:2px}

/* Shared panel shell. Absolute, so the 84px bar is untouched and every page
   height below it stays exactly as measured. */
.ls-mega,.ls-mobile{
  position:absolute;left:0;right:0;top:100%;z-index:60;
  background:var(--ls-surface-page);padding-inline:var(--ls-gutter);
}
.ls-mega[hidden],.ls-mobile[hidden]{display:none}
.ls-mega{box-shadow:0 2px 4px rgba(0,0,0,.06),0 6px 16px rgba(0,0,0,.10)}
.ls-mega__inner,.ls-mobile__inner{max-width:var(--ls-container);margin-inline:auto}
.ls-mega__inner{padding:36px 0 28px}
/* Five columns since ServiceNow joined the eight. The gap comes down from
   40 to 24 to buy the descriptions back some measure: at a 1200 container
   five columns on a 40 gap leave 208px each, which wraps the longer ones to
   four lines. On 24 they get 220 and hold at three. */
.ls-mega__cols{
  display:grid;grid-template-columns:repeat(5,1fr);grid-template-rows:auto auto;
  grid-auto-flow:column;column-gap:24px;
}
/* The column wrappers stay in the markup for the mobile panel's sake, but on
   the desktop menu they step out of the box model so the ten items become
   direct grid children. Without this each column sizes its own rows, and one
   wrapped title (Application Development) drops that column's second item
   below the other four. */
.ls-mega__col{display:contents}
.ls-mega__item{
  display:flex;gap:10px;align-items:flex-start;text-decoration:none;
  padding:10px;margin:0 -10px 8px;border-radius:var(--ls-radius-sm);
}
.ls-mega__item:hover,.ls-mega__item:focus-visible{background:var(--ls-surface-accent)}
.ls-mega__item svg,.ls-mobile__cap svg{
  width:20px;height:20px;flex:none;fill:none;stroke:var(--ls-text-brand);
  stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;
}
.ls-mega__item svg{margin-top:2px}
.ls-mega__item:hover svg,.ls-mobile__cap:hover svg{stroke:var(--ls-accent-marker)}
.ls-mega__title{
  display:block;font-size:17px;font-weight:600;line-height:1.3;
  color:var(--ls-text-brand);margin-bottom:4px;
}
.ls-mega__desc{display:block;font-size:13.5px;line-height:1.55;color:var(--ls-text-secondary)}
.ls-mega__foot{margin:0;padding-top:14px}

/* Mobile panel. Scrolls internally rather than pushing the page down.
   The height is measured in dvh, not vh: on a phone 100vh is the viewport
   with the browser chrome hidden, so a vh-only panel ends below the address
   bar and the last row, the call to action, cannot be scrolled to. The vh
   line stays first as the fallback for browsers without dvh. */
.ls-mobile{
  border-bottom:1px solid var(--ls-border-default);
  box-shadow:0 6px 16px rgba(0,0,0,.10);
  max-height:calc(100vh - 84px);
  max-height:calc(100dvh - 84px);
  overflow-y:auto;
  /* Scrolling the panel to its end must not start scrolling the page behind. */
  overscroll-behavior:contain;
}
/* The last 24px sat under the gesture bar on phones that have one. */
.ls-mobile__inner{padding:10px 0 calc(24px + env(safe-area-inset-bottom, 0px))}
.ls-mobile__primary{display:flex;flex-direction:column;align-items:flex-start}
.ls-mobile__link{
  display:flex;align-items:center;height:48px;text-decoration:none;
  font-size:17px;font-weight:500;color:var(--ls-text-primary);
}
/* The panel marks the current page in colour alone. A rule under a 48px row
   sits hard against the next link and reads as a divider rather than a
   marker, which is the opposite of what it is for. */
.ls-mobile__link.is-active{color:var(--ls-text-brand)}
.ls-mobile__rule{border:0;height:1px;background:var(--ls-border-default);margin:14px 0 16px;align-self:stretch}
.ls-mobile__cta{align-self:flex-start}
/* The call to action is a block of its own rather than the tail of __primary.
   Inside __primary it rendered fourth of thirteen on a phone, above the
   capability list, because one markup serves both layouts and __primary is
   the tablet's left column. Split out, source order ends with the button. */
.ls-mobile__foot{display:flex;flex-direction:column;align-items:flex-start}
.ls-mobile__caps{padding-top:14px}
/* Eyebrow plus the 28x3 accent marker the h2 rules already use. */
.ls-mobile__label{
  margin:0 0 6px;font-size:11px;font-weight:600;line-height:1.3;
  letter-spacing:1.6px;text-transform:uppercase;color:var(--ls-text-muted);
}
.ls-mobile__label::after{content:"";display:block;width:28px;height:3px;background:var(--ls-accent-marker);margin-top:6px}
/* 44px rows: the same weight and colour as the primary links, only smaller,
   so the two columns read as equals rather than one looking washed out. */
.ls-mobile__cap{
  display:flex;align-items:center;gap:12px;height:44px;text-decoration:none;
  font-size:15px;font-weight:500;color:var(--ls-text-primary);
  border-radius:var(--ls-radius-sm);padding-inline:8px;margin-inline:-8px;
}
.ls-mobile__cap:hover,.ls-mobile__cap:focus-visible{background:var(--ls-surface-accent)}
/* "Capabilities" stays in the primary list at every width the panel is shown at.
   The eight cards below link to the individual capability pages; only this link
   reaches the /capabilities/ landing page, so it must never be hidden. */

/* Tablet: two columns, so the width is used and the CTA stays in view. */
@media (min-width:601px) and (max-width:1000px){
  /* Grid, not a row: three source blocks but two columns. The left column
     stacks primary over foot, the right spans both rows. */
  .ls-mobile__inner{
    display:grid;grid-template-columns:180px 1fr;column-gap:40px;
    grid-template-areas:"primary caps" "foot caps";
    align-items:start;padding:26px 0 30px;
  }
  .ls-mobile__primary{grid-area:primary}
  .ls-mobile__foot{grid-area:foot}
  .ls-mobile__caps{grid-area:caps}
  .ls-mobile__caps{
    flex:1;min-width:0;padding:18px 22px 20px;
    background:var(--ls-surface-subtle);border-radius:var(--ls-radius-sm);
  }
  .ls-mobile__capgrid{display:grid;grid-template-columns:1fr 1fr;column-gap:24px}
  .ls-mobile__label{margin-bottom:12px}
}

/* Which navigation is in play at which width. */
@media (max-width:1000px){
  .ls-burger{display:inline-flex}
  .ls-header__cta{display:none}
  .ls-mega{display:none}
  .ls-header{height:72px}
  .ls-header__logo{width:196px;height:55px}
  .ls-mobile{max-height:calc(100vh - 72px);max-height:calc(100dvh - 72px)}
  /* The bar is static, and the panel hangs off it, so opening the menu part
     way down a page put both above the top of the screen and the tap looked
     like it had done nothing. Pinned only while the panel is open, so the
     resting header is still the one in the frames. */
  .ls-header.is-mobile-open{position:sticky;top:0;z-index:70}
}
@media (max-width:720px){
  .ls-header{height:64px}
  .ls-header__logo{width:168px;height:47px}
  .ls-mobile{max-height:calc(100vh - 64px);max-height:calc(100dvh - 64px)}
}
@media (min-width:1001px){
  .ls-mobile{display:none}
}

/* Stop the page scrolling behind an open mobile panel. */
.ls-noscroll{overflow:hidden}

/* ==================================================================
   23. USABILITY, measured fixes, 2026-08-08
   ================================================================== */
/* Photography. Every capability page pulled three background images at
   their full 2400px size: hero 663KB, breather 491KB, approach 398KB,
   1.55MB served identically to a 390px phone and a 2560px monitor. CSS
   backgrounds cannot use srcset, so the URL is swapped here instead.
   functions.php now emits a --ls-*-image-sm beside each one, pointing at
   the 1024px derivative WordPress already generated on upload. The
   indirection below is what lets a single rule serve both, and it falls
   back to the full file if a derivative is ever missing. */
body{
  --ls-hero-src:var(--ls-hero-image);
  --ls-breather-src:var(--ls-breather-image);
  --ls-approach-src:var(--ls-approach-image);
  /* Home's own three photographs, 360KB, 852KB and 569KB at full size,
     all on the one page, which made it the heaviest on the site. */
  --ls-home-positioning-src:var(--ls-home-positioning-image);
  --ls-home-ai-src:var(--ls-home-ai-image);
  --ls-home-security-src:var(--ls-home-security-image);
}
@media (max-width:1024px){
  body{
    --ls-hero-src:var(--ls-hero-image-sm,var(--ls-hero-image));
    --ls-breather-src:var(--ls-breather-image-sm,var(--ls-breather-image));
    --ls-approach-src:var(--ls-approach-image-sm,var(--ls-approach-image));
    --ls-home-positioning-src:var(--ls-home-positioning-image-sm,var(--ls-home-positioning-image));
    --ls-home-ai-src:var(--ls-home-ai-image-sm,var(--ls-home-ai-image));
    --ls-home-security-src:var(--ls-home-security-image-sm,var(--ls-home-security-image));
  }
}
/* The hero alone takes a third step. Its band is portrait on a phone while
   the photographs are landscape, so cover scales by height and only the
   middle of the frame survives: at 390px and 3 device pixels per CSS pixel
   that is about a 2.4x upscale of the 1024px file. The 1536px derivative
   brings it to 1.6x for 66KB more, asked for only where the density can
   show the difference, so a low density tablet keeps the lighter file. The
   two comma separated queries are the same test written twice, the second
   for Safari versions that predate min-resolution. */
@media (max-width:1024px) and (min-resolution:2dppx),
       (max-width:1024px) and (-webkit-min-device-pixel-ratio:2){
  body{ --ls-hero-src:var(--ls-hero-image-md,var(--ls-hero-image-sm,var(--ls-hero-image))); }
}

@media (max-width:720px){
  /* Footer links measured 22px tall with 9px between them, half the 44px
     guideline, on the one part of the site mobile visitors were forced to
     use for navigation. 40px rows plus the existing 9px gap clears 44px
     between adjacent targets without changing the type or the rhythm. */
  .ls-footer__col a,.ls-footer__subcol a{display:flex;align-items:center;min-height:40px}
  .ls-footer__brand{min-height:0;display:block}

  /* The home hero rendered 38px on a phone where every other page rendered
     30px: .ls-hero--home at <=900px was outweighing the <=720px rule on
     specificity rather than by intent. */
  .ls-hero--home .ls-hero__title{font-size:30px;letter-spacing:-.4px}

  /* The anchor row scrolls sideways here with nothing to say so, hiding
     every section past the third. Fading the right edge is the standard
     affordance and costs no markup. */
  .ls-anchors{
    -webkit-mask-image:linear-gradient(90deg,#000 84%,transparent 100%);
    mask-image:linear-gradient(90deg,#000 84%,transparent 100%);
  }
}

/* Back to top. Pages run to 10,500px on a phone, roughly 27 screens, and
   the header does not stick, so reaching the menu again meant scrolling
   the whole way back. Shown only where that is true: below 1000px, and
   only after two screens of scrolling, so it never covers content on
   arrival. */
.ls-totop{
  position:fixed;right:16px;bottom:16px;z-index:70;
  width:44px;height:44px;padding:0;border:0;cursor:pointer;
  display:flex;align-items:center;justify-content:center;
  border-radius:var(--ls-radius-sm);
  background:var(--ls-action-primary);color:var(--ls-text-inverse);
  box-shadow:0 2px 8px rgba(0,0,0,.22);
  opacity:0;visibility:hidden;transform:translateY(6px);
  transition:opacity .18s ease,transform .18s ease,visibility .18s;
}
.ls-totop.is-shown{opacity:1;visibility:visible;transform:translateY(0)}
.ls-totop svg{
  width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round;
}
.ls-totop:focus-visible{outline:2px solid var(--ls-text-link);outline-offset:2px}
@media (min-width:1001px){.ls-totop{display:none}}
