:root {
  --paper:  #F4F1EA;
  --ink:    #1A1815;
  --dim:    #8E8779;
  --dim-strong: #4A463E;   /* dim pulled toward ink, for small type on the field */
  --accent: #17150F;
  --display: 'EB Garamond', Georgia, serif;
  --body: Inter, system-ui, sans-serif;
  --edge: clamp(20px, 3.4vw, 52px);
}

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

html, body { height: 100%; }

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
  /* The page reads as a composed surface rather than a document, so drag-
     selecting it is only ever accidental. The composer's own fields opt back
     in below — this is presentational only and does not affect screen
     readers, find-in-page, or the accessibility tree. */
  -webkit-user-select: none;
  user-select: none;
  /* Suppresses the iOS long-press copy/lookup callout on the same content. */
  -webkit-touch-callout: none;
}

/* Anything the visitor types is theirs to select, copy and edit as normal. */
.sheet-form textarea,
.sheet-form input {
  -webkit-user-select: text;
  user-select: text;
  -webkit-touch-callout: default;
}

#field {
  position: fixed;
  inset: 0;
  z-index: 0;
  display: block;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 900ms ease;
}
body.is-ready #field { opacity: 1; }

/* Nav and headline multiply, so the dot field reads through the letterforms
   instead of punching a hole in it. */
nav {
  position: absolute;
  top: clamp(20px, 3.6vh, 34px);
  left: var(--edge);
  right: var(--edge);
  z-index: 3;
  display: flex;
  align-items: baseline;
  gap: 38px;
  mix-blend-mode: multiply;
}
.brand {
  display: inline-flex;
  /* baseline, not center: nav aligns its children on the baseline, and a
     center-aligned flex container hands up the mark's bottom edge as its
     baseline instead of the wordmark's — which lifts the wordmark off the
     line shared with "Contact". Baseline here also sets the mark on the
     baseline like a glyph, which is where it belongs in a lockup. */
  align-items: baseline;
  /* The wordmark is tracked out at .16em, so the mark needs a clearly wider
     gap than that to read as separate from the first letter rather than as
     another glyph in the run. */
  gap: 12px;
  font-weight: 600;
  font-size: 12px;
  letter-spacing: .16em;
  text-transform: uppercase;
}
.brand-mark {
  display: block;
  /* Matched to the wordmark's cap height, not its font-size — the mark is
     wider than it is tall, so sizing it to 12px would read as larger. */
  height: 10px;
  width: auto;
}
/* Portfolio and Contact are the same control in two places — one rule, so
   they cannot drift apart. .right only adds the push to the far edge. */
.nav-link,
nav .right {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 13.5px;
  color: var(--ink);
  text-decoration: none;
  cursor: pointer;
  opacity: 1;
  transition: opacity 180ms ease;
}
.nav-link:hover,
nav .right:hover { opacity: .6; }

nav .right { margin-left: auto; }

.copy {
  position: absolute;
  left: var(--edge);
  bottom: 13vh;
  max-width: 60%;
  z-index: 2;
}
.eyebrow {
  position: relative;
  display: inline-block;
  font-size: 11px;
  letter-spacing: .22em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--dim-strong);
  text-shadow: 0 0 3px var(--paper), 0 0 3px var(--paper), 0 0 7px var(--paper);
  margin-bottom: 22px;
}

/* A blurred paper wash clears the dots immediately under the small type. Soft
   edges, so it reads as the field thinning out rather than as a panel. */
.eyebrow::before,
.foot::before {
  content: '';
  position: absolute;
  inset: -12px -20px;
  z-index: -1;
  background: var(--paper);
  filter: blur(11px);
  opacity: .8;
}
h1 {
  mix-blend-mode: multiply;
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(50px, 7.4vw, 124px);
  line-height: .94;
  letter-spacing: -.03em;
}
h1 .dim { color: var(--dim); }

.side {
  position: absolute;
  right: var(--edge);
  bottom: 14vh;
  max-width: 280px;
  z-index: 3;
  text-align: right;
}
.sub {
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink);
  opacity: .82;
  text-shadow: 0 0 6px rgba(244, 241, 234, .8);
  max-width: 34ch;
  margin-left: auto;
}
.cta {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-top: 20px;
  padding: 12px 20px;
  border-radius: 2px;
  background: var(--accent);
  color: var(--paper);
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
}

