/* Shared styles for / (the desk) and /more/ — luxury stationery still life.
   A seamless studio surface, soft light from the upper left, and objects built
   like product renders: gloss black resin, polished gold, heavy white paper,
   glass. Palette: black, gold, white, grays. The materials are gradients in
   .paper-defs (index.html / more/index.html), colored from the tokens below. */

/* ---------- Desk layout: nudge the objects here ----------
   --x / --y   the object's center, as a share of the desk (the viewport)
   --rot       its angle
   --scale     its size (1 = as designed; the planes are largest by design)
   Each label follows its object, offset by --label-dx / --label-dy (scene
   units from the object's center) and hung from --label-anchor. */

.object-find, .label-find { --x: 40%; --y: 59%; --rot: -6deg; --scale: 1; }
.object-sign, .label-sign { --x: 65%; --y: 44%; --rot: 6deg; --scale: 1; }
.object-send, .label-send { --x: 85%; --y: 67%; --rot: -8deg; --scale: 0.85; }
.hint { --x: 4.6%; --y: 44%; }

/* Every placard sits centered just below its object */
.label-find { --label-dx: 0; --label-dy: 13.4; --label-anchor: -50% 0; --label-align: center; }
.label-sign { --label-dx: -2; --label-dy: 11.6; --label-anchor: -50% 0; --label-align: center; }
.label-send { --label-dx: -1; --label-dy: 11; --label-anchor: -50% 0; --label-align: center; }

:root {
  /* ---- The look: editorial — a white sweep with a deep falloff, Playfair Display ---- */

  /* The studio surface: a seamless sweep, brightest under the light */
  /* warm key light from the upper left, cool fill falling into the shadows */
  --surface-hi: #fffdf8;
  --surface: #eef0f1;
  --surface-lo: #bfc7cf;
  --light-x: 36%;
  --light-y: 24%;

  /* Materials */
  --paper-hi: #ffffff;
  --paper: #f5f4f1;
  --paper-lo: #d6dae0;
  --paper-edge: #b6bcc5;
  --fold-hi: #eceef0;
  --fold: #bcc3cb;
  --resin-hi: #6f7a78;
  --resin-mid: #24302d;
  --resin: #111614;
  --resin-lo: #020403;
  --gold-hi: #fbe8b4;
  --gold: #c99a46;
  --gold-lo: #6b4a18;
  --gold-ink: #b2873a;
  --print: #23272d;

  /* Text */
  --ink: #111418;
  --ink-2: #4a5059;
  --ink-3: #8a919a;
  --hairline: rgb(0 0 0 / 0.14);
  --hairline-strong: rgb(0 0 0 / 0.24);
  --accent: var(--gold);

  /* Type */
  --font-display: "Playfair Display", "Didot", "Bodoni 72", Georgia, serif;
  --font-body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --name-size: clamp(3.25rem, 6.2vw, 6.25rem);
  --name-weight: 500;
  --name-style: normal;
  --name-tracking: -0.02em;
  --name-opsz: 96;
  --title-weight: 500;
  --title-style: normal;
  --title-tracking: -0.015em;
  --title-size: 2.5rem;

  /* Shadows: the light is up and to the left, so they fall down and right */
  --shadow-contact: 1px 2px 1.5px rgb(0 0 0 / 0.45);
  --shadow-cast: 14px 22px 22px rgb(0 0 0 / 0.45);
  --shadow-cast-lifted: 18px 28px 24px rgb(0 0 0 / 0.38);
  --sheet-shadow:
    0 1px 0 rgb(0 0 0 / 0.1),
    0 2px 3px rgb(0 0 0 / 0.35),
    10px 16px 26px rgb(0 0 0 / 0.3),
    24px 40px 80px -10px rgb(0 0 0 / 0.5);

  /* Older names the rules below still use */
  --color-bg: var(--surface);
  --color-text: var(--ink);
  --color-link: var(--ink);
  --color-focus: var(--gold);
  --desk-highlight: rgb(250 226 64 / 0.5);
  --badge-revoked: #9a3a30;

  /* Type scale */
  --font-family: var(--font-body);
  --font-size-base: 1.0625rem;
  --font-size-small: 0.875rem;
  --font-size-label: 0.6875rem;
  --font-weight-normal: 400;
  --font-weight-medium: 500;
  --font-weight-bold: 600;
  --line-height: 1.65;
  --line-height-tight: 1.2;
  --letter-spacing-label: 0.24em;

  /* Layout */
  --column-width: 38rem;
  --modal-width: 42rem;
  --gutter: 1.25rem;
  --list-indent: 1.5rem;
  --tap-size: 2.75rem;
  --desk-lift: -6px;
  --desk-lift-time: 320ms;
  --desk-lift-ease: cubic-bezier(0.2, 0.7, 0.2, 1);
  --desk-text-top: clamp(1.5rem, 6vh, 4rem);
  --desk-text-left: clamp(1.25rem, 4.6vw, 4.5rem);
  --desk-text-width: 34rem;
  --desk-text-stroke: 3.2;
  --desk-title-stroke: 5.5;
  --desk-mark-stroke: 2.4;

  /* Screenshot frame */
  --shot-aspect: 16 / 10;
  --shot-radius: 3px;
  --shot-bar-height: 1.75rem;
  --shot-dot-size: 0.4375rem;

  /* Page transition clock */
  --clock-size: min(70vmin, 30rem);
  --clock-mark-stroke: 2.5;
  --clock-quarter-stroke: 4.5;

  /* Outbound sheet stack */
  --sheet-tuck: 0.75rem;

  /* Spacing */
  --space-1: 0.25rem;
  --space-2: 0.75rem;
  --space-3: 1.5rem;
  --space-4: 2.5rem;
  --space-5: 4.5rem;
  --space-page: 4rem;
}

