/*
Theme Name: ALLReady Construction
Theme URI: https://allready-construction.com
Author: Arbalest Solutions
Description: Bespoke theme for All Ready Construction Inc. Navy and gold taken from the
  client's own logo and live site; Newsreader and Libre Franklin for type. Deliberately
  not a page builder: the design system is this one stylesheet, and the project pages are
  a custom post type so the repeating content has a real editing surface.
Version: 1.0.0
Requires at least: 6.5
Requires PHP: 8.1
License: Proprietary
Text Domain: allready
*/

/* ============================================================
   ALL READY CONSTRUCTION - proposed home page, draft 02
   Palette and type taken from the live site and the logo file:
     navy  #0A1936   logo ground / site rgb(10,25,54)
     gold  #C49D3D   site brand gold
     grey  #5F6360 / #E2E2E2   site greys
     Newsreader       display + body. Variable optical size, so the
                      hero and the body copy each get a correct cut.
     Libre Franklin   UI, labels, figures. Franklin gothic lineage:
                      American, journalistic, authoritative. Kept in
                      the 7 Sep type pass: Franklin is the lettering
                      of American infrastructure and newspapers,
                      which is the right register for a contractor
                      selling to institutional owners. Inter reads
                      SaaS, Lexend reads education, Plex reads tech.
                      The pairing was never the problem; the absence
                      of a system was. See TYPE SYSTEM below.
   Deliberately single-theme. This is a website comp, so it must
   read to the client exactly as the live site would, on any host.
   ============================================================ */
:root{
  --navy:#0A1936;
  --navy-deep:#06101F;
  --navy-raised:#13203C;
  --navy-rule:#25324F;

  --gold:#C49D3D;
  --gold-lift:#DDB865;
  /* same brand hue, darkened until it clears 4.5:1 on both paper and white */
  --gold-dark:#7A5F21;      /* 6.02:1 on white. The workhorse gold for text. */
  /* Same hue, lighter. gold-dark goes olive at 52px, which is what made the
     hero phrase read brown. 4.00:1 clears AA for LARGE text only, so this is
     restricted to 24px and up and must never be used on body copy. */
  --gold-display:#9A7B2E;
  --gold-wash:rgba(196,157,61,.10);
  --gold-edge:rgba(196,157,61,.42);

  --paper:#FFFFFF;
  --paper-alt:#F4F7FA;
  --sky:#EDF3F9;
  --paper-lift:#FFFFFF;
  --rule:#DFE4EA;
  --rule-soft:#EBEFF3;

  --ink:#0A1936;
  /* Was #5F6360, a neutral warm grey sitting on a cool navy palette, and it
     carried every lede, label and card paragraph on the site: that is what
     read as washed out. Navy-tinted now, and 7.38:1 on white against 6.10. */
  --ink-soft:#4C566A;
  --ink-body:#2A2F3C;
  --on-navy:#E7EAF0;
  --on-navy-soft:#A9B3C7;   /* 9.04:1 on navy-deep, was 7.26 */

  /* Header geometry. scroll-margin-top used to be a hardcoded 98px against an
     82px header; driving both from one token means an anchor can never land
     under the header again after a height change. --nav-pad and --sub-pad are
     the two paddings that have to agree for a dropdown to line up with the
     label that opened it. */
  --header-h:72px;
  --nav-pad:.6rem;
  --sub-pad:1.05rem;

  --measure:66ch;
  --shell:min(1260px,calc(100% - 2.75rem));
  --gap:clamp(1.5rem,4vw,3.25rem);

  /* ============================================================
     TYPE SYSTEM  ·  golden ratio, cube-rooted
     ------------------------------------------------------------
     One ladder, ratio phi^(1/3) = 1.17398. Every rung is a step on
     it, so any two rungs THREE apart are exactly the golden ratio
     and the whole set stays on one curve:

       rung  token       mobile   desktop
        0    micro       12.00 -> 12.34px
        1    small       14.00 -> 14.48px
        2    body        16.00 -> 17.00px
        3    lead        18.00 -> 19.96px
        4    h4          20.30 -> 23.43px
        5    h3          23.00 -> 27.51px
        7    h2          29.00 -> 37.92px
        9    h1          33.00 -> 52.28px

     micro -> lead, small -> h4 and body -> h3 are each three rungs,
     so each is phi. h2 and h1 skip a rung so display type pulls
     clear of the text sizes; micro -> h1 is nine rungs, which is
     phi cubed (12.34 x 4.236 = 52.28). Rungs 6 and 8 are left out
     on purpose, not missing.

     Each clamp runs from its floor at a 400px viewport to its
     ceiling at 1280px, so the page scales on one continuous line
     and no font-size needs a media query any more.

     This replaced 56 hand-picked font-size values. If you want a
     size that is not on this ladder, the ladder is wrong, not the
     exception.
     ============================================================ */
  --fs-micro:clamp(.75rem,.740rem + .039vw,.771rem);
  --fs-small:clamp(.875rem,.861rem + .055vw,.905rem);
  --fs-body:clamp(1rem,.972rem + .114vw,1.0625rem);
  --fs-lead:clamp(1.125rem,1.069rem + .223vw,1.2475rem);
  --fs-h4:clamp(1.269rem,1.180rem + .356vw,1.4644rem);
  --fs-h3:clamp(1.4375rem,1.309rem + .513vw,1.7194rem);
  --fs-h2:clamp(1.8125rem,1.559rem + 1.014vw,2.370rem);
  --fs-h1:clamp(2.0625rem,1.515rem + 2.191vw,3.2675rem);

  /* Leading. Body is phi itself, which lands mid-band of the
     1.5-1.75 that long-form reading wants. Headings tighten as
     they grow, because large type needs less air between lines. */
  --lh-display:1.04;
  --lh-head:1.14;
  --lh-lead:1.45;
  --lh-body:1.618;
  --lh-ui:1.5;

  /* Tracking. Four values, not the twenty this file used to carry.
     Uppercase labels get one number; big display type gets a
     negative to close the gaps that open up at size. */
  --track-display:-.02em;
  --track-head:-.008em;
  --track-nav:.1em;
  --track-label:.14em;

  /* Families, declared once. They were repeated inline 46 times. */
  --font-display:Newsreader,"Iowan Old Style","Hoefler Text",Georgia,serif;
  --font-ui:"Libre Franklin","Helvetica Neue",Arial,sans-serif;

  /* Back-compat only. The templates no longer carry an inline
     font-size, but page bodies already saved in the database do,
     and a page the seeders do not rewrite would otherwise lose its
     heading size. Keep these until the DB is known clean. Never
     use them in new CSS. */
  --t--1:var(--fs-micro);
  --t-0:var(--fs-body);
  --t-1:var(--fs-lead);
  --t-2:var(--fs-h2);
  --t-3:var(--fs-h1);
  --t-4:var(--fs-h1);
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
/* sticky header is ~82px, so anchored sections must clear it */
/* Every anchor target has to clear the sticky header, not just the ones that
   happen to be a <section>. The twelve service anchors the nav submenus point
   at are <li id> inside .dsvc, so the old section-only rule dropped each of
   them under the header. :target keeps focus rings honest for keyboard users
   who arrive by anchor. */
[id]{scroll-margin-top:calc(var(--header-h) + 1rem)}
body{
  margin:0;
  background:var(--paper);
  color:var(--ink);
  font-family:var(--font-display);
  font-size:var(--fs-body);
  line-height:var(--lh-body);
  letter-spacing:0;
  font-synthesis-weight:none;
  text-rendering:optimizeLegibility;
  -webkit-font-smoothing:antialiased;
}
h1,h2,h3,h4{
  font-family:var(--font-display);
  font-weight:500;
  font-optical-sizing:auto;
  line-height:var(--lh-head);
  letter-spacing:var(--track-head);
  text-wrap:balance;
  margin:0;
}
h1{font-size:var(--fs-h1)}
h2{font-size:var(--fs-h2)}
h3{font-size:var(--fs-h3)}
h4{font-size:var(--fs-h4)}
/* Display type is set tighter on both axes: at 33px and up the default
   leading opens gaps a headline should not have. */
h1,.hero h1,.phero h1{line-height:var(--lh-display);letter-spacing:var(--track-display)}
p{margin:0}
a{color:inherit}
img{max-width:100%;display:block}

/* Focus ring works on navy, on paper AND on the gold buttons:
   a dark inner halo plus a light outer ring, so one of the two
   always contrasts with whatever sits behind it. */
:focus-visible{
  outline:2px solid var(--navy-deep);
  outline-offset:2px;
  box-shadow:0 0 0 4px var(--gold-lift);
  border-radius:1px;
}
.band--navy :focus-visible,.band--deep :focus-visible,.hero :focus-visible,.top :focus-visible,.foot :focus-visible{
  outline-color:var(--paper-lift);
  box-shadow:0 0 0 4px var(--gold);
}

/* Skip link */
.skip{
  position:absolute;left:.75rem;top:.75rem;z-index:100;
  background:var(--gold);color:#181205;padding:.8rem 1.15rem;
  font-family:var(--font-ui);font-size:var(--fs-micro);font-weight:600;
  letter-spacing:var(--track-label);text-transform:uppercase;text-decoration:none;
  transform:translateY(-400%);
  transition:transform .2s cubic-bezier(.22,1,.36,1);
}
.skip:focus{transform:none}

/* Scroll reveal - subtle, 340ms, and off entirely under reduced motion */
/* .js guard: without it, a JS failure or a blocked script leaves every
   revealed section permanently invisible rather than merely unanimated. */
.js .reveal{opacity:0;transform:translateY(14px);transition:opacity .34s ease-out,transform .34s ease-out}
.js .reveal.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){.js .reveal{opacity:1;transform:none;transition:none}}

.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ============================================================
   ATMOSPHERE
   Flat navy at this scale reads digitally sterile. A fractal
   noise plate at 3.5% breaks it up the way film grain does.
   Generated inline as SVG - no external host, CSP-safe.
   ============================================================ */
.grain{
  position:fixed;inset:-50%;z-index:1;pointer-events:none;
  opacity:.018;mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)'/%3E%3C/svg%3E");
}
@media (prefers-reduced-motion:reduce){.grain{opacity:.025}}

/* ============================================================
   ENTRY SEQUENCE
   No blocking preloader: an asset manager should never wait on
   a splash. Instead the hero holds its first frame until the
   fonts resolve, then plays a single 700ms cascade. Everything
   below is authored visible, so with JS off nothing is hidden.
   ============================================================ */
