@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 300;
  font-stretch: 125%;
  font-display: swap;
  src: url(../fonts/f01.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 900;
  font-stretch: 125%;
  font-display: swap;
  src: url(../fonts/f01.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(../fonts/f02.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(../fonts/f03.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 400;
  font-stretch: 100%;
  font-display: swap;
  src: url(../fonts/f04.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 500;
  font-stretch: 100%;
  font-display: swap;
  src: url(../fonts/f04.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url(../fonts/f04.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Integral Construction of NY, Design DNA v1.1
   Paper, ink, one redline. The brand looks like the contract documents.
   2026-08-28: trialled Benjamin Moore 705 Sioux Falls at Dwayne's request, then put
   back on his written instruction ("Put back the red"). The redline stays. */

:root{
  --canvas:#FAFAF7;
  --ink:#121316;
  --steel:#4B4E54;
  --redline:#C1121F;
  /* The screen variant for dark grounds (brand-masters/tokens/integral.tokens.json accentOnDark): #C1121F on Slab fails
     legibility, so slab surfaces draw the redline in this lift. The artwork itself is never recoloured. */
  --redline-dark:#E4606A;
  --manila:#DCC89E;
  --slab:#1A1B1E;

/* ── THE DISPLAY SCALE ────────────────────────────────────────────────────────────────────────
   Seven steps, replacing twenty-two. Nine of the old twenty-two lived in style="" attributes in
   the HTML rather than here, four sat within 4px of each other at 1440 where the eye cannot tell
   them apart, and at 390px the whole hierarchy compressed into 17-48px with eight sizes between
   26 and 34 — so on a phone the page had no top level at all.

   The steps are anchored to sizes this design already used rather than to a ratio picked off a
   chart, so nothing lurches: 118 stays the hero, 88 the section head, 26 the smallest display
   line. What changes is that near-duplicates collapse and the mobile minima separate, which is
   where the hierarchy was being lost.

   Leading is stepped with size, which is the other half of it. One line-height of 1.02 was applied
   from 19px to 118px. Archivo's natural line box is 1.088em, so that reads correct at 86px and
   visibly cramped at 19px, which is exactly where the .svc and .steps headings live.

   The responsive overrides further down are left alone, deliberately. The ≤600px hero sizes carry
   comments recording the device emulation they were measured against; the ≤900px .phead override
   is load-bearing rather than decorative, because at 320px the scale's own t6 minimum of 38px
   clips "Headquarters" in a 282px column. The nav sheet also keeps its own 7vw sizing: it is a
   full-screen overlay, not part of the page's reading hierarchy, and its wrapping was measured
   separately. Widening a 3px gap by inventing a twenty-third number is how this started. */
  --t1:clamp(19px,2vw,26px);    --lh1:1.16;
  --t2:clamp(22px,2.6vw,34px);  --lh2:1.12;
  --t3:clamp(25px,3.2vw,42px);  --lh3:1.08;
  --t4:clamp(28px,4vw,54px);    --lh4:1.05;
  --t5:clamp(31px,4.4vw,66px);  --lh5:1.03;
  --t6:clamp(38px,6vw,88px);    --lh6:1.01;
  --t7:clamp(46px,7.2vw,118px); --lh7:.97;
  /* Without this, a machine set to dark renders the one <select> and the one <input type=date>
     on the contact form in dark UA chrome, inside a cream form. The site is paper and stays
     paper; declaring that is what stops the browser guessing. */
  color-scheme:light;
  --hairline:rgba(75,78,84,.25);
  /* A form field's edge is a UI boundary, not decoration, so WCAG 1.4.11 asks 3:1 and --hairline
     gives 1.49:1 over the canvas. The field background is the same cream as the page, so that
     border is the ONLY thing saying "type here". Kept separate from --hairline so the decorative
     rules on tables and figures stay as light as they were drawn. .72 measures 3.42:1 in the browser, which leaves room for a future tweak. */
  --field-line:rgba(75,78,84,.72);
  --hairline-light:rgba(250,250,247,.22);
  --display:'Archivo',sans-serif;
  --body:'IBM Plex Sans',sans-serif;
  --mono:'IBM Plex Mono',monospace;
}
*{margin:0;padding:0;box-sizing:border-box}



/* The 64px sticky bar covers anything scrolled flush to the top, which is exactly what happens
   tabbing backwards: a 19.8px project-nav link ends up entirely underneath it. Worse at 400% zoom,
   where the bar is a quarter of the viewport height. */
html{scroll-padding-top:80px}
html{scroll-behavior:smooth}
body{background:var(--canvas);color:var(--ink);font-family:var(--body);font-size:16px;line-height:1.65;-webkit-font-smoothing:antialiased}
::selection{background:var(--redline);color:var(--canvas)}
:focus-visible{outline:2px solid var(--redline);outline-offset:3px}
/* Redline on the slab is 2.77:1 where the ring needs 3:1, so on every dark ground the focus
   indicator was effectively invisible: roughly twenty links a page, including all seven footer
   links, every project card and the primary call to action. Canvas on slab is 16.47:1. The offset
   puts slab on both sides of the ring, so recolouring the outline is enough. */
.dark :focus-visible,.clients :focus-visible,.projects :focus-visible,.cta :focus-visible,footer :focus-visible{outline-color:var(--canvas)}
/* Skip link, visible only when focused, so a keyboard or screen-reader user can
   get past the header on every page. */

/* Named steps for the markup to use instead of style="font-size:…". Every heading on the site now
   names a step, so a size changes in one place and the set stays a set. */
.t1{font-size:var(--t1);line-height:var(--lh1)}
.t2{font-size:var(--t2);line-height:var(--lh2)}
.t3{font-size:var(--t3);line-height:var(--lh3)}
.t4{font-size:var(--t4);line-height:var(--lh4)}
.t5{font-size:var(--t5);line-height:var(--lh5)}
.t6{font-size:var(--t6);line-height:var(--lh6)}
.t7{font-size:var(--t7);line-height:var(--lh7)}

/* This exact declaration was repeated inline on twelve pages: the mono line under a call to
   action. Twelve copies of one component is how a component ends up edited on eleven pages. */
.ctanote{font-family:var(--mono);font-size:13px;letter-spacing:.1em;margin-top:26px;color:rgba(250,250,247,.6)}
.skip{position:absolute;left:-9999px;top:0;z-index:200;background:var(--ink);color:var(--canvas);
  font-family:var(--mono);font-size:12px;letter-spacing:.1em;text-transform:uppercase;
  padding:12px 18px;text-decoration:none}
.skip:focus{left:6px;top:6px}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}.rv{opacity:1!important;transform:none!important;transition:none!important}.pcard img,.hero-fig img,.figframe img,.gal img,.pdetail-hero img,.field-break img,.portrait img,.btn,a,.clog img,.filelist .bar span,form button{transition:none!important}}
img{display:block;max-width:100%}
/* <picture> is a wrapper for format negotiation only. display:contents removes it from
   layout entirely, so every existing `.something img {...}` rule keeps applying exactly
   as it did when the img was a direct child. */
picture{display:contents}
a{color:inherit}

/* ---------- primitives ---------- */
.sheet{position:relative;padding:120px 6vw}
.sheet.tight{padding:80px 6vw}
.tblock{position:absolute;top:0;right:6vw;z-index:2;display:flex;border:1px solid var(--hairline);border-top:none;font-family:var(--mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--steel);background:inherit}
.tblock span{padding:9px 14px}
.tblock span+span{border-left:1px solid var(--hairline)}
.tblock .no{font-weight:500;color:var(--ink)}
.dark .tblock{border-color:var(--hairline-light);color:rgba(250,250,247,.55)}
.dark .tblock span+span{border-left-color:var(--hairline-light)}
.dark .tblock .no{color:var(--canvas)}
.eyebrow{font-family:var(--mono);font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--steel);display:block;margin-bottom:22px}
.dark .eyebrow{color:rgba(250,250,247,.5)}
.wpair{font-family:var(--display);font-stretch:125%;text-transform:uppercase;letter-spacing:.04em;line-height:1.02;overflow-wrap:break-word}
.wpair .hv{font-weight:900}
.wpair .lt{font-weight:300}
.btn{display:inline-block;font-family:var(--mono);font-size:13px;letter-spacing:.12em;text-transform:uppercase;text-decoration:none;padding:10px 4px 12px;color:inherit;border-bottom:2px solid var(--redline);transition:box-shadow .25s ease}
/* Was letter-spacing .12em -> .2em, which reflows the primary call to action on hover and
   animates a property that cannot be composited. Same gesture, no layout shift. */
.btn:hover{box-shadow:inset 0 -10px 0 rgba(193,18,31,.13)}
/* Reveal is an enhancement, never a prerequisite. Without the `js` class
   on <html> these elements are simply visible. */
/* 🔴 A REVEAL MAY NOT HIDE CONTENT AT REST (2026-09-09). This rule read
   `opacity:0;transform:translateY(26px)`. Measured on production at a 1440x900 viewport, three
   seconds after load, scrollY 0: 22 of 22 .rv blocks still computed to opacity 0 — everything
   below y=2306 of an 8505px page. After this change, 0 of 22.

   BE HONEST ABOUT WHO THIS HURT, because the first write-up of it over-claimed and the correction
   belongs next to the fix. Print is not affected (the @media print block below forces these back
   on), reduced-motion is not affected (same, above), Netlify's deploy screenshot is not affected
   (it captures 960x600, the fold only — the before and after images are byte-identical), and a
   reader with working script sees everything as they scroll. What is left is real but narrow: a
   browser whose IntersectionObserver never fires strands the whole page invisible, and any
   full-page programmatic render gets a blank sheet.

   It is fixed anyway, because the resilient version costs nothing. transform does not affect
   layout, so a block that is never revealed sits 26px low and reads perfectly; the slide survives
   and only the fade goes. Lighthouse mobile went 99 to 100 across the change. A design that
   depends on script running correctly to be legible is a design with a failure mode, and this one
   did not have to have one. check-site.py now refuses any `.js`-gated rule setting opacity below 1. */
.js .rv{transform:translateY(26px);transition:transform .7s ease}
.js .rv.in{transform:none}
.d1{transition-delay:.12s}.d2{transition-delay:.24s}.d3{transition-delay:.36s}
.lede{font-size:19px;color:var(--steel);max-width:44ch}
.dark .lede{color:rgba(250,250,247,.65)}
.prose p{color:var(--steel);max-width:46ch}
.prose p+p{margin-top:18px}

/* ---------- nav ---------- */
nav{position:sticky;top:0;z-index:50;background:var(--canvas);border-bottom:1px solid var(--hairline);display:flex;align-items:center;justify-content:space-between;padding:0 6vw;height:64px}
.brand{font-family:var(--display);font-stretch:125%;text-transform:uppercase;font-size:15px;letter-spacing:.04em;text-decoration:none;color:var(--ink);white-space:nowrap}
.brand b{font-weight:900}.brand span{font-weight:300}
nav ul{display:flex;gap:32px;list-style:none;align-items:center}
nav ul a{font-family:var(--mono);font-size:12px;letter-spacing:.1em;text-transform:uppercase;text-decoration:none;color:var(--steel);padding:22px 0;position:relative;display:block}
nav ul a.on{color:var(--ink)}
nav ul a.on::after{content:"";position:absolute;left:0;right:0;bottom:14px;height:2px;background:var(--ink)}
nav ul a:hover{color:var(--ink)}
nav .navcta{color:var(--ink)}
/* The header is on every page, so it never competes with the page's one redline (DNA: once per view). 2026-10-18 audit. */
nav .navcta::after{content:"";position:absolute;left:0;right:0;bottom:14px;height:2px;background:var(--ink)}

/* ---------- index sheet (small screens) ---------- */
.menubtn{
  display:none;font-family:var(--mono);font-size:12px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink);background:none;border:0;
  border-bottom:2px solid var(--ink);padding:4px 2px 5px;cursor:pointer;
}
.navsheet{display:none}
.navsheet[hidden]{display:none}
.navsheet ol{list-style:none;counter-reset:ix}
.navsheet li{counter-increment:ix;border-top:1px solid var(--hairline)}
.navsheet li:last-child{border-bottom:1px solid var(--hairline)}
.navsheet ol a{
  /* minmax(0,1fr), not 1fr: a grid track sized 1fr carries an automatic MIN-CONTENT floor, and the
     longest unbreakable word sets that floor. PREQUALIFICATION therefore held the column open at its
     own full width and overflowed the sheet no matter what wrapping the text was allowed — which is
     why hyphens alone did nothing. Letting the track shrink below min-content is what lets the
     wrapping rules below actually apply. */
  display:grid;grid-template-columns:auto minmax(0,1fr);gap:22px;align-items:baseline;
  text-decoration:none;padding:22px 2px;
  font-family:var(--display);font-stretch:125%;font-weight:300;
  text-transform:uppercase;letter-spacing:.05em;font-size:clamp(24px,7vw,34px);
  /* PREQUALIFICATION is one unbreakable 16-character word. At 375px it wants 383px inside a 330px
     box and was being clipped mid-word — "PREQUALIFICATIO" — on the commonest phone width. The type
     is not shrunk to fix it: SUPPLIER DIVERSITY and SEND US THE DRAWINGS already wrap to two lines
     here, so a hyphenated break is what this list does anyway. hyphens needs the lang attribute,
     which check-site.py already requires on every page. */
  overflow-wrap:break-word;hyphens:auto;
}
.navsheet ol a::before{
  content:counter(ix,decimal-leading-zero);
  font-family:var(--mono);font-weight:400;font-size:12px;letter-spacing:.1em;color:var(--steel);
}
.navsheet ol a[aria-current="page"]{font-weight:900}
.navsheet ol a[aria-current="page"]::before{color:var(--redline)}
.sheettop{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:64px;margin-bottom:6vh}
.sheettop .brand{font-size:clamp(11.5px,3.4vw,15px);min-width:0}
.sheetclose{flex:0 0 auto}
.sheetfoot{
  font-family:var(--mono);font-size:12px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--steel);margin-top:6vh;line-height:2;
}

/* ---------- page header ---------- */
.phead{border-bottom:1px solid var(--hairline);padding:96px 6vw 72px;position:relative}
.phead h1{font-size:var(--t6);line-height:var(--lh6)}
.phead .lede{margin-top:26px}
.crumb{font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--steel);margin-bottom:22px}
.crumb a{text-decoration:none}
.crumb a:hover{color:var(--ink)}

/* ---------- home hero ---------- */
.hero{min-height:calc(100vh - 64px);display:grid;grid-template-columns:minmax(0,6.5fr) minmax(0,5fr);gap:5vw;align-items:center;border-bottom:1px solid var(--hairline);padding-top:80px;padding-bottom:80px}
.hero h1{font-family:var(--display);font-stretch:125%;text-transform:uppercase;letter-spacing:.04em;line-height:var(--lh7);font-size:var(--t7);font-weight:900}
/* t4, not t5. This is the word "Construction" — twelve characters that cannot break, inside a
   fixed grid column. It was clamp(28px,4vw,64px) and fitted; mapping it to a 4.8vw step made it
   20% larger in the mid range and it ran 78px past its column at 1280. Caught by measuring
   scrollWidth against clientWidth, not by looking at it. t4 keeps the 4vw the column was sized
   around. */
.hero h1 .lt{font-weight:300;display:block;font-size:var(--t4);letter-spacing:.04em;margin-top:8px}
/* The hero carries the lockup itself, the brand's primary mark, never the name re-typeset in Archivo (DNA marks.never;
   Mark 2026-10-18: "her wordmark needs to follow the brand"). OF NY sits under CONSTRUCTION because that is the artwork.
   Clear space is one I-height, about 4.2% of the lockup's width, kept on every side; the screen floor is 220px. */
.hero .hero-mark{margin:0;line-height:0}
.hero .hero-mark img{display:block;width:100%;max-width:780px;min-width:220px;height:auto;aspect-ratio:1928/223;padding:1.2% 0}
.hero .tagline{font-family:var(--display);font-stretch:125%;font-weight:300;font-size:var(--t2);line-height:1.25;margin-top:6vh;max-width:520px}
.hero .tagline em{font-style:normal;font-weight:900;text-transform:uppercase;letter-spacing:.04em}
.hero .tagline .rl{box-shadow:inset 0 -3px 0 var(--redline)}
.hero .sub{max-width:400px;color:var(--steel);font-size:15px;margin-top:26px}
.hero-fig{position:relative;border:1px solid var(--hairline);padding:14px;background:var(--canvas)}
.hero-fig img{width:100%;aspect-ratio:4/4.6;object-fit:cover;filter:grayscale(1) contrast(1.04);transition:filter .5s ease}
.hero-fig:hover img{filter:none}
.hero-fig figcaption{position:absolute;left:14px;bottom:14px;right:14px;display:flex;justify-content:space-between;background:rgba(18,19,22,.82);color:var(--canvas);font-family:var(--mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;padding:9px 14px}

/* ---------- work strip ---------- */
.clients{background:var(--slab);color:var(--canvas);padding:64px 6vw 72px;border-bottom:1px solid var(--hairline)}
.clients ul{list-style:none;display:flex;flex-wrap:wrap;gap:18px 0;align-items:baseline}
.clients li{font-family:var(--display);font-stretch:125%;font-weight:300;text-transform:uppercase;letter-spacing:.04em;font-size:var(--t1);color:rgba(250,250,247,.82)}
/* Separator sits BEFORE each item except the first, so it can never be left
   dangling at the end of a wrapped line. */
/* Separators TRAIL each item (::after on all but the last) rather than lead the next one.
   With a leading ::before, a wrapped line opened with "/ Name" while the first line opened
   flush -- Dwayne read it as "Art Basel is outdented and the rest are aligned" (9/1 call,
   on his phone). Trailing slashes leave every wrapped line starting on a word. */
.clients li:not(:last-child)::after{content:"/";font-family:var(--mono);color:rgba(250,250,247,.28);margin:0 22px;font-size:.75em}
.clients a{color:inherit;text-decoration:none}
.clients a:hover,.clients a:focus-visible{color:var(--canvas);text-decoration:underline;text-underline-offset:6px;text-decoration-thickness:1px}

/* ---------- two-column ---------- */
.split{display:grid;grid-template-columns:minmax(0,4fr) minmax(0,7fr);gap:6vw;align-items:start}
.split.even{grid-template-columns:1fr 1fr}
.figframe{border:1px solid var(--hairline);padding:12px}
.figframe img{width:100%;object-fit:cover}
.figframe img,.gal img,.pdetail-hero img,.field-break img,.portrait img{filter:grayscale(1) contrast(1.04);transition:filter .5s ease}
.figframe:hover img,.gal figure:hover img,.pdetail-hero:hover img,.field-break:hover img,.portrait:hover img{filter:none}
.figframe figcaption{font-family:var(--mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--steel);padding:10px 4px 2px;display:flex;justify-content:space-between;gap:12px}
.sticky{position:sticky;top:96px}

/* ---------- fact list ---------- */
.facts{margin-top:44px;border-top:1px solid var(--hairline);display:grid;grid-template-columns:repeat(2,1fr);max-width:660px}
.facts div{padding:18px 22px 18px 0;border-bottom:1px solid var(--hairline);font-size:14px}
.facts dt{font-family:var(--mono);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--steel);margin-bottom:4px}
.facts dd{font-weight:500}

/* ---------- services ---------- */
.services{background:rgba(220,200,158,.16);border-top:1px solid var(--hairline);border-bottom:1px solid var(--hairline)}
.svc{display:grid;grid-template-columns:auto minmax(0,4fr) minmax(0,6fr);gap:4vw;align-items:start;padding:54px 0;border-top:1px solid var(--hairline)}
.svc:first-of-type{border-top:none}
.svc .num{font-family:var(--mono);font-size:13px;color:var(--steel);padding-top:10px;letter-spacing:.06em}
/* t2, not t3. These headings are service names, and the truth pass correctly joined
   "Preconstruction" into the single fifteen-character word it always was. One unbreakable word in
   a 403px column cannot take a 3.2vw step: at 1280 it wanted 442px. t2 is the step the old
   2.65vw sizing actually landed on. */
.svc h2,.svc h3{font-size:var(--t2);line-height:var(--lh2)}.svc h2 .hv,.svc h2 .lt,.svc h3 .hv,.svc h3 .lt{display:inline-block}
.svc p{color:var(--steel);max-width:44ch}
.svc ul{list-style:none;margin-top:18px;display:flex;flex-wrap:wrap;gap:10px}
.svc ul li{font-family:var(--mono);font-size:12px;letter-spacing:.05em;text-transform:uppercase;border:1px solid var(--hairline);padding:6px 12px;color:var(--steel)}

/* ---------- field break ---------- */
.field-break{position:relative;height:56vh;overflow:hidden;border-bottom:1px solid var(--hairline)}
.field-break img{width:100%;height:100%;object-fit:cover;object-position:center 40%}
.field-break .cap{position:absolute;left:6vw;bottom:32px;background:var(--canvas);border:1px solid var(--hairline);font-family:var(--mono);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--steel);padding:10px 16px}

