:root{
  --navy:#00204F;          /* brand ground — sampled #001E64, deepened for large fields */
  --navy-deep:#001536;     /* hovers, the layer below navy */
  --azure:#0E76DC;         /* the logo's bright blue — accents and actions */
  --azure-deep:#0A5CB0;    /* azure hover */
  --ink:#0A1526;           /* near-black with a blue cast, so it sits under navy rather than beside it */
  --ink-soft:#12203A;
  --paper:#FFFFFF;
  --mist:#EFF4FA;          /* light sections — cool white, not cream */
  --line-on-navy:rgba(255,255,255,.14);
  --on-navy:#fff;
  --on-navy-dim:rgba(255,255,255,.72);
  --font-head:'Space Grotesk',sans-serif;
  --font-body:'Inter',sans-serif;
  --maxw:1440px;
  --pad:48px;
  /* The fixed navbar's height. The container hangs from it, so the two have
     to agree; measured at 96px (22px padding either side of the mark). */
  --nav-h:96px;
}

*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
body{
  font-family:var(--font-body);
  background:var(--navy);
  color:var(--on-navy);
  line-height:1.5;
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
ul{list-style:none}
h1,h2,h3,h4{font-family:var(--font-head);font-weight:500;line-height:.98;letter-spacing:-.02em}

.wrap{max-width:var(--maxw);margin:0 auto;padding:0 var(--pad)}
@media(max-width:720px){:root{--pad:22px}}

/* Buttons — sharp corners */
.btn{
  display:inline-flex;align-items:center;gap:14px;
  font-family:var(--font-head);font-weight:500;font-size:1rem;
  background:var(--azure);color:#fff;padding:16px 26px;
  border-radius:2px;transition:background .3s,transform .3s;
}
.btn:hover{background:var(--azure-deep);transform:translateY(-2px)}
.btn .arw{transition:transform .3s}
.btn:hover .arw{transform:translate(4px,-4px)}
.btn.on-dark{background:#fff;color:var(--ink)}
.btn.on-dark:hover{background:var(--azure);color:#fff}

/* Small labels with rotating badge */
.label{display:inline-flex;align-items:center;gap:10px;font-family:var(--font-head);font-size:.8rem;letter-spacing:.12em;text-transform:uppercase;font-weight:500}
.label .badge{width:12px;height:12px;background:currentColor;clip-path:polygon(50% 0,100% 50%,50% 100%,0 50%);animation:spin 6s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}

/* ===== Preloader ===== */
#preloader{position:fixed;inset:0;z-index:1000;background:var(--navy);display:flex;align-items:center;justify-content:center;flex-direction:column;gap:14px}
#preloader .pl-logo{font-family:var(--font-head);font-weight:700;font-size:2.4rem;color:#fff;letter-spacing:-.03em}
#preloader .pl-tag{font-family:var(--font-head);font-size:.8rem;letter-spacing:.3em;text-transform:uppercase;color:var(--on-navy-dim);overflow:hidden}
#preloader .pl-bar{position:absolute;bottom:0;left:0;height:3px;background:var(--azure);width:0}
.grid-cols{position:absolute;inset:0;display:flex;justify-content:space-between;padding:0 var(--pad);pointer-events:none}
.grid-cols span{width:1px;background:var(--line-on-navy)}

/* ===== Nav ===== */
header.nav{position:fixed;top:0;left:0;right:0;z-index:100;padding:22px 0;
  transition:background .3s,padding .3s,box-shadow .3s}
header.nav.solid,header.nav.always-solid{padding:12px 0}
header.nav.solid::before,header.nav.always-solid::before{
  content:'';position:absolute;inset:0;z-index:-1;
  background:rgba(0,32,79,.94);
  -webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
  box-shadow:0 1px 0 rgba(255,255,255,.10),0 18px 40px -28px rgba(0,0,0,.8);
}
.nav-inner{display:flex;align-items:center;justify-content:space-between;position:relative}
.brand{display:flex;align-items:center;gap:11px}
.brand img{width:44px;height:44px;display:block}
.brand b{font-family:var(--font-head);color:#fff;font-weight:700;font-size:1.3rem;letter-spacing:-.02em}
.nav-right{display:flex;align-items:center;gap:22px}
.nav-menu{display:flex;gap:28px}
.nav-menu a{font-family:var(--font-head);font-weight:500;font-size:.95rem;opacity:.85;transition:opacity .2s}
.nav-menu a:hover{opacity:1}
.nav-contact{background:var(--azure);color:#fff;padding:14px 24px;border-radius:2px;font-family:var(--font-head);font-weight:500;transition:background .3s}
.nav-contact:hover{background:var(--azure-deep)}
/* The overlay's own Contact Us. .nav-contact is a sibling of .nav-menu, so with
   the menu open the primary call to action sat behind a full-screen panel and
   could only be reached by closing it first. This one lives inside the menu and
   is display:none until the overlay exists, so desktop still has exactly one. */
.menu-contact{display:none}
.burger{display:none;flex-direction:column;gap:5px;background:none;border:0;cursor:pointer;padding:8px}
.burger span{width:26px;height:2px;background:#fff;display:block}
@media(max-width:900px){
  /* visibility, not transform alone. If anything ever makes an ancestor the
     containing block again, translateY(-100%) measures against that box rather
     than the viewport and stops hiding this — the menu flashes across the page.
     Hidden is hidden, whatever the geometry does. */
  /* Grid, not a centred flex column.
   *
   * align-items:center centred each link individually, so four words of very
   * different lengths — Home at 78px, Instant Quotes at 206px — shared a centre
   * line and nothing else. Their left edges ranged over 64px, which is what
   * reads as untidy: the eye follows the starts of words, not their midpoints.
   *
   * A single max-content column sized to the longest item, centred as a block
   * with justify-content, and every link starting at its left edge with
   * justify-items:start. The group stays optically centred; the words line up. */
  /* Translucent, so the page stays readable behind it and the panel feels like
     a layer over the site rather than a different screen. The blur is what makes
     that legible — at 82% alpha alone, hero type and the container showed
     through as noise behind the links. -webkit- prefix included: iOS Safari
     still needs it, and without it the fallback is the flat colour, which is
     the old behaviour rather than a broken one. */
  .nav-menu{position:fixed;inset:0;
            background:rgba(10,21,38,.82); /* fallback: --ink at the same alpha */
            background:color-mix(in srgb, var(--ink) 82%, transparent);
            -webkit-backdrop-filter:blur(16px) saturate(130%);
            backdrop-filter:blur(16px) saturate(130%);
            display:grid;align-content:center;justify-content:center;justify-items:start;
            gap:34px;font-size:1.6rem;
            transform:translateY(-100%);visibility:hidden;
            transition:transform .4s cubic-bezier(.7,0,.2,1),visibility .4s}
  .nav-menu.open{transform:translateY(0);visibility:visible}
  .nav-menu a{font-size:1.8rem;opacity:1}
  /* Marked as the action by colour and a rule, not by a filled slab. A solid
     azure block in a column of plain white links read as a foreign object —
     heavier than everything around it and a different shape. The azure moves to
     the text, and a hairline above it does the separating. */
  .menu-contact{display:block;justify-self:start;margin-top:12px;padding-top:26px;
                border-top:1px solid var(--line-on-navy);
                color:var(--azure);background:none;border-radius:0}
  /* Centred on the screen's axis, which is the axis the menu block below it is
     centred on. Left to the flex row it sat 21px left of centre — between the
     brand and nav-right, not on any line the open menu uses — so the icon and
     the panel it opens never agreed on a centre. */
  .burger{display:flex;z-index:101;position:absolute;left:50%;transform:translateX(-50%)}
}

/* ===== Hero + merged container showcase (one continuous scroll-scrubbed sequence) ===== */
.hero{position:relative;min-height:100vh;display:flex;align-items:center;padding:140px 0 80px;overflow:hidden}
.hero .grid-cols{opacity:1}
.hero-content{position:relative;z-index:3;text-align:center;width:100%}
.hero h1{font-size:clamp(3rem,9vw,9.5rem);font-weight:500;margin:0 auto;max-width:14ch;color:#fff}
.hero .kicker{margin-bottom:34px}
.hero .sub{max-width:44ch;margin:30px auto 40px;font-size:1.15rem;color:var(--on-navy-dim)}
.hero-cta{display:flex;gap:16px;justify-content:center;flex-wrap:wrap}

/* The one container: starts as a faint hero backdrop, scroll-scrubs into a full, sharp showcase */
/* Hung from the navbar rather than floating mid-page.
 *
 * The chains run to the very top edge of the asset, so the element's top edge
 * is where they start. Sitting it 30px behind the nav — which is z-index 100 to
 * this element's 1 — hides that edge entirely, so there is no seam to misalign
 * and the chains simply continue up out of sight. Meeting the nav exactly would
 * be a hairline to get wrong at every viewport.
 *
 * transform-origin moves to the top centre, which is the point it hangs from.
 * That is the difference between the scrub's rotation reading as a swinging
 * load and reading as a picture spinning about its middle — and it keeps the
 * chain tops pinned under the nav while the scrub scales it from .8 to 1.
 * Previously the scale pulled the top down 64px, which is what left the chains
 * starting in mid-air. */
.cargo{position:absolute;top:calc(var(--nav-h) - 30px);left:50%;width:min(680px,88vw);z-index:1;
       transform-origin:50% 0;will-change:transform,opacity;pointer-events:none;
       transform-style:flat;backface-visibility:hidden}
/* No drop-shadow here, deliberately. It cost a 60px blur across the whole
   image on every scrub frame — at dpr 2 that is a 1360x1360 raster re-blurred
   each time the scale moves — and paid back nothing visible: the shadow is
   offset 50px downward, so it lands below the fold, and 35% black over #00204F
   navy is invisible regardless. Screenshots with it on and off are
   indistinguishable. If a shadow is ever wanted back, bake it into the asset
   rather than asking the compositor to redraw it sixty times a second. */
/* The load sways, because a thing on a crane does.
 *
 * On the image, not on .cargo: GSAP owns .cargo's transform for the desktop
 * scrub, and two writers on one transform is a fight. The child is free, so the
 * sway composes on top of the scrub instead of competing with it — and it is
 * the only motion phones get, where the scrub is deliberately off.
 *
 * Nothing here is bound to scroll position, which is the whole point. The
 * pinned scrub stuttered on phones because it had to chase a scroll offset
 * computed on the compositor thread; a keyframed rotation is handed to the
 * compositor once and never asks the main thread for anything, so it cannot
 * judder the way that did.
 *
 * Half a degree, pivoting from the top where the chains are. Over a 680px image
 * that moves the base about 6px — visible as weight, not as an effect. */
.cargo-img{width:100%;height:auto;display:block;transform-origin:50% 0;
           animation:cargo-sway 5.5s ease-in-out infinite alternate}
@keyframes cargo-sway{from{transform:rotate(-.5deg)}to{transform:rotate(.5deg)}}
@media(prefers-reduced-motion:reduce){.cargo-img{animation:none}}
.container-lead{position:absolute;bottom:9%;left:0;right:0;text-align:center;z-index:3;color:#fff;opacity:0}
.container-lead h2{font-size:clamp(1.6rem,3.5vw,3rem);max-width:20ch;margin:0 auto}

/* Phones do not get the pinned, scroll-scrubbed showcase.
 *
 * A scrubbed pin has to track a scroll position that phones compute on the
 * compositor thread, and during momentum scrolling it cannot keep step — which
 * is the stutter reported on the container and on the line beneath it. That is
 * structural, not a budget that can be tuned down: removing the drop-shadow
 * took real work out of every frame and the stutter survived it.
 *
 * So phones get the same content with nothing bound to scroll position. The
 * three pieces that the desktop sequence reveals in turn are simply laid out in
 * order: copy, then the container at full strength so the roundel actually
 * reads, then the line. Everything is visible in the CSS resting state, so a
 * failure in main.js leaves this readable rather than blank.
 */
/* Phones get the static layout by default. Adding ?scrub=1 to the URL puts the
   desktop pinned sequence back on a phone, so the stutter that got it removed
   can be re-tested on a real device without a deploy between the two runs — and
   without the default ever being the experiment. */
@media(max-width:720px){
  html:not(.force-scrub) .hero{min-height:auto;padding:118px 0 64px;flex-direction:column;justify-content:flex-start}
  html:not(.force-scrub) .hero-content{order:1}
  /* In flow, not centred behind the copy: at any opacity high enough for the
     logo to read, a container sitting under the headline wrecks the type. */
  html:not(.force-scrub) .cargo{position:static;transform:none;order:2;width:100%;max-width:430px;
         /* Negative, so the chains tuck behind the buttons instead of starting
            below them. hero-content is z-index 3 and .cargo is 1, so the overlap
            reads as the hooks passing behind — which is what sells it. */
         /* transform is scrubbed now (see main.js), so the compositor is told to
            expect it — it was auto back when nothing on phones animated. */
         margin:-10px auto 0;opacity:1;will-change:transform}

  /* The two buttons hang from the crane.
   *
   * The chains in container.webp run to the very top edge of the image, at
   * 25.7% and 75.4% across it — measured off the asset's alpha channel, not
   * eyeballed. A two-column grid puts the buttons' centres at 25% and 75%, so
   * each one sits within about 3px of the chain above it at any phone width.
   *
   * It breaks out of .wrap's padding with left:50% + translateX(-50%) rather
   * than a width calc: .cargo is a child of .hero and spans the viewport, the
   * buttons are inside .wrap and do not, so auto margins cannot line them up —
   * a box wider than its parent does not centre, it just overflows to the
   * right. Escaping to the viewport and capping at the same 430px gives the two
   * boxes identical geometry at every width. .hero is overflow:hidden, so 100vw
   * cannot introduce a horizontal scrollbar. */
  html:not(.force-scrub) .hero-cta{display:grid;grid-template-columns:1fr 1fr;gap:0;justify-items:center;
            width:100vw;max-width:430px;position:relative;left:50%;transform:translateX(-50%)}
  html:not(.force-scrub) .hero-cta > *{max-width:100%}
  /* 22px measured as only 36px of visible gap: the asset carries about 6% of
     transparent tail below the container, so the image box overstates where the
     picture actually ends and the line sat almost against the crate. */
  html:not(.force-scrub) .container-lead{position:static;order:3;opacity:1;margin-top:58px;padding:0 var(--pad)}
  .container-lead h2{font-size:1.45rem;max-width:24ch}
}

/* ===== Editorial section ===== */
.editorial{background:var(--mist);color:var(--ink);padding:120px 0}
.ed-grid{display:grid;grid-template-columns:180px 1fr 1fr;gap:40px;align-items:start}
.ed-grid .ed-label{color:var(--azure)}
.ed-grid h2{font-size:clamp(2.2rem,4vw,3.6rem)}
.ed-grid .ed-body{font-size:1.2rem;color:#333}
.ed-grid .ed-body p+p{margin-top:20px}
.ed-rule{grid-column:1/-1;height:1px;background:rgba(0,0,0,.12);margin:56px 0 0}
@media(max-width:860px){.ed-grid{grid-template-columns:1fr;gap:24px}}

/* value stats */
.ed-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:30px;margin-top:60px}
.ed-stats .st .n{font-family:var(--font-head);font-size:clamp(2.6rem,5vw,4rem);font-weight:500;color:var(--azure);letter-spacing:-.03em}
.ed-stats .st .l{font-size:.9rem;color:#555;margin-top:6px;text-transform:uppercase;letter-spacing:.08em}
@media(max-width:720px){.ed-stats{grid-template-columns:1fr}}

/* ===== Services strip (terra) ===== */
.services{background:var(--navy);position:relative;padding:120px 0}
.services .grid-cols{opacity:1}
.services-inner{position:relative;z-index:3}
.services h2{font-size:clamp(2.4rem,6vw,5rem);max-width:16ch;margin:24px 0 60px;color:#fff}
.svc-list{border-top:1px solid var(--line-on-navy)}
.svc-row{display:grid;grid-template-columns:80px 1fr auto;gap:30px;align-items:center;padding:34px 0;border-bottom:1px solid var(--line-on-navy);transition:padding-left .35s ease}
.svc-row:hover{padding-left:20px}
.svc-row .num{font-family:var(--font-head);font-size:1rem;color:var(--on-navy-dim)}
.svc-row .name{font-family:var(--font-head);font-size:clamp(1.6rem,3.5vw,2.6rem);font-weight:500}
.svc-row .desc{max-width:34ch;color:var(--on-navy-dim);font-size:1rem}
@media(max-width:820px){.svc-row{grid-template-columns:50px 1fr}.svc-row .desc{display:none}}

/* ===== Process sticky-stack cards ===== */
.process{position:relative;background:var(--ink)}
.process-media{position:absolute;inset:0;background:linear-gradient(180deg,rgba(13,13,13,.6),rgba(13,13,13,.85)),url('https://images.unsplash.com/photo-1494412574643-ff11b0a5c1c3?auto=format&fit=crop&w=1600&q=80') center/cover fixed;opacity:.55}
.process-inner{position:relative;z-index:2;padding:120px 0}
.process-head{text-align:center;margin-bottom:60px}
.process-head h2{font-size:clamp(2.4rem,5vw,4rem);color:#fff;max-width:18ch;margin:18px auto 0}
.stack{position:relative;max-width:520px;margin:0 auto}
.stack-card{
  position:sticky;top:120px;
  background:var(--navy);border-radius:10px;padding:44px;margin-bottom:26px;
  box-shadow:0 30px 60px -20px rgba(0,0,0,.5);
}
.stack-card:nth-child(2){background:var(--azure)}
.stack-card:nth-child(3){background:var(--navy-deep)}
.stack-card:nth-child(4){background:#d9613f}
.stack-card .sc-num{font-family:var(--font-head);font-size:1.1rem;color:rgba(255,255,255,.7)}
.stack-card h3{font-size:clamp(1.8rem,4vw,2.6rem);margin:8px 0 20px;color:#fff}
.stack-card p{color:rgba(255,255,255,.85);font-size:1.05rem;max-width:36ch}
.stack-card .sc-icon{width:54px;height:54px;margin-top:28px;color:rgba(255,255,255,.85)}

/* ===== CTA + Footer ===== */
.cta{background:var(--mist);color:var(--ink);padding:120px 0;text-align:center}
.cta h2{font-size:clamp(2.4rem,5vw,4.4rem);max-width:16ch;margin:20px auto 30px}
.cta .sub{max-width:44ch;margin:0 auto 36px;color:#444;font-size:1.15rem}

footer{background:var(--ink);color:#fff;padding:80px 0 40px}
.foot-top{display:grid;grid-template-columns:2fr 1fr 1fr;gap:40px;padding-bottom:50px;border-bottom:1px solid rgba(255,255,255,.12)}
.foot-top h4{font-family:var(--font-head);color:var(--azure);font-size:.85rem;text-transform:uppercase;letter-spacing:.1em;margin-bottom:18px}
.foot-top li{margin-bottom:12px;color:rgba(255,255,255,.7)}
.foot-top .f-brand{font-family:var(--font-head);font-size:2rem;font-weight:700}
.foot-top .f-brand+p{color:rgba(255,255,255,.6);margin-top:16px;max-width:36ch}
.foot-bottom{padding-top:30px;display:flex;justify-content:space-between;color:rgba(255,255,255,.5);font-size:.85rem;flex-wrap:wrap;gap:12px}
@media(max-width:760px){.foot-top{grid-template-columns:1fr}}

/* ===== Sub-page hero (shorter) ===== */
.hero.short{min-height:62vh;padding:180px 0 90px}
.hero.short h1{font-size:clamp(2.6rem,7vw,6.5rem)}
.hero.short .hero-content{text-align:left}
.hero.short .sub{margin:26px 0 0}

/* generic light + dark section helpers */
.sec{padding:110px 0}
.sec.cream{background:var(--mist);color:var(--ink)}
.sec.paper{background:var(--paper);color:var(--ink)}
.sec.ink{background:var(--ink);color:#fff}
.sec-head{max-width:60ch;margin-bottom:56px}
.sec-head h2{font-size:clamp(2.2rem,4.5vw,3.8rem);margin-top:16px}
.sec-head p{font-size:1.15rem;margin-top:20px;opacity:.8}

/* feature cards grid (new style) */
.fcards{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:2px;background:rgba(0,0,0,.08)}
.sec.ink .fcards{background:rgba(255,255,255,.1)}
.fcard{background:var(--mist);padding:44px 38px;transition:background .3s}
.sec.paper .fcard{background:var(--paper)}
.sec.ink .fcard{background:var(--ink)}
/* The hover has to out-specify the per-section background rules.
 *
 * .fcard:hover is one class and a pseudo-class; .sec.paper .fcard is three
 * classes, so the section rule won and only the COLOUR flipped on hover —
 * white text arriving on a background that stayed white. The card looked like
 * it vanished under the cursor, and while scrolling past it did so repeatedly.
 * about-us.html compounded it with an inline background, which no stylesheet
 * rule can beat at all; those are gone, since the section rule already sets
 * the same value. */
.fcard:hover,
.sec.paper .fcard:hover,
.sec.cream .fcard:hover,
.sec.ink .fcard:hover{background:var(--navy);color:#fff}
.fcard .fnum{font-family:var(--font-head);font-size:.9rem;opacity:.55;margin-bottom:26px}
.fcard h3{font-size:1.7rem;margin-bottom:14px}
.fcard p{opacity:.75;font-size:1rem}
.fcard:hover p,.fcard:hover .fnum{opacity:.95}

/* two-col editorial reuse on subpages */
.split2{display:grid;grid-template-columns:1fr 1fr;gap:64px;align-items:center}
@media(max-width:880px){.split2{grid-template-columns:1fr;gap:36px}}

/* AI chat mock (new style) */
.chat{background:var(--ink);border-radius:12px;padding:26px;display:flex;flex-direction:column;gap:14px;box-shadow:0 30px 60px -25px rgba(0,0,0,.4)}
.chat .b{max-width:82%;padding:13px 17px;border-radius:12px;font-size:.95rem;line-height:1.45}
.chat .b.u{align-self:flex-end;background:var(--azure);color:#fff;border-bottom-right-radius:3px}
.chat .b.a{align-self:flex-start;background:#242424;color:#eee;border-bottom-left-radius:3px}

/* comparison table */
.ctable{width:100%;border-collapse:collapse;font-size:1rem}
.ctable th,.ctable td{text-align:left;padding:20px 22px;border-bottom:1px solid rgba(255,255,255,.12)}
.ctable th{font-family:var(--font-head);font-weight:500;color:var(--azure);text-transform:uppercase;letter-spacing:.06em;font-size:.8rem}
.ctable td{color:rgba(255,255,255,.7)}
.ctable td.win{color:#fff;font-weight:500}
@media(max-width:640px){.ctable th,.ctable td{padding:14px 12px;font-size:.85rem}}

/* impact stat cards */
.impact{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:2px;background:rgba(255,255,255,.1)}
.impact .ic{background:var(--ink);padding:40px 30px;text-align:center}
.impact .ic .n{font-family:var(--font-head);font-size:clamp(2.4rem,5vw,3.6rem);color:var(--azure);letter-spacing:-.03em}
.impact .ic p{color:rgba(255,255,255,.65);font-size:.9rem;margin-top:10px}

/* contact form */
.field{margin-bottom:22px}
.field label{display:block;font-family:var(--font-head);font-size:.85rem;margin-bottom:8px;color:var(--ink)}
.field input,.field select,.field textarea{width:100%;padding:15px 16px;border:1px solid rgba(0,0,0,.18);border-radius:3px;background:#fff;font-family:var(--font-body);font-size:1rem;color:var(--ink)}
.field textarea{min-height:120px;resize:vertical}
.field input:focus,.field select:focus,.field textarea:focus{outline:none;border-color:var(--azure)}
.contact-detail{display:flex;gap:16px;align-items:flex-start;padding:22px 0;border-bottom:1px solid rgba(0,0,0,.1)}
.contact-detail:last-child{border-bottom:none}
.contact-detail .cd-ic{width:22px;height:22px;color:var(--azure);flex-shrink:0;margin-top:3px}
.contact-detail b{font-family:var(--font-head);font-weight:500}
.contact-detail span{display:block;opacity:.7;margin-top:2px}

/* reveal helper */
.reveal{opacity:0;transform:translateY(40px)}
.line-mask{overflow:hidden;display:block}


/* ===== Legal pages ===== */
/* Marketing type is set tight and large. A privacy policy is read, not
   scanned, so it gets a measure and a rhythm of its own. */
.legal{max-width:68ch;font-size:1.02rem;line-height:1.8;color:#26374d}
.legal h2{font-family:var(--font-head);font-size:1.35rem;line-height:1.25;color:var(--navy);margin:38px 0 12px}
.legal p{margin-bottom:16px}
.legal ul{list-style:disc;padding-left:22px;margin-bottom:16px}
.legal li{margin-bottom:9px}
.legal a{color:var(--azure);text-decoration:underline;text-underline-offset:2px}
.legal b{color:var(--navy)}


/* ===== App store buttons ===== */
.stores{display:flex;gap:14px;justify-content:center;flex-wrap:wrap;margin-top:8px}
.store{
  display:inline-flex;flex-direction:column;align-items:flex-start;justify-content:center;
  min-width:190px;padding:12px 24px;border-radius:6px;
  background:var(--ink);color:#fff;
  transition:background .3s,transform .3s,opacity .3s;
}
.store:hover{background:var(--azure);transform:translateY(-2px)}
.store .store-sub{font-size:.72rem;letter-spacing:.06em;text-transform:uppercase;opacity:.72;line-height:1.3}
.store .store-name{font-family:var(--font-head);font-weight:500;font-size:1.15rem;line-height:1.25}
/* Not published yet: visibly inert rather than a link that 404s. */
.store.is-pending{opacity:.5;cursor:default;background:var(--ink)}
.store.is-pending:hover{background:var(--ink);transform:none}
.store .store-soon{font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;opacity:.8;margin-top:2px}
.store-note.is-secondary{opacity:.55;font-size:.85rem}
@media(max-width:520px){.stores{flex-direction:column;align-items:stretch}.store{min-width:0}}


/* ===== Contact cards ===== */
/* Deliberately plain anchors rather than a form. The form that used to be here
   swallowed enquiries; these each do exactly one thing and cannot fail
   silently. No .reveal either — contact details are the last content that
   should be waiting on an animation to become visible. */
.contact-grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));max-width:900px}
.contact-card{
  display:flex;align-items:center;gap:18px;
  background:var(--paper);border-radius:10px;padding:26px 28px;
  transition:transform .25s,box-shadow .25s;
}
.contact-card:hover{transform:translateY(-3px);box-shadow:0 22px 40px -28px rgba(0,32,79,.55)}
.contact-card svg{width:30px;height:30px;color:var(--azure);flex-shrink:0}
.contact-card div{display:flex;flex-direction:column;gap:2px;min-width:0}
.contact-card b{font-family:var(--font-head);font-weight:500;font-size:1.15rem;color:var(--navy)}
.contact-card span{font-size:1rem;color:#2b3d55;word-break:break-word}
.contact-card em{font-style:normal;font-size:.82rem;opacity:.6}


/* ===== Mobile ===== */
/* The ↗ glyphs are decoration. On a phone a link is obviously a link, and the
   extra character crowds an already tight line. */
@media(max-width:720px){
  .arw{display:none}
  .btn{gap:0}
}


/* ===== Quoting paused ===== */
/* Shown by default and removed by JS when the API says quoting is live — see
   the comment in quotes.html. Sized as a notice rather than a hero: it is the
   answer to a question the page already asked, not the page's subject. */
.quotes-paused{margin:30px 0 0;padding:22px 24px;max-width:52ch;
               border:1px solid var(--line-on-navy);border-radius:4px;
               background:rgba(255,255,255,.04)}
.quotes-paused p{margin:0 0 16px;color:var(--on-navy-dim);line-height:1.65}
.quotes-paused strong{color:var(--on-navy);font-weight:500}
.qp-actions{display:flex;gap:12px;flex-wrap:wrap}
.btn-ghost{background:transparent;border:1px solid var(--line-on-navy);color:var(--on-navy)}
.btn-ghost:hover{background:rgba(255,255,255,.06)}


/* ===== Location ===== */
/* Map beside the address on a desktop, stacked on a phone. The map keeps a
   fixed aspect rather than a fixed height so it never letterboxes, and the
   address column has a floor so a short address does not leave the row
   lopsided against a tall map. */
.loc{display:grid;gap:26px;grid-template-columns:minmax(0,1.35fr) minmax(260px,1fr);
     align-items:stretch;max-width:1000px}
.loc-map{position:relative;aspect-ratio:16/10;border-radius:12px;overflow:hidden;
         /* --paper-deep was never defined; an unresolvable var made this
            transparent, so the map area was blank rather than grey while the
            iframe loaded. */
         background:var(--mist);box-shadow:0 22px 44px -30px rgba(0,32,79,.5)}
.loc-map iframe{position:absolute;inset:0;width:100%;height:100%;border:0;display:block}
.loc-info{display:flex;flex-direction:column;justify-content:center;gap:14px;
          background:var(--paper);border-radius:12px;padding:28px 30px}
.loc-info b{font-family:var(--font-head);font-weight:500;font-size:1.3rem;color:var(--navy)}
.loc-info address{font-style:normal;font-size:1rem;line-height:1.75;color:#2b3d55}
.loc-actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:4px}
@media(max-width:820px){
  .loc{grid-template-columns:1fr}
  .loc-map{aspect-ratio:4/3}
}