.hero-h1 .wd{display:inline-block;overflow:hidden;padding-bottom:.14em;margin-bottom:-.14em;vertical-align:top}
.hero-h1 .wd > i{display:inline-block;font-style:inherit}
.js .hero-h1 .wd > i{transform:translateY(108%);transition:transform .78s cubic-bezier(.22,1,.36,1)}
.js.ready .hero-h1 .wd > i{transform:none}

.js .hero-rise{opacity:0;transform:translateY(18px);transition:opacity .7s ease-out,transform .7s cubic-bezier(.22,1,.36,1)}
.js.ready .hero-rise{opacity:1;transform:none}

/* same trap as the image wipe: inset(0) clips the plate away with the shadow */

@media (prefers-reduced-motion:reduce){
  .js .hero-h1 .wd > i,.js .hero-rise{transform:none;opacity:1;clip-path:none;transition:none}
}

.ui{
  font-family:var(--font-ui);
  font-size:var(--fs-micro);
  letter-spacing:var(--track-label);
  text-transform:uppercase;
  font-weight:600;
}
.shell{width:var(--shell);margin-inline:auto}
.stack{display:flex;flex-direction:column;gap:clamp(1.1rem,2.4vw,1.85rem)}
.lede{max-width:var(--measure);font-size:var(--fs-lead);line-height:var(--lh-lead)}
.body{max-width:var(--measure)}
.num{font-variant-numeric:tabular-nums}

/* ---- bands -------------------------------------------------
   Each band publishes a surface palette. Components consume the
   --s-* tokens instead of naming navy, so one set of rules works
   on a white band and a navy one.
   ------------------------------------------------------------ */
:root{
  --s-bg:var(--paper-lift);
  --s-bg-alt:var(--paper-alt);
  --s-line:var(--rule);
  --s-line-soft:var(--rule-soft);
  --s-ink:var(--ink);
  --s-soft:var(--ink-soft);
  --s-accent:var(--gold-dark);
}
.band{padding-block:clamp(3.5rem,6.4vw,5.75rem)}

.band--navy,.band--deep,.foot{
  --s-bg:var(--navy-raised);
  --s-bg-alt:var(--navy);
  --s-line:var(--navy-rule);
  --s-line-soft:var(--navy-rule);
  --s-ink:var(--on-navy);
  --s-soft:var(--on-navy-soft);
  --s-accent:var(--gold);
}
.band--navy{background:var(--navy);color:var(--on-navy)}
.band--deep{background:var(--navy-deep);color:var(--on-navy)}
.band--paper{background:var(--paper);color:var(--ink)}
.band--alt{background:var(--paper-alt);color:var(--ink)}
.band--paper .lede,.band--alt .lede{color:var(--ink-soft)}
.band--paper .body,.band--alt .body{color:var(--ink-body)}
.band--navy .lede,.band--deep .lede{color:var(--on-navy-soft)}

.eyebrow{color:var(--gold);display:block}
.band--paper .eyebrow,.band--alt .eyebrow,.hero .eyebrow{color:var(--gold-dark)}

/* ---- the skyline rule -------------------------------------
   The logo mark is a stack of vertical gold bars of differing
   height. That is the one graphic device this page repeats.   */
.skyline{display:flex;align-items:flex-end;gap:3px;height:22px}
.skyline i{width:2px;background:var(--gold);display:block}
.band--paper .skyline i,.band--alt .skyline i,.hero .skyline i{background:var(--gold-dark)}
.skyline i:nth-child(1){height:32%}
.skyline i:nth-child(2){height:52%}
.skyline i:nth-child(3){height:40%}
.skyline i:nth-child(4){height:100%}
.skyline i:nth-child(5){height:84%}
.skyline i:nth-child(6){height:68%}
.skyline i:nth-child(7){height:92%}
.skyline i:nth-child(8){height:56%}
.skyline i:nth-child(9){height:44%}
.skyline i:nth-child(10){height:76%}
.skyline i:nth-child(11){height:30%}
.skyline i:nth-child(12){height:60%}
.skyline i:nth-child(13){height:38%}
.skyline i:nth-child(14){height:26%}
.skyline--wide{height:34px;gap:5px}
.skyline--wide i{width:3px}

