/*
Theme Name:  BoxSolve
Theme URI:   https://boxsolve.com/
Description: Child theme of OceanWP for BOXSOLVE, LLC. All BoxSolve customisation
             lives here so parent theme updates cannot overwrite it. Design language
             and tokens: 02-brand/guidelines/BRAND-GUIDELINES.md.
Author:      BoxSolve
Author URI:  https://boxsolve.com/
Template:    oceanwp
Version:     1.0.0
*/

/* The parent stylesheet is enqueued from functions.php, not @import.
   Everything below is the approved site CSS, lifted unchanged from the static
/* ==========================================================================
   BoxSolve — site stylesheet
   Design language: V8 "patent drawing". Warm laid paper, hairline rules,
   FIG. numbering, engraved/hatched line work, one blue accent.

   This file is the single source of truth for the static build and is written
   so it ports straight into the WordPress child theme. Keep it that way:
   no page-ID-scoped rules, everything class-scoped.
   ========================================================================== */

:root{
  --paper:#FCFBF7; --paper-2:#F5F3ED;
  --ink:#17181A; --ink-2:#3A3C40; --ink-3:#6B6E73; --ink-4:#6B6E73;
  --hair:#C9C6BD;
  --blue:#0E7099; --blue-dk:#0B5E82; --blue-lt:#66CEF6;
  --sans:"IBM Plex Sans","Plex-fallback",system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --disp:Jost,"Jost-fallback","IBM Plex Sans",system-ui,sans-serif;
  --mono:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
}
*,*::before,*::after{box-sizing:border-box}

/* ==========================================================================
   HOST-THEME NEUTRALISERS
   These exist because this stylesheet runs inside OceanWP, which sets its own
   root size and styles bare form elements. Both were found by diffing computed
   styles against the static build, not by looking.
   ========================================================================== */

/* OceanWP sets html{font-size:62.5%}. Every rem in this file assumes a 16px
   root, so without this EVERY size renders at 0.625x - an 80px headline became
   50px. 100% is also the accessible value: it honours the visitor's own browser
   font-size setting, which 62.5% quietly discards. */
html{font-size:100%}

html{scroll-behavior:smooth}
body{margin:0;background:var(--paper);color:var(--ink-2);font-family:var(--sans);
  font-size:17px;line-height:1.7;-webkit-font-smoothing:antialiased;overflow-x:hidden}
/* laid-paper tooth */
body::before{
  content:"";position:fixed;inset:0;z-index:0;pointer-events:none;opacity:.5;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='p'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='4'/><feColorMatrix type='saturate' values='0'/></filter><rect width='180' height='180' filter='url(%23p)' opacity='.28'/></svg>");
  mix-blend-mode:multiply;
}
.page{position:relative;z-index:1}
.wrap{width:min(1240px,100% - 3.4rem);margin-inline:auto}
.wrap-n{width:min(820px,100% - 3.4rem);margin-inline:auto}
a{color:var(--blue);text-underline-offset:.22em}
a:hover{color:var(--blue-dk)}
/* Drive OceanWP's own focus variables as well as our rule. The parent
   theme's a11y sheet loads after ours at equal specificity, so setting the
   variables is what actually takes effect. */
:root{--owp-focus-outline-color:var(--blue);--owp-focus-outline-offset:3px;
  --owp-focus-outline-width:2px}
.boxsolve :where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{
  outline:2px solid var(--blue);outline-offset:3px}
img,svg{max-width:100%}
h1,h2,h3,h4{font-family:var(--disp);color:var(--ink);letter-spacing:-.028em;
  text-wrap:balance;font-weight:300;margin:0}
