/* Reset + element defaults. Loaded after tokens.css. */

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

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

/* Lenis smooth-scroll hooks. Active only once main.js attaches Lenis;
   otherwise the native `scroll-behavior: smooth` above remains in effect. */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  color: var(--color-text);
  background: var(--color-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* Prevent iOS landscape from auto-bumping fonts, and stop horizontal
     scroll on rotated decorative cards in the hero. */
  -webkit-text-size-adjust: 100%;
  overflow-x: hidden;
}

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

h1, h2, h3, h4, h5, h6 {
  margin: 0 0 var(--space-md);
  color: var(--color-ink);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-tight);
}

/* Display headings (h1, h2) use Fraunces — warm scholarly serif with optical size */
h1, h2 {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.02em;
  font-variation-settings: "opsz" 96;
}

h1 { font-size: var(--fs-3xl); }
h2 { font-size: var(--fs-2xl); }
h3 { font-size: var(--fs-xl); }
h4 { font-size: var(--fs-lg); }

p { margin: 0 0 var(--space-md); max-width: var(--content-max); }
p:last-child { margin-bottom: 0; }

a {
  color: var(--color-ink);
  text-decoration: underline;
  text-decoration-color: var(--color-accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 2px;
  transition: color var(--dur) var(--ease);
}
a:hover { color: var(--color-accent-hover); }

ul, ol { margin: 0 0 var(--space-md); padding-left: var(--space-lg); }
li { margin-bottom: var(--space-xs); }

strong, b { font-weight: var(--fw-bold); }
em, i { font-style: italic; }

small { font-size: var(--fs-sm); color: var(--color-muted); }

hr {
  border: 0;
  border-top: 1px solid var(--color-border);
  margin: var(--space-2xl) 0;
}

/* Form element defaults */
button, input, select, textarea {
  font: inherit;
  color: inherit;
}
button { cursor: pointer; background: none; border: none; padding: 0; }

/* Focus-visible: clear ring on every interactive element */
:focus { outline: none; }
:focus-visible {
  outline: 3px solid var(--color-accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Skip-to-content link (visible only when focused) */
.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  padding: var(--space-sm) var(--space-md);
  background: var(--color-ink);
  color: #fff;
  text-decoration: none;
  z-index: 1000;
}
.skip-link:focus { top: 0; }

/* Scroll progress indicator — thin orange bar at top of viewport */
.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  height: 3px;
  width: 0;
  background: linear-gradient(90deg, var(--color-accent) 0%, var(--color-accent-bright) 100%);
  z-index: 100;
  pointer-events: none;
  transition: width 80ms linear;
}

/* Editorial section label — small caps kicker above h2 */
.eyebrow {
  display: inline-block;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--color-accent-hover);
  margin-bottom: var(--space-sm);
}
.eyebrow::before {
  content: attr(data-num) "  ·  ";
  color: var(--color-ink);
  opacity: 0.55;
  font-variant-numeric: tabular-nums;
}

/* Scroll-reveal: elements fade + slide up as they enter the viewport.
   JS adds `is-visible` via IntersectionObserver (see scripts/main.js).
   Three independent transform inputs travel as CSS vars so cards/testimonials
   can compose their own perspective transform without us overwriting it: see
   card.css / testimonial.css. */
.reveal {
  opacity: 0;
  --reveal-x: 0px;
  --reveal-y: 40px;
  --reveal-scale: 0.97;
  --reveal-blur: 0px;
  filter: blur(var(--reveal-blur));
  transition: opacity var(--dur-xslow) var(--ease-out),
              transform var(--dur-xslow) var(--ease-out),
              filter var(--dur-xslow) var(--ease-out);
  will-change: opacity, transform, filter;
}
.reveal:not(.card):not(.testimonial) {
  transform: translate3d(var(--reveal-x), var(--reveal-y), 0) scale(var(--reveal-scale));
}
.reveal.is-visible {
  opacity: 1;
  --reveal-x: 0px;
  --reveal-y: 0px;
  --reveal-scale: 1;
  --reveal-blur: 0px;
}
/* Direction variants — opt in by adding the modifier class. */
.reveal--left  { --reveal-x: -48px; --reveal-y: 0px; }
.reveal--right { --reveal-x:  48px; --reveal-y: 0px; }
.reveal--blur  { --reveal-blur: 8px; --reveal-y: 16px; }
.reveal--zoom  { --reveal-scale: 0.88; --reveal-y: 0px; }