.foot {
  position: absolute;
  left: var(--edge);
  bottom: 4.5vh;
  z-index: 3;
  display: flex;
  gap: 34px;
  font-size: 10px;
  letter-spacing: .15em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--dim-strong);
  text-shadow: 0 0 3px var(--paper), 0 0 3px var(--paper), 0 0 7px var(--paper);
}
.foot b {
  display: block;
  margin-top: 4px;
  color: var(--ink);
  font-weight: 600;
  letter-spacing: .08em;
  text-shadow: 0 0 3px var(--paper), 0 0 3px var(--paper), 0 0 7px var(--paper);
}

/* --- mobile -------------------------------------------------------------
   Desktop is deliberately untouched. On narrow screens the bottom-left /
   bottom-right split cannot hold: .copy and .side are both absolutely
   positioned against the bottom edge, and once the headline wraps to the
   full width they overlap. Below 720px the three blocks become a normal
   bottom-anchored column instead. */
@media (max-width: 720px) {
  body {
    /* svh, not vh: vh counts the area behind mobile browser chrome, which
       pushes the footer under the URL bar. svh is the always-visible box. */
    height: 100svh;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    /* the headline's descenders hang below its box; give them room */
    gap: clamp(22px, 3.2vh, 30px);
    /* The absolute blocks each supplied their own inset; once they are in
       normal flow the page itself has to hold the margin. */
    padding: var(--edge);
  }

  /* The eyebrow's paper wash bleeds 20px past its box, which is wider than the
     page margin on a phone and pushes the document sideways. */
  .eyebrow::before { inset: -10px -12px; }

  .copy, .side, .foot {
    /* relative, not static: these carry z-index to sit above the fixed canvas.
       static would drop them out of the positioned stacking order and the dot
       field would paint straight over the type. */
    position: relative;
    inset: auto;
    max-width: none;
    text-align: left;
  }
  .sub { margin-left: 0; max-width: 32ch; }

  h1 {
    /* The desktop floor of 50px overflows a 320px screen. */
    font-size: clamp(33px, 11.5vw, 52px);
  }
  .eyebrow { margin-bottom: 14px; }

  .foot { gap: 13px 18px; font-size: 9.5px; flex-wrap: wrap; }
  .side { gap: 12px; }

  /* Centring the dialog puts it behind the on-screen keyboard once it opens.
     Anchor it near the top and let the overlay scroll instead. */
  .sheet {
    place-items: start center;
    padding: 7vh 16px 16px;
    overflow-y: auto;
  }

  /* iOS Safari auto-zooms the whole page when a focused control is under 16px,
     and does not zoom back out. 16px is the threshold, not a design choice. */
  .sheet-form textarea,
  .sheet-form input[type="email"] {
    font-size: 16px;
  }

  /* 30px is a fine mouse target and a poor thumb one. */
  .sheet-close {
    top: 6px;
    right: 6px;
    width: 44px;
    height: 44px;
  }

  /* --- paper washes, mobile only ---------------------------------------
     Same trick as the stats row: a blurred paper rectangle behind each text
     block thins the dot field just where type sits, with edges soft enough
     to read as the field clearing rather than as a panel. A phone screen
     puts the copy over the densest part of the plume with no room to move
     it, so every block gets one here. */
  nav::before,
  .copy::before,
  .side::before {
    content: '';
    position: absolute;
    inset: -16px -22px;
    z-index: -1;
    background: var(--paper);
    /* Softer and weaker than the stats wash: these blocks are large and sit
       next to each other, so their washes merge. Too opaque and the lower
       third stops reading as artwork and starts reading as a panel. */
    filter: blur(19px);
    opacity: .6;
  }

  /* The eyebrow sits inside .copy and now shares its wash — its own would
     stack a second layer on the same spot and read as a visible blob. */
  .eyebrow::before { display: none; }

  /* nav is the blended element itself, so a wash inside it would be
     multiplied away to nothing. Trade the blend for legibility here; the
     headline keeps multiply because its wash sits on .copy, one level up. */
  nav { mix-blend-mode: normal; }
}

/* No hover on touch, so the field would otherwise stay bent around wherever
   the last tap landed. */
@media (hover: none) {
  .cta:hover { transform: none; }
}

/* --- contact sheet ------------------------------------------------------ */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* The honeypot must be reachable by a scripted filler but never by a person,
   so it is moved off-screen rather than display:none — some bots skip hidden
   fields, and screen readers skip it via aria-hidden + tabindex="-1". */
