/* ============================================================
   whereisrussell.com — styles
   Measured against the live Semplice site (June 2026):
   bg #f7f7f7, cream #f9f6eb lower half, ink #333,
   titles 46px Light, statements 28px Bold, body 16px Book,
   text grid 39%/58% inside a 1280px container.
   ============================================================ */

@font-face {
  font-family: "Circular";
  src: url("../assets/fonts/CircularXXWeb-Book.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Circular";
  src: url("../assets/fonts/CircularXXWeb-Light.woff2") format("woff2");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
/* Bold is downloaded by get-images.sh. If it's missing, text falls
   back to the "Circular" Book face rather than a system font. */
@font-face {
  font-family: "CircularBold";
  src: url("../assets/fonts/CircularXXWeb-Bold.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  --accent: #dd6025;
  --ink: #333333;
  --muted: #999999;
  --bg: #f7f7f7;
  --cream: #f9f6eb;
  --hairline: rgba(51, 51, 51, 0.18);
  --hairline-soft: rgba(51, 51, 51, 0.12);
  --wide: 1280px;            /* sliders, statements, experience, clients */
  --pad: clamp(1.25rem, 4vw, 2rem);
  --ease: cubic-bezier(0.25, 0.1, 0.25, 1);
  --font-book: "Circular", -apple-system, sans-serif;
  --font-light: "Circular", -apple-system, sans-serif;
  --font-bold: "CircularBold", "Circular", -apple-system, sans-serif;
}

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

/* clip horizontal overflow on BOTH html and body — iOS Safari ignores it on
   body alone, which let the carousel expose blank space to the side */
html {
  scroll-behavior: smooth;
  overflow-x: hidden;
  overflow-x: clip;
  max-width: 100%;
}

body {
  font-family: var(--font-book);
  font-weight: 400;
  font-size: 16px;
  line-height: 1.78;
  background: var(--bg);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  overflow-x: clip;
  max-width: 100%;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }

/* Wide container: sliders, statements, experience, clients, footer */
.wide {
  max-width: var(--wide);
  margin-left: auto;
  margin-right: auto;
  padding-left: var(--pad);
  padding-right: var(--pad);
}
/* Text grid: title column 39%, body column 58%, inset 8% inside .wide.
   --split is overridable per section from the visual editor (admin2). */
.text-grid {
  display: grid;
  grid-template-columns: var(--split, 39%) 1fr;
  gap: 24px;
  margin-left: 8%;
  margin-right: 8%;
}
/* Column placement overrides set by the visual editor (desktop only) */
@media (min-width: 901px) {
  .text-grid > .ecol-left { grid-column: 1; }
  .text-grid > .ecol-right { grid-column: 2; }
  .text-grid > .ecol-full { grid-column: 1 / -1; }
}

/* ---------- progress bar ---------- */
#progress-bar {
  position: fixed;
  top: 0; left: 0;
  height: 2px;
  width: 0%;
  background: var(--accent);
  z-index: 1000;
}

/* ---------- custom cursor ---------- */
.has-custom-cursor, .has-custom-cursor a, .has-custom-cursor button { cursor: none; }
#cursor { position: fixed; top: 0; left: 0; pointer-events: none; z-index: 2000; }
#cursor .cursor-inner {
  width: 14px; height: 14px;
  border-radius: 50%;
  background-color: var(--ink);
  transform: translate(-50%, -50%);
  transition: width 0.25s var(--ease), height 0.25s var(--ease);
}
#cursor.is-hover { mix-blend-mode: color-dodge; }
#cursor.is-hover .cursor-inner { width: 44px; height: 44px; }
@media (hover: none), (pointer: coarse) {
  #cursor { display: none; }
  .has-custom-cursor, .has-custom-cursor a { cursor: auto; }
}

/* ---------- hero ---------- */
.hero {
  position: relative;
  overflow: hidden;
}
/* divider draws in left-to-right as part of the opening cascade */
.hero::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: #d3d3d3;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.7s var(--ease);
  transition-delay: var(--divider-delay, 0ms);
}
.hero.divider-in::after { transform: scaleX(1); }
@media (prefers-reduced-motion: reduce) {
  .hero::after { transform: none; transition: none; }
}
.hero #hero-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
}
.hero .hero-inner { position: relative; z-index: 1; }