/* ---- draft bar -------------------------------------------- */
.draft{background:var(--gold);color:#1D1607}
.draft .shell{display:flex;flex-wrap:wrap;gap:.35rem 1.4rem;align-items:baseline;padding-block:.55rem}
.draft .ui{letter-spacing:var(--track-label)}
.draft span{font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:var(--track-nav);opacity:.78}

/* ---- header ----------------------------------------------- */
/* Contextual header: retreats on the way down, returns on the way up,
   and frosts once it is over content rather than over the hero. */
.top{
  background:var(--navy-deep);border-bottom:1px solid var(--navy-rule);
  position:sticky;top:0;z-index:50;
  transition:transform .38s cubic-bezier(.22,1,.36,1),background .3s ease,border-color .3s ease;
}
.top.lifted{
  background:rgba(6,16,31,.82);
  -webkit-backdrop-filter:blur(14px) saturate(140%);
  backdrop-filter:blur(14px) saturate(140%);
  border-bottom-color:var(--gold-edge);
}
.top.gone{transform:translateY(-100%)}
@media (prefers-reduced-motion:reduce){.top.gone{transform:none}}
.top .shell{
  display:flex;align-items:center;gap:clamp(.9rem,1.4vw,1.35rem);
  min-height:var(--header-h);position:relative;
  transition:min-height .28s cubic-bezier(.22,1,.36,1);
}
/* Once the header is over content rather than the hero it loses a few more
   pixels. Small enough not to read as a jump, enough to feel lighter. */
.top.lifted .shell{min-height:calc(var(--header-h) - 6px)}
@media (prefers-reduced-motion:reduce){.top .shell{transition:none}}
.lockup{display:flex;align-items:center;gap:.6rem;text-decoration:none;margin-right:auto;min-height:44px}
/* Phil, 10 Sep: "the logo seems a little smaller, maybe this should be
   bigger". Taken back up, and the wordmark with it, while still leaving the
   header shorter than the 82px it was before the September pass. */
.lockup img{height:40px;width:auto;transition:height .28s cubic-bezier(.22,1,.36,1)}
.top.lifted .lockup img{height:34px}
.lockup .wm{display:flex;flex-direction:column;line-height:1;gap:.26rem}
/* .3em on a 12px sub-line pushed the wordmark wider than the mark is tall and
   was most of what made the header feel heavy. */
.lockup .a{font-family:var(--font-ui);font-weight:600;font-size:var(--fs-lead);letter-spacing:.12em;color:var(--gold)}
.lockup .b{font-family:var(--font-ui);font-weight:400;font-size:.7rem;letter-spacing:.18em;color:var(--on-navy-soft)}
.nav{display:flex;gap:.35rem}
/* The header is a label row, so it belongs on the micro rung with every other
   label on the site. Measured at 1024px on the live build: the shell overflowed
   by 37px and Residential, Join Our Team and Contact each wrapped to two lines,
   and that was at 12.16px. On --fs-small the six-item nav needs a 1205px
   viewport; on --fs-micro it needs 1089px. Nothing here wraps, ever: a nav item
   breaking across two lines is what pushed the button out of the shell. */
.top .nav a,.top .navtop,.top .shell > .btn{font-size:var(--fs-micro);white-space:nowrap}
.top .lockup,.top .lockup .wm span{flex-shrink:0;white-space:nowrap}
.nav a{
  font-family:var(--font-ui);font-size:var(--fs-small);font-weight:500;
  letter-spacing:var(--track-nav);text-transform:uppercase;text-decoration:none;color:var(--on-navy-soft);
  display:flex;align-items:center;min-height:44px;padding:0 var(--nav-pad);
  position:relative;transition:color .18s ease;
}
/* The indicator is a hairline under the LABEL, not a 2px slab across the whole
   padding box. It grows from the centre, which reads as deliberate rather than
   as a border switching on. */
.nav > a::after,.navtop::after{
  content:"";position:absolute;left:var(--nav-pad);right:var(--nav-pad);bottom:calc(50% - .95em);
  height:1.5px;background:var(--gold);transform:scaleX(0);transform-origin:50% 50%;
  transition:transform .24s cubic-bezier(.22,1,.36,1);
}
.nav a:hover,.nav a:focus-visible{color:var(--on-navy)}
/* The gold CTA lives inside .nav, so `.nav a` (0,1,1) was painting its label
   --on-navy-soft on --gold: 1.21:1, effectively invisible. The first attempt at
   this used `.nav a:not(.btn)`, but :not() contributes its argument's weight, so
   the base rule jumped to (0,2,1) and silently outranked every mobile override
   below it (.nav > a, .nav .navtop, .subnav .subitem) — the phone menu lost its
   52px rows, its submenu indent and its 12px submenu type. Fix the button with a
   rule that beats (0,1,1) on its own, and leave the base selector's weight alone. */
.nav .btn{color:#181205}
.nav .btn:hover{color:#181205}
.nav > a:hover::after,.nav > a:focus-visible::after{transform:scaleX(1)}
.nav a[aria-current="page"]{color:var(--on-navy)}
.nav > a[aria-current="page"]::after{transform:scaleX(1)}
/* belt and braces: nothing inside a dropdown ever draws the top-row rule */
.subnav a::after{content:none}
@media (prefers-reduced-motion:reduce){
  .nav a::after,.navtop::after{transition:none}
}

/* Menu toggle - hidden on desktop, the only nav below 1160px */
.menu-btn{
  display:none;align-items:center;gap:.55rem;cursor:pointer;
  min-height:44px;padding:0 .85rem;background:transparent;
  border:1px solid var(--navy-rule);color:var(--on-navy);
  font-family:var(--font-ui);font-size:var(--fs-micro);font-weight:600;
  letter-spacing:var(--track-nav);text-transform:uppercase;transition:border-color .18s ease;
}
.menu-btn:hover{border-color:var(--gold)}
.menu-btn .bars{display:flex;flex-direction:column;gap:3px;width:15px}
.menu-btn .bars i{height:2px;background:var(--gold);transition:transform .18s ease,opacity .18s ease}
.menu-btn[aria-expanded="true"] .bars i:nth-child(1){transform:translateY(5px) rotate(45deg)}
.menu-btn[aria-expanded="true"] .bars i:nth-child(2){opacity:0}
.menu-btn[aria-expanded="true"] .bars i:nth-child(3){transform:translateY(-5px) rotate(-45deg)}

@media (max-width:1160px){
  :root{--header-h:58px}
  /* .nav is absolutely positioned and .top .shell was position:relative, so the
     panel was sized to the shell: 346px inside a 390px phone, leaving a 22px
     white gutter down each side under a full-bleed header. Dropping the shell
     out of the positioning chain hands .nav to .top, which is sticky and
     therefore already a containing block, so left:0/right:0 means the viewport.
     Using 100vw instead would reintroduce the scrollbar-overflow bug on the
     desktop widths this block still covers. */
  .top .shell{position:static}
  .menu-btn{display:inline-flex}
  .top .shell > .btn{display:none}
  .nav{
    position:absolute;left:0;right:0;top:100%;
    flex-direction:column;gap:0;
    background:var(--navy-deep);border-bottom:1px solid var(--navy-rule);
    padding:.5rem 0 1rem;
    /* Measured on a 375x667 phone with the Commercial group open: the panel ran
       105px past the bottom of the screen with overflow visible and no max
       height, and because .top is sticky the panel travels with it, so the page
       cannot be scrolled to reach the end. Request a bid, the last item, was
       simply unreachable. Cap it to what is left below the header and let the
       panel itself scroll. */
    max-height:calc(100dvh - var(--header-h));
    overflow-y:auto;
    overscroll-behavior:contain;
    -webkit-overflow-scrolling:touch;
  }
  /* dvh is recent; vh is the fallback and is only wrong while the URL bar is
     animating, which costs a few pixels rather than the whole button. */
  @supports not (height:100dvh){ .nav{max-height:calc(100vh - var(--header-h))} }
  .nav[hidden]{display:none}
  /* Direct children only. `.nav a` (0,1,1) outranks `.navtop` (0,1,0), so a
     group label was drawing its own short rule that stopped at the chevron
     while .navhead drew the full-width one underneath it. */
  .nav > a{
    width:var(--shell);margin-inline:auto;min-height:52px;padding:0;
    border-bottom:1px solid var(--navy-rule);
  }
  .nav .btn{width:var(--shell);margin:.9rem auto 0}
}
/* Complementary with the max-width:1160px block above. The pair used to be
   1020/1021, which left every fractional width between them matching neither
   query, so both Request a bid links rendered: two tab stops to one URL. */
@media (min-width:1160.02px){.nav .btn{display:none}}

/* ---- buttons ---------------------------------------------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;
  font-family:var(--font-ui);font-weight:600;font-size:var(--fs-small);
  letter-spacing:var(--track-nav);text-transform:uppercase;text-decoration:none;
  min-height:44px;padding:.85rem 1.5rem;border:1px solid var(--gold);background:var(--gold);color:#181205;
  transition:background .18s ease,color .18s ease;cursor:pointer;
}
.btn:hover{background:var(--gold-lift);border-color:var(--gold-lift)}
/* Magnetic pull, restrained to 5px and only where there is a real
   pointer. On touch this code never runs. */
@media (hover:hover) and (pointer:fine){
  .magnetic{will-change:transform}
  .magnetic.settle{transition:transform .45s cubic-bezier(.22,1,.36,1)}
}
@media (prefers-reduced-motion:reduce){.magnetic{transform:none !important}}
/* The default was raw --gold, and the readable --gold-dark override existed
   only for .band--paper. The hero and the projects band are neither, so
   "See the properties" and "See all 53 communities" rendered at 2.55:1 and
   2.37:1. Light is the common case, so light is now the default and the dark
   bands opt out. */
.btn--line{background:transparent;color:var(--gold-dark);border-color:var(--gold-dark)}
.btn--line:hover{background:var(--gold);color:#181205;border-color:var(--gold)}
.band--navy .btn--line,.band--deep .btn--line,.top .btn--line,
.nav .btn--line,.foot .btn--line{color:var(--gold);border-color:var(--gold)}
.band--navy .btn--line:hover,.band--deep .btn--line:hover,.top .btn--line:hover,
.nav .btn--line:hover,.foot .btn--line:hover{background:var(--gold);color:#181205}
.btn-row{display:flex;flex-wrap:wrap;gap:.7rem}

/* ---- holds: content we are still waiting on ---------------- */
.hold{border:1px dashed var(--gold-edge);background:var(--gold-wash);padding:.9rem 1.05rem;display:flex;flex-direction:column;gap:.35rem}
/* On white, a 10% gold wash disappears. Light contexts get a real tint and
   a firmer edge so a hold still reads as a deliberate gap. */
.band--paper .hold,.band--alt .hold,.hero .hold,.phero .hold,
.band--paper .ref,.band--alt .ref,
.band--paper .proj-hold,.band--alt .proj-hold,
.band--paper .svc-hold,.band--alt .svc-hold{
  background:#F5E9CB;
  border-color:#C3A24A;
}
.band--paper .hold .v,.band--alt .hold .v{color:#5A5442}
.band--paper .ref .q,.band--alt .ref .q{color:#5A5442}
.band--paper .proj-hold .n,.band--alt .proj-hold .n{color:var(--gold-dark)}
.band--paper .proj-hold .v,.band--alt .proj-hold .v{color:#5A5442}
.hold .k{color:var(--s-accent);font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:var(--track-label);text-transform:uppercase;font-weight:600}
.hold .v{font-size:var(--fs-body);line-height:var(--lh-ui);color:var(--s-soft)}
.band--paper .hold .k{color:var(--gold-dark)}
.band--paper .hold .v{color:var(--ink-soft)}
.hold--tag{padding:.28rem .55rem}
.hold--tag .k{font-size:var(--fs-micro);letter-spacing:var(--track-label)}

/* ---- hero -------------------------------------------------- */
/* ============================================================
   HOME HERO
   ------------------------------------------------------------
   Was a light split: a text column beside a small photograph on
   an offset plate, on --paper, directly beneath a navy header.
   The most important screen on the site was therefore its
   flattest, and the picture was a card rather than a place.

   It now shares the media and scrim of the inner heroes, so the
   whole site opens on one surface. It gets more height than they
   do because this is the page that has to land, and it keeps the
   two calls to action and the licence line inside the first
   screen: someone vetting a contractor should not scroll to find
   the licence number.
   ============================================================ */
.hero{
  position:relative;isolation:isolate;overflow:hidden;
  background:var(--navy-deep);
  border-bottom:1px solid var(--navy-rule);
  color:var(--on-navy);
}
.hero--img{
  /* Column, not row. As a row the .shell and the credit line became two items
     side by side: the copy lost its gutter and sat flush to the viewport edge,
     and the caption floated up the middle of the picture. */
  display:flex;flex-direction:column;justify-content:center;
  min-height:min(84svh,50rem);
  padding-block:clamp(3.5rem,9vw,7rem);
}
.hero-lead{max-width:60ch}
.hero h1{
  font-size:var(--fs-h1);font-weight:400;
  letter-spacing:var(--track-display);line-height:var(--lh-display);
  max-width:17ch;hanging-punctuation:first;color:var(--on-navy);
}
/* --gold-display was tuned for large text on white. On navy it is far too dark,
   so the phrase takes the light gold the rest of the dark surfaces use. */
.hero h1 em{font-style:normal;color:var(--gold-lift)}
.hero .lede{color:var(--on-navy-soft);max-width:54ch}
.hero .meta{
  display:flex;flex-wrap:wrap;gap:.4rem 1.1rem;color:var(--on-navy-soft);
  font-family:var(--font-ui);font-size:var(--fs-micro);
  letter-spacing:var(--track-label);text-transform:uppercase;
}
.hero .meta i{font-style:normal;color:var(--gold)}
.hero .eyebrow{color:var(--gold)}
.hero .skyline i{background:var(--gold)}
/* The outline button sat on a light band before; on navy it takes the bright
   gold, matching every other dark surface on the site. */
.hero .btn--line{color:var(--gold);border-color:var(--gold)}
.hero .btn--line:hover{background:var(--gold);color:#181205}

/* ---- proof figures ----------------------------------------- */
.figures{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(180px,100%),1fr));border-top:1px solid var(--navy-rule)}
.figures > div{padding:1.6rem 1.4rem;border-right:1px solid var(--navy-rule);display:flex;flex-direction:column;gap:.5rem}
.figures > div:last-child{border-right:0}
.figures .n{font-variant-numeric:tabular-nums;font-family:var(--font-display);font-size:var(--fs-h1);line-height:1;color:var(--gold)}
.figures .n.wait{font-size:var(--fs-body);font-family:var(--font-ui);font-weight:500;letter-spacing:0;color:var(--gold-lift);line-height:var(--lh-lead)}
.figures .l{font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--on-navy-soft);line-height:var(--lh-ui)}

/* ---- clients ----------------------------------------------- */
.clients{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(200px,100%),1fr));gap:1px;background:var(--s-line);border:1px solid var(--s-line)}
.clients div{background:var(--s-bg);padding:1.25rem 1.2rem;display:flex;flex-direction:column;gap:.35rem}
.clients .n{font-family:var(--font-display);font-size:var(--fs-h4);color:var(--s-ink);line-height:var(--lh-head)}
.clients .t{font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--s-soft);line-height:var(--lh-ui)}

/* ---- two column split -------------------------------------- */
.split{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.8fr);gap:clamp(1.5rem,4.5vw,3.5rem);align-items:center}
.split--wide{grid-template-columns:minmax(0,1.35fr) minmax(0,.65fr);align-items:start}
.split--wide img{position:sticky;top:110px}
.split img{width:100%;aspect-ratio:5/4;object-fit:cover}
@media (max-width:860px){.split{grid-template-columns:1fr}.split--wide img{position:static}}
.marks{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.6rem;max-width:var(--measure)}
.marks li{display:grid;grid-template-columns:14px 1fr;gap:.75rem;align-items:start}
.marks li::before{content:"";width:2px;height:1.05em;background:var(--gold);margin-top:.3em}

/* ---- cost of the overrun ----------------------------------- */
.cost{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(262px,100%),1fr));gap:1px;background:var(--s-line);border-block:1px solid var(--s-line)}
.cost article{background:var(--s-bg-alt);padding:1.6rem 1.4rem;display:flex;flex-direction:column;gap:.7rem}
.cost h3{font-size:var(--fs-h4);color:var(--s-accent);line-height:var(--lh-head)}
.cost p{font-size:var(--fs-body);color:var(--s-soft);line-height:var(--lh-ui)}

/* ---- what stops -------------------------------------------- */
.stops{list-style:none;margin:0;padding:0;display:grid;gap:0}

/* full-width image inside a band */
.band-img{width:100%;aspect-ratio:16/9;object-fit:cover;border:1px solid var(--navy-rule)}
.band--paper .band-img,.band--alt .band-img{border-color:var(--rule)}
@media (max-width:820px){.band-img{aspect-ratio:4/3}}
/* Each li holds a marker, a <b> and a bare text node. As a 2-column grid the
   text node auto-placed into row 2 col 1, widened the auto column and crushed
   the bold lead-in into a ribbon. Absolute marker, normal text flow. */