@media (max-width: 30rem) {
  :root {
    --font-size-base: 1rem;
    --title-size: 2rem;
    --space-5: 3.5rem;
    --space-page: 2.5rem;
  }
}

/* ---------- Base ---------- */

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  background: #2a1610;
  overflow-x: clip;
}

html:has(dialog[open]) {
  overflow: hidden;
}

body {
  margin: 0;
  padding: var(--space-page) 0;
  background: transparent;
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-normal);
  line-height: var(--line-height);
  overflow-wrap: break-word;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* The studio sweep, fixed behind every page */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  /* A worn rosewood table with a marbled green resin river poured through it
     (baked into one image), lit from the upper left, falling off at the edges */
  background:
    radial-gradient(70% 60% at var(--light-x) var(--light-y), rgb(255 226 190 / 0.16), transparent 70%),
    radial-gradient(130% 110% at var(--light-x) var(--light-y), transparent 35%, rgb(8 4 3 / 0.55) 100%),
    url("/images/desk-table.webp") center / cover no-repeat,
    #2a1610;
}

/* A faint, still photographic grain over the page, so no surface is a flat fill */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 30;
  background: url("/images/grain.webp") 0 0 / 256px;
  opacity: 0.035;
  pointer-events: none;
}

::selection {
  background: rgb(206 168 86 / 0.35);
  color: var(--ink);
}

h1, h2, h3, p, ul, dl, dd {
  margin: 0;
}

h1 {
  font-family: var(--font-display);
  font-size: var(--name-size);
  font-style: var(--name-style);
  font-weight: var(--name-weight);
  font-variation-settings: "opsz" var(--name-opsz);
  letter-spacing: var(--name-tracking);
  line-height: 0.95;
}

h2 {
  margin-bottom: var(--space-3);
  font-size: var(--font-size-label);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
}

h3,
dt {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
}

p + p {
  margin-top: var(--space-2);
}

a {
  color: var(--color-link);
  text-decoration-line: underline;
  text-decoration-color: var(--hairline-strong);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.25em;
  transition: color 200ms ease, text-decoration-color 200ms ease;
}

a:hover {
  text-decoration-color: currentColor;
}

a:focus-visible,
button:focus-visible {
  outline: 1px solid var(--color-focus);
  outline-offset: 4px;
  border-radius: 1px;
}

/* ---------- Layout ---------- */

.wrap {
  max-width: calc(var(--column-width) + 2 * var(--gutter));
  margin: 0 auto;
  padding: 0 var(--gutter);
}

/* ---------- Nav and header ---------- */

.site-nav {
  margin-bottom: var(--space-5);
}

.site-nav ul {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--space-1) var(--space-4);
  padding: 0;
  font-size: 0.75rem;
  font-weight: var(--font-weight-medium);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  list-style: none;
}

.site-nav a {
  display: inline-block;
  padding: 0.3rem 0;
  color: var(--ink-2);
  text-decoration: none;
  background: linear-gradient(var(--gold), var(--gold)) left bottom / 0 1px no-repeat;
  transition: color 200ms ease, background-size 300ms var(--desk-lift-ease);
}

.site-nav a:hover {
  color: var(--ink);
  background-size: 100% 1px;
}

/* /more/: About me, Experience and Contact centered; Back to desk at the left */
.site-header .site-nav ul {
  position: relative;
  justify-content: center;
}

.site-nav .nav-back {
  position: absolute;
  left: 0;
}

@media (max-width: 40rem) {
  .site-nav .nav-back {
    position: static;
    flex-basis: 100%;
    text-align: center;
  }
}

.site-header .tagline {
  margin-top: var(--space-3);
  max-width: 24em;
  color: var(--ink-2);
  font-size: 1.125rem;
  line-height: 1.5;
}

.site-header p + p {
  margin-top: var(--space-2);
  color: var(--ink-3);
  font-size: var(--font-size-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
}

/* ---------- /more/: a single sheet of heavy white paper on the sweep ---------- */

.wrap.site-header,
main.wrap {
  position: relative;
}

main.wrap {
  margin-top: var(--space-5);
  margin-bottom: var(--space-4);
  padding: clamp(2rem, 6vw, 4.5rem) clamp(1.5rem, 6vw, 4.5rem);
  max-width: calc(var(--column-width) + 2 * clamp(1.5rem, 6vw, 4.5rem));
  border-radius: 2px;
  background:
    linear-gradient(160deg, rgb(255 255 255 / 1) 0%, rgb(255 255 255 / 0) 55%),
    linear-gradient(170deg, var(--paper-hi) 0%, var(--paper) 70%, #ececec 100%);
  /* heavy stock: a crisp edge you can see, then soft studio shadows */
  box-shadow:
    1px 1px 0 #e3e3e3,
    2px 2px 0 #d2d2d2,
    var(--sheet-shadow);
  color: var(--ink);
}

@media (max-width: 40rem) {
  main.wrap {
    margin-inline: var(--gutter);
  }
}

main.wrap > section {
  margin: 0;
}

main.wrap > section + section {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--hairline);
}

/* Section labels: small capitals behind a short gold rule */
main h2 {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  color: var(--ink-2);
}

main h2::before {
  content: "";
  width: 1.5rem;
  height: 1px;
  background: var(--gold);
}

main section > p {
  color: var(--ink);
}

.entry + .entry {
  margin-top: var(--space-4);
}

.entry h3 {
  font-family: var(--font-display);
  font-size: 1.75rem;
  font-style: var(--title-style);
  font-weight: var(--title-weight);
  font-variation-settings: "opsz" 48;
  letter-spacing: var(--title-tracking);
  line-height: 1.1;
}

.entry h3 + .meta {
  margin-top: 0.375rem;
}

.meta {
  color: var(--ink-2);
  font-size: var(--font-size-small);
}

/* Tool tags: hairline-outlined, black and gray only */
.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  margin-top: var(--space-2);
  padding: 0;
  list-style: none;
}

