/* ==========================================================================
   Tokens — change the whole look from here.
   ========================================================================== */
:root {
  --bg: #000;
  --fg: #fff;
  --muted: rgb(255 255 255 / 0.55);
  --line: rgb(255 255 255 / 0.28);
  --gold: #e9dd88;                                 /* project categories */
  --bar-line: 2px solid #fff;                      /* header + footer bar rules */
  --grain-opacity: 0.22;                           /* hero film grain, 0 = off */
  --scanline-opacity: 0.35;                        /* hero scanlines, 0 = off */

  --font-ui: "Inter", "Helvetica Neue", Arial, sans-serif;
  --font-display: "Helvetica Neue", Helvetica, Arial, sans-serif;

  --text-xs: 0.75rem;                              /* 12px labels */
  --text-header: clamp(0.8125rem, 1.15vw, 1.125rem); /* top bar, 13–18px */
  --text-display: clamp(2rem, 5.4vw, 5.25rem);     /* project titles */

  --gutter: clamp(1rem, 1.6vw, 1.75rem);
  --header-h: 4.5rem;                              /* updated live by main.js */
  --footer-h: 3rem;                                /* updated live by main.js */
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
}

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

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

body {
  margin: 0;
  padding-bottom: var(--footer-h); /* room for the fixed footer bar */
  background: var(--bg);
  color: var(--fg);
  font: 400 var(--text-xs) / 1.35 var(--font-ui);
  letter-spacing: 0.01em;
  text-transform: uppercase;
  -webkit-font-smoothing: antialiased;
}

/* Oversized pixel-hand cursor from the original site (hotspot = fingertip). */
html { cursor: url("assets/cursor/hand.png") 23 2, auto; }
a, button, [role="button"] { cursor: url("assets/cursor/hand-hover.png") 23 2, pointer; }

a { color: inherit; text-decoration: none; }
img, video { display: block; max-width: 100%; }
ul, ol { list-style: none; margin: 0; padding: 0; }
h1, h2, h3, p { margin: 0; font: inherit; }

.u-link { text-decoration: underline; text-underline-offset: 0.2em; text-decoration-thickness: 1px; }
.u-link:hover { color: var(--muted); }

/* Desktop header links (name, "Polymarket", Info, Awards): Polymarket-blue
   highlight with white type on hover. The padding is cancelled by the
   margin so nothing shifts. */
.site-header__brand-link {
  padding: 0 0.15em;
  margin: 0 -0.15em;
  transition: background-color 0.2s, color 0.2s;
}
@media (min-width: 761px) {
  .site-header .site-header__brand-link:hover { background: #1652f0; color: #fff; }
}

/* Header name + description. Desktop: only the name links home. Phones: the
   name, emoji and description are one link home, with the name and
   description underlined (never the emoji). */
.site-header__id--mobile { display: none; }
.site-header__home { transition: color 0.2s; }
.site-header__home:hover { color: var(--muted); }
.site-header__name,
.site-header__role--mobile {
  text-decoration: underline;
  text-underline-offset: 0.2em;
  text-decoration-thickness: 1px;
}

.label { color: var(--muted); margin-bottom: 1.25rem; }

/* ==========================================================================
   Header
   ========================================================================== */
.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  display: grid;
  grid-template-columns: 1fr 1fr auto;
  gap: var(--gutter);
  align-items: start;
  padding: 1.25rem var(--gutter) 1rem;
  background: var(--bg);
  border-bottom: var(--bar-line);
  font-size: var(--text-header);
  line-height: 1.25;
}

.site-header__role { display: block; line-height: 1.05; letter-spacing: -0.02em; }
.site-header__role--mobile { display: none; line-height: 1.2; letter-spacing: -0.02em; } /* a bit more air now that it is underlined */
.site-header__currently { line-height: 1.05; }

.site-header__nav { display: flex; gap: 1.25rem; }
.site-header__nav a[aria-current="page"] { color: var(--muted); }

/* ==========================================================================
   Hero — fills the viewport under the header at every size.
   object-fit: cover crops instead of stretching, so it never goes wonky.
   ========================================================================== */
.hero {
  position: relative;
  height: calc(var(--screen-h, 100svh) - var(--header-h) - var(--footer-h));
  min-height: 20rem;
  overflow: hidden;
  background: #000;
  opacity: var(--hero-fade, 1); /* set by main.js as you scroll */
}

/* Hide iOS's big play button that appears before an autoplaying video starts. */
.hero__video::-webkit-media-controls-start-playback-button,
.hero__video::-webkit-media-controls { display: none !important; -webkit-appearance: none; }