.stops li{
  position:relative;
  padding:1.05rem 0 1.05rem 1.9rem;
  border-bottom:1px solid var(--rule);
  color:var(--ink-soft);font-size:var(--fs-body);line-height:var(--lh-ui);
}
.stops li:first-child{border-top:1px solid var(--rule)}
.stops li::before{
  content:"";position:absolute;left:0;top:1.5em;
  width:11px;height:11px;background:var(--gold);
  clip-path:polygon(0 38%,38% 38%,38% 0,62% 0,62% 38%,100% 38%,100% 62%,62% 62%,62% 100%,38% 100%,38% 62%,0 62%);
  transform:rotate(45deg);
}
.stops b{
  display:block;margin-bottom:.22rem;
  color:var(--ink);font-weight:500;
  font-family:var(--font-display);
  font-size:var(--fs-h4);line-height:var(--lh-head);letter-spacing:var(--track-display);
}

/* ---- projects ---------------------------------------------- */
.filters{display:flex;flex-wrap:wrap;gap:.6rem}
.filters button{
  font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:var(--track-label);
  text-transform:uppercase;font-weight:600;
  display:inline-flex;align-items:center;min-height:44px;padding:0 1.15rem;
  border:1px solid var(--navy-rule);background:transparent;color:var(--on-navy-soft);
  cursor:pointer;transition:border-color .18s ease,color .18s ease,background .18s ease;
}
.filters button:hover{color:var(--on-navy);border-color:var(--gold-lift)}
.filters button[aria-pressed="true"]{border-color:var(--gold);color:var(--gold);background:var(--gold-wash)}
.pgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(300px,100%),1fr));gap:1.35rem}
.proj{
  background:var(--s-bg);border:1px solid var(--s-line);
  display:flex;flex-direction:column;overflow:hidden;
  transition:transform .4s cubic-bezier(.22,1,.36,1),border-color .3s ease;
}
.proj > img{width:100%;aspect-ratio:4/3;object-fit:cover;transition:transform .6s cubic-bezier(.22,1,.36,1)}
.proj .in{color:var(--s-ink)}
.proj h3 a{color:var(--s-ink)}
@media (hover:hover) and (pointer:fine){
  .proj:hover{transform:translate3d(0,-5px,0);border-color:var(--gold-edge)}
  .proj:hover > img{transform:scale(1.045)}
}
@media (prefers-reduced-motion:reduce){
  .proj,.proj > img{transition:none}
  .proj:hover{transform:none}
  .proj:hover > img{transform:none}
}
.proj .thumbs{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:var(--s-line);border-block:1px solid var(--s-line)}
.proj .thumbs img{width:100%;aspect-ratio:1/1;object-fit:cover}
.proj .in{padding:1.15rem 1.2rem 1.3rem;display:flex;flex-direction:column;gap:.6rem;flex:1}
.proj .tag{font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--s-accent);display:flex;flex-wrap:wrap;gap:.3rem .8rem}
.proj .tag em{font-style:normal;color:var(--s-soft)}
.proj h3{font-size:var(--fs-h3)}
.proj h3 a{display:flex;align-items:center;min-height:44px;text-decoration:none;color:inherit}
.proj h3 a:hover{color:var(--gold-lift)}
.proj p{font-size:var(--fs-body);color:var(--s-soft);line-height:var(--lh-ui)}
.proj-hold{border:1px dashed var(--gold-edge);background:var(--gold-wash);min-height:360px;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:.6rem;padding:1.75rem;overflow:hidden}
.proj-hold img{width:100%;max-width:190px;aspect-ratio:3/4;object-fit:cover;opacity:.9;margin-bottom:.35rem}
.proj-hold .k{font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--s-accent);font-weight:600}
.proj-hold .n{font-family:var(--font-display);font-size:var(--fs-h3);color:var(--gold-lift)}
.proj-hold .v{font-size:var(--fs-body);color:var(--s-soft);line-height:var(--lh-ui);max-width:27ch}

/* ---- services ---------------------------------------------- */
.svc{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(268px,100%),1fr));gap:1px;background:var(--rule);border:1px solid var(--rule)}
.svc article{background:var(--paper-lift);padding:1.5rem 1.4rem;display:flex;flex-direction:column;gap:.6rem}
.svc .k{font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--gold-dark);font-weight:600}
.svc h3{font-size:var(--fs-h3);color:var(--ink)}
.svc p{font-size:var(--fs-body);color:var(--ink-soft);line-height:var(--lh-ui)}
.svc .svc-hold{background:var(--gold-wash);border-left:1px dashed var(--gold-edge)}
.svc .svc-hold h3{color:var(--gold-dark)}

/* ---- who we serve ------------------------------------------ */
.serve{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(232px,100%),1fr));gap:1.5rem}
.serve article{display:flex;flex-direction:column;gap:.5rem;padding-top:.9rem;border-top:2px solid var(--s-accent)}
.serve h3{font-size:var(--fs-h4);color:var(--s-ink)}
.serve p{font-size:var(--fs-body);color:var(--s-soft);line-height:var(--lh-ui)}

/* ---- references -------------------------------------------- */
.refs{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(290px,100%),1fr));gap:1.35rem}
.ref{border:1px dashed var(--gold-edge);background:var(--gold-wash);padding:1.6rem 1.5rem;display:flex;flex-direction:column;gap:1rem;min-height:236px}
.ref .q{font-size:var(--fs-lead);color:var(--s-soft);line-height:var(--lh-ui);flex:1;position:relative;padding-left:1.35rem}
.ref .q::before{content:'\201C';position:absolute;left:0;top:-.08em;font-size:var(--fs-h3);line-height:1;color:var(--gold);opacity:.85}
.ref .who{display:flex;flex-direction:column;gap:.25rem;border-top:1px solid var(--gold-edge);padding-top:.85rem}
.ref .who b{font-family:var(--font-ui);font-weight:600;font-size:var(--fs-small);letter-spacing:var(--track-nav);color:var(--s-accent)}
.ref .who span{font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--s-soft)}

/* ---- bid form ---------------------------------------------- */
.form{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(238px,100%),1fr));gap:1rem}
.f{display:flex;flex-direction:column;gap:.4rem}
.f--wide{grid-column:1/-1}
.f label{font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--ink-soft);font-weight:600}
.f input,.f select,.f textarea{font-family:var(--font-display);font-size:var(--fs-body);color:var(--ink);background:var(--paper-lift);border:1px solid var(--rule);min-height:44px;padding:.68rem .85rem;width:100%}
.f input:focus,.f select:focus,.f textarea:focus{border-color:var(--gold)}
.f textarea{min-height:120px;resize:vertical}
.f select{appearance:none;border-radius:0}
.f .hint{font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:0;color:var(--ink-soft);text-transform:none}
.f .err{font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:0;color:#9A2515;text-transform:none;font-weight:500}
.f.invalid input,.f.invalid select,.f.invalid textarea{border-color:#9A2515;background:#FCF3F1}
.sent{font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--gold-dark);font-weight:600;display:flex;align-items:center;gap:.5rem}
.sent b{font-weight:600}
.holds-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(226px,100%),1fr));gap:1rem}

/* ---- footer ------------------------------------------------ */
.foot{background:var(--navy-deep);padding-block:3rem 3.5rem;border-top:1px solid var(--navy-rule)}
.foot-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(178px,100%),1fr));gap:2rem}
@media (min-width:920px){.foot-grid{grid-template-columns:1.3fr 1fr 1fr 1fr}}
.foot .foot-h{font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--gold);font-weight:600;margin:0}
.foot ul{list-style:none;margin:.6rem 0 0;padding:0;display:flex;flex-direction:column}
.foot li{color:var(--on-navy-soft);font-size:var(--fs-body);padding-block:.35rem}
.foot a{color:var(--on-navy-soft);text-decoration:none;font-size:var(--fs-body);display:inline-flex;align-items:center;min-height:44px;width:fit-content;max-width:100%}
.foot a:hover{color:var(--on-navy)}
.foot .lockup{display:flex;width:auto;min-height:0;color:inherit}
.foot .gold{color:var(--gold-lift)}
/* Legal row. Its own landmark above the copyright line, because the three
   legal pages are linked from nowhere else on the site. Kept visually quieter
   than the column links so it reads as fine print without becoming unreadable:
   still on the micro step, still clears 44px for touch. */
.foot-legal{margin-top:2.4rem;display:flex;flex-wrap:wrap;gap:0 1.75rem}
.foot-legal a{
  font-family:var(--font-ui);font-size:var(--fs-micro);
  letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--on-navy-soft);text-decoration:none;
  display:inline-flex;align-items:center;min-height:44px;
}
.foot-legal a:hover{color:var(--gold-lift)}
.foot-base{margin-top:1.1rem;padding-top:1.3rem;border-top:1px solid var(--navy-rule);display:flex;flex-wrap:wrap;gap:.5rem 1.75rem;font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--on-navy-soft)}


/* ============================================================
   MOBILE PASS
   Measured on a 390px viewport: the page ran to 18.6 phone
   screens, the hero alone was 1003px with the photo crushed to a
   197px letterbox, and the six qualification figures stacked to
   611px. This tightens the vertical rhythm and gives the imagery
   back its proportions.
   ============================================================ */
@media (max-width:820px){
  .band{padding-block:clamp(2.75rem,8vw,3.5rem)}

  /* hero: no forced viewport height, and let the portrait photo be portrait */
  .hero--img{min-height:0;padding-block:2.75rem 3rem}
  .hero h1{max-width:none}
  .hero .lede{color:var(--ink-soft)}
  .hero .meta{flex-direction:column;gap:.35rem}
  .hero .meta i{display:none}

  /* full-width CTAs: a 164px button in a 346px column reads as an afterthought */
  .btn-row{flex-direction:column;align-items:stretch;gap:.6rem}
  .btn-row .btn{width:100%}
  .endcta{flex-direction:column;align-items:stretch}
  .endcta .btn{width:100%}

  /* qualification figures two-up rather than a 611px column */
  .figures{grid-template-columns:1fr 1fr}
  .figures > div{padding:1.1rem .9rem}
  .figures > div:nth-child(2n){border-right:0}

  /* the draft bar is scaffolding, not content */
  .draft .shell{padding-block:.45rem;gap:.15rem .9rem}

  /* tables and wide blocks */
  .captable th{width:42%}
  .captable th,.captable td{padding:.75rem .6rem}

  /* section headings were running to four lines */
  .phero h1,.band h2{max-width:none}
}

@media (max-width:480px){
  .figures > div{padding:.95rem .75rem}
}

