/* ============================================================
   BBH CAPITAL — main.css
   Sections:
     1. Reset & Custom Properties
     2. Base & Typography
     3. Utilities
     4. Components — Buttons
     5. Navigation
     6. Hero
     7. About / Thesis
     8. Portfolio
     9. Insights
    10. Contact
    11. Footer
    12. Animations
    13. Responsive
   ============================================================ */


/* ──────────────────────────────────────
   1. RESET & CUSTOM PROPERTIES
────────────────────────────────────── */

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

:root {
  /* Colour palette */
  --black:       #0A0A0A;
  --white:       #FFFFFF;
  --off-white:   #F8F7F5;
  --light-grey:  #EBEBEB;
  --mid-grey:    #ABABAB;
  --dark-grey:   #555555;

  --navy:       #0D2045;

  /* Single warm accent — used very sparingly (filter pill,
     nav link hover, featured tag) to keep the restrained palette
     from feeling completely austere. */
  --accent:        #B45F2C;
  --accent-soft:   rgba(180, 95, 44, 0.12);

  /* Nav metrics referenced from JS as well */
  --nav-height: 72px;

  /* Typography */
  --serif: 'Cormorant Garamond', serif;
  --sans:  'DM Sans', sans-serif;
}

html {
  scroll-behavior: smooth;
}


/* ──────────────────────────────────────
   2. BASE & TYPOGRAPHY
────────────────────────────────────── */

html {
  overflow-x: hidden;
}

body {
  font-family: var(--sans);
  background: var(--white);
  color: var(--black);
  font-size: 15px;
  line-height: 1.65;
}


/* ──────────────────────────────────────
   3. UTILITIES
────────────────────────────────────── */

.container {
  /* Matches the nav's edge-to-edge layout — 60px gutter on each side,
     no inner cap, so content fills the same horizontal band as the
     logo and nav links above. */
  width: 100%;
  margin: 0 auto;
  padding: 0 60px;
}

section {
  padding: 100px 0;
}

/* Per-section rhythm — slightly varied paddings instead of one uniform
   pulse, so the page reads as a composition rather than a stack of
   equal slabs. */
#portfolio { padding: 140px 0 100px; }
#insights  { padding:  80px 0  80px; }
#contact   { padding: 120px 0 100px; }

.hidden {
  display: none !important;
}

/* Section-level hide — keeps markup, removes from layout */
.is-hidden-section {
  display: none !important;
}

.divider {
  width: 100%;
  height: 1px;
  background: var(--light-grey);
}

/* Section labels */
.section-eyebrow {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 20px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--mid-grey);
}

.section-eyebrow::before {
  content: '';
  display: inline-block;
  width: 24px;
  height: 1px;
  background: var(--mid-grey);
}

/* Section titles */
.section-title {
  font-family: var(--serif);
  font-size: clamp(34px, 4vw, 54px);
  font-weight: 300;
  line-height: 1.1;
  letter-spacing: -0.01em;
  margin-bottom: 20px;
}

.section-title em {
  font-style: italic;
}

.section-title--flush {
  margin-bottom: 0;
}

/* Body copy */
.section-desc {
  font-size: 15px;
  font-weight: 300;
  color: var(--dark-grey);
  max-width: 500px;
  line-height: 1.75;
}

.section-desc--spaced {
  margin-bottom: 24px;
}


/* ──────────────────────────────────────
   4. COMPONENTS — BUTTONS
────────────────────────────────────── */

.btn-primary {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  background: var(--black);
  color: var(--white);
  padding: 14px 28px;
  border-radius: 2px;
  text-decoration: none;
  border: 1px solid var(--black);
  transition: background 0.2s, color 0.2s;
  cursor: pointer;
}

.btn-primary:hover {
  background: #333;
}

.btn-outline {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  background: transparent;
  color: var(--black);
  padding: 14px 28px;
  border-radius: 2px;
  text-decoration: none;
  border: 1px solid var(--light-grey);
  transition: border-color 0.2s;
  cursor: pointer;
}

.btn-outline:hover {
  border-color: var(--black);
}

.btn-outline--nowrap {
  white-space: nowrap;
}


/* ──────────────────────────────────────
   5. NAVIGATION
────────────────────────────────────── */

body > nav {
  position: sticky;
  top: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 60px;
  height: var(--nav-height);
  /* Solid at rest (over the hero); transitions to a translucent
     frosted state once the user has scrolled past the hero edge. */
  background: #FFFFFF;
  border-bottom: 1px solid transparent;
  transition: background 0.25s ease, border-color 0.25s ease,
              backdrop-filter 0.25s ease;
}

body > nav.is-scrolled {
  background: rgba(255, 255, 255, 0.72);
  -webkit-backdrop-filter: saturate(160%) blur(18px);
  backdrop-filter: saturate(160%) blur(18px);
  border-bottom-color: rgba(0, 0, 0, 0.06);
}

/* Logo */
.nav-logo {
  display: flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
  color: var(--black);
}

/* SVG logo mark — sized to sit comfortably alongside the wordmark */
.nav-logo-img {
  display: block;
  height: 48px;
  width: auto;
  /* currentColor is set by the parent .nav-logo colour */
  color: var(--black);
}

