/* Sizes scale with viewport width: N px at a 1440 design = calc(N * var(--u)). */
html { font-size: 1vw; }
:root {
  --scale: 14.4;
  /* Clamped so meta text never drops below ~12px on small laptops or balloons on huge screens. */
  --u: clamp(0.85px, calc(1rem / var(--scale)), 1.6px);
  --ink: #000;
  --paper: #fff;
  --mute: #6b6b6b;
  --rule: calc(1 * var(--u));
  --gap: calc(16 * var(--u));
  --cols: 8;
  --ease-curtain: cubic-bezier(0.76, 0, 0.24, 1);
  --ease-rise: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-slide: cubic-bezier(0.45, 0, 0.55, 1);
}
@media (max-width: 991px) {
  :root { --scale: 3.93; --gap: calc(12 * var(--u)); --cols: 6; }
}
/* Tablets: the phone layout at a 768 design width, not the phone design magnified 2x. */
@media (min-width: 541px) and (max-width: 991px) { :root { --scale: 7.68; } }

* { box-sizing: border-box; margin: 0; padding: 0; }
body {
  background: var(--paper);
  color: var(--ink);
  font-family: "Inter Tight", system-ui, sans-serif;
  font-weight: 500;
  font-size: calc(14 * var(--u));
  line-height: 1.15;
  letter-spacing: -0.02em;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }
::selection { background: var(--ink); color: var(--paper); }

.grid {
  display: grid;
  grid-template-columns: repeat(var(--cols), 1fr);
  column-gap: var(--gap);
  padding: 0 var(--gap);
}
.h1 { font-size: calc(200 * var(--u)); line-height: 0.86; letter-spacing: -0.055em; font-weight: 500; }
.h2 { font-size: calc(56 * var(--u)); line-height: 0.92; letter-spacing: -0.045em; font-weight: 500; }
.meta { font-size: calc(14 * var(--u)); line-height: 1.15; }
.mute { color: var(--mute); }
.pill {
  display: inline-block;
  border: var(--rule) solid var(--ink);
  border-radius: 999px;
  padding: calc(10 * var(--u)) calc(20 * var(--u));
  transition: background .25s, color .25s;
}
.pill:hover { background: var(--ink); color: var(--paper); }

/* Header */
.nav { padding-top: var(--gap); align-items: start; }
.nav .links { grid-column: 4 / span 3; display: flex; gap: calc(24 * var(--u)); }
.nav .presence { grid-column: -2 / -1; text-align: right; }
.nav a:hover { color: var(--mute); }