.sheet-trap {
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

/* The default ring is a saturated blue against a warm parchment palette.
   Keyboard-only, so pointer users never see it either way. */
:focus-visible {
  outline: 2px solid rgba(26, 24, 21, .5);
  outline-offset: 3px;
  border-radius: 2px;
}

button.right,
button.cta {
  border: 0;
  font: inherit;
  cursor: pointer;
}
button.right {
  background: none;
  padding: 0;
  color: var(--ink);
  font-size: 13.5px;
}

.sheet {
  position: fixed;
  inset: 0;
  z-index: 10;
  display: grid;
  place-items: center;
  padding: 20px;
}
.sheet[hidden] { display: none; }

.sheet-scrim {
  position: absolute;
  inset: 0;
  background: rgba(244, 241, 234, .74);
  backdrop-filter: blur(7px) saturate(1.05);
  -webkit-backdrop-filter: blur(7px) saturate(1.05);
  animation: sheet-fade 240ms ease both;
}

.sheet-panel {
  position: relative;
  width: min(440px, 100%);
  padding: 30px 30px 26px;
  background: var(--paper);
  border: 1px solid rgba(26, 24, 21, .14);
  border-radius: 3px;
  box-shadow: 0 30px 70px -24px rgba(26, 24, 21, .34);
  animation: sheet-rise 260ms cubic-bezier(.2, .7, .3, 1) both;
}

@keyframes sheet-fade { from { opacity: 0 } to { opacity: 1 } }
@keyframes sheet-rise {
  from { opacity: 0; transform: translateY(10px) scale(.985) }
  to   { opacity: 1; transform: none }
}
@media (prefers-reduced-motion: reduce) {
  .sheet-scrim, .sheet-panel { animation-duration: 1ms }
}

.sheet-close {
  position: absolute;
  top: 10px; right: 12px;
  width: 30px; height: 30px;
  border: 0;
  background: none;
  color: var(--dim);
  font: 400 22px/1 var(--body);
  cursor: pointer;
  border-radius: 2px;
  transition: color 160ms ease;
}
.sheet-close:hover { color: var(--ink); }

.sheet-title {
  font-family: var(--display);
  font-weight: 400;
  font-size: 33px;
  line-height: 1.04;
  letter-spacing: -.022em;
  margin-bottom: 18px;
}
.sheet-body {
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink);
  opacity: .8;
  margin-bottom: 22px;
}

.sheet-form textarea,
.sheet-form input[type="email"] {
  display: block;
  width: 100%;
  font-family: var(--body);
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--ink);
  background: rgba(255, 255, 255, .5);
  border: 1px solid rgba(26, 24, 21, .16);
  border-radius: 2px;
  padding: 11px 13px;
  transition: border-color 160ms ease, box-shadow 160ms ease;
}
.sheet-form textarea {
  min-height: 108px;
  resize: vertical;
  margin-bottom: 10px;
}
.sheet-form ::placeholder { color: var(--dim); opacity: 1; }
.sheet-form textarea:focus,
.sheet-form input[type="email"]:focus {
  outline: none;
  border-color: rgba(26, 24, 21, .5);
  box-shadow: 0 0 0 3px rgba(26, 24, 21, .07);
}
.sheet-form [aria-invalid="true"] { border-color: #9C3B2E; }

.sheet-actions {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 16px;
}
.sheet-note {
  flex: 1;
  min-width: 0;
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--dim);
}
.sheet-note[data-state="error"] { color: #9C3B2E; }
.sheet-send { margin-top: 0; }
.sheet-send[disabled] { opacity: .55; cursor: default; }

.sheet-done .cta { margin-top: 0; }

/* --- portfolio ---------------------------------------------------------- */
.deals {
  list-style: none;
  margin-top: 4px;
}
.deal {
  display: flex;
  align-items: center;
  gap: 15px;
  padding: 17px 2px;
  border-top: 1px solid rgba(26, 24, 21, .13);
}
.deal:last-child { border-bottom: 1px solid rgba(26, 24, 21, .13); }
.deal-mark {
  display: block;
  height: 15px;
  width: auto;
  flex: none;
}
.deal-name {
  font-family: var(--display);
  font-size: 21px;
  letter-spacing: -.01em;
}
.deal-date {
  margin-left: auto;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--dim-strong);
}

@media (max-width: 460px) {
  .sheet-panel { padding: 26px 22px 22px; }
  .sheet-title { font-size: 28px; }
}
