@import "_tokens.css";
@import "sections/_shared.css";
@import "_header-footer.css";
@import "_projects.css";
@import "_expertise.css";
@import "_news.css";
@import "_reveal.css";
@import "_text-reveal.css";
@import "_image-reveal.css";
@import "_swipe-stage.css";
@import "_lenis.css";
@import "_links.css";
@import "_global-animations.css";

/* Self-hosted brand fonts (drop woff2 into assets/fonts/; graceful fallback until then) */
@font-face { font-family: "Konfus"; src: url("../fonts/konfus.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "Arial Nova"; src: url("../fonts/arial-nova.woff2") format("woff2"); font-weight: 300; font-display: swap; }
@font-face { font-family: "Arial Nova"; src: url("../fonts/arial-nova-regular.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "Arial Nova"; src: url("../fonts/arial-nova-bold.woff2") format("woff2"); font-weight: 700; font-display: swap; }

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scrollbar-gutter: stable; }
body { margin: 0; font-family: var(--font-body); font-weight: 300; font-size: var(--text-body-lg); line-height: var(--lh-body); color: var(--c-text); background: var(--c-bg); -webkit-font-smoothing: antialiased; }
h1, h2 { font-family: var(--font-display); font-weight: 400; color: var(--c-heading); margin: 0 0 0.3em; }
h1 { font-size: var(--text-h1); line-height: var(--lh-hero); }
h2 { font-size: var(--text-h2); line-height: var(--lh-tight); }
h3 { font-size: var(--text-h3); line-height: var(--lh-quote); }
h3, h4, h6 { font-family: var(--font-body); color: var(--c-heading); margin: 0 0 0.4em; line-height: var(--lh-snug); }
h4 { font-size: var(--text-h4); font-weight: 300; }
h5 { font-size: var(--text-h5); font-weight: 700; font-family: var(--font-display); }
h6 { font-size: var(--text-h6); font-weight: 400; }
.eyebrow { font-family: var(--font-body); font-size: var(--text-h7); line-height: var(--lh-snug); text-transform: uppercase; letter-spacing: 0.08em; display: inline-block; }
p { margin: 0 0 1em; }
.body-sm { font-size: var(--text-body-sm); }
/* Type-style utilities — apply any design type step to any element. These mirror the H1–H7 / body scale; the
   templates already use them (e.g. <h2 class="t-h5">) but the classes were never defined, so headings fell back
   to the element size. Defining them here is what makes section headings render at their Figma step. */
.t-h1 { font-family: var(--font-display); font-weight: 400; font-size: var(--text-h1); line-height: var(--lh-hero); }
.t-h2 { font-family: var(--font-display); font-weight: 400; font-size: var(--text-h2); line-height: var(--lh-tight); }
.t-h3 { font-family: var(--font-display); font-weight: 400; font-size: var(--text-h3); line-height: var(--lh-quote); }
.t-h4 { font-family: var(--font-body); font-weight: 300; font-size: var(--text-h4); line-height: var(--lh-snug); }
.t-h5 { font-family: var(--font-display); font-weight: 400; font-size: var(--text-h5); line-height: var(--lh-snug); }
.t-h6 { font-family: var(--font-body); font-weight: 400; font-size: var(--text-h6); line-height: var(--lh-snug); }
.t-h7 { font-family: var(--font-body); font-weight: 400; font-size: var(--text-h7); line-height: var(--lh-snug); }
.t-body-lg { font-family: var(--font-body); font-weight: 300; font-size: var(--text-body-lg); line-height: var(--lh-body); }
.t-body-sm { font-family: var(--font-body); font-weight: 300; font-size: var(--text-body-sm); line-height: var(--lh-body); }
a { color: var(--c-link); text-decoration: none; }
a:hover { text-decoration: underline; }
img { max-width: 100%; height: auto; display: block; }
.container { max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
/* 12-column grid primitive. Compose with .container: <div class="container grid">.
   Sections place children with grid-column spans in their own _section-*.css. */
.grid { display: grid; grid-template-columns: repeat(var(--grid-columns, 12), 1fr); gap: var(--grid-gap); }
/* Responsive grid: 12 cols desktop → 6 cols tablet (≤900) → 4 cols mobile (≤600).
   Set on :root so every var(--grid-columns) grid reduces — the .grid primitive AND nested
   sub-grids (.section-header, .lead-statement__copy). 12-col spans are clamped to 1/-1 at
   these widths by the overflow guard in sections/_shared.css so nothing overflows. */
@media (max-width: 900px) { :root { --grid-columns: 6; } }
@media (max-width: 600px) { :root { --grid-columns: 4; } }
/* Phosphor icons inherit colour (currentColor) + size (1em). Nudge inline icons onto the text baseline. */
.ph { vertical-align: -0.15em; line-height: 1; }
/* Page-load logo intro overlay (plays once per session; markup + logic in header.php). */
.intro { position: fixed; inset: 0; width: 100vw; z-index: 9999; display: grid; place-items: center; overflow: hidden; background: var(--color-alabaster); --intro-grid: 80px; }
/* Hide is a grid fade — the alabaster cover is a mesh of tiles that dissolve in a staggered
   diagonal wave, revealing the page. Background drops to transparent instantly (invisible under
   the still-opaque tiles) so the page shows through as the tiles clear. */
.intro.is-done { background: transparent; pointer-events: none; }
/* Faint technical grid overlay (mirrors .cta-band--overlay), zooming out on load, fading with the tiles on exit. */
.intro::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  transform-origin: center;
  background-image:
    repeating-linear-gradient(to right, rgba(30, 23, 17, 0.06) 0 1px, transparent 1px var(--intro-grid, 80px)),
    repeating-linear-gradient(to bottom, rgba(30, 23, 17, 0.06) 0 1px, transparent 1px var(--intro-grid, 80px));
  animation: intro-grid-zoom 1.2s cubic-bezier(0.76, 0, 0.24, 1) backwards;
  transition: opacity .55s ease;
}
.intro.is-done::after { opacity: 0; }
@keyframes intro-grid-zoom {
  from { transform: scale(1.15); opacity: 0; }
  to   { transform: scale(1); opacity: 1; }
}
/* Tile mesh (built in header.php) — each tile fades on its own --d delay for the diagonal wave. */
.intro__tiles { position: absolute; inset: 0; z-index: 0; display: grid; grid-template-columns: repeat(var(--intro-cols, 7), var(--intro-grid, 80px)); grid-template-rows: repeat(var(--intro-rows, 7), var(--intro-grid, 80px)); pointer-events: none; }
.intro__tile { background: var(--color-alabaster); transition: opacity 1.2s ease; transition-delay: var(--d, 0s); }
.intro--quick .intro__tile { transition-duration: .4s; } /* return-visit quick wipe (see header.php) */
.intro.is-done .intro__tile { opacity: 0; }
.intro__lottie { position: relative; z-index: 2; width: min(55vw, 520px); aspect-ratio: 1200 / 900; display: block; transition: transform .6s cubic-bezier(0.76, 0, 0.24, 1), opacity .5s ease; }
.intro.is-done .intro__lottie { transform: scale(.97); opacity: 0; }
.intro__lottie svg { display: block; width: 100%; height: 100%; }
@media (prefers-reduced-motion: reduce) { .intro { display: none; } }

/* Page-transition OUTRO (cover) — the exit half of the wipe (markup in footer.php,
   engine in assets/js/page-transition.js). Mirrors the intro tile mesh so the
   destination's intro dissolve continues it as one alabaster diagonal wave. Kept in
   main.css (not an @import) so ?mtime cache-busts it — see the sticky-hero note. */
.pt-wipe { position: fixed; inset: 0; z-index: 9998; overflow: hidden; pointer-events: none; display: grid; grid-template-columns: repeat(var(--pt-cols, 12), 80px); grid-template-rows: repeat(var(--pt-rows, 8), 80px); }
.pt-wipe.is-covering { pointer-events: auto; } /* block interaction while covering */
/* Transition lives on the base tile (like .intro__tile) so flipping opacity animates it. FADE/SPREAD mirror page-transition.js. */
.pt-wipe__tile { background: var(--color-alabaster); opacity: 0; transition: opacity .4s ease; transition-delay: var(--d, 0s); }
.pt-wipe.is-covering .pt-wipe__tile { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .pt-wipe { display: none; } }

.site-footer { padding-block: var(--gutter); }
.btn { display: inline-block; padding: 0.9em 1.8em; border-radius: var(--radius); background: var(--color-clay); color: var(--color-white); font-family: var(--font-body); font-weight: 400; font-size: var(--text-body-sm); text-decoration: none; transition: opacity 0.2s; }
.btn:hover { opacity: 0.9; text-decoration: none; }
.section--water { background: var(--color-water); color: var(--c-inverse); }
.section--land { background: var(--color-land); color: var(--c-inverse); }
.section--clay { background: var(--color-clay); color: var(--c-inverse); }
.section--skyline { background: var(--color-skyline); color: var(--color-steel); }
.section--water h1, .section--water h2, .section--water h3, .section--land h1, .section--land h2, .section--land h3, .section--clay h1, .section--clay h2, .section--clay h3 { color: var(--c-inverse); }

/* Sticky hero — top-of-page counterpart to the fixed footer (see _header-footer.css). On
   pages that opt in (body.ttw-sticky-hero — see ttw_hero_is_sticky()), the first section
   pins to the top and every following section scrolls up and over it. Only heroes WITHOUT
   their own pinned scroll animation opt in: single project, single news, and Text /
   News-landing heroes — the About & Expertise heroes keep their bespoke zoom/sweep, and
   Home is untouched. Followers carry opaque backgrounds, so the pinned hero is covered as
   they rise. Lives in main.css (not an @import) so the ?mtime cache-bust reaches it. Safe
   with Lenis (native-scroll mode), exactly like the fixed footer.
   NOTE: keep this in main.css — @import-ed partials get no cache-bust (only main.css does). */
body.ttw-sticky-hero .ttw-main > :first-child {
  position: sticky;
  top: 0;
  z-index: 0;
}
body.ttw-sticky-hero .ttw-main > :first-child ~ * {
  position: relative;
  z-index: 1;
}

/* ── Brand line icons (inline SVG, replaces the Phosphor glyphs) ──────────────
   Inherit colour via currentColor and size via 1em, so every existing `.ph`
   hook (font-size sizing, hover translate, caret rotation) keeps driving them. */
svg.ttw-ico {
  display: inline-block;
  width: var(--text-body-sm);
  height: auto;
  fill: none;
  stroke: currentColor;
  vertical-align: -0.15em;
}
/* Header search: circular magnifier button (icon carries its own ring). */
.site-header__search svg.ttw-ico { height: 2.375rem; width: 2.375rem  }
/* Social badges: the linkedin/instagram icons carry their own ring, so drop the
   container border and let the SVG fill it. */
.site-footer__social a { border: 0; }
.site-footer__social a svg.ttw-ico { height: 2.75rem; width: 2.75rem; stroke: var(--color-water); }
/* card-person LinkedIn badge is fully owned by _section-people_grid.css (20×18, no ring). */