@media (prefers-reduced-motion:reduce){*{animation-duration:.01ms !important;transition-duration:.01ms !important}}

/* ============================================================
   INNER PAGES
   ============================================================ */
.phero .shell{display:flex;flex-direction:column;gap:1.15rem}
/* Takes the h1 rung from the element rule. It was briefly pinned to --fs-h2
   to calm the inner pages down, which made every inner-page title exactly
   the size of the section headings under it and of the closing CTA: a 1:1
   rank on twelve pages. If a smaller inner title is ever wanted it needs
   its own rung between h1 and h2, not the h2 value. */

/* ============================================================
   INNER PAGE HERO
   ------------------------------------------------------------
   Was a ~5rem strip of --paper-alt holding a title and a
   paragraph, sitting directly beneath a navy header, so every
   inner page opened by interrupting the brand's own surface with
   a grey band and then left two thirds of a 1440px screen empty.

   Now: full-bleed photograph of the company's own work, on navy,
   flowing straight out of the header. The scrim is two layers,
   not one -- a horizontal ramp that keeps the left edge close to
   solid so the headline never sits on busy pixels, and a vertical
   one that seats the whole frame and stops the image floating.
   Text contrast is therefore a property of the scrim, not of
   whichever photograph a page happens to use.
   ============================================================ */
.phero{
  position:relative;isolation:isolate;
  background:var(--navy-deep);
  border-bottom:1px solid var(--navy-rule);
  padding-block:clamp(3rem,7vw,5.5rem);
  color:var(--on-navy);
  overflow:hidden;
}
.phero--img{
  min-height:clamp(23rem,58vh,40rem);
  display:flex;flex-direction:column;justify-content:center;
  padding-block:clamp(3.5rem,9vw,7rem);
}

/* --- the photograph and its scrim ------------------------------------ */
.phero-media{position:absolute;inset:0;z-index:-1;overflow:hidden}
.phero-media img{
  width:100%;height:100%;object-fit:cover;object-position:center 45%;
  display:block;
}
/* The photograph settles rather than appearing. Transform only, so it composites
   on the GPU and cannot reflow anything, and the will-change is dropped once the
   class lands so it does not hold a layer for the life of the page. */
.js .phero-media img{transform:scale(1.06);transition:transform 1.5s cubic-bezier(.22,1,.36,1)}
.js.ready .phero-media img{transform:none}
@media (prefers-reduced-motion:reduce){
  .js .phero-media img{transform:none;transition:none}
}
/* Two ramps. The horizontal one protects the headline column; the vertical
   one seats the frame so it reads as a photograph the page sits on rather
   than a picture floating behind text. */
.phero-scrim{
  position:absolute;inset:0;
  background:
    linear-gradient(100deg,
      rgba(6,16,31,.96) 0%,
      rgba(6,16,31,.90) 28%,
      rgba(6,16,31,.68) 58%,
      rgba(6,16,31,.42) 100%),
    linear-gradient(to top,
      rgba(6,16,31,.80) 0%,
      rgba(6,16,31,.10) 45%,
      rgba(6,16,31,.35) 100%);
}
/* The horizontal ramp exists because on a wide screen the text occupies the left
   half and the photograph gets to breathe on the right. Below 900px the text
   spans the whole frame, so that ramp protects nothing: measured on the home
   image, the lede fell to 3.69:1 over the lit porte-cochere. Narrow screens get
   an even scrim instead. The value was measured against every hero image with text across
   the full frame: .76 fails at 4.29, .78 is the floor, and this ramp averages
   .82 for a worst case of 5.36:1 while still letting the photograph read. */
@media (max-width:900px){
  .phero-scrim{
    background:
      linear-gradient(to bottom,
        rgba(6,16,31,.84) 0%,
        rgba(6,16,31,.80) 45%,
        rgba(6,16,31,.86) 100%);
  }
}

/* --- the text ---------------------------------------------------------- */
.phero .phero-grid{
  display:grid;grid-template-columns:1fr;gap:clamp(1.6rem,4vw,3rem);
  align-items:end;position:relative;
}
.phero-lead{display:flex;flex-direction:column;gap:1.15rem;min-width:0}
.phero h1{font-weight:400;letter-spacing:var(--track-display);max-width:20ch}
.phero .lede{max-width:56ch}

/* On the photographic heroes everything sits on navy, so the light-band
   overrides for eyebrow, mark and body colour have to be undone. */
.phero h1{color:var(--on-navy)}
.phero .lede{color:var(--on-navy-soft)}
.phero .eyebrow{color:var(--gold)}
.phero .skyline i{background:var(--gold)}
.phero .crumbs{color:var(--on-navy-soft)}
.phero .crumbs a{color:var(--gold)}

@media (min-width:900px){
  .phero--proof .phero-grid{grid-template-columns:minmax(0,1.35fr) minmax(0,.65fr)}
}

/* --- the proof rail ---------------------------------------------------- */
.phero-proof-rail{
  list-style:none;margin:0;padding:0;
  display:grid;gap:1px;background:var(--rule);
  border:1px solid var(--rule);
}
.phero-proof-rail li{
  background:var(--paper);padding:1rem 1.15rem;
  display:flex;flex-direction:column;gap:.2rem;
}
.phero-proof-rail .v{
  font-family:var(--font-display);font-variant-numeric:tabular-nums;
  font-size:var(--fs-h3);line-height:var(--lh-head);
  color:var(--gold-dark);letter-spacing:var(--track-head);
}
.phero-proof-rail .l{
  font-family:var(--font-ui);font-size:var(--fs-micro);
  letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--ink-soft);
}
/* Over a photograph the rail becomes glass rather than paper: the frame stays
   readable, and the picture keeps showing through so it reads as one hero. */
.phero--img .phero-proof-rail{
  background:var(--gold-edge);border-color:var(--gold-edge);
  box-shadow:0 18px 44px -22px rgba(0,0,0,.9);
}
.phero--img .phero-proof-rail li{
  /* .72 left the small label at 3.69:1 against a bright photo. The glass has to
     carry the label, not the photograph, so it is deepened and the label takes
     the brighter ink. Measured worst case, i.e. pure white behind the glass. */
  background:rgba(6,16,31,.82);
  -webkit-backdrop-filter:blur(12px) saturate(130%);
  backdrop-filter:blur(12px) saturate(130%);
}
.phero--img .phero-proof-rail .v{color:var(--gold-lift)}
.phero--img .phero-proof-rail .l{color:var(--on-navy)}

/* --- the credit line --------------------------------------------------- */
.phero-cap{
  position:relative;margin:clamp(1.75rem,4vw,3rem) 0 0;
  font-family:var(--font-ui);font-size:var(--fs-micro);
  letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--on-navy-soft);
}
.phero-cap .shell{display:block}

@media (max-width:600px){
  .phero-proof-rail{grid-template-columns:1fr 1fr}
  .phero-proof-rail li{padding:.75rem .85rem}
  .phero-proof-rail .v{font-size:var(--fs-h4)}
  /* Three facts in two columns leaves an empty cell that paints as a box,
     because the 1px gaps show the container behind. Keyed off the count so it
     self-corrects if a fact is added or removed. */
  .phero-proof-rail > li:last-child:nth-child(odd){grid-column:1 / -1}
}
.crumbs{display:flex;flex-wrap:wrap;gap:.4rem .55rem;align-items:center;font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--ink-soft)}
.crumbs a{color:var(--gold-dark);text-decoration:none;display:inline-flex;align-items:center;min-height:44px}
.crumbs a:hover{text-decoration:underline}
.crumbs span[aria-current]{color:var(--ink-soft)}

.prose{max-width:var(--measure);display:flex;flex-direction:column;gap:1rem}
.prose p{color:inherit}
/* Service, sector and project paragraphs are body copy that happened to be set
   in the metadata grey. ink-soft stays for ledes, labels and captions; anything
   a reader is meant to actually read takes ink-body at 13.37:1.
   SCOPED TO THE LIGHT BANDS ON PURPOSE. .cost sits inside .band--navy, and an
   unscoped version of this rule put near-black paragraphs on navy at 1.3:1.
   Anything on a dark band keeps its inherited light colour. */
.band--paper .svc p,.band--alt .svc p,
.band--paper .serve p,.band--alt .serve p,
.band--paper .proj p,.band--alt .proj p,
.band--paper .dsvc p,.band--alt .dsvc p,
.band--paper .stops li,.band--alt .stops li{color:var(--ink-body)}
.band--paper .prose p{color:var(--ink-body)}
.band--navy .prose p,.band--deep .prose p{color:var(--on-navy-soft)}

/* Long-form pages (privacy, terms, accessibility) set their own sub-headings
   inside .prose. Without this they inherit body size and the page reads as one
   undifferentiated column. Extra top gap on all but the first, so a heading
   sits with the text it opens rather than floating between two paragraphs. */
.prose h2,.prose h3{margin:0;color:var(--s-ink,var(--ink));text-wrap:balance}
.prose h2{font-size:var(--fs-h3);max-width:34ch}
.prose h3{font-size:var(--fs-h4);letter-spacing:var(--track-head)}
.prose h2:not(:first-child),.prose h3:not(:first-child){margin-top:1.4rem}

/* project factsheet */
.facts{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(190px,100%),1fr));gap:1px;background:var(--s-line);border:1px solid var(--s-line)}
.facts > div{background:var(--s-bg);padding:1.1rem 1.15rem;display:flex;flex-direction:column;gap:.4rem}
.facts .k{font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--s-soft)}
.facts .v{font-size:var(--fs-h4);color:var(--s-ink);line-height:var(--lh-head)}
.facts .v.wait{color:var(--s-accent);font-size:var(--fs-body)}

/* galleries */
.gallery{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(260px,100%),1fr));gap:1rem}
.gallery figure{margin:0;display:flex;flex-direction:column;gap:.55rem}
.gallery img{width:100%;aspect-ratio:4/3;object-fit:cover;border:1px solid var(--s-line)}
.band--paper .gallery img{border-color:var(--rule)}
.gallery figcaption{font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--s-soft)}
.band--paper .gallery figcaption{color:var(--ink-soft)}
.gallery--wide{grid-template-columns:repeat(auto-fit,minmax(min(340px,100%),1fr))}

/* prev / next */
.pagenav{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(240px,100%),1fr));gap:1px;background:var(--navy-rule);border:1px solid var(--navy-rule)}
.pagenav a{background:var(--navy);padding:1.3rem 1.35rem;text-decoration:none;display:flex;flex-direction:column;gap:.4rem;transition:background .2s ease}
.pagenav a:hover{background:var(--navy-raised)}
.pagenav .k{font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--gold)}
.pagenav .t{font-size:var(--fs-h4);color:var(--on-navy)}