/* Inline SVG logo (nav). Strokes use currentColor so the mark colour
   follows .nav-logo's color. Each path is pre-armed for the draw-on
   animation by setting stroke-dasharray + stroke-dashoffset = path length
   from JS on page load; the animation property below then transitions
   dashoffset back to 0. */
.nav-logo-svg {
  display: block;
  height: 48px;
  width: auto;
  color: var(--black);
  overflow: visible;
}

.nav-logo-svg .logo-paths path {
  /* `--len` is injected per-path by JS once getTotalLength() is known. */
  stroke-dasharray: var(--len, 0);
  stroke-dashoffset: var(--len, 0);
  transition: stroke-dashoffset 1.6s cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: var(--delay, 0s);
}

/* Once the .has-drawn class is on the SVG, every path animates its
   dashoffset to 0 — which "draws" the stroke onto the screen. */
.nav-logo-svg.has-drawn .logo-paths path {
  stroke-dashoffset: 0;
}

.logo-text {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--black);
}

/* Two-line stacked wordmark — used in the nav so "BIG BRAIN" sits above
   "HOLDINGS". Letter-spacing matches the rest of the logo type. */
.logo-text--stacked {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.15;
}

.logo-text--stacked .logo-text-line {
  display: block;
  white-space: nowrap;
}

.logo-dot {
  display: inline-block;
  width: 4px;
  height: 4px;
  background: var(--black);
  border-radius: 50%;
  margin: 0 6px;
  vertical-align: middle;
  position: relative;
  top: -1px;
}

/* Nav links */
.nav-links {
  display: flex;
  align-items: center;
  gap: 36px;
  list-style: none;
}

.nav-links a {
  position: relative;
  text-decoration: none;
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--dark-grey);
  transition: color 0.2s;
}

.nav-links a:hover {
  color: var(--black);
}

/* Animated accent underline for non-CTA nav links */
.nav-links a:not(.nav-cta)::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -6px;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}

.nav-links a:not(.nav-cta):hover::after {
  transform: scaleX(1);
}

.nav-cta {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--white) !important;
  background: var(--black);
  padding: 9px 20px;
  border-radius: 2px;
  text-decoration: none;
  transition: opacity 0.2s !important;
}

.nav-cta:hover {
  opacity: 0.75;
}


/* ── Hamburger button (mobile only) ──────────────────────────────── */

.nav-hamburger {
  display: none;
  width: 44px;
  height: 44px;
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
  position: relative;
}

.nav-hamburger-bar {
  position: absolute;
  left: 10px;
  right: 10px;
  height: 1.5px;
  background: var(--black);
  border-radius: 1px;
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1),
              top 0.3s cubic-bezier(0.22, 1, 0.36, 1),
              opacity 0.2s;
}

.nav-hamburger-bar:nth-child(1) { top: 16px; }
.nav-hamburger-bar:nth-child(2) { top: 26px; }

.nav-hamburger.is-open .nav-hamburger-bar:nth-child(1) {
  top: 21px;
  transform: rotate(45deg);
}

.nav-hamburger.is-open .nav-hamburger-bar:nth-child(2) {
  top: 21px;
  transform: rotate(-45deg);
}


/* ── Mobile slide-down panel ─────────────────────────────────────── */

.nav-mobile-panel {
  position: fixed;
  top: var(--nav-height);
  left: 0;
  right: 0;
  z-index: 9998;
  background: var(--white);
  border-bottom: 1px solid var(--light-grey);
  /* Hidden by default — slides down when .is-open is set */
  transform: translateY(-100%);
  opacity: 0;
  pointer-events: none;
  visibility: hidden;
  transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1),
              opacity 0.3s ease,
              visibility 0s linear 0.4s;
}

.nav-mobile-panel.is-open {
  transform: translateY(0);
  opacity: 1;
  pointer-events: auto;
  visibility: visible;
  transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1),
              opacity 0.3s ease,
              visibility 0s linear;
}

.nav-mobile-links {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 20px 24px 28px;
}

.nav-mobile-links a {
  display: block;
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--dark-grey);
  text-decoration: none;
  padding: 14px 0;
  border-bottom: 1px solid var(--light-grey);
  transition: color 0.2s;
}

.nav-mobile-links li:last-child a {
  border-bottom: none;
}

.nav-mobile-links a:hover {
  color: var(--black);
}


/* ──────────────────────────────────────
   6. HERO
────────────────────────────────────── */

#hero {
  min-height: calc(100vh - 72px);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding-top: 120px;
  padding-bottom: 80px;
  position: relative;
  overflow: hidden;
}

/* Bottom-left anchored hero block.
   Width follows the rest of the page: ~70% of the inner band, capped so
   it never gets uncomfortably wide on ultra-wide screens. The headline
   wraps via explicit <br>s, so the wider container just gives the block
   more horizontal room without changing the line layout. */
.hero-content {
  position: relative;
  width: 100%;
  max-width: min(1400px, 70%);
}