header.site-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 2.4rem;
  margin-left: 8%;
  margin-right: 8%;
}
@media (max-width: 900px) {
  header.site-header { margin-left: 0; margin-right: 0; }
}
header.site-header .logo,
header.site-header nav a {
  font-weight: 300;
  font-size: 16px;
}
/* SVG monogram logo */
header.site-header .logo--mark {
  display: inline-flex;
  align-items: center;
  cursor: default; /* not a link */
}
header.site-header .logo--mark img { height: 26px; width: auto; display: block; }
header.site-header nav a { position: relative; }
header.site-header nav a::after,
.u-line::after {
  content: "";
  position: absolute;
  left: 0; bottom: -3px;
  width: 100%; height: 1px;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.35s var(--ease);
}
header.site-header nav a:hover::after,
.u-line:hover::after { transform: scaleX(1); transform-origin: left; }

.hero-grid {
  padding-top: clamp(3rem, 7vw, 7.2rem);
  /* matches the first section's padding-top so the divider sits centred */
  padding-bottom: clamp(4rem, 8vw, 7rem);
  align-items: start;
}
.hero-skills {
  display: grid;
  grid-template-columns: auto auto;
  justify-content: start;
  column-gap: clamp(2rem, 6vw, 5.5rem);
}
.hero-skills ul { list-style: none; }
.hero-skills li { font-size: 16px; line-height: 1.45; padding-bottom: 0.1rem; }
.hero-statement h1 {
  font-family: var(--font-bold);
  font-weight: 500;
  /* fixed size (not vw) so the statement no longer grows/shrinks with browser
     width — at its 3-line wrap this matches the skills list height */
  font-size: 26px;
  line-height: 1.3;
  color: var(--ink);
  max-width: 628px;
  text-wrap: balance; /* even line lengths, avoid a lone trailing word */
}

/* ---------- project sections ---------- */
.project-section {
  position: relative;
  padding-top: clamp(6rem, 11vw, 10.5rem);
}
.project-section .speckle-canvas {
  position: absolute;
  left: 0;
  width: 100%;            /* full section width without 100vw overflow */
  height: 500px;
  margin-top: -70px;
  pointer-events: none;
  z-index: 0;
}
/* breathing room beneath the final project gallery before the cream half */
.project-section:last-of-type { padding-bottom: clamp(5rem, 10vw, 9rem); }
/* equal space above and below the hero/first-section divider */
.project-section:first-of-type { padding-top: clamp(4rem, 8vw, 7rem); }
.project-section .section-head { position: relative; z-index: 1; margin-bottom: clamp(2.5rem, 4.5vw, 4.3rem); }
.section-title {
  font-weight: 300;
  font-size: clamp(30px, 3.2vw, 46px);
  line-height: 1.1;
  letter-spacing: -0.04em;
  color: var(--ink);
  white-space: pre-line; /* honour explicit line breaks in titles */
}
.section-body {
  font-size: 16px;
  line-height: 1.78;
  max-width: 628px;
}

/* ---------- gallery slider ---------- */
.gallery { position: relative; z-index: 1; }
.gallery .track-viewport { overflow: visible; }
.gallery .track {
  display: flex;
  gap: 20px;
  will-change: transform;
  /* position is animated in JS (js/main.js) for smooth, re-targetable motion */
}
.gallery .slide {
  flex: 0 0 100%;
  overflow: hidden;
  border-radius: 24px;
}
.gallery .slide img,
.gallery .slide .slide-media {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  display: block;
  cursor: pointer;
  user-select: none;
  -webkit-user-drag: none;
}
/* images fade + subtly slide up once loaded */
.gallery .slide img {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.6s ease, transform 0.6s var(--ease);
}
.gallery .slide img.loaded { opacity: 1; transform: none; }
/* video shows its poster straight away, then subtly slides up once it loads */
.gallery .slide .slide-media {
  opacity: 1;
  background: #e7e8e8;
  transform: translateY(18px);
  transition: transform 0.6s var(--ease);
}
.gallery .slide .slide-media.loaded { transform: none; }
/* a single-image gallery isn't navigable, so no interactive cursor */
.gallery.single .slide img,
.gallery.single .slide .slide-media { cursor: default; }
.gallery .dots {
  display: flex;
  justify-content: flex-start;
  gap: 4px;
  padding-top: 1.4rem;
}
.gallery .dots button {
  width: 30px; height: 2px;
  border: none;
  padding: 0;
  background: var(--ink);
  opacity: 0.25;
  cursor: pointer;
  transition: opacity 0.3s ease;
}
.gallery .dots button.active { opacity: 1; }
.gallery.single .dots { display: none; }

/* ---------- cream lower half ---------- */
.lower { background: var(--cream); }

