/* ==========================================================================
   Master's Flooring & Custom Tile — shared stylesheet
   Token-driven. Every page uses this file and nothing else.
   ========================================================================== */

/* ---------- Fonts (self-hosted, no third-party request) ---------- */
@font-face{
  font-family:'Archivo';
  src:url('../fonts/archivo-latin-var.woff2') format('woff2-variations'),
      url('../fonts/archivo-latin-var.woff2') format('woff2');
  font-weight:100 900; font-style:normal; font-display:swap;
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215;
}
@font-face{
  font-family:'Inter';
  src:url('../fonts/inter-latin-var.woff2') format('woff2-variations'),
      url('../fonts/inter-latin-var.woff2') format('woff2');
  font-weight:100 900; font-style:normal; font-display:swap;
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215;
}

/* ---------- Tokens ---------- */
:root{
  --ink-900:#141414; --ink-800:#1F1F1F; --ink-700:#2E2E2E; --ink-600:#454545;
  --bone-50:#FAF8F5; --bone-100:#F2EFEA; --bone-200:#E4DFD8; --bone-300:#CFC8BE;
  --orange-300:#F0A65E; --orange-500:#E08127; --orange-700:#A85614;
  --stone-500:#868487;
  --text:#1A1815; --text-muted:#57534E;
  --text-inv:#F5F2ED; --text-inv-muted:#B5B0A9;

  --font-display:'Archivo',system-ui,sans-serif;
  --font-body:'Inter',system-ui,-apple-system,'Segoe UI',sans-serif;

  --s1:.25rem; --s2:.5rem; --s3:.75rem; --s4:1rem; --s5:1.5rem;
  --s6:2rem; --s7:3rem; --s8:4rem; --s9:6rem; --s10:8rem;
  --section:clamp(4rem,8vw,7.5rem);
  --container:1200px; --gutter:1.5rem;

  --radius:3px; --radius-card:6px;
  --shadow-card:0 1px 2px rgb(20 20 20/.04),0 8px 24px rgb(20 20 20/.07);
  --shadow-lift:0 2px 4px rgb(20 20 20/.06),0 18px 42px rgb(20 20 20/.12);

  --ease:cubic-bezier(.22,1,.36,1);
  --dur-micro:200ms; --dur-reveal:400ms; --dur-hero:800ms;
  --header-h:76px;
}

/* ---------- Reset / base ---------- */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;scroll-padding-top:calc(var(--header-h) + 1rem)}
body{
  margin:0;background:var(--bone-50);color:var(--text);
  font-family:var(--font-body);font-size:1.0625rem;line-height:1.7;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  overflow-x:hidden;
}
img,picture,svg,canvas{display:block;max-width:100%}
img{height:auto}
h1,h2,h3,h4{font-family:var(--font-display);line-height:1.1;margin:0;color:var(--text)}
h1{font-size:clamp(2.2rem,1.5rem + 3vw,3.75rem);font-weight:700;letter-spacing:-.02em}
h2{font-size:clamp(1.7rem,1.3rem + 1.9vw,2.6rem);font-weight:600;letter-spacing:-.015em}
h3{font-size:clamp(1.2rem,1.08rem + .7vw,1.5rem);font-weight:600;letter-spacing:-.005em}
/* h4 needs an explicit size or it inherits 1em at heading weight — smaller AND
   heavier than the h3 above it, which runs the type scale backwards. */