/* Background decorations */
.hero-bg-grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(to right, #e8e8e8 1px, transparent 1px),
    linear-gradient(to bottom, #e8e8e8 1px, transparent 1px);
  background-size: 80px 80px;
  opacity: 0.4;
  pointer-events: none;
}

.hero-bg-circle {
  position: absolute;
  right: -120px;
  top: 50%;
  transform: translateY(-50%);
  transform-origin: center center;
  width: 600px;
  height: 600px;
  border-radius: 50%;
  border: 1px solid #d5d5d5;
  pointer-events: none;
  /* Hint to the compositor — the JS scroll handler retargets transform &
     opacity on every frame, so we want this layer promoted up front. */
  will-change: transform, opacity;
}

.hero-bg-circle::before {
  content: '';
  position: absolute;
  inset: 60px;
  border-radius: 50%;
  border: 1px solid #d5d5d5;
}

.hero-bg-circle::after {
  content: '';
  position: absolute;
  inset: 120px;
  border-radius: 50%;
  border: 1px solid #d5d5d5;
}

/* Content — same edge-to-edge band as the nav so the hero text starts in
   line with the BIG BRAIN logo. */
.hero-inner {
  position: relative;
  width: 100%;
  margin: 0 auto;
  padding: 0 60px;
}

.hero-eyebrow {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 36px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--mid-grey);
}

.hero-eyebrow::before {
  content: '';
  display: inline-block;
  width: 36px;
  height: 1px;
  background: var(--mid-grey);
}

.hero-headline {
  font-family: var(--serif);
  /* Floor lowered to 38px so the title doesn't crowd small phones.
     Ceiling unchanged. */
  font-size: clamp(38px, 7vw, 100px);
  font-weight: 300;
  /* Loose line-height so each row's highlight pill sits inside its own row,
     never bleeding into the text of the row above. */
  line-height: 1.22;
  letter-spacing: -0.01em;
  color: var(--black);
  /* Anchor for ::before progress-bar fill. */
  position: relative;
  /* Prevent widow words: in the 1450-1720px viewport range the
     default greedy wrap leaves "a" alone on its own line. `balance`
     asks the browser to pull a neighbour down (so the wrap becomes
     "Backing the visionaries" / "of a" / "world …" instead of
     ".../of" / "a" / "world …"). Older browsers ignore the property
     and keep the current behaviour. */
  text-wrap: balance;
  /* Headline fills the hero-content block; the actual line wrapping is
     controlled by the explicit <br>s in the markup. */
  max-width: 100%;
  margin-bottom: 36px;
}

.hero-headline em {
  font-style: italic;
  font-weight: 300;
}

/* ── Progress-bar fill overlay ──────────────────────────────────────
   The headline gets a navy "progress bar" that sweeps in from the left
   as the user scrolls — ROW BY ROW. Implementation:

     * The base h1 renders the headline as black text.
     * A ::before pseudo, with `content: attr(data-text)`, paints the
       SAME text again — this time white on a navy background — and is
       positioned absolutely on top of the h1, inset to 0 so it
       covers the headline exactly.
     * `clip-path: var(--hero-fill-clip)` reveals the pseudo via a
       per-line SVG path() computed by initHeroFill() — one rectangle
       per text line, each rectangle's width = that line's proportional
       share of the overall scroll progress. So row 1 is fully revealed
       before row 2 starts filling, row 2 before row 3, etc.

   initHeroFill measures the line rectangles via Range.getClientRects()
   on load + resize, then writes the path() value on every
   herolock:progress / scroll event. Stopping mid-scroll freezes the
   clip-path at whatever progress it was on, leaving the word it landed
   in half-painted.

   No CSS transition on clip-path — JS already throttles via rAF and
   we want the bar to track the scroll wheel exactly. A transition
   would introduce lag.
   ──────────────────────────────────────────────────────────────── */
.hero-headline::before {
  content: attr(data-text);
  position: absolute;
  inset: 0;
  background: var(--navy);
  color: #FFFFFF;
  /* Fallback `inset(0 100% 0 0)` clips out everything until JS sets
     the per-line path() — so the pseudo doesn't flash on first paint. */
  clip-path: var(--hero-fill-clip, inset(0 100% 0 0));
  pointer-events: none;
  /* Inherit every font/layout property so the overlay text wraps and
     aligns 1:1 with the base text below. text-wrap: balance inherits
     too, so both render with identical line breaks. */
  font: inherit;
  font-weight: inherit;
  font-style: inherit;
  letter-spacing: inherit;
  line-height: inherit;
  text-wrap: inherit;
  margin: 0;
  padding: 0;
}

.hero-sub {
  font-size: 16px;
  font-weight: 300;
  color: var(--dark-grey);
  /*max-width: 640px;*/
  line-height: 1.75;
  margin-bottom: 52px;
}

.hero-actions {
  display: flex;
  align-items: center;
  gap: 28px;
}

/* Stats bar
   Starts invisible so the hero stays text-first during the
   scroll-locked intro. The `is-revealed` class is added by
   initHeroStatsCounter() once the hero lock unlocks (or the user
   scrolls past ~100px on devices where the lock isn't engaged).

   The !important on opacity/animation overrides the .fade-up
   delay-4 auto-play that all other hero elements use — we want the
   stats to wait, not fade in on page load like the headline.
   The element still occupies layout space throughout so the hero's
   vertical rhythm doesn't shift when the reveal fires. */
