/* Inter variable, Latin subset: the same file Google Fonts serves, self-hosted
   so the page makes no third-party font requests. One download covers body
   text (every weight) and the decorative card lettering. */
@font-face{font-family:Inter;src:url('assets/inter-variable-latin.woff2') format('woff2');font-weight:100 900;font-style:normal;font-display:swap;unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
/* Keep decorative card lettering independent of the body-font swap. */
@font-face {
  font-family: "Card Inter";
  src: url("assets/inter-variable-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: block;
}
.card-font-pending .project-bg-text { visibility: hidden; }

:root, :host {
  --font: "Inter", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --text: #111;
  --muted: rgba(0, 0, 0, 0.4);
  --bg: #ffffff;
  --line: #f2f2f2;
  --placeholder: #f4f4f3;
  --focus: rgba(0, 122, 255, 0.5);
}

*, *::before, *::after { box-sizing: border-box; }
html, body, h1, h2, h3, p, ul { margin: 0; padding: 0; }
html { background: var(--bg); color: var(--text); }
body {
  min-height: 100vh;
  overflow-y: scroll;
  font-family: var(--font);
  font-size: 16px;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  text-size-adjust: none;
}
::selection { color: var(--text); background: #ededed; }
button { font: inherit; color: inherit; }

/* Content column. */
.page { max-width: 36.375rem; margin: 0 auto; padding: 5rem 1rem 0; }

/* Intro */
.article > header { display: flex; flex-direction: column; gap: 0.25rem; padding-bottom: 3rem; }
.article h1, .article .role, .article > p {
  font-size: 1rem;
  line-height: 1.5rem;
  letter-spacing: -0.00563rem;
}
.article h1 { font-weight: 700; }
.article .role { color: var(--muted); font-weight: 460; }
.article > p { padding-top: 1rem; font-weight: 460; }
.article > header + p { padding-top: 0; }
.article-continuation { margin-top: 64px; }
.article-continuation > p:first-child { padding-top: 0; }

.basic-link { position: relative; color: inherit; text-decoration: none; transition: 0.2s; }
.basic-link::before {
  content: "";
  pointer-events: none;
  position: absolute;
  inset: auto 0 0;
  height: 1px;
  border-radius: 2px;
  background: #d9d9d9;
  transition: inherit;
}
.basic-link:hover::before { background: #666; }
.basic-link:focus-visible { border-radius: 2px; padding: 0 2px; margin: 0 -2px; outline: 2px solid var(--focus); transition: none; }

/* Company logos: on hover the logo takes the cursor's place. */
.company-logo-cursor {
  pointer-events: none;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 20;
  width: 20px;
  height: 20px;
  overflow: hidden;
  border-radius: 4px;
  box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.12), 0 1px 2px -1px rgba(0, 0, 0, 0.1);
  transform: translate(-50%, -50%);
}
.company-logo-cursor img { display: block; width: 20px; height: 20px; object-fit: contain; }
@media (hover: hover) and (pointer: fine) {
  .company-link:hover { cursor: none; }
}

/* Projects: Shopify Design's multi-card sizing, anchored near the text column.
   The cards overhang the text by 64px when space allows. */
html { overflow-x: clip; }
.projects {
  --gutter: max(1rem, calc((100vw - 36.375rem) / 2 + 1rem));
  --card-size: min(360px, calc(100vw - 32px));
  --carousel-gutter: max(16px, calc(var(--gutter) - 64px));
  position: relative;
  margin: 64px calc(50% - 50vw) 0;
}
.projects:focus { outline: none; }
.projects-head { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 0.375rem; padding: 0 var(--gutter) 24px; }
.projects-head h2 { font-size: 1rem; font-weight: 500; line-height: 1.5rem; letter-spacing: -0.00563rem; }
/* "Live", circled by hand once the section comes into view (rough-notation, after benji.org). */
.projects-live { position: relative; margin-left: 0.75rem; color: #218238; font-size: 1rem; font-weight: 460; line-height: 1.5rem; }

/* Room above and below so the hover lift and its shadow (0 12px 31px)
   aren't clipped by the scroller. */
.projects-track {
  display: flex;
  gap: 16px;
  margin: -1.5rem 0 -3rem;
  padding: 3rem var(--carousel-gutter, var(--gutter));
  list-style: none;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--carousel-gutter, var(--gutter));
  scrollbar-width: none;
}
@media (min-width: 1024px) {
  .page { padding-top: 120px; }
  .projects {
    --card-size: 415px;
  }
  .projects-track { gap: 24px; }
}
.projects-track::-webkit-scrollbar { display: none; }
.projects-track:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; border-radius: 1.5rem; }

.project-card { flex: 0 0 var(--card-size); height: var(--card-size); scroll-snap-align: start; }
@media (max-width: 639px) {
  .projects { --card-size: min(360px, calc(100vw - 80px)); }
  /* First card reveals the next; middle cards snap with a peek on both sides. */
  .projects-track > .project-card { scroll-snap-align: center; }
}
.project-link { display: block; height: 100%; color: inherit; text-decoration: none; border-radius: 1.5rem; -webkit-user-drag: none; }
.project-link:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

/* The card: a coloured panel, a tilted cover in the middle, a mono caption along the bottom. */
.project-media {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: calc(var(--card-size) * 0.068);
  overflow: hidden;
  border-radius: 1.5rem;
  background: var(--card-bg, var(--placeholder));
  color: var(--card-footer-fg, var(--text));
  user-select: none;
  box-shadow: 0 12px 31px rgba(0, 0, 0, 0);
  transition: transform 0.65s var(--ease-spring-bouncy), box-shadow 0.65s var(--ease-spring-bouncy);
}
@supports (corner-shape: superellipse(1.2)) {
  .project-media { corner-shape: superellipse(1.2); }
}
.project-art {
  position: relative;
  z-index: 2;
  display: flex;
  flex: 1;
  align-items: center;
  justify-content: center;
  transform: rotate(var(--media-rotation, 2deg));
}
/* A big word behind the cover that drifts sideways on hover (after shopify.design). */
.project-bg-text {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 1;
  transform: translate(-45%, -50%);
  font-family: "Card Inter", system-ui, sans-serif;
  font-size: calc(var(--card-size) * 0.335);
  font-weight: 500;
  line-height: 0.85;
  letter-spacing: -0.04em;
  white-space: nowrap;
  color: var(--card-fg);
  pointer-events: none;
}
.project-frame {
  position: relative;
  overflow: hidden;
  border-radius: calc(var(--card-size) * 0.058);
  box-shadow: 0 24px 32px rgba(0, 0, 0, 0.12);
}
.project-frame > img {
  display: block;
  max-width: calc(var(--card-size) * 0.58);
  /* Tied to the width, so the cover keeps its size in the square card. */
  max-height: calc(var(--card-size) * 0.63);
  object-fit: cover;
  -webkit-user-drag: none;
}
.project-frame > video {
  display: block;
  /* Same box as the cover images; the recordings sit on white, so they fit inside it. */
  width: calc(var(--card-size) * 0.58);
  height: calc(var(--card-size) * 0.63);
  object-fit: contain;
  background: #fff;
}
.projects-track .project-frame > video { opacity: 0; pointer-events: none; }
.projects-track .project-frame > video[data-playing] { opacity: 1; }
.projects-track video::-webkit-media-controls-start-playback-button { display: none !important; }
/* AI agents card: the old project's receptionist scene (agent-call/), on white
   instead of its star sky. It's laid out on a 1440×810 stage; the stage is sized so
   700px of it spans the frame, and the bubbles are pulled in to sit inside that. */
.agent-call {
  position: relative;
  width: calc(var(--card-size) * 0.58);
  height: calc(var(--card-size) * 0.63);
  overflow: hidden;
  background: #fff;
}
.agent-call .receptionist-film {
  inset: auto;
  top: 50%;
  left: 50%;
  width: calc(var(--card-size) * 0.58 * 1440 / 700);
  aspect-ratio: 1440 / 810;
  translate: -50% -50%;
}
.agent-call .receptionist-bubble.ai { left: 416px; }
.agent-call .receptionist-bubble.caller { right: 416px; }
/* The sky gave the bubbles their edge; on white they need a fill, a hairline and a soft shadow. */
.agent-call .receptionist-bubble [data-message-bubble] { box-shadow: 0 4px 14px rgba(70, 40, 20, 0.07); }
.agent-call .receptionist-bubble.ai [data-message-bubble] { background: rgba(246, 243, 239, 0.82); }
.agent-call .receptionist-bubble.caller [data-message-bubble] { background: #fff; border-color: rgba(0, 0, 0, 0.1); }
.project-play {
  position: absolute;
  bottom: 12px;
  left: 12px;
  display: flex;
  align-items: center;
  gap: 3px;
  color: #fff;
  font-size: calc(var(--card-size) * 0.039);
  font-weight: 500;
}
.project-play svg { width: calc(var(--card-size) * 0.034); height: calc(var(--card-size) * 0.034); }
.project-footer {
  position: relative;
  z-index: 2;
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 6px;
  margin-top: auto;
}
.project-footer h3 {
  font-size: 18px;
  font-weight: 460;
  line-height: 1.5rem;
  letter-spacing: -0.00563rem;
}

@media (hover: hover) and (pointer: fine) {
  .project-link:hover .project-media { transform: scale(1.015); box-shadow: 0 12px 31px rgba(0, 0, 0, 0.12); }
  .project-link:active .project-media { transform: scale(0.97); box-shadow: 0 12px 31px rgba(0, 0, 0, 0); }
  .project-link:hover .project-art { transform: rotate(var(--media-rotation, 2deg)) scale(1.04); }
  .project-bg-text { transition: transform 1s var(--ease-spring-medium); }
  .project-link:hover .project-bg-text { transform: translate(-55%, -50%); }
}

/* Project sheet: a Silk bottom sheet holding the project page. Its size, and the page
   sinking back over near-black while it's up, follow marvinschwaibold.com. */
:root, :host {
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --sheet-stack-bg: #050505;
  --sheet-gap: max(calc(env(safe-area-inset-top) + 1.3vh), 2.6vh);
  --sheet-scenery-offset: max(env(safe-area-inset-top), 1.3vh);
  --ease-spring-medium: linear(0, .006 1%, .022 2%, .048 3%, .081 4%, .119 5%, .162 6%, .209 7%, .257 8%, .308 9%, .358 10%, .409 11%, .459 12%, .508 13%, .556 14%, .602 15%, .645 16%, .687 17%, .726 18%, .762 19%, .796 20%, .827 21%, .856 22%, .882 23%, .905 24%, .927 25%, .946 26%, .963 27%, .977 28%, .99 29%, 1.001 30%, 1.011 31%, 1.019 32%, 1.025 33%, 1.031 34%, 1.035 35%, 1.038 36%, 1.04 37%, 1.042 38%, 1.043 39%, 1.043 40%, 1.042 41%, 1.042 42%, 1.041 43%, 1.039 44%, 1.037 45%, 1.035 46%, 1.033 47%, 1.031 48%, 1.029 49%, 1.027 50%, 1.023 52%, 1.019 54%, 1.015 56%, 1.011 58%, 1.008 60%, 1.006 62%, 1.004 64%, 1.002 66%, 1.001 68%, 1 69%, .999 71%, .999 73%, .998 75%, .998 80%, .998 85%, .999 90%, .999 95%, 1);
  --ease-spring-bouncy: linear(0, .008, .032 2%, .13 4.4%, .26 6.6%, .681 13%, .891 17.1%, .968, 1.028, 1.073, 1.103 25.2%, 1.114, 1.119, 1.12, 1.115 31.4%, 1.098 34.4%, 1.042 41.6%, 1.017 45.4%, .998 49.5%, .988 53.9%, .986 60.4%, 1.001 80.9% 100%);
}
/* translate, not transform, so the cover keeps its tilt */
.project-footer, .project-art { transition: opacity 500ms ease, translate 600ms var(--ease-out), transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); }
.scenery { min-height: 100vh; background: var(--bg); }
/* The page scales from its scroll position; JS writes its transform directly. */
html.has-sheet { overflow: hidden; background: var(--sheet-stack-bg); }
html.has-sheet .scenery {
  transform-origin: 50% var(--scenery-top, 0px);
  transform: translateY(0) scale(1);
  clip-path: inset(var(--scenery-top, 0px) 0 var(--scenery-bottom, 0px) round 24px);
  will-change: transform;
}

/* Silk keeps a stable scroll viewport as mobile browser bars expand/collapse.
   Size the visible content separately; a percentage here would use that larger
   scroll viewport and push the sheet's top above the visible screen. */
.sheet-view { z-index: 2000; height: var(--silk-100-lvh-dvh-pct); }
.sheet-backdrop { background-color: var(--sheet-stack-bg); }
.sheet {
  box-sizing: border-box;
  display: grid;
  height: calc(100dvh - var(--sheet-gap));
}
.sheet-bleed {
  background: #fff;
  border-radius: 24px 24px 0 0;
  box-shadow: 0 10px 15px -3px rgb(0 0 0 / 10%), 0 4px 6px -4px rgb(0 0 0 / 10%);
}
.sheet-body {
  position: relative;
  z-index: 0;
  grid-area: 1 / 1;
  min-height: 0;
  overflow: clip;
  border-radius: 24px 24px 0 0;
  background: #fff;
}
.sheet-content {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 200ms ease, transform 200ms ease;
}
.sheet.is-ready .sheet-content {
  opacity: 1;
  transform: none;
  transition: opacity 600ms var(--ease-out) 120ms, transform 700ms var(--ease-out) 120ms;
}
/* Project-to-project navigation keeps the shell still and hands off content
   only once it is hidden. A short departure leads into a soft, immediate settle. */
.sheet.is-switching .sheet-content {
  transform: translateY(10px);
  transition: none;
}
.sheet.is-switching.is-switching-out .sheet-content {
  transform: translateY(-8px);
  transition: opacity 140ms cubic-bezier(0.4, 0, 1, 1), transform 140ms cubic-bezier(0.4, 0, 1, 1);
}
.sheet.is-switching.is-ready .sheet-content {
  opacity: 1;
  transform: none;
  transition: opacity 240ms cubic-bezier(0.25, 1, 0.5, 1), transform 320ms cubic-bezier(0.22, 1, 0.36, 1);
}
@media (prefers-reduced-motion: reduce) {
  .sheet.is-switching .sheet-content {
    transform: none !important;
    transition: opacity 100ms ease !important;
  }
}
/* Mobile and touch: keep the grabber available regardless of hover capability. */
.sheet-handle {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate3d(-50%, 0, 0);
  z-index: 2;
  width: 64px;
  height: 44px;
  padding: 0;
  border: 0;
  background: transparent;
  color: transparent;
  font-size: 0;
  cursor: grab;
  touch-action: none;
  appearance: none;
  -webkit-tap-highlight-color: transparent;
}
.sheet-handle::after {
  content: "";
  position: absolute;
  top: 10px;
  left: 50%;
  width: 36px;
  height: 4px;
  border-radius: 999px;
  background: rgb(0 0 0 / 28%);
  transform: translateX(-50%);
}
@media (min-width: 768px) and (hover: hover) and (pointer: fine) {
  .sheet-handle { display: none; }
}

/* Reference-style gray surface and outlined white X; ring counts gallery frames. */
.sheet-button {
  position: absolute;
  z-index: 3;
  left: 50%;
  bottom: calc(64px + env(safe-area-inset-bottom));
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  margin-left: -29px;
  padding: 0;
  border: 1px solid rgb(255 255 255 / 40%);
  border-radius: 50%;
  background: rgb(96 96 96 / 68%);
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / 10%);
  color: #fff;
  cursor: pointer;
  opacity: 0;
  transform: translateY(12px) scale(0.92);
  transition: opacity 0.42s ease, transform 0.52s cubic-bezier(0.2, 0.8, 0.2, 1);
}
/* It arrives once the sheet has come to rest */
.sheet-view:has(.sheet.is-open) .sheet-button {
  opacity: 1;
  transform: none;
  transition:
    opacity 0.42s ease 60ms,
    transform 0.52s cubic-bezier(0.2, 0.8, 0.2, 1) 60ms;
}
@media (hover: hover) and (pointer: fine) {
  .sheet-view:has(.sheet.is-open) .sheet-button:hover { transform: scale(1.04); transition-delay: 0ms; }
}
.sheet-view:has(.sheet.is-open) .sheet-button:focus-visible {
  transform: scale(1.04);
  outline: 2px solid var(--focus);
  outline-offset: 3px;
  transition-delay: 0ms;
}
.sheet-button svg { display: block; width: 100%; height: 100%; }
.sheet-button-track,
.sheet-button-progress { fill: none; stroke-width: 3; transform: rotate(-90deg); transform-origin: 50% 50%; }
.sheet-button-track { stroke: rgb(255 255 255 / 18%); }
/* Follow the gallery's rendered position directly; a transition adds scroll lag. */
.sheet-button-progress { stroke: rgb(255 255 255 / 80%); stroke-linecap: round; }
.sheet-button-close,
.sheet-button-close-outline {
  fill: none;
  stroke: currentColor;
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  transform-origin: 50% 50%;
  transform: scale(0.72);
}
.sheet-button-close-outline { stroke: rgb(0 0 0 / 50%); stroke-width: 5.5; }
@media (max-width: 760px) {
  .sheet-button { bottom: calc(56px + env(safe-area-inset-bottom)); width: 52px; height: 52px; margin-left: -26px; }
}
@media (hover: none), (pointer: coarse) {
  :root {
    --sheet-gap: calc(env(safe-area-inset-top) + 16px);
    --sheet-scenery-offset: calc(env(safe-area-inset-top) + 8px);
  }
  /* The viewport layer keeps the bottom-center control above the content.
     Its visibility never depends on Silk reaching an exact animation state. */
  .sheet-view .sheet-button { opacity: 1; transform: none; transition: none; }
}
@media (prefers-reduced-motion: reduce) {
  .sheet-content, .sheet-button, .sheet-button * { transition: none !important; }
}

/* Footer */
.footer { padding: 4rem 0 5rem; }
.footer::before { content: ""; display: block; width: 3.125rem; height: 1px; margin-bottom: 4rem; background: #ededed; }
.footer p { color: var(--muted); font-size: 1rem; line-height: 1.5rem; font-weight: 460; letter-spacing: -0.0025rem; font-variant-numeric: tabular-nums; }

.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* Digits roll when the minute changes. */
.clock { display: inline-flex; }
.digit { display: inline-block; position: relative; overflow: hidden; height: 1.2em; line-height: 1.2em; vertical-align: bottom; }
.digit > span { display: block; }
.digit > .out { position: absolute; inset: 0; animation: digitOut 0.4s cubic-bezier(0.3, 0, 0.2, 1) both; }
.digit > .in { animation: digitIn 0.4s cubic-bezier(0.3, 0, 0.2, 1) both; }
@keyframes digitOut { to { transform: translateY(-100%); opacity: 0; } }
@keyframes digitIn { from { transform: translateY(100%); opacity: 0; } }

/* Benji's entrance: 8px rise, 500ms ease, 50ms between blocks.
   Explicit page order keeps the stagger continuous across the carousel. */
@keyframes staggerIn {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}
.article > *, .projects, .footer {
  animation: staggerIn 0.5s ease;
  animation-fill-mode: backwards;
}
.page > .article > header { animation-delay: 0s; }
.page > .article > p { animation-delay: 0.05s; }
.projects { animation-delay: 0.1s; }
.page > .article-continuation > p:first-child { animation-delay: 0.15s; }
.page > .article-continuation > p:nth-child(2) { animation-delay: 0.2s; }
.page > .article-continuation > p:nth-child(3) { animation-delay: 0.25s; }
.footer { animation-delay: 0.3s; }

@media (max-width: 768px) {
  .page { padding: 2rem 1.5rem 0; }
  .projects { --gutter: max(1.5rem, calc((100vw - 36.375rem) / 2 + 1.5rem)); }
}
@media (prefers-reduced-motion: reduce) {
  .article > *, .projects, .footer, .digit > span { animation: none; }
}

/* Direct galleries share the page's font without importing the legacy shell. */
.sheet-content .gallery-intro { flex-direction: column; gap: 1rem; }
.sheet-content .gallery-project-orb {
  display: block; width: 80px; height: 80px; flex: 0 0 auto;
  object-fit: contain; pointer-events: none; user-select: none;
}
.sheet-content .gallery-project-title {
  margin: 0; max-width: 34.375rem; font-family: var(--font);
  font-size: 1rem; font-weight: 700; line-height: 1.5rem;
  letter-spacing: -0.00563rem; color: var(--text); text-align: center;
}
.sheet-content .project-gallery { background: transparent; }
.sheet-content .project-gallery:focus-visible { outline: none; }
.sheet-content .project-description p {
  max-width: 34.375rem; font-family: var(--font); font-weight: 460;
  letter-spacing: -.00563rem; color: #111; text-align: center;
}