/* closing CTA on inner pages */
.endcta{display:flex;flex-wrap:wrap;gap:1.4rem;align-items:center;justify-content:space-between}
.endcta h2{font-size:var(--fs-h2);max-width:18ch}

/* capabilities table */
.captable{font-variant-numeric:tabular-nums;width:100%;border-collapse:collapse;font-size:var(--fs-body)}
.captable th,.captable td{text-align:left;padding:.9rem 1rem;border-bottom:1px solid var(--rule);vertical-align:top}
.captable th{font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--ink-soft);font-weight:600;width:34%}
.captable td{color:var(--ink)}
.captable td.wait{color:var(--gold-dark)}
.tablewrap{overflow-x:auto}

/* site index, for the review build only */
.pages{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(230px,100%),1fr));gap:1px;background:var(--navy-rule);border:1px solid var(--navy-rule)}
.pages a{background:var(--navy);padding:1.1rem 1.15rem;text-decoration:none;display:flex;flex-direction:column;gap:.35rem}
.pages a:hover{background:var(--navy-raised)}
.pages .t{font-size:var(--fs-lead);color:var(--on-navy)}
.pages .u{font-family:var(--font-ui);font-size:var(--fs-micro);letter-spacing:var(--track-label);color:var(--gold)}

/* ============================================================
   TWO-LEVEL NAV
   Matching the competitor structure: About Us / Our Services /
   Our Projects each open a group. Hover on pointer devices,
   click everywhere, and a plain stacked list on mobile.
   ============================================================ */
.navgroup{position:relative;display:flex;align-items:center}
.navhead{display:flex;align-items:center}
.navtop{
  display:flex;align-items:center;gap:.4rem;min-height:44px;
  padding:0 .1rem 0 var(--nav-pad);
  background:transparent;border:0;cursor:pointer;text-decoration:none;
  font-family:var(--font-ui);
  font-size:var(--fs-small);font-weight:500;letter-spacing:var(--track-nav);text-transform:uppercase;
  color:var(--on-navy-soft);position:relative;transition:color .18s ease;
}
.navtop::after{right:.1rem}
.navtop:hover,.navgroup:hover .navtop,.navgroup[data-open="true"] .navtop{color:var(--on-navy)}
.navgroup:hover .navtop::after,.navgroup[data-open="true"] .navtop::after,
.navtop:focus-visible::after{transform:scaleX(1)}
.navtop[data-current="1"]{color:var(--on-navy)}
.navtop[data-current="1"]::after{transform:scaleX(1)}
/* 44px of chevron beside every group label was ~54px of header width across the
   three groups and made the row feel gappy. 26px still clears the 24px WCAG 2.2
   target minimum for a pointer, and the mobile block below takes it back to
   52px where the finger is. */
.navtoggle{
  display:flex;align-items:center;justify-content:center;
  min-width:26px;width:26px;min-height:44px;padding:0;
  background:transparent;border:0;cursor:pointer;color:var(--on-navy-soft);
  transition:color .18s ease;
}
.navtoggle:hover,.navgroup:hover .navtoggle,.navgroup[data-open="true"] .navtoggle{color:var(--on-navy)}
.chev{width:6px;height:6px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(45deg) translateY(-2px);transition:transform .2s ease}
.navgroup[data-open="true"] .chev{transform:rotate(225deg) translateY(-2px)}

/* The panel used to sit flush at left:0, so its items were indented by their
   own --sub-pad while the label above them was indented by --nav-pad: the
   submenu text landed about 9px to the right of the label that opened it.
   Pulling the panel left by the difference makes the two columns of text line
   up, which is the alignment the client asked for. */
.subnav{
  position:absolute;top:100%;
  left:calc(var(--nav-pad) - var(--sub-pad) - 1px);
  min-width:224px;z-index:60;
  background:var(--navy-deep);border:1px solid var(--navy-rule);
  border-top:1px solid var(--gold-edge, var(--gold));
  padding:.3rem 0;display:none;flex-direction:column;
  box-shadow:0 16px 34px -10px rgba(0,0,0,.55);
}
.navgroup[data-open="true"] .subnav{display:flex}
.subnav .subitem{
  display:flex;align-items:center;min-height:42px;padding:0 var(--sub-pad);
  border-bottom:0;font-size:var(--fs-micro);letter-spacing:var(--track-nav);
  color:var(--on-navy-soft);white-space:nowrap;
  border-left:2px solid transparent;
  transition:color .16s ease,background .16s ease,border-color .16s ease;
}
.subnav .subitem:hover{color:var(--gold);background:var(--navy-raised);border-left-color:var(--gold)}
.subnav .subitem[aria-current]{color:var(--gold);border-left-color:var(--gold)}

.nav .navphone{
  display:flex;align-items:center;min-height:44px;padding:0 .6rem;
  font-family:var(--font-ui);
  font-size:var(--fs-small);font-weight:600;letter-spacing:var(--track-nav);color:var(--gold);text-decoration:none;
}
.nav .navphone.hold-phone{color:var(--gold);opacity:.75;font-style:normal}

@media (max-width:1160px){
  .navgroup{flex-direction:column;align-items:stretch;width:var(--shell);margin-inline:auto}
  /* link and chevron share one row; the chevron keeps a 52px tap target */
  .navhead{width:100%;justify-content:space-between;border-bottom:1px solid var(--navy-rule)}
  /* `.nav a` is (0,1,1) and .navtop is an <a> inside .nav, so a bare `.navtop`
     rule (0,1,0) loses to it and the group labels kept the desktop padding:
     COMMERCIAL sat 9.6px right of CAPABILITIES in the mobile list. */
  .nav .navtop{flex:1;min-height:52px;padding:0}
  .navtop::after,.nav > a::after{display:none}   /* the hairline is a desktop cue */
  .navtoggle{min-width:52px;width:52px;min-height:52px;padding:0}
  .subnav{position:static;display:none;border:0;box-shadow:none;background:transparent;
          padding:0 0 .5rem;min-width:0}
  .navgroup[data-open="true"] .subnav{display:flex}
  .subnav .subitem{padding-left:1rem;min-height:46px;border-bottom:1px solid var(--navy-rule);width:100%}
  .nav .navphone{width:var(--shell);margin-inline:auto;min-height:52px;border-bottom:1px solid var(--navy-rule)}
}

/* ============================================================
   QUALIFICATION TICKER
   Replaces the six-cell figures grid, which ran to a full screen
   on a phone. One slim band, continuous scroll, edge-masked.
   The track holds two identical sets and translates -50%, so the
   loop is seamless; the second set is aria-hidden so a screen
   reader hears the facts once.
   ============================================================ */
.ticker{
  position:relative;background:var(--sky);
  border-block:1px solid #D8E3EF;
  overflow:hidden;padding-block:1.1rem;
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 6%,#000 94%,transparent 100%);
          mask-image:linear-gradient(90deg,transparent 0,#000 6%,#000 94%,transparent 100%);
}
.ticker-track{
  display:flex;width:max-content;
  animation:tickerRun 52s linear infinite;
  will-change:transform;
}
.ticker:hover .ticker-track,
.ticker:focus-within .ticker-track{animation-play-state:paused}
.ticker-set{display:flex;align-items:center;flex:0 0 auto}

@keyframes tickerRun{
  from{transform:translate3d(0,0,0)}
  to{transform:translate3d(-50%,0,0)}
}

@media (max-width:820px){
  .ticker{padding-block:.9rem}
  .ticker-track{animation-duration:38s}
}

/* ---- client logos as the ticker ---------------------------------------
   The same five logos as the old static row, same monochrome treatment, on
   the pale band the facts ticker used so the hero still hands off to light. */
.logo-band{
  background:var(--sky);border-bottom:1px solid #D8E3EF;
  padding-top:clamp(1.25rem,2.6vw,1.75rem);
}
.logo-band .eyebrow{display:block;text-align:center;color:var(--gold-dark);margin:0}
.ticker--logos{
  background:transparent;border-block:0;
  padding-block:clamp(1rem,2.4vw,1.6rem) clamp(1.4rem,3vw,2rem);
}
.ticker--logos .ticker-track{animation-duration:40s}
.ticker--logos .ticker-set{list-style:none;margin:0;padding:0}
.logo-tick{
  flex:0 0 auto;display:flex;align-items:center;justify-content:center;
  padding-inline:clamp(1.75rem,4vw,3.25rem);
}
.logo-tick-img{
  height:52px;width:auto;max-width:none;object-fit:contain;display:block;
  filter:grayscale(1) contrast(1.12);
  -webkit-user-drag:none;user-select:none;
}
@media (max-width:820px){
  .logo-tick{padding-inline:1.4rem}
  .logo-tick-img{height:38px}
  .ticker--logos .ticker-track{animation-duration:30s}
}

/* Motion here is decorative; without it the same facts sit still. */
@media (prefers-reduced-motion:reduce){
  .ticker{-webkit-mask-image:none;mask-image:none;padding-block:1.15rem}
  .ticker-track{animation:none;width:100%;flex-wrap:wrap;justify-content:center;row-gap:.6rem}
  .ticker-set[aria-hidden="true"]{display:none}
  /* standing still, the five logos appear once, centred, not twice */
  .ticker--logos .dup{display:none}
  .ticker--logos .ticker-set{flex-wrap:wrap;justify-content:center;row-gap:1rem}
}

/* ============================================================
   CLIENT LOGOS
   Source files were trimmed of their white margin and set to a
   single optical height, so a wide wordmark and a stacked one
   read at the same weight rather than by bounding box.
   ============================================================ */
.logos{
  list-style:none;margin:0;padding:0;
  display:grid;grid-template-columns:repeat(auto-fit,minmax(min(180px,100%),1fr));
  gap:clamp(1.25rem,3vw,2.5rem);align-items:center;
}
.logos li{display:flex;flex-direction:column;align-items:center;gap:.7rem}
.logos .logo-img{
  height:54px;width:auto;max-width:100%;object-fit:contain;
  /* Monochrome keeps four unrelated brand palettes calm next to each other,
     but at 72% on a pale band they disappeared. Full opacity, and a touch of
     contrast to hold the thinner wordmarks together. */
  filter:grayscale(1) contrast(1.12);
  transition:filter .25s ease;
}
.logos li:hover .logo-img{filter:grayscale(0) contrast(1)}
.logos .logo-role{
  font-family:var(--font-ui);
  font-size:var(--fs-micro);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--s-soft);text-align:center;
}
@media (max-width:820px){
  .logos{grid-template-columns:repeat(2,1fr);gap:1.5rem 1rem}
  .logos .logo-img{height:42px}
  /* Two columns and an odd number of logos strands the last one alone in the
     left cell. Adding Essex on 8 Sep took the row from four to five and did
     exactly that. Let a trailing odd item span both columns so it centres
     instead; the selector keys off the count, so it self-corrects if a logo is
     ever added or dropped again. */
  .logos > li:last-child:nth-child(odd){grid-column:1 / -1}
}
@media (prefers-reduced-motion:reduce){.logos .logo-img{transition:none}}