/* Desktop page-load intro (main.js adds .is-loading-in): the top bar fades in
   over 0.9s, then the home video fades up right after it. */
.is-loading-in .site-header { animation: intro-fade 0.9s ease-out both; }
.is-loading-in .hero__video { animation: intro-fade 1.2s ease-out 0.9s both; }
@keyframes intro-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.hero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* Scanlines: thin dark horizontal lines every 3px. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: repeating-linear-gradient(to bottom, #000 0 1px, transparent 1px 3px);
  opacity: var(--scanline-opacity);
}

/* Film grain: a tiny tile of noise, jittered a few times a second. */
.hero::after {
  content: "";
  z-index: 1;
  position: absolute;
  inset: -50%;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0.33 0.33 0.33 0 0 0.33 0.33 0.33 0 0 0.33 0.33 0.33 0 0 0 0 0 0 1'/%3E%3CfeComponentTransfer%3E%3CfeFuncR type='linear' slope='3' intercept='-1'/%3E%3CfeFuncG type='linear' slope='3' intercept='-1'/%3E%3CfeFuncB type='linear' slope='3' intercept='-1'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 220px;
  opacity: var(--grain-opacity);
  mix-blend-mode: overlay;
  animation: grain 0.9s steps(6) infinite;
}

@keyframes grain {
  0%   { transform: translate(0, 0); }
  20%  { transform: translate(-7%, 4%); }
  40%  { transform: translate(5%, -6%); }
  60%  { transform: translate(-4%, -3%); }
  80%  { transform: translate(6%, 5%); }
  100% { transform: translate(0, 0); }
}

.hero__scroll {
  z-index: 2;
  position: absolute;
  left: 50%;
  bottom: 1.5rem;
  translate: -50% 0;
  display: grid;
  justify-items: center;
  gap: 0.5rem;
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  mix-blend-mode: difference;
}

/* On the home page the cue's line runs right down to the footer bar's rule. */
.hero > .hero__scroll { bottom: 0; }

.hero__scroll::after {
  content: "";
  width: 1px;
  height: 2rem;
  background: currentColor;
  transform-origin: top;
  animation: scroll-line 2s var(--ease) infinite;
}

@keyframes scroll-line {
  0%   { transform: scaleY(0); }
  50%  { transform: scaleY(1); transform-origin: top; }
  51%  { transform-origin: bottom; }
  100% { transform: scaleY(0); transform-origin: bottom; }
}

/* ==========================================================================
   Work list
   ========================================================================== */
.work { padding: 0 var(--gutter); }

.project { border-bottom: 1px solid var(--line); }

.project__link {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(9rem, 16rem);
  gap: var(--gutter);
  padding: clamp(1.5rem, 3vw, 3rem) 0;
  transition: opacity 0.4s var(--ease);
}

.project__title {
  max-width: 19ch;
  font: 400 var(--text-display) / 0.95 var(--font-display);
  letter-spacing: -0.025em;
  text-transform: none;
  text-wrap: balance;
  text-decoration: underline 1px transparent;
  text-underline-offset: 0.1em;
}

.project__link:hover .project__title,
.project__link:focus-visible .project__title { text-decoration-color: currentColor; }

.project__meta { display: grid; align-content: start; gap: 1rem; }
.project__year { text-decoration: underline; text-underline-offset: 0.2em; }

/* Client + category line: phones only for now (see the small-screens block). */
.project__labels { display: none; }
.project__client { text-decoration: underline; text-underline-offset: 0.2em; }
.project__category { color: var(--gold); text-align: right; }

.badges { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem 0.75rem; }

.badges img {
  width: auto;
  height: auto;
  max-height: 2.5rem;
  max-width: 5rem;
}

/* Dim the rest of the list while one project is hovered. */
@media (hover: hover) {
  .work__list:has(.project__link:hover) .project__link:not(:hover) { opacity: 0.3; }
}

/* ==========================================================================
   Case-study pages (drawn by canvas.js from data/<page>.json)
   Every number in the data is in "canvas units": 1024 across on desktop,
   320 on phones. --u converts one unit to real pixels for the current width.
   ========================================================================== */
.plain { display: grid; gap: 0.35em; }

.canvas {
  container-type: inline-size;
  /* Readymag measured from the top of the window, under the header. */
  margin-top: calc(-1 * var(--header-h));
  overflow: hidden;
  text-transform: none;
  letter-spacing: normal;
  font-family: Roboto, Arial, sans-serif;
  line-height: normal;
}

