/* ============ SETTINGS ============
   Everything adjustable lives here. */

:root {
  /* the site is dark as standard */
  --ink: #fff;
  --paper: #000;
  /* Gridlines cover the home page's first screen in even squares, one square to 9 degrees of the map,
     then fade out a few squares into the work. No other page has them.
     The page is four columns wide and every column edge falls on a gridline (site.js sizes the squares).
     They are drawn in white and blended by "difference", like the header, so they work on either page colour. */
  --grid: rgba(255, 255, 255, .12);  /* the last number is their strength */
  --hair: .5px;              /* their thickness */
  --grid-tail: 4;            /* how many squares past the first screen they take to fade away */
  --peek: clamp(192px, 19.2vw, 312px); /* width of the image that follows the pointer over a marker */

  --m: 10px;                 /* the site margin: page edge and the space between tiles */
  --radius: 3px;             /* corner rounding on tile images */
  --columns: 3;              /* work gallery columns on a wide screen (also set in site.js) */
  --chart: 50vw;             /* width of the chart on the home page */

  /* type: one size, 12px, for everything on the site; leading and tracking are stand-ins until tuned on type/index.html */
  --font: "ABC Diatype", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --text: 12px;
  --leading: 1.3;
  --tracking: 0;
  --features: normal;        /* stylistic sets, e.g. "ss01", "ss14" */

  /* motion */
  --dur: .6s;
  --ease: cubic-bezier(.2, .6, .2, 1);
  --zoom: 1.025;             /* image scale on hover */
  --slide: .9s;              /* how long a "slider" takes to move from one image to the next */
  --fade: 2.4s;              /* how long one image takes to dissolve into the next in a slideshow: slow and deliberate */
  --cap: calc(var(--text) * var(--leading) + 7px);  /* how much of a tile's foot is cropped to show its title */
}

/* day, chosen with the dot beside the clock: black on a white with just a little grey in it */
:root[data-theme="day"] {
  --ink: #000;
  --paper: rgb(249, 249, 249);
}

/* ============ FONT ============
   ABC Diatype, four cuts. Only these exist, so the browser is told never to fake a weight or slant. */

@font-face { font-family: "ABC Diatype"; font-weight: 400; font-style: normal; font-display: swap; src: url("fonts/ABCDiatype-Regular.woff2") format("woff2"); }
@font-face { font-family: "ABC Diatype"; font-weight: 400; font-style: italic; font-display: swap; src: url("fonts/ABCDiatype-Italic.woff2") format("woff2"); }
@font-face { font-family: "ABC Diatype"; font-weight: 700; font-style: normal; font-display: swap; src: url("fonts/ABCDiatype-Bold.woff2") format("woff2"); }
@font-face { font-family: "ABC Diatype"; font-weight: 700; font-style: italic; font-display: swap; src: url("fonts/ABCDiatype-BoldItalic.woff2") format("woff2"); }

/* ============ BASE ============ */

* { box-sizing: border-box; border-radius: 0; }
html, body { margin: 0; background: var(--paper); color: var(--ink); }
body {
  font: var(--text) / var(--leading) var(--font);
  letter-spacing: var(--tracking);
  font-feature-settings: var(--features);
  font-synthesis: none;
  -webkit-text-size-adjust: 100%;
}
body { position: relative; }
a { color: inherit; text-decoration: none; }

/* ============ GRIDLINES: the home page's first screen, fading out into the work ============
   site.js sets the square size; chart.js shifts the lines so they agree with the map. */