h4{
  font-size:.8125rem;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:var(--text-muted);line-height:1.4;margin-bottom:var(--s2);
}
.section--dark h4{color:var(--text-inv-muted)}
p{margin:0 0 var(--s4);max-width:68ch}
a{color:var(--orange-700);text-underline-offset:.2em;text-decoration-thickness:1px}
a:hover{color:var(--ink-900)}
/* Links on dark surfaces: orange-700 on ink measures poorly; use the light brass-orange. */
.section--dark a:not(.btn),
.cta-band a:not(.btn),
.hero a:not(.btn){color:var(--orange-300)}
.section--dark a:not(.btn):hover,
.cta-band a:not(.btn):hover,
.hero a:not(.btn):hover{color:#F7C48C}
ul,ol{margin:0 0 var(--s4);padding-left:1.25rem}
li{margin-bottom:var(--s2);max-width:66ch}
strong{font-weight:600}
hr{border:0;border-top:1px solid var(--bone-200);margin:var(--s7) 0}

:focus-visible{outline:2px solid var(--orange-700);outline-offset:2px;border-radius:var(--radius)}
/* Light outline only on surfaces that are ACTUALLY dark at the time. */
.site-header--dark.is-over-hero :focus-visible,
.hero :focus-visible,
.section--dark :focus-visible,
.cta-band :focus-visible,
.site-footer :focus-visible,
.nav.is-open :focus-visible{outline-color:var(--orange-300)}

::selection{background:var(--orange-300);color:var(--ink-900)}

/* ---------- Layout ---------- */
.container{width:100%;max-width:var(--container);margin-inline:auto;padding-inline:var(--gutter)}
.container--narrow{max-width:820px}
.section{padding-block:var(--section)}
.section--tight{padding-block:clamp(3rem,5vw,4.5rem)}
.section--flush-end{padding-bottom:0}
.section--dark{background:var(--ink-900);color:var(--text-inv)}
.section--dark h1,.section--dark h2,.section--dark h3{color:var(--text-inv)}
.section--dark p{color:var(--text-inv-muted)}
.section--bone{background:var(--bone-100)}

.skip-link{
  position:absolute;left:var(--s4);top:-100px;z-index:200;
  background:var(--ink-900);color:var(--text-inv);
  padding:var(--s3) var(--s5);border-radius:var(--radius);
  font-family:var(--font-display);font-weight:600;text-decoration:none;
  transition:top var(--dur-micro) var(--ease);
}
.skip-link:focus{top:var(--s4);color:var(--text-inv)}

/* ---------- Eyebrow / heads ---------- */
.eyebrow{
  font-family:var(--font-display);font-size:.8125rem;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;color:var(--orange-700);
  margin:0 0 var(--s3);display:flex;align-items:center;gap:var(--s3);
}
.eyebrow::before{content:"";width:26px;height:2px;background:var(--orange-500);flex:none}
.section--dark .eyebrow,.hero .eyebrow,.cta-band .eyebrow{color:var(--orange-300)}
.section-head{max-width:60ch;margin-bottom:var(--s7)}
.lead{font-size:clamp(1.1rem,1.03rem + .4vw,1.35rem);line-height:1.6;color:var(--text-muted)}
.section--dark .lead{color:var(--text-inv-muted)}

/* ---------- Buttons ---------- */
.btn{
  --btn-bg:var(--orange-700); --btn-fg:#fff; --btn-bd:var(--orange-700);
  display:inline-flex;align-items:center;justify-content:center;gap:var(--s2);
  min-height:48px;padding:0 var(--s5);
  background:var(--btn-bg);color:var(--btn-fg);border:1px solid var(--btn-bd);
  border-radius:var(--radius);
  font-family:var(--font-display);font-size:1rem;font-weight:600;letter-spacing:.01em;
  text-decoration:none;cursor:pointer;white-space:nowrap;
  transition:background var(--dur-micro) var(--ease),color var(--dur-micro) var(--ease),
             border-color var(--dur-micro) var(--ease),transform var(--dur-micro) var(--ease);
}
.btn:hover{--btn-bg:#8C460F;--btn-bd:#8C460F;color:#fff;transform:translateY(-1px)}
.btn:active{transform:translateY(0)}
/* 3:1 minimum for a UI component boundary (WCAG 1.4.11) — a --bone-300 border
   measures about 1.5:1 and reads as framed text rather than a button. */
.btn--ghost{--btn-bg:transparent;--btn-fg:var(--text);--btn-bd:#8A8078}
.btn--ghost:hover{--btn-bg:var(--ink-900);--btn-fg:#fff;--btn-bd:var(--ink-900)}
.btn--on-dark{--btn-bg:transparent;--btn-fg:var(--text-inv);--btn-bd:rgb(240 166 94/.58)}
.btn--on-dark:hover{--btn-bg:var(--orange-300);--btn-fg:var(--ink-900);--btn-bd:var(--orange-300)}
.btn--lg{min-height:54px;padding:0 var(--s6);font-size:1.0625rem}
.btn--block{width:100%}
.btn svg{width:18px;height:18px;flex:none}

/* ---------- Header ---------- */
.site-header{
  position:sticky;top:0;z-index:100;
  background:transparent;border-bottom:1px solid transparent;
  transition:border-color var(--dur-micro) var(--ease);
}
/* The blur MUST live on a pseudo-element, never on .site-header itself.
   backdrop-filter makes an element a containing block for position:fixed
   descendants — and .nav (the mobile overlay) is a child of the header, so with
   the filter on the header its inset:0 resolves against a 76px bar and the whole
   menu gets clipped. */
.site-header::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:rgb(250 248 245/.90);
  backdrop-filter:saturate(1.5) blur(12px);
  -webkit-backdrop-filter:saturate(1.5) blur(12px);
  transition:opacity var(--dur-micro) var(--ease);
}
/* Solid is the DEFAULT, including on the dark-hero page. The transparent
   treatment is opt-IN via .is-over-hero, which JS adds — so if the script ever
   fails the header degrades to solid-and-readable, not invisible. */
.site-header.is-stuck,.site-header--solid,.site-header--dark{border-bottom-color:var(--bone-200)}
.site-header--dark.is-over-hero::before{opacity:0}
.site-header--dark.is-over-hero{border-bottom-color:transparent}

.site-header__inner{display:flex;align-items:center;gap:var(--s5);min-height:var(--header-h)}
.brand{display:flex;align-items:center;gap:var(--s3);text-decoration:none;min-width:0;margin-right:auto}
.brand__mark{width:44px;height:44px;flex:none}
.brand__text{display:flex;flex-direction:column;line-height:1.05}
.brand__name{
  font-family:var(--font-display);font-weight:700;font-size:1.0625rem;
  letter-spacing:.01em;color:var(--text);text-transform:uppercase;
}
.brand__sub{
  font-family:var(--font-display);font-size:.625rem;font-weight:600;
  letter-spacing:.2em;text-transform:uppercase;color:var(--text-muted);
}
@media (max-width:520px){ .brand__sub{display:none} .brand__name{font-size:1rem} }

/* Persistent mobile click-to-call. The nav's phone button sits INSIDE .nav,
   which is translated off-screen below the breakpoint — without this the only
   phone link on a phone is buried in the hamburger. */
.header-call{display:none}

.nav-toggle{
  display:none;align-items:center;justify-content:center;
  flex:none;                        /* must never shrink below the 44px target */
  width:48px;height:48px;margin-right:calc(var(--s3) * -1);
  background:none;border:0;color:var(--text);cursor:pointer;
}
.nav-toggle svg{width:26px;height:26px}
.nav-toggle .icon-close{display:none}
.nav-toggle[aria-expanded="true"] .icon-open{display:none}
.nav-toggle[aria-expanded="true"] .icon-close{display:block}
/* While the menu is open the full-screen overlay behind the toggle is
   --ink-900, but the toggle itself keeps color:var(--text) — near-black — on
   every page except the home hero. The X was rendering the whole time and was
   simply invisible against it. This is what makes the close affordance show. */
.nav-toggle[aria-expanded="true"]{color:var(--text-inv)}

.nav{display:flex;align-items:center;gap:var(--s5)}
.nav__link{
  font-family:var(--font-display);font-size:.9375rem;font-weight:600;
  color:var(--text);text-decoration:none;padding:var(--s2) 0;position:relative;
  transition:color var(--dur-micro) var(--ease);
}
.nav__link::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:2px;
  background:var(--orange-500);transform:scaleX(0);transform-origin:left;
  transition:transform var(--dur-micro) var(--ease);
}
.nav__link:hover::after,.nav__link[aria-current="page"]::after{transform:scaleX(1)}
.nav__link[aria-current="page"]{color:var(--orange-700)}

/* Transparent-over-dark-hero variant. MUST come after the base .brand/.nav
   rules so the light-on-dark treatment is unambiguous. */
.site-header--dark.is-over-hero .brand__name{color:var(--text-inv)}
.site-header--dark.is-over-hero .brand__sub{color:var(--text-inv-muted)}
.site-header--dark.is-over-hero .nav-toggle{color:var(--text-inv)}
.site-header--dark.is-over-hero .nav__link{color:var(--text-inv)}
.site-header--dark.is-over-hero .nav__link:hover{color:var(--orange-300)}
.site-header--dark.is-over-hero .nav__link[aria-current="page"]{color:var(--orange-300)}

@media (max-width:1040px){
  /* z-index 100 beats the overlay's 99: without it the close (X) icon paints
     underneath the open menu and taps land on the overlay, trapping touch users. */
  .nav-toggle{display:inline-flex;position:relative;z-index:100}
  .header-call{
    display:inline-flex;align-items:center;justify-content:center;flex:none;
    width:48px;height:48px;margin-right:var(--s2);
    background:var(--orange-700);color:#fff;border-radius:var(--radius);
    text-decoration:none;
  }
  .header-call svg{width:20px;height:20px}
  .site-header--dark.is-over-hero .header-call{background:var(--orange-300);color:var(--ink-900)}

  .nav{
    position:fixed;inset:0;z-index:99;
    flex-direction:column;align-items:stretch;justify-content:center;gap:var(--s2);
    background:var(--ink-900);padding:var(--s8) var(--gutter) var(--s6);
    transform:translateY(-100%);visibility:hidden;
    /* visibility flips only AFTER the slide-out, so links are never focusable
       while off-screen */
    transition:transform var(--dur-reveal) var(--ease),
               visibility 0s linear var(--dur-reveal);
    overflow-y:auto;
  }
  .nav.is-open{
    transform:translateY(0);visibility:visible;
    transition:transform var(--dur-reveal) var(--ease),visibility 0s;
  }
  .nav__link{
    color:var(--text-inv);font-size:1.4rem;
    padding:var(--s4) 0;border-bottom:1px solid rgb(240 166 94/.18);
  }
  .nav__link::after{display:none}
  .nav__link[aria-current="page"]{color:var(--orange-300)}
  .nav .btn{margin-top:var(--s5);--btn-bg:var(--orange-300);--btn-fg:var(--ink-900);--btn-bd:var(--orange-300)}
  body.nav-open{overflow:hidden}
}

/* ---------- Hero ---------- */
.hero{
  position:relative;background:var(--ink-900);color:var(--text-inv);
  margin-top:calc(var(--header-h) * -1);
  padding-top:calc(var(--header-h) + clamp(3rem,7vw,5.5rem));
  padding-bottom:clamp(3rem,7vw,5.5rem);
  overflow:hidden;isolation:isolate;
}
/* PHONE ONLY. The background photograph is a CSS background, not an <img>:
   desktop then never downloads it, and it can never end up as a flex child of
   .hero (which is exactly how it landed beside the copy instead of behind it).
   Desktop keeps the contained portrait panel it has always had. */
@media (max-width:899px){
  .hero{
    min-height:min(88svh,820px);display:flex;align-items:center;
    background-image:url("../img/hero-bg-portrait-900.jpg");
    background-size:cover;background-position:center;
  }
}
/* Full-bleed photograph behind the copy. The <picture> swaps a tall crop for a
   wide one at 900px, so neither shape is produced by distorting the other.
   --ink-900 sits underneath: if the image never loads the hero is simply dark
   and the white type is still perfectly readable. */
/* Hero photograph. Their images cap at 619px wide, so this is a contained
   portrait panel rather than a full-bleed background — it never upscales. */
.hero__media{position:relative;isolation:isolate;justify-self:end;max-width:619px;width:100%;display:none}
.hero__media img{width:100%;height:auto;border-radius:var(--radius-card);border:1px solid rgb(240 166 94/.22)}
.hero__media::after{
  content:"";position:absolute;inset:auto -14px -14px auto;width:52%;height:52%;
  border-right:2px solid var(--orange-500);border-bottom:2px solid var(--orange-500);
  border-radius:0 0 var(--radius-card) 0;z-index:-1;pointer-events:none;
}


/* The exploded build-up diagram, now in the "why it lasts" section where a
   diagram is the right tool — rather than in the hero pretending to be a photo. */
.buildup-viz{
  position:relative;width:100%;aspect-ratio:16/10;
  border-radius:var(--radius-card);overflow:hidden;
  background:radial-gradient(78% 74% at 52% 46%,#2E2A27 0%,#211E1C 48%,#141414 100%);
  border:1px solid var(--ink-600);
}
.buildup-viz canvas{position:absolute;inset:0;width:100%;height:100%}
/* 16/10 leaves the diagram only ~204px tall on a 375px phone, which is too
   short to read a five-layer stack. Give it more height where width is scarce. */
@media (max-width:700px){ .buildup-viz{aspect-ratio:4/3} }
@media (max-width:420px){ .buildup-viz{aspect-ratio:1/1} }
.buildup-caption{font-size:.875rem;color:var(--text-inv-muted);margin:var(--s3) 0 0;max-width:52ch}

/* ---------- Work grid ----------
   The old galleries mixed 619x1100 portraits with 1067x800 landscapes in a
   CSS-columns masonry, which is why they read as scattered. Every card here is
   the same square instead, so the set looks deliberate. The photographs are
   pre-cropped square at build time; object-fit:cover only absorbs rounding. */
.workgrid{
  display:grid;gap:var(--s4);
  grid-template-columns:repeat(auto-fill,minmax(min(100%,230px),1fr));
}
.workgrid figure{margin:0}
.workgrid img{
  display:block;width:100%;aspect-ratio:1;object-fit:cover;
  border-radius:var(--radius-card);background:var(--bone-200);
}
.workgrid figcaption{
  font-size:.8125rem;color:var(--text-muted);
  padding-top:var(--s3);line-height:1.5;
}
.section--dark .workgrid figcaption{color:var(--text-inv-muted)}
.workgrid__head{
  grid-column:1/-1;margin:0 0 calc(var(--s2) * -1);
  font-family:var(--font-display);font-size:.75rem;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:var(--text-muted);
}
.section--dark .workgrid__head{color:var(--orange-300)}
.workgrid__head:not(:first-child){margin-top:var(--s6)}

/* ---------- Before / after wipe ----------
   The "before" is clipped with clip-path rather than a wrapper with overflow,
   because a wrapper that changes width squashes the image inside it. clip-path
   only changes what is painted, so the photo never distorts.
   The control is a real <input type=range>: that hands us pointer drag, touch
   drag, click-to-jump, arrow keys, Home/End and screen-reader semantics without
   writing any of it — and it stays operable if our JS never runs. */
.ba{
  --pos:50%;
  position:relative;isolation:isolate;overflow:hidden;
  border-radius:var(--radius-card);border:1px solid var(--ink-600);
  background:var(--ink-900);line-height:0;
  /* the figure itself is the drag surface. pan-y keeps a vertical swipe
     scrolling the page; horizontal gestures come to us as pointer events */
  touch-action:pan-y;cursor:ew-resize;
  -webkit-user-select:none;user-select:none;
}
.ba img{display:block;width:100%;height:auto}
.ba__before{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  clip-path:inset(0 calc(100% - var(--pos)) 0 0);
}
.ba__line{
  position:absolute;top:0;bottom:0;left:var(--pos);width:2px;margin-left:-1px;
  background:#fff;box-shadow:0 0 0 1px rgb(0 0 0/.28);pointer-events:none;z-index:2;
}
.ba__range{
  position:absolute;inset:0;width:100%;height:100%;margin:0;padding:0;
  -webkit-appearance:none;appearance:none;background:transparent;
  cursor:ew-resize;z-index:3;touch-action:pan-y;pointer-events:none;
}
.ba__range::-webkit-slider-runnable-track{background:transparent;border:0;height:100%}
.ba__range::-moz-range-track{background:transparent;border:0;height:100%}
/* The native thumb is kept at full size so it stays an easy grab target, but is
   painted transparent: a full-height range puts its thumb at the top of the
   track, not the middle, so the VISIBLE handle is .ba__grip instead, centred
   properly. Dragging is unaffected — pointer-down anywhere on a range jumps to
   that value and begins a drag, so the whole photo is draggable. */
.ba__range::-webkit-slider-thumb{
  -webkit-appearance:none;appearance:none;
  width:48px;height:48px;border-radius:50%;
  background:transparent;border:0;cursor:ew-resize;
}
.ba__range::-moz-range-thumb{
  width:48px;height:48px;border-radius:50%;box-sizing:border-box;
  background:transparent;border:0;cursor:ew-resize;
}
.ba__range:focus{outline:none}
.ba__grip{
  position:absolute;top:50%;left:var(--pos);z-index:2;
  width:48px;height:48px;margin:-24px 0 0 -24px;border-radius:50%;
  background:var(--orange-300);border:3px solid #fff;
  box-shadow:0 3px 14px rgb(0 0 0/.4);
  pointer-events:none;display:grid;place-items:center;
}
/* focus lands on the input, but the thing the eye tracks is the grip */
.ba:has(.ba__range:focus-visible) .ba__grip{outline:3px solid #fff;outline-offset:3px}
.ba:has(.ba__range:focus-visible) .ba__line{box-shadow:0 0 0 2px rgb(255 255 255/.6)}
.ba__grip svg{width:22px;height:22px;color:var(--ink-900)}
.ba__tag{
  position:absolute;top:var(--s4);z-index:2;pointer-events:none;
  padding:.35rem .75rem;border-radius:999px;
  background:rgb(20 20 20/.74);color:var(--text-inv);
  font-family:var(--font-display);font-size:.6875rem;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;line-height:1.6;
}
.ba__tag--before{left:var(--s4)}
.ba__tag--after{right:var(--s4)}
/* TOUCH DEVICES.
   The range was stretched over the whole photograph. On a phone that meant every
   swipe intended to scroll the page started life as a grab on the slider, and
   every stray tap threw the divider across the image. Confining the control to a
   band around the handle fixes both: the rest of the photo scrolls like any
   ordinary image, and the draggable area is where it visibly appears to be.
   touch-action:pan-y is still what lets a vertical swipe STARTING on the band
   scroll the page rather than fighting it. */
@media (pointer:coarse), (max-width:820px){
  .ba__grip{width:56px;height:56px;margin:-28px 0 0 -28px}
  .ba__grip svg{width:26px;height:26px}
}
@media (max-width:520px){
  .ba__tag{font-size:.625rem;padding:.3rem .6rem}
}

/* The "black shadow" over the photograph. Tuned against the BRIGHTEST part of
   each image rather than its average — white type only has to fail once to be
   unreadable. On a phone the copy sits over the whole frame so the darkening is
   even; on desktop the copy is left-aligned so it is weighted left. */
/* ::before is the desktop ambient gradient. It MUST NOT run on a phone: a
   negative-z-index child paints above its parent's own background, so it would
   sit on top of the background photograph and hide it entirely. */
@media (min-width:900px){
  .hero::before{
    content:"";position:absolute;inset:0;z-index:-3;
    background:radial-gradient(88% 70% at 70% 45%,#3A3330 0%,#242020 46%,#141414 100%);
  }
}
.hero::after{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(180deg,
    rgb(16 16 16/.86) 0%, rgb(16 16 16/.82) 45%, rgb(16 16 16/.90) 100%);
}
@media (min-width:900px){
  .hero::after{
    background:linear-gradient(100deg,var(--ink-900) 0%,rgb(20 20 20/.86) 34%,rgb(20 20 20/.30) 60%,rgb(20 20 20/.08) 100%);
  }
}
/* Secondary hero text is brightened from the on-dark muted token. That token is
   mixed for a FLAT --ink-900 panel; over a photograph whose brightest pixels are
   pure white it measured 3.31:1 even under the scrim. These clear 4.5:1 against
   the worst pixel in either background image. */
/* Brightened only where the copy sits on a photograph. On desktop the copy is
   over a flat dark gradient, so the original tokens are kept untouched. */
@media (max-width:899px){
  .hero .hero__lead,
  .hero .hero__trust{color:#E8E4DE}
  .hero .eyebrow{color:#F7C48C}
}
.hero__grid{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s7);align-items:center}
.hero__copy{max-width:38rem}
.hero h1{color:var(--text-inv);font-size:clamp(2.6rem,1.5rem + 5vw,5.5rem);letter-spacing:-.025em}
.hero h1 em{font-style:normal;color:var(--orange-300);display:block}
.hero__lead{color:var(--text-inv-muted);font-size:clamp(1.08rem,1rem + .4vw,1.3rem);margin-top:var(--s5);max-width:46ch}
.hero__actions{display:flex;flex-wrap:wrap;gap:var(--s3);margin-top:var(--s6)}
.hero__actions .btn:first-child{--btn-bg:var(--orange-300);--btn-fg:var(--ink-900);--btn-bd:var(--orange-300)}
.hero__actions .btn:first-child:hover{--btn-bg:#F7C48C;--btn-bd:#F7C48C;--btn-fg:var(--ink-900)}
.hero__trust{
  display:flex;flex-wrap:wrap;gap:var(--s2) var(--s5);margin-top:var(--s7);
  padding-top:var(--s5);border-top:1px solid rgb(240 166 94/.24);
  font-family:var(--font-display);font-size:.8125rem;font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;color:var(--text-inv-muted);
}
.hero__trust span{display:flex;align-items:center;gap:var(--s2)}
.hero__trust span::before{content:"";width:6px;height:6px;background:var(--orange-500);flex:none;transform:rotate(45deg)}

/* Split at 900, not 980: between the two the photo dropped below the fold and
   the first screen was copy against a half-empty dark field. */
@media (min-width:900px){
  .hero{min-height:min(86svh,840px);display:flex;align-items:center}
  .hero__grid{grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr)}
  .hero__media{display:block}
  .hero h1{font-size:clamp(2.4rem,.5rem + 3.9vw,4.75rem)}
}
@media (max-width:640px){
  .hero{padding-top:calc(var(--header-h) + 2rem);padding-bottom:2.5rem}
  .hero h1{font-size:clamp(2.3rem,1.4rem + 4.4vw,3rem)}
  .hero__lead{margin-top:var(--s4);font-size:1.0625rem}
  .hero__actions{margin-top:var(--s5)}
  .hero__actions .btn{width:100%}
  .hero__trust{margin-top:var(--s5);padding-top:var(--s4);gap:var(--s1) var(--s4);font-size:.6875rem;letter-spacing:.08em}
}

/* ---------- Forms ---------- */
.field{margin-bottom:var(--s5)}
.field label{
  display:block;margin-bottom:var(--s2);
  font-family:var(--font-display);font-size:.875rem;font-weight:600;letter-spacing:.03em;
}
.field .req{color:var(--orange-700)}
.section--dark .field .req{color:var(--orange-300)}
input[type=text],input[type=tel],input[type=email],select,textarea{
  width:100%;min-height:48px;padding:var(--s3) var(--s4);
  background:#fff;color:var(--text);
  border:1px solid var(--bone-300);border-radius:var(--radius);
  font-family:var(--font-body);font-size:1rem;line-height:1.5;
  transition:border-color var(--dur-micro) var(--ease),box-shadow var(--dur-micro) var(--ease);
}
textarea{min-height:130px;resize:vertical}
select{appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='%2357534E' d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 1rem center;background-size:12px;padding-right:2.5rem}
input:focus,select:focus,textarea:focus{
  outline:none;border-color:var(--orange-700);box-shadow:0 0 0 3px rgb(168 86 20/.16)
}
.field-error{display:block;margin-top:var(--s2);color:#A32F1E;font-size:.875rem;font-weight:500}
.section--dark .field-error{color:#F0A08F}
input[aria-invalid="true"],select[aria-invalid="true"],textarea[aria-invalid="true"]{border-color:#A32F1E}
.form-note{font-size:.8125rem;color:var(--text-muted);margin-top:var(--s4)}
.section--dark .form-note{color:var(--text-inv-muted)}
.hp-field{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
/* Never display:none — a hidden element is absent from the accessibility tree,
   so the role="status" region is not registered and the FIRST message is missed. */
.form-status{margin-top:var(--s4);font-size:.9375rem}
.form-status:not(:empty){
  padding:var(--s4);border-radius:var(--radius);
  border:1px solid var(--bone-300);background:var(--bone-100)
}
.form-status--ok{border-color:#2F6B45;background:#EAF3ED;color:#1D4A2E}
.form-status--err{border-color:#A32F1E;background:#FBEDEA;color:#7A2314}

/* ---------- Cards / grids ---------- */
.grid{display:grid;gap:var(--s5)}
.grid--2{grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr))}
.grid--3{grid-template-columns:repeat(auto-fit,minmax(min(100%,290px),1fr))}

.card{
  display:flex;flex-direction:column;
  background:#fff;border:1px solid var(--bone-200);border-radius:var(--radius-card);
  overflow:hidden;text-decoration:none;color:inherit;
  transition:transform var(--dur-reveal) var(--ease),box-shadow var(--dur-reveal) var(--ease),
             border-color var(--dur-reveal) var(--ease);
}
a.card:hover{transform:translateY(-4px);box-shadow:var(--shadow-lift);border-color:var(--bone-300);color:inherit}
.card__media{position:relative;aspect-ratio:3/4;background:var(--bone-200);overflow:hidden}
.card__media img{width:100%;height:100%;object-fit:cover;transition:transform 600ms var(--ease)}
a.card:hover .card__media img{transform:scale(1.04)}
.card__body{padding:var(--s5);display:flex;flex-direction:column;flex:1}
.card__body h3{margin-bottom:var(--s2)}
.card__body p{font-size:.9375rem;color:var(--text-muted);margin-bottom:var(--s4)}
.card__more{
  margin-top:auto;font-family:var(--font-display);font-weight:600;font-size:.9375rem;
  color:var(--orange-700);display:inline-flex;align-items:center;gap:var(--s2);
}
a.card:hover .card__more{color:var(--ink-900)}
.card__more svg{width:16px;height:16px;transition:transform var(--dur-micro) var(--ease)}
a.card:hover .card__more svg{transform:translateX(3px)}

/* numbered steps */
.step{border-top:2px solid var(--orange-500);padding-top:var(--s5)}
.section--dark .step{border-top-color:var(--orange-500)}
.step__n{
  font-family:var(--font-display);font-size:.8125rem;font-weight:700;letter-spacing:.16em;
  color:var(--orange-700);display:block;margin-bottom:var(--s3)
}
.section--dark .step__n{color:var(--orange-300)}
.step h3{margin-bottom:var(--s2)}
.step p{font-size:.9375rem;color:var(--text-muted);margin:0}
.section--dark .step p{color:var(--text-inv-muted)}

/* ---------- Gallery ----------
   Their photographs are 619x1100 portrait, so the portfolio is built around
   that natively rather than square-cropping the life out of them. */
.gallery{display:grid;gap:var(--s4);grid-template-columns:repeat(auto-fit,minmax(min(100%,260px),1fr))}
.gallery figure{margin:0}
.gallery__item{
  position:relative;display:block;border-radius:var(--radius-card);overflow:hidden;
  background:var(--bone-200);border:1px solid var(--bone-200);
}
.gallery__item img{width:100%;height:100%;object-fit:cover;aspect-ratio:3/4}
.gallery figcaption{font-size:.875rem;color:var(--text-muted);padding-top:var(--s3);line-height:1.5}
/* dark-surface variant — text-muted on ink measures 2.41:1 and fails AA */
.section--dark .gallery figcaption,
.cta-band .gallery figcaption{color:var(--text-inv-muted)}

/* Portfolio layout: keeps each photo's own proportions instead of cropping. */
.gallery--natural{display:block;columns:3;column-gap:var(--s5)}
.gallery--natural figure{break-inside:avoid;margin:0 0 var(--s5);display:inline-block;width:100%}
.gallery--natural .gallery__item img{aspect-ratio:auto;height:auto;object-fit:fill}
@media (max-width:900px){.gallery--natural{columns:2}}
@media (max-width:560px){.gallery--natural{columns:1}}

/* ---------- Proof strip ---------- */
.proof{
  display:grid;gap:var(--s5);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,190px),1fr));
  border-block:1px solid var(--bone-200);padding-block:var(--s6)
}
.proof__k{
  font-family:var(--font-display);font-size:1.5rem;font-weight:700;color:var(--text);
  display:block;line-height:1.2;margin-bottom:var(--s1)
}
.proof__v{font-size:.875rem;color:var(--text-muted);margin:0;line-height:1.5}
/* dark-surface variant — without this the band renders near-black on near-black */
.section--dark .proof{border-block-color:rgb(240 166 94/.24)}
.section--dark .proof__k{color:var(--text-inv)}
.section--dark .proof__v{color:var(--text-inv-muted)}

/* ---------- Testimonials ---------- */
.tgrid{display:grid;gap:var(--s5);grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr))}
.tcard{
  display:flex;flex-direction:column;margin:0;
  background:#fff;border:1px solid var(--bone-200);border-radius:var(--radius-card);
  padding:var(--s6);border-top:3px solid var(--orange-500);
}
.section--dark .tcard{background:var(--ink-800);border-color:var(--ink-600);border-top-color:var(--orange-500)}
.tcard blockquote{margin:0 0 var(--s5);font-size:1.0625rem;line-height:1.62;color:var(--text)}
.section--dark .tcard blockquote{color:var(--text-inv)}
.tcard blockquote p{margin:0 0 var(--s3);max-width:none}
.tcard blockquote p:last-child{margin-bottom:0}
.tcard figcaption{
  margin-top:auto;padding-top:var(--s4);border-top:1px solid var(--bone-200);
  font-family:var(--font-display);font-size:.875rem;font-weight:600;
}
.section--dark .tcard figcaption{border-top-color:var(--ink-600);color:var(--text-inv)}
.tcard figcaption span{
  display:block;font-family:var(--font-body);font-weight:400;font-size:.8125rem;
  letter-spacing:.05em;text-transform:uppercase;color:var(--text-muted);margin-top:var(--s1)
}
.section--dark .tcard figcaption span{color:var(--text-inv-muted)}

/* ---------- FAQ ---------- */
.faq{border-top:1px solid var(--bone-200);max-width:820px}
.faq details{border-bottom:1px solid var(--bone-200)}
.faq summary{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s4);
  padding:var(--s5) 0;cursor:pointer;list-style:none;
  font-family:var(--font-display);font-size:1.1rem;font-weight:600;
}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{
  content:"";flex:none;width:12px;height:12px;
  border-right:2px solid var(--orange-700);border-bottom:2px solid var(--orange-700);
  transform:rotate(45deg) translateY(-3px);transition:transform var(--dur-micro) var(--ease)
}
.faq details[open] summary::after{transform:rotate(-135deg) translateY(-3px)}
.faq details > div{padding-bottom:var(--s5)}
.faq p{margin-bottom:var(--s3)}
.faq p:last-child{margin-bottom:0}

/* ---------- Split feature ---------- */
.split{display:grid;gap:clamp(2rem,5vw,4rem);align-items:center}
@media (min-width:860px){
  .split{grid-template-columns:repeat(2,minmax(0,1fr))}
  .split--reverse .split__media{order:2}
}
/* isolate: the ::after rule sits at z-index -1. Without its own stacking context
   it paints behind the nearest ancestor background and vanishes on tinted sections. */
.split__media{position:relative;isolation:isolate}
/* Cap the frame at the asset's own width — their photos are small and the split
   column is wider than several of them, which would upscale and go soft. */
.split__media--narrow{max-width:450px}
.split__media img{width:100%;border-radius:var(--radius-card);border:1px solid var(--bone-200)}
.split__media::after{
  content:"";position:absolute;inset:auto -14px -14px auto;width:56%;height:56%;
  border-right:2px solid var(--orange-500);border-bottom:2px solid var(--orange-500);
  border-radius:0 0 var(--radius-card) 0;z-index:-1;pointer-events:none
}

/* ---------- CTA band ---------- */
.cta-band{background:var(--ink-900);color:var(--text-inv);position:relative;overflow:hidden}
.cta-band::before{
  content:"";position:absolute;inset:0;
  background:radial-gradient(68% 120% at 85% 50%,rgb(224 129 39/.22) 0%,transparent 62%);
  pointer-events:none
}
.cta-band .container{position:relative}
.cta-band h2{color:var(--text-inv)}
.cta-band p{color:var(--text-inv-muted)}
.cta-band__actions{display:flex;flex-wrap:wrap;gap:var(--s3);margin-top:var(--s6)}
.cta-band__actions .btn:first-child{--btn-bg:var(--orange-300);--btn-fg:var(--ink-900);--btn-bd:var(--orange-300)}
.cta-band__actions .btn:first-child:hover{--btn-bg:#F7C48C;--btn-bd:#F7C48C}

/* ---------- Footer ---------- */
.site-footer{background:var(--ink-800);color:var(--text-inv-muted);padding-block:var(--s8) var(--s6);font-size:.9375rem}
.site-footer a{color:var(--text-inv-muted);text-decoration:none}
.site-footer a:hover{color:var(--orange-300);text-decoration:underline}
.footer__grid{display:grid;gap:var(--s6);grid-template-columns:repeat(auto-fit,minmax(min(100%,215px),1fr))}
.footer__h{
  font-family:var(--font-display);font-size:.8125rem;font-weight:700;letter-spacing:.16em;
  text-transform:uppercase;color:var(--text-inv);margin:0 0 var(--s4)
}
.site-footer ul{list-style:none;padding:0;margin:0}
.site-footer li{margin-bottom:var(--s3);max-width:none}
.site-footer .brand__name{color:var(--text-inv)}
.site-footer .brand__sub{color:var(--text-inv-muted)}
.footer__tagline{margin:var(--s4) 0 0;font-size:.9375rem;max-width:34ch;color:var(--text-inv-muted)}
.footer__bottom{
  margin-top:var(--s7);padding-top:var(--s5);border-top:1px solid rgb(240 166 94/.18);
  display:flex;flex-wrap:wrap;gap:var(--s3) var(--s5);align-items:center;justify-content:space-between;
  font-size:.8125rem
}
.footer__legal{display:flex;flex-wrap:wrap;gap:var(--s2) var(--s5);margin:0;list-style:none;padding:0}
.footer__legal li{margin:0}
.footer__ccb{
  font-family:var(--font-display);letter-spacing:.1em;text-transform:uppercase;font-size:.75rem;
  color:var(--text-inv-muted)
}

/* ---------- Page head (inner pages) ---------- */
.page-head{background:var(--bone-100);border-bottom:1px solid var(--bone-200);padding-block:clamp(2.5rem,5vw,4.5rem)}
.page-head h1{margin-bottom:var(--s4)}
.page-head .lead{max-width:56ch;margin:0}
.breadcrumb{
  display:flex;flex-wrap:wrap;gap:var(--s2);list-style:none;padding:0;
  margin:0 0 var(--s5);font-size:.8125rem;color:var(--text-muted)
}
.breadcrumb li{margin:0;display:flex;align-items:center;gap:var(--s2)}
.breadcrumb li + li::before{content:"/";color:var(--bone-300)}
.breadcrumb a{color:var(--text-muted);text-decoration:none}
.breadcrumb a:hover{color:var(--orange-700);text-decoration:underline}

/* ---------- Prose (legal) ---------- */
.prose{max-width:72ch}
.prose h2{margin:var(--s8) 0 var(--s4)}
.prose h3{margin:var(--s6) 0 var(--s3)}
.prose h2:first-child{margin-top:0}
.prose ul{margin-bottom:var(--s5)}
.prose__meta{color:var(--text-muted);font-size:.9375rem;margin-bottom:var(--s7)}

/* ---------- Scroll reveal (IntersectionObserver-driven) ---------- */
.reveal{opacity:0;transform:translateY(18px);transition:opacity var(--dur-hero) var(--ease),transform var(--dur-hero) var(--ease)}
.reveal.is-in{opacity:1;transform:none}
.reveal[data-delay="1"]{transition-delay:80ms}
.reveal[data-delay="2"]{transition-delay:160ms}
.reveal[data-delay="3"]{transition-delay:240ms}

/* ---------- Utilities ---------- */
.visually-hidden{
  position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0
}
.text-center{text-align:center}
.mt-0{margin-top:0}.mb-0{margin-bottom:0}
.stack > * + *{margin-top:var(--s4)}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{
    animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important
  }
  .reveal{opacity:1!important;transform:none!important}
  a.card:hover{transform:none}
  a.card:hover .card__media img{transform:none}
}

/* ---------- Print ---------- */
@media print{
  .site-header,.nav,.buildup-viz,.cta-band{display:none!important}
  body{background:#fff;color:#000;font-size:11pt}
  a[href^="http"]::after{content:" (" attr(href) ")";font-size:9pt;color:#555}
}

/* ---------- Phone refinements ----------
   Collected here rather than scattered so the mobile behaviour is reviewable
   in one place. */
@media (max-width:600px){
  /* four full-width rows of proof pushed the services section a whole screen
     down; two-up keeps the same information in half the height */
  .proof{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s5) var(--s4)}
  .proof__v{font-size:1.35rem}
}
/* ==========================================================================
   PHONE PASS — from an eight-page audit at 360 / 390 / 430px.
   Appended rather than edited in place so every fix sits next to the problem
   it solves; equal-specificity later rules win over the originals above.
   ========================================================================== */

/* 1. figcaptions inside figure.gallery__item were clipped to 1px. The figure is
      overflow:hidden and the image was height:100%, so the image grew to the
      figure's full auto height — image PLUS caption — and pushed the caption
      past the clip. Measured: caption top at 420px inside a 421px figure. */
.gallery__item img{height:auto}
figure.gallery__item > figcaption{padding:var(--s3) var(--s4) var(--s4)}

/* 2. Tall portrait split photos filled a whole phone screen before any copy,
      and the photo precedes the copy in DOM order. A max-height cap, NOT a
      forced ratio: two split images are landscape/square and a blanket 3/4
      would make those taller instead of shorter. */
@media (max-width:859px){
  .split__media img{max-height:56vh;max-height:56svh;object-fit:cover;object-position:50% 35%}
}

/* 3 + 4. Tap targets. Inline tel: links in the legal prose, breadcrumb links
   and footer links all measured 22–29px tall against a 44px minimum, and the
   two phone numbers sat one 29px line apart — a fat-finger tap dialled the
   wrong person. Visible text size is unchanged; only the hit box grows, and
   the surrounding margins shrink to absorb it. */
.prose a[href^="tel:"]{display:inline-block;padding-block:.5rem;font-weight:600}
.prose .contact-lines{list-style:none;padding:0;margin:0 0 var(--s4)}
.prose .contact-lines li{margin-bottom:var(--s2)}
.breadcrumb a{display:inline-block;padding-block:.7rem}
.breadcrumb{margin-bottom:var(--s4)}
.site-footer li a{display:inline-block;padding-block:.6rem}
.site-footer li{margin-bottom:var(--s1)}

/* 5. The closing CTA never got the full-width treatment its twin in the hero
      has, so both buttons wrapped onto their own shrink-to-fit row with dead
      space beside them. On /tile this is the only CTA on the page. */
@media (max-width:640px){
  .cta-band__actions .btn{width:100%}
}

/* 6. The wordmark wrapped to two lines at 360–390px. Reclaiming ~32px from the
      header chrome keeps it on one line; overflow:hidden is the safety net so
      a too-tight fit truncates rather than wraps. */
@media (max-width:520px){
  .site-header__inner{gap:var(--s3)}
  .header-call{margin-right:0}
  .brand__text{overflow:hidden}
  .brand__name{font-size:.9375rem;letter-spacing:0;white-space:nowrap}
}
@media (max-width:400px){ .brand__name{font-size:.875rem} }

/* 7. .prose h2 carried a flat 64px top margin that never scaled. Across the
      eleven headings on /privacy that is ~700px of margin to scroll past.
      .prose h2:first-child{margin-top:0} has higher specificity and still wins. */
@media (max-width:600px){
  .prose h2{margin-top:clamp(2.25rem,9vw,4rem)}
}