.hero-stats {
  display: flex;
  gap: 0;
  margin-top: 80px;
  border-top: 1px solid var(--light-grey);
  padding-top: 40px;
  opacity: 0 !important;
  animation: none !important;
  transform: translateY(16px);
  transition:
    opacity   700ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 700ms cubic-bezier(0.22, 1, 0.36, 1);
}

.hero-stats.is-revealed {
  opacity: 1 !important;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .hero-stats { transition: none; }
}

.hero-stat {
  flex: 1;
  padding-right: 40px;
}

.hero-stat + .hero-stat {
  padding-left: 40px;
  border-left: 1px solid var(--light-grey);
}

.stat-number {
  font-family: var(--serif);
  font-size: 42px;
  font-weight: 300;
  line-height: 1;
  margin-bottom: 8px;
}

.stat-label {
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--mid-grey);
}


/* ── Hero scroll cue ─────────────────────────────────────────────── */

.hero-scroll-cue {
  position: absolute;
  bottom: 28px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  pointer-events: none;
  opacity: 0;
  animation: scrollCueIn 0.6s 1.4s ease-out forwards;
  transition: opacity 0.4s ease;
}

/* Once the user has scrolled even a little the cue fades out. */
body.has-scrolled .hero-scroll-cue {
  opacity: 0 !important;
}

.hero-scroll-label {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--mid-grey);
}

.hero-scroll-line {
  display: block;
  width: 1px;
  height: 44px;
  background: linear-gradient(to bottom,
              transparent 0%,
              var(--mid-grey) 50%,
              var(--mid-grey) 100%);
  position: relative;
  overflow: hidden;
}

/* A small "pulse" dot travels down the line. */
.hero-scroll-line::after {
  content: '';
  position: absolute;
  left: -1px;
  top: 0;
  width: 3px;
  height: 10px;
  background: var(--black);
  border-radius: 2px;
  animation: scrollPulse 2.2s ease-in-out infinite;
}

@keyframes scrollCueIn {
  from { opacity: 0; transform: translate(-50%, 10px); }
  to   { opacity: 0.75; transform: translate(-50%, 0); }
}

@keyframes scrollPulse {
  0%   { transform: translateY(-100%); opacity: 0; }
  30%  { opacity: 1; }
  70%  { opacity: 1; }
  100% { transform: translateY(440%); opacity: 0; }
}



/* ──────────────────────────────────────
   6b. HERO — NAVY DARK THEME  (index.html)
   Full navy background with all child
   elements adapted for dark context.
   ──
   6c. HERO WORD HIGHLIGHT  (index_2.html)
   White background; navy pill on "intelligent".
────────────────────────────────────── */

/* ── Navy hero — active only when <body class="navy-hero"> (index.html) ── */

body.navy-hero #hero                         { background: var(--navy); }

body.navy-hero #hero .hero-bg-grid {
  background-image:
    linear-gradient(to right,  rgba(255,255,255,0.07) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255,255,255,0.07) 1px, transparent 1px);
  opacity: 1;
}

body.navy-hero #hero .hero-bg-circle         { border-color: rgba(255,255,255,0.08); }
body.navy-hero #hero .hero-bg-circle::before,
body.navy-hero #hero .hero-bg-circle::after  { border-color: rgba(255,255,255,0.08); }

body.navy-hero #hero .hero-eyebrow           { color: rgba(255,255,255,0.5); }
body.navy-hero #hero .hero-eyebrow::before   { background: rgba(255,255,255,0.25); }

body.navy-hero #hero .hero-headline          { color: #FFFFFF; }
body.navy-hero #hero .hero-sub               { color: rgba(255,255,255,0.65); }

body.navy-hero #hero .btn-primary            { background: #FFFFFF; color: var(--navy); border-color: #FFFFFF; }
body.navy-hero #hero .btn-primary:hover      { background: rgba(255,255,255,0.88); border-color: rgba(255,255,255,0.88); }

body.navy-hero #hero .btn-outline            { color: rgba(255,255,255,0.85); border-color: rgba(255,255,255,0.25); }
body.navy-hero #hero .btn-outline:hover      { color: #FFFFFF; border-color: rgba(255,255,255,0.7); }

body.navy-hero #hero .hero-stats             { border-top-color: rgba(255,255,255,0.12); }
body.navy-hero #hero .hero-stat + .hero-stat { border-left-color: rgba(255,255,255,0.12); }
body.navy-hero #hero .stat-number            { color: #FFFFFF; }
body.navy-hero #hero .stat-label             { color: rgba(255,255,255,0.45); }

/* Hero headline progress-bar fill — implemented as a ::before pseudo
   on .hero-headline (see the rule a few hundred lines above). No
   per-word or cycle markup anymore — the headline is now a single
   text node and the navy sweeps in as one continuous fill driven by
   --hero-fill from initHeroFill() in main.js. */

/* Legacy class kept for the rare case the old per-word markup is
   ever restored — unused by the current production hero. */
.hero-highlight {
  display: inline;
  background: var(--navy);
  color: #FFFFFF;
  padding: 0.04em 0.22em 0.10em;
  border-radius: 4px;
  font-style: inherit;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* ──────────────────────────────────────
   7. ABOUT / THESIS
────────────────────────────────────── */

#about {
  background: var(--off-white);
}