.gridlines {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: calc(100vh + var(--cell, 48px) * var(--grid-tail));
  height: calc(100svh + var(--cell, 48px) * var(--grid-tail));
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - var(--cell, 48px) * var(--grid-tail)), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - var(--cell, 48px) * var(--grid-tail)), transparent);
  z-index: 1;
  pointer-events: none;
  mix-blend-mode: difference;
  background-image:
    linear-gradient(to right, var(--grid) var(--hair), transparent var(--hair)),
    linear-gradient(to bottom, var(--grid) var(--hair), transparent var(--hair));
  background-size: var(--cell, 48px) var(--cell, 48px);
  background-position: var(--grid-x, 0) var(--grid-y, 0);
}
p, h1, h2 { margin: 0; font: inherit; }
img { display: block; }
button { font: inherit; letter-spacing: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
:focus-visible { outline: 1px solid var(--ink); outline-offset: 2px; }

/* ============ HEADER: locked in place, in front of everything ============
   White with "difference" blending: reads white on the black page, near-black on the
   day page, and inverts whatever image it passes over. Name left, Etc. right. */

.head {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 10;
  display: flex;
  justify-content: space-between;
  padding: var(--m);
  color: #fff;
  mix-blend-mode: difference;
  pointer-events: none;      /* only the two links catch clicks, not the strip between them */
}
.head a { pointer-events: auto; }
/* Etc.: the name runs on into a sentence, held to the first of the four columns.
   The words are always there, in place; opening Etc. lets them appear one after another. */
.head .bio { max-width: max(calc(25vw - 2 * var(--m)), 240px); }
.head .bio-rest span { opacity: 0; transition: opacity .2s; }
html.etc .head .bio-rest span { opacity: 1; transition: opacity .5s calc(var(--i) * 35ms + 120ms); }
/* "Etc." and "Close" trade places with a quick fade */
.head [data-etc] { transition: opacity .15s; display: inline-grid; justify-items: end; }
.head [data-etc] > span { grid-area: 1 / 1; }   /* the two words stacked in one place (site.js) */
.head [data-etc]:not(.closing) > :last-child, .head [data-etc].closing > :first-child { visibility: hidden; }
.head [data-etc].swap { opacity: 0; }
.head :focus-visible { outline-color: #fff; }

/* ============ HOME: the chart alone in a blank screen ============ */

.intro {
  position: relative;
  touch-action: pan-y;       /* on a phone, up and down still scrolls the page; sideways drags the map */
  user-select: none;
  -webkit-user-select: none;
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  place-items: center;
  padding: calc(var(--m) * 4) var(--m);
}
.intro .chart { width: max(var(--chart), min(100%, 420px)); }
/* the map runs on past the screen's sides (the land, a name, the hover image): it is cut off there,
   so the page never grows wider than the screen and can't be pushed sideways on a phone */
.intro { overflow-x: clip; }
body { overflow-x: clip; }
.intro[data-view="geo"]:not(.still) { cursor: grab; }
.intro[data-view="geo"].dragging { cursor: grabbing; }

/* Etc. is the first screen only: the work and the footer are put away, so there is nothing to scroll to */
html.etc .work, html.etc .footer { display: none; }

/* a project's image (or stand-in colour) trails the pointer while its marker is hovered */
.peek {
  position: absolute;
  left: 0; top: 0;
  width: var(--peek);
  z-index: 3;                /* in front of the gridlines, markers and dotted links: the image simply covers them */
  aspect-ratio: 4 / 3;       /* every hover image takes this standard crop */
  background-size: cover;
  background-position: center;
  clip-path: inset(0 round var(--radius));
  opacity: 0;
  transition: opacity .25s;
  pointer-events: none;
  will-change: transform;
}
.peek-name {
  position: absolute;
  left: 0; top: 0;
  z-index: 3;
  display: flex;
  align-items: baseline;
  gap: .6em;
  background: var(--paper);
  padding: 1px 0;
  white-space: nowrap;
  opacity: 0;
  transition: opacity .25s;
  pointer-events: none;
  will-change: transform;
}
.peek-name { min-width: var(--peek); }  /* as wide as the image above it, */
.peek-name .note { opacity: .55; }
/* the tag sits at its right edge, under the image's right side, as it does on the tiles */
.peek.on, .peek-name.on { opacity: 1; }

/* ============ WORK: gallery of tiles, no words until hover ============ */

.work {
  position: relative;
  z-index: 2;                /* tiles sit in front of the gridlines */
  padding: 0 var(--m) var(--m);
  columns: var(--columns);   /* fallback; site.js deals tiles into columns in reading order */
  column-gap: var(--m);
}
.work.dealt { columns: auto; display: flex; align-items: flex-start; gap: var(--m); }
.work .col { flex: 1; min-width: 0; }

.tile {
  position: relative;
  display: block;
  aspect-ratio: var(--w) / var(--h);   /* each tile keeps the proportions it was given */
  margin-bottom: var(--m);
  break-inside: avoid;
  cursor: pointer;
}
.tile:focus-visible { outline: none; }

.media {
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow: hidden;
  clip-path: inset(0 round var(--radius));
  transition: clip-path var(--dur) var(--ease);
}
.media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur) var(--ease);
}