h1 b,h2 b,h3 b{font-weight:500}
p{margin:0}
.skip{position:absolute;left:-9999px;top:0;background:var(--ink);color:#fff;padding:.7rem 1.1rem;z-index:100}
.skip:focus{left:.6rem;top:.6rem}

/* registration marks at the sheet corners */
.regmark{position:fixed;width:20px;height:20px;z-index:3;pointer-events:none;opacity:.5}
.regmark::before,.regmark::after{content:"";position:absolute;background:var(--hair)}
.regmark::before{left:0;top:9px;width:20px;height:1px}
.regmark::after{top:0;left:9px;width:1px;height:20px}
.r1{top:20px;left:20px}.r2{top:20px;right:20px}.r3{bottom:20px;left:20px}.r4{bottom:20px;right:20px}
@media(max-width:900px){.regmark{display:none}}

/* figure caption */
.fig{font-family:var(--mono);font-size:.68rem;letter-spacing:.22em;text-transform:uppercase;
  color:var(--blue);margin:0 0 1.5rem;display:flex;align-items:center;gap:.9rem}
.fig i{font-style:normal;color:var(--ink-4)}
.fig::after{content:"";flex:1;height:1px;background:var(--hair);max-width:200px}

/* ------------------------------------------------------------------ header */
.hdr{position:sticky;top:0;z-index:60;padding:1.2rem 0;background:rgba(252,251,247,.93);
  backdrop-filter:blur(10px);border-bottom:1px solid transparent;transition:border-color .3s,padding .3s}
.hdr.is-stuck{border-bottom-color:var(--hair);padding:.75rem 0}
.hdr .wrap{display:flex;align-items:center;justify-content:space-between;gap:2rem}
.hdr img{height:27px;display:block}
.nav{display:flex;gap:2.1rem}
.nav a{font-family:var(--mono);font-size:.74rem;letter-spacing:.13em;text-transform:uppercase;
  color:var(--ink-3);text-decoration:none;position:relative;padding:.15rem 0}
.nav a:hover{color:var(--blue)}
.nav a[aria-current="page"]{color:var(--ink)}
.nav a[aria-current="page"]::after{content:"";position:absolute;left:0;right:0;bottom:-3px;height:1px;background:var(--blue)}
.call{font-family:var(--mono);font-size:.8rem;color:var(--ink);text-decoration:none;
  border:1px solid var(--hair);padding:.5rem 1rem;background:var(--paper);
  transition:border-color .25s,background .25s,color .25s}
.call:hover{border-color:var(--blue);background:var(--blue);color:#fff}
a[href^="tel:"]{white-space:nowrap}
@media(max-width:980px){.nav{display:none}}

/* ------------------------------------------------------------------ buttons */
.cta-row{display:flex;flex-wrap:wrap;gap:.9rem}
.boxsolve .btn,.btn{display:inline-flex;align-items:center;gap:.6rem;padding:.95rem 1.7rem;font-family:var(--mono);
  font-size:.78rem;letter-spacing:.11em;text-transform:uppercase;text-decoration:none;
  border:1px solid transparent;cursor:pointer;
  transition:transform .18s cubic-bezier(.2,.8,.3,1),background .22s,color .22s,border-color .22s}
.boxsolve .btn:active,.btn:active{transform:translateY(1px)}
.boxsolve .btn-a,.btn-a{background:var(--ink);color:var(--paper);border-color:transparent}
.boxsolve .btn-a:hover,.btn-a:hover{background:var(--blue);color:#fff;transform:translateY(-2px)}
.boxsolve .btn-b,.btn-b{border-color:var(--hair);color:var(--ink);background:var(--paper)}
.btn-b:hover{border-color:var(--ink);color:var(--ink);transform:translateY(-2px)}
.boxsolve .btn svg,.btn svg{width:14px;height:14px;flex:none}

/* ------------------------------------------------------- the etched drawing */
.plate svg{width:100%;height:auto;display:block;overflow:visible}
.et-out{fill:none;stroke:var(--ink);stroke-width:2.6;stroke-linejoin:round;
  stroke-dasharray:var(--l,3400);stroke-dashoffset:var(--l,3400);
  transition:stroke-dashoffset 1.6s cubic-bezier(.25,.85,.3,1)}
.is-drawn .et-out{stroke-dashoffset:0}
html:not(.js) .et-out{stroke-dashoffset:0}
html:not(.js) .et-fill,html:not(.js) .et-ink,html:not(.js) .et-lab,html:not(.js) .et-sub,html:not(.js) .et-dim,html:not(.js) .et-dimtx{opacity:1}
html:not(.js) .et-lead{stroke-dashoffset:0}
.et-blue{stroke:var(--blue-dk)}
.et-fill{opacity:0;transition:opacity .9s ease .75s}
.is-drawn .et-fill{opacity:1}
.et-ink{opacity:0;transition:opacity 1.1s ease 1.35s}
.is-drawn .et-ink{opacity:1}
.et-lead{fill:none;stroke:var(--ink-4);stroke-width:1.6;stroke-dasharray:var(--l,400);
  stroke-dashoffset:var(--l,400);transition:stroke-dashoffset 1s cubic-bezier(.3,.9,.3,1) .9s}
.is-drawn .et-lead{stroke-dashoffset:0}
.et-lab{font-family:var(--mono);font-size:30px;fill:var(--ink);letter-spacing:.12em;opacity:0;transition:opacity .7s ease 1.5s}
.et-sub{font-family:var(--mono);font-size:23px;fill:var(--ink-4);letter-spacing:.06em;opacity:0;transition:opacity .7s ease 1.65s}
.is-drawn .et-lab,.is-drawn .et-sub{opacity:1}
.et-dim{fill:none;stroke:var(--blue);stroke-width:1.4;opacity:0;transition:opacity .7s ease 1.2s}
.et-dimtx{font-family:var(--mono);font-size:21px;fill:var(--blue);letter-spacing:.08em;opacity:0;transition:opacity .7s ease 1.35s}
.is-drawn .et-dim,.is-drawn .et-dimtx{opacity:1}
[data-box]{--open:0}
[data-box] .s-top{transform:translateY(calc(var(--open) * -262.2px))}
[data-box] .s-bot{transform:translateY(calc(var(--open) *  262.2px))}
.plate .s-top{animation:oT 1.5s cubic-bezier(.22,.92,.28,1) .5s both}
.plate .s-bot{animation:oB 1.5s cubic-bezier(.22,.92,.28,1) .5s both}
@keyframes oT{from{transform:translateY(0)}to{transform:translateY(-262.2px)}}
@keyframes oB{from{transform:translateY(0)}to{transform:translateY(262.2px)}}

/* -------------------------------------------------------------------- hero */
.hero{padding:6rem 0 5.6rem}
.hero .wrap{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.04fr);gap:3.5rem;align-items:center}
.hero h1{font-size:clamp(2.7rem,1.2rem + 5vw,5rem);line-height:1.0;margin:0 0 1.8rem}
.hero .lede{font-size:1.18rem;color:var(--ink-3);max-width:48ch;margin:0 0 2.4rem}
/* Fallback metrics matched to Jost and IBM Plex Sans.
   Once the parent theme's unused CSS stopped blocking first paint, the page
   painted BEFORE the webfonts arrived and the swap reflowed the hero - CLS went
   from 0.000 to 0.034 on a phone. Overriding the fallback's metrics makes the
   pre-swap and post-swap text occupy nearly the same box. */
@font-face{font-family:'Jost-fallback';src:local('Helvetica Neue'),local('Arial');
  size-adjust:106%;ascent-override:95%;descent-override:24%;line-gap-override:0%}
@font-face{font-family:'Plex-fallback';src:local('Helvetica Neue'),local('Arial');
  size-adjust:104%;ascent-override:96%;descent-override:26%;line-gap-override:0%}
@media(max-width:920px){.hero{padding:4.4rem 0 4rem}.hero .wrap{grid-template-columns:1fr;gap:2.5rem}}

/* interior page hero (no drawing) */
.phero{padding:5.6rem 0 4.4rem;border-bottom:1px solid var(--hair)}
.phero h1{font-size:clamp(2.3rem,1.2rem + 3.6vw,4rem);line-height:1.02;margin:0 0 1.4rem;max-width:20ch}
.phero .lede{font-size:1.16rem;color:var(--ink-3);max-width:60ch;margin:0 0 2.2rem}
.crumb{font-family:var(--mono);font-size:.68rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--ink-4);margin:0 0 1.4rem}
.crumb a{color:var(--ink-4);text-decoration:none;display:inline-block;padding:.35rem 0}
.crumb a:hover{color:var(--blue)}
.crumb span{margin:0 .55rem;opacity:.6}

/* ---------------------------------------------------------------- sections */
section{padding:5.6rem 0;border-top:1px solid var(--hair);position:relative}
section:first-of-type{border-top:0}
h2{font-size:clamp(1.9rem,1.1rem + 2.6vw,3rem);line-height:1.07;margin:0 0 1.2rem}
h3{font-size:1.35rem;font-weight:400}
.lede{font-size:1.08rem;color:var(--ink-3);max-width:58ch}
.two{display:grid;grid-template-columns:minmax(0,4fr) minmax(0,7fr);gap:4.5rem}
@media(min-width:961px){.two>div:first-child{position:sticky;top:7rem;align-self:start}}
@media(max-width:960px){.two{grid-template-columns:1fr;gap:2.4rem}}

/* FAIL-SAFE REVEAL.
   Content is visible by DEFAULT. The hidden starting state only applies once
   the inline head script has set .js on <html>, which it does synchronously
   before first paint, so there is no flash.

   Why this way round: with `[data-reveal]{opacity:0}` as the default, a
   JavaScript error, a blocked script, or a crawler that does not execute JS
   leaves most of the page INVISIBLE. That happened here and it took a
   full-page screenshot to notice, because the top of the page looked perfect. */
[data-reveal]{opacity:1;transform:none}
html.js [data-reveal]{opacity:0;transform:translateY(16px);
  transition:opacity .75s cubic-bezier(.2,.7,.25,1),transform .75s cubic-bezier(.2,.7,.25,1)}
html.js [data-reveal].is-in{opacity:1;transform:none}

/* ------------------------------------------------- drifting ghost slabs ---- */
.drift-host{position:relative}
.drift-host > .wrap{position:relative;z-index:1}
.drift{position:absolute;inset:0;overflow:clip;pointer-events:none;z-index:0}
.drift svg{position:absolute;display:block;width:var(--w,300px);height:auto;
  stroke:var(--ink);fill:none;stroke-width:2.6;stroke-linejoin:round;opacity:.13}
.drift .g1{left:0%;top:20%;--w:min(360px,27vw)}
.drift .g2{left:15%;top:56%;--w:min(280px,21vw);opacity:.10}
.drift .g3{right:-4%;bottom:5%;--w:min(240px,18vw);opacity:.115}
@media(max-width:960px){.drift{display:none}}
@supports (animation-timeline: view()){
  @media (prefers-reduced-motion: no-preference){
    .drift-host{view-timeline:--drift;overflow-x:clip}
    .drift svg{animation:linear both;animation-timeline:--drift;animation-range:cover}
    .drift .g1{animation-name:drift1}
    .drift .g2{animation-name:drift2}
    .drift .g3{animation-name:drift3}
  }
}
@keyframes drift1{0%{transform:translate3d(-14px,110px,0);opacity:0}20%{opacity:.13}80%{opacity:.13}100%{transform:translate3d(14px,-110px,0);opacity:0}}
@keyframes drift2{0%{transform:translate3d(18px,160px,0);opacity:0}22%{opacity:.10}78%{opacity:.10}100%{transform:translate3d(-18px,-160px,0);opacity:0}}
@keyframes drift3{0%{transform:translate3d(-8px,80px,0);opacity:0}20%{opacity:.115}80%{opacity:.115}100%{transform:translate3d(10px,-80px,0);opacity:0}}

/* ------------------------------------------------------------- spec list --- */
.spec{list-style:none;margin:0;padding:0;border-top:1px solid var(--hair)}
.spec li{display:grid;grid-template-columns:6.5rem 1fr;gap:1.8rem;padding:2rem 0;
  border-bottom:1px solid var(--hair)}
.spec .k{font-family:var(--mono);font-size:.7rem;letter-spacing:.14em;color:var(--blue);padding-top:.5rem}
.spec h3{font-size:1.5rem;margin:0 0 .5rem;letter-spacing:-.018em}
.spec p{color:var(--ink-3);font-size:1rem;max-width:54ch}
@media(max-width:640px){.spec li{grid-template-columns:1fr;gap:.5rem}}

/* ---------------------------------------------------------- detail cards --- */
.details{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:1.5rem;margin-top:3.2rem}
.dt{background:var(--paper);border:1px solid var(--hair);padding:2.4rem 2.1rem;position:relative;
  display:flex;flex-direction:column;text-decoration:none;color:inherit;
  transition:border-color .35s ease,transform .35s cubic-bezier(.2,.8,.3,1),box-shadow .35s ease}
.dt::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;background:var(--blue);
  transform:scaleX(0);transform-origin:left;transition:transform .45s cubic-bezier(.2,.8,.3,1)}