/* The Services photo, square and smaller (Dwayne 2026-10-18: it looked stretched across the full width; "put it back
   square and make it smaller to have it more clear"). The source is 1248 by 1200, so it is shown at its own proportions
   in a framed sheet with its caption underneath, not cropped into a band. */
.field-break.sq{height:auto;display:block;overflow:visible;padding:56px 6vw}
.field-break.sq picture{display:block;width:min(520px,100%);aspect-ratio:1/1;border:1px solid var(--hairline);padding:12px;background:var(--canvas);box-sizing:border-box}
.field-break.sq img{width:100%;height:100%;object-fit:cover;object-position:center;display:block}
.field-break.sq .cap{position:static;display:inline-block;margin-top:16px}

/* ---------- projects ---------- */
.projects{background:var(--slab);color:var(--canvas)}
.pgrid{display:grid;grid-template-columns:repeat(12,1fr);gap:26px}
.pcard{position:relative;text-decoration:none;color:inherit;display:block;min-width:0}
.pcard .pimg{overflow:hidden;border:1px solid var(--hairline-light)}
.projects .pcard .pimg{border-color:var(--hairline-light)}
.pcard img{width:100%;height:100%;object-fit:cover;filter:grayscale(1) contrast(1.02);transition:filter .5s ease,transform .6s ease}
.pcard:hover img{filter:none;transform:scale(1.025)}