.canvas__stage {
  --u: calc(100cqw / var(--cw));
  position: relative;
  height: calc(var(--ch) * var(--u) + var(--after-shift, 0px));
}

.c-item {
  position: absolute;
  left: calc(var(--x) * var(--u));
  top: calc(var(--y) * var(--u) + var(--shift, 0px));
  width: calc(var(--w) * var(--u));
  height: calc(var(--h) * var(--u));
  rotate: var(--angle, 0deg);
  opacity: var(--opacity, 1);
}

/* Text */
.c-text { white-space: pre-wrap; overflow-wrap: break-word; }
.c-text, .c-text * { font-size: calc(var(--fs, 16) * var(--u)); }
.c-text p, .c-text li { margin: 0; }
.c-text [style*="--lh"] { line-height: calc(var(--lh) * var(--u)); }
.c-text [style*="--ls"] { letter-spacing: calc(var(--ls) * var(--u)); }
.c-text [style*="--ti"] { text-indent: calc(var(--ti) * var(--u)); }
.c-text [style*="--pt"] { padding-top: calc(var(--pt) * var(--u)); }
.c-text [style*="--pb"] { padding-bottom: calc(var(--pb) * var(--u)); }
.c-text a { color: inherit; transition: opacity 0.3s var(--ease); }
.c-text a:hover { opacity: 0.6; }

/* Images */
.c-image { display: block; overflow: hidden; border-radius: calc(var(--radius, 0) * var(--u)); }
.c-image img { width: 100%; height: 100%; object-fit: cover; }
.c-image.is-cropped img { position: absolute; max-width: none; object-fit: fill; }

/* Video */
.c-video { overflow: hidden; background: #000; }
.c-video iframe, .c-video video { width: 100%; height: 100%; border: 0; object-fit: cover; }

/* Lines and shapes */
.c-line::before {
  content: "";
  position: absolute;
  inset: 50% 0 auto;
  height: max(1px, calc(var(--weight) * var(--u)));
  translate: 0 -50%;
  background: var(--color);
}

.c-shape {
  background: var(--fill, transparent);
  border: calc(var(--border, 0) * var(--u)) solid var(--color, transparent);
  border-radius: calc(var(--radius, 0) * var(--u));
}
.c-shape.is-ellipse { border-radius: 50%; }

/* The home page's animated "Scroll" cue, at the bottom of a project's first screen. */
.page-scroll {
  position: absolute;
  inset: 0 0 auto;
  height: calc(var(--screen-h, 100svh) - var(--footer-h));
  z-index: 1;
  pointer-events: none;
}
.page-scroll .hero__scroll {
  pointer-events: auto;
  font-family: var(--font-ui);
  text-transform: uppercase;
}

/* Intro screen (pages with "introScreen": true): the intro is centred on an
   all-black first screen, everything after it starts below the fold, and the
   Scroll cue's line runs down to the footer bar like on the home page. */
.has-intro-screen .is-intro { --shift: var(--intro-shift, 0px); }
.has-intro-screen .is-after { --shift: var(--after-shift, 0px); }
.has-intro-screen .page-scroll .hero__scroll { bottom: 0; }
/* Phones keep the page's own layout (no intro screen), so the cue would land
   on top of the copy: leave it out there. */
@media (max-width: 600px) { .page-scroll { display: none; } }

/* Smooth reveal: each item fades and rises as it scrolls into view. */
.canvas.is-animated .c-item {
  opacity: 0;
  translate: 0 1.25rem;
  transition:
    opacity 1.1s cubic-bezier(0.16, 1, 0.3, 1),
    translate 1.1s cubic-bezier(0.16, 1, 0.3, 1);
}
.canvas.is-animated .c-item.is-visible { opacity: var(--opacity, 1); translate: 0 0; }

/* ==========================================================================
   Footer
   ========================================================================== */
.site-footer { padding: 0 var(--gutter); }

.site-footer__grid {
  display: grid;
  gap: var(--gutter);
  padding: clamp(3rem, 8vw, 7rem) 0;
}

/* The closing thank-you, in the headline typeface at half the headline size (no underline). */
.site-footer__note {
  max-width: 19ch;
  font: 400 calc(var(--text-display) * 0.5) / 1 var(--font-display);
  letter-spacing: -0.025em;
  text-transform: none;
  text-wrap: balance;
}
.site-footer__note--mobile { display: none; }

/* Always visible, pinned to the bottom of the screen on every page. */
.site-footer__bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 10;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.85rem var(--gutter) calc(0.85rem + env(safe-area-inset-bottom));
  background: var(--bg);
  border-top: var(--bar-line);
  font-size: var(--text-header);
}