/* title on the left, tag on the right, waiting under the foot of the image */
.cap {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: .6em;
  white-space: nowrap;
}
.cap > :first-child { overflow: hidden; text-overflow: ellipsis; }
/* a credit: a smaller line under the title, sized between the main text and the tag. It may run to two lines. */
.cap .credit { flex: 0 0 100%; font-size: 10px; line-height: 1.3; white-space: normal; opacity: .55; }

/* the tag: a minor note of what kind of project this is. Tiny tracked capitals, greyed back,
   at the tile's right edge on the same baseline as the title. */
.tag {
  flex: none;
  margin-left: auto;
  margin-right: -.1em;       /* takes back the tracking after the last letter, so it sits flush with the image's edge */
  font-size: 7px;
  line-height: 1;
  letter-spacing: .1em;
  text-transform: uppercase;
  white-space: nowrap;
  opacity: .55;
}

/* SELECTS: a tile that is its own small slideshow. Arrows in the bottom corners, or a swipe, slide between images. */
.tile.selects { cursor: default; }
.slides {
  display: flex;
  width: 100%;
  height: 100%;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.slides::-webkit-scrollbar { display: none; }
.slides > * { flex: 0 0 100%; height: 100%; scroll-snap-align: start; }
/* The strip only ever moves sideways, and its images are pinned to the top of the frame, so the
   hover crop takes away from the bottom and nothing shifts. The zoom is applied to the strip as a
   whole (below), not to each image, which is what used to nudge them up and to the left. */
.slides { overflow-y: hidden; transform-origin: 50% calc((100% - 24px) / 2); transition: transform var(--dur) var(--ease); }
.media .slides img, .media .slideshow img { object-position: top; }
/* belt and braces: the strip runs a little past the foot of its frame, so a scrollbar could never show even if a browser drew one */
.slides { height: calc(100% + 24px); padding-bottom: 24px; }
.arrow {
  position: absolute;
  z-index: 2;
  bottom: 6px;
  padding: 2px 4px;
  color: #fff;
  mix-blend-mode: difference;   /* readable on any image, like the header */
  opacity: 0;                   /* the arrows only appear with the hover */
  transition: bottom var(--dur) var(--ease), opacity .3s;
}
.arrow.prev { left: 6px; }
.arrow.next { right: 6px; }
.arrow:focus-visible { outline-color: #fff; }

/* the reveal: image zooms slightly and crops up from the bottom */
@media (hover: hover) {
  .tile:hover .media { clip-path: inset(0 0 var(--cap) 0 round var(--radius)); }
  .tile:hover .media img { transform: scale(var(--zoom)); }
  .tile:hover .slides img { transform: none; }
  .tile:hover .slides { transform: scale(var(--zoom)); }
}
@media (hover: hover) {
  .tile:hover .arrow { bottom: calc(var(--cap) + 6px); opacity: 1; }  /* the arrows arrive with the crop */
}
.arrow:focus-visible { opacity: 1; }
.tile:focus-visible .media { clip-path: inset(0 0 var(--cap) 0 round var(--radius)); }
/* no hover on a touch screen: the first tap does what the hover does ("open", set by site.js), a second tap opens the page */
@media (hover: none) {
  .tile.open .media { clip-path: inset(0 0 var(--cap) 0 round var(--radius)); }
  .tile.open .media img { transform: scale(var(--zoom)); }
  .tile.open .slides img { transform: none; }
  .tile.open .slides { transform: scale(var(--zoom)); }
  .tile.open .arrow { bottom: calc(var(--cap) + 6px); opacity: 1; }
  .tile:not(.open) .arrow { pointer-events: none; }  /* until then a tap on an arrow just opens the tile */
}

@media (max-width: 899px) { :root { --columns: 2; } }
@media (max-width: 599px) { :root { --columns: 1; } }

/* ============ CHART ============ */

.chart { --mk: 10px; }
/* the view switch sits in the bottom-left corner of the first screen and scrolls away with it */
.chart .views { position: absolute; left: var(--m); bottom: var(--m); z-index: 2; display: flex; gap: 1.4em; transition: opacity .3s; }
html.etc .chart .views { opacity: 0; pointer-events: none; }
/* beside the view's name: a reading (map coordinates, or a position in the Industry view), and in Geography a way back once the map has been dragged */
.chart .views .coords { min-width: 9.5em; }
.chart .views .reset { visibility: hidden; }
.chart .views.away .reset { visibility: visible; }
.chart .views:not([data-view="geo"]) .reset { display: none; }

.chart .stage {
  position: relative;
  z-index: 2;
  width: 100%;
  aspect-ratio: 2 / 1;
  color: #fff;                  /* everything in the chart is white, then blended like the header */
  mix-blend-mode: difference;
}
.chart svg { position: absolute; left: 0; top: 0; overflow: visible; pointer-events: none; }
.chart .mk, .chart .home-mark { cursor: pointer; }
.chart .lines { width: 100%; height: 100%; }
.chart .lines line, .chart .lines path.cn { fill: none; stroke: #fff; stroke-width: 1; transition: opacity .5s; }
.chart .lines .cn { stroke-dasharray: 2 3; stroke-width: 1.5; }  /* the dotted link between a project's two cities: a flight path */
/* the continents: vague dotted outlines, as grey as the gridlines, in the Geography view only */
.chart .lines .land { fill: none; stroke: var(--grid); stroke-width: 1; stroke-dasharray: 2 3; }
/* home: a small square on London that links to the Etc. page */
.chart .home-mark { position: absolute; left: 0; top: 0; z-index: 1; width: 8px; height: 8px; background: #fff; }
.chart .home-mark::after { content: ""; position: absolute; inset: -6px; }

/* things that belong to one view fade with it */
.chart .geo, .chart .lb.v-service, .chart .lb.v-industry { opacity: 0; transition: opacity .5s; }
.chart .stage[data-view="geo"] .geo,
.chart .stage[data-view="service"] .lb.v-service,
.chart .stage[data-view="industry"] .lb.v-industry { opacity: 1; }

.chart .lb { position: absolute; left: 0; top: 0; white-space: nowrap; pointer-events: none; line-height: 1; background: #000; padding: 1px 2px; }  /* black here reads as "nothing", so a label clears the line behind it */

.chart .mk {
  position: absolute; left: 0; top: 0; z-index: 1;
  width: var(--mk); height: var(--mk);
  border-radius: 50%;
  background: #fff;
  outline: 1px solid #000;  /* a clear ring that keeps overlapping markers distinct */
  transition: opacity .25s;
  will-change: transform;
}
.chart .mk::after { content: ""; position: absolute; inset: -4px; }
.chart .mk.twin { z-index: 0; }
/* Geography view: each marker bobs very slightly about its true place, out of step with its neighbours */
@keyframes bob { 0%, 100% { translate: 0 -1.5px; } 50% { translate: 0 1.5px; } }
.chart .stage[data-view="geo"] .mk { animation: bob 5s ease-in-out infinite; }
.chart .stage[data-view="geo"] .mk:nth-of-type(3n) { animation-duration: 6.1s; animation-delay: -2s; }
.chart .stage[data-view="geo"] .mk:nth-of-type(3n + 1) { animation-duration: 4.3s; animation-delay: -1s; }
@media (prefers-reduced-motion: reduce) { .chart .stage .mk { animation: none !important; } }
/* an Selects project is a ring; a Case Study is a solid dot */
.chart .mk.kind-selects { background: #000; border: 1.5px solid #fff; }
.chart .home-mark { transition: opacity .25s; }
.chart .stage.hov .mk:not(.on) { opacity: .15; }
.chart .stage.hov .lines line:not(.on), .chart .stage.hov .lines path.cn:not(.on) { opacity: .12; }
/* Services and Industry views. Each has an outline, dotted and as grey as the gridlines behind it
   (an octagon for Industry, a loose curve for Services), a small node at each point that is grey until a
   hover lights it, and dotted ties from a project to its points that only appear on hover. */
.chart .lines .shape { fill: none; stroke: var(--grid); stroke-width: 1; stroke-dasharray: 2 3; opacity: 0; transition: opacity .5s; }
.chart .lines .end { fill: #fff; opacity: 0; transition: opacity .3s; }
.chart .lines line.mx { opacity: 0; stroke-dasharray: 2 3; stroke-width: 1.5; }
.chart .stage.hov .lines line.mx:not(.on) { opacity: 0; }  /* other projects' ties stay fully hidden, in every view */
.chart .stage[data-view="service"] .lines .shape.v-service,
.chart .stage[data-view="industry"] .lines .shape.v-industry { opacity: 1; }
.chart .stage[data-view="service"] .lines .end.v-service,
.chart .stage[data-view="industry"] .lines .end.v-industry { opacity: .3; }
.chart .stage[data-view="service"] .lines .end.v-service.on,
.chart .stage[data-view="industry"] .lines .end.v-industry.on,
.chart .stage[data-view="service"].hov .lines line.mx.v-service.on,
.chart .stage[data-view="industry"].hov .lines line.mx.v-industry.on { opacity: 1; }
/* the point names can be hovered, and pulled about */
.chart .lb.cat { color: #fff; font: inherit; pointer-events: none; cursor: grab; touch-action: none; }
.chart .stage[data-view="service"] .lb.cat.v-service,
.chart .stage[data-view="industry"] .lb.cat.v-industry { pointer-events: auto; }
.chart .lb.cat.held { cursor: grabbing; }
.chart .lb.cat:focus-visible { outline-color: #fff; }
/* each view has its own kind of line; the other kind stays hidden even while something is hovered */
.chart .stage:not([data-view="geo"]) .lines .cn { opacity: 0; }
/* the whole map steps aside while Etc. is open */
.chart .stage { transition: opacity .4s; }
html.etc .chart .stage { opacity: 0; pointer-events: none; }

/* ============ ETC.: four columns of information, and the links, at the foot of the first screen ============ */

.etc-foot {
  position: fixed;           /* pinned to the window: Contact and Instagram are always at the very bottom */
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding-bottom: var(--m);
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity .3s, visibility 0s .3s;
}
html.etc .etc-foot { opacity: 1; visibility: visible; transition: opacity .6s .3s; }
.etc-foot > * { pointer-events: auto; }

.info {
  --clearance: 4;            /* empty lines between the foot of the longest column and Contact / Instagram */
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  align-items: start;        /* the four headings share one line */
  margin-bottom: calc(var(--text) * var(--leading) * var(--clearance));
}
.info > div { padding: 0 var(--m); }
.info h2 { margin-bottom: calc(var(--text) * var(--leading)); }
.info p + p { margin-top: calc(var(--text) * var(--leading)); }
.info ul { list-style: none; margin: 0; padding: 0; }

.links { display: flex; gap: 1.4em; padding: 0 var(--m); }

/* Etc. is a single screen at every size: nothing scrolls while it is open */
html.etc, html.etc body { overflow: hidden; height: 100%; }
html.etc .gridlines { height: 100%; -webkit-mask-image: none; mask-image: none; }  /* no tail running on below the screen */

/* small screens: two columns, with less clearance so everything fits on the one screen */
@media (max-width: 899px) {
  .info { --clearance: 2; grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: calc(var(--text) * var(--leading) * 2); }
}

/* ============ CASE STUDY ============
   An opening image, three blocks of introduction, then rows of images with short chapters of text between them.
   Everything is centred. Images sit one grid square in from the page edges. */

.case {
  --inset: var(--cell, 48px);  /* margin either side of the images: one grid square */
  --between: var(--m);         /* space between images, across and down */
  --breath: calc(var(--cell, 48px) * 2);  /* space around the introduction and around a chapter that has an image beside it */
  --break: calc(var(--cell, 48px) * 1.4);  /* a "line break": the space around a plain chapter or a grey line, and between images that should not touch */
  position: relative;
  z-index: 2;
  padding-top: var(--inset);
}

/* a row holds one, two or three images; side by side they share a height and keep their own proportions */
.case .row { display: flex; gap: var(--between); margin: 0 var(--inset) var(--between); }
.case figure {
  position: relative;
  margin: 0;
  min-width: 0;
  flex: calc(var(--w) / var(--h)) 1 0%;
  aspect-ratio: var(--w) / var(--h);
  overflow: hidden;
  clip-path: inset(0 round var(--radius));
}
.case figure img, .case figure video { display: block; width: 100%; height: 100%; object-fit: cover; }

/* break: this row stands apart from the one above it instead of sitting tight against it */
.case .row.break { margin-top: var(--break); }

/* medium: a single image at a narrower width, centred, for when it needs more room around it or has less resolution */
.case .row.medium { width: calc(var(--cell, 48px) * 16); margin-left: auto; margin-right: auto; }

/* a thin grey line across the standard width, marking off a part of the project */
.case .line { border: 0; height: 1px; background: var(--ink); opacity: .2; margin: var(--break) var(--inset); }

/* full bleed: a row that runs to the very edges of the window, square-cornered. The opening image is one. */
.case .row.bleed { margin-left: 0; margin-right: 0; }
.case .row.bleed figure { clip-path: none; }
.case .row.bleed:first-child { margin-top: calc(var(--inset) * -1); }  /* and it starts at the very top of the page */
/* "page": the image is cropped to exactly fill the window */
.case .row.page figure { aspect-ratio: auto; height: 100vh; height: 100svh; }

/* introduction: set one grid square inside the images' width, on five even columns.
   The description takes the first two; Services, Credits and more Credits take one each. */
.case-intro {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  column-gap: calc(var(--m) * 2);
  row-gap: calc(var(--text) * var(--leading) * 2);
  margin: 0 calc(var(--inset) + var(--cell, 48px));
  padding: var(--breath) 0;
}
.case-intro > :first-child { grid-column: span 2; padding-right: calc(var(--cell, 48px) * 2); }  /* two grid squares of air before Services */
.case-intro h2:empty::before { content: "\00a0"; }  /* a column that continues the one before keeps its place */
.case-intro h1, .case-intro h2, .chapter h2 { margin-bottom: calc(var(--text) * var(--leading)); }
.case p + p { margin-top: calc(var(--text) * var(--leading)); }
.case ul { list-style: none; margin: 0; padding: 0; }

/* a chapter: text set left-aligned, in a narrow block at the centre of the page (eight grid squares, about a quarter) */
.chapter {
  width: calc(var(--cell, 48px) * 8);
  margin: var(--break) auto;
  padding: 0 var(--m);
}

/* a chapter with an image to its right: the pair is centred on the page as one, the image centred on the text's height */
.chapter-row {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: calc(var(--cell, 48px) * 2);
  margin: var(--breath) var(--inset);
}
.chapter-row .chapter { margin: 0; flex: none; }
.case .chapter-row .aside { flex: none; width: calc(var(--cell, 48px) * 8.4); }

/* slideshow: images stacked in one frame, each dissolving into the next on a timer (site.js). Click to step by hand.
   The incoming image fades in over the outgoing one, so the picture never dims in between. */
.slideshow > * { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; }
.slideshow > .was { opacity: 1; z-index: 1; }
.slideshow > .on { opacity: 1; z-index: 2; transition: opacity var(--fade); }
.slideshow.cut > .on { transition: none; }  /* "cut": a hard jump between images, like a GIF */
.media .slideshow { position: absolute; inset: 0; cursor: inherit; }  /* a slideshow inside a gallery tile */
.slideshow { cursor: pointer; }

/* slider: images side by side in one frame, sliding sideways to the next on a timer, round and round (site.js) */
.slider .track { display: flex; height: 100%; will-change: transform; }
.slider .track > * { flex: 0 0 100%; min-width: 0; }

/* a link inside a chapter's text is underlined, so it can be told from the text around it */
.chapter a { text-decoration: underline; text-underline-offset: 3px; }

@media (max-width: 899px) {
  .case { --inset: var(--m); }
  .case-intro { grid-template-columns: repeat(2, minmax(0, 1fr)); margin: 0 var(--inset); }
  .case-intro > :first-child { padding-right: 0; }
  .chapter { width: auto; margin-left: 0; margin-right: 0; }
  .case .row.medium { width: auto; margin-left: var(--inset); margin-right: var(--inset); }
  .chapter { margin-top: var(--break); margin-bottom: var(--break); }
  .chapter-row { flex-direction: column; align-items: stretch; gap: calc(var(--text) * var(--leading) * 2); margin: var(--breath) 0; }
  .case .chapter-row .aside { width: auto; margin: 0 var(--inset); }
}
@media (max-width: 599px) {
  .case .row { flex-direction: column; }
  .case figure { flex: none; }
}
/* two columns of introduction: a column that continues the credits (empty heading) runs on beneath them,
   so every credited name falls in the same column */
@media (max-width: 899px) {
  .case-intro > :has(> h2:empty) { grid-column: 2; margin-top: calc(var(--text) * var(--leading) * -1); }
  .case-intro > :has(> h2:empty) > h2 { display: none; }
}

/* ============ DAY / NIGHT ============ */

/* bottom-right corner, locked in place: the day/night dot, then the clock. Same blending trick as the header. */
.corner {
  position: fixed;
  right: var(--m);
  bottom: var(--m);
  z-index: 10;
  display: flex;
  align-items: center;
  gap: .5em;
  color: #fff;
  mix-blend-mode: difference;
}
/* about the size of a lowercase "o", centred on the height of the numerals */
.theme {
  position: relative;
  width: .5em;
  height: .5em;
  transform: translateY(-.045em);
  background: #fff;
  border-radius: 50%;
}
.theme::after { content: ""; position: absolute; inset: -10px; }  /* larger target for fingers */
.theme:focus-visible { outline-color: #fff; }

/* ============ PHONE ============
   Things locked to the screen's top and bottom edges are drawn a little in from them, clear of the curved corners.
   The clock no longer travels: it sits at the foot of the home page's first screen (and on Etc.), and is left off the other pages. */

@media (max-width: 599px) {
  :root {
    --nudge: calc(var(--text) * var(--leading));  /* how far in: one line */
    --peek: 140px;             /* the map's hover image, smaller to suit the screen */
  }
  .head { padding-top: calc(var(--m) + var(--nudge)); }
  .chart .views { bottom: calc(var(--m) + var(--nudge)); right: calc(var(--m) + 8.5em); }  /* stops short of the clock */
  .chart .views > * { flex: none; }
  /* the map's hover: the title alone, without "Case Study" or "Selects" (a project's own tag, like "Coming Soon", stays) */
  .peek-name .tag:not(.own) { display: none; }
  /* the reading stays on one line and fades away where it runs out of room, rather than wrapping */
  .chart .views .coords {
    flex: 1;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 3em), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 3em), transparent);
  }
  .etc-foot { padding-bottom: calc(var(--m) + var(--nudge)); }
  .corner {
    position: absolute;
    bottom: auto;
    top: calc(100vh - var(--m) - var(--nudge) - var(--text) * var(--leading));
    top: calc(100svh - var(--m) - var(--nudge) - var(--text) * var(--leading));
  }
  body:not(.home) .corner { display: none; }
}

/* ============ FOOTER: end of every page ============
   The name stays in the far left corner. The links sit in equal columns, each an eighth of the
   page wide, centred as a group: Home, Top of Page, Previous, Next on a case study make up half the page.
   The text rests on the bottom line; the height above it is room for illustrations later. */

.footer {
  --footer-height: 172px;    /* twice what it was */
  position: relative;
  z-index: 2;
  display: flex;
  justify-content: center;
  align-items: flex-end;
  min-height: var(--footer-height);
  padding-bottom: var(--m);
}
.footer > a { flex: 0 0 12.5%; text-align: center; }
.footer .copyright { position: absolute; left: var(--m); bottom: var(--m); }
@media (max-width: 899px) {
  /* the name takes its own line above the links */
  .footer { flex-wrap: wrap; align-content: flex-end; padding-bottom: calc(var(--m) + var(--text) * var(--leading) * 2); }  /* clear of the locked clock */
  .footer > a { flex-basis: 25%; }
  .footer .copyright { position: static; flex: 0 0 100%; padding: 0 var(--m); margin-bottom: calc(var(--text) * var(--leading)); }
}
/* phone: the links stack one to a line on the right (Home, Top of Page, Previous, Next, as written),
   the last of them on the same line as the name at the left */
@media (max-width: 599px) {
  .footer {
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: flex-end;
    justify-content: flex-end;
    padding: 0 var(--m) calc(var(--m) + var(--nudge));
  }
  .footer > a { flex: none; text-align: right; }
  .footer .copyright { position: absolute; left: var(--m); bottom: calc(var(--m) + var(--nudge)); padding: 0; margin: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .media, .media img, .slides { transition: none; }
}