/* a logo sitting inside a reference card */
.ref .ref-logo{height:28px;width:auto;filter:grayscale(1) contrast(1.12);margin-bottom:.35rem}

/* ============================================================
   SITEWIDE MOTION
   The home hero already had a word-mask cascade; every other
   page opened flat. This carries the same choreography across
   all 21 pages, plus the connective tissue between them.
   Everything below is transform/opacity only and is switched
   off wholesale under prefers-reduced-motion.
   ============================================================ */

/* --- 1. scroll progress ------------------------------------ */
.progress{
  position:fixed;top:0;left:0;right:0;height:2px;z-index:70;
  background:transparent;pointer-events:none;
}
.progress i{
  display:block;height:100%;width:100%;
  background:linear-gradient(90deg,var(--gold-dark),var(--gold));
  transform:scaleX(0);transform-origin:0 50%;
  will-change:transform;
}

/* --- 2. inner-page headline, same cascade as the hero ------- */
.js .phero h1 .wd{display:inline-block;overflow:hidden;padding-bottom:.14em;margin-bottom:-.14em;vertical-align:top}
.js .phero h1 .wd > i{display:inline-block;font-style:inherit;transform:translateY(108%);transition:transform .72s cubic-bezier(.22,1,.36,1)}
.js.ready .phero h1 .wd > i{transform:none}
.js .phero .crumbs,
.js .phero .lede,
.js .phero .eyebrow,
.js .phero .phero-proof-rail,
.js .phero .skyline{opacity:0;transform:translateY(14px);transition:opacity .6s ease-out,transform .6s cubic-bezier(.22,1,.36,1)}
.js.ready .phero .crumbs,
.js.ready .phero .lede,
.js.ready .phero .eyebrow,
.js.ready .phero .phero-proof-rail,
.js.ready .phero .skyline{opacity:1;transform:none}

/* --- 3. imagery arrives with a wipe rather than a pop -------- */
.js .img-wipe{clip-path:inset(0 0 100% 0);transition:clip-path .95s cubic-bezier(.22,1,.36,1)}
/* A clip-path clips the element's shadow along with it, and inset(0 0 0 0)
   clips exactly to the box, which is why the offset plate never painted. The
   wipe now ends on a negative inset that includes the plate and its shadow.
   Both states are inset(), so the transition is unchanged. */
.js .img-wipe.in{clip-path:inset(0 -72px -72px 0)}

/* --- 4. dropdowns ease open --------------------------------- */
@media (min-width:1160.02px){
  /* The panel is positioned against .navgroup, and the group was only as tall
     as its 44px label sitting centred in a 64px header. top:100% therefore
     landed at y=54 while the header ran to y=65, so the panel's top edge cut
     11px up into the header and crossed its bottom border.
     Stretching the group to the full header height puts top:100% exactly on
     the header's bottom edge, and has the side benefit that the whole height
     of the header is hoverable rather than just the middle 44px. The 44px
     min-heights stay as the floor for touch. */
  .nav{align-self:stretch}
  .navgroup{align-self:stretch}
  .navhead{height:100%}
  .nav > a,.navtop,.navtoggle{height:100%}

  .subnav{
    display:flex;visibility:hidden;opacity:0;
    top:calc(100% + 1px);            /* clear the header's 1px bottom border */
    transform:translateY(-6px);pointer-events:none;
    transition:opacity .2s ease,transform .2s cubic-bezier(.22,1,.36,1),visibility .2s;
  }
  .navgroup[data-open="true"] .subnav{
    visibility:visible;opacity:1;transform:none;pointer-events:auto;
  }
}

/* --- 5. text links get a sweep, not a jump ------------------ */
.prose a:not(.btn),.stops a:not(.btn),.foot a{
  position:relative;text-decoration:none;
  background-image:linear-gradient(currentColor,currentColor);
  background-size:0% 1px;background-position:0 100%;background-repeat:no-repeat;
  transition:background-size .3s cubic-bezier(.22,1,.36,1),color .2s ease;
}
.prose a:not(.btn):hover,.stops a:not(.btn):hover,.foot a:hover{background-size:100% 1px}

@media (prefers-reduced-motion:reduce){
  .progress{display:none}
  .js .phero h1 .wd > i,
  .js .phero .crumbs,.js .phero .lede,.js .phero .eyebrow,.js .phero .phero-proof-rail,.js .phero .skyline{
    transform:none;opacity:1;transition:none;
  }
  .js .img-wipe{clip-path:none;transition:none}
  .subnav{transition:none}
  .prose a:not(.btn),.stops a:not(.btn),.foot a{transition:none}
}

/* --- property wall -------------------------------------------------------
   Phil's brief: a big grid of everywhere All Ready has worked, each tile
   carrying only the property name and its city. No addresses, no links.
   Most tiles are typographic because we do not own photographs of these
   communities; the photo variant upgrades a tile wherever we do. */
.pwall{
  list-style:none;margin:2rem 0 0;padding:0;
  display:grid;gap:.75rem;
  grid-template-columns:repeat(auto-fill,minmax(min(232px,100%),1fr));
}
.pcard{
  position:relative;display:flex;flex-direction:column;gap:.3rem;
  padding:1.05rem 1.1rem 1.15rem;
  background:var(--s-bg,var(--paper));
  border:1px solid var(--s-line,var(--rule));
  border-top:2px solid var(--s-accent,var(--navy));
  border-radius:2px;
}
.pcard-name{
  font-family:var(--font-display);
  font-size:var(--fs-body);line-height:var(--lh-head);color:var(--s-ink,var(--ink));
  text-wrap:balance;
}
.pcard-loc{
  font-family:var(--font-ui);
  font-size:var(--fs-micro);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--s-soft,var(--ink-soft));
}
.pcard--img{padding:0;overflow:hidden;border-top-width:1px}
.pcard--img img{display:block;width:100%;height:auto;aspect-ratio:3/2;object-fit:cover}
.pcard--img .pcard-body{
  display:flex;flex-direction:column;gap:.3rem;
  padding:.95rem 1.1rem 1.1rem;border-top:2px solid var(--s-accent,var(--navy));
}
.pwall-note{
  margin:1.5rem 0 0;font-size:var(--fs-micro);
  color:var(--s-soft,var(--ink-soft));max-width:60ch;
}
/* the count reads as proof, so it gets to be typographically loud */
.pcount{
  display:flex;align-items:baseline;gap:.6rem;flex-wrap:wrap;
  margin:0 0 .4rem;
}
.pcount b{font-variant-numeric:tabular-nums;
  font-family:var(--font-display);font-weight:600;
  font-size:var(--fs-h1);line-height:1;
  color:var(--s-ink,var(--ink));font-variant-numeric:tabular-nums;
}
.pcount span{
  font-family:var(--font-ui);
  font-size:var(--fs-micro);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--s-soft,var(--ink-soft));
}
/* division page: the "what we do" rows above the wall */
.dsvc{list-style:none;margin:2rem 0 0;padding:0;display:grid;gap:1.6rem;
  grid-template-columns:repeat(auto-fit,minmax(min(280px,100%),1fr))}
.dsvc > li{display:flex;flex-direction:column;gap:.5rem}
.dsvc h3{margin:0;font-size:var(--fs-h4);color:var(--s-ink,var(--ink))}
.dsvc h3::before{
  content:"";display:block;width:34px;height:2px;margin-bottom:.7rem;
  background:var(--s-accent,var(--navy));
}
.dsvc p{margin:0;color:var(--s-soft,var(--ink-soft));font-size:var(--fs-body)}
@media (hover:hover) and (pointer:fine){
  .pcard{transition:transform .22s cubic-bezier(.22,1,.36,1),border-color .22s ease}
  .pcard:hover{transform:translateY(-2px);border-color:var(--s-accent,var(--navy))}
}
@media (prefers-reduced-motion:reduce){ .pcard{transition:none} .pcard:hover{transform:none} }
.pcard--link{padding:0}
.pcard--link > a{display:flex;flex-direction:column;height:100%;text-decoration:none;color:inherit}
.pcard--link .pcard-body{flex:1}
.pcard--link .pcard-name{text-decoration:underline;text-decoration-color:transparent;text-underline-offset:3px;transition:text-decoration-color .2s ease}
@media (hover:hover) and (pointer:fine){
  .pcard--link:hover .pcard-name{text-decoration-color:currentColor}
}

/* "Home" is the shortest breadcrumb label and lands at 38px wide, under the
   44px touch minimum every other control on the site clears. inline-flex with
   a floor keeps the text left-aligned and moves the separator by six pixels. */
.crumbs a{display:inline-flex;align-items:center;min-width:44px;min-height:44px}

/* the email sits under the bid form as the low-friction alternative to it */
.contactline{margin:1.4rem 0 0;font-size:var(--fs-body);color:var(--s-soft,var(--ink-soft))}
.contactline a{color:var(--s-ink,var(--ink));text-underline-offset:3px}

/* Leadership portrait. The source is already a circular crop, so CSS clips to
   the same circle rather than shipping a heavy PNG with an alpha channel. */
.portrait{
  align-self:start;justify-self:start;
  width:min(280px,100%);height:auto;aspect-ratio:1;border-radius:50%;
  object-fit:cover;
  border:1px solid var(--s-line,var(--rule));
  box-shadow:0 12px 34px rgba(10,25,54,.14);
}
@media (max-width:760px){ .portrait{width:min(200px,60%);justify-self:center} }

/* The positioning statement. It is the one place on the site that gets to be
   a headline twice the size of everything around it, because it is the whole
   argument compressed into six words. */
.pitch-line{
  margin:.5rem 0 0;max-width:20ch;
  font-size:var(--fs-h1);line-height:var(--lh-display);
  letter-spacing:var(--track-display);text-wrap:balance;color:var(--s-ink,var(--ink));
}
.pitch-grid{
  display:grid;gap:1.5rem 2.6rem;margin-top:1.9rem;
  grid-template-columns:repeat(auto-fit,minmax(min(320px,100%),1fr));
}
.pitch-close{
  margin:1.9rem 0 0;padding-top:1.25rem;max-width:56ch;
  border-top:2px solid var(--s-accent,var(--navy));
  font-size:var(--fs-lead);color:var(--s-ink,var(--ink));
}