.dt:hover{border-color:var(--blue);transform:translateY(-5px);box-shadow:0 18px 40px -26px rgba(23,24,26,.4)}
.dt:hover::after{transform:scaleX(1)}
.dt .k{font-family:var(--mono);font-size:.67rem;letter-spacing:.17em;color:var(--blue);display:block;margin-bottom:1.4rem}
.dt .ico{width:38px;height:38px;color:var(--blue-dk);margin-bottom:1.3rem}
.dt h3{font-size:1.36rem;margin:0 0 .6rem;letter-spacing:-.018em}
.dt p{margin:0 0 1.4rem;color:var(--ink-3);font-size:.97rem}
.dt .more{margin-top:auto;font-family:var(--mono);font-size:.72rem;letter-spacing:.12em;
  text-transform:uppercase;color:var(--blue);display:inline-flex;align-items:center;gap:.5rem}
.dt .more svg{width:13px;height:13px;transition:transform .3s cubic-bezier(.2,.8,.3,1)}
.dt:hover .more svg{transform:translateX(4px)}

/* --------------------------------------------------------------- sequence --- */
.seq{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:2rem}
.sq{position:relative;padding-top:2.6rem;border-top:1px solid var(--ink)}
.sq::before{content:"";position:absolute;top:-4.5px;left:0;width:8px;height:8px;
  background:var(--paper);border:1px solid var(--blue);transform:rotate(45deg)}