.about-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 100px;
  align-items: center;
}

/* Focus area cards */
.about-right {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--light-grey);
  border: 1px solid var(--light-grey);
}

.focus-card {
  background: var(--off-white);
  padding: 32px 28px;
  transition: background 0.2s;
}

.focus-card:hover {
  background: var(--white);
}

.focus-icon {
  width: 36px;
  height: 36px;
  margin-bottom: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.focus-card h3 {
  font-family: var(--serif);
  font-size: 20px;
  font-weight: 400;
  margin-bottom: 10px;
  line-height: 1.2;
}

.focus-card p {
  font-size: 13px;
  color: var(--dark-grey);
  line-height: 1.7;
  font-weight: 300;
}


/* ──────────────────────────────────────
   8. PORTFOLIO
────────────────────────────────────── */

#portfolio {
  background: var(--off-white);
}

.portfolio-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  margin-bottom: 48px;
}

/* Filter tabs */
.filter-tabs {
  position: relative;
  display: flex;
  gap: 0;
  border: 1px solid var(--light-grey);
  border-radius: 2px;
  overflow: hidden;
  background: var(--white);
}

/* The animated indicator that slides between tabs. Width and translateX
   are written by JS based on the active tab's geometry. */
.filter-tab-indicator {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  background: var(--black);
  z-index: 0;
  transform: translateX(0);
  width: 0;
  transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1),
              width 0.45s cubic-bezier(0.22, 1, 0.36, 1),
              background 0.3s ease;
  pointer-events: none;
}

.filter-tab {
  position: relative;
  z-index: 1;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 10px 18px;
  border: none;
  background: transparent;
  color: var(--mid-grey);
  cursor: pointer;
  transition: color 0.25s ease;
  border-right: 1px solid var(--light-grey);
}

.filter-tab:last-child {
  border-right: none;
}

.filter-tab:hover {
  color: var(--black);
}

.filter-tab.active {
  /* Indicator paints the bg now — only the text colour changes. */
  color: var(--white);
}

/* Portfolio grid */
.portfolio-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  border: 1px solid var(--light-grey);
}

.portfolio-item {
  border-right: 1px solid var(--light-grey);
  border-bottom: 1px solid var(--light-grey);
  padding: 28px 24px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  /* Two transitions: a generic background swap PLUS a transform/shadow
     pair that handles the hover lift. */
  transition: background 0.2s ease,
              transform 0.35s cubic-bezier(0.22, 1, 0.36, 1),
              box-shadow 0.35s cubic-bezier(0.22, 1, 0.36, 1);
  text-decoration: none;
  color: var(--black);
  cursor: pointer;
  position: relative;
}

/* Subtle navy left-edge accent that grows in on hover. */
.portfolio-item::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--navy);
  transform: scaleY(0);
  transform-origin: top center;
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}

.portfolio-item:nth-child(5n) {
  border-right: none;
}

.portfolio-item:hover {
  background: var(--white);
  transform: translateY(-3px);
  box-shadow: 0 12px 30px -16px rgba(13, 32, 69, 0.22);
  z-index: 1;
}

.portfolio-item:hover::before {
  transform: scaleY(1);
}

.portfolio-item:hover .portfolio-arrow {
  opacity: 1;
  transform: translate(0, 0);
}

.portfolio-arrow {
  position: absolute;
  top: 14px;
  right: 14px;
  font-size: 13px;
  color: var(--mid-grey);
  opacity: 0;
  transform: translate(-4px, 4px);
  transition: opacity 0.2s, transform 0.2s;
}

.portfolio-tag {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mid-grey);
  background: var(--white);
  border: 1px solid var(--light-grey);
  padding: 3px 8px;
  border-radius: 2px;
}

.portfolio-name {
  font-size: 14px;
  font-weight: 500;
  color: var(--black);
  line-height: 1.3;
}

.portfolio-desc {
  font-size: 12px;
  color: var(--dark-grey);
  font-weight: 300;
  line-height: 1.5;
}

/* Logo — sits at the top of each card.
   A fixed-size box (width × height) plus object-fit: contain gives every
   logo the same footprint regardless of the SVG's natural aspect ratio,
   so the grid reads as a consistent row of marks. */
.portfolio-logo {
  display: block;
  width: 100%;
  max-width: 140px;
  height: 40px;
  object-fit: contain;
  object-position: left center;
  margin-bottom: 18px;
  /* Converts any remaining white/light SVG pixels to dark — safe fallback */
  filter: brightness(0);
  opacity: 0.72;
  transition: opacity 0.15s;
}

.portfolio-item:hover .portfolio-logo {
  opacity: 1;
}


/* ──────────────────────────────────────
   9. INSIGHTS
────────────────────────────────────── */

#insights {
  background: var(--white);
}

.insights-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
}

.insights-grid {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  gap: 1px;
  background: var(--light-grey);
  border: 1px solid var(--light-grey);
  margin-top: 48px;
}

.insight-card {
  position: relative;
  background: var(--off-white);
  padding: 36px 32px;
  text-decoration: none;
  color: var(--black);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  transition: background 0.25s ease, transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
  min-height: 280px;
}