/* ---------- second statement ---------- */
.statement-2 {
  padding-top: clamp(5rem, 9vw, 8.5rem);
  padding-bottom: clamp(3.5rem, 6vw, 5.5rem);
}
.statement-2 h1 {
  font-family: var(--font-bold);
  font-weight: 500;
  font-size: clamp(20px, 1.95vw, 28px);
  line-height: 1.5;
  color: var(--ink);
  max-width: 75%;
}

/* ---------- experience ---------- */
.xp-cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  padding-bottom: 2.5rem;
}
.xp-card .xp-thumb { overflow: hidden; border-radius: 24px; }
.xp-card img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  transition: opacity 0.6s ease;
  opacity: 0;
}
.xp-card img.loaded { opacity: 1; }
.xp-card .xp-role { font-size: 16px; margin-top: 1.3rem; line-height: 1.5; }
.xp-card .xp-dates { font-size: 16px; font-weight: 300; line-height: 1.6; }

.xp-rows .xp-row {
  display: grid;
  grid-template-columns: 58% 1fr;
  gap: 24px;
  padding: 1.45rem 0;
  border-top: 1px solid var(--hairline-soft);
}
.xp-rows .xp-row:last-child { border-bottom: 1px solid var(--hairline-soft); }
.xp-rows .xp-role { font-size: 16px; }
.xp-rows .xp-dates { font-size: 16px; font-weight: 300; }

/* ---------- education ---------- */
.education { padding-top: clamp(4rem, 7vw, 6.5rem); }
.block-title {
  font-weight: 400; /* Circular Book */
  font-size: 24px;
  line-height: 1.4;
  margin-bottom: 2.2rem;
}
.edu-item { padding: 1.45rem 0; border-top: 1px solid var(--hairline-soft); }
.edu-item:last-child { border-bottom: 1px solid var(--hairline-soft); }
.edu-item .qual { font-size: 16px; }
.edu-item .detail { font-size: 16px; font-weight: 300; }

/* ---------- clients ---------- */
.client-group { padding-top: clamp(4rem, 7vw, 6.5rem); }
.client-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: clamp(2rem, 4vw, 4.5rem);
}
.client-cols .client-row {
  font-size: 16px;
  padding: 1.3rem 0;
  border-bottom: 1px solid var(--hairline-soft);
}

/* ---------- keywords ---------- */
.keywords {
  padding-top: clamp(5rem, 9vw, 8rem);
  font-weight: 400; /* Circular Book */
  font-size: clamp(19px, 1.75vw, 25px);
  line-height: 1.76;
  color: var(--ink);
}

/* ---------- footer ---------- */
footer.site-footer { padding-top: 3.5rem; padding-bottom: 2rem; }
/* Pill button used in both the header and the footer.
   The fill is a layer that eases vertically on hover for a bit of delight. */
.footer-btn {
  --btn-ease: cubic-bezier(0.22, 1, 0.36, 1);
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: inline-block;
  padding: 8px 16px;
  font-size: 16px;
  font-weight: 400; /* Circular Book */
  border: 1px solid var(--ink);
  border-radius: 8px;
  background: transparent;
}
.footer-btn .btn-label {
  position: relative;
  z-index: 1;
  transition: color 0.45s var(--btn-ease);
}
.footer-btn::before {
  content: "";
  position: absolute;
  inset: -1px;            /* cover the border too */
  background: var(--ink);
  z-index: 0;
  /* slow to start, then accelerates and springs up to the top */
  transition: transform 0.46s cubic-bezier(0.7, 0, 0.85, 0.2);
}

/* The fill creeps, then springs up and lifts the button; the button's weight
   then drops it back down. Per-keyframe easings give the spring + gravity. */
@keyframes btn-jump {
  0%, 68% { transform: translateY(0); animation-timing-function: cubic-bezier(0.2, 0.85, 0.3, 1.55); }
  82%     { transform: translateY(-8px); animation-timing-function: cubic-bezier(0.5, 0, 0.85, 0.8); }
  100%    { transform: translateY(0); }
}
/* bounce is toggled in JS (not :hover) so a quick out-and-back while the
   button is still active doesn't replay it */
.footer-btn.bounce { animation: btn-jump 0.6s linear; }
@media (prefers-reduced-motion: reduce) { .footer-btn.bounce { animation: none; } }