.tags li {
  padding: 0.22rem 0.6rem;
  border: 1px solid var(--hairline-strong);
  border-radius: 1px;
  color: var(--ink-2);
  font-size: 0.6875rem;
  font-weight: var(--font-weight-medium);
  letter-spacing: 0.1em;
  line-height: var(--line-height-tight);
  text-transform: uppercase;
}

/* Tags rise in softly, staggered, as their section scrolls into view (more.js) */
.tags-rise main .tags li {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 500ms ease, transform 600ms cubic-bezier(0.2, 0.7, 0.2, 1);
  transition-delay: calc(var(--i, 0) * 60ms);
}

.tags-rise main .tags.is-in-view li {
  opacity: 1;
  transform: none;
}

.points {
  margin-top: var(--space-3);
  padding-left: var(--list-indent);
  list-style: none;
}

.points li {
  position: relative;
}

.points li::before {
  content: "";
  position: absolute;
  top: 0.82em;
  left: calc(-1 * var(--list-indent));
  width: 0.75rem;
  height: 1px;
  background: var(--ink-3);
}

.points li + li {
  margin-top: var(--space-2);
}

.skills > div {
  display: grid;
  grid-template-columns: 10rem 1fr;
  gap: var(--space-1) var(--space-3);
}

.skills > div + div {
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px solid var(--hairline);
}

.skills dt,
.skills dd {
  font-size: var(--font-size-small);
  line-height: var(--line-height);
}

.skills dd {
  color: var(--ink-2);
}

@media (max-width: 30rem) {
  .skills > div {
    grid-template-columns: 1fr;
  }
}

.links {
  margin-top: var(--space-3);
  padding: 0;
  list-style: none;
}

.links li + li {
  margin-top: var(--space-1);
}

.links a {
  font-family: var(--font-display);
  font-size: clamp(1.375rem, 3.4vw, 1.875rem);
  font-style: var(--title-style);
  font-weight: var(--title-weight);
  letter-spacing: var(--title-tracking);
  line-height: 1.35;
  text-decoration-color: var(--gold);
}

/* ---------- The art: product-render materials ---------- */

.art {
  stroke-linecap: round;
  stroke-linejoin: round;
}

.art .shape,
.art .detail,
.art .line {
  vector-effect: non-scaling-stroke;
}

.art .shape {
  fill: var(--paper);
  stroke: none;
}

.art .line {
  fill: none;
  stroke: var(--ink);
  stroke-width: 1;
}

/* Printed text on the paper */
.art .text-line {
  fill: none;
  stroke: var(--print);
  stroke-width: var(--desk-text-stroke);
  opacity: 0.5;
}

.art .text-title {
  stroke: var(--ink);
  stroke-width: var(--desk-title-stroke);
  opacity: 0.88;
}

.art use {
  fill: none;
  stroke: var(--print);
  stroke-width: var(--desk-text-stroke);
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.7;
}

.art .mark,
.art .tick,
.art .sig {
  fill: none;
  stroke: var(--ink);
  stroke-width: var(--desk-mark-stroke);
  opacity: 0;
}

.art .mark[d^="M-4"] {
  stroke: var(--ink-3);
}

/* Gold ink from the fountain pen */
.art .sig,
.art .tick {
  stroke: var(--gold-ink);
  stroke-width: 2;
}

.art .highlight {
  opacity: 0;
}

/* Gradient stops, colored from the tokens */
.s-paper-hi { stop-color: var(--paper-hi); }
.s-paper { stop-color: var(--paper); }
.s-paper-lo { stop-color: var(--paper-lo); }
.s-edge { stop-color: var(--paper-edge); }
.s-fold-hi { stop-color: var(--fold-hi); }
.s-fold { stop-color: var(--fold); }
.s-resin-hi { stop-color: var(--resin-hi); }
.s-resin-mid { stop-color: var(--resin-mid); }
.s-resin { stop-color: var(--resin); }
.s-resin-lo { stop-color: var(--resin-lo); }
.s-gold-hi { stop-color: var(--gold-hi); }
.s-gold { stop-color: var(--gold); }
.s-gold-lo { stop-color: var(--gold-lo); }