/* ---------- client logos ---------- */
.clientlogos{background:var(--canvas)}
/* A-104 Client Record: the logo grid read as a drawing sheet. Grid bubbles name every cell (A1, B3),
   pointing at a client runs a redline crosshair through its row and column, and the readout below
   prints its reference. Without JS it is the plain grid with sectors, nothing hidden. */
.crhead{display:flex;justify-content:space-between;align-items:baseline;gap:20px;flex-wrap:wrap;margin-bottom:22px}
.crhead .eyebrow{margin-bottom:0}
.crcount{font-family:var(--mono);font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--steel);font-variant-numeric:tabular-nums}
.crcount b{font-weight:500;color:var(--ink)}.crcount span{color:rgba(250,250,247,.4);margin:0 6px}
.crsheet{position:relative}
.crsheet.live{padding:40px 0 0 40px}
.crx,.cry{position:absolute;inset:0;pointer-events:none}
.crx i,.cry i{position:absolute;width:26px;height:26px;margin:-13px 0 0 -13px;border:1px solid var(--field-line);border-radius:50%;display:flex;align-items:center;justify-content:center;font:500 11px/1 var(--mono);font-style:normal;color:var(--steel);background:var(--canvas);transition:background .25s ease,color .25s ease,border-color .25s ease}
.crx i{top:14px}.cry i{left:14px}
.crx i::after,.cry i::after{content:"";position:absolute;background:var(--hairline)}
.crx i::after{top:25px;left:50%;width:1px;height:14px}.cry i::after{left:25px;top:50%;height:1px;width:14px}
.crx i.hit,.cry i.hit{background:var(--redline);border-color:var(--redline);color:var(--canvas)}
.clogrid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1px;background:var(--hairline);border:1px solid var(--hairline);list-style:none;margin:0;padding:0}
.clog{background:var(--canvas);aspect-ratio:3/2;position:relative;display:flex}
.clog>a{display:flex;flex:1;color:inherit;text-decoration:none}
.clog picture,.clog>a picture{flex:1;display:flex;align-items:center;justify-content:center;padding:30px 26px}
.clog img{max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain;filter:grayscale(1) opacity(.72);transition:filter .4s ease}
.clog.line img{filter:grayscale(1) opacity(.9)}
.cword{flex:1;display:flex;align-items:center;justify-content:center;padding:30px 26px;font-family:var(--display);font-stretch:125%;font-weight:300;text-transform:uppercase;letter-spacing:.04em;font-size:clamp(20px,2.4vw,34px);color:var(--steel);text-align:center;transition:color .4s ease}
.clog:hover .cword,.clog.hit .cword{color:var(--ink)}
/* The typeset clients close the grid. Whatever the column count, the last row is filled by stretching a cell instead of leaving a hole. */
@media (min-width:901px){.clogrid li:last-child:nth-child(4n+1){grid-column:1/-1;aspect-ratio:auto;min-height:130px}.clogrid li:last-child:nth-child(4n+3){grid-column:span 2;aspect-ratio:auto;min-height:130px}.clogrid li:last-child:nth-child(4n+2){grid-column:span 3;aspect-ratio:auto;min-height:130px}}
@media (min-width:601px) and (max-width:900px){.clogrid li:last-child:nth-child(3n+1){grid-column:1/-1;aspect-ratio:auto;min-height:130px}.clogrid li:last-child:nth-child(3n+2){grid-column:span 2;aspect-ratio:auto}}
@media (max-width:600px){.clogrid li:last-child:nth-child(2n+1){grid-column:1/-1;aspect-ratio:auto;min-height:110px}}
.cword.sm{font-size:clamp(15px,1.7vw,24px);line-height:1.25;white-space:normal;overflow-wrap:anywhere}
@media (max-width:600px){.cword.sm{white-space:normal;font-size:14px}}
.clog.hit img,.clog:hover img{filter:none}
.cref,.csec,.cgo{position:absolute;font-family:var(--mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;line-height:1}
.cref{top:10px;left:10px;color:var(--steel)}
.csec{bottom:10px;left:10px;right:10px;color:var(--steel);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cgo{top:10px;right:10px;color:var(--redline);opacity:0;transform:translateX(-4px);transition:opacity .25s ease,transform .25s ease}
.clog.has::before{content:"";position:absolute;top:0;right:0;border-style:solid;border-width:0 12px 12px 0;border-color:transparent rgba(250,250,247,.6) transparent transparent}
.clog.has.hit .cgo,.clog.has:hover .cgo,.clog.has a:focus-visible .cgo{opacity:1;transform:none}
.clog.has.hit::before{opacity:0}
.clog.hit .cref{color:var(--redline)}
.clog a:focus-visible{outline:2px solid var(--redline);outline-offset:-2px}
.crh,.crv{position:absolute;pointer-events:none;background:var(--redline);opacity:0;transition:opacity .2s ease,transform .35s cubic-bezier(.2,.7,.2,1)}
.crh{left:40px;right:0;top:0;height:1px;transform:translateY(var(--cy,0))}
.crv{top:40px;bottom:0;left:0;width:1px;transform:translateX(var(--cx,0))}
.crsheet.aim .crh,.crsheet.aim .crv{opacity:.55}
.crread{margin-top:16px;font-family:var(--mono);font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--steel);display:flex;gap:14px;align-items:baseline;min-height:1.4em}
.crread .k{color:var(--canvas);background:var(--ink);padding:3px 7px;font-weight:500;font-variant-numeric:tabular-nums}
.crread .v{color:var(--ink)}
@media (max-width:900px){.clogrid{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width:600px){.clogrid{grid-template-columns:repeat(2,minmax(0,1fr))}.cword{padding:28px 8px;font-size:15px;letter-spacing:.03em;white-space:nowrap}.clog picture,.clog>a picture{padding:28px 16px}.crsheet.live{padding:40px 0 0 0}.cry,.crh{display:none}.crread{display:none}.csec{font-size:9px;letter-spacing:.05em;white-space:normal;line-height:1.25}.cgo{display:none}}
@media(prefers-reduced-motion:reduce){.crh,.crv,.cgo,.crx i,.cry i{transition:none}}
.pcard .pmeta{display:flex;justify-content:space-between;align-items:baseline;gap:16px;padding:16px 2px 0}
.pcard .pname{min-width:0;overflow-wrap:anywhere;font-family:var(--display);font-stretch:125%;font-weight:300;text-transform:uppercase;letter-spacing:.04em;font-size:var(--t1);line-height:1.15}
.pcard .pno{font-family:var(--mono);font-size:11px;letter-spacing:.08em;white-space:nowrap;color:var(--steel)}
.projects .pcard .pno,.projects .pcard .ptype{color:rgba(250,250,247,.56)}
.pcard .ptype{font-family:var(--mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;margin-top:4px;color:var(--steel)}
.pcard .go{font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;margin-top:12px;display:inline-block;border-bottom:1px solid currentColor;padding-bottom:3px}
.p-a{grid-column:1/8}.p-a .pimg{aspect-ratio:16/10}
.p-b{grid-column:8/13;align-self:end}.p-b .pimg{aspect-ratio:4/3.4}
.p-c{grid-column:1/6}.p-c .pimg{aspect-ratio:4/3.4}
.p-d{grid-column:6/13}.p-d .pimg{aspect-ratio:16/9.5}
/* 21:8 against a 3:2 source kept 57%. 2:1 keeps 75% and is still a banner. */
.p-e{grid-column:1/13}.p-e .pimg{aspect-ratio:2/1}
.p-half{grid-column:span 6}.p-half .pimg{aspect-ratio:4/2.9}
@media(hover:none){.pcard img{filter:none}}

/* ---------- project detail ---------- */
.pdetail-hero{border-bottom:1px solid var(--hairline)}
.pdetail-hero img{width:100%;height:min(66vh,620px);object-fit:cover}
.gal{display:grid;grid-template-columns:repeat(2,1fr);gap:26px}
.gal figure{border:1px solid var(--hairline);padding:12px}
.gal img{width:100%;aspect-ratio:4/3;object-fit:cover}
.gal figcaption{font-family:var(--mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--steel);padding:10px 4px 2px}
.gal .wide{grid-column:1/-1}
/* 🔴 THE CROPS WERE DISCARDING THE EVIDENCE. Fixed 2026-09-07.
   21:9 is a cinema ratio and none of these photographs is one: the sources are 3:2, 1.41 and
   4:3, so the box was cutting 36 to 43 percent off the top and bottom of every wide figure —
   which on an interiors job is the ceiling and the floor, the two planes a fit-out contractor
   is actually judged on. 16:9 keeps 75 to 84 percent of the same frames. */
.gal .wide img{aspect-ratio:16/9}
/* Four photographs are portrait (2:3) and sat in the 4:3 box, where object-fit:cover threw away
   exactly half of each one, centred, top and bottom. A portrait frame gets a portrait box. */
.gal .tall{grid-column:auto}
.gal .tall img{aspect-ratio:3/4}
.scopelist{list-style:none;margin-top:24px;border-top:1px solid var(--hairline)}
.scopelist li{padding:14px 0;border-bottom:1px solid var(--hairline);display:grid;grid-template-columns:auto 1fr;gap:20px;align-items:baseline;font-size:15px}
.scopelist .k{font-family:var(--mono);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--steel);min-width:120px}
.pnav{display:flex;justify-content:space-between;gap:20px;border-top:1px solid var(--hairline);padding:34px 6vw;font-family:var(--mono);font-size:12px;letter-spacing:.1em;text-transform:uppercase}
.pnav a{text-decoration:none;color:var(--steel)}
.pnav a:hover{color:var(--ink)}

/* ---------- credentials ---------- */
.creds{background:var(--manila);border-bottom:1px solid var(--hairline)}
.creds-grid{display:grid;grid-template-columns:minmax(0,5fr) minmax(0,6fr);gap:6vw;align-items:center}
.creds h2{font-size:var(--t5);line-height:var(--lh5)}
.creds p{margin-top:22px;color:var(--ink);max-width:46ch}
.cred-block{border:1px solid var(--ink);position:relative;padding:36px 34px;background:rgba(250,250,247,.4)}
.cred-block::before{content:"";position:absolute;top:10px;left:10px;right:10px;bottom:10px;border:1px solid var(--ink);opacity:.35;pointer-events:none}
.cred-block ul{list-style:none;font-family:var(--mono);font-size:clamp(14px,1.5vw,18px);letter-spacing:.1em;text-transform:uppercase}
.cred-block li{padding:16px 4px;display:flex;justify-content:space-between;gap:20px}
.cred-block li+li{border-top:1px solid rgba(18,19,22,.25)}
.cred-block .ck{font-weight:500}
/* A small link under a program's name, spelling it out (Dwayne 2026-10-18: REAP spelled out, a small link under the
   mention). Mono, steel, the brand's figure face at label size; underlined so it reads as a link without colour. */
.cred-block .ck-sub{display:block;margin-top:3px;font-family:var(--mono);font-weight:400;font-size:11px;letter-spacing:.06em;text-transform:none;color:var(--steel);text-decoration:underline;text-decoration-color:var(--hairline);text-underline-offset:3px}
.cred-block .ck-sub:hover,.cred-block .ck-sub:focus-visible{color:var(--ink);text-decoration-color:var(--ink)}
.cred-stack{display:grid;gap:22px;align-content:start}
.cred-label{display:block;font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--steel);padding:0 4px 4px}
.cred-block.progs{padding:26px 34px 20px}
.cred-block.progs ul{font-size:clamp(12px,1.25vw,15px)}
.cred-block.progs li{text-align:right}
.cred-block.progs li .ck{text-align:left}
.cred-block a{color:var(--ink);text-decoration:underline;text-underline-offset:4px;text-decoration-thickness:1px}
.cred-block a:hover,.cred-block a:focus-visible{text-decoration-color:var(--redline)}

/* ---------- portrait ---------- */
.portrait{border:1px solid var(--hairline);padding:12px}
.portrait img{width:100%;aspect-ratio:4/4.4;object-fit:cover;object-position:top}
.portrait figcaption{font-family:var(--mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--steel);padding:10px 4px 2px;display:flex;justify-content:space-between}
.cv{margin-top:34px;border-top:1px solid var(--hairline);font-size:14px}
.cv div{display:grid;grid-template-columns:minmax(96px,auto) 1fr;gap:22px;padding:13px 0;border-bottom:1px solid var(--hairline)}
.cv dt{font-family:var(--mono);font-size:12px;color:var(--steel);letter-spacing:.05em}
.cv dd{font-weight:500}

/* ---------- numbers ---------- */
.numbers{border-top:1px solid var(--hairline);border-bottom:1px solid var(--hairline);padding:0 6vw;display:grid;grid-template-columns:repeat(3,1fr)}
.numbers>div{padding:64px 34px;border-left:1px solid var(--hairline)}
.numbers>div:first-child{border-left:none;padding-left:0}
.numbers .val{font-family:var(--display);font-stretch:125%;font-weight:900;font-size:var(--t6);line-height:var(--lh6)}
.numbers .lbl{font-family:var(--mono);font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--steel);margin-top:14px}