/* Footer: filled by default; on hover the fill eases out upwards -> outline */
.footer-btn::before { transform-origin: top; transform: scaleY(1); }
.footer-btn .btn-label { color: #ffffff; }
.footer-btn:hover::before { transform: scaleY(0); }
.footer-btn:hover .btn-label { color: #000000; }

/* Header: inverse — outline by default; on hover the fill eases up from below */
.footer-btn.btn-inverse::before { transform-origin: bottom; transform: scaleY(0); }
.footer-btn.btn-inverse .btn-label { color: var(--ink); }
.footer-btn.btn-inverse:hover::before { transform: scaleY(1); }
.footer-btn.btn-inverse:hover .btn-label { color: #ffffff; }

/* the header nav underline must not draw under the button */
header.site-header nav a.footer-btn::after { content: none; }
/* the header nav rule sets weight 300; keep the button text Book */
header.site-header nav a.footer-btn { font-weight: 400; }
.footer-bar {
  margin-top: clamp(4rem, 7vw, 6rem);
  border-top: 1px solid var(--hairline);
  padding-top: 1.4rem;
  display: flex;
  justify-content: space-between;
  font-size: 14px;
  font-weight: 500;
  font-family: var(--font-bold);
}

/* ---------- back to top ---------- */
#back-to-top {
  position: fixed;
  right: 45px;
  bottom: 30px;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 900;
  opacity: 0;
  transform: translateY(12px);
  pointer-events: none;
  transition: opacity 0.4s ease, transform 0.4s var(--ease), background 0.3s ease;
}
#back-to-top.visible { opacity: 1; transform: translateY(0); pointer-events: auto; }
#back-to-top:hover { background: #000; }
#back-to-top svg { width: 20px; height: 20px; fill: #f7f7f7; }

/* ---------- typewriter word reveal ---------- */
/* inline (not inline-block) so words flow as normal text — this lets
   non-breaking spaces and text-wrap: balance control wrapping cleanly */
.tw-w {
  opacity: 0;
  transition: opacity 0.14s ease;
  will-change: opacity;
}
.tw-on .tw-w { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .tw-w { opacity: 1 !important; transition: none !important; }
}

/* ---------- reveal transitions ---------- */
.reveal {
  opacity: 0;
  transform: translateY(36px);
  transition: opacity 0.9s var(--ease), transform 0.9s var(--ease);
  will-change: opacity, transform;
}
.reveal.is-visible { opacity: 1; transform: translateY(0); }
.reveal[data-delay="1"] { transition-delay: 0.1s; }
.reveal[data-delay="2"] { transition-delay: 0.2s; }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
  html { scroll-behavior: auto; }
  .gallery .track { transition: none; }
  .gallery .slide img, .gallery .slide .slide-media { transform: none !important; transition: opacity 0.4s ease; }
}

/* ---------- responsive ---------- */
@media (max-width: 900px) {
  .text-grid { grid-template-columns: 1fr; margin-left: 0; margin-right: 0; gap: 1.2rem; }
  /* hero fills the browser height, with the copy + lists bottom-aligned */
  .hero { min-height: 100vh; min-height: 100svh; }
  .hero .hero-inner {
    min-height: 100vh;
    min-height: 100svh;
    display: flex;
    flex-direction: column;
  }
  .hero-grid { gap: 2.5rem; margin-top: auto; padding-top: 0; }
  /* statement leads, skills columns follow on mobile */
  .hero-grid .hero-statement { order: -1; }
  /* on mobile the hero statement matches the section-headline size */
  .hero-statement h1 { font-size: clamp(30px, 3.2vw, 46px); line-height: 1.15; }
  /* second skills column hugs the right edge of the window on mobile */
  .hero-skills { justify-content: space-between; }
  .hero-skills ul:last-child { text-align: right; }
  .statement-2 h1 { max-width: 100%; }
  .xp-cards { grid-template-columns: 1fr; }
  .client-cols { grid-template-columns: 1fr; column-gap: 0; }
  .client-cols .client-row:first-child { border-top: 0; }
  #back-to-top { right: 18px; bottom: 18px; width: 48px; height: 48px; }

  /* clip the carousel so off-screen slides don't create horizontal scroll
     (iOS Safari ignores body overflow-x:hidden when a child overflows) */
  .gallery, .gallery .track-viewport { overflow: hidden; }
  /* smaller corner radius on images throughout on mobile */
  .gallery .slide { border-radius: 8px; }
  .xp-card .xp-thumb { border-radius: 8px; }

  /* mobile section order: title -> gallery -> body copy (every section).
     section-head dissolves so its title/body become flex items of .wide. */
  .project-section .wide { display: flex; flex-direction: column; }
  .project-section .section-head { display: contents; }
  .project-section .section-title { order: 1; margin-bottom: 1.25rem; }
  .project-section .gallery { order: 2; }
  .project-section .section-body { order: 3; margin-top: 1.5rem; }
}
