/* ============================================================================
   Premier Concrete Solutions — site stylesheet
   ----------------------------------------------------------------------------
   The design tokens below are not invented. They are lifted from the Avada
   theme options in the WordPress backup this site replaces
   (fx73_options -> fusion_options), so the rebuild keeps the brand the client
   already signed off on:

     Main            #1cb9ea   the cyan in the logo mark
     Main Dark       #1598c3   hover/pressed
     Secondary       #58585a   body copy
     Color 8         #2c2c2e   darkest ink, dark section grounds
     Secondary Hover #3e3e40
     Color 9         #f7f9fa   soft section ground
     Color 3         #e5e5e5   hairlines

   Typography set, same source (typography1..4):
     Headings    Plus Jakarta Sans 700, 62px/1.3, capitalize
     Subheadings Plus Jakarta Sans 600, 24px/1.6
     Lead        Plus Jakarta Sans 600, 16px/1.2, capitalize
     Body        Plus Jakarta Sans 300, 17px/1.8

   Avada shipped those sizes as fixed pixels, which is why the old site broke
   awkwardly between breakpoints. Here they are clamp()ed against the viewport
   so the same visual hierarchy holds from 360px up without a media query per
   heading.
   ========================================================================= */

:root {
  /* Brand */
  --pc-cyan:       #1cb9ea;
  --pc-cyan-dark:  #1598c3;
  --pc-cyan-soft:  rgba(28, 185, 234, 0.12);

  /* Ink + neutrals */
  --pc-ink:        #2c2c2e;
  --pc-ink-2:      #3e3e40;
  --pc-grey:       #58585a;
  --pc-grey-mid:   #999999;
  --pc-line:       #e5e5e5;
  --pc-bg-soft:    #f7f9fa;
  --pc-bg-alt:     #f1f1f1;
  --pc-white:      #ffffff;

  /* Type */
  --pc-font: "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
             Arial, Helvetica, sans-serif;

  --pc-h1: clamp(2.35rem, 1.30rem + 4.20vw, 3.875rem); /* -> 62px */
  --pc-h2: clamp(1.75rem, 1.15rem + 3.20vw, 3.125rem); /* -> 50px */
  --pc-h3: clamp(1.375rem, 1.05rem + 1.30vw, 2rem);   /* -> 32px; 40px crowded the h2 */
  --pc-h4: clamp(1.25rem, 1.05rem + 0.80vw, 1.500rem); /* -> 24px */
  --pc-body: 1.0625rem;                                 /*    17px */

  /* Rhythm. One scale, used everywhere, so sections stack predictably. */
  --pc-gap:     1.25rem;
  --pc-gap-lg:  2rem;
  --pc-section: clamp(3.5rem, 2rem + 6vw, 7rem);
  /* In rem, not px, so the wide-screen scale below carries the content column
     with the type instead of leaving it stranded. 77.5rem = the original 1240px. */
  --pc-shell:   77.5rem;
  /* Side gutter: 20px on phones, growing to 48px on desktop. A fixed 20px left
     the logo, hero copy and card edges almost touching the window at 1280. */
  --pc-gutter:  clamp(1.25rem, 4vw, 3rem);
  --pc-radius:  4px;   /* Avada Factory is near-square; concrete, not candy. */

  --pc-shadow:    0 2px 8px rgba(44, 44, 46, 0.06);
  --pc-shadow-lg: 0 18px 48px rgba(44, 44, 46, 0.14);

  --pc-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* ── Very wide screens ─────────────────────────────────────────────────
   Every clamp() above tops out by around 1000px of viewport and the shell is a
   fixed width, so from there up to a 3440px monitor the design stopped growing
   entirely: on the 2985px window this site is being reviewed on, a 1240px page
   sat inside 870px of empty margin either side, with headings the size they are
   on a laptop.

   Scaling the root scales the whole system in one move - type, rhythm, and the
   content column, which is why the widths above are written in rem. Characters
   per line do not change, because the text and the column it sits in grow
   together: the page is the same design seen larger, not a re-wrapped one.
   Nothing below 1800px moves. */
:root {
  /* Written in rem rather than px on purpose. On the root element's own
     font-size, 1rem means the browser's inherited default - so a reader who has
     set their default text larger keeps that, scaled up from their size rather
     than overridden by ours. A px value here would quietly cancel that setting.
     Smooth rather than stepped, so nothing jumps as a window is dragged wider. */
  font-size: clamp(1rem, 1rem + (100vw - 1800px) / 400, 1.25rem);
}

/* ── Reset ────────────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

body {
  margin: 0;
  font-family: var(--pc-font);
  font-weight: 300;
  font-size: var(--pc-body);
  line-height: 1.8;
  color: var(--pc-grey);
  background: var(--pc-white);
  -webkit-font-smoothing: antialiased;
}

img, svg, video { max-width: 100%; height: auto; display: block; }

a { color: var(--pc-cyan-dark); text-decoration: none; }
a:hover { color: var(--pc-cyan); }

h1, h2, h3, h4, h5, h6 {
  font-weight: 700;
  line-height: 1.3;
  color: var(--pc-ink);
  margin: 0 0 .6em;
  letter-spacing: -0.01em;
}
/* Avada set typography1 to text-transform:capitalize, which is fine on the demo's
   two-word headings but turns a real sentence into "Concrete That Holds The
   Schedule And The Spec" — articles and conjunctions capitalised, which is not
   title case, just wrong. Casing is left to the copy instead. */
h1 { font-size: var(--pc-h1); }
h2 { font-size: var(--pc-h2); }
h3 { font-size: var(--pc-h3); line-height: 1.4; }
h4 { font-size: var(--pc-h4); font-weight: 600; line-height: 1.6; }

/* Headings were the most visible flaw on the site: at nearly every width some
   heading dropped one or two words onto a line of their own ("…looks / like",
   "…a number you can / build to."). A baseline audit counted 218 of them across
   14 pages at four widths, plus 204 paragraphs ending on a single stranded word.
   balance evens out the lines of short text; pretty keeps paragraphs from ending
   on a runt. Both are progressive — an older browser simply wraps as it always did. */
h1, h2, h3, h4, summary, figcaption,
.eyebrow, .stat-l, .card-go, .btn, .project-tag { text-wrap: balance; }
p, li, dd, .lede, .hero-sub { text-wrap: pretty; }

p { margin: 0 0 1.15em; }
p:last-child { margin-bottom: 0; }

ul, ol { margin: 0 0 1.15em; padding-left: 1.25rem; }
li { margin-bottom: .4em; }

/* Keyboard users get a visible ring; mouse users do not. */
:focus-visible {
  outline: 3px solid var(--pc-cyan);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--pc-ink); color: #fff; padding: .75rem 1.25rem;
  font-weight: 600;
}
.skip-link:focus { left: 0; color: #fff; }

/* ── Layout primitives ────────────────────────────────────────────────── */

.shell {
  width: min(100% - 2 * var(--pc-gutter), var(--pc-shell));
  margin-inline: auto;
}
.shell-narrow { width: min(100% - 2 * var(--pc-gutter), 53.75rem); margin-inline: auto; }

.section { padding-block: var(--pc-section); }
.section-soft { background: var(--pc-bg-soft); }
.section-dark { background: var(--pc-ink); color: rgba(255,255,255,.78); }
.section-dark h1, .section-dark h2,
.section-dark h3, .section-dark h4 { color: #fff; }

/* The small caps label that sits above nearly every heading on this site.
   Avada called it "Lead"; it is the one piece of cyan on an otherwise
   monochrome page and it does a lot of the brand's work. */
.eyebrow {
  display: inline-flex; align-items: flex-start; gap: .55rem;
  font-size: .8125rem; font-weight: 700; line-height: 1.2;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--pc-cyan-dark);
  margin: 0 0 1rem;
}
.eyebrow::before {
  content: ""; width: 26px; height: 2px;
  background: var(--pc-cyan); flex: none;
  /* Centred on the first line's height (line-height 1.2 -> .6em), so the rule sits
     beside the opening words whether the label runs to one line or two. */
  margin-top: calc(.6em - 1px);
}
.section-dark .eyebrow { color: var(--pc-cyan); }
.eyebrow-center { justify-content: center; text-align: center; }
/* A centred eyebrow gets a rule on both sides. With only the leading one, the rule
   counted in the centring and pushed the label ~15px right of the heading below. */
.eyebrow-center::after {
  content: ""; width: 26px; height: 2px; flex: none;
  background: var(--pc-cyan); margin-top: calc(.6em - 1px);
}
/* Phones: tighter tracking rather than smaller type. .75rem (12px) was the audit's
   most common small-text hit; 13px uppercase at .08em reads cleanly and fits most
   labels on one line. */
@media (max-width: 480px) {
  .eyebrow { letter-spacing: .08em; }
  .eyebrow::before, .eyebrow-center::after { width: 18px; }
}

.section-head { max-width: 48.75rem; margin-bottom: clamp(2rem, 1rem + 3vw, 3.5rem); }
.section-head.center { margin-inline: auto; text-align: center; }
/* :not(.eyebrow) on every context rule that styles paragraphs. .section-head p
   (0,1,1) outranks .eyebrow (0,1,0), so eyebrows rendered at 17px here and in the
   hero and CTA band but 13px everywhere else — two sizes of the same label. */
.section-head p:not(.eyebrow) { font-size: 1.0625rem; }
/* Centred intros balance their lines; they stranded "ask for." / "a headline." */
.section-head.center p:not(.eyebrow) { text-wrap: balance; }
/* Tried capping these to a tighter measure and reverted it: an 85-character line
   is long, but these intros are two lines read in one pass, and the cap pushed
   them to three uneven ones. The long reading on this site is the FAQ answers,
   and that is where the cap earns its keep. */

.lede { font-size: clamp(1.0625rem, 1rem + .35vw, 1.1875rem); line-height: 1.75; }

/* ── Buttons ──────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .55rem;
  font-family: inherit;
  font-size: .9375rem; font-weight: 700; line-height: 1;
  letter-spacing: .04em; text-transform: uppercase;
  padding: 1.0625rem 1.85rem;
  border: 2px solid transparent; border-radius: var(--pc-radius);
  cursor: pointer;
  transition: background .2s var(--pc-ease), color .2s var(--pc-ease),
              border-color .2s var(--pc-ease), transform .2s var(--pc-ease);
}
.btn:hover { transform: translateY(-2px); }
.btn svg { flex: none; }

.btn-primary { background: var(--pc-cyan); border-color: var(--pc-cyan); color: #fff; }
.btn-primary:hover { background: var(--pc-cyan-dark); border-color: var(--pc-cyan-dark); color: #fff; }

.btn-dark { background: var(--pc-ink); border-color: var(--pc-ink); color: #fff; }
.btn-dark:hover { background: var(--pc-ink-2); border-color: var(--pc-ink-2); color: #fff; }

.btn-ghost { background: transparent; border-color: currentColor; color: var(--pc-ink); }
.btn-ghost:hover { background: var(--pc-ink); border-color: var(--pc-ink); color: #fff; }

/* .btn-ghost draws its border from currentColor, so on any dark ground it has to
   be flipped to white or it renders near-invisible — dark ink on a dark band.
   Every dark surface on the site must be listed here; .cta-band was missing and
   its "Call us" button disappeared entirely. */
.section-dark .btn-ghost,
.cta-band .btn-ghost,
.page-hero .btn-ghost,
.hero .btn-ghost { color: #fff; }
.section-dark .btn-ghost:hover,
.cta-band .btn-ghost:hover,
.page-hero .btn-ghost:hover,
.hero .btn-ghost:hover { background: #fff; border-color: #fff; color: var(--pc-ink); }

.btn-row { display: flex; flex-wrap: wrap; gap: .875rem; }
.btn-row.center { justify-content: center; }
/* Phones: stack full width. Side by side, two CTAs wrapped into a ragged pair of
   unequal widths (234px + 185px in a 335px row) on nearly every page. */
@media (max-width: 560px) {
  .btn-row { flex-direction: column; align-items: stretch; }
  .btn-row .btn { width: 100%; }
  /* Full width already gives the target its size; narrower side padding keeps a
     longer label like "Talk Through Your Scope" on one line at 360px. */
  .btn { padding-inline: 1.25rem; }
}

/* ── Header / navigation ──────────────────────────────────────────────── */

.site-header {
  position: sticky; top: 0; z-index: 100;
  background: #fff;
  border-bottom: 1px solid var(--pc-line);
}
.header-inner {
  width: min(100% - 2 * var(--pc-gutter), var(--pc-shell));
  margin-inline: auto;
  display: flex; align-items: center; gap: 1.5rem;
  min-height: 88px;
}
/* Size the mark by HEIGHT, not width. The logo is 175x100 — a 158px width makes
   it ~90px tall inside an 88px header, so it overflows and the bar looks stuffed.
   Constraining the height leaves real air above and below at any logo aspect. */
.brand { flex: none; display: block; }
.brand img { height: 58px; width: auto; }

.nav { margin-left: auto; }
.nav-list {
  list-style: none; margin: 0; padding: 0;
  display: flex; align-items: center; gap: .35rem;
}
.nav-list > li { margin: 0; position: relative; }
.nav-list a {
  display: block; padding: .7rem .9rem;
  font-size: .9375rem; font-weight: 600; line-height: 1.2;
  color: var(--pc-ink);
  border-radius: var(--pc-radius);
  transition: color .18s var(--pc-ease), background .18s var(--pc-ease);
}
.nav-list a:hover { color: var(--pc-cyan-dark); background: var(--pc-bg-soft); }

/* Active state is CSS-driven off <body data-page="…">, so the nav stays one
   file. Adding a page never means editing a copy of the nav in every page. */
body[data-page="home"]     .nav-list a[href="/"],
body[data-page="about"]    .nav-list a[href="/about"],
body[data-page="services"] .nav-list a[href="/services"],
body[data-page="projects"] .nav-list a[href="/projects"],
body[data-page="faq"]      .nav-list a[href="/faq"],
body[data-page="contact"]  .nav-list a[href="/contact"] {
  color: var(--pc-cyan-dark);
}
body[data-page="services"] .nav-drop > .nav-drop-t { color: var(--pc-cyan-dark); }

.nav-drop-t {
  display: inline-flex; align-items: center; gap: .35rem;
  font-family: inherit; font-size: .9375rem; font-weight: 600; line-height: 1.2;
  color: var(--pc-ink);
  background: none; border: 0; cursor: pointer;
  padding: .7rem .9rem; border-radius: var(--pc-radius);
  transition: color .18s var(--pc-ease), background .18s var(--pc-ease);
}
.nav-drop-t:hover { color: var(--pc-cyan-dark); background: var(--pc-bg-soft); }
.nav-drop-caret { transition: transform .2s var(--pc-ease); }

.nav-drop-menu {
  position: absolute; top: calc(100% + .35rem); left: 0;
  min-width: 264px; margin: 0; padding: .5rem;
  list-style: none;
  background: #fff; border: 1px solid var(--pc-line);
  border-radius: var(--pc-radius); box-shadow: var(--pc-shadow-lg);
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity .18s var(--pc-ease), transform .18s var(--pc-ease),
              visibility .18s var(--pc-ease);
}
.nav-drop:hover .nav-drop-menu,
.nav-drop:focus-within .nav-drop-menu {
  opacity: 1; visibility: visible; transform: translateY(0);
}
.nav-drop:hover .nav-drop-caret,
.nav-drop:focus-within .nav-drop-caret { transform: rotate(180deg); }
.nav-drop-menu a { padding: .6rem .75rem; font-weight: 500; }

.nav-cta {
  background: var(--pc-cyan); color: #fff !important;
  padding: .85rem 1.4rem !important;
  text-transform: uppercase; letter-spacing: .04em;
  font-size: .8125rem !important; font-weight: 700 !important;
  margin-left: .5rem;
}
.nav-cta:hover { background: var(--pc-cyan-dark) !important; }

.nav-phone {
  display: inline-flex; align-items: center; gap: .45rem;
  font-weight: 700; color: var(--pc-ink); font-size: .9375rem;
  padding: .7rem .9rem;
}
.nav-phone:hover { color: var(--pc-cyan-dark); }

.nav-toggle {
  display: none; margin-left: auto;
  width: 46px; height: 46px; padding: 11px;
  background: none; border: 1px solid var(--pc-line);
  border-radius: var(--pc-radius); cursor: pointer;
}
.nav-toggle span {
  display: block; height: 2px; background: var(--pc-ink);
  border-radius: 2px; transition: transform .22s var(--pc-ease), opacity .18s;
}
.nav-toggle span + span { margin-top: 5px; }
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 1040px) {
  .nav-toggle { display: block; }
  .nav {
    position: absolute; inset: 100% 0 auto; margin: 0;
    background: #fff; border-bottom: 1px solid var(--pc-line);
    box-shadow: var(--pc-shadow-lg);
    display: none;
  }
  .nav.open { display: block; }
  .nav-list {
    flex-direction: column; align-items: stretch; gap: 0;
    width: min(100% - 2 * var(--pc-gutter), var(--pc-shell));
    margin-inline: auto;
    padding: .75rem 0 1.5rem;
  }
  .nav-list > li { border-bottom: 1px solid var(--pc-line); }
  .nav-list a, .nav-drop-t { padding: .95rem .25rem; width: 100%; text-align: left; }
  .nav-drop-menu {
    position: static; opacity: 1; visibility: visible; transform: none;
    border: 0; box-shadow: none; padding: 0 0 .5rem .9rem;
    min-width: 0;
  }
  .nav-cta { margin: 1rem .25rem 0; justify-content: center; display: flex; }
  .site-header { position: relative; }

  /* The open panel never runs past the screen. On an 812px phone it was 787px
     tall, which put Request a Quote — the one action that matters — below the
     fold. dvh tracks the visible area as mobile browser chrome shows and hides. */
  .nav.open {
    max-height: calc(100vh - 88px); max-height: calc(100dvh - 88px);
    overflow-y: auto; overscroll-behavior: contain;
  }
  /* Services is a real disclosure on touch screens: collapsed until its own
     button is tapped (site.js toggles .open and aria-expanded). Permanently
     expanded, its seven links doubled the menu's height, and the caret beside it
     promised a toggle that did nothing. */
  .nav-drop-t { justify-content: space-between; }
  .nav-drop-menu {
    display: none;
    margin: 0 0 .75rem .25rem; padding: .15rem 0 .15rem .75rem;
    border-left: 2px solid var(--pc-cyan-soft);
  }
  .nav-drop.open .nav-drop-menu { display: block; }
  .nav-drop-menu a { padding: .6rem .5rem; font-size: .9375rem; }
  .nav-drop:hover .nav-drop-caret,
  .nav-drop:focus-within .nav-drop-caret { transform: none; }
  .nav-drop.open .nav-drop-caret { transform: rotate(180deg); }
  .nav-drop-caret { width: 14px; height: 14px; }
  /* .nav-list a (0,1,1) sets display:block and text-align:left for every menu
     link, which outranked .nav-cta (0,1,0) — so the quote button's label sat
     left-aligned inside its full-width bar. Matched specificity to centre it. */
  .nav-list .nav-cta { display: flex; justify-content: center; text-align: center; }
  /* The quote button's list item is last; its divider drew a stray line under it. */
  .nav-list > li:last-child { border-bottom: 0; }
}

/* ── Hero ─────────────────────────────────────────────────────────────── */

.hero {
  position: relative;
  display: flex; align-items: center;
  min-height: clamp(520px, 72vh, 760px);
  padding-block: clamp(4rem, 3rem + 6vw, 7rem);
  background: var(--pc-ink) center/cover no-repeat;
  color: rgba(255,255,255,.82);
  isolation: isolate;
}
/* Two-stop scrim: heavy on the left where the type sits, clear on the right so
   the jobsite photograph still reads as a photograph. */
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(100deg,
    rgba(21,21,23,.90) 0%, rgba(21,21,23,.76) 42%, rgba(21,21,23,.30) 100%);
}
.hero-inner { max-width: 47.5rem; }
.hero h1 { color: #fff; margin-bottom: .5em; }
.hero .eyebrow { color: var(--pc-cyan); }
.hero-sub {
  font-size: clamp(1.0625rem, 1rem + .45vw, 1.25rem);
  line-height: 1.7; max-width: 56ch; margin-bottom: 2rem;
}
.hero .btn-row { margin-top: .5rem; }

/* Page banner for interior pages — Avada called this the Page Title Bar. */
.page-hero {
  position: relative;
  padding-block: clamp(3.25rem, 2.5rem + 5vw, 6rem);
  background: var(--pc-ink) center/cover no-repeat;
  color: rgba(255,255,255,.78);
  isolation: isolate;
  overflow: hidden;
}
/* The banner photo is re-drawn with a light blur. Seven interior banners stretch a
   300-414px phone photo 3-4x across 1280px, and at that scale it reads as a
   low-resolution image. Softened, it reads as depth of field behind crisp type.
   background: inherit picks up each page's inline background-image. */
.page-hero::before {
  content: ""; position: absolute; inset: 0; z-index: -2;
  background: inherit;
  filter: blur(2px);
  transform: scale(1.05);  /* keeps the blurred edge off-screen */
}
.page-hero::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(100deg, rgba(21,21,23,.92) 0%, rgba(21,21,23,.62) 100%);
}
.page-hero h1 { color: #fff; margin-bottom: .35em; }
.page-hero p:not(.eyebrow) { max-width: 60ch; font-size: 1.0625rem; }

.crumbs {
  display: flex; flex-wrap: wrap; gap: .5rem;
  list-style: none; margin: 1.5rem 0 0; padding: 0;
  font-size: .875rem; color: rgba(255,255,255,.6);
}
.crumbs li { margin: 0; }
/* The separator closes each crumb rather than opening the next. When a long trail
   wraps on a phone, line one then ends "Home / Services /" instead of line two
   starting with a stray "/" — and nothing has to be truncated to avoid it. */
.crumbs li:not(:last-child)::after { content: "/"; margin-left: .5rem; opacity: .5; }
.crumbs a { color: rgba(255,255,255,.82); }
/* Every crumb gets the same box. Padding on the links alone (for a taller tap
   target) left the current-page crumb sitting ~5px higher than the rest. */
.crumbs li > a, .crumbs li > span { display: inline-block; padding-block: .3rem; }
.crumbs a:hover { color: var(--pc-cyan); }
.crumbs [aria-current] { color: var(--pc-cyan); }

/* ── Trust bar ────────────────────────────────────────────────────────── */

.trustbar {
  border-bottom: 1px solid var(--pc-line);
  background: #fff;
}
.trustbar-grid {
  display: grid; grid-template-columns: minmax(0, 1fr);
  gap: 1px; background: var(--pc-line);
}
/* 4 -> 2x2 -> stacked. auto-fit gave 3/1 on tablets, and because the gaps are the
   hairlines, the empty fourth cell showed as a grey block. */
@media (min-width: 560px)  { .trustbar-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1080px) { .trustbar-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.trustbar-item {
  background: #fff; padding: 2rem 1.5rem;
  display: flex; align-items: flex-start; gap: .9rem;
}
.trustbar-item svg { color: var(--pc-cyan); flex: none; margin-top: 3px; }
.trustbar-item strong {
  display: block; color: var(--pc-ink); font-size: 1rem;
  font-weight: 700; line-height: 1.35; margin-bottom: .15rem;
}
.trustbar-item span { font-size: .875rem; line-height: 1.55; display: block; text-wrap: balance; }
@media (max-width: 559px) { .trustbar-item { padding: 1.25rem; } }

/* ── Cards ────────────────────────────────────────────────────────────── */

/* Explicit column counts, not auto-fit. auto-fit/minmax(290px) means "as many
   columns as fit", which is four at the 1240px shell — so .grid-3 laid six service
   cards out 4/2 and the gallery 4/4/2, and .grid-4 went 3/1 at 1024. Every count
   below is chosen so the item counts actually used on this site (3, 4, 6, 12)
   divide evenly at every width. minmax(0, 1fr) rather than 1fr lets a column
   shrink below its content's min-content width instead of pushing the page wide. */
.grid { display: grid; gap: 1.5rem; grid-template-columns: minmax(0, 1fr); }
.grid > * { min-width: 0; }

@media (min-width: 560px) {
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }            /* 4 -> 2x2 */
}
/* Range-scoped on purpose. .grid-3:has(> :nth-child(4)) scores (0,2,0), which beats
   the plain .grid-3 desktop rule (0,1,0) regardless of source order — unscoped, it
   held every 6- and 12-item grid at two columns on desktop too. */
@media (min-width: 560px) and (max-width: 959px) {
  .grid-3:has(> :nth-child(4)) { grid-template-columns: repeat(2, minmax(0, 1fr)); } /* 6, 12 */
}
/* A three-item grid skips two columns entirely (2/1 strands a card alone) and
   holds off three-up until 900px: at 700-899 its columns were ~240px, so titles
   wrapped unevenly and copy ran 8-9 narrow lines. Until then it stacks as one
   centred column, the same width as a stacked photo split. */
@media (max-width: 899px) {
  .grid-3:not(:has(> :nth-child(4))) { max-width: 36rem; margin-inline: auto; }
}
@media (min-width: 900px) {
  .grid-3:not(:has(> :nth-child(4))) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (min-width: 760px) {
  .grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 960px) {
  .grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (min-width: 1080px) {
  .grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* Service card: photo top, cyan rule that grows on hover. */
.card {
  display: flex; flex-direction: column;
  background: #fff;
  border: 1px solid var(--pc-line);
  border-radius: var(--pc-radius);
  overflow: hidden;
  transition: transform .25s var(--pc-ease), box-shadow .25s var(--pc-ease),
              border-color .25s var(--pc-ease);
}
a.card { color: inherit; }
a.card:hover { transform: translateY(-4px); box-shadow: var(--pc-shadow-lg); border-color: transparent; }

.card-media { position: relative; aspect-ratio: 4 / 3; overflow: hidden; background: var(--pc-bg-alt); }
.card-media img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s var(--pc-ease); }
a.card:hover .card-media img { transform: scale(1.05); }

.card-body { padding: 1.5rem; display: flex; flex-direction: column; flex: 1; }
.card-body h3 { font-size: 1.3125rem; line-height: 1.35; margin-bottom: .5rem; }
.card-body p { font-size: .9688rem; line-height: 1.7; }
.card-body p:last-of-type { margin-bottom: 0; }

.card-go {
  margin-top: auto; padding-top: 1.1rem;
  display: inline-flex; align-items: center; gap: .45rem;
  font-size: .8125rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--pc-cyan-dark);
}
.card-go svg { transition: transform .2s var(--pc-ease); }
a.card:hover .card-go svg { transform: translateX(4px); }

/* Numbered process step */
.step {
  position: relative;
  background: #fff; border: 1px solid var(--pc-line);
  border-radius: var(--pc-radius); padding: 2rem 1.5rem 1.5rem;
}
.step-n {
  display: inline-flex; align-items: center; justify-content: center;
  width: 46px; height: 46px; margin-bottom: 1.1rem;
  background: var(--pc-cyan-soft); color: var(--pc-cyan-dark);
  border-radius: var(--pc-radius);
  font-size: 1.0625rem; font-weight: 700; line-height: 1;
}
.step h3 { font-size: 1.1875rem; line-height: 1.4; margin-bottom: .45rem; }
.step p { font-size: .9375rem; line-height: 1.7; }

/* Icon feature (no photo) */
.feature { padding: 0; }
.feature-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 56px; height: 56px; margin-bottom: 1.1rem;
  background: var(--pc-cyan); color: #fff; border-radius: var(--pc-radius);
}
/* A 24px glyph read as a speck inside the solid 56px tile. */
.feature-icon svg { width: 28px; height: 28px; }
.feature h3 { font-size: 1.25rem; line-height: 1.4; margin-bottom: .5rem; }
.feature p { font-size: .9688rem; }

/* ── Stats ────────────────────────────────────────────────────────────── */

.stats {
  /* 2x2 on phones and tablets, a row of four from 900px. auto-fit gave 3/1 at
     tablet width with the hairline background showing as an empty cell. */
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px; background: rgba(255,255,255,.14);
  border: 1px solid rgba(255,255,255,.14);
  border-radius: var(--pc-radius); overflow: hidden;
}
@media (min-width: 900px) { .stats { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
/* Below 900px the 2x2 cells are ~150px wide, so some labels wrap and others do not,
   leaving four cells with ragged baselines. Every label reserves two lines. */
@media (max-width: 899px) {
  .stat { padding: 1.85rem .85rem; }
  .stat-l { letter-spacing: .1em; line-height: 1.35; min-height: 2.7em; }
}
.stat { background: var(--pc-ink); padding: 2.25rem 1.25rem; text-align: center; }
.stat-n {
  display: block;
  font-size: clamp(2.25rem, 1.6rem + 2.6vw, 3.25rem);
  font-weight: 700; line-height: 1.1; color: #fff;
  letter-spacing: -0.02em;
}
.stat-n .unit { color: var(--pc-cyan); }
.stat-l {
  display: block; margin-top: .35rem;
  font-size: .8125rem; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase;
  color: rgba(255,255,255,.62);
}

/* ── Split (image + copy) ─────────────────────────────────────────────── */

/* Image + copy. Three problems with the old version, all measured:
   1. Equal columns with the image vertically centred. Copy runs 700-900px, most
      photos 400-550px, so the photo floated mid-column with empty space above and
      below — 60 "imbalanced" splits in the audit.
   2. auto-fit(minmax(340px)) went two-up at ~750px, squeezing copy into 344px.
   3. width:auto on the image (to avoid upscaling small phone photos) overrode the
      width/height attributes, so the browser reserved no space and every split
      photo was 0px tall until it loaded, then shoved the page down.
   Now: single column below 900px; above it the photo gets 5 parts and the copy 7
   — a wider copy column is a shorter one, and a narrower photo column means the
   small sources upscale ~1.2x instead of ~1.5x. Both columns start on the same top
   line, and the photo is sticky, so a photo shorter than its copy travels with
   the reader instead of leaving a hole. The ratio follows the PHOTO, not DOM
   order, so splits with the photo second still get the narrow column. */
.split {
  display: grid; gap: clamp(2rem, 1rem + 3vw, 4rem);
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}
.split > * { min-width: 0; }
.split-media img {
  width: 100%; height: auto;
  border-radius: var(--pc-radius);
  box-shadow: var(--pc-shadow-lg);
}
.split.reverse .split-media { order: 2; }

/* Photo splits stay stacked until 1200px. Two-up any narrower, the copy column
   is under ~600px wide, so it ran 1,000-1,300px tall beside a ~400px photo — the
   worst imbalance in the audit (ratios 0.29-0.48 at 1024-1100px). Stacked, the
   photo and its copy form one centred reading column instead of hugging the left
   edge of a wide tablet screen. Text-only splits (the contact form) go two-up
   from 900px. */
@media (max-width: 1199px) {
  .split:has(> .split-media) { justify-items: center; }
  .split-media, .split.reverse .split-media { order: -1; width: 100%; max-width: 36rem; }
  .split-media img { max-height: 34rem; object-fit: cover; }
  .split:has(> .split-media) > :not(.split-media) { width: 100%; max-width: 36rem; }
}
@media (max-width: 899px) {
  .split:not(:has(> .split-media)) > * { max-width: 62ch; }
}
/* Phones: a portrait photo stacked above its copy filled ~70% of the screen
   before the reader reached the heading. */
@media (max-width: 560px) { .split-media img { max-height: min(60vh, 25rem); } }
/* This crop's subject — the crew and the walls — is at the bottom of the frame;
   a centred crop cut them off on tablets. */
.split-media img[src*="foundation-pour-tall"] { object-position: 50% 85%; }
/* Overcast sky filled the top half of this crop; the apron is at the bottom. */
.split-media img[src*="detail-02"] { object-position: 50% 78%; }
/* A portrait source in a 4:3 frame: the centred crop kept the foreground dirt
   pile and cut away the pump the caption is about. Frame the top of the shot. */
.project img[src*="cap-slab-pour"], .card-media img[src*="cap-slab-pour"] { object-position: 50% 12%; }
@media (min-width: 900px) {
  .split:not(:has(> .split-media)) { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  /* Text-only split (the contact page): the short details column travels with the
     long form instead of leaving ~600px of blank page beside it. */
  .split:not(:has(> .split-media)) > :last-child { position: sticky; top: 2rem; }
}
@media (min-width: 1041px) { .split:not(:has(> .split-media)) > :last-child { top: calc(88px + 2rem); } }
@media (min-width: 1200px) {
  .split:has(> .split-media) { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
  .split.reverse:has(> .split-media),
  .split:has(> .split-media:last-child) { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
  /* Sticky clears the 88px header, which is itself sticky above 1040px. */
  .split-media { position: sticky; top: calc(88px + 2rem); }
  .split-media img { max-height: min(78vh, 42rem); object-fit: cover; }
}

/* Ultrawide photography (the 3.5:1 site shots) belongs across the page, not in a
   column. In a ~584px split column such a file renders ~164px tall beside copy
   that runs 700-900px, which reads as a letterbox strip floating next to text.
   Given the full shell width it becomes a deliberate cinematic band instead. */
.media-band {
  margin-block: clamp(2rem, 1rem + 3vw, 3.5rem);
  margin-inline: 0; /* <figure> defaults to 40px each side */
}
.media-band:first-child { margin-top: 0; }
/* The photo behind this band is 1300px wide and there is no larger original, so
   once the shell grows past that on a wide monitor the browser starts stretching
   it. Cap the band at the file's own width and centre it instead. */
@media (min-width: 1200px) { .media-band { max-width: 1300px; margin-inline: auto; } }
/* Below 1200px everything else on the page stacks into a centred 36rem column, so
   the band joins it — full-shell width it left the photos below starting ~110px
   further in. At that width a 3.57:1 frame would be a sliver, so crop to 16:9. */
@media (max-width: 1199px) {
  .media-band { max-width: 36rem; margin-inline: auto; }
  .media-band img { aspect-ratio: 16 / 9; object-fit: cover; }
}
.media-band img {
  width: 100%;
  border-radius: var(--pc-radius);
  box-shadow: var(--pc-shadow-lg);
}
.media-band figcaption {
  margin-top: .85rem;
  font-size: .875rem;
  line-height: 1.6;
  color: var(--pc-grey-mid);
}


/* Checklist used inside split copy */
.ticks { list-style: none; margin: 1.5rem 0 0; padding: 0; }
.ticks li {
  position: relative; padding-left: 2rem; margin-bottom: .7rem;
  font-size: 1rem; line-height: 1.65;
}
.ticks li:last-child { margin-bottom: 0; }
.ticks li::before {
  content: ""; position: absolute; left: 0; top: .45em;
  width: 18px; height: 10px;
  border-left: 2.5px solid var(--pc-cyan);
  border-bottom: 2.5px solid var(--pc-cyan);
  transform: rotate(-45deg);
}

/* ── Marquee (the Avada Factory scrolling strip) ──────────────────── */

/* Two identical tracks slide left by exactly their own width, one behind the
   other, so the band is never empty. Speed - not duration - is the constant:
   each track holds three copies of the list, so the original 34s-per-copy pace
   is 102s here, and it stays 51px/s at every window width. */
.marquee {
  display: flex; overflow: hidden; padding-block: 1.35rem;
  background: var(--pc-cyan);
  border-block: 1px solid var(--pc-cyan-dark);
  --marquee-duration: 102s;
}
.marquee-track {
  display: flex; align-items: center; flex: 0 0 auto;
  /* Never narrower than the window. Three copies measure ~5200px, so this only
     matters on a display wider than that - and there it spreads the labels out
     rather than leaving a hole, which is the failure this section had. */
  min-width: 100%; justify-content: space-around;
  animation: marquee var(--marquee-duration) linear infinite;
}
.marquee:hover .marquee-track { animation-play-state: paused; }
.marquee-item {
  display: inline-flex; align-items: center; gap: 2.5rem;
  padding-right: 2.5rem;
  font-size: clamp(1rem, .9rem + .5vw, 1.375rem);
  font-weight: 700; letter-spacing: .02em; text-transform: uppercase;
  color: #fff; white-space: nowrap;
}
.marquee-item::after {
  content: ""; width: 9px; height: 9px; flex: none;
  background: rgba(255,255,255,.72); transform: rotate(45deg);
}
@keyframes marquee { to { transform: translateX(-100%); } }

@media (prefers-reduced-motion: reduce) {
  /* One static, centred row of the five scopes - not six copies of it. The
     diamonds go with the movement: standing still they only separate items
     mid-row, so on a phone, where the list wraps, every row would end on one
     and sit visibly off-centre. A gap does the same job at any width. */
  .marquee { display: block; padding-inline: var(--pc-gutter); }
  .marquee-track {
    animation: none; flex-wrap: wrap; justify-content: center;
    min-width: 0; column-gap: 2.5rem; row-gap: .4rem;
  }
  .marquee-track + .marquee-track,
  .marquee-track > :nth-child(n+6) { display: none; }
  .marquee-item { padding-right: 0; }
  .marquee-item::after { display: none; }
}

/* ── Projects ─────────────────────────────────────────────────────────── */

/* Caption BELOW the photo, not laid over it. Overlaid, a tag + title + sentence
   covered more than 70% of the frame on 31 tiles in the audit — the photograph,
   which is the whole point of the page, was mostly a dark gradient. Below the
   photo the caption can run as long as it needs and every tile lines up with the
   service cards elsewhere on the site. */
.project {
  display: flex; flex-direction: column;
  background: #fff; color: var(--pc-grey);
  border: 1px solid var(--pc-line);
  border-radius: var(--pc-radius); overflow: hidden;
  transition: transform .25s var(--pc-ease), box-shadow .25s var(--pc-ease),
              border-color .25s var(--pc-ease);
}
a.project:hover { transform: translateY(-4px); box-shadow: var(--pc-shadow-lg); border-color: transparent; color: var(--pc-grey); }
.project img {
  width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover;
  background: var(--pc-bg-alt);
}
.project-cap { display: flex; flex-direction: column; flex: 1; padding: 1.25rem 1.35rem 1.5rem; }
.project-tag {
  display: block; margin-bottom: .4rem;
  font-size: .8125rem; font-weight: 700; line-height: 1.3;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--pc-cyan-dark);
}
.project-cap h3 {
  color: var(--pc-ink); font-size: 1.125rem; line-height: 1.4; margin: 0 0 .4rem;
}
.project-cap p { font-size: .9375rem; line-height: 1.65; color: var(--pc-grey); margin: 0; }

/* ── FAQ ──────────────────────────────────────────────────────────────── */

.faq { border-top: 1px solid var(--pc-line); }
/* No background of its own: on a grey section a white row showed as a band with
   the question 4px from its edge and the chevron flush against the other. */
.faq details {
  border-bottom: 1px solid var(--pc-line);
}
.faq summary {
  /* A block with an absolutely placed caret, not a flex row. As flex, every run of
     text and every inline element inside a question became its own flex item: one
     <span> in "Broom finish or steel trowel — which do we want where?" split the
     question into three side-by-side columns on a phone. */
  display: block; position: relative;
  padding: 1.5rem 2.25rem 1.5rem .25rem;
  font-size: clamp(1.0625rem, 1rem + .35vw, 1.1875rem);
  font-weight: 600; line-height: 1.5; color: var(--pc-ink);
  cursor: pointer; list-style: none;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::marker { content: ""; }
.faq summary::after {
  content: ""; position: absolute; right: .4rem; top: calc(1.5rem + .45em);
  width: 12px; height: 12px;
  border-right: 2.5px solid var(--pc-cyan);
  border-bottom: 2.5px solid var(--pc-cyan);
  transform: rotate(45deg);
  transition: transform .22s var(--pc-ease);
}
.faq details[open] summary::after { transform: rotate(-135deg); top: calc(1.5rem + .8em); }
.faq summary:hover { color: var(--pc-cyan-dark); }
.faq-a { padding: 0 3rem 1.75rem .25rem; font-size: 1rem; }
/* The 3rem right gutter keeps answers clear of the caret column on wide screens.
   On a 375px phone it cut every answer to 84% of its row, so the text visibly
   stopped short of the question above it. */
@media (max-width: 560px) { .faq-a { padding-right: .25rem; } }
/* Answers and checklists sit in full-shell sections on the service pages, where at
   tablet width a line ran past 100 characters. */
/* 57ch, not 68: this font's "0" is unusually wide, so a ch cap overshoots. At
   68ch the FAQ answers - the longest reading on the site - ran 93 characters a
   line, well past the 75-ish where the eye starts losing its place. */
.faq-a > * { max-width: 57ch; }
.ticks { max-width: 68ch; }
.faq-a p:last-child { margin-bottom: 0; }

/* ── Forms ────────────────────────────────────────────────────────────── */

.form-grid { display: grid; gap: 1.1rem; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 560px) { .form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.field { display: flex; flex-direction: column; gap: .45rem; }
.field-wide { grid-column: 1 / -1; }
.field label {
  font-size: .8125rem; font-weight: 700;
  letter-spacing: .09em; text-transform: uppercase; color: var(--pc-ink);
}
.field .req { color: var(--pc-cyan-dark); }
.field input, .field select, .field textarea {
  font-family: inherit; font-size: 1rem; font-weight: 300; color: var(--pc-ink);
  padding: .875rem 1rem;
  background: #fff;
  border: 1px solid var(--pc-line); border-radius: var(--pc-radius);
  transition: border-color .18s var(--pc-ease), box-shadow .18s var(--pc-ease);
}
.field textarea { min-height: 148px; resize: vertical; line-height: 1.7; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--pc-cyan);
  box-shadow: 0 0 0 3px var(--pc-cyan-soft);
}
.field-hint { font-size: .8125rem; line-height: 1.5; color: var(--pc-grey-mid); }
/* Small type in a full-width form ran past 100 characters a line at tablet width. */
.field-hint, form p { max-width: 60ch; }

/* Honeypot: a real person never sees this, a dumb bot fills it in. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ── Contact detail blocks ────────────────────────────────────────────── */

.contact-list { list-style: none; margin: 0; padding: 0; }
.contact-list li {
  display: flex; gap: 1rem; padding: 1.25rem 0;
  border-bottom: 1px solid var(--pc-line); margin: 0;
}
.contact-list li:first-child { padding-top: 0; }
.contact-list svg {
  /* Fixed size, pinned to the first line. The global svg { height: auto } let the
     flex row stretch each icon to the whole row, so it floated halfway down —
     level with the note, not the label. */
  color: var(--pc-cyan); flex: none;
  width: 22px; height: 22px; align-self: flex-start; margin-top: 1px;
}
.contact-list strong {
  display: block; color: var(--pc-ink);
  font-size: .8125rem; font-weight: 700;
  letter-spacing: .11em; text-transform: uppercase; margin-bottom: .3rem;
}
.contact-list a { color: var(--pc-ink); font-weight: 500; display: inline-block; padding-block: .2rem; }
/* One treatment for every note under a contact detail. They were three: two at
   full body size running straight into the value above, one small grey span. */
.contact-note {
  display: block; margin: .4rem 0 0; max-width: 44ch;
  font-size: .875rem; line-height: 1.6; color: var(--pc-grey-mid);
}
.contact-list a:hover { color: var(--pc-cyan-dark); }

/* ── CTA band ─────────────────────────────────────────────────────────── */

.cta-band {
  position: relative; isolation: isolate;
  background: var(--pc-ink) center/cover no-repeat;
  color: rgba(255,255,255,.8);
  padding-block: clamp(3.25rem, 2.5rem + 4vw, 5.5rem);
  text-align: center;
}
.cta-band::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: rgba(21,21,23,.86);
}
.cta-band h2 { color: #fff; margin-bottom: .5em; }
.cta-band p:not(.eyebrow) { max-width: 58ch; margin-inline: auto; margin-bottom: 2rem; font-size: 1.0625rem; text-wrap: balance; }
/* balance only works up to about six lines. On a phone these centred intros run
   longer, and past that limit balance falls back to plain wrapping and strands the
   last word or two ("…the right crew / for it."). pretty guards the last line at
   any length, so phones use it instead. */
@media (max-width: 480px) {
  .section-head.center p:not(.eyebrow), .cta-band p:not(.eyebrow) { text-wrap: pretty; }
}

/* ── Footer ───────────────────────────────────────────────────────────── */

.site-footer { background: var(--pc-ink); color: rgba(255,255,255,.66); }
.footer-main {
  /* Rebuilt per width. The old minmax(260px,…) + auto-fit(minmax(170px,…)) needed
     at least 470px, so inside a 350px phone shell every page on the site scrolled
     sideways. Phones: one column — side by side, the 161px link columns wrapped
     "Commercial & / Industrial" with the ampersand dangling. Tablets: brand
     across the top, three columns under it. Desktop: four. */
  display: grid; gap: 2rem 1.75rem;
  grid-template-columns: minmax(0, 1fr);
  padding-block: clamp(3rem, 2rem + 4vw, 4.5rem);
}
.footer-main > * { min-width: 0; }
.footer-brand { grid-column: 1 / -1; }
@media (min-width: 640px) {
  /* The contact column is the widest, so the email address fits on one line at
     most tablet widths instead of breaking after the "@". */
  .footer-main { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.35fr); }
}
@media (min-width: 1024px) {
  .footer-main { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.2fr); }
  .footer-brand { grid-column: auto; }
}
.footer-brand img { width: 168px; margin-bottom: 1.25rem; }
.footer-about { font-size: .9375rem; line-height: 1.75; max-width: 38ch; }
/* h2, not h4: these are the footer landmark's own section labels, and the
   heading before them is the CTA band's h2 — an h4 here skipped a level on every
   page. The visual weight is set here, so the tag is free to be semantic. */
.footer-col h2 {
  color: #fff; font-size: .8125rem; font-weight: 700;
  line-height: 1.4; letter-spacing: .14em; text-transform: uppercase;
  margin: 0 0 1.1rem;
}
.footer-col ul { list-style: none; margin: 0; padding: 0; }
.footer-col li { margin-bottom: .25rem; }
/* inline-block + padding makes each link a ~34px-tall target (it was 19px) while
   keeping the same visual rhythm as the old .6rem gaps. */
.footer-col a { color: rgba(255,255,255,.66); font-size: .9375rem; display: inline-block; padding-block: .35rem; }
.footer-col a:hover { color: var(--pc-cyan); }
.footer-col address { font-style: normal; font-size: .9375rem; line-height: 1.75; padding-top: .35rem; }
/* An email address is a single unbreakable token. At 1024px it was wider than its
   footer column and pushed every page 22px wider than the viewport. */
.footer-col a, .footer-col address, .contact-list a { overflow-wrap: anywhere; }
.footer-col address a[href^="tel:"] { margin-top: .5rem; }

.footer-bottom {
  display: flex; flex-wrap: wrap; gap: 1rem 2rem;
  align-items: center; justify-content: space-between;
  padding-block: 1.5rem;
  border-top: 1px solid rgba(255,255,255,.12);
  font-size: .8438rem;
}
.footer-bottom p { margin: 0; }
.footer-legal { display: flex; flex-wrap: wrap; gap: 1.25rem; }

/* ── Reveal on scroll (progressive: no JS = everything visible) ───────── */

.reveal { opacity: 0; transform: translateY(18px); }
.reveal.in { opacity: 1; transform: none; transition: opacity .6s var(--pc-ease), transform .6s var(--pc-ease); }
.no-js .reveal, .reveal.no-anim { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .reveal { opacity: 1; transform: none; } }

/* ── Utilities ────────────────────────────────────────────────────────── */

.center { text-align: center; }
.mt-0 { margin-top: 0; }
.mt-2 { margin-top: 2rem; }
.mb-0 { margin-bottom: 0; }
/* Set by scripts/build.js around a word and the dash after it. */
.nowrap { white-space: nowrap; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Anything wide (a table, a code block) scrolls inside itself; the page body
   must never scroll sideways. */
.scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }

@media print {
  .site-header, .site-footer, .cta-band, .nav-toggle { display: none; }
  body { color: #000; }
}