/* ---------- process ---------- */
.steps{counter-reset:s;border-top:1px solid var(--hairline);margin-top:40px}
.steps li{list-style:none;counter-increment:s;border-bottom:1px solid var(--hairline);padding:28px 0;display:grid;grid-template-columns:auto minmax(0,3fr) minmax(0,6fr);gap:4vw;align-items:baseline}
.steps li::before{content:counter(s,decimal-leading-zero);font-family:var(--mono);font-size:13px;color:var(--steel);letter-spacing:.06em}
.steps h2,.steps h3{font-size:var(--t1);line-height:var(--lh1)}
.steps p{color:var(--steel);max-width:44ch}
/* 404 drawing index: the entries are links and have to look like it. */
.setindex a{text-decoration:none;box-shadow:inset 0 -2px 0 var(--ink);transition:box-shadow .2s ease}
.setindex a:hover,.setindex a:focus-visible{box-shadow:inset 0 -8px 0 var(--redline)}

/* ---------- contact ---------- */
.cgrid{display:grid;grid-template-columns:minmax(0,5fr) minmax(0,6fr);gap:6vw;align-items:start}
.cblock{border-top:1px solid var(--hairline)}
.cblock div{padding:20px 0;border-bottom:1px solid var(--hairline)}
.cblock dt{font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--steel);margin-bottom:6px}
.cblock dd{font-size:17px;font-weight:500}
.cblock dd a,.cv dd a{text-decoration:none;box-shadow:inset 0 -1px 0 var(--hairline)}
.cblock dd a:hover,.cv dd a:hover{box-shadow:inset 0 -2px 0 var(--redline)}
form{border:1px solid var(--hairline);padding:34px}
form label{display:block;font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--steel);margin-bottom:8px}
form input,form textarea,form select{width:100%;font-family:var(--body);font-size:16px;padding:12px 14px;border:1px solid var(--field-line);background:var(--canvas);color:var(--ink);margin-bottom:22px}
form input:focus-visible,form textarea:focus-visible,form select:focus-visible{outline:2px solid var(--redline);outline-offset:2px;border-color:var(--redline)}
form input:focus,form textarea:focus,form select:focus{border-color:var(--redline)}
form textarea{min-height:130px;resize:vertical}
form button{font-family:var(--mono);font-size:13px;letter-spacing:.12em;text-transform:uppercase;background:var(--ink);color:var(--canvas);border:none;padding:15px 30px;cursor:pointer;transition:box-shadow .2s ease}
/* 🔴 A RED-FILLED SUBMIT READS AS DESTRUCTIVE. This is the button that sends a bid set, and
   filling it with the same red that marks an expired certificate says "delete" in every
   convention a visitor arrives with. The redline stays — it is the brand, and the client asked
   for it in writing — but it arrives as the underline this site already uses to mean action
   (.setindex a:hover) rather than as a fill. */
