/* Folio — shared styles
   Layout mirrors the Figma frames (1512px wide, 12-col grid, 1.5px #444 gutters) at every width
   from 640px up; below that the grid becomes a single column.
   Everything scales from the design so proportions match desktop at every breakpoint:
   - --k: 1 design px relative to the tile's own width (type, in-tile geometry). Children only.
   - --u: 1 design px relative to the page width (padding, buttons), usable on tiles themselves.
     Equals --k for the desktop grid; on mobile, tiles are full width so --u = 100vw / 753.75. */

@font-face {
  font-family: "Humane";
  src: url("fonts/Humane-SemiBold.ttf") format("truetype");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

:root {
  --ink: #e5e7d5;
  --tile: #000;
  --tile-hover: #141414;            /* #000 + 8% white overlay */
  --line: #444;
  --edge: #1c1c1c;
  --gap: 1.5px;                     /* snapped to whole screen pixels by the inline <head> script */
  --max: 1760px;                    /* widest the site gets; black space either side beyond this */
  --u: calc(min(100vw, var(--max)) / 1512);
  --pad: calc(32 * var(--u));
  --btn: calc(64 * var(--u));
  --serif: "Instrument Serif", Georgia, "Times New Roman", serif;
  --display: "Humane", "Arial Narrow", Impact, sans-serif;
}

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

html { background: #000; -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: #000;
  color: var(--ink);
  font-family: var(--serif);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img { display: block; }
h1, h2, p { margin: 0; font-weight: inherit; font-size: inherit; }
a { color: inherit; text-decoration: none; }
/* No browser focus ring on mouse or touch clicks (it shows in the system accent colour); keyboard
   users get the site's own outline instead. */
a:focus:not(:focus-visible), a:focus:not(:focus-visible) * { outline: none; }
a:focus-visible { outline: 2px solid var(--ink); outline-offset: -6px; }

/* ---------- Grid ---------- */

.grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--gap);
  padding: var(--gap);
  max-width: var(--max);
  margin: 0 auto;
  background: var(--line);          /* shows through the gaps as the 1.5px lines */
}

.tile {
  --base: 753.75;                   /* tile width in the design (px) */
  --px: calc(2 * var(--pad));       /* total horizontal padding */
  --k: calc((100cqi + var(--px)) / var(--base));   /* use on children only */
  position: relative;
  container-type: inline-size;
  align-self: stretch;              /* every tile fills its row, so taller neighbours never leave gaps */
  justify-self: stretch;            /* exactly its columns' width: with an aspect ratio, a tile stretched */
  min-width: 0;                     /* to its row's height would otherwise widen into the gap beside it */
  padding: var(--pad);
  background: var(--tile);
  transition: background-color 0.3s ease;
}
/* text blocks only (project cards, "Let's work together"); image previews keep their black frame */
a.tile:not(.tile--img):focus-visible { background-color: var(--tile-hover); }
/* Hover effects only with a mouse or trackpad: on touch screens, scrolling past a block would
   otherwise trigger them. */
@media (hover: hover) and (pointer: fine) {
  a.tile:not(.tile--img):hover { background-color: var(--tile-hover); }
}

.s4  { grid-column: span 4;  --base: 502; }
.s6  { grid-column: span 6; }
.s8  { grid-column: span 8;  grid-row: span 2; --base: 1005; }
.s12 { grid-column: span 12; --base: 1508; }
.bd { --px: calc(2 * var(--pad) + 2px); border-right: 2px solid var(--edge); border-bottom: 2px solid var(--edge); }

/* ---------- Type ---------- */

.title-xl, .title-lg, .hero__title {
  font-family: var(--display);
  font-weight: 600;
  line-height: 0.78;
  text-transform: uppercase;
  text-wrap: balance;
  overflow-wrap: break-word;
  font-feature-settings: "ordn" 1, "salt" 1, "dlig" 1;
  text-box: trim-both cap alphabetic;
}
.title-xl { font-size: calc(244 * var(--k)); }
.title-lg { font-size: calc(128 * var(--k)); }

.body-lg, .body-sm, .cta {
  font-family: var(--serif);
  letter-spacing: -0.02em;
  font-feature-settings: "ordn" 1;
  text-box: trim-both cap alphabetic;
}
.body-lg, .body-sm {
  line-height: 1.06;
  text-wrap: pretty;                /* fill lines to the edge, but no lone last word */
  /* Right edge sits at 80% of the block's width, leaving a 20% gap on the right in every block
     (block width = content width + horizontal padding). */
  width: calc(0.8 * (100cqi + var(--px)) - var(--pad));
  max-width: none;
}
/* Paragraphs scale with the design but never drop below a comfortable reading size. */
.body-lg { font-size: max(19px, calc(34.2 * var(--k))); }
.body-sm { font-size: max(17px, calc(24 * var(--k))); }

