/* ═══ THE LENS ═══════════════════════════════════════════════════
   The cursor as a light source, identical to the landing's. Copied
   from style.css for the same reason the nav is: these pages don't
   load style.css, and pulling in the whole landing stylesheet to get
   one light would ship a page of dead CSS.

   It sits UNDER the content (z-index 1; .ds-wrap is 2) and is blurred
   hard enough that it never resolves into a shape — the moment it does
   it reads as a cursor gimmick rather than as light in the room. */
.lens {
  position: fixed;
  left: 0; top: 0;
  width: 560px; height: 560px;
  margin: -280px 0 0 -280px;
  border-radius: var(--radius-full);
  pointer-events: none;
  z-index: 1;
  opacity: 0;
  background: radial-gradient(circle,
    rgba(var(--light-1), 0.20), rgba(var(--light-3), 0.13) 44%, transparent 68%);
  filter: blur(46px);
  will-change: transform;
  transition: opacity var(--duration-long) var(--ease-standard);
}
/* Held dark until the pointer first moves: on a touch device the light
   would otherwise sit frozen in the middle of the screen. */
body.is-lit .lens { opacity: 1; }

@media (prefers-reduced-transparency: reduce) {
  .lens { display: none; }
}

/* The content has to sit above the light, or the light washes over the
   text instead of behind it. */
.ds-wrap { position: relative; z-index: 2; }


/* ═══════════════════════════════════════════════════════════════
   NAV + FOOTER for the blog pages.

   The rules are the landing's, in style.css, copied verbatim rather
   than linked: style.css also carries the hero field, the case-study
   cards and the testimonial rail, none of which exist here, and
   loading all of it to get a header would ship a page of dead CSS.

   The CV page inlines its own copy of the same block for the same
   reason. That makes THREE copies, which is a real cost — a shared
   design-system/chrome.css is the right fix and is worth doing when
   the design system is next touched. Until then: a change to the
   landing's header must be made here and in cv/index.html too.

   ONE deliberate difference from the landing: the landing's nav is
   transparent at rest because a hero sits behind it. These pages open
   on a heading rather than a hero, so the bar starts lit — a
   transparent header over an already-scrolled document reads as a
   missing header.
   ═══════════════════════════════════════════════════════════════ */

#nav {
  position: sticky;
  top: 0;
  /* Above the mobile sheet, never below: one header, and the menu
     opens underneath it, so the wordmark never moves. */
  z-index: 70;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-bottom: 1px solid transparent;
  transition: background-color var(--duration-medium) ease,
              border-color var(--duration-medium) ease,
              backdrop-filter var(--duration-medium) ease;
}
/* Transparent at rest, lit once the page has moved — the same two
   states the landing's header has, so the bar does not differ between
   pages. */
#nav.is-scrolled {
  background: rgba(22, 22, 22, 0.76);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-bottom-color: var(--color-line);
}
/* 1fr auto 1fr, not space-between: equal side tracks are what put the
   link group on the page's true centre. */
#nav .ds-wrap { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: var(--space-6); }
#nav .brand { justify-self: start; }
#nav .navlinks { justify-self: center; }
#nav .nav-contact {
  justify-self: end;
  font-size: var(--type-caption);
  font-weight: 500;
  color: var(--color-fg-subtle);
  transition: color var(--duration-short) ease;
}
#nav .nav-contact:hover { color: var(--color-fg); }
#nav .nav-toggle { justify-self: end; }

.brand { display: flex; align-items: center; gap: var(--space-3); font-weight: 700; font-size: 1.25rem; letter-spacing: var(--tracking-tight); color: var(--color-fg); }

.navlinks { display: flex; gap: 34px; }
.navlinks a { font-size: var(--type-caption); font-weight: 500; color: var(--color-fg-subtle); transition: color var(--duration-short) ease; }
.navlinks a:hover { color: var(--color-fg); }
/* The page you are on is stated, not merely implied by a hover you
   are not performing. */
.navlinks a[aria-current="page"] { color: var(--color-fg); }

.nav-toggle { display: none; align-items: center; justify-content: center; width: 44px; height: 44px; border: 0; background: none; color: var(--color-fg); cursor: pointer; border-radius: var(--radius-md); }
.nav-toggle svg { width: 24px; height: 24px; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; fill: none; }
/* One button, two glyphs, switched off the attribute assistive tech
   already reads — so the state lives in exactly one place. */
.nav-toggle .ico-close { display: none; }
.nav-toggle[aria-expanded="true"] .ico-open { display: none; }
.nav-toggle[aria-expanded="true"] .ico-close { display: inline-flex; }

@media (max-width: 960px) {
  .navlinks,
  #nav .nav-contact { display: none; }
  .nav-toggle { display: inline-flex; }
  /* Back to two ends: with the centre track's contents hidden, the
     toggle would otherwise inherit the middle and sit dead centre. */
  #nav .ds-wrap { display: flex; justify-content: space-between; }
}

/* Full-screen and opaque: at this width the sheet IS the page.
   `visibility` rather than opacity alone, so the closed sheet leaves
   the compositor entirely and opening cannot ghost the page through
   the middle of the fade. */
#mob-menu {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: var(--color-bg);
  display: grid;
  align-content: start;
  gap: var(--space-2);
  padding: calc(var(--nav-h) + var(--space-6)) var(--space-gutter) var(--space-8);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-12px);
  pointer-events: none;
  transition: opacity var(--duration-short) var(--ease-standard),
              transform var(--duration-medium) var(--ease-standard),
              visibility 0s linear var(--duration-short);
}
#mob-menu.is-open {
  opacity: 1;
  visibility: visible;
  transform: none;
  pointer-events: auto;
  transition: opacity var(--duration-short) var(--ease-standard),
              transform var(--duration-medium) var(--ease-standard),
              visibility 0s;
}
/* A short stagger, so it reads as a menu unfolding rather than a
   panel appearing. */
#mob-menu > * {
  opacity: 0;
  transform: translateY(-10px);
  transition: opacity var(--duration-short) var(--ease-standard),
              transform var(--duration-medium) var(--ease-standard);
}
#mob-menu.is-open > * { opacity: 1; transform: none; }
#mob-menu.is-open > :nth-child(2) { transition-delay: 40ms; }
#mob-menu.is-open > :nth-child(3) { transition-delay: 80ms; }
#mob-menu.is-open > :nth-child(4) { transition-delay: 120ms; }
#mob-menu.is-open > :nth-child(5) { transition-delay: 160ms; }
#mob-menu a[data-mob-link] {
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  color: var(--color-fg);
  padding: var(--space-3) 0;
}
#mob-menu a[data-mob-link][aria-current="page"] { color: var(--color-fg-muted); }

@media (prefers-reduced-motion: reduce) {
  #mob-menu, #mob-menu > * { transition-duration: 1ms; }
}

footer { padding: 44px 0 var(--space-8); background: var(--rule-top); }
footer .ds-wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  flex-wrap: wrap;
}
footer .ds-meta { display: inline-flex; align-items: center; gap: var(--space-2); }
.ftr-links { display: flex; align-items: center; gap: var(--space-5); }
.ftr-links a { transition: color var(--duration-short) ease; }
.ftr-links a:hover { color: var(--color-fg); }
@media (max-width: 700px) {
  footer .ds-wrap { justify-content: flex-start; gap: var(--space-3); }
  .ftr-links { gap: var(--space-4); }
}