.sq .k{font-family:var(--mono);font-size:.68rem;letter-spacing:.15em;color:var(--blue);display:block;margin-bottom:.8rem}
.sq h3{font-size:1.1rem;margin:0 0 .45rem}
.sq p{font-size:.94rem;color:var(--ink-3)}

/* ----------------------------------------------------------------- notes --- */
.notes{display:grid;grid-template-columns:repeat(auto-fit,minmax(285px,1fr));gap:2.2rem}
.nt{position:relative;padding-left:1.6rem}
.nt::before{content:"";position:absolute;left:0;top:.55rem;bottom:.4rem;width:1px;background:var(--blue)}
.nt h3{font-size:1.08rem;margin:0 0 .55rem;line-height:1.35}
.nt p{font-size:.94rem;color:var(--ink-3)}

/* ------------------------------------------------------------------ prose --- */
.prose{max-width:68ch}
.prose h2{font-size:clamp(1.6rem,1.1rem + 1.6vw,2.2rem);margin:3rem 0 1rem}
.prose h2:first-child{margin-top:0}
.prose h3{font-size:1.3rem;margin:2.2rem 0 .7rem}
.prose p{margin:0 0 1.15rem;color:var(--ink-2)}
.prose ul,.prose ol{margin:0 0 1.4rem;padding-left:1.3rem;color:var(--ink-2)}
.prose li{margin:.45rem 0}
.prose strong{font-weight:600;color:var(--ink)}
.prose hr{border:0;border-top:1px solid var(--hair);margin:2.6rem 0}
.prose .small{font-size:.9rem;color:var(--ink-3)}

/* ------------------------------------------------------------------- FAQ --- */
.faq{border-top:1px solid var(--hair);margin-top:2.6rem}
.faq details{border-bottom:1px solid var(--hair)}
.faq summary{cursor:pointer;list-style:none;padding:1.5rem 2.5rem 1.5rem 0;position:relative;
  font-family:var(--disp);font-size:1.2rem;font-weight:400;color:var(--ink);letter-spacing:-.015em}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"";position:absolute;right:.4rem;top:2rem;width:11px;height:11px;
  border-right:1.5px solid var(--blue);border-bottom:1.5px solid var(--blue);
  transform:rotate(45deg);transition:transform .3s ease}
.faq details[open] summary::after{transform:rotate(-135deg);top:2.3rem}
.faq .a{padding:0 2.5rem 1.7rem 0;color:var(--ink-3);max-width:66ch}
.faq .a p{margin:0 0 .9rem}
.faq .a p:last-child{margin:0}