.insight-card:hover {
  background: var(--white);
}

/* ── Featured insight (the wider 2fr card) ───────────────────────── */
.insight-card--featured {
  min-height: 360px;
  background: var(--navy);
  color: var(--white);
  padding: 40px 36px;
}

.insight-card--featured:hover {
  background: #122a55; /* one shade up from navy on hover */
}

.insight-card--featured::before {
  content: 'Featured';
  position: absolute;
  top: 24px;
  right: 28px;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent);
  padding: 4px 10px;
  background: var(--accent-soft);
  border-radius: 2px;
}

.insight-date {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--mid-grey);
  margin-bottom: 18px;
}

/* Mid dots inside the editorial date stay subtle */
.insight-date .date-sep {
  opacity: 0.5;
  margin: 0 4px;
}

.insight-card--featured .insight-date {
  color: rgba(255, 255, 255, 0.55);
  font-size: 12px;
  margin-bottom: 24px;
}

.insight-title {
  font-family: var(--serif);
  font-size: 22px;
  font-weight: 400;
  line-height: 1.3;
  margin-bottom: 14px;
}

.insight-card--featured .insight-title {
  font-size: 36px;
  line-height: 1.15;
  color: var(--white);
  margin-bottom: 18px;
}

.insight-excerpt {
  font-size: 13px;
  color: var(--dark-grey);
  line-height: 1.7;
  font-weight: 300;
  flex: 1;
}

.insight-card--featured .insight-excerpt {
  font-size: 14px;
  color: rgba(255, 255, 255, 0.72);
  max-width: 540px;
}

.insight-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--black);
  margin-top: 24px;
  text-decoration: none;
}

.insight-card--featured .insight-link {
  color: var(--white);
}

.insight-link::after {
  content: '→';
  font-size: 14px;
  font-style: normal;
}


/* ── "All Articles" CTA variant (sixth grid cell) ─────────────────
   Subtle accent treatment: very light terracotta tint as background,
   a 2px accent edge along the top, and accent-coloured CTA link.
   Reads as a "different kind" of card without screaming for attention. */

.insight-card--cta {
  background: var(--accent-soft);
  /* Replace the default neutral hover bg with a slightly deeper accent
     wash, and emphasise the top edge on hover. */
  position: relative;
  transition: background 0.25s ease, transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}

.insight-card--cta::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--accent);
  transform: scaleX(1);
  transform-origin: left center;
  transition: opacity 0.3s ease;
}

.insight-card--cta:hover {
  background: rgba(180, 95, 44, 0.18);
}

.insight-date--cta {
  color: var(--accent);
  font-weight: 500;
}

.insight-title--cta {
  color: var(--black);
}

.insight-title--cta em {
  font-style: italic;
  color: var(--accent);
}

.insight-link--cta {
  color: var(--accent);
}


/* ──────────────────────────────────────
   10. CONTACT
────────────────────────────────────── */

#contact {
  background: var(--off-white)
}

.contact-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 100px;
  align-items: flex-start;
}

/* Single-column variant — kept for compatibility */
.contact-grid--single {
  grid-template-columns: 1fr;
  max-width: 640px;
  gap: 0;
}

/* CTA variant — info on the left taking ~70% of the row, button anchored
   flush to the right edge with the remaining empty space between them. */
.contact-grid--cta {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-end;
  gap: 60px;
  /* Cancel the .contact-grid base-grid styles in this variant */
  grid-template-columns: none;
}

.contact-grid--cta .contact-info {
  flex: 1 1 auto;
  width: 100%;
  max-width: min(1200px, 70%);
}

.contact-cta-side {
  flex: 0 0 auto;
  display: flex;
  align-items: flex-end;
}

.contact-cta {
  padding: 16px 32px;
  font-size: 12px;
}

.contact-info p {
  font-size: 16px;
  font-weight: 300;
  color: var(--dark-grey);
  line-height: 1.75;
  margin-bottom: 40px;
  /*max-width: 600px;*/
}

.contact-channels {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.contact-channel {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 13px;
  text-decoration: none;
  color: var(--black);
  font-weight: 400;
  letter-spacing: 0.03em;
  transition: color 0.2s;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--light-grey);
}

.contact-channel:last-child {
  border-bottom: none;
}

.contact-channel:hover {
  color: var(--mid-grey);
}

.channel-label {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid-grey);
  min-width: 80px;
}

/* Form */
.contact-form {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  border-bottom: 1px solid var(--light-grey);
}

.form-row--single {
  grid-template-columns: 1fr;
}

.form-field {
  display: flex;
  flex-direction: column;
  padding: 20px 24px 20px 0;
  gap: 8px;
  border-right: 1px solid var(--light-grey);
}

.form-row .form-field:last-child {
  border-right: none;
  padding-right: 0;
  padding-left: 24px;
}

.form-row--single .form-field {
  border-right: none;
  padding-right: 0;
  padding-left: 0;
}

label {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid-grey);
}

input,
textarea,
select {
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 300;
  color: var(--black);
  background: transparent;
  border: none;
  outline: none;
  width: 100%;
  resize: none;
  line-height: 1.5;
}

input::placeholder,
textarea::placeholder {
  color: var(--mid-grey);
}