/* ---------- Buttons ---------- */

.btn {
  position: relative;
  display: block;
  flex: none;
  width: var(--btn);
  height: var(--btn);
}
.btn svg {
  position: absolute;
  top: -2.34%;
  left: -2.34%;
  width: 104.68%;
  height: 104.68%;
  overflow: visible;
  transition: transform 0.3s ease;
}
/* The ring keeps the gutter width (1.5px) at every button size (non-scaling stroke). */
.btn__ring { fill: none; stroke: var(--edge); stroke-width: var(--gap); transition: stroke 0.3s ease; }
.btn__arrow { fill: var(--ink); }
a:focus-visible .btn svg { transform: scale(1.08); }
a:focus-visible .btn__ring { stroke: #444444; }
@media (hover: hover) and (pointer: fine) {
  a:hover .btn svg { transform: scale(1.08); }
  a:hover .btn__ring { stroke: #444444; }
}
/* In the footer "Fearless" block the logo and the back arrow are separate links; hovering the logo
   shows the arrow as hovered too (at the top of project pages they already share one link). */
.tile:has(.hero__logo-link:focus-visible) .hero__back .btn svg { transform: scale(1.08); }
.tile:has(.hero__logo-link:focus-visible) .hero__back .btn__ring { stroke: #444444; }
@media (hover: hover) and (pointer: fine) {
  .tile:has(.hero__logo-link:hover) .hero__back .btn svg { transform: scale(1.08); }
  .tile:has(.hero__logo-link:hover) .hero__back .btn__ring { stroke: #444444; }
}

/* ---------- Case study intro ---------- */

.tile--intro {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 80px;                        /* the least space between the heading and the paragraph */
}
.intro__heading {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: calc(56 * var(--k));
  width: 100%;
}
.back { position: relative; display: flex; height: var(--btn); }
.back__logo {
  position: absolute;
  left: calc(var(--btn) - 24.54 * var(--k));   /* 39.46 at desktop; stays clear of a larger button */
  top: calc(12.09 * var(--k));
  width: calc(186.778 * var(--k));
  height: calc(84.316 * var(--k));
  max-width: none;
  transform: rotate(-8deg);
  cursor: pointer;                  /* part of the back link: clicking the logo goes home too */
}

/* ---------- Image + text tiles ---------- */

.tile--img { display: flex; flex-direction: column; overflow: hidden; }
.media { position: relative; flex: 1 1 0; min-height: 1px; width: 100%; overflow: hidden; }
/* Each image overhangs its frame by 2px on every side; .media clips the overhang, hiding any
   discoloured edge pixels from the exports or compression. */
.media img {
  position: absolute;
  top: -2px;
  left: -2px;
  width: calc(100% + 4px);
  height: calc(100% + 4px);
  max-width: none;
}
.fit-cover { object-fit: cover; }
.fit-fill { object-fit: fill; }
a.tile--img .media img { transition: transform 0.7s cubic-bezier(0.2, 0.7, 0.2, 1); }
/* .is-hover: hovering a project's text card zooms its image too (site.js); not the other way round */
a.tile--img.is-hover .media img { transform: scale(1.03); }
@media (hover: hover) and (pointer: fine) {
  a.tile--img:hover .media img { transform: scale(1.03); }
}

.tile--text { display: flex; flex-direction: column; justify-content: flex-end; }

/* ---------- Project cards (homepage) ---------- */

.tile--card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  --px: calc(3 * var(--pad) + var(--btn));
  padding-right: calc(2 * var(--pad) + var(--btn));
}
/* paragraph sits at the bottom, at least 80px below the title */
.tile--card .title-lg { margin-bottom: max(80px, calc(80 * var(--k))); }
.tile--card .body-sm { margin-top: auto; }
.tile--card .title-lg { width: 100%; }
.tile--card .btn { position: absolute; top: var(--pad); right: var(--pad); }
.tile--card-fixed { aspect-ratio: 502 / 613.93; justify-content: space-between; }

/* Tick-over heading: each time the pointer enters a card (script.js adds .is-ticking), every letter
   rolls up once like an odometer digit, staggered left to right.
   Capitals span -0.031em..0.681em of each 0.78em line. Each letter is clipped to just its capitals
   (-0.036em..0.686em, allowing for antialiasing), so neighbouring lines always keep a 0.058em gap and
   cut letter edges never meet. A 0.8em roll moves each copy fully out of its window and keeps the
   outgoing and incoming copies 0.088em apart. */
.tick__w { white-space: nowrap; }
.tick__c {
  position: relative;
  display: inline-block;
  clip-path: inset(-0.036em -0.15em 0.094em -0.15em);
}
.tick__c > span { display: block; }
.tick__c > span + span { position: absolute; top: 0; left: 0; transform: translateY(0.8em); }
.tick.is-ticking .tick__c > span {
  animation: 0.5s cubic-bezier(0.65, 0, 0.25, 1) calc(var(--i) * var(--tick-step, 35ms)) both;
}
.tick.is-ticking .tick__c > span:first-child { animation-name: tick-out; }
.tick.is-ticking .tick__c > span + span { animation-name: tick-in; }
@keyframes tick-out { from { transform: translateY(0); } to { transform: translateY(-0.8em); } }
@keyframes tick-in { from { transform: translateY(0.8em); } to { transform: translateY(0); } }

/* Load-in tick (first heading on each page, and the "Fearless…" headings): as its block is revealed, site.js adds .is-ticking-in and
   the letters roll up into place, staggered left to right. Only the incoming copy moves; the resting
   copy stays hidden until the roll ends, so the result is identical to the static heading. */
.tick.is-ticking-in .tick__c > span:first-child { visibility: hidden; }
.tick.is-ticking-in .tick__c > span + span {
  animation: tick-in 0.5s cubic-bezier(0.65, 0, 0.25, 1) calc(var(--i) * var(--tick-step, 35ms)) both;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- Hero ("Fearless…") + call to action ---------- */

.tile--hero { --pad: 0px; aspect-ratio: 753.75 / 928.69; overflow: hidden; }
.hero__title {
  position: absolute;
  left: calc(32 * var(--k));
  right: calc(32 * var(--k));
  top: calc(247.35 * var(--k));
  font-size: calc(180 * var(--k));
  text-align: center;
}
.hero__title > span { display: block; text-wrap: balance; }
.hero__logo {
  position: absolute;
  left: calc(141.34 * var(--k));
  top: calc(105.63 * var(--k));
  width: calc(412.328 * var(--k));
  height: calc(186.136 * var(--k));
  max-width: none;
  transform: rotate(-8deg);
  z-index: 1;                       /* logo overlaps the title, as in the design */
}
.hero__back { position: absolute; left: calc(32.5 * var(--k)); top: calc(31.75 * var(--k)); }

/* The "Fearless…" logo links home. The link takes no box of its own, so the logo keeps its position. */
.hero__logo-link { display: contents; }
.hero__logo-link .hero__logo { cursor: pointer; }
.hero__logo-link:focus-visible .hero__logo { outline: 2px solid var(--ink); outline-offset: 4px; }

/* Project page → homepage hand-off (site.js): the footer back button fades away as it is clicked, and
   on arrival the homepage shows its top row in place with no load-in animation. */
.js-reveal .tile > .hero__back.is-leaving, .hero__back.is-leaving {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
  transition-delay: 0s;
}
.handoff .grid > .tile:nth-child(-n + 2) > * { opacity: 1; translate: none; transition: none; }

/* First-visit loading screen (site.js): black from the very first paint, the page hidden beneath, the
   logo writing in and out at half the screen's width. Fades away once everything has downloaded. */
html.is-loading, html.is-loading body { background: #000; overflow: hidden; }
html.is-loading main { visibility: hidden; }
.loader {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: grid;
  place-items: center;
  background: #000;
  transition: opacity 0.6s ease;
}
.loader.is-done { opacity: 0; pointer-events: none; }
.loader__logo {
  /* the same size as the logo in the "Fearless…" block (site.js copies its exact size) */
  width: calc(412.328 * var(--u));
  height: calc(186.136 * var(--u));
  max-width: none;
  transform: rotate(-8deg);         /* as everywhere else on the site */
}

/* Homepage → project transition (TEST: transition-test.html → project pages with ?vt=1). The clicked
   preview image glides and resizes into the project's first image while the pages cross-fade softly.
   Images keep their crop while the frame changes shape (no stretching). */
.vt-arrive #lead-image > * { opacity: 1; translate: none; transition: none; }
::view-transition-group(project-image) {
  animation-duration: 0.7s;
  animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1);
}
::view-transition-old(project-image),
::view-transition-new(project-image) {
  height: 100%;
  object-fit: cover;
  animation-duration: 0.7s;
}
::view-transition-old(root) { animation: 0.35s ease-out both vt-fade-out; }
::view-transition-new(root) { animation: 0.45s ease-out 0.15s both vt-fade-in; }
@keyframes vt-fade-out { to { opacity: 0; } }
@keyframes vt-fade-in { from { opacity: 0; } }

.tile--cta {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 754 / 929;
}
.cta {
  font-size: max(19px, calc(34.2 * var(--k)));
  line-height: 1.16;
  text-align: center;
  white-space: nowrap;
}
.u {
  text-decoration: underline;
  text-decoration-thickness: from-font;
  text-decoration-skip-ink: none;
}
.tile--cta .btn { position: absolute; right: var(--pad); bottom: var(--pad); }

/* ---------- Reveal on load / scroll ---------- */
/* site.js adds .is-revealed (with a staggered --reveal-delay) as each block enters the viewport.
   Only the contents move, so the black blocks and grey gutters stay put. `translate` is used rather
   than `transform` so it combines with existing transforms such as the rotated logo. */
.js-reveal .tile > * {
  opacity: 0;
  translate: 0 24px;
  transition: opacity 2s cubic-bezier(0.2, 0.7, 0.2, 1), translate 2s cubic-bezier(0.2, 0.7, 0.2, 1);
  transition-delay: var(--reveal-delay, 0ms);
}
.js-reveal .tile.is-revealed > * { opacity: 1; translate: none; }

/* ---------- Tablet + mobile scale tweaks ---------- */
/* Same layout as desktop, but buttons read slightly larger and serif text slightly smaller than a
   pure scale-down: buttons +10%, serif text -10% (including its minimum sizes). */
@media (max-width: 1023px) {
  :root { --btn: calc(70.4 * var(--u)); }
  .body-lg, .cta { font-size: max(17.1px, calc(30.78 * var(--k))); }
  .body-sm { font-size: max(15.3px, calc(21.6 * var(--k))); }
}

/* ---------- Mobile: single column ---------- */

@media (max-width: 639px) {
  :root {
    --u: calc(100vw / 753.75);          /* tiles are full width, scaled like a desktop half-tile */
    --pad: calc(32 * var(--u) + 8px);   /* 8px more inset inside every block */
  }
  .hero__back { left: calc(32.5 * var(--k) + 8px); top: calc(31.75 * var(--k) + 8px); }
  .hero__title { left: calc(32 * var(--k) + 8px); right: calc(32 * var(--k) + 8px); }
  .grid > .tile { grid-column: 1 / -1; grid-row: auto; --base: 753.75; }

  /* pair each homepage preview with its card */
  .page-home .tile { order: var(--o, 0); }
  .tile--card-fixed { aspect-ratio: auto; }
  .tile--no-phone { display: none; }   /* feature rows keep only their large image */

  /* text blocks 25% shorter (not the "Fearless" blocks); --ar-phone is set per block by the build */
  .tile--intro, .tile--text { aspect-ratio: var(--ar-phone) !important; }
  .tile--cta { aspect-ratio: 754 / 557.4; }   /* 40% shorter than desktop (25%, then 20% more) */
  /* at least 64px between a heading and its paragraph; blocks grow taller when they need the room */
  .tile--intro { gap: 64px; }
  .tile--card .title-lg { margin-bottom: max(64px, calc(80 * var(--k))); }

  /* arrow buttons 10% larger, their arrows 20% larger (ring stroke stays 1.5px) */
  :root { --btn: calc(77.44 * var(--u)); }
  .btn__arrow { transform-box: fill-box; transform-origin: center; scale: 1.0909; }

  /* paragraphs reach 92% of the block width (80% on larger screens) */
  .body-lg, .body-sm { width: calc(0.92 * (100cqi + var(--px)) - var(--pad)); }

  /* serif text 32% larger than on tablet (20%, then 10% more; minimum sizes too) */
  .body-lg, .cta { font-size: max(22.57px, calc(40.63 * var(--k))); }
  .body-sm { font-size: max(22.2px, calc(28.51 * var(--k) + 2px)); }   /* +2px on top of the scaling */
  .title-xl { font-size: calc(244 * var(--k) - 8px); }   /* project page headings 8px smaller */
  /* homepage card titles 10% larger (project page headings and the "Fearless" blocks unchanged) */
  .title-lg { font-size: calc(140.8 * var(--k)); }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}
