/* Nathaniel Mason — portfolio
   Plain CSS. Type scale mirrors the original Cargo site: 1rem scales with viewport width. */

:root {
  --font: "Inter Tight", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --white: #fff;
  --text-soft: rgba(255, 255, 255, 0.85);
  --link-green: #91f9a3;
  --active: var(--link-green); /* current-page link and focus rings use the same green as everything else */
  --bleed: 12rem; /* the blur starts this far outside the column, so rows/nav run past the column edge */
  --edge: 32rem; /* width of the blurred feather inside each column edge */
  --pad: 3.2rem; /* inner side padding of the content */
  --col: 1280px; /* the site is a centred tablet-width column; the backdrop still fills the screen */
}

html {
  /* the original's type scale (~8.7px at 390px wide, ~13px at 1440px), capped at the column width */
  font-size: calc(7.17px + min(100vw, var(--col)) * 0.00402);
  -webkit-text-size-adjust: 100%;
  background: #000;
}

@media (max-width: 767px) {
  :root { --bleed: 0rem; }
  html { font-size: calc((7.17px + 0.402vw) * 1.14); }
}

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

body {
  overflow-x: clip;
  margin: 0;
  min-height: 100vh;
  background: #000;
  color: var(--white);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a { color: inherit; }
a:active { opacity: 0.7; }
:focus-visible { outline: 0.2rem solid var(--active); outline-offset: 0.2rem; }


/* progressive blur: everything outside the column is fully blurred, and inside each column edge the blur
   eases off gradually.  12 thin layers. Deeper layers blur only a hair, layers
   nearer the edge blur more, and each fades in over a short distance, so the blur builds up smoothly with no
   sharp-to-blurred step anywhere */
.edge-blur {
  position: fixed;
  inset: 0;
  z-index: 25;
  pointer-events: none;
}
.edge-blur i {
  --m: calc(var(--edge) * 2 / 12);                    /* how long each layer takes to fade out (overlaps its neighbours) */
  --d: calc((var(--edge) - var(--m)) * (12 - var(--k)) / 11); /* distance from the edge where this layer is fully on */
  position: absolute;
  inset: 0;
  -webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(calc(50% - min(var(--col), 100%) / 2 - var(--bleed)) + var(--d)), transparent calc(calc(50% - min(var(--col), 100%) / 2 - var(--bleed)) + var(--d) + var(--m)), transparent calc(calc(50% + min(var(--col), 100%) / 2 + var(--bleed)) - var(--d) - var(--m)), #000 calc(calc(50% + min(var(--col), 100%) / 2 + var(--bleed)) - var(--d)), #000 100%);
  mask-image: linear-gradient(to right, #000 0, #000 calc(calc(50% - min(var(--col), 100%) / 2 - var(--bleed)) + var(--d)), transparent calc(calc(50% - min(var(--col), 100%) / 2 - var(--bleed)) + var(--d) + var(--m)), transparent calc(calc(50% + min(var(--col), 100%) / 2 + var(--bleed)) - var(--d) - var(--m)), #000 calc(calc(50% + min(var(--col), 100%) / 2 + var(--bleed)) - var(--d)), #000 100%);
}
.edge-blur i:nth-child(1) { --k: 1; -webkit-backdrop-filter: blur(0.05rem); backdrop-filter: blur(0.05rem); }
.edge-blur i:nth-child(2) { --k: 2; -webkit-backdrop-filter: blur(0.073rem); backdrop-filter: blur(0.073rem); }
.edge-blur i:nth-child(3) { --k: 3; -webkit-backdrop-filter: blur(0.107rem); backdrop-filter: blur(0.107rem); }
.edge-blur i:nth-child(4) { --k: 4; -webkit-backdrop-filter: blur(0.155rem); backdrop-filter: blur(0.155rem); }
.edge-blur i:nth-child(5) { --k: 5; -webkit-backdrop-filter: blur(0.227rem); backdrop-filter: blur(0.227rem); }
.edge-blur i:nth-child(6) { --k: 6; -webkit-backdrop-filter: blur(0.331rem); backdrop-filter: blur(0.331rem); }
.edge-blur i:nth-child(7) { --k: 7; -webkit-backdrop-filter: blur(0.483rem); backdrop-filter: blur(0.483rem); }
.edge-blur i:nth-child(8) { --k: 8; -webkit-backdrop-filter: blur(0.705rem); backdrop-filter: blur(0.705rem); }
.edge-blur i:nth-child(9) { --k: 9; -webkit-backdrop-filter: blur(1.029rem); backdrop-filter: blur(1.029rem); }
.edge-blur i:nth-child(10) { --k: 10; -webkit-backdrop-filter: blur(1.502rem); backdrop-filter: blur(1.502rem); }
.edge-blur i:nth-child(11) { --k: 11; -webkit-backdrop-filter: blur(2.193rem); backdrop-filter: blur(2.193rem); }
.edge-blur i:nth-child(12) { --k: 12; -webkit-backdrop-filter: blur(3.2rem); backdrop-filter: blur(3.2rem); }

/* ---------- typography ---------- */

.bodycopy {
  display: block;
  font-size: 2.1rem;
  font-weight: 500;
  line-height: 1;
  color: var(--white);
}
.bodycopy a { color: var(--white); text-decoration: underline; }
.bodycopy h1 a { color: var(--link-green); text-decoration: none; }
.bodycopy h2 a { color: var(--white); text-decoration: none; }

[style*="--font-scale"] { font-size: calc(var(--font-scale) * 1em); }

h1 {
  display: inline-block;
  margin: 0;
  font-weight: 400;
  font-size: 6.4rem;
  line-height: 1;
  color: var(--text-soft);
  font-feature-settings: "ss07";
}
h1 a { color: var(--link-green); text-decoration: none; }

h2 {
  display: inline-block;
  margin: 0;
  font-weight: 500;
  font-size: 3.35rem;
  line-height: 1.1;
  color: var(--white);
}
h2 a { color: var(--white); text-decoration: none; }

.small-caps { font-variant: small-caps; text-transform: lowercase; }

hr {
  display: block;
  height: 0.5rem;
  margin: -0.1rem 0 0.7rem;
  border: 0;
  background: var(--text-soft);
}

blockquote { margin: 0; padding: 0 0 0 2em; }

.caption {
  display: block;
  font-size: 1.6rem;
  font-weight: 500;
  line-height: 1.2;
  color: var(--text-soft);
}
.caption a { color: var(--text-soft); text-decoration: underline; }

.side-note {
  display: block;
  font-size: 1.45rem;
  font-weight: 500;
  line-height: 1;
}
.side-note a { text-decoration: underline; }

/* ---------- layout ---------- */

.page-content {
  position: relative;
  max-width: var(--col);
  margin: 0 auto;
  padding: 15.5rem var(--pad) 5rem;
}

.cols {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter, 1rem);
}
.col {
  grid-column: span var(--span, 12);
  min-width: 0;
}

/* ---------- nav ---------- */

.site-nav {
  position: absolute;
  top: 0; left: 0; right: 0;
  max-width: var(--col);
  margin: 0 auto;
  z-index: 1;
  display: flex;
  flex-direction: column;
  padding: 1.5rem 0;
}
/* scrolling line across the full width, name directly underneath */
.site-nav .nav-marquee {
  order: -1;
  margin: 0 calc(-1 * var(--bleed));
  max-width: none;
  font-size: 2.1rem;
  font-weight: 500;
  line-height: 1.5;
  color: #fbfbfb;
}
.brand {
  display: block;
  margin: 0.4rem 0 0 var(--pad);
  text-decoration: none;
}
.brand h2 { font-size: 4rem; line-height: 1.1; white-space: nowrap; }
/* about / email / insta: directly under the name, under the edge blur like the name itself (still clickable) */
.nav-links {
  position: absolute; top: 9.9rem; left: 0; right: 0; z-index: 2; /* above the backdrop, below the edge blur (z-index 25) */
  max-width: var(--col); margin: 0 auto; padding-left: var(--pad);
  font-size: 2.1rem; font-weight: 500; line-height: 1.2; color: var(--white);
  pointer-events: none;
}
.nav-links a { color: var(--white); text-decoration: underline; pointer-events: auto; }
.nav-links a.active { color: var(--active); }

.mobile-nav { display: none; }

/* text, video and images stay crisp: only the background, the nav line, the marquee rows and the map scene go under the blur */
.bodycopy > :not(.marquee):not(.map) { position: relative; z-index: 30; }

/* ---------- marquees ---------- */

.marquee {
  overflow: hidden;
  white-space: nowrap;
  max-width: 100%;
  touch-action: pan-y;
}
.marquee[data-drag] { cursor: grab; }
.marquee.dragging { cursor: grabbing; user-select: none; }
.marquee-track { display: inline-flex; will-change: transform; }
.marquee-inner { display: inline-block; vertical-align: top; padding-right: 1.2rem; }
.marquee-inner h1 { white-space: nowrap; }
.marquee-inner hr { margin-right: 0; }

/* project thumbnails inside the home-page rows: taller than the lettering, they grow on hover */
.thumbs { display: inline-flex; align-items: center; gap: 1.2rem; margin: 0 1rem 0 1.8rem; vertical-align: middle; }
.thumb { display: block; }
.thumb img { display: block; height: 8.5rem; width: auto; transform-origin: center; transition: transform 0.35s ease, opacity 0.35s ease; }
@media (hover: hover) {
  .thumb:hover img { transform: scale(1.5); opacity: 1; }
}

/* the rows clip their contents, so give them spare room above and below for the enlarged thumbnails.
   The padding and the matching negative margin cancel out, so the page layout doesn't change. */
.home .page-content .marquee { position: relative; padding-block: 2.6rem; margin-top: -5.2rem; }
/* neighbouring negative margins would merge, so only the top margin is used; the first and last rows are trimmed to match */
.home .page-content .cols + .marquee { margin-top: -2.6rem; }
.home .page-content .marquee:last-child { margin-bottom: -2.6rem; }
.home .page-content .marquee:hover { z-index: 3; }

/* ---------- media ---------- */

.mi { position: relative; display: block; margin: 0; }
.mi img, .mi video { display: block; width: 100%; height: auto; }
.mi .caption { margin-top: 0.5em; }
.mi-embed iframe { display: block; width: 100%; aspect-ratio: 16 / 9; border: 0; }
.col > .mi { width: var(--scale, 100%); }
.mi.zoomable img { cursor: zoom-in; }

.gallery-grid {
  --cols: 12;
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  gap: var(--gutter);
  margin-top: 1rem;
}
.gallery-grid > .mi { grid-column: span var(--span, var(--cols)); }

.gallery-columnized {
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  gap: var(--gutter);
}

/* justified rows: each item's basis is aspect-ratio x row height (row height is a % of the gallery width) */
.gallery-justify {
  container-type: inline-size;
  display: flex;
  flex-wrap: wrap;
  gap: var(--gutter);
  margin-top: 1rem;
}
.gallery-justify > .mi {
  flex: var(--ar, 1.5) 1 calc(var(--ar, 1.5) * var(--row-h) * 1cqw);
  min-width: 0;
}
.gallery-justify > .mi.last-row { flex-grow: 0; }
.gallery-justify > .mi .caption { display: none; }

/* freeform "moodboard": positions are percentages of the gallery width */
.freeform-wrap { container-type: inline-size; overflow-x: clip; margin-top: 1rem; }
.gallery-freeform { position: relative; height: calc(var(--h) * 1cqw); }
.gallery-freeform > .mi {
  position: absolute;
  left: calc(var(--x) * 1%);
  top: calc(var(--y) * 1cqw);
  width: calc(var(--w) * 1%);
  z-index: var(--z, 1);
}

/* ---------- home ---------- */

.backdrop {
  position: fixed;
  inset: -12%;
  z-index: 0;
  background: #000 url("../assets/home/backdrop.jpg") center / cover no-repeat;
  opacity: 0.5;
  animation: backdrop-drift 120s ease-in-out infinite alternate;
  pointer-events: none;
}
@keyframes backdrop-drift {
  from { transform: rotate(-4deg) scale(1.05) translate3d(-2%, -1%, 0); }
  to   { transform: rotate(5deg)  scale(1.18) translate3d(2%, 2%, 0); }
}

.home .page-content { padding-top: 15.5rem; }
/* intro: video on top, welcome note underneath, at every width */
.home .cols { display: block; margin-bottom: 4rem; padding: 0 15%; }
.home .col { margin-bottom: 1.5rem; }
.home .cols span { --font-scale: 1 !important; }
.marquee hr { display: none; }
.marquee-inner h1 { margin-bottom: 0.6rem; }
.home .cols .mi video { background: transparent; }
.home .marquee-inner h1 { display: inline-block; }
.home .page-content .marquee { margin-left: calc(-1 * (var(--pad) + var(--bleed))); margin-right: calc(-1 * (var(--pad) + var(--bleed))); max-width: none; }

.flying-object {
  position: fixed;
  left: 0; top: 0;
  z-index: 0; /* floats over the backdrop but behind the text and video */
  width: 16.9vmax;
  animation: fly 90s linear infinite;
}
.flying-object img { display: block; width: 100%; height: auto; }
@keyframes fly {
  0%   { transform: translate(8vw, 62vh)  rotate(0deg); }
  25%  { transform: translate(68vw, 18vh) rotate(90deg); }
  50%  { transform: translate(52vw, 64vh) rotate(180deg); }
  75%  { transform: translate(14vw, 26vh) rotate(270deg); }
  100% { transform: translate(8vw, 62vh)  rotate(360deg); }
}

/* ---------- lightbox ---------- */

.lightbox {
  position: fixed; inset: 0; z-index: 10000;
  display: flex; align-items: center; justify-content: center;
  padding: 3rem;
  background: rgba(0, 0, 0, 0.94);
  cursor: zoom-out;
}
.lightbox img { max-width: 100%; max-height: 100%; object-fit: contain; }
.lightbox button {
  position: absolute; top: 50%;
  width: 4.4rem; height: 4.4rem; margin-top: -2.2rem;
  border: 0; border-radius: 50%;
  background: rgba(168, 168, 168, 0.6); color: #000;
  font: inherit; font-size: 2.4rem; line-height: 1; cursor: pointer;
}
.lightbox .lb-prev { left: 1rem; }
.lightbox .lb-next { right: 1rem; }

/* visible to screen readers only */
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }

/* ---------- map page ---------- */


.map-intro { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 2.4rem; margin: 1.6rem 0 2.2rem; }
.map-intro p { margin: 0; }
.map-toggle { display: inline-flex; }
.map-toggle { margin-left: auto; }
.map-toggle button {
  font: inherit; font-size: 1.25rem; font-weight: 500; line-height: 1;
  color: var(--white); background: transparent;
  border: 0.14rem solid var(--text-soft); padding: 0.45rem 1rem; cursor: pointer;
}
.map-toggle button + button { border-left: 0; }
.map-toggle button[aria-pressed="true"] { background: var(--white); color: #000; }
.map-toggle button:hover { background: rgba(255, 255, 255, 0.18); }
.map-toggle button[aria-pressed="true"]:hover { background: var(--white); }

/* no JavaScript: the index shows. JavaScript switches the view with data-view. */
.mapwrap[data-view="index"] .map,
.mapwrap[data-view="index"] [data-map-only] { display: none; }
.mapwrap[data-view="map"] .index { display: none; }

/* the 3D scene: JavaScript places every node; depth sets its size and brightness */
.map {
  position: relative; overflow: hidden; contain: layout paint;
  margin-left: calc(-1 * (var(--pad) + var(--bleed))); margin-right: calc(-1 * (var(--pad) + var(--bleed)));
  height: max(520px, 72vh);
  cursor: grab; touch-action: pan-y; user-select: none; -webkit-user-select: none;
}
.map.dragging { cursor: grabbing; }
.map-lines { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.map-lines line { stroke: var(--white); stroke-width: 1.4; transition: stroke 0.25s ease, stroke-width 0.25s ease; }
.map.has-focus .map-lines line { stroke-opacity: 0.06 !important; }
.map .map-lines line.is-linked { stroke: var(--link-green); stroke-width: 2.4; stroke-opacity: 1 !important; }

.node { position: absolute; left: 0; top: 0; margin: 0; --depth: 1; opacity: calc(0.3 + 0.7 * var(--depth)); transition: opacity 0.25s ease; will-change: transform; }
.map.has-focus .node { opacity: 0.18; }
.map.has-focus .node.is-near { opacity: 0.5; }
.map.has-focus .node.is-linked { opacity: 1; }

/* keywords: solid green blocks, a little bigger the more projects they hold */
.hub {
  cursor: pointer;
  font: inherit; font-weight: 600; font-size: calc(1.5rem + var(--n) * 0.17rem); line-height: 1; white-space: nowrap;
  color: #000; background: var(--link-green);
  border: 0; padding: 0.55em 0.75em;
}
.hub .count { font-size: 0.55em; margin-left: 0.3em; vertical-align: top; opacity: 0.65; }
.hub[aria-pressed="true"] { background: var(--white); }

.bodycopy .project {
  display: block; width: 7.2rem; padding: 0.4rem 0.4rem 0.5rem;
  color: var(--white); text-decoration: none; cursor: pointer;
  border: 0.14rem solid #000; background: rgba(0, 0, 0, 0.35);
  transition: opacity 0.25s ease, border-color 0.25s ease, background-color 0.25s ease;
}
.map.has-focus .project.is-linked { border-color: var(--link-green); background: rgba(145, 249, 163, 0.12); }
.project img { display: block; width: 100%; height: 4.8rem; object-fit: cover; user-select: none; -webkit-user-drag: none; pointer-events: none; }
/* labels fade out for nodes at the back, and come back when something lights them up */
.project .label { display: block; margin-top: 0.35rem; font-size: 1.05rem; font-weight: 500; line-height: 1.1; text-transform: uppercase; opacity: calc((var(--depth) - 0.3) * 2.4); }
.map.has-focus .node.is-linked .label, .map.has-focus .node.is-near .label { opacity: 1; }
.bodycopy .project:hover .label, .bodycopy .project:focus-visible .label { text-decoration: underline; }

/* the selected project: a short summary panel, with a button to open the page */
.map .project.is-selected { border-color: var(--link-green); background: rgba(145, 249, 163, 0.16); }
.mapwrap.bodycopy > .map-panel {
  position: fixed; left: 50%; bottom: 1.2rem; z-index: 1000; /* pinned to the window so it is always on screen */
  width: min(46rem, calc(100% - 2rem)); padding: 1.2rem 1.4rem 1.3rem;
  transform: translateX(-50%);
  background: rgba(0, 0, 0, 0.8); border: 0.14rem solid var(--link-green);
  font-size: 1.5rem; line-height: 1.3; cursor: default;
  animation: panel-in 0.25s ease;
}
.map-panel p { margin: 0; }
.map-panel .panel-title { padding-right: 2.4rem; font-size: 1.7rem; font-weight: 600; line-height: 1.1; text-transform: uppercase; }
.map-panel .panel-text { margin-top: 0.6rem; font-weight: 400; color: var(--text-soft); }
.bodycopy .map-panel .panel-link {
  display: inline-block; margin-top: 0.9rem; padding: 0.5rem 1rem;
  font-size: 1.4rem; font-weight: 600; line-height: 1; color: #000; text-decoration: none; background: var(--link-green);
}
.map-panel .panel-close {
  position: absolute; top: 0.5rem; right: 0.6rem; padding: 0.2rem 0.6rem;
  font: inherit; font-size: 2.2rem; line-height: 1; color: var(--white); background: transparent; border: 0; cursor: pointer;
}
@keyframes panel-in { from { opacity: 0; transform: translate(-50%, 0.8rem); } to { opacity: 1; transform: translate(-50%, 0); } }
@media (prefers-reduced-motion: reduce) { .map-panel { animation: none; } }

/* the index: an edge-to-edge grid of tall picture tiles; the text sits on white labels in the top corner */
.index {
  margin-left: calc(-1 * var(--pad)); margin-right: calc(-1 * var(--pad)); /* full width of the column */
}
.index-list { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.1rem; margin: 0; padding: 0; list-style: none; background: rgba(0, 0, 0, 0.85); }
.index-project { margin: 0; min-width: 0; }
.bodycopy .tile { position: relative; display: block; aspect-ratio: 3 / 4; overflow: hidden; color: #000; text-decoration: none; background: #111; }
.tile img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: filter 0.3s ease, transform 0.6s ease; }
.tile:hover img, .tile:focus-visible img { filter: brightness(1.12); transform: scale(1.03); }
.tile-text { position: relative; display: block; padding: 0.7rem 0.8rem; line-height: 1.2; pointer-events: none; }
.tile-title, .tile-sub {
  background: #fff; color: #000;
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}
.tile-title { display: inline; padding: 0.05em 0.3em; font-size: 2.3rem; font-weight: 500; line-height: 1.3; }
.tile-sub { display: table; margin-top: 0.4rem; padding: 0.1em 0.35em; font-size: 1.45rem; font-weight: 400; }

/* ---------- mobile ---------- */

@media (max-width: 767px) {
  .bodycopy { font-size: 2.55rem; }
  h1 { font-size: 4.5rem; font-weight: 440; }
  .caption { font-size: 2rem; }
  .side-note { font-size: 2rem; }

  .edge-blur { display: none; }
  .site-nav, .nav-links { display: none; }
  .mobile-nav {
    display: block;
    position: absolute; top: 0; left: 0; right: 0; z-index: 20;
    padding: 0.7rem;
    font-size: 2.55rem; font-weight: 500; line-height: 1.15;
  }
  .mobile-nav h2 { display: block; font-size: 3.35rem; margin-bottom: 0.4rem; }
  .mobile-nav a { display: block; color: var(--white); text-decoration: underline; }
  .mobile-nav h2 a { text-decoration: none; }

  .page-content { padding: 15rem 0.7rem 5rem; }
  .home .page-content { padding-top: 15rem; }
  .home .page-content .marquee { margin-left: -0.7rem; margin-right: -0.7rem; }
  .flying-object { width: 12vmax; }

  .cols { display: block; }
  .home .cols { padding: 0; }
  .col { margin-bottom: 1.2rem; }
  .gallery-grid { grid-template-columns: 1fr; }
  .gallery-grid > .mi { grid-column: auto; max-width: 100%; }
  .gallery-justify { gap: var(--m-gutter); }
  .gallery-justify > .mi { flex-basis: calc(var(--ar, 1.5) * var(--m-row-h) * 1cqw); }
  .gallery-freeform {
    height: auto;
    display: flex; flex-direction: column; gap: var(--m-gutter);
  }
  .gallery-freeform > .mi { position: static; width: 100%; }
  .lightbox { padding: 0.5rem; }

  .map-intro { gap: 1rem; }
  .map-toggle { margin-left: 0; }
  .map-toggle button { font-size: 1.5rem; padding: 0.55rem 1.1rem; }
    .map { height: min(80vh, 680px); margin-left: 0; margin-right: 0; }
  .hub { font-size: calc(1.15rem + var(--n) * 0.12rem); padding: 0.5em 0.65em; }
  .hub .count { display: none; }
  .bodycopy .project { width: 6rem; }
  .project img { height: 4rem; }
  .project .label { font-size: 1rem; }
  .index { margin-left: -0.7rem; margin-right: -0.7rem; }
  .index-list { grid-template-columns: 1fr 1fr; }
  .tile-text { padding: 0.5rem 0.55rem; }
  .tile-title { font-size: 1.9rem; }
  .tile-sub { font-size: 1.3rem; }
  }

@media (prefers-reduced-motion: reduce) {
  .backdrop, .flying-object { animation: none; }
}