textarea {
  min-height: 80px;
}

.form-submit {
  margin-top: 32px;
}


/* ──────────────────────────────────────
   11. FOOTER
────────────────────────────────────── */

footer {
  background: var(--black);
  color: var(--white);
  padding: 60px 0 40px;
}

.footer-inner {
  width: 100%;
  margin: 0 auto;
  padding: 0 60px;
}

.footer-top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  padding-bottom: 48px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  margin-bottom: 40px;
}

/* Footer logo — overrides for dark background */
.footer-logo {
  display: flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
}

/* Invert the SVG mark to white for the dark footer */
.footer-logo .footer-logo-img {
  filter: brightness(0) invert(1);
  opacity: 0.85;
}

.footer-logo .logo-text {
  color: rgba(255, 255, 255, 0.8);
}

.footer-logo .logo-dot {
  background: rgba(255, 255, 255, 0.4);
}

/* Footer nav */
.footer-nav {
  display: flex;
  gap: 60px;
}

.footer-col h4 {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.35);
  margin-bottom: 16px;
}

.footer-col ul {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.footer-col a {
  font-size: 13px;
  font-weight: 300;
  color: rgba(255, 255, 255, 0.65);
  text-decoration: none;
  transition: color 0.2s;
}

.footer-col a:hover {
  color: var(--white);
}

.footer-bottom {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.footer-copy {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.3);
  font-weight: 300;
  letter-spacing: 0.04em;
}

.footer-tagline {
  font-family: var(--serif);
  font-size: 14px;
  color: rgba(255, 255, 255, 0.3);
  font-style: italic;
  font-weight: 300;
}


/* ──────────────────────────────────────
   11b. CONTACT MODAL
────────────────────────────────────── */

.contact-modal {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.contact-modal.is-open {
  display: flex;
}

.contact-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(10, 10, 10, 0.45);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  animation: modalBackdropIn 0.25s ease;
}

.contact-modal-dialog {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 640px;
  max-height: calc(100vh - 48px);
  overflow-y: auto;
  background: var(--white);
  border-radius: 4px;
  padding: 56px 56px 48px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.28);
  animation: modalDialogIn 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}

.contact-modal-header {
  margin-bottom: 32px;
}

.contact-modal-close {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 40px;
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  color: var(--dark-grey);
  cursor: pointer;
  border-radius: 50%;
  transition: background 0.15s, color 0.15s;
}

.contact-modal-close:hover {
  background: var(--light-grey);
  color: var(--black);
}

/* Inside the modal: tighter form footprint */
.contact-modal-dialog .contact-form {
  margin: 0;
}

.contact-modal-dialog .form-submit {
  margin-top: 24px;
}

/* Lock body scroll when modal is open */
body.modal-open {
  overflow: hidden;
}