/* Stagger variants — apply to children of a .reveal-group */
.reveal-group > .reveal { transition-delay: 0ms; }
.reveal-group > .reveal:nth-child(2) { transition-delay: 80ms; }
.reveal-group > .reveal:nth-child(3) { transition-delay: 160ms; }
.reveal-group > .reveal:nth-child(4) { transition-delay: 240ms; }
.reveal-group > .reveal:nth-child(5) { transition-delay: 320ms; }
.reveal-group > .reveal:nth-child(6) { transition-delay: 400ms; }

/* Word-by-word headline reveal. JS wraps each word in `.word > .word__inner`,
   then sets `.is-visible` on the parent to play the inner spans in stagger.
   `.word` is inline-block so each word transforms independently while the
   line still wraps. Don't set `display` on `.headline-anim` — it's the host
   <h2>, which needs to stay block-level. */
.headline-anim .word {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  line-height: inherit;
}
.headline-anim .word__inner {
  display: inline-block;
  transform: translateY(110%);
  opacity: 0;
  transition:
    transform var(--dur-xslow) var(--ease-out),
    opacity  var(--dur-slow)  var(--ease-out);
  will-change: transform, opacity;
}
.headline-anim.is-visible .word__inner {
  transform: translateY(0);
  opacity: 1;
}
/* Per-word stagger — JS sets --i on each .word__inner */
.headline-anim .word__inner { transition-delay: calc(var(--i, 0) * 60ms); }

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1; transform: none; }
}

/* ------------------------------------------------------------------
   Page-enter animation — every page fades in on open.
   Runs on initial load, refresh, direct URL, and Firefox (no VT).
   When arriving via a cross-document View Transition (Chrome/Safari),
   the inline `pagereveal` listener in head.php adds .vt-arriving to
   <html> before first paint, suppressing this so the VT plays alone.

   Opacity-only on purpose: a `transform` keyframe on <main> would
   establish a containing block, which kills `background-attachment:
   fixed` on descendants (the parallax notebook grid behind .hero,
   .section--alt, and .page-hero). The hero already has its own
   slide-up via `hero-rise`, and section content uses `.reveal`, so
   nothing visibly regresses.
   ------------------------------------------------------------------ */
main {
  animation: r2-page-enter 460ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
html.vt-arriving main { animation: none; }

@keyframes r2-page-enter {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  main { animation: none; }
}

/* ------------------------------------------------------------------
   Cross-document View Transitions — smooth crossfade when navigating
   between pages (Services → About, etc.) instead of a hard reload.
   Progressive enhancement: Chrome 126+, Edge 126+, Safari 18.2+ get
   the animation; Firefox + older browsers fall back to instant nav.
   ------------------------------------------------------------------ */
@view-transition {
  navigation: auto;
}

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 240ms;
  animation-timing-function: cubic-bezier(0.22, 0.61, 0.36, 1);
}
::view-transition-old(root) {
  animation-name: r2-page-out;
}
::view-transition-new(root) {
  animation-name: r2-page-in;
}

@keyframes r2-page-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
@keyframes r2-page-out {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translateY(-4px); }
}

/* Pin the navbar and footer so they appear to persist across navigations
   instead of being part of the crossfade — same feel as meva's Next.js
   layout, where the shell stays mounted while only main content swaps. */
.navbar { view-transition-name: site-nav; }
.footer { view-transition-name: site-footer; }