/* ------------------------------------------------------------ related ------ */
.related{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:1.2rem;margin-top:2.4rem}
.rl{border:1px solid var(--hair);padding:1.6rem 1.5rem;text-decoration:none;color:inherit;
  transition:border-color .3s,transform .3s cubic-bezier(.2,.8,.3,1)}
.rl:hover{border-color:var(--blue);transform:translateY(-3px)}
.rl b{display:block;font-family:var(--mono);font-size:.64rem;letter-spacing:.17em;
  text-transform:uppercase;color:var(--blue);margin-bottom:.6rem;font-weight:500}
.rl span{font-family:var(--disp);font-size:1.14rem;color:var(--ink);display:block;letter-spacing:-.015em}

/* ---------------------------------------------------------------- contact --- */
.contact{background:var(--paper-2)}
.cgrid{display:grid;grid-template-columns:minmax(0,.95fr) minmax(0,1.05fr);gap:4rem;align-items:start}
.bigphone{font-family:var(--disp);font-weight:200;font-size:clamp(2.1rem,1.4rem + 2.4vw,3.3rem);
  color:var(--ink);text-decoration:none;letter-spacing:-.035em;display:inline-block;
  margin:.4rem 0 2rem;transition:color .22s}
.bigphone:hover{color:var(--blue)}
.cmeta{display:grid;gap:1.2rem;border-top:1px solid var(--hair);padding-top:1.7rem}
.cmeta b{display:block;font-family:var(--mono);font-size:.66rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--blue);margin-bottom:.2rem;font-weight:500}
.cmeta a{color:var(--ink);text-decoration:none;border-bottom:1px solid var(--blue)}
form{background:var(--paper);border:1px solid var(--hair);padding:2.2rem}
.f{margin-bottom:1.15rem}
.f label{display:block;font-family:var(--mono);font-size:.66rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-4);margin-bottom:.4rem}
.boxsolve .f input,.boxsolve .f select,.boxsolve .f textarea,
.f input,.f select,.f textarea{width:100%;padding:.78rem .8rem;background:var(--paper-2);
  color:var(--ink);border:1px solid var(--hair);font-family:var(--sans);font-size:.97rem;
  line-height:1.7;border-radius:0;transition:border-color .22s,background .22s}
.f input:focus-visible,.f select:focus-visible,.f textarea:focus-visible{
  outline:2px solid var(--blue);outline-offset:2px}
/* OceanWP paints :invalid red on FOCUS, so tabbing into an empty required
   field showed an error state before the visitor had done anything wrong. */
.boxsolve form :is(input,select,textarea):focus-visible:invalid{
  color:var(--ink);border-color:var(--blue)}