form button:hover{background:var(--ink);box-shadow:inset 0 -5px 0 var(--redline)}

/* ---------- CTA + footer ---------- */
.cta{background:var(--slab);color:var(--canvas)}
.cta h2{font-size:var(--t6);line-height:var(--lh6);max-width:15ch}
.cta .btn{margin-top:40px;color:var(--canvas);font-size:14px}
footer{background:var(--slab);color:rgba(250,250,247,.6);border-top:1px solid var(--hairline-light);padding:56px 6vw 80px;display:flex;flex-wrap:wrap;gap:40px 8vw;justify-content:space-between;font-size:14px}
footer .flogo{height:34px;width:auto}
/* WCAG 2.5.8: the tapped phone number is the conversion on mobile. */
footer .mono a{display:inline-block;padding:6px 0}
/* WCAG 2.5.8 target size, 24x24 minimum. Vertical padding on an INLINE link
   grows the hit area without growing the line box, so none of these reflow.
   Measured before and after: brand 21->29, dl links 18-22->30, 404 index 21->29. */
.brand{padding-block:4px}
.cblock dd a,.cv dd a,.facts dd a{padding-block:6px}
.setindex a{padding-block:4px}
.crumb a{padding-block:6px}
footer a{text-decoration:none}
footer a:hover{color:var(--canvas)}
footer .mono{font-family:var(--mono);font-size:12px;letter-spacing:.08em;text-transform:uppercase;line-height:2.1}
footer nav.fnav{position:static;background:none;border:none;height:auto;padding:0;display:block}
footer .fnav a{display:block;color:rgba(250,250,247,.6)}