/* A solid strip below the bar, so nothing (video or projects) ever shows
   underneath it, even through a see-through phone toolbar. */
.site-footer__bar::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  height: 100vh;
  background: var(--bg);
}

.social { display: flex; gap: 1rem; }
.social svg { width: 1.125rem; height: 1.125rem; fill: currentColor; }
.social a:hover { color: var(--muted); }

/* ==========================================================================
   Reveal on scroll (only once JS has marked the page ready)
   ========================================================================== */
.js .reveal { opacity: 0; transform: translateY(1.5rem); }
.js .reveal.is-visible {
  opacity: 1;
  transform: none;
  transition: opacity 0.9s var(--ease), transform 0.9s var(--ease);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js .reveal { opacity: 1; transform: none; }
  .hero__scroll::after, .hero::after { animation: none; }
}

/* ==========================================================================
   Light mode (desktop and phones): toggled by the pill switch in the
   header, which sets <html data-theme="light"> (or "dark"). Light is the default.
   ========================================================================== */
.site-header__nav { align-items: center; }

.theme-toggle {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  line-height: 0;
}

/* Pill-shaped track with a sun on the left and a moon on the right. The knob
   sits over the moon in dark mode and slides over to the sun in light mode. */
.theme-toggle__track {
  --pill-h: 1.35em;
  --knob: calc(var(--pill-h) - 6px);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  width: 2.7em;
  height: var(--pill-h);
  padding: 0 0.3em;
  border: 1.5px solid currentColor;
  border-radius: 999px;
}

.theme-toggle__icon {
  width: 0.72em;
  height: 0.72em;
  fill: currentColor;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
}

.theme-toggle__knob {
  position: absolute;
  top: 50%;
  left: calc(100% - var(--knob) - 2px);
  width: var(--knob);
  height: var(--knob);
  border-radius: 50%;
  background: currentColor;
  translate: 0 -50%;
  transition: left 0.3s var(--ease);
}

:root[data-theme="light"] .theme-toggle__knob { left: 2px; }
.theme-toggle:hover .theme-toggle__track { opacity: 0.7; }

/* The home video's Scroll cue always sits on footage, so it stays white. */
.hero > .hero__scroll { color: #fff; }

:root[data-theme="light"] {
  --bg: #fff;
  --fg: #000;
  --muted: rgb(0 0 0 / 0.55);
  --line: rgb(0 0 0 / 0.28);
  --bar-line: 2px solid #000;
  --gold: #857414; /* deeper gold so phone category labels read on white */
}

/* Case-study pages: white page, white type and rules become black.
   Coloured accents and black type on images are left as they are. */
:root[data-theme="light"] .canvas { background: var(--bg) !important; }
:root[data-theme="light"] .c-text.is-white,
:root[data-theme="light"] .c-text [style*="color:#fff"] { color: #000 !important; }
/* White-on-transparent award/press logos (tagged by canvas.js) flip to black. */
:root[data-theme="light"] .c-image.is-white-logo img { filter: invert(1); }
:root[data-theme="light"] .c-line { --color: #000 !important; }
:root[data-theme="light"] .page-scroll .hero__scroll { color: #000; mix-blend-mode: normal; }

/* ==========================================================================
   Small screens
   ========================================================================== */
@media (max-width: 760px) {
  .site-header { grid-template-columns: 1fr auto; }
  .site-header__currently { display: none; }
  .site-header__nav .hide-mobile { display: none; }

  /* On phones the Scroll cue's line runs down to the footer bar's rule on every page. */
  .hero__scroll { bottom: 0; }

  /* Phones swap the two-line title for the shorter mobile one. */
  .site-header__role { display: none; }
  .site-header__role--mobile { display: block; }
  .site-header__id--desktop { display: none; }
  .site-header__id--mobile { display: inline-block; }

  .project__link { grid-template-columns: 1fr; gap: 1rem; }
  .project__title { max-width: none; }

  /* Client (left) and category (right) replace the year above each headline. */
  .project__labels {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    font-size: var(--text-header);
  }
  .project__year { display: none; }

  .info { grid-template-columns: 1fr; }
  .info__col { padding: 0 0 2.5rem; border-left: 0; }

  /* Footer on phones: just the thank-you text. */
  .site-footer__grid { grid-template-columns: 1fr; }
  .site-footer__grid > * { display: none; }
  .site-footer__grid > .site-footer__note--mobile { display: block; }
}