.f input:focus,.f select:focus,.f textarea:focus{border-color:var(--blue);background:#fff;outline:none}
.f textarea{min-height:94px;resize:vertical}
.f2{display:grid;grid-template-columns:1fr 1fr;gap:1.15rem}
.consent{display:flex;flex-wrap:wrap;gap:.35rem .7rem;font-size:.83rem;color:var(--ink-3);margin:1.4rem 0}
/* The consent control is a real checkbox, restyled. The browser default is a
   small hollow box that reads as decoration next to 14px text, and David could
   not tell it was a control. This gives it a visible border at rest and a solid
   brand-blue tick when checked, at a size that is legible next to the label. */
.consent input[type=checkbox]{
  appearance:none;-webkit-appearance:none;
  width:20px;height:20px;flex:none;margin:0;
  border:1.5px solid var(--ink-3);background:#fff;
  display:inline-block;vertical-align:middle;position:relative;top:1px;
  cursor:pointer;transition:background-color .15s ease,border-color .15s ease}
.consent input[type=checkbox]:hover{border-color:var(--blue)}
.consent input[type=checkbox]:checked{
  background-color:var(--blue);border-color:var(--blue);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6L9 17l-5-5'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:center;background-size:13px 13px}
.consent input[type=checkbox]:focus-visible{
  outline:2px solid var(--blue);outline-offset:2px}
.consent label{font-size:.83rem;color:var(--ink-3);cursor:pointer}
.consent-x{font-size:.83rem;color:var(--ink-3);flex-basis:100%;margin-left:1.4rem}
.opt{color:var(--ink-3);font-weight:400;text-transform:none;letter-spacing:0}
.boxsolve form button,form button{border:0;width:100%;justify-content:center;font-family:var(--mono);font-size:.78rem;letter-spacing:.11em;text-transform:uppercase;font-weight:400;line-height:normal;padding:.95rem 1.7rem}
.trust{display:flex;flex-wrap:wrap;gap:1.4rem;margin:1.6rem 0 0;padding-top:1.4rem;
  border-top:1px solid var(--hair);font-family:var(--mono);font-size:.7rem;
  letter-spacing:.09em;text-transform:uppercase;color:var(--ink-4)}
.trust span{display:inline-flex;align-items:center;gap:.5rem}
.trust svg{width:13px;height:13px;color:var(--blue);flex:none}
@media(max-width:960px){.cgrid{grid-template-columns:1fr;gap:2.6rem}.f2{grid-template-columns:1fr;gap:0}}

/* ------------------------------------------------- sticky mobile call bar --- */
.callbar{display:none}
@media(max-width:860px){
  .callbar{display:flex;position:fixed;left:0;right:0;bottom:0;z-index:70;background:var(--ink);
    border-top:1px solid rgba(255,255,255,.14);padding:.55rem .8rem;gap:.6rem}
  .callbar a{flex:1;display:inline-flex;align-items:center;justify-content:center;gap:.55rem;
    padding:.85rem .6rem;font-family:var(--mono);font-size:.78rem;letter-spacing:.09em;
    text-transform:uppercase;text-decoration:none;white-space:nowrap}
  .callbar .c1{background:var(--blue);color:#fff}
  .callbar .c2{border:1px solid rgba(255,255,255,.3);color:#fff}
  .callbar svg{width:15px;height:15px;flex:none}
  body{padding-bottom:68px}
}

/* --------------------------------------------------- footer / title block --- */
footer{border-top:2px solid var(--ink);background:var(--paper)}
.tblock{display:grid;grid-template-columns:2fr 1fr 1fr 1.1fr;border-bottom:1px solid var(--hair)}
.tb{padding:1.7rem 1.6rem;border-right:1px solid var(--hair)}
.tb:last-child{border-right:0}
.tb b{display:block;font-family:var(--mono);font-size:.63rem;letter-spacing:.18em;
  text-transform:uppercase;color:var(--ink-4);margin-bottom:.55rem;font-weight:500}
.tb img{height:26px;margin-bottom:.7rem}
.hdr .wrap > a:first-child{display:flex;align-items:center;padding:.45rem 0}
.tb a{color:var(--ink-2);text-decoration:none}
.tb ul a{display:inline-block;padding:.42rem 0}
.tb a:hover{color:var(--blue)}
.tb ul{list-style:none;margin:0;padding:0;display:grid;gap:.05rem;font-size:.88rem}
.tb ul li{line-height:1.5}
.tb p{font-size:.88rem;color:var(--ink-3)}
.legal{padding:1.3rem 1.6rem;display:flex;flex-wrap:wrap;gap:.5rem 1.8rem;
  justify-content:space-between;font-family:var(--mono);font-size:.72rem;
  letter-spacing:.06em;color:var(--ink-4)}
.legal .ent{color:var(--ink)}
.legal a{color:var(--ink-4)}
@media(max-width:900px){.tblock{grid-template-columns:1fr 1fr}.tb{border-bottom:1px solid var(--hair)}}
@media(max-width:560px){.tblock{grid-template-columns:1fr}.tb{border-right:0}}

@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation:none !important;transition:none !important}
  [data-reveal],html.js [data-reveal]{opacity:1 !important;transform:none !important}
  .et-out,.et-lead{stroke-dashoffset:0 !important}
  .et-fill,.et-ink,.et-lab,.et-sub,.et-dim,.et-dimtx{opacity:1 !important}
  .plate .s-top{transform:translateY(-262.2px)}
  .plate .s-bot{transform:translateY(262.2px)}
  .dt::after{transform:scaleX(0)}
  .drift svg{transform:none}
}

/* ==========================================================================
   RESPONSIVE — verified at 1280 desktop / 768 tablet / 390 phone,
   plus 360 and 320 for the phone button wrap check. Those are the widths the
   carried-over QA sweep uses; see 05-build/WP-BUILD-KNOWLEDGE.md sec.4.
   ========================================================================== */

/* ---------------------------------------------------- mobile / tablet nav ---
   <details> rather than a JS toggle, so it works with scripting off and is
   keyboard accessible for free. The panel is absolutely positioned, so opening
   it moves nothing: CLS 0 by construction. */
.mnav{display:none;position:relative}
.mnav summary{
  list-style:none;cursor:pointer;width:44px;height:44px;display:flex;
  align-items:center;justify-content:center;border:1px solid var(--hair);
  background:var(--paper);transition:border-color .25s}
.mnav summary::-webkit-details-marker{display:none}
.mnav summary:hover{border-color:var(--blue)}
.mnav summary i{display:block;width:19px;height:1.5px;background:var(--ink);position:relative}
.mnav summary i::before,.mnav summary i::after{
  content:"";position:absolute;left:0;width:19px;height:1.5px;background:var(--ink);
  transition:transform .28s cubic-bezier(.2,.8,.3,1)}
.mnav summary i::before{top:-6px}
.mnav summary i::after{top:6px}
.mnav[open] summary i{background:transparent}
.mnav[open] summary i::before{transform:translateY(6px) rotate(45deg)}
.mnav[open] summary i::after{transform:translateY(-6px) rotate(-45deg)}
.mnav .panel{
  position:absolute;right:0;top:calc(100% + .7rem);z-index:80;min-width:240px;
  background:var(--paper);border:1px solid var(--hair);
  box-shadow:0 22px 48px -28px rgba(23,24,26,.45);padding:.5rem 0}
.mnav .panel a{
  display:block;padding:.85rem 1.5rem;font-family:var(--mono);font-size:.76rem;
  letter-spacing:.13em;text-transform:uppercase;color:var(--ink-2);text-decoration:none}
.mnav .panel a:hover{background:var(--paper-2);color:var(--blue)}
.mnav .panel a[aria-current="page"]{color:var(--blue)}
.mnav .panel hr{border:0;border-top:1px solid var(--hair);margin:.5rem 0}
@media(max-width:980px){ .mnav{display:block} }

/* ------------------------------------------------------------ 1100 and down */
@media(max-width:1100px){
  .details{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* --------------------------------------------------- tablet, 1024 and down */
@media(max-width:1024px){
  .wrap,.wrap-n{width:min(1240px,100% - 2.6rem)}
  section{padding:4.6rem 0}
  .hero{padding:4.8rem 0 4.4rem}
  .phero{padding:4.4rem 0 3.6rem}
  .seq{grid-template-columns:repeat(2,minmax(0,1fr));gap:2rem 2.4rem}
  .notes{grid-template-columns:repeat(2,minmax(0,1fr))}
  .hdr .wrap{gap:1rem}
}

/* ------------------------------------------------- small tablet, 768 down */
@media(max-width:768px){
  body{font-size:16.5px}
  .details{grid-template-columns:1fr}
  .notes{grid-template-columns:1fr;gap:1.8rem}
  .phero{padding:4.2rem 0 3.4rem}
  .phero h1{max-width:none}
  section{padding:4rem 0}
  .cta-row .btn{flex:1 1 auto;justify-content:center}
  .faq summary{font-size:1.08rem;padding-right:2.2rem}
  .prose{max-width:none}
}

/* --------------------------------------------------------- phone, 600 down */
/* ------------------------------------------------- the assembly on a phone */
/* The drawing's viewBox reserves x1330-1860 (28% of its width) for the
   '01 THE SITE' callouts. Scaled into a 390px column those labels render at
   about 6px - unreadable - while still holding a third of the width empty, so
   the box itself came out small and parked left.
   Crop that column off and scale the drawing to fill instead. viewBox cannot
   be set from CSS, so it is done by over-widthing the SVG inside a clipping
   parent: 1900/1420 = 1.338. */
@media(max-width:760px){
  .plate{overflow:hidden}
  .plate svg{width:133.8%;max-width:none;overflow:hidden}
  .plate .et-lab,.plate .et-sub,.plate .et-lead,
  .plate .et-dim,.plate .et-dimtx{display:none}
}

@media(max-width:600px){
  .wrap,.wrap-n{width:min(1240px,100% - 2.1rem)}
  /* The header phone button is dropped on phones: it does not fit next to the
     logo and the menu (measured cramped from 430px down), and the sticky call
     bar already puts Call Now permanently on screen. Removing it also kills a
     duplicate call action rather than shrinking one until it is unreadable. */
  .hdr .call{display:none}
  .seq{grid-template-columns:1fr;gap:1.8rem}
  .hero h1,.phero h1{letter-spacing:-.02em}
  .hero .lede,.phero .lede,.lede{font-size:1.04rem}
  .cta-row{gap:.7rem}
  .cta-row .btn{width:100%;flex:1 1 100%}
  .dt{padding:1.9rem 1.5rem}
  form{padding:1.6rem 1.3rem}
  .trust{gap:.8rem;flex-direction:column}
  .legal{flex-direction:column;gap:.5rem}
  .tb{padding:1.4rem 1.3rem}
  .spec li{padding:1.6rem 0}
  .bigphone{font-size:clamp(1.9rem,1.1rem + 4vw,2.6rem)}
  .mnav .panel{min-width:min(78vw,280px)}
}

/* ----------------------------------------------------- very narrow, 380 down
   The tel: button must stay on ONE line at 390 / 360 / 320. Carried-over rule:
   target the href, never a class list. */
@media(max-width:380px){
  .hdr img{height:24px}
  .call{font-size:.74rem;padding:.45rem .7rem}
  .callbar a{font-size:.72rem;letter-spacing:.06em;padding:.8rem .4rem}
  .btn{padding:.9rem 1.1rem;font-size:.73rem;letter-spacing:.08em}
  h2{font-size:1.75rem}
}

/* ==========================================================================
   HOST-THEME NEUTRALISERS, part 2
   OceanWP styles bare elements (body, h2, footer, button, select) at the same
   specificity as this file and emits its customiser CSS INLINE in <head>, which
   lands after any enqueued stylesheet. Equal specificity, later source, so it
   wins. Re-asserting under the shared body class raises us above it.

   Every rule here was produced by diffing computed styles against the static
   build (04-design/site-build/qa/parity.js), not by eye. Do not add to this
   block speculatively - add only what a diff proves is being overridden.
   ========================================================================== */
.boxsolve{font-size:17px;line-height:1.7;color:var(--ink-2);background:var(--paper)}
.boxsolve h1,.boxsolve h2,.boxsolve h3,.boxsolve h4{
  font-family:var(--disp);color:var(--ink);letter-spacing:-.028em;font-weight:300;margin:0}
.boxsolve h2{font-size:clamp(1.9rem,1.1rem + 2.6vw,3rem);line-height:1.07;margin:0 0 1.2rem}
.boxsolve h3{font-size:1.35rem;font-weight:400}
.boxsolve h1 b,.boxsolve h2 b,.boxsolve h3 b{font-weight:500}
.boxsolve .lede{font-size:1.08rem;line-height:1.7;color:var(--ink-3)}
.boxsolve .spec h3{font-size:1.5rem;line-height:1.7;letter-spacing:-.018em}
.boxsolve .dt h3{font-size:1.36rem;line-height:1.7;letter-spacing:-.018em}
.boxsolve .nt h3{font-size:1.08rem;line-height:1.35}
.boxsolve .sq h3{font-size:1.1rem;line-height:1.7}
.boxsolve .faq summary{line-height:1.7}
.boxsolve .bigphone{line-height:1.7}
.boxsolve .fig,.boxsolve .crumb,.boxsolve .cmeta b,.boxsolve .tb b,.boxsolve .trust,
.boxsolve .f label{line-height:1.7}
.boxsolve footer{font-size:.9rem;line-height:1.7}
/* These three need !important, and only these three. OceanWP declares
   `form select{padding-top:0 !important;padding-bottom:0 !important}` literally,
   and its button rule wins the cascade against our scoped selector. Verified
   with CSS.getMatchedStylesForNode - not assumed. Do not spread !important
   beyond the declarations a diff proves are being overridden. */
.boxsolve form button,.boxsolve .btn{font-weight:400 !important;line-height:normal !important}
.boxsolve .f select{
  /* OceanWP forces select{height:2.25em} AND min-height:40px. With border-box
     and our 12.5px padding that leaves ~13px of content box for 15.5px text, so
     the option label is clipped at the baseline. Release the fixed height and
     let padding size the control, which also makes it match the inputs (53px). */
  height:auto !important;min-height:0 !important;
  padding:.905rem .8rem !important;line-height:1.7}
.boxsolve .f input,.boxsolve .f textarea{line-height:1.7}

/* ------------------------------------------------------------- form state --- */
/* Honeypot: off-screen rather than display:none, because some bots skip hidden
   fields. Never focusable, never announced. */
.hp{position:absolute;left:-9999px;top:auto;width:1px;height:1px;overflow:hidden}
.formnote{scroll-margin-top:6rem;padding:1rem 1.2rem;margin:0 0 1.2rem;font-size:.95rem;border-left:3px solid}
.formnote.good{background:#eef7f1;border-color:#0d7a4a;color:#14532d}
.formnote.bad{background:#fdf2f2;border-color:#b32d2e;color:#7f1d1d}

/* The skip link moves focus here programmatically; main needs to be
   focusable for that, and the ring would otherwise be a visual artifact. */
#main:focus{outline:none}
/* list-style:none strips list semantics in Safari/VoiceOver. role=list on
   the markup restores them; this is the matching note. */


/* CF7 wraps every control in <span class="wpcf7-form-control-wrap">, which is
   inline by default and adds a stray line-height gap under each field - most
   visibly under the select. Block removes it without touching our own layout. */
.boxsolve .wpcf7-form-control-wrap{display:block}
/* ...except the consent checkbox, which must stay inline with its label. */
.boxsolve .consent .wpcf7-form-control-wrap{display:inline;flex:none}
.boxsolve .consent .wpcf7-list-item{margin:0}
.boxsolve .consent .wpcf7-list-item-label{display:none}
.boxsolve .consent{align-items:flex-start}

/* ------------------------------------------------------- Contact Form 7 ---
   The form is CF7, so the submit control is an <input>, not a <button>. An
   input cannot contain the arrow SVG the design uses and it does not take
   ::after, so the arrow is a background image here. Width matches the
   hand-built button it replaced. */
/* The offline preview's <button> is styled to match the live CF7 <input>
   exactly, including the arrow, so a parity diff between static and live means
   something is genuinely wrong rather than "that is just the CF7 swap". A
   permanent expected difference trains you to ignore the check. */
.cf7-preview button.btn,
.boxsolve .wpcf7 input[type=submit].btn{
  width:100%;display:block;text-align:center;
  padding-right:3rem;padding-left:3rem;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FCFBF7' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 1.7rem center;background-size:14px 14px}
.boxsolve .wpcf7 input[type=submit].btn:hover{background-color:var(--blue)}

/* CF7 injects its own response and validation markup. Style it to the site
   rather than leaving the plugin's defaults on an otherwise custom page. */
.boxsolve .wpcf7-not-valid-tip{color:#7F1D1D;font-size:.8rem;margin-top:.35rem;display:block}
.boxsolve .wpcf7 .f input.wpcf7-not-valid,
.boxsolve .wpcf7 .f textarea.wpcf7-not-valid{border-color:#7F1D1D}
.boxsolve .wpcf7-response-output{
  margin:1.2rem 0 0;padding:.85rem 1rem;border:1px solid;font-size:.9rem;
  scroll-margin-top:6rem}
.boxsolve .wpcf7 form.sent .wpcf7-response-output{
  border-color:#14532D;background:#EEF7F1;color:#14532D}
.boxsolve .wpcf7 form.invalid .wpcf7-response-output,
.boxsolve .wpcf7 form.unaccepted .wpcf7-response-output,
.boxsolve .wpcf7 form.failed .wpcf7-response-output,
.boxsolve .wpcf7 form.spam .wpcf7-response-output{
  border-color:#7F1D1D;background:#FDF2F2;color:#7F1D1D}
/* The plugin's spinner sits inline and shifts the button; keep it out of flow. */
.boxsolve .wpcf7-spinner{position:absolute;margin-left:.6rem}
.boxsolve .wpcf7 form{position:relative}