/* ---------- responsive ---------- */
@media(max-width:900px){
  .sheet{padding:80px 6vw}
  .sheet.tight{padding:60px 6vw}
  .phead{padding:64px 6vw 52px}
  .phead h1{font-size:clamp(28px,7.6vw,44px)}
  /* 🔴 THE TITLE BLOCK IS THE CONCEIT, AND IT USED TO VANISH HERE. Fixed 2026-09-07.
     display:none below 900px removed the one device that makes this site a drawing set, at
     exactly the width where most of the audience is. What was left without it is a competent
     cream editorial template carrying none of its own apparatus.
     The print stylesheet already solved this — static and inline at the top of the sheet. Same
     move, and it costs about 30px of height. */
  .tblock{position:static;display:flex;flex-wrap:wrap;width:100%;right:auto;margin:0 0 26px;
    border:none;border-bottom:1px solid var(--hairline);font-size:10px;background:none}
  /* Each cell holds together or moves to the next line whole. Without this the flex row shrinks
     the cells instead, and at 320px it broke "G-000" across two lines — a sheet number splitting
     in half is the one thing a title block may never do. */
  .tblock span{padding:0 0 7px;white-space:nowrap}
  .tblock span+span{margin-left:12px;padding-left:12px;border-left:1px solid var(--hairline)}
  .dark .tblock{border-bottom-color:var(--hairline-light)}
  /* No JS: every link stays reachable, wrapped under the wordmark.
     With JS: the list is replaced by the index sheet. */
  nav{height:auto;min-height:64px;flex-wrap:wrap;gap:10px 16px;padding-top:12px;padding-bottom:12px}
  .brand{font-size:clamp(11.5px,3.4vw,15px)}
  nav ul{gap:12px 18px;flex-wrap:wrap}
  nav ul li,nav ul li.mkeep{display:block}
  nav ul a{padding:0}
  nav ul a.on::after{bottom:-5px}
  .js nav ul{display:none /* js-hide-ok: .js .menubtn shows the button that replaces it, so the navigation is never absent, only in a different control */}
  .js .menubtn{display:block}
  .navsheet{
    position:fixed;inset:0;z-index:100;background:var(--canvas);
    display:flex;flex-direction:column;justify-content:safe center;
    padding:24px 6vw 40px;overflow-y:auto;
  }
  .navsheet[hidden]{display:none}
  .hero{grid-template-columns:1fr;gap:52px;padding-top:56px;padding-bottom:64px}
  .hero h1{font-size:clamp(38px,11.5vw,52px)}
  .hero h1 .lt{font-size:clamp(22px,6.4vw,30px)}
    .clients li{white-space:normal}
  .clients li:not(:last-child)::after{margin:0 12px}
  .split,.split.even,.creds-grid,.cgrid{grid-template-columns:1fr;gap:44px}
  .sticky{position:static}
  .svc,.steps li{grid-template-columns:1fr;gap:12px;padding:36px 0}
  .numbers{grid-template-columns:1fr}
  .numbers>div{border-left:none;border-top:1px solid var(--hairline);padding:40px 0}
  .numbers>div:first-child{border-top:none}
  .pgrid{grid-template-columns:1fr;gap:40px}
  .p-a,.p-b,.p-c,.p-d,.p-e,.p-half{grid-column:1/-1}
  .p-a .pimg,.p-b .pimg,.p-c .pimg,.p-d .pimg,.p-e .pimg,.p-half .pimg{aspect-ratio:4/3}
  .field-break{height:38vh}
  .field-break.sq{height:auto;padding:40px 6vw}
  .gal{grid-template-columns:1fr}
}
/* 320-360px only (iPhone SE 1st gen, small Androids). The card meta row is a
   flex line of uppercase display type plus a nowrap sector label; below about
   360px the two cannot share a line and the card grew to 357px on a 320px
   viewport, so Home and Projects scrolled sideways. Measured 2026-09-04 with
   Playwright device emulation; 375, 390 and desktop were clean and are not
   touched by this block. */
@media(max-width:360px){
  .pcard .pmeta{flex-direction:column;align-items:flex-start;gap:6px}
  .pcard .pno{white-space:normal}
  .pcard .pname{overflow-wrap:break-word}
  .clients li{overflow-wrap:anywhere}
  .gal .wide img{aspect-ratio:4/3}
  .pdetail-hero img{height:44vh}
  .facts{grid-template-columns:1fr}
  form{padding:24px}
}

/* ---------- Release 2 (2026-09-05): the record as a document, the transmittal, the sheet index ---------- */
/* Every value below is a token already on this sheet; nothing new enters the palette. */
.muted{color:var(--steel)}
.doc .rec{margin-top:26px;border-top:1px solid var(--hairline);max-width:900px}
.doc .rec div{display:grid;grid-template-columns:minmax(150px,220px) 1fr;gap:18px;padding:14px 0;border-bottom:1px solid var(--hairline);font-size:15px;align-items:baseline}
.doc .rec dt{font-family:var(--mono);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--steel)}
.doc .rec dt a{text-decoration:none;box-shadow:inset 0 -1px 0 var(--hairline);color:var(--ink);padding-block:4px}
.doc .rec dt a:hover{box-shadow:inset 0 -2px 0 var(--redline)}
.doc .rec dd{font-weight:500;overflow-wrap:anywhere;min-width:0}
/* Below 600px the two-column record stacks: at 320 the label column plus an email address or a
   UNSPSC code ran 23px past the viewport (measured 2026-09-05, Playwright iPhone SE). */