/* Hero */
/* The hero fills exactly one screen below the nav: type sizes are capped by viewport height so wide, short windows don't overflow. */
:root { --nav-h: calc(48 * var(--u)); }
.hero { min-height: calc(100svh - var(--nav-h)); grid-template-rows: auto 1fr auto auto; row-gap: calc(32 * var(--u)); padding-top: calc(56 * var(--u)); padding-bottom: calc(32 * var(--u)); }
.hero .role-a { grid-column: 1 / span 2; grid-row: 1; }
.hero .role-b { grid-column: 7 / span 2; grid-row: 1; text-align: right; }
/* Avatar signs off the hero: bottom-right, ending the Nitesh → Dodeja → tagline diagonal, level with the Now line. */
.hero .hero-portrait { grid-column: 8; grid-row: 2 / span 3; align-self: end; }
.hero .name { grid-column: 1 / -1; grid-row: 2; align-self: end; font-size: min(calc(200 * var(--u)), 21vh); }
.hero .name span, .footer .h1 span { display: block; margin-left: -0.04em; }
.hero .name span + span { padding-left: calc(3 * (100% + var(--gap)) / 8); }
.hero .line { grid-column: 4 / span 4; grid-row: 3; margin-top: calc(16 * var(--u)); font-size: min(calc(56 * var(--u)), 6.2vh); }
.hero .now { grid-column: 1 / span 3; grid-row: 4; }
.hero .now time { font-variant-numeric: tabular-nums; }
.ink-defs { position: absolute; }
.ink-pending [data-ink] { filter: url(#ink); }

/* Section heads and rows */
.section { padding-top: calc(160 * var(--u)); }
.section-head { align-items: end; padding-bottom: calc(32 * var(--u)); }
.section-head .h2 { grid-column: 1 / span 4; }
.section-head .count { grid-column: -2 / -1; text-align: right; }
.list { list-style: none; padding: 0 var(--gap); }
.row a {
  display: grid;
  grid-template-columns: repeat(var(--cols), 1fr);
  column-gap: var(--gap);
  align-items: baseline;
  border-top: var(--rule) solid var(--ink);
  padding: calc(44 * var(--u)) 0;
  transition: color .3s;
}
.list .row:last-child a { border-bottom: var(--rule) solid var(--ink); }
.row .title { grid-column: 1 / span 5; font-size: calc(56 * var(--u)); letter-spacing: -0.045em; line-height: 1; transition: transform .4s var(--ease-rise); }
.row .role { grid-column: 6 / span 2; }
/* Work rows: what the project is, with the job title as a quiet second line. */
.row .role .sub { display: block; margin-top: calc(4 * var(--u)); }
.row .year { grid-column: 8; text-align: right; }
@media (hover: hover) {
  .list:hover .row a { color: var(--mute); }
  .list .row a:hover { color: var(--ink); }
  .list .row a:hover .title { transform: translateX(calc(12 * var(--u))); }
}

/* Secondary "Also shipped" list: same grid, smaller rows, no hover preview */
.also { padding-top: calc(72 * var(--u)); padding-bottom: calc(16 * var(--u)); }
.also h3 { grid-column: 1 / -1; font-weight: 500; }
.list-compact .row a { padding: calc(18 * var(--u)) 0; cursor: default; }
.list-compact .row .title { font-size: calc(24 * var(--u)); letter-spacing: -0.03em; }
.list-compact:hover .row a { color: inherit; }
.list-compact .row a:hover .title { transform: none; }
.list-compact:not(.list-links) .row a, .list-compact:not(.list-links) .row:last-child a { border-color: #e5e5e5; }

/* Company tag on non-Adobe Work rows: small, grey, beside the title */
.row .title .co { font-size: calc(20 * var(--u)); letter-spacing: -0.01em; color: var(--mute); margin-left: calc(16 * var(--u)); white-space: nowrap; }
@media (max-width: 991px) { .row .title .co { font-size: calc(14 * var(--u)); margin-left: calc(8 * var(--u)); } }

/* Cursor-following "View" bubble (desktop pointers only) */
.follow-bubble { position: fixed; left: 0; top: 0; pointer-events: none; z-index: 20; }
.follow-bubble .inner {
  width: calc(88 * var(--u)); height: calc(88 * var(--u)); border-radius: 50%;
  display: grid; place-items: center;
  background: var(--ink); color: var(--paper);
  transform: translate(-50%, -50%) scale(0);
  transition: transform .4s var(--ease-rise);
}
.follow-on .follow-bubble .inner { transform: translate(-50%, -50%) scale(1); }
@media (hover: none), (max-width: 540px) { .follow-bubble { display: none; } }

/* Footer */
.footer { padding-top: calc(200 * var(--u)); padding-bottom: var(--gap); row-gap: calc(64 * var(--u)); }
.footer .h1 { grid-column: 1 / -1; font-size: calc(140 * var(--u)); }
.footer .h1 span:nth-child(2) { padding-left: calc(2 * (100% + var(--gap)) / 8); }
.footer .h1 span:nth-child(3) { padding-left: calc(4 * (100% + var(--gap)) / 8); }
.footer .contact { grid-column: 1 / span 5; display: flex; flex-wrap: wrap; gap: calc(12 * var(--u)); }
.footer .chat-hint { grid-column: 6 / span 3; text-align: right; align-self: center; }
.footer .legal { grid-column: 1 / -1; display: flex; justify-content: space-between; border-top: var(--rule) solid var(--ink); padding-top: var(--gap); }

/* Intro loader: dark curtain with a curved bottom edge */
.loader {
  position: fixed; inset: 0; z-index: 100;
  background: var(--ink); color: var(--paper);
  display: grid; place-items: center;
  font-size: calc(48 * var(--u));
  /* Per-glyph fallback: Latin from Inter Tight, other scripts from the matching Noto family. */
  font-family: "Inter Tight", "Noto Sans Devanagari", "Noto Sans Bengali", "Noto Sans Tamil", "Noto Sans Telugu",
    "Noto Sans Kannada", "Noto Sans Malayalam", "Noto Sans Gujarati", "Noto Sans Gurmukhi", "Noto Sans JP", "Noto Sans KR", system-ui, sans-serif;
}
.loader-word { display: grid; line-height: 1.4; white-space: nowrap; }
.loader-word > span { grid-area: 1 / 1; justify-self: center; opacity: 0; }
.loader-curve { position: absolute; top: 100%; left: 0; width: 100%; height: 10vh; overflow: hidden; }
.loader-curve div {
  position: absolute; left: 50%; width: 150%; height: 750%;
  border-radius: 50%; background: var(--ink);
  transform: translate(-50%, -86.666%);
}
.no-loader .loader { display: none; }
.is-loading { cursor: wait; }
.is-loading .once-in { transform: translateY(50vh); }
@media (max-width: 540px) { .loader-curve { height: 5vh; } }

/* Live presence */
.presence-layer { position: absolute; left: 0; top: 0; width: 100%; overflow-x: clip; pointer-events: none; z-index: 30; }
@media (hover: none) { .presence-layer, .chat-hint { display: none; } }
.peer { position: absolute; left: 0; top: 0; transition: transform .12s linear; }
.peer-dot { width: calc(10 * var(--u)); height: calc(10 * var(--u)); border-radius: 50%; background: var(--ink); }
.peer-label, .peer-msg, .chat-input {
  position: absolute; left: calc(14 * var(--u)); top: calc(6 * var(--u));
  font-size: calc(12 * var(--u)); white-space: nowrap;
  background: var(--ink); color: var(--paper);
  border-radius: 999px; padding: calc(4 * var(--u)) calc(10 * var(--u));
}
.peer-msg { top: calc(32 * var(--u)); background: var(--paper); color: var(--ink); border: var(--rule) solid var(--ink); transition: opacity .6s; }
.peer-msg:empty { display: none; }
.peer-msg.fade { opacity: 0; }
.chat-input {
  position: fixed; z-index: 40; border: 0; outline: 0; font: inherit; font-size: calc(14 * var(--u));
  min-width: calc(200 * var(--u)); transform: translate(calc(14 * var(--u)), calc(6 * var(--u)));
  left: 0; top: 0;
}
.chat-input::placeholder { color: var(--mute); }
.presence-off [data-presence] { display: none; }

/* Article */
.article-head { padding-top: calc(160 * var(--u)); row-gap: calc(24 * var(--u)); }
.article-head .kicker { grid-column: 1 / span 2; }
.article-head .h1 { grid-column: 1 / -1; font-size: calc(120 * var(--u)); }
.article-head .h1 .co { font-size: 0.3em; letter-spacing: -0.02em; color: var(--mute); margin-left: 0.4em; white-space: nowrap; }
.prose { padding: calc(96 * var(--u)) var(--gap) 0; }
.prose > * { margin-left: calc(2 * (100% + var(--gap)) / 8); max-width: calc(4 * (100% + var(--gap)) / 8); }
.prose p, .prose li { font-size: calc(20 * var(--u)); line-height: 1.45; letter-spacing: -0.01em; margin-bottom: calc(24 * var(--u)); }
.prose h3 { font-size: calc(32 * var(--u)); letter-spacing: -0.03em; margin: calc(64 * var(--u)) auto calc(20 * var(--u)) calc(2 * (100% + var(--gap)) / 8); }
.prose code { font-family: ui-monospace, Menlo, monospace; font-size: .9em; }
.prose .wide { margin-left: 0; max-width: none; }

/* Demo */
.demo { border: var(--rule) solid var(--ink); margin: calc(48 * var(--u)) 0; }
.demo-bar { display: flex; flex-wrap: wrap; gap: calc(12 * var(--u)); align-items: center; justify-content: space-between; padding: var(--gap); border-bottom: var(--rule) solid var(--ink); }
.demo-bar .group { display: flex; gap: calc(8 * var(--u)); }
.demo .pill { font: inherit; background: none; cursor: pointer; padding: calc(6 * var(--u)) calc(14 * var(--u)); }
.demo .pill[aria-pressed="true"] { background: var(--ink); color: var(--paper); }
.demo-view { padding: var(--gap); min-height: calc(380 * var(--u)); font-size: calc(14 * var(--u)); }
.demo figcaption { padding: var(--gap); border-top: var(--rule) solid var(--ink); }
.trace-step { display: grid; grid-template-columns: calc(90 * var(--u)) 1fr auto; gap: var(--gap); padding: calc(10 * var(--u)) 0; border-bottom: var(--rule) solid #e5e5e5; animation: step-in .4s var(--ease-rise); }
.trace-step .kind { text-transform: lowercase; }
.trace-step code { font-family: ui-monospace, Menlo, monospace; }
.trace-step.err .detail { text-decoration: underline wavy; text-underline-offset: 3px; }
.bars { display: grid; gap: calc(8 * var(--u)); }
.bar-row { display: grid; grid-template-columns: calc(220 * var(--u)) 1fr calc(80 * var(--u)); gap: var(--gap); align-items: center; }
.bar-track { position: relative; height: calc(14 * var(--u)); }
.bar { position: absolute; top: 0; height: 100%; background: var(--ink); animation: step-in .4s var(--ease-rise); }
.bar.tool { background: repeating-linear-gradient(45deg, var(--ink) 0 2px, transparent 2px 6px); border: var(--rule) solid var(--ink); }
@keyframes step-in { from { opacity: 0; transform: translateY(6px); } }

@media (max-width: 991px) {
  .h1 { font-size: calc(72 * var(--u)); }
  .h2, .row .title { font-size: calc(32 * var(--u)); }
  .nav .links { grid-column: 3 / span 3; }
  :root { --nav-h: calc(72 * var(--u)); }
  /* Phones scroll naturally, so the hero hugs its content instead of stretching to the screen. */
  .hero { min-height: 0; grid-template-rows: auto auto auto auto; row-gap: calc(20 * var(--u)); padding-top: calc(32 * var(--u)); padding-bottom: calc(24 * var(--u)); }
  .hero .name { margin-top: calc(24 * var(--u)); }
  .nav > a:first-child { grid-column: 1 / span 3; white-space: nowrap; }
  .hero .role-a { grid-column: 1 / span 3; grid-row: 1; }
  .hero .role-b { grid-column: 4 / span 3; grid-row: 1; text-align: right; }
  /* Phones: type-only hero; the real photo is just below in About. */
  .hero .hero-portrait { display: none; }
  .hero .name { grid-row: 2; font-size: min(calc(72 * var(--u)), 11vh); }
  .hero .line { grid-column: 1 / -1; grid-row: 3; font-size: calc(32 * var(--u)); }
  .hero .now { grid-column: 1 / -1; grid-row: 4; }
  .row .title { grid-column: 1 / -1; }
  .row .role { grid-column: 1 / span 4; padding-top: calc(8 * var(--u)); }
  .row .year { grid-column: 5 / span 2; }
  .footer .h1 { font-size: calc(56 * var(--u)); }
  .footer .contact, .footer .chat-hint { grid-column: 1 / -1; text-align: left; }
  .prose > *, .prose h3 { margin-left: 0; max-width: none; }
  .prose p, .prose li { font-size: calc(16 * var(--u)); }
  .article-head { padding-top: calc(96 * var(--u)); }
  .article-head .h1 { font-size: min(calc(64 * var(--u)), 13vw); text-wrap: balance; }
  .section { padding-top: calc(96 * var(--u)); }
  .footer { padding-top: calc(120 * var(--u)); }
  .section-head .count { grid-column: 4 / -1; white-space: nowrap; }
  .nav .links a { padding-block: calc(14 * var(--u)); margin-block: calc(-14 * var(--u)); }
  .bar-row { grid-template-columns: 1fr; }
}

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

/* Patents: compact rows that link out */
/* .fold: a native <details> list that opens from one quiet line (pending patents, Also shipped). */
/* Continuation fold: sits right under a list, inset by the page gutter; the list's last rule is its top edge. */
.fold-ruled { margin: 0 var(--gap); }
.fold.fold-ruled > summary { padding-left: 0; padding-right: 0; }
.fold-ruled .list { padding: 0; }
.fold summary { list-style: none; cursor: pointer; align-items: baseline; padding: calc(28 * var(--u)) var(--gap); }
.fold summary::-webkit-details-marker { display: none; }
.fold summary .title { grid-column: 1 / span 5; font-size: calc(24 * var(--u)); letter-spacing: -0.03em; }
.fold summary .toggle { grid-column: -2 / -1; text-align: right; }
.fold summary:hover .title { text-decoration: underline; text-underline-offset: 0.15em; text-decoration-thickness: 1px; }
.fold[open] .show, .fold:not([open]) .hide { display: none; }
@media (max-width: 991px) { .fold summary .title { grid-column: 1 / span 4; } .fold summary .toggle { grid-column: 5 / -1; } }
.list-links .row a { cursor: pointer; }
.list-links .row a:hover .title { text-decoration: underline; text-underline-offset: 0.15em; text-decoration-thickness: 1px; }
/* Project pages: patents sit on the text column like the rest of the article; title on top, status and year below. */
.prose .list-links { padding: 0; }
@media (min-width: 992px) { .prose .list-links.wide { margin-left: calc(2 * (100% + var(--gap)) / 8); max-width: calc(4 * (100% + var(--gap)) / 8); } }
.prose .list-links .row a { grid-template-columns: 1fr auto; row-gap: calc(8 * var(--u)); }
.prose .list-links .row .title { grid-column: 1 / -1; }
.prose .list-links .row .role { grid-column: 1; padding-top: 0; }
.prose .list-links .row .year { grid-column: 2; }

/* Project pages */
.prose .lede { font-size: calc(32 * var(--u)); line-height: 1.15; letter-spacing: -0.03em; }
.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(calc(200 * var(--u)), 1fr)); gap: var(--gap); border-top: var(--rule) solid var(--ink); padding-top: var(--gap); margin: calc(48 * var(--u)) 0; }
.facts dd { font-size: calc(18 * var(--u)); margin-top: calc(6 * var(--u)); }
.media { aspect-ratio: 16 / 9; width: 100%; margin-bottom: calc(64 * var(--u)); }
.media.video iframe { width: 100%; height: 100%; border: 0; }
.facade { position: relative; display: block; cursor: pointer; }
.facade img { display: block; width: 100%; height: 100%; object-fit: cover; }
.facade .play { position: absolute; left: 50%; top: 50%; width: calc(64 * var(--u)); height: calc(64 * var(--u)); border-radius: 50%; display: grid; place-items: center; background: color-mix(in srgb, var(--ink) 45%, transparent); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); color: var(--paper); transform: translate(-50%, -50%); transition: transform .4s var(--ease-rise), background .3s; }
/* The path's box sits right of centre and its centroid slightly left: the usual optical-centring compromise. */
.facade .play svg { width: 50%; height: 50%; fill: currentColor; }
.facade:hover .play, .facade:focus-visible .play { transform: translate(-50%, -50%) scale(1.12); background: color-mix(in srgb, var(--ink) 70%, transparent); }
.facade:focus-visible { outline: var(--rule) solid var(--ink); outline-offset: calc(4 * var(--u)); }
.did { list-style: none; }
.did li { border-top: var(--rule) solid #e5e5e5; padding-top: calc(14 * var(--u)); }
.sources { list-style: none; }
.sources a { border-bottom: var(--rule) solid var(--ink); }
.sources a:hover { color: var(--mute); }
/* Multi-part project pages (e.g. GA and beta): each part opens with a kicker and an h2. */
.prose .part-kicker { margin-top: calc(120 * var(--u)); margin-bottom: calc(12 * var(--u)); }
.prose .part { margin-bottom: calc(8 * var(--u)); }
.next { padding-top: calc(160 * var(--u)); row-gap: calc(12 * var(--u)); }
.next > * { grid-column: 1 / -1; }
.next:hover .h2 { color: var(--mute); }

/* Mobile header: four nav links need the full right side; the presence count lives in the footer hint. */
@media (max-width: 991px) {
  .nav .links { grid-column: 4 / -1; justify-content: flex-end; gap: calc(14 * var(--u)); }
  .nav .presence { display: none; }
  .article-head .kicker { grid-column: 1 / -1; }
}

/* About: B&W portrait, colour on hover */
.about { align-items: end; row-gap: calc(32 * var(--u)); }
/* About photo (the hero shows the line-engraved avatar instead). */
.about .portrait { grid-column: 1 / span 2; }
.portrait img { display: block; width: 100%; height: auto; filter: grayscale(1) contrast(1.05); transition: filter .6s var(--ease-rise); }
.portrait:hover img { filter: none; }
.about-text { grid-column: 4 / span 4; display: grid; gap: calc(28 * var(--u)); }
.about-body { font-size: calc(20 * var(--u)); line-height: 1.4; letter-spacing: -0.01em; max-width: 36em; }
.about-facts { display: flex; gap: calc(48 * var(--u)); border-top: var(--rule) solid var(--ink); padding-top: var(--gap); }
.about-facts dd { font-size: calc(24 * var(--u)); margin-top: calc(4 * var(--u)); letter-spacing: -0.03em; }
@media (max-width: 991px) {
  .about .portrait { grid-column: 1 / span 4; }
  .about-text { grid-column: 1 / -1; }
  .about-body { font-size: calc(16 * var(--u)); }
  .about-facts { gap: calc(16 * var(--u)) calc(24 * var(--u)); flex-wrap: wrap; }
  .about-facts dd { font-size: calc(18 * var(--u)); white-space: nowrap; }
}

/* Project screenshots with caption */
.shot { margin: calc(48 * var(--u)) 0; }
/* Stills (and a video paired with a lead still) sit on the text column, cols 3–6. A lead still sits left of the lede. */
@media (min-width: 992px) {
  .prose .wide.shot, .prose .wide.narrow { margin-left: calc(2 * (100% + var(--gap)) / 8); max-width: calc(4 * (100% + var(--gap)) / 8); }
  .lede-row { display: grid; grid-template-columns: repeat(8, 1fr); column-gap: var(--gap); align-items: start; }
  /* Drop the still by the lede's cap offset (~0.205em of its 32u size) so the frame lines up with the top of the capitals. */
  .lede-row .shot { grid-column: 1 / span 2; grid-row: 1; margin: calc(0.205 * 32 * var(--u)) 0 0; }
  .lede-row .lede { grid-column: 3 / span 4; grid-row: 1; }
}
.shot img, .shot video { display: block; width: 100%; height: auto; }
.shot figcaption { padding-top: calc(10 * var(--u)); }
/* Same size and colour as the facts-row values (.facts dd). */
.shot-labels { display: grid; padding-bottom: calc(10 * var(--u)); font-size: calc(18 * var(--u)); line-height: 1.15; }
/* A figure attached to a "What I did" line sits under its text. */
.did .shot { margin: calc(24 * var(--u)) 0 calc(8 * var(--u)); }

/* Hero avatar: illustrated portrait; main.js drifts it toward the cursor. */
.avatar img { display: block; width: 100%; height: auto; }


/* Avatar button (Easter egg): smaller than the cell, pinned to the right margin. */
.hero .hero-portrait { position: relative; }
.avatar-btn { all: unset; display: block; width: calc(118 * var(--u)); margin-left: auto; cursor: pointer; transform-origin: 50% 55%; }
.avatar-btn:focus-visible { outline: var(--rule) solid var(--ink); outline-offset: calc(8 * var(--u)); }
.avatar-bubble { position: absolute; right: 0; bottom: calc(100% + 10 * var(--u)); white-space: nowrap; background: var(--ink); color: var(--paper); border-radius: 999px; padding: calc(5 * var(--u)) calc(12 * var(--u)); pointer-events: none; }
.avatar-rain { position: fixed; top: 0; z-index: 80; height: auto; pointer-events: none; }
