/* Alternative "mono" theme. Shared by every page: the header, the tile grid,
   the density slider and the lightbox. Case-study-specific overrides live in
   case.css, which loads after each case study's own inline styles. */

@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;1,400&family=Inter:wght@300;400;500;600&display=swap');

:root {
  /* Same pairing as the live site: Inter for text, Cormorant for display. */
  --mono: "Inter", -apple-system, sans-serif;
  --serif: "Cormorant Garamond", Georgia, serif;
  --ink: #111;
  --muted: #8a8a8a;
  --tile: #d4d4d4;
  --tile-dark: #141414;
  --gutter: 10px;
  --radius: 12px;
}

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

html { background: #fff; }

body.mono {
  font-family: var(--mono);
  font-size: 14px;
  line-height: 1.7;
  color: var(--ink);
  background: #fff;
  padding: 0 var(--gutter) 80px;
  -webkit-font-smoothing: antialiased;
}

.mono a { color: inherit; text-decoration: none; }

/* ── Header: name | bio | links, in loose columns like a colophon ── */
.mh {
  display: grid;
  grid-template-columns: 150px minmax(0, 360px) auto;
  column-gap: 30px;
  padding: 34px 0 0;
  font-family: var(--mono);
  font-size: 14px;
  line-height: 1.7;
  color: var(--ink);
}
.mh p + p { margin-top: 1em; }
.mh-bio .mh-more { color: var(--muted); }
.mh-links { display: flex; flex-direction: column; align-items: flex-start; }
.mh-links a::before { content: "["; }
.mh-links a::after { content: "]"; }
.mh-links a:hover { color: var(--muted); }
.mh-links a.active { color: var(--muted); }
.mh-links .mh-gap { height: 1em; }

@media (max-width: 720px) {
  .mh { grid-template-columns: 1fr; row-gap: 1.2em; padding-top: 24px; }
}

/* ── Section bar: label on the left, density control on the right ── */
.bar {
  display: flex; align-items: center; justify-content: space-between;
  margin: 70px 0 16px;
  color: var(--muted);
}
.bar:first-of-type { margin-top: 70px; }
.bar + .grid + .bar { margin-top: 56px; }

.density { display: flex; align-items: center; gap: 12px; }
.density svg { width: 20px; height: 20px; fill: #b5b5b5; cursor: pointer; }
.density svg:hover { fill: var(--ink); }
.density input[type=range] {
  -webkit-appearance: none; appearance: none;
  width: 110px; height: 1px; background: #cfcfcf; outline: none; cursor: pointer;
}
.density input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none; width: 10px; height: 10px; border-radius: 50%; background: #666;
}
.density input[type=range]::-moz-range-thumb {
  width: 10px; height: 10px; border: 0; border-radius: 50%; background: #666;
}
@media (max-width: 720px) { .density { display: none; } }

/* ── Tile grid ── */
.grid {
  --cols: 2;
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  gap: var(--gutter);
}
@media (max-width: 720px) { .grid { --cols: 1 !important; } }

.tile { display: block; cursor: pointer; }
.tile-media {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius);
  background: var(--tile);
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
.tile-media img, .tile-media video {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform 0.6s cubic-bezier(.2,.7,.2,1);
}
.tile.inset .tile-media { padding: 6% 14%; }
.tile.inset .tile-media img, .tile.inset .tile-media video { object-fit: contain; border-radius: 4px; }
.tile:hover .tile-media img, .tile:hover .tile-media video { transform: scale(1.02); }

.tile-cap {
  display: flex; justify-content: space-between; gap: 16px;
  padding: 8px 2px 14px;
  font-size: 12px; color: var(--muted);
  opacity: 0; transition: opacity 0.2s;
}
.tile:hover .tile-cap, .tile:focus-visible .tile-cap { opacity: 1; }
.tile:focus-visible { outline: none; }
.tile:focus-visible .tile-media { outline: 1px solid var(--ink); outline-offset: 3px; }
@media (hover: none) { .tile-cap { opacity: 1; } }

/* Text tile for work that sits behind the login: no gated imagery on public
   pages, so the tile carries type instead. */
.tile.text .tile-media {
  background: var(--tile-dark); color: #eee;
  align-items: flex-start; justify-content: space-between; flex-direction: column;
  padding: 26px 28px;
}
.tile.text .tt-num { color: #777; }
.tile.text .tt-title { font-family: var(--serif); font-size: 28px; font-weight: 500; line-height: 1.15; max-width: 22ch; color: #fff; }
.tile.text .tt-tag { color: #9a9a9a; max-width: 44ch; margin-top: 10px; }
.tile.text .tt-lock { color: #777; }
.tile.text:hover .tt-title { color: #cfcfcf; }
.grid[style*="--cols: 3"] .tile.text .tt-title,
.grid[style*="--cols: 4"] .tile.text .tt-title { font-size: 22px; }
.grid[style*="--cols: 4"] .tile.text .tt-tag { display: none; }

/* ── Lightbox ── */
#lb {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(255,255,255,0.97);
  display: none; grid-template-columns: minmax(0, 1fr) 320px; gap: 40px;
  padding: 40px;
  font-family: var(--mono); font-size: 13px; color: var(--ink);
}
#lb.open { display: grid; }
#lb-media { display: flex; align-items: center; justify-content: center; min-height: 0; }
#lb-media img, #lb-media video { max-width: 100%; max-height: calc(100vh - 80px); border-radius: var(--radius); }
#lb-text { align-self: end; }
#lb-title { margin-bottom: 0.6em; font-family: var(--serif); font-size: 22px; font-weight: 500; line-height: 1.2; }
#lb-desc { color: #555; }
#lb-close { position: fixed; top: 24px; right: 30px; z-index: 201; display: none;
  background: none; border: 0; font: inherit; font-family: var(--mono); font-size: 13px; cursor: pointer; color: var(--ink); }
#lb.open + #lb-close { display: block; }
#lb-close::before { content: "["; } #lb-close::after { content: "]"; }
@media (max-width: 720px) {
  #lb { grid-template-columns: 1fr; padding: 60px 16px 24px; gap: 16px; }
  #lb-text { align-self: start; }
}

.foot { margin-top: 80px; color: var(--muted); font-size: 12px; }

/* Work index tiles: caption always visible, it's the only label. */
.tile.work .tile-cap { opacity: 1; color: var(--ink); }
.tile.work .tile-cap span:last-child { color: var(--muted); }

/* Archive pieces sit on a pale grey ground, like a print laid on a table:
   generous margin all round, the object uncropped, square corners on the art. */
.tile[data-src] .tile-media {
  background: #eaeaea;
  padding: 7% 12%;
}
.tile[data-src] .tile-media img,
.tile[data-src] .tile-media video {
  width: auto; height: auto;
  max-width: 100%; max-height: 100%;
  object-fit: contain;
  border-radius: 0;
}
.grid[style*="--cols: 3"] .tile[data-src] .tile-media,
.grid[style*="--cols: 4"] .tile[data-src] .tile-media { padding: 8% 10%; }
#lb { background: #eaeaea; }
#lb-media img, #lb-media video { border-radius: 0; }

/* Processing.js sketches are screen pieces, not objects: let them fill the
   whole frame instead of sitting on the grey ground. */
.tile.fill .tile-media { padding: 0 !important; background: #fff; }
.tile.fill .tile-media img,
.tile.fill .tile-media video {
  width: 100%; height: 100%; max-width: none; max-height: none;
  object-fit: cover;
}
/* A hair of overscan hides the last pixels of baked-in white at the edges. */
.tile.fill .tile-media video { transform: scale(1.04); }
.tile.fill:hover .tile-media video { transform: scale(1.06); }

/* ── Archive masonry ──
   Tiles keep their own proportions (--ar, set per piece) and are packed into
   columns by mono.js, shortest column first, so the grid staggers like a
   contact sheet. Without JS it falls back to CSS columns. */
.grid.masonry { display: block; columns: var(--cols); column-gap: var(--gutter); }
.grid.masonry > .tile { break-inside: avoid; margin-bottom: var(--gutter); }
.grid.masonry.packed { display: flex; gap: var(--gutter); columns: auto; align-items: flex-start; }
.grid.masonry .mcol { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: var(--gutter); }
.grid.masonry .mcol > .tile { margin-bottom: 0; }
.grid.masonry .tile { position: relative; }
.grid.masonry .tile-media { aspect-ratio: var(--ar, 16 / 10); }

/* Captions float over the tile instead of taking a row, so tiles butt
   together with only the gutter between them. */
.grid.masonry .tile-cap {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 10px 14px; color: var(--ink);
  background: linear-gradient(to top, rgba(255,255,255,0.85), rgba(255,255,255,0));
  border-radius: 0 0 var(--radius) var(--radius);
}
@media (hover: none) { .grid.masonry .tile-cap { opacity: 0; } }

/* Archive tiles take each piece's own proportions (--ar is its native
   width / height), so the frame IS the piece: no grey ground, no crop. */
.grid.masonry .tile[data-src] .tile-media { padding: 0 !important; background: none; }
.grid.masonry .tile[data-src] .tile-media img,
.grid.masonry .tile[data-src] .tile-media video {
  width: 100%; height: 100%; max-width: none; max-height: none;
  object-fit: cover; border-radius: 0; transform: none;
}
.grid.masonry .tile:hover .tile-media img,
.grid.masonry .tile:hover .tile-media video { transform: scale(1.02); }

/* Work tiles in the merged grid carry their own type; no overlay caption. */
.grid.masonry .tile.text .tile-cap { display: none; }

/* Display type: the name and titles use the live site's serif. */
.mh-name { font-family: var(--serif); font-size: 22px; font-weight: 600; line-height: 1.1; }

/* Case study tiles size their type to the tile, not the viewport, so they
   hold up at any column count. */
.tile.text .tile-media { container-type: inline-size; }
@container (max-width: 420px) {
  .tile.text .tt-title { font-size: 22px; }
  .tile.text .tt-tag { display: none; }
}
@container (max-width: 280px) {
  .tile.text .tt-title { font-size: 18px; }
}


/* Lightbox with several images (work projects): stack and scroll. */
#lb-media.stack { flex-direction: column; justify-content: flex-start; gap: 16px; overflow-y: auto; max-height: calc(100vh - 80px); }
#lb-media.stack img { max-height: none; width: 100%; height: auto; }
#lb-desc a { text-decoration: underline; text-decoration-color: #bbb; text-underline-offset: 2px; }
#lb-desc a:hover { text-decoration-color: var(--ink); }

/* Expanded view: media on the left, title and write-up in a column on the right. */
#lb-text { align-self: center; max-width: 320px; }

/* ── Cursor glow (cursor.js) ──
   Same lavender and falloff as the live site, fixed to the window so it
   follows the pointer down the whole page, behind every section. */
.mh-glow {
  position: fixed; inset: 0; z-index: 0;
  pointer-events: none;
  background: radial-gradient(ellipse 17.5vw 140px at var(--gx, 50%) var(--gy, 40%), #C7BAED 0%, transparent 70%);
  opacity: 0; transition: opacity 0.6s ease;
}
.mh-glow.on { opacity: 1; }
body.mono { position: relative; }
.mh, .bar, .grid, .content { position: relative; z-index: 1; }
.cs-toc { z-index: 1; }

/* Header stacks in one left-aligned column: name, bio, then links. */
.mh { grid-template-columns: minmax(0, 560px); row-gap: 1.2em; justify-items: start; }
.mh-name { margin-bottom: -0.2em; }
.mh-bio .mh-more { color: var(--muted); }
.mh-links { flex-direction: row; flex-wrap: wrap; gap: 0 18px; }

/* LinkedIn and Instagram as icons; brackets stay on the text link only. */
.mh-links { align-items: center; }
.mh-links a.mh-icon::before, .mh-links a.mh-icon::after { content: none; }
.mh-icon { display: inline-flex; color: var(--ink); }
.mh-icon svg { width: 16px; height: 16px; fill: currentColor; display: block; }
.mh-icon:hover { color: var(--muted); }
/* No brackets on any header link now, including the email. */
.mh-links a::before, .mh-links a::after { content: none; }

/* Column count by width (no-JS fallback; mono.js packs to the same counts). */
.grid { --cols: 3 !important; }
@media (max-width: 1024px) { .grid { --cols: 2 !important; } }
@media (max-width: 600px)  { .grid { --cols: 1 !important; } }

/* Expanded view sits on frosted glass, so the page shows faintly behind it. */
#lb {
  background: rgba(241, 241, 239, 0.72);
  -webkit-backdrop-filter: blur(14px) saturate(1.1);
          backdrop-filter: blur(14px) saturate(1.1);
}
@media (min-width: 1025px) { .grid[data-cols="4"] { --cols: 4 !important; } }

/* Page margins: more room on the left, right and top. */
:root { --page-x: 48px; --page-top: 64px; }
@media (max-width: 1024px) { :root { --page-x: 32px; --page-top: 48px; } }
@media (max-width: 600px)  { :root { --page-x: 18px; --page-top: 32px; } }
body.mono { padding-left: var(--page-x) !important; padding-right: var(--page-x) !important; }
.mh { padding-top: var(--page-top) !important; }
#lb-desc p + p { margin-top: 0.9em; }
/* Expanded view keeps the tiles' rounded corners on every image and video. */
#lb-media img, #lb-media video { border-radius: var(--radius) !important; }
/* The "ideal day" paragraph reads in the same black as the bio. */
.mh-bio .mh-more { color: var(--ink); }

/* Phones: the expanded view always fills the screen from the very top (dvh
   tracks Safari's collapsing toolbar, where 100vh leaves a gap), stacks media
   above text, and scrolls when the two together are taller than the screen,
   instead of centring and clipping the top. */
@media (max-width: 720px) {
  #lb {
    top: 0; left: 0; right: 0; bottom: auto;
    height: 100vh; height: 100dvh;
    display: none; overflow-y: auto; -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    grid-template-columns: 1fr; align-content: start;
    padding: calc(56px + env(safe-area-inset-top)) 16px calc(32px + env(safe-area-inset-bottom));
  }
  #lb.open { display: grid; }
  #lb-media { display: block; }
  #lb-media img, #lb-media video { width: 100%; height: auto; max-height: 70vh; max-height: 70dvh; object-fit: contain; }
  #lb-text { align-self: start; max-width: none; }
  #lb-close { top: calc(16px + env(safe-area-inset-top)); right: 16px; }
}
@media (max-width: 720px) {
  #lb.open { display: block; }
  #lb-media { min-height: auto; }
  #lb-text { margin-top: 20px; }
}