::view-transition-old(site-nav),
::view-transition-new(site-nav),
::view-transition-old(site-footer),
::view-transition-new(site-footer) {
  animation-duration: 240ms;
  animation-timing-function: cubic-bezier(0.22, 0.61, 0.36, 1);
}

@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root),
  ::view-transition-old(site-nav),
  ::view-transition-new(site-nav),
  ::view-transition-old(site-footer),
  ::view-transition-new(site-footer) {
    animation-duration: 1ms !important;
    animation-name: none !important;
  }
}

/* Selection */
::selection { background: var(--color-accent); color: var(--color-ink); }

/* ------------------------------------------------------------------
   Editorial utilities — signature type treatments used across pages.
   ------------------------------------------------------------------ */

/* Accent word inside a display headline — Fraunces italic at max opsz. */
.swash {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 500;
  color: var(--color-accent);
  font-variation-settings: "opsz" 144, "SOFT" 100;
  position: relative;
  display: inline-block;
  white-space: nowrap;
}
/* Hand-drawn marker underline beneath a .swash. Use `data-underline` on parent h1. */
.marker-underline {
  position: relative;
  display: inline-block;
}
.marker-underline::after {
  content: "";
  position: absolute;
  left: -0.08em;
  right: -0.08em;
  bottom: -0.16em;
  height: 0.28em;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 14' preserveAspectRatio='none'><path d='M2 9 C 60 2, 120 14, 180 6 S 290 10, 298 5' fill='none' stroke='%23f26618' stroke-width='4' stroke-linecap='round' opacity='0.85'/></svg>") center/100% 100% no-repeat;
  pointer-events: none;
}

/* Small editorial pill — subject tags, category chips. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  padding: 0.2em 0.7em 0.25em;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent-ink);
  background: var(--color-accent-soft);
  border-radius: var(--radius-pill);
  border: 1px solid rgba(242, 102, 24, 0.28);
  line-height: 1.2;
}
.chip--ink {
  color: #fff;
  background: rgba(255, 255, 255, 0.12);
  border-color: rgba(255, 255, 255, 0.25);
}

/* Torn-paper / angled section divider. Put inside a section as sibling to .container. */
.section-divider {
  position: absolute;
  left: 0; right: 0;
  height: 32px;
  pointer-events: none;
  z-index: 0;
}
.section-divider--top    { top: -1px; }
.section-divider--bottom { bottom: -1px; transform: scaleY(-1); }

/* Count-up target — JS rewrites text content; this hides visual jump before anim. */
[data-countup] { font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------------
   .spotlight — warm radial glow that follows the cursor on hover.
   Any element tagged with [data-spotlight] gets a soft orange light.
   JS sets --mx / --my (px from top-left of the element) on mousemove.
   ------------------------------------------------------------------ */
[data-spotlight] {
  isolation: isolate;  /* keep the ::after z-index local to this element */
}
[data-spotlight]::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(
    380px circle at var(--mx, 50%) var(--my, 50%),
    rgba(242, 102, 24, 0.14),
    rgba(242, 102, 24, 0.06) 20%,
    transparent 50%
  );
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease);
  border-radius: inherit;
}
[data-spotlight]:hover::after { opacity: 1; }

/* On navy-backed cards (e.g. inside .section--dark), switch to a warm-white
   glow so it reads against the darker surface. */
.section--dark [data-spotlight]::after {
  background: radial-gradient(
    380px circle at var(--mx, 50%) var(--my, 50%),
    rgba(251, 146, 60, 0.18),
    rgba(251, 146, 60, 0.08) 20%,
    transparent 50%
  );
}

@media (prefers-reduced-motion: reduce) {
  [data-spotlight]::after { transition: none; }
}
@media (hover: none) {
  /* Skip the glow on touch devices — mousemove doesn't apply. */
  [data-spotlight]::after { display: none; }
}