/* ============================================================
   PREMIUM PASS, 2 Sep 2026
   Measured first: type was already right (18/29 body at 1440).
   What read as cheap was flat imagery, a uniform 216px void
   between sections, prose in caption grey, and a form squashed
   five-across. Fixed as one system, not five patches.
   ============================================================ */

/* --- 1. anything that exists for the client review only --- */
body:not(.is-preview) .hold,
body:not(.is-preview) .holds-row,
body:not(.is-preview) .hold--tag,
body:not(.is-preview) .proj-hold,
body:not(.is-preview) .svc-hold{display:none !important}

/* --- 2. one image system -------------------------------------
   Sharp corners stay (the identity is editorial, not rounded-lg),
   but every photograph now sits on an offset plate that echoes
   the stacked bars of the mark, with a soft lifted shadow. The
   plate colour follows the band so it works on paper and navy. */
:root{
  /* --sky on white measured 1.05:1 and vanished. This navy-tinted tone sits at
     ~1.27:1: present as a plate, quiet enough not to compete with the photo. */
  --plate:#DCE4EE;
  --plate-off:18px;
  --img-shadow:0 1px 2px rgba(10,25,54,.07),0 26px 48px -24px rgba(10,25,54,.34);
}
.band--alt{--plate:#CBD6E4}
.band--navy,.band--deep,.hero.hero--navy{--plate:var(--navy-raised);--img-shadow:0 1px 2px rgba(0,0,0,.2),0 26px 48px -20px rgba(0,0,0,.55)}
.hero-figure,
.split img,
.band-img{
  border-radius:2px;
  box-shadow:var(--plate-off) var(--plate-off) 0 0 var(--plate),var(--img-shadow);
}
.hero-figure{margin-right:var(--plate-off);margin-bottom:var(--plate-off)}
.split img{margin-bottom:var(--plate-off)}
.proj{border-radius:2px;box-shadow:0 1px 2px rgba(10,25,54,.05)}
@media (hover:hover) and (pointer:fine){ .proj:hover{box-shadow:var(--img-shadow)} }
.pcard--img img,.pcard--link img{border-radius:2px 2px 0 0}
@media (max-width:820px){ :root{--plate-off:14px} }

/* --- 3. calls to action carry a little more weight ---------- */
#main .btn,.endcta .btn,.hero .btn{
  font-size:var(--fs-small);letter-spacing:var(--track-nav);padding:.95rem 1.7rem;min-height:48px;
  transition:background .18s ease,color .18s ease,transform .18s cubic-bezier(.22,1,.36,1),box-shadow .18s ease;
}
@media (hover:hover) and (pointer:fine){
  #main .btn:not(.btn--line):hover,.endcta .btn:hover{transform:translateY(-1px);box-shadow:0 10px 24px -12px rgba(196,157,61,.7)}
}

/* --- 4. the bid form: two columns, not five ------------------ */
.form{max-width:820px;grid-template-columns:repeat(auto-fit,minmax(min(300px,100%),1fr));gap:1.2rem 1.5rem}
.f{gap:.5rem}
.f label{font-size:var(--fs-micro);letter-spacing:var(--track-label)}
.f input,.f select,.f textarea{
  min-height:48px;padding:.8rem .95rem;font-size:var(--fs-body);border-radius:2px;
  transition:border-color .15s ease,box-shadow .15s ease;
}
.f input:focus,.f select:focus,.f textarea:focus{outline:0;border-color:var(--gold-dark);box-shadow:0 0 0 3px var(--gold-wash)}
.f textarea{min-height:150px}
.f select{
  background-image:linear-gradient(45deg,transparent 50%,var(--ink-soft) 50%),linear-gradient(135deg,var(--ink-soft) 50%,transparent 50%);
  background-position:calc(100% - 20px) 55%,calc(100% - 14px) 55%;background-size:6px 6px,6px 6px;background-repeat:no-repeat;padding-right:2.4rem;
}

/* --- 5. logos and inner-page heroes get a touch more presence - */
.logos .logo-img{height:60px}
@media (max-width:820px){ .logos .logo-img{height:46px} }
.phero .lede{font-size:var(--fs-lead)}

/* --- 6. the 53-tile wall is two-up on a phone, not a 53-row list */
@media (max-width:640px){
  /* On a phone the headline wraps mid-clause, so the gold phrase starts partway
     along a line and reads as a stray colour change rather than a second
     thought. Give it its own line. */
  .hero h1 em{display:block}
  /* ============================================================
     CARD DENSITY ON PHONES
     ------------------------------------------------------------
     Measured at 390px before this block: a property card was
     168.6px wide with 12.8px of padding a side and a further
     17.6px inside .pcard-body, so the photo came out 141px, only
     36% of the screen, and the text block below it was taller
     than the picture.

     The root cause was this rule. `.pcard--img{padding:0}` exists
     precisely so a photographed card runs its image to the card
     edge, but a bare `.pcard` override here has the same
     specificity and comes later in the file, so it put the
     padding back and inset every image by 12.8px a side.
     Scope it to the cards that actually need it.
     ============================================================ */
  .pwall{grid-template-columns:repeat(2,minmax(0,1fr));gap:.5rem}
  .pcard--noimg{padding:.8rem .75rem .9rem}
  .pcard--img{padding:0}
  .pcard--img .pcard-body{padding:.6rem .7rem .75rem;gap:.15rem}
  .pcard-name{font-size:var(--fs-small)}

  /* A quote card gave a quarter of a 346px screen to its own margins. */
  .ref{padding:1.1rem 1rem;min-height:0}
  .ref .q{padding-left:1.1rem}

  /* Same story on the other padded blocks, in proportion. .dsvc > li carries no
     padding of its own, so it is deliberately not in this list. */
  .svc article{padding:1.15rem 1rem}
  .cost article{padding:1.2rem 1rem}
}

/* The page gutter is 44px total, 11% of a 390px screen, and it applies to
   every band. Narrow it on small phones so the content, not the margin, gets
   the width back. */
@media (max-width:480px){
  :root{--shell:min(1260px,calc(100% - 1.75rem))}
}

/* --- 7. reduced motion keeps every visual, drops the movement -- */
@media (prefers-reduced-motion:reduce){
  #main .btn,.endcta .btn,.hero .btn{transition:none;transform:none !important}
}

/* --- bid form: honeypot, and the states a submit can end in ---------- */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.formnote{
  margin:0 0 1.4rem;padding:.9rem 1.1rem;max-width:56ch;border-left:3px solid;
  font-size:var(--fs-body);
}
.formnote--ok{border-color:#0A7D33;background:#F1F8F3;color:#14331F}
.formnote--err{border-color:#9A2515;background:#FCF3F1;color:#5A160C}
.sent--ok{color:#0A7D33}
.sent--err{color:#9A2515}

/* --- keyboard focus, visible on every surface ------------------------
   There were two :focus-visible rules in the whole stylesheet, so most
   controls fell back to the browser default, which is close to invisible
   on the navy bands. One ring, drawn in the surface's own accent. */
:where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{
  outline:2px solid var(--s-accent,var(--gold-dark));
  outline-offset:2px;border-radius:1px;
}
.band--navy :focus-visible,.band--deep :focus-visible,
.top :focus-visible,.foot :focus-visible,.ticker :focus-visible{
  outline-color:var(--gold-lift);
}

/* --- print: an asset manager files the capabilities page -------------
   Drop the furniture, keep the facts, and expose link targets so a
   printed page still says where it pointed. */
@media print{
  .top,.nav,.ticker,.endcta,.foot,.progress,.grain,.btn,.filters,
  .draft,.skip,.hold,.holds-row,.formnote,.form{display:none !important}
  html,body{background:#fff !important;color:#000 !important;font-size:11pt}
  .band,.phero,.hero{padding-block:.6rem !important;background:#fff !important;color:#000 !important}
  .shell{width:100% !important}
  h1{font-size:20pt}h2{font-size:14pt}h3{font-size:12pt}
  h1,h2,h3,tr,figure,.pcard{break-inside:avoid;page-break-inside:avoid}
  a{text-decoration:none;color:#000}
  .prose a[href^="http"]::after,.captable a[href^="http"]::after{content:" (" attr(href) ")";font-size:9pt;word-break:break-all}
  img{max-width:52% !important;box-shadow:none !important;filter:grayscale(1)}
  .pwall{grid-template-columns:repeat(3,1fr) !important;gap:.3rem !important}
  .captable th,.captable td{padding:.25rem .4rem !important}
  @page{margin:14mm}
}

/* --- a card with no photograph yet ----------------------------------
   Occupies the same 3:2 block a photo would, carrying the stacked-bar
   mark from the logo, so a partly-photographed wall still reads as one
   grid rather than as holes in it. */
.pcard--noimg .pcard-plate{
  display:block;width:100%;aspect-ratio:3/2;
  background:
    repeating-linear-gradient(90deg,
      var(--s-accent,var(--navy)) 0 3px, transparent 3px 9px)
      center/54px 26px no-repeat,
    var(--s-bg,var(--paper-alt));
  opacity:.32;
  border-bottom:1px solid var(--s-line,var(--rule));
}
.band--alt .pcard--noimg .pcard-plate{background-color:#E4EBF3}

/* --- responsive images keep their CSS aspect ratio -------------------
   The page-wide upgrade filter adds width/height attributes so the browser
   can reserve space (good for CLS). Those attributes map to a presentational
   `height`, which outranks `aspect-ratio` and rendered the 4:3 hero as a
   528x1050 portrait. height:auto hands sizing back to aspect-ratio while
   keeping the attributes doing their job. */
.hero-figure img,
.split img,
.band-img,
.proj > img,
.proj .thumbs img,
.pcard--img img,
.pcard--link img,
.portrait{height:auto}

/* Closing CTA: question plus what happens next */
.endcta .endcta-copy{display:grid;gap:.8rem;max-width:44rem}
.endcta .endcta-copy h2{max-width:24ch;margin:0}
.endcta .endcta-copy p{margin:0;color:var(--on-navy-soft);font-size:var(--fs-body);line-height:1.6;max-width:52ch}

/* Phil's line. The cost section's verdict, set as the biggest type on the band. */
.pitch-close.pitch-close--big{
  margin:2.6rem 0 0;padding-top:1.9rem;max-width:22ch;
  font-family:var(--font-display);font-weight:400;
  font-size:clamp(2.25rem,1.35rem + 3.2vw,4.25rem);
  line-height:var(--lh-display);letter-spacing:var(--track-display);text-wrap:balance;
  border-top-width:3px;
}
.pitch-close--big span,.pitch-close--big em{display:block}
.pitch-close--big em{font-style:italic;color:var(--gold)}