/* Heavy paper: a visible edge under every sheet */
.art .sheet-edge {
  fill: url(#g-sheet-edge);
}

/* FIND: a stack of heavy cotton paper and a gold-rimmed glass */
.object-find .gs-sheet > .shape {
  fill: url(#p-sheet-top);
}

/* Printed text: letter-sized breaks in each line, so it reads as type */
.object-find .text-line,
.object-find use {
  stroke-linecap: butt;
  stroke-width: 2.3;
  stroke-dasharray: 2.2 0.55 3.1 0.55 1.5 0.55 2.6 0.55 1.9 0.55 3.4 0.55 1.2 0.55;
}

/* Lamp light across every sheet (and the badge): bright near the light, aged at the far edge */
.art .sheet-light {
  fill: url(#g-light);
  pointer-events: none;
}

.object-find .gs-chaff .text-line {
  opacity: 0.32;
}

/* The sheets beneath are slightly different stocks: a warm ivory, a cool grey-blue */
.object-find svg > g:nth-of-type(1) .gs-sheet > .shape { fill: url(#p-sheet-kraft); }
.object-find svg > g:nth-of-type(2) .gs-sheet > .shape { fill: url(#p-sheet-ledger); }
.object-find svg > g:nth-of-type(3) .gs-sheet > .shape { fill: url(#p-sheet-grid); }

/* A steel paper clip on the kept sheet */
.paper-clip {
  filter: drop-shadow(1.5px 2.5px 1.2px rgb(0 0 0 / 0.4));
}

.clip-wire {
  fill: none;
  stroke: url(#g-steel);
  stroke-width: 2.4;
  stroke-linecap: round;
}

.art .lens-paper {
  fill: var(--paper-hi);
}

.gs-lens-body {
  filter: drop-shadow(4px 8px 5px rgb(0 0 0 / 0.26));
}

.gs-lens-body > rect.shape {
  fill: url(#p-wood);
}

.gs-lens-body > .handle-collar {
  fill: url(#g-gold-bar);
}

.gs-lens-body > .handle-hl {
  fill: rgb(255 255 255 / 0.32);
}

.gs-lens-body > line.line {
  stroke: var(--gold-hi);
  stroke-width: 1.4;
  vector-effect: none;
  opacity: 0.8;
}

.gs-lens-body > path.shape {
  fill: url(#g-gold);
}

.gs-rim-bevel {
  fill: none;
  stroke: rgb(255 244 212 / 0.75);
  stroke-width: 0.9;
}

.gs-glass {
  fill: url(#g-glass);
}

.gs-lens-body > path.line {
  stroke: rgb(255 255 255 / 0.9);
  stroke-width: 2.2;
}

/* SIGN: an ID badge on a lanyard */
.object-sign .ob-sheet {
  fill: transparent;
}

.badge-edge {
  fill: #b9b4aa;
}

.badge-band {
  fill: url(#g-band);
}

.badge-guilloche {
  fill: none;
  stroke: rgb(170 220 200 / 0.22);
  stroke-width: 0.5;
}

.badge-slot {
  fill: #1b120d;
  stroke: rgb(0 0 0 / 0.5);
  stroke-width: 0.6;
}

.badge-seal {
  fill: url(#g-gold);
}

.badge-seal-ring {
  fill: none;
  stroke: rgb(80 54 16 / 0.6);
  stroke-width: 0.6;
}

.badge-band-text {
  fill: none;
  stroke: rgb(236 244 240 / 0.85);
  stroke-width: 2.4;
  stroke-linecap: round;
}

.badge-photo {
  fill: url(#g-photo);
  stroke: rgb(0 0 0 / 0.18);
  stroke-width: 0.6;
}

.badge-photo-head,
.badge-photo-body {
  fill: #4b5a66;
}

.badge-photo-gloss {
  fill: url(#g-photo-gloss);
}

.badge-row {
  stroke-width: 3 !important;
}

.badge-holo {
  fill: url(#g-holo);
  opacity: 0.85;
}

.badge-holo-sheen {
  fill: url(#g-holo-sheen);
  opacity: 0.8;
}

.badge-holo-lines {
  fill: none;
  stroke: rgb(255 255 255 / 0.55);
  stroke-width: 0.5;
}

.badge-chip {
  fill: url(#g-gold);
  stroke: rgb(90 60 20 / 0.6);
  stroke-width: 0.5;
}

.badge-chip-lines {
  fill: none;
  stroke: rgb(90 60 20 / 0.55);
  stroke-width: 0.6;
}

.badge-bar {
  fill: #1d1b19;
}

.badge-serial {
  fill: none;
  stroke: var(--ink-3);
  stroke-width: 2;
  stroke-dasharray: 2 1.6;
  stroke-linecap: butt;
}

/* Lanyard: woven red fabric, a fine weave, a stitched edge. (Its shadow comes from
   the badge layer's own; a second filter here would redraw while the pen moves.) */
.badge-lanyard .strap {
  fill: none;
  stroke: url(#g-strap);
  stroke-width: 12;
}

.badge-lanyard .strap-weave {
  fill: none;
  stroke: rgb(255 210 200 / 0.12);
  stroke-width: 11;
  stroke-dasharray: 0.8 1.6;
}

.badge-lanyard .strap-stitch {
  fill: none;
  stroke: rgb(240 200 180 / 0.4);
  stroke-width: 0.6;
  stroke-dasharray: 3 2.4;
}

.badge-clip-plate,
.badge-clip-bar {
  fill: url(#g-steel);
}

.badge-clip-rivet {
  fill: #3a3e42;
  stroke: rgb(255 255 255 / 0.5);
  stroke-width: 0.6;
}

.ob-box {
  fill: none;
  stroke: var(--ink-2);
  stroke-width: 1;
}

.ob-sign-line {
  fill: none;
  stroke: rgb(0 0 0 / 0.38);
  stroke-width: 1;
}

.ob-sign-x {
  fill: none;
  stroke: var(--ink-3);
  stroke-width: 1.2;
}

/* The fountain pen (also the clock's minute hand) and its cap */
#ob-pen,
#ob-cap {
  filter: drop-shadow(3px 6px 3.5px rgb(0 0 0 / 0.26));
}

.pen-nib,
.cap-clip-ball {
  fill: url(#g-gold);
}

.pen-nib-slit {
  fill: none;
  stroke: rgb(0 0 0 / 0.55);
  stroke-width: 0.6;
}

.pen-nib-hole {
  fill: #1a1a1a;
}

.pen-grip {
  fill: url(#g-resin);
}

/* Barrel, end and cap: marbled green resin, with cylinder shading laid over it */
.pen-barrel,
.pen-end,
.cap-body {
  fill: url(#p-marble);
}

.pen-shade,
.handle-shade {
  fill: url(#g-cyl-shade);
}

.pen-band,
.cap-ring,
.cap-clip {
  fill: url(#g-gold-bar);
}

.pen-hl {
  fill: rgb(255 255 255 / 0.5);
}

.pen-hl-low {
  fill: rgb(255 255 255 / 0.12);
}

/* ---------- The desk ---------- */

.desk-page {
  padding: 0;
}

.desk {
  position: relative;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
}

.desk-text {
  position: absolute;
  top: var(--desk-text-top);
  left: var(--desk-text-left);
  z-index: 5;
  max-width: var(--desk-text-width);
}

/* The nav sits centered across the top of the page */
.desk-text {
  padding-top: calc(1.6rem + clamp(1.75rem, 7vh, 3.75rem));
}

.desk-text .site-nav {
  position: fixed;
  top: var(--desk-text-top);
  right: 0;
  left: 0;
  z-index: 6;
  margin: 0;
}

.desk-text .site-nav ul {
  justify-content: center;
}

.desk-text .tagline {
  margin-top: var(--space-3);
  max-width: 22em;
  color: var(--ink-2);
  font-size: 1.0625rem;
  line-height: 1.5;
}

.desk-text p + p {
  margin-top: var(--space-2);
  color: var(--ink-3);
  font-size: var(--font-size-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
}

.hint {
  position: absolute;
  top: var(--y);
  left: var(--x);
  z-index: 5;
  padding-left: 2.25rem;
  color: var(--ink-2);
  font-size: 0.875rem;
  letter-spacing: 0.01em;
  line-height: var(--line-height-tight);
  white-space: nowrap;
}

.hint::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  width: 1.5rem;
  height: 1px;
  background: var(--gold);
}

/* Objects are positioned in scene units, so the whole layout scales together */
.scene {
  position: absolute;
  inset: 0;
  container-type: size;
  --u: min(1cqw, 1.6cqh);
}

.desk-anim .scene,
.desk-anim .hint {
  visibility: hidden;
}

.desk-object {
  position: absolute;
  top: var(--y);
  left: var(--x);
  display: block;
  transform: translate(-50%, -50%) translateY(var(--lift, 0px));
  transition: transform var(--desk-lift-time) var(--desk-lift-ease);
}

.object-find { width: calc(22 * var(--scale) * var(--u)); }
.object-sign { width: calc(17 * var(--scale) * var(--u)); }
.object-send { width: calc(30 * var(--scale) * var(--u)); }

.desk-object {
  color: inherit;
  text-decoration: none;
  outline: none;
}

.desk-object:focus-visible {
  outline: 1px dashed var(--color-focus);
  outline-offset: 10px;
}

/* The shadow sits on an unrotated wrapper so it always falls away from the light */
.desk-art {
  display: block;
  /* No will-change here: left in the page's own layer, each shadow is drawn once
     and reused; promoted to a layer, it would be re-applied on every frame of
     any animation anywhere on the desk */
  filter: drop-shadow(var(--shadow-contact)) drop-shadow(var(--shadow-cast));
  transition: filter var(--desk-lift-time) var(--desk-lift-ease);
  animation: cast-shadow 1.3s steps(1, end);
}

/* While the desk sets itself in, the objects move without shadows (cheap); the
   shadows appear under them the moment they land */
@keyframes cast-shadow {
  from { filter: none; }
}

.desk-rot {
  display: block;
  transform: rotate(var(--rot));
}

.desk-rot > svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.sign-rot {
  position: relative;
  aspect-ratio: 260 / 300;
}

/* SIGN is two stacked drawings: the form (with its own still shadow) and the
   pen and cap above it (each with a small shadow of its own). The wrapper
   casts no shadow, so a moving pen never makes a large shadow redraw. */
.sign-rot > .sign-scene {
  position: absolute;
  inset: 0;
  height: 100%;
}

.object-sign .desk-art,
.object-sign:is(:hover, :focus-visible) .desk-art {
  filter: none;
}

.sign-paper {
  filter: drop-shadow(var(--shadow-contact)) drop-shadow(var(--shadow-cast));
  transition: filter var(--desk-lift-time) var(--desk-lift-ease);
}

.object-sign:is(:hover, :focus-visible) .sign-paper {
  filter: drop-shadow(var(--shadow-contact)) drop-shadow(var(--shadow-cast-lifted));
}

.sign-tools {
  will-change: transform;
}

/* Hover lift: composed with the rotation, never replacing it */
.desk-object:is(:hover, :focus-visible):not(.object-send) {
  --lift: var(--desk-lift);
}

.desk-object:is(:hover, :focus-visible):not(.object-send) .desk-art {
  filter: drop-shadow(var(--shadow-contact)) drop-shadow(var(--shadow-cast-lifted));
}

/* Placards: plain engraved-style text. When the object is hovered or focused
   (desk.js adds .is-shown), a hairline box draws itself around the text: the
   top and bottom rules grow out from the middle, then the sides close it. */
.desk-label {
  position: absolute;
  top: calc(var(--y) + var(--label-dy) * var(--scale) * var(--u));
  left: calc(var(--x) + var(--label-dx) * var(--scale) * var(--u));
  z-index: 4;
  translate: var(--label-anchor);
  padding: 0.5rem 0.85rem 0.55rem;
  color: var(--ink-2);
  font-size: 0.8125rem;
  line-height: var(--line-height-tight);
  text-align: var(--label-align);
  white-space: nowrap;
  pointer-events: none;
  transition: opacity 250ms ease;
}

.desk-label::before,
.desk-label::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.desk-label::before {
  border-top: 1px solid var(--ink);
  border-bottom: 1px solid var(--ink);
  transform: scaleX(0);
  transition: transform 260ms cubic-bezier(0.6, 0, 0.4, 1) 120ms;
}

.desk-label::after {
  border-left: 1px solid var(--ink);
  border-right: 1px solid var(--ink);
  transform: scaleY(0);
  transition: transform 180ms cubic-bezier(0.6, 0, 0.4, 1);
}

.desk-label.is-shown::before {
  transform: scaleX(1);
  transition: transform 340ms cubic-bezier(0.2, 0.7, 0.2, 1);
}

.desk-label.is-shown::after {
  transform: scaleY(1);
  transition: transform 240ms cubic-bezier(0.2, 0.7, 0.2, 1) 260ms;
}

.desk-label > span {
  display: block;
  transition: color 260ms ease;
}

.desk-verb {
  margin-bottom: 0.45rem;
  color: var(--gold);
  font-size: 0.5625rem;
  font-weight: var(--font-weight-bold);
  letter-spacing: 0.32em;
}

.desk-name {
  padding-top: 0.45rem;
  background: linear-gradient(var(--gold), var(--gold)) top center / 1.25rem 1px no-repeat;
  letter-spacing: 0.01em;
}

.desk-label.is-shown .desk-name {
  color: var(--ink);
}

@media (prefers-reduced-motion: reduce) {
  .desk-label::before,
  .desk-label::after,
  .desk-label.is-shown::before,
  .desk-label.is-shown::after {
    transition: none;
  }
}

/* The planes' label riding beside a plane: desk.js moves it with a transform */
.desk-label.is-following {
  top: 0;
  left: 0;
  translate: -50% -100%;
  text-align: center;
}

body:has(.clock-layer.is-active) :is(.desk-label, .plane-trails) {
  opacity: 0;
}

/* While everything flies into the clock, the objects travel without their cast
   shadows (redrawing them every frame is what makes a transition stutter) */
body:has(.clock-layer.is-active) :is(.desk-art, .plane svg, #ob-pen, #ob-cap, .gs-lens-body, .sign-paper) {
  filter: none;
}

/* Planes: their own full-viewport layer, above the desk and below the text */
.plane-layer {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
}

.plane {
  position: absolute;
  top: 0;
  left: 0;
  display: grid;
  place-items: center;
  min-width: var(--tap-size);
  min-height: var(--tap-size);
  cursor: pointer;
  pointer-events: auto;
  will-change: transform;
}

.plane svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
  filter: drop-shadow(1px 2px 1px rgb(0 0 0 / 0.18)) drop-shadow(8px 12px 10px rgb(0 0 0 / 0.14));
  transition: filter var(--desk-lift-time) var(--desk-lift-ease);
  animation: cast-shadow 1.3s steps(1, end);
}

.plane-layer.is-flying .plane svg {
  filter: drop-shadow(26px 40px 16px rgb(0 0 0 / 0.1));
}

/* Crisp white paper with a shaded far wing and sharp creases */
.plane .shape {
  fill: url(#p-paper-sm);
}

/* A bright highlight along the centre crease */
.plane .crease {
  fill: none;
  stroke: rgb(255 255 255 / 0.75);
  stroke-width: 0.8;
}

.plane .fold {
  fill: rgb(40 30 22 / 0.2);
}

.plane .line {
  stroke: rgb(0 0 0 / 0.2);
  stroke-width: 0.7;
}

/* The others: kraft, pale blue, and one black with a gold edge.
   (nth-of-type: the trails layer is the first child of the plane layer) */
.plane:nth-of-type(2) .shape {
  fill: url(#p-kraft);
}

.plane:nth-of-type(2) .line {
  stroke: rgb(70 44 18 / 0.35);
}

.plane:nth-of-type(2) .crease {
  stroke: rgb(255 236 210 / 0.5);
}

.plane:nth-of-type(3) .shape {
  fill: url(#p-blue);
}

.plane:nth-of-type(1) .shape {
  fill: url(#p-black);
  stroke: var(--gold);
  stroke-width: 1;
}

.plane:nth-of-type(1) .fold {
  fill: rgb(255 255 255 / 0.07);
}

.plane:nth-of-type(1) .line {
  stroke: rgb(206 168 86 / 0.55);
}

.plane:nth-of-type(1) .crease {
  stroke: rgb(255 255 255 / 0.18);
}

@media (prefers-reduced-motion: reduce) {
  .desk-object,
  .desk-art,
  .plane svg {
    transition: none;
  }

  .desk-object:is(:hover, :focus-visible):not(.object-send) {
    --lift: 0px;
  }
}

/* Dotted gold trails behind the flying planes (desk.js adds the dots) */
.plane-trails {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 450ms ease;
}

.plane-layer.is-flying .plane-trails {
  opacity: 1;
}

.trail-dot {
  position: absolute;
  top: -1.5px;
  left: -1.5px;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--gold);
  will-change: transform;
}

/* Stacked project list, shown when the desk is too small to tap */

.project-list {
  display: none;
}

.project-list ul {
  padding: 0;
  list-style: none;
}

.project-list li + li {
  border-top: 1px solid var(--hairline);
}

.project-list a {
  display: block;
  min-height: var(--tap-size);
  padding: var(--space-2) 0;
  color: var(--ink);
  text-decoration: none;
}

.project-list .project-name {
  display: block;
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-style: var(--title-style);
  font-weight: var(--title-weight);
  letter-spacing: var(--title-tracking);
  line-height: 1.25;
}

.project-list .meta {
  display: block;
  margin-top: 0.125rem;
  color: var(--ink-3);
}

/* Phones: text and hint flow normally, the scene becomes a square */
@media (max-width: 40rem) {
  .desk-text {
    position: static;
    max-width: none;
    padding: var(--space-page) var(--gutter) 0;
  }

  .desk-text .site-nav {
    position: static;
    margin-bottom: var(--space-4);
  }

  .desk {
    height: auto;
    padding-bottom: var(--space-page);
  }

  .hint {
    position: relative;
    top: auto;
    left: auto;
    display: block;
    margin: var(--space-3) var(--gutter) 0;
  }

  .scene {
    position: relative;
    inset: auto;
    aspect-ratio: 1;
    margin-top: var(--space-2);
    --u: 1.35cqw;
  }

  .object-find { --x: 34%; --y: 56%; }
  .object-sign { --x: 70%; --y: 36%; }
  .object-send { --x: 78%; --y: 78%; }

  .scene .desk-label {
    visibility: hidden;
  }

  .project-list {
    display: block;
    padding: var(--space-3) var(--gutter) 0;
  }
}

/* ---------- Page transition: an antique clock ----------
   A weathered pale face in a dark iron bezel (one baked image, so it costs
   nothing to scale), engraved Roman numerals that ride with the hour marks,
   and blued-steel style hands. Leaving the desk, the pen and the glass's
   handle fly in as the hands and dissolve into the clock's own (.is-gathering). */
.clock-layer {
  position: fixed;
  inset: 0;
  z-index: 10;
  display: grid;
  place-items: center;
  visibility: hidden;
  pointer-events: none;
}

.clock-layer.is-active,
.clock-in .clock-layer {
  visibility: visible;
  pointer-events: auto;
}

.clock {
  width: var(--clock-size);
  height: var(--clock-size);
  overflow: visible;
}

.art .clock-face {
  fill: url(#p-dial);
  stroke: none;
}

.clock-letters {
  position: absolute;
  inset: 0;
}

.clock-letter {
  position: absolute;
  white-space: pre;
  will-change: transform;
}

.art .clock-tick {
  stroke: #161816;
  stroke-width: var(--clock-mark-stroke);
  stroke-linecap: butt;
  vector-effect: non-scaling-stroke;
}

.art .clock-tick.is-quarter {
  stroke-width: var(--clock-quarter-stroke);
}

.clock-numeral {
  fill: #141614;
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.04em;
  text-anchor: middle;
  dominant-baseline: central;
}

/* The clock's own hands: dark steel with a faint edge catching the light */
.hand-blade {
  fill: #121413;
  stroke: rgb(255 255 255 / 0.18);
  stroke-width: 0.5;
  vector-effect: non-scaling-stroke;
}

.hand-boss {
  fill: #0c0d0c;
  stroke: rgb(255 255 255 / 0.25);
  stroke-width: 0.6;
  vector-effect: non-scaling-stroke;
}

.hand-tool {
  opacity: 0;
}

/* Leaving the desk: the pen and the handle arrive as the hands, then become them */
.clock-layer.is-gathering .hand-tool {
  animation: hand-tool-out 0.4s ease 0.55s both;
}

.clock-layer.is-gathering .hand-ornate {
  animation: hand-ornate-in 0.4s ease 0.55s both;
}

@keyframes hand-tool-out {
  from { opacity: 1; }
  to { opacity: 0; }
}

@keyframes hand-ornate-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* The pen and handle drawings, while they're still the pen and the handle */
.clock-hour .hand-tool > rect.shape {
  fill: url(#p-wood);
}

.clock-hour .hand-tool > .handle-collar {
  fill: url(#g-gold-bar);
}

.clock-hour .hand-tool > .handle-hl {
  fill: rgb(255 255 255 / 0.32);
}

.clock-hour .hand-tool > line.line {
  stroke: var(--gold-hi);
  stroke-width: 1.4;
  vector-effect: none;
}

.art .clock-pin {
  fill: #121413;
  stroke: rgb(255 255 255 / 0.3);
  stroke-width: 0.8;
}

.art .clock-pin-dot {
  fill: #7d827d;
}

.clock-in body > :not(.clock-layer) {
  visibility: hidden;
}

/* Arriving: nothing paints until the clock face and table are ready (see the
   head script), so the browser keeps the previous page's frame on screen */
.clock-wait body,
.clock-wait body .clock-layer {
  visibility: hidden !important;
}

/* /more/: when the clock dissolves, the sheet fades in with its text instead of
   popping in behind the clock */
main.wrap {
  transition: opacity 450ms ease 150ms;
}

.clock-in main.wrap {
  opacity: 0;
  transition: none;
}

.paper-defs {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

@keyframes page-fade-in {
  from {
    opacity: 0;
  }
}

.fade-in body {
  animation: page-fade-in 0.25s ease-out both;
}

/* ---------- Project modals: white paper under studio light ---------- */

.modal {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  overflow: hidden;
}

.modal::backdrop {
  background: transparent;
}

.modal-scrim {
  position: absolute;
  inset: 0;
  background: rgb(18 10 7 / 0.72);
}

.modal-stage {
  position: absolute;
  inset: 0;
  display: flex;
  padding: calc(var(--gutter) + 1.5rem) var(--gutter);
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.paper {
  border-radius: 2px;
  background: linear-gradient(160deg, var(--paper-hi) 0%, var(--paper-hi) 40%, var(--paper) 100%);
  box-shadow:
    1px 1px 0 #e6e6e6,
    var(--sheet-shadow);
}

.modal-card {
  width: min(var(--modal-width), 100%);
  margin: auto;
  padding: 0 clamp(1.25rem, 5vw, 3rem) clamp(1.75rem, 5vw, 3rem);
  border: 0;
}

.modal-bar {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  justify-content: flex-end;
  margin: 0 calc(-1 * clamp(1.25rem, 5vw, 3rem));
  padding: var(--space-2) var(--space-2) 0 0;
}

.modal-close {
  display: grid;
  place-items: center;
  width: var(--tap-size);
  height: var(--tap-size);
  padding: 0;
  border: 1px solid var(--hairline-strong);
  border-radius: 50%;
  background: rgb(255 255 255 / 0.9);
  color: var(--ink-2);
  font: inherit;
  font-size: 1.25rem;
  font-weight: 300;
  line-height: 1;
  cursor: pointer;
  transition: border-color 200ms ease, color 200ms ease;
}

.modal-close:hover {
  border-color: var(--gold);
  color: var(--ink);
}

.modal-title {
  margin-top: var(--space-4);
  margin-bottom: 0;
  color: var(--ink);
  font-family: var(--font-display);
  font-size: var(--title-size);
  font-style: var(--title-style);
  font-weight: var(--title-weight);
  font-variation-settings: "opsz" 72;
  letter-spacing: var(--title-tracking);
  line-height: 1.05;
  text-transform: none;
}

.modal-title + .meta {
  margin-top: var(--space-2);
}

.modal-card .tags,
.sheet-top .tags {
  margin-top: var(--space-3);
}

.modal-card .points {
  padding-top: var(--space-3);
  border-top: 1px solid var(--hairline);
}

.modal-chips {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.chip {
  position: absolute;
  border-radius: 1px;
  background: var(--desk-highlight);
  will-change: transform;
}

/* SIGN: the signed form, copied above the scrim at the same spot as on the desk */
.modal-badge {
  position: absolute;
  inset: 0;
  pointer-events: none;
  filter: drop-shadow(var(--shadow-contact)) drop-shadow(var(--shadow-cast));
}

.modal-badge .sign-rot {
  position: absolute;
}

/* SEND: the planes unfold into a stack of sheets */
.sheet-stack {
  width: min(var(--modal-width), 100%);
  margin: auto;
}

.sheet {
  border: 0;
}

.sheet-slot {
  position: relative;
}

.sheet-slot-top {
  z-index: 4;
}

.sheet-top {
  padding: 0 clamp(1.25rem, 5vw, 3rem) clamp(1.75rem, 5vw, 2.5rem);
}

.sheet-points {
  margin: 0;
  padding: 0;
  list-style: none;
}

.sheet-points .sheet-slot {
  margin-top: calc(-1 * var(--sheet-tuck));
}

.sheet-points .sheet {
  padding: calc(var(--sheet-tuck) + var(--space-3)) clamp(1.25rem, 5vw, 3rem) var(--space-3);
  color: var(--ink);
  line-height: 1.6;
}

.sheet-points .sheet-slot:nth-child(1) {
  z-index: 3;
  rotate: 0.6deg;
  translate: 8px 0;
}

.sheet-points .sheet-slot:nth-child(2) {
  z-index: 2;
  rotate: -0.6deg;
  translate: -7px 0;
}

.sheet-points .sheet-slot:nth-child(3) {
  z-index: 1;
  rotate: 0.4deg;
  translate: 4px 0;
}

/* Screenshot frame: a black lacquer window. Replace .shot-empty with <img src="/images/…"> */

.shot {
  overflow: hidden;
  border-radius: var(--shot-radius);
  background: linear-gradient(160deg, #1d1d20, #050506);
  box-shadow: 0 1px 1px rgb(0 0 0 / 0.2), 0 10px 22px -8px rgb(0 0 0 / 0.35);
}

.shot-bar {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  height: var(--shot-bar-height);
  padding: 0 var(--space-2);
  border-bottom: 1px solid rgb(255 255 255 / 0.06);
}

.shot-bar span {
  width: var(--shot-dot-size);
  height: var(--shot-dot-size);
  border-radius: 50%;
  background: rgb(255 255 255 / 0.18);
}

.shot-bar span:first-child {
  background: var(--gold);
}

.shot-view {
  display: grid;
  place-items: center;
  aspect-ratio: var(--shot-aspect);
}

.shot-view img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top;
}

.shot-empty {
  color: rgb(255 255 255 / 0.42);
  font-size: 0.6875rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
}


/* ---------- Text on the table: light, warm ink ---------- */
.desk-text,
.hint,
.desk-label,
.project-list,
.site-header {
  --ink: #f4ede3;
  --ink-2: #d9ccbb;
  --ink-3: #ad9d89;
  --hairline: rgb(244 237 227 / 0.18);
  --hairline-strong: rgb(244 237 227 / 0.35);
  color: var(--ink);
}

.desk-text h1,
.site-header h1 {
  color: var(--ink);
}

/* Projects without a screenshot skip the frame entirely */
.shot:has(.shot-empty) {
  display: none;
}

.shot:has(.shot-empty) + .modal-title {
  margin-top: var(--space-2);
}