@media(max-width:600px){.doc .rec div{grid-template-columns:1fr;gap:4px} .fgrid{grid-template-columns:1fr}}
.doc .rec dd a{text-decoration:none;box-shadow:inset 0 -1px 0 var(--hairline);padding-block:4px}
.doc .src{font-family:var(--mono);font-size:11px;letter-spacing:.06em;color:var(--steel);margin-top:14px;max-width:70ch}
.cert{font-family:var(--mono);font-size:12px;letter-spacing:.06em;text-transform:uppercase}
.cert-ok{color:var(--ink)}
/* Status colours are workspace-only (DNA): an expired certificate reads as its word, in ink and heavier, never red. */
.cert-exp{color:var(--ink);font-weight:700}
.reqlist{list-style:none;margin-top:22px;border-top:1px solid var(--hairline);max-width:38ch}
.reqlist li{padding:12px 0;border-bottom:1px solid var(--hairline);font-size:15px}
/* the transmittal */
.fgrid{display:grid;grid-template-columns:1fr 1fr;gap:0 18px}
.drop{border:1px dashed var(--steel);padding:16px;margin-bottom:22px;background:rgba(220,200,158,.10)}
.drop input[type=file]{width:100%;font-family:var(--body);font-size:14px;padding:6px 0;border:0;margin:0;background:none}
.drophint{font-family:var(--mono);font-size:11px;letter-spacing:.05em;color:var(--steel);margin-top:8px;line-height:1.7}
.filelist{list-style:none;margin-top:10px}
.filelist li{display:grid;grid-template-columns:1fr auto auto;gap:6px 14px;align-items:center;padding:10px 0;border-top:1px solid var(--hairline);font-size:14px}
.filelist .fname{font-weight:500;overflow-wrap:anywhere}
.filelist .fsize,.filelist .fstat{font-family:var(--mono);font-size:11px;letter-spacing:.06em;color:var(--steel);white-space:nowrap}
.filelist .bar{grid-column:1/-1;height:3px;background:var(--hairline);display:block}
.filelist .bar span{display:block;height:100%;width:0;background:var(--redline);transition:width .2s ease}
.filelist .frm{grid-column:3;justify-self:end;font-family:var(--mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;background:none;color:var(--steel);border:0;padding:4px 0;cursor:pointer}
.filelist .frm:hover{color:var(--redline)}
.tsbox{margin:0 0 14px}
.tsbox:empty{margin:0}
.fmsg{margin-top:16px;font-size:14px;padding:12px 14px;border-left:3px solid var(--steel);background:rgba(220,200,158,.16)}
.fmsg.bad{border-left-color:var(--ink)}
.receipt{border:1px solid var(--hairline);padding:34px}
.receipt .cblock{margin-top:22px}
/* the sheet index, on every width. The Index button used to exist only below 900px; a drawing set
   has an index at every size, and it is where Prequalification and the revision live. */
.js .menubtn{display:block}
/* "safe" centring, because justify-content:center inside an overflowing scroll container puts the
   overflow ABOVE the scroll origin where no scrollbar reaches it. At 400% zoom the sheet needs
   ~756px in a 256px box, so the brand link and the Close button scroll off the top with no way
   back. safe falls back to flex-start the moment the content would overflow. */
.js .navsheet:not([hidden]){position:fixed;inset:0;z-index:100;background:var(--canvas);display:flex;flex-direction:column;justify-content:safe center;padding:24px 6vw 40px;overflow-y:auto}
@media(min-width:901px){.js .navsheet ol a{font-size:clamp(24px,3.4vw,40px)} .js .menubtn{margin-left:28px}}
[data-rev]{font-family:var(--mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--steel)}
.tblock [data-rev]{color:var(--steel)}
/* On the slab footer, steel is 2.06:1 (Lighthouse, 2026-09-05, every page). The footer's own
   muted tone is the fix, not a new value. */
footer [data-rev]{color:rgba(250,250,247,.6)}
/* ---------- print: every page is a titled sheet ---------- */
@media print{
  nav,.navsheet,.menubtn,.skip,.field-break,.btn,form,.cta{display:none!important}
  .js .rv{opacity:1!important;transform:none!important}
  body{background:#fff;color:#000;font-size:11pt}
  .sheet,.phead{padding:0 0 18pt;border:0}
  .tblock{position:static;display:inline-flex;margin:0 0 10pt;border:1px solid #000;color:#000;background:#fff}
  .tblock .no{color:#000}
  .dark,.projects,.clients{background:#fff!important;color:#000!important}
  .pcard img,.hero-fig img,.figframe img,.portrait img{filter:none}
  footer{background:#fff;color:#000;border-top:1px solid #000;padding:12pt 0 0}
  footer a{color:#000}
  .flogo{filter:invert(1)}
  a[href^="http"]::after{content:""}
  @page{margin:.7in .75in;size:letter}
}

/* ---------- the supplier-diversity calculator (P-202) ---------- */
/* Buyer-side arithmetic. Uses only tokens already on this sheet; the output is
   a sentence rather than a big number, because the number is the buyer's and
   the caveat travels with it. */
.calc{border:1px solid var(--hairline);padding:26px;margin-top:26px;max-width:820px;background:rgba(220,200,158,.10)}
.calcgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:0 18px}
.calc label{display:block;font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--steel);margin-bottom:8px}
.calc div{position:relative}
.calc input{width:100%;font-family:var(--mono);font-size:16px;padding:12px 14px;border:1px solid var(--hairline);background:var(--canvas);color:var(--ink);margin-bottom:0}
.calc input:focus-visible{outline:2px solid var(--redline);outline-offset:2px;border-color:var(--redline)}
.calc .suffix{position:absolute;right:14px;bottom:13px;font-family:var(--mono);font-size:14px;color:var(--steel);pointer-events:none}
.calcout{display:block;margin-top:22px;padding-top:18px;border-top:1px solid var(--hairline);font-size:17px;line-height:1.6;color:var(--ink)}
@media(max-width:700px){.calcgrid{grid-template-columns:1fr;gap:0}.calc input{margin-bottom:18px}.calc .suffix{bottom:31px}}

/* The studio's line, on its own rule across the foot of the client's footer. Same .6 alpha the
   rest of the footer text uses, which measures 6.64:1 on the slab. */
/* The foot of the sheet is a drawing's title block (10/17): three ruled cells, key above value,
   the way the bottom right of every drawing names who drew it and what it runs on. The cells are
   whole links, so each is one tap. Same .6 alpha as the rest of the footer: 6.64:1 on the slab. */
footer .tbfoot{flex-basis:100%;display:grid;grid-template-columns:1.25fr 1fr 1fr;border:1px solid var(--hairline-light);margin-top:6px}
footer .tbc{display:flex;flex-direction:column;gap:6px;padding:18px 22px 20px;line-height:1.35;min-height:0;color:rgba(250,250,247,.6);text-decoration:none;position:relative;transition:background .25s ease,color .25s ease}
footer .tbc+.tbc{border-left:1px solid var(--hairline-light)}
footer .tbk{font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase}
footer .tbv{font-family:var(--display);font-stretch:125%;font-weight:900;font-size:15px;letter-spacing:.04em;color:var(--canvas);display:flex;align-items:center;gap:10px}
footer .tbs{font-family:var(--mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase}
footer .abmark{flex:none;width:22px;height:22px}
footer .tbc:hover{background:rgba(250,250,247,.04);color:var(--canvas)}
footer .tbc::after{content:"";position:absolute;left:-1px;right:-1px;bottom:-1px;height:2px;background:var(--redline-dark);transform:scaleX(0);transform-origin:left;transition:transform .35s ease}
footer .tbc:hover::after,footer .tbc:focus-visible::after{transform:none}
footer .tbarr{display:inline-block;transition:transform .25s ease}
footer .tbin:hover .tbarr{transform:translateX(4px)}
@media (max-width:760px){
  footer .tbfoot{grid-template-columns:1fr}
  footer .tbc+.tbc{border-left:0;border-top:1px solid var(--hairline-light)}
}
@media (prefers-reduced-motion:reduce){footer .tbc,footer .tbc::after,footer .tbarr{transition:none}}
/* Sign in is a door, not a sheet: a hairline sets it apart from the four pages before it. */
nav li.navin{border-left:1px solid var(--hairline);padding-left:32px;margin-left:0}
nav li.navin a{color:var(--steel)}
@media (max-width:900px){nav li.navin{border-left:0;padding-left:0}}
.navsheet .sheetin{display:inline-block;margin-top:14px;padding:6px 0;color:var(--ink);text-decoration:none;border-bottom:2px solid var(--ink)}

/* ---------- interaction states ---------- */
/* The stylesheet had fourteen :hover rules and no :active, :disabled or :invalid at all. Hover
   does not exist on a phone, so on the device most visitors use, nothing on this site
   acknowledged being pressed. */
a:active,button:active,.btn:active,.menubtn:active{opacity:.62}
form button[disabled],form button[aria-busy="true"]{opacity:.5;cursor:progress}
form button[disabled]:hover{background:var(--ink);box-shadow:none}
/* Only after the field has been touched and left: :invalid alone paints every required field red
   before anyone has typed a character. */
form input:not(:placeholder-shown):invalid,form textarea:not(:placeholder-shown):invalid{border-color:var(--ink)}

/* The addressed prequalification package (2026-09-09). A GET form in the sheet header, which must
   NOT inherit the bordered 34px box `form` carries for the contact page: this is one field beside
   a button, not a form somebody fills in. */
.pqform{border:0;padding:0;margin:22px 0 0;max-width:560px}
.pqrow{display:flex;gap:12px;flex-wrap:wrap;align-items:stretch}
.pqrow input{flex:1 1 240px;margin-bottom:0}
/* 🔴 NO .btn ON THIS BUTTON. `.btn` styles a LINK: it sets color:var(--ink) for dark text on the
   page. `form button` sets background:var(--ink) for light text on a dark chip. Put both on one
   element and the text colour equals the background colour exactly - a solid black rectangle with
   the label invisible inside it. That shipped to production on 2026-09-09 and axe passed the page
   with zero violations, which is the clearest illustration this repo has of check-a11y.sh's own
   warning that automated rules find 20-50% of problems. It was found by looking at the page. */
.pqrow button{flex:0 0 auto;white-space:nowrap}
.pqnote{font-family:var(--mono);font-size:11px;letter-spacing:.06em;line-height:1.7;color:var(--steel);margin:10px 0 0}

/* ---------- phones: touch targets and touch color (Mark, 10/17) ---------- */
form input[type=file]{font-size:16px}
@media (max-width:900px){
  .pnav a{display:inline-flex;align-items:center;min-height:44px}
  .clients a{display:inline-block;padding:6px 0}
  /* Links set inside a list or a record row get a full thumb's height (10/17 audit: 19 to 22px). */
  .reqlist li>a,.rec dt a,.scopelist a{display:inline-block;padding:10px 0;margin:-10px 0}
}
@media (max-width:600px){
  /* A project name never breaks inside a word: the sector drops under it instead (10/17: "PARAMOUN T" at 390). */
  .pcard .pmeta{flex-direction:column;align-items:flex-start;gap:6px}
  .pcard .pno{white-space:normal}
  .pcard .pname{overflow-wrap:break-word}
  .csec{font-size:10px}
  .pnav{flex-wrap:wrap;row-gap:4px}
  .pnav a{display:inline-flex;align-items:center;min-height:44px}
  .clients a{display:inline-block;padding:6px 0}
  footer .fnav a,footer a{display:inline-block;min-height:32px;line-height:32px}
  /* inline-block alone ran the seven links together ("HOMESERVICESPROJECTS", 10/17 audit): two columns. */
  footer nav.fnav{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));column-gap:20px}
}
/* No hover on a phone, so a photograph shows its color while it sits in view instead
   (the .tv class is set by the small script at the end of each page). */
@media (hover:none){
  .tv img,.tv.clog img{filter:none!important}
}

/* Square marks (NBC) sit smaller so they carry the same weight as the wide wordmarks. */
.clog[data-name="NBC"] picture{padding:46px 26px}
@media (max-width:600px){.clog[data-name="NBC"] picture{padding:36px 16px}}
/* The narrowest phones (320): QUALIFICATION, the longest half of the index's one long word, needs
   21px to sit on one line after its soft hyphen. */
@media (max-width:360px){.navsheet ol a{font-size:21px}}
/* Desktop footer as four true columns (10/17 audit): as a wrapping flex row, the stamped certification
   dates made the third column wide enough to push contact alone onto a second row at 1440. */
@media (min-width:1000px){
  footer{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,.75fr) minmax(0,1.45fr) minmax(0,1fr);gap:40px 4vw}
  footer .tbfoot{grid-column:1/-1}
}
.nw{white-space:nowrap}
/* The header carries the wordmark artwork itself, not the name typed in Archivo (10/17: the DNA's
   "never re-typeset the mark"). The file is the brand-masters export, byte for byte; the artwork has
   its own clear space, so the image is taller than the letters. */
.brand img{display:block;height:34px;width:auto;margin-left:-11px}
/* Sized so the Index button stays on the same line down to 320 (the art is 11.6 times as wide as tall,
   and its own clear space is a third of its height on the left, which the negative margin takes back). */
@media (max-width:900px){.brand img{height:clamp(17px,5.6vw,30px);margin-left:calc(clamp(17px,5.6vw,30px) * -.33)}}
/* The photographer's credit sits with her photographs, not only in the fact list (Dwayne 10/17: "give Desiree her credit on the pictures"). */
.photocredit{font-family:var(--mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--steel);margin:10px 6vw 0;text-align:right}
.photocredit a{color:inherit;text-decoration:underline;text-underline-offset:3px;padding-block:6px;display:inline-block}
.gal+.photocredit{margin:14px 0 0}

/* ONE REDLINE PER VIEW (DNA, 2026-10-18 audit). A page's one red is its primary button; the home page's is the mark under
   "letter" in the hero, so its buttons are ink. Chrome, status and decoration are never red; hover and focus are the live
   element and stay red. :has() is supported everywhere current; an older browser shows both reds, which is the old look. */
body:has(.hero .tagline .rl) .btn{border-bottom-color:var(--ink)}
/* On a Slab surface the redline is the dark-ground lift. */
.cta .btn,.projects .btn,.dark .btn{border-bottom-color:var(--redline-dark)}
body:has(.hero .tagline .rl) .cta .btn,body:has(.hero .tagline .rl) .dark .btn{border-bottom-color:var(--canvas)}