@keyframes modalBackdropIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes modalDialogIn {
  from { opacity: 0; transform: translateY(24px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}


/* ──────────────────────────────────────
   12. ANIMATIONS
────────────────────────────────────── */

@keyframes fadeUp {
  from {
    opacity: 0;
    transform: translateY(24px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.fade-up {
  animation: fadeUp 0.7s ease forwards;
  opacity: 0;
}

.delay-1 { animation-delay: 0.10s; }
.delay-2 { animation-delay: 0.25s; }
.delay-3 { animation-delay: 0.40s; }
.delay-4 { animation-delay: 0.55s; }
.delay-5 { animation-delay: 0.70s; }


/* ──────────────────────────────────────
   12b. CUSTOM CURSOR

   A small ring + dot that follow the mouse on desktop. The ring scales
   up over interactive elements. Touch devices fall back to the system
   cursor (no pointer events triggered → never visible) but we also
   force-hide them in the responsive block.
────────────────────────────────────── */

.cursor-ring,
.cursor-dot {
  position: fixed;
  top: 0;
  left: 0;
  pointer-events: none;
  z-index: 10001;
  opacity: 0;
  /* Hidden until JS reports the first mousemove, at which point
     .cursor-active is added to <body>. */
  transition: opacity 0.25s ease, transform 0.25s cubic-bezier(0.22, 1, 0.36, 1),
              background-color 0.25s ease, border-color 0.25s ease;
  will-change: transform, opacity;
}

.cursor-ring {
  width: 32px;
  height: 32px;
  margin-left: -16px;
  margin-top: -16px;
  /* White stroke + difference blend mode = the ring inverts to whatever
     contrasts the background. On white sections it reads as black; on the
     navy headline highlight or the dark footer it reads as light. */
  border: 1.5px solid #FFFFFF;
  border-radius: 50%;
  mix-blend-mode: difference;
}

.cursor-dot {
  width: 4px;
  height: 4px;
  margin-left: -2px;
  margin-top: -2px;
  background: #FFFFFF;
  border-radius: 50%;
  mix-blend-mode: difference;
}

body.cursor-active .cursor-ring,
body.cursor-active .cursor-dot {
  opacity: 1;
}

/* When hovering an interactive element, the ring grows + tints toward the
   accent. mix-blend-mode still applies, so the accent reads as its inverted
   complement on light bgs (cyan-ish) and roughly itself on dark bgs — in
   both cases distinctly different from the resting state. */
body.cursor-hover .cursor-ring {
  transform: scale(1.7);
  border-color: var(--accent);
  background: rgba(180, 95, 44, 0.25);
}

/* Pointer over native interactive elements: hide system cursor on those
   so only our custom one is visible (touch devices ignored by media query). */
@media (hover: hover) and (pointer: fine) {
  html,
  body,
  a,
  button,
  input,
  textarea,
  select,
  .filter-tab,
  .portfolio-item,
  .contact-cta {
    cursor: none;
  }
}


/* ──────────────────────────────────────
   13. RESPONSIVE
────────────────────────────────────── */

@media (max-width: 900px) {
  body > nav {
    padding: 0 24px;
  }

  .nav-links {
    display: none;
  }

  /* Show hamburger on narrow viewports */
  .nav-hamburger {
    display: block;
  }

  .nav-logo-svg {
    height: 40px;
  }

  /* Section paddings tighten on mobile */
  section            { padding: 80px 0; }
  #portfolio         { padding: 100px 0 80px; }
  #insights          { padding:  60px 0 60px; }
  #contact           { padding:  80px 0 80px; }

  /* Scroll cue is overkill on mobile */
  .hero-scroll-cue {
    display: none;
  }

  /* Cursor effects don't apply on touch — make sure ring/dot are gone */
  .cursor-ring,
  .cursor-dot {
    display: none !important;
  }

  .hero-inner,
  .container {
    padding: 0 24px;
  }

  /* Let the hero content take the full width of the inner container
     on mobile — the desktop `max-width: min(1400px, 70%)` makes the
     headline wrap into 4-5 fragmented lines at phone widths because
     the content area collapses to ~190px. */
  .hero-content {
    max-width: 100%;
  }

  /* Hide the decorative ring background on mobile — at 600×600 with
     a -120px right offset it occupies the entire viewport behind the
     headline at phone widths, which is visual noise more than
     atmosphere. Desktop still gets it. */
  .hero-bg-circle {
    display: none;
  }

  /* Switch hero-stats to a 2-column grid on mobile so each stat has
     enough horizontal room for its number + label. The desktop
     `flex: 1` rule would otherwise force all four to share one row
     even with flex-wrap, ending up ~62px wide each at 320px. */
  .hero-stats {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 24px 16px;
  }

  .hero-stat {
    flex: none;
    padding-right: 0;
  }

  .hero-stat + .hero-stat {
    border-left: none;
    padding-left: 0;
  }

  .about-grid {
    grid-template-columns: 1fr;
    gap: 48px;
  }

  .about-right {
    grid-template-columns: 1fr 1fr;
  }

  .portfolio-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  /* Reset desktop nth-child overrides for 2-col mobile layout */
  .portfolio-item:nth-child(5n) {
    border-right: 1px solid var(--light-grey);
  }

  .portfolio-item:nth-child(2n) {
    border-right: none;
  }

  /* Stack the portfolio header vertically — title on top, full-width tabs
     strip below. Otherwise the long filter list either wraps into multiple
     rows (which breaks the indicator) or squeezes against the title. */
  .portfolio-header {
    flex-direction: column;
    align-items: stretch;
    gap: 24px;
  }

  /* Single-row scrollable tab strip. No wrap → the indicator's 100% height
     stays equal to a single tab's height. Hide the scrollbar but keep
     overflow scrollable for touch swipe. */
  .filter-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    width: 100%;
    -ms-overflow-style: none;
    scrollbar-width: none;
    /* Snap tabs to the start edge as the user swipes */
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
  }

  .filter-tabs::-webkit-scrollbar { display: none; }

  .filter-tab {
    flex: 0 0 auto;
    white-space: nowrap;
    scroll-snap-align: start;
  }

  .insights-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 24px;
  }

  .insights-grid {
    grid-template-columns: 1fr;
  }

  .contact-grid {
    grid-template-columns: 1fr;
    gap: 48px;
  }

  .contact-cta-side {
    justify-content: flex-start;
  }

  .contact-modal-dialog {
    padding: 48px 24px 32px;
  }

  .contact-modal-close {
    top: 8px;
    right: 8px;
  }

  .footer-top {
    flex-direction: column;
    gap: 40px;
  }

  .footer-nav {
    flex-wrap: wrap;
    gap: 32px;
  }
}

/* Tablet range: 3-col portfolio sits comfortably between the
   desktop 5-col layout and the mobile 2-col layout. This block sits
   AFTER the @media (max-width: 900px) block above so that, in the
   600-900px overlap, its rules win the cascade and bring the grid
   to 3 columns instead of 2. */
@media (min-width: 600px) and (max-width: 900px) {
  .portfolio-grid {
    grid-template-columns: repeat(3, 1fr);
  }
  /* Re-enable the right border on every item (it would otherwise
     have been removed by the desktop nth-child(5n) rule or the
     mobile-block's nth-child(2n) rule). */
  .portfolio-item {
    border-right: 1px solid var(--light-grey);
  }
  .portfolio-item:nth-child(2n),
  .portfolio-item:nth-child(5n) {
    border-right: 1px solid var(--light-grey);
  }
  .portfolio-item:nth-child(3n) {
    border-right: none;
  }
}
