/* Webfont registration and typography roles come from font-config.js. */

/* ================================================================
   CREATIVE DIRECTOR CONTROL PANEL
   EDIT HERE
   ================================================================ */
:root {
  color-scheme: light;
  font-synthesis: none;

  /* DEFAULT ENVIRONMENT */
  --page-bg: #000000;
  --page-text: #ffffff;

  /* ==============================================
     CREATIVE DIRECTOR — LANDING INTERACTION
     Dim color, values and timing map before paint from halftone-config.js.
     This layer never replaces or recolors the gradient environment.
     ============================================== */
  --dot-matrix-opacity: 1;
  --card-hover-scale: 1.05;

  /* Corner interface transition remains independent from the landing dim. */
  --corner-interface-opacity: 1;
  --corner-interface-color: #ffffff;
  --project-area-interface-duration: 1000ms;
  --project-area-interface-easing: cubic-bezier(0.22, 1, 0.36, 1);

  /* ================================================================
     CREATIVE DIRECTOR — TOP-LEFT SIGNATURE
     The PNG keeps its intrinsic 5:1 aspect ratio; width is the only dimension.
     ================================================================ */
  --corner-signature-width: 320px;
  --corner-signature-x: 34px;
  --corner-signature-y: 34px;
  --corner-signature-opacity: 1;
  --corner-signature-rotation: 0deg;
  --corner-signature-width-mobile: 220px;
  --corner-signature-x-mobile: 26px;
  --corner-signature-y-mobile: 18px;

  /* ================================================================
     CREATIVE DIRECTOR — CONTACT LINE
     Shared contact/social links remain compact. Alignment accepts left/right.
     Desktop and mobile values are independent and centralized here.
     ================================================================ */
  --contact-font: var(--font-contact, Arial, Helvetica, sans-serif);
  --contact-size: 14px;
  --contact-line-height: 1;
  --contact-letter-spacing: 0em;
  --contact-gap: 10px;
  --contact-align: right;
  --contact-x: 34px;
  --contact-y: 34px;
  --contact-max-width: 470px;

  --contact-font-mobile: var(--font-contact, Arial, Helvetica, sans-serif);
  --contact-size-mobile: 14px;
  --contact-line-height-mobile: 1.1;
  --contact-letter-spacing-mobile: 0em;
  --contact-link-gap-mobile: 7px;
  --contact-row-gap-mobile: 6px;
  --contact-align-mobile: end;
  --contact-x-mobile: 26px;
  --contact-y-mobile: 34px;
  --contact-max-width-mobile: 375px;

  /* ================================================================
     CREATIVE DIRECTOR — MOBILE PROJECT FEED
     Featured projects remain ordinary vertical document content. Their tint
     spans the viewport while one inset controls cover, miniature and copy.
     ================================================================ */
  --mobile-project-side-inset: 16px;
  --mobile-project-gap: 0px;
  --mobile-project-feed-top-padding: 0px;
  --mobile-project-feed-bottom-padding: 0px;
  --mobile-featured-padding-top: 28px;
  --mobile-cover-title-gap: 32px;
  --mobile-title-description-gap: 10px;
  --mobile-description-thumbnails-gap: 20px;
  --mobile-thumbnail-next-project-gap: 96px;
  --mobile-featured-padding-bottom: var(--mobile-thumbnail-next-project-gap);
  --mobile-project-background-base: #000000;
  --mobile-project-fallback-background: #000000;
  --mobile-project-fallback-title: #ffffff;
  --mobile-project-fallback-description: rgba(255, 255, 255, 0.5);

  /* MOBILE ARCHIVE — editorial title index + centered cover context. */
  --mobile-archive-padding-top: 56px;
  --mobile-archive-padding-bottom: 0px;
  /* Fallback only: active Archive projects use the shared project treatment. */
  --mobile-archive-background: #000000;
  --mobile-archive-background-transition-duration: 520ms;
  --mobile-archive-background-transition-easing: ease;
  --mobile-archive-heading-size: 14px;
  --mobile-archive-heading-gap: 28px;
  --mobile-archive-title-inset:
    calc(var(--room-gutter) + var(--archive-left-offset));
  --mobile-archive-title-size: 24px;
  --mobile-archive-title-line-height: 1.05;
  --mobile-archive-title-gap: 18px;
  --mobile-archive-title-center-compensation: 0.525em;
  --mobile-archive-title-runway:
    max(0px, calc(50svh - var(--mobile-archive-title-center-compensation)));
  --mobile-archive-title-opacity: 0.38;
  --mobile-archive-active-title-opacity: 1;
  --mobile-archive-preview-width: min(75vw, 18rem);
  --mobile-archive-preview-sticky-y: 50svh;
  --mobile-archive-preview-opacity: 0.88;
  --mobile-archive-preview-transition-duration: 420ms;
  --mobile-archive-preview-transition-easing: ease;

  /* MOBILE ATMOSPHERE — CSS-only background experiment.
     The layer is fixed behind mobile content and never changes content opacity. */
  --mobile-gradient-opacity: 0.0;
  --mobile-gradient-speed: 28s;
  --mobile-gradient-blur: 64px;

  /* MOBILE SIGNATURE — one persistent viewport layer, recolored via PNG mask. */
  --mobile-signature-width: 220px;
  --mobile-signature-top: 18px;
  --mobile-signature-left: 16px;
  --mobile-signature-opacity: 1;
  --mobile-signature-color: #ffffff;
  --mobile-signature-z-index: 20;
  --mobile-signature-opening-space: 64px;

  --mobile-project-cover-max-height: none;
  --mobile-project-cover-object-position-x: 50%;
  --mobile-project-cover-object-position-y: 50%;
  --mobile-project-cover-object-fit: contain;

  /* Project-owned gallery miniatures. Every derivative keeps its natural ratio
     at the shared height and wraps only when the next image no longer fits. */
  --mobile-gallery-thumb-height: 70px;
  --mobile-gallery-thumb-column-gap: 0px;
  --mobile-gallery-thumb-row-gap: 0px;
  --mobile-gallery-thumb-margin-top: var(--mobile-description-thumbnails-gap);
  --mobile-gallery-thumb-opacity: 1;

  --mobile-project-title-size: clamp(21px, 6.4vw, 27px);
  --mobile-project-title-line-height: 1;
  --mobile-project-title-letter-spacing: 0em;
  --mobile-project-title-gap: var(--mobile-cover-title-gap);

  --mobile-project-description-size: 12px;
  --mobile-project-description-line-height: 1.45;
  --mobile-project-description-letter-spacing: 0.02em;
  --mobile-project-description-max-width: 95%;
  --mobile-project-description-gap: var(--mobile-title-description-gap);

  /* Per-project project.css may override these natural-image controls. */
  --mobile-cover-object-position-x: 50%;
  --mobile-cover-object-position-y: 50%;
  --mobile-cover-object-fit: contain;

  /* =========================================
     CREATIVE DIRECTOR — GALLERY OVERLAY
     ========================================= */
  --gallery-open-duration: var(--motion-medium);
  --gallery-close-duration: var(--motion-medium);
  --gallery-image-transition-duration: var(--motion-medium);
  --gallery-overlay-bg: #000000;
  --gallery-overlay-ink: #ffffff;
  --gallery-caption-size: 0.75rem;
  --gallery-caption-line-height: 1.4;
  --gallery-caption-gap: 0.75rem;
  --gallery-caption-opacity: 0.68;
  --gallery-caption-max-width: 42rem;
  --gallery-overview-max-width: 90rem;
  --gallery-overview-padding-block: clamp(7rem, 16vh, 10rem);
  --gallery-overview-padding-inline: clamp(3rem, 6vw, 7rem);
  --gallery-overview-copy-column-width: 45%;
  --gallery-overview-thumbnail-column-width: 33%;
  --gallery-overview-copy-width: 32rem;
  --gallery-overview-column-gap: clamp(4rem, 7vw, 7rem);
  --gallery-overview-divider-padding: clamp(2.5rem, 4vw, 4.5rem);
  --gallery-overview-title-size: clamp(2.5rem, 4vw, 4.5rem);
  --gallery-overview-title-line-height: 0.95;
  --gallery-overview-description-size: 1rem;
  --gallery-overview-description-line-height: 1.5;
  --gallery-overview-copy-gap: clamp(2.25rem, 4vh, 3.5rem);
  --gallery-overview-thumbnail-size: clamp(6.5rem, 8vw, 8.5rem);
  --gallery-overview-thumbnail-gap: clamp(1rem, 1.5vw, 1.5rem);
  --gallery-overview-desktop-thumbnail-columns: 3;
  --gallery-overview-desktop-thumbnail-gap: clamp(1.2rem, 1.8vw, 1.8rem);
  --gallery-overview-desktop-thumbnail-max-height: clamp(10rem, 12vw, 11rem);
  --gallery-overview-divider-color: rgba(255, 255, 255, 0.2);
  --gallery-overview-divider-height: 135%;
  --gallery-overview-mobile-title-size: 2rem;
  --gallery-overview-mobile-description-size: 0.875rem;
  --gallery-overview-mobile-thumbnail-columns: 2;
  --gallery-overview-mobile-padding-top: 7rem;
  --gallery-overview-mobile-padding-bottom: 4.5rem;
  --gallery-overview-mobile-padding-inline: 1.25rem;
  --gallery-overview-mobile-copy-gap: 2.5rem;
  --gallery-overview-mobile-divider-gap: 4rem;
  --gallery-overview-mobile-thumbnail-top-gap: 3rem;
  --gallery-overview-mobile-thumbnail-row-gap: 1.5rem;
  --gallery-overview-mobile-thumbnail-column-gap: 1rem;

  /* ================================================================
     CREATIVE DIRECTOR — ARCHIVE TYPOGRAPHIC INDEX
     The left edge follows the first featured card through the shared
     --project-left-edge-offset control. The extra bottom space lets the
     final title reach the activation line without changing row geometry.
     ================================================================ */
  --archive-section-padding-top: clamp(9rem, 20svh, 16rem);
  --archive-section-padding-bottom:
    max(clamp(7rem, 16svh, 13rem), 50svh);
  --archive-section-padding-inline: var(--room-gutter);
  --archive-left-offset: var(--project-left-edge-offset);
  --archive-title-font:
    var(--font-archive-title, Arial, Helvetica, sans-serif);
  --archive-title-size: 50px;
  --archive-title-line-height: normal;
  --archive-title-letter-spacing: 0em;
  --archive-subtitle-font: var(--font-archive-subtitle, Georgia, serif);
  --archive-subtitle-size: 12px;
  --archive-subtitle-line-height: 1.5;
  --archive-subtitle-letter-spacing: 0.05em;
  --archive-row-gap: 0;
  --archive-title-subtitle-gap: 0px;
  --archive-alignment: start;
  --archive-active-offset-x: 40px;
  --archive-inactive-opacity: 0.3;
  --archive-active-opacity: 1;
  --archive-state-transition-duration: 650ms;
  --archive-state-transition-easing: cubic-bezier(0.22, 1, 0.36, 1);

  /* ARCHIVE PREVIEW — shares the existing middle-card sizing system */
  --archive-preview-width: var(--catalog-default-width);
  --archive-preview-scale: var(--catalog-default-scale);
  --archive-preview-offset-x: 0px;
  --archive-preview-offset-y: 0px;
  --archive-preview-opacity: 1;
  --archive-preview-transition-duration: 650ms;
  --archive-preview-transition-easing: cubic-bezier(0.22, 1, 0.36, 1);

  /* ARCHIVE MOBILE — independent typography and reading state */
  --archive-section-padding-top-mobile: clamp(8rem, 20svh, 12rem);
  --archive-section-padding-bottom-mobile:
    max(clamp(7rem, 16svh, 11rem), 50svh);
  --archive-row-gap-mobile: 0;
  --archive-title-subtitle-gap-mobile: 0px;
  --archive-title-size-mobile: 50px;
  --archive-title-line-height-mobile: normal;
  --archive-title-letter-spacing-mobile: 0em;
  --archive-subtitle-size-mobile: 12px;
  --archive-subtitle-line-height-mobile: 1.5;
  --archive-subtitle-letter-spacing-mobile: 0.05em;
  --archive-active-offset-x-mobile: 20px;
  --archive-inactive-opacity-mobile: 0.3;

  /* ================================================================
     CREATIVE DIRECTOR — WHITE END SECTION
     Content stays in assets/content/bio-content.js. Layout/type controls live
     here; desktop and mobile values remain independently art-directable.
     ================================================================ */
  --bio-section-min-height: 100svh;
  --bio-section-background: #ffe0f7;
  --bio-section-color: #b02b42;
  --bio-section-spacing-top: clamp(8rem, 18svh, 14rem);
  --bio-section-spacing-bottom: clamp(6rem, 14svh, 11rem);
  --bio-column-gap: clamp(3rem, 8vw, 10rem);
  --bio-column-bio-width: minmax(0, 1fr);
  --bio-column-selected-width: minmax(0, 1fr);
  --bio-label-font: var(--font-selected, Arial, Helvetica, sans-serif);
  --bio-label-size: 14px;
  --bio-label-line-height: 1;
  --bio-label-bottom-spacing: clamp(2rem, 4vw, 4rem);
  --bio-font: var(--font-bio, Arial, Helvetica, sans-serif);
  --bio-size: clamp(18px, 1.25vw, 24px);
  --bio-line-height: 1.15;
  --bio-max-width: 36rem;
  --bio-paragraph-gap: 1em;
  --selected-font: var(--font-selected, Arial, Helvetica, sans-serif);
  --selected-size: clamp(18px, 1.25vw, 24px);
  --selected-line-height: 1.15;
  --selected-row-gap: 0.15em;
  --bio-contact-top-spacing: clamp(6rem, 12svh, 10rem);
  --bio-contact-font: var(--contact-font);
  --bio-contact-size: var(--contact-size);
  --bio-contact-line-height: var(--contact-line-height);
  --bio-contact-gap: var(--contact-gap);

  --bio-section-min-height-mobile: 100svh;
  --bio-section-spacing-top-mobile: clamp(6rem, 14svh, 9rem);
  --bio-section-spacing-bottom-mobile: clamp(5rem, 12svh, 8rem);
  --bio-column-gap-mobile: clamp(5rem, 14svh, 8rem);
  --bio-label-size-mobile: 12px;
  --bio-label-line-height-mobile: 1;
  --bio-label-bottom-spacing-mobile: 2rem;
  --bio-size-mobile: 18px;
  --bio-line-height-mobile: 1.4;
  --bio-max-width-mobile: 100%;
  --bio-paragraph-gap-mobile: 1em;
  --selected-size-mobile: 16px;
  --selected-line-height-mobile: 1.4;
  --selected-row-gap-mobile: 0.15em;
  --bio-contact-top-spacing-mobile: clamp(5rem, 12svh, 7rem);
  --bio-contact-size-mobile: var(--contact-size-mobile);
  --bio-contact-line-height-mobile: var(--contact-line-height-mobile);

  /* ================================================================
     PROJECT SCENE — the fixed halftone and corner interface stay independent.
     ================================================================ */
  --projects-layer-x: 0px;
  --projects-layer-y: 0px;
  --projects-camera-depth: 0.65;

  /* ================================================================
     CREATIVE DIRECTOR — SCENE CAMERA CONTROLS
     Keep these values small: the camera should be almost imperceptible.
     ================================================================ */
  --camera-x: 5;
  --camera-y: 4;
  --camera-strength: 1;
  --camera-response: 0.075;
  --camera-projects-x: 0px;
  --camera-projects-y: 0px;

  /* =========================================
     CREATIVE DIRECTOR — CARD DEPTH CONTROLS
     Retained for the existing card composition; hover does not alter them.
     ========================================= */
  --card-depth-z: 0px;
  --card-perspective: 1200px;
  --card-motion-smoothing: var(--motion-medium);

  /* Shadow remains intentionally disabled unless explicitly art-directed. */
  --card-shadow-opacity: 0;
  --card-shadow-blur: 30px;
  --card-shadow-y: 16px;
  --card-shadow-spread: -10px;

  /* ================================================================
     MOTION SYSTEM — every CSS animation uses this shared vocabulary
     ================================================================ */
  --motion-fast: 100ms;
  --motion-medium: 600ms;
  --motion-slow: 1200ms;
  --ease-standard: cubic-bezier(0.22, 0.7, 0.2, 1);
  --ease-quiet: ease;
  --ease-enter: ease-out;
  --ease-return: ease-in-out;

  /* INTERNAL LAYOUT + TEXT ALIASES */
  --ink: var(--page-text);
  --room-gutter: clamp(1.25rem, 2.6vw, 2.5rem);
  --project-left-edge-offset: clamp(0rem, 4vw, 4.5rem);

  /* ================================================================
     CATALOG DEFAULT — used automatically by IDs without custom controls
     ================================================================ */
  --catalog-default-x: 0px;
  --catalog-default-y: 0px;
  --catalog-default-width: clamp(22rem, 42vw, 41rem);
  --catalog-default-rotation: 0deg;
  --catalog-default-depth: 0px;
  --catalog-default-scale: 1;
  --catalog-default-spacing: 16svh;

  /* Optional project copy defaults; project.css may override public names. */
  --catalog-default-project-copy-width: 100%;
  --catalog-default-project-copy-align: start;
  --catalog-default-project-copy-gap: 10px;
  --project-title-font:
    var(--font-featured-project-title, Arial, Helvetica, sans-serif);
  --catalog-default-project-title-size: 10px;
  --catalog-default-project-title-line-height: normal;
  /* One mobile title rhythm control; a project may override this variable. */
  --project-title-line-height-mobile: 0.88;
  --catalog-default-project-title-letter-spacing: 0em;
  --catalog-default-project-title-align: left;
  --catalog-default-project-title-width: 100%;
  --catalog-default-project-title-description-gap: 5px;
  --project-description-font:
    var(--font-featured-project-subtitle, Georgia, serif);
  --catalog-default-project-description-size: 8px;
  --catalog-default-project-description-line-height: 1.35;
  --catalog-default-project-description-letter-spacing: 0em;
  --catalog-default-project-description-align: left;
  --catalog-default-project-description-width: 100%;
  --catalog-default-copy-gradient-angle: 30deg;
  --catalog-default-copy-gradient-1: currentColor;
  --catalog-default-copy-gradient-2: currentColor;
  --catalog-default-copy-gradient-3: currentColor;

}

* {
  box-sizing: border-box;
}

html {
  min-height: 100%;
  min-height: 100dvh;
  scroll-behavior: smooth;
  background-color: var(--page-bg);
}

body {
  min-height: 100vh;
  min-height: 100dvh;
  margin: 0;
  isolation: isolate;
  overflow-x: hidden;
  background-color: var(--page-bg);
  color: var(--ink);
  font-family: var(--font-body, Arial, Helvetica, sans-serif);
  transition: color var(--motion-medium) var(--ease-quiet);
}

body.gallery-open {
  overflow: hidden;
}

a {
  color: inherit;
}

/*
 * Fixed viewport environment: deliberately outside the perspective scene.
 * viewport-fit=cover makes inset: 0 bleed behind iPhone safe areas; content
 * keeps its existing spacing because no safe-area padding is introduced.
 */
.dot-matrix-layer {
  position: fixed;
  z-index: 0;
  inset: 0;
  width: 100vw;
  height: 100vh;
  height: 100dvh;
  min-height: 100dvh;
  overflow: hidden;
  background: #000000;
  isolation: isolate;
  opacity: var(--dot-matrix-opacity);
  pointer-events: none;
}

.dot-matrix-layer::after {
  position: absolute;
  z-index: 1;
  inset: 0;
  background: var(--landing-dim-color);
  content: "";
  opacity: clamp(0, var(--landing-default-dim), 1);
  pointer-events: none;
  transition:
    opacity var(--landing-dim-transition-duration)
    var(--landing-dim-transition-easing);
}

body.landing-card-hover .dot-matrix-layer::after {
  opacity: clamp(0, var(--landing-hover-dim), 1);
}

body.archive-reading .dot-matrix-layer::after {
  opacity: clamp(0, var(--archive-section-dim), 1);
}

.dot-matrix {
  position: absolute;
  z-index: 0;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  background: #000000;
}

/* MOBILE SAFARI VIEWPORT STABILITY
   100dvh follows every address-bar movement and stretches the existing Canvas
   bitmap before its backing geometry catches up. A large-viewport-height layer
   stays physically stable while browser chrome expands/collapses; the visible
   viewport simply reveals a different portion of the same composition. */
@media (max-width: 640px) {
  .dot-matrix-layer {
    top: 0;
    right: 0;
    bottom: auto;
    left: 0;
    height: 100vh;
    height: 100lvh;
    min-height: 100vh;
    min-height: 100lvh;
  }
}

/* REQUEST 077 — opt-in physical-iPhone diagnostics (?debugHalftone=1). */
.halftone-debug-panel {
  position: fixed;
  z-index: 9999;
  top: calc(8px + env(safe-area-inset-top));
  left: calc(8px + env(safe-area-inset-left));
  max-width:
    calc(100vw - 16px - env(safe-area-inset-left) - env(safe-area-inset-right));
  max-height:
    calc(100dvh - 16px - env(safe-area-inset-top) - env(safe-area-inset-bottom));
  margin: 0;
  padding: 8px;
  overflow: hidden;
  border: 1px solid rgb(255 255 255 / 45%);
  background: rgb(0 0 0 / 86%);
  color: #ffffff;
  font: 9px/1.3 ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
  letter-spacing: 0;
  white-space: pre-wrap;
  pointer-events: none;
}

/* ================================================================
   CORNER INTERFACE
   A fixed, safe-area-aware HTML layer independent from the Canvas renderer.
   ================================================================ */
.corner-interface {
  position: fixed;
  z-index: 20;
  inset: 0;
  color: var(--corner-interface-color);
  opacity: var(--corner-interface-opacity);
  pointer-events: none;
  visibility: visible;
  transition:
    color var(--motion-medium) var(--ease-quiet),
    opacity var(--project-area-interface-duration)
    var(--project-area-interface-easing),
    visibility 0s linear 0s;
}

body.projects-in-view .corner-interface {
  opacity: 0;
  visibility: hidden;
  transition:
    color var(--motion-medium) var(--ease-quiet),
    opacity var(--project-area-interface-duration)
    var(--project-area-interface-easing),
    visibility 0s linear var(--project-area-interface-duration);
}

.corner-signature,
.corner-contact {
  position: absolute;
  margin: 0;
}

.corner-signature {
  top: calc(var(--corner-signature-y) + env(safe-area-inset-top));
  left: calc(var(--corner-signature-x) + env(safe-area-inset-left));
  display: block;
  width: var(--corner-signature-width);
  max-width:
    calc(100vw - var(--corner-signature-x) - var(--corner-signature-x));
  height: auto;
  opacity: var(--corner-signature-opacity);
  transform: rotate(var(--corner-signature-rotation));
  transform-origin: center;
}

.corner-contact {
  right: calc(var(--contact-x) + env(safe-area-inset-right));
  bottom: calc(var(--contact-y) + env(safe-area-inset-bottom));
  display: flex;
  flex-wrap: wrap;
  max-width: var(--contact-max-width);
  align-items: baseline;
  justify-content: flex-end;
  gap: var(--contact-gap);
  font-family: var(--contact-font);
  font-size: var(--contact-size);
  font-style: normal;
  font-weight: 400;
  line-height: var(--contact-line-height);
  letter-spacing: var(--contact-letter-spacing);
  text-align: var(--contact-align);
  text-transform: none;
  white-space: normal;
}

.corner-contact a {
  color: inherit;
  pointer-events: auto;
  text-decoration: none;
}

.corner-contact a:focus-visible {
  outline: 1px solid currentColor;
  outline-offset: 4px;
}

/* Row wrappers are layout-neutral on desktop so the approved single-line
   contact composition remains exactly the same. */
.contact-row {
  display: contents;
}

.site-content {
  position: relative;
  z-index: 10;
}

/*
   * LAYER CONTRACT
   * Persistent dot matrix 0 / content 10 / corner interface 20.
   * Card perspective remains local to project images; the shared scene is flat.
   */
.scene {
  perspective: none;
  transform-style: flat;
}

/* One empty sticky viewport establishes the quiet entrance. */
.opening {
  position: sticky;
  top: 0;
  z-index: 2;
  height: 100svh;
  background: transparent;
  transform-style: flat;
}

.opening__frame {
  position: relative;
  height: 100svh;
  padding: var(--room-gutter);
  overflow: hidden;
}

.projects {
  position: relative;
  z-index: 10;
  min-height: 560svh;
  margin-top: -8svh;
  padding: 20svh var(--room-gutter) 34svh;
  transform-style: flat;
  transform: translate3d(
    calc(var(--projects-layer-x) + var(--camera-projects-x)),
    calc(var(--projects-layer-y) + var(--camera-projects-y)),
    0
  );
  transition: transform var(--motion-slow) var(--ease-standard);
}

/* Layout-neutral on desktop; mobile promotes each wrapper to a stack interval. */
.project-scene {
  display: contents;
}

/* Three anchors establish composition; project variables control every size. */
.project {
  --card-current-tilt-x: 0deg;
  --card-current-tilt-y: 0deg;
  --card-current-shift-x: 0px;
  --card-current-shift-y: 0px;
  --card-current-scale: 1;
  --project-default-x: var(--catalog-default-x);
  --project-default-y: var(--catalog-default-y);
  --project-default-width: var(--catalog-default-width);
  --project-default-rotation: var(--catalog-default-rotation);
  --project-default-depth: var(--catalog-default-depth);
  --project-default-scale: var(--catalog-default-scale);
  --project-default-gap: var(--catalog-default-spacing);

  /* Public project.css controls feed the reusable card implementation. */
  --project-x: var(--card-x, var(--project-default-x));
  --project-y: var(--card-y, var(--project-default-y));
  --project-width: var(--card-width, var(--project-default-width));
  --project-rotation: var(--card-rotation, var(--project-default-rotation));
  --project-depth: var(--card-scene-depth, var(--project-default-depth));
  --project-scale: var(--card-scale, var(--project-default-scale));
  --project-gap: var(--card-spacing, var(--project-default-gap));
  appearance: none;
  position: relative;
  z-index: var(--card-z-index, 1);
  display: grid;
  margin-top: var(--project-gap);
  padding: 0;
  width: var(--project-width);
  border: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  text-align: inherit;
  text-decoration: none;
  transform: translate3d(var(--project-x), var(--project-y), var(--project-depth)) rotate(var(--project-rotation)) scale(var(--project-scale));
  transform-origin: center;
  transform-style: flat;
  transition:
    color var(--motion-medium) var(--ease-quiet),
    opacity var(--motion-medium) var(--ease-quiet),
    transform var(--motion-medium) var(--ease-standard);
}

.project[data-gallery] {
  cursor: pointer;
}

/* The mobile feed is absent from desktop layout and stacking. */
.mobile-project-feed {
  display: none;
}

/* Physical-Safari diagnostics remain absent unless the mobile debug query is on. */
.mobile-grid-debug {
  display: none;
}

.project-scene:first-child .project {
  margin-top: 0;
}

/* ================================================================
   AUTOMATIC ARCHIVE
   The same catalog and gallery system supplies every item after the newest five.
   ================================================================ */
.archive {
  position: relative;
  z-index: 10;
  padding-top: var(--archive-section-padding-top);
  padding-right: var(--archive-section-padding-inline);
  padding-bottom: var(--archive-section-padding-bottom);
  padding-left:
    calc(var(--archive-section-padding-inline) + var(--archive-left-offset));
  overflow: visible;
  color: var(--ink);
}

.archive[hidden] {
  display: none;
}

.archive__list {
  position: relative;
  z-index: 2;
  display: grid;
  margin: 0;
  padding: 0;
  gap: var(--archive-row-gap);
  list-style: none;
}

.archive__item {
  margin: 0;
  padding: 0;
}

.archive-entry {
  appearance: none;
  position: relative;
  display: grid;
  width: fit-content;
  max-width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  gap: var(--archive-title-subtitle-gap);
  justify-self: var(--archive-alignment);
  text-align: var(--archive-alignment);
  transform: translate3d(0, 0, 0);
  transition:
    opacity var(--archive-state-transition-duration)
      var(--archive-state-transition-easing),
    transform var(--archive-state-transition-duration)
      var(--archive-state-transition-easing);
}

.archive-entry[data-project-overview] {
  cursor: pointer;
}

.archive-entry__title {
  font-family: var(--archive-title-font);
  font-size: var(--archive-title-size);
  font-weight: 400;
  letter-spacing: var(--archive-title-letter-spacing);
  line-height: var(--archive-title-line-height);
}

.archive-entry__subtitle {
  /* Desktop Archive is a title-only index, regardless of project metadata. */
  display: none;
}

.archive.has-active-entry .archive-entry {
  opacity: var(--archive-inactive-opacity);
}

.archive.has-active-entry .archive-entry.is-active {
  opacity: var(--archive-active-opacity);
  transform: translate3d(var(--archive-active-offset-x), 0, 0);
}

/* One fixed stage; the single natural-ratio image switches without a fade. */
.archive-preview {
  appearance: none;
  -webkit-appearance: none;
  position: fixed;
  z-index: 1;
  top: 50%;
  left: 50%;
  width: var(--archive-preview-width);
  height: 0;
  opacity: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
  pointer-events: none;
  transform:
    translate3d(
      calc(-50% + var(--archive-preview-offset-x)),
      var(--archive-preview-offset-y),
      0
    )
    scale(var(--archive-preview-scale));
  transform-origin: center;
  visibility: hidden;
  transition:
    opacity var(--archive-preview-transition-duration)
      var(--archive-preview-transition-easing),
    transform var(--archive-preview-transition-duration)
      var(--archive-preview-transition-easing),
    visibility 0s linear var(--archive-preview-transition-duration);
}

/* Exit-to-Bio only; cover-to-cover source changes remain immediate. */
.archive-preview.is-exiting-to-bio {
  transform:
    translate3d(
      calc(-50% + var(--archive-preview-offset-x)),
      calc(
        var(--archive-preview-offset-y) +
          var(--archive-preview-exit-translate-y)
      ),
      0
    )
    scale(var(--archive-preview-scale));
  transition:
    opacity var(--archive-preview-exit-duration)
      var(--archive-preview-exit-easing),
    transform var(--archive-preview-exit-duration)
      var(--archive-preview-exit-easing),
    visibility 0s linear var(--archive-preview-exit-duration);
}

.archive-preview.is-visible {
  opacity: var(--archive-preview-opacity);
  pointer-events: auto;
  visibility: visible;
  transition:
    opacity var(--archive-preview-transition-duration)
      var(--archive-preview-transition-easing),
    transform var(--archive-preview-exit-duration)
      var(--archive-preview-exit-easing),
    visibility 0s linear 0s;
}

.archive-preview__image {
  position: absolute;
  top: 0;
  left: 0;
  display: block;
  width: 100%;
  max-width: 100%;
  height: auto;
  opacity: 1;
  object-fit: contain;
  object-position: center;
  transform:
    translateY(-50%)
    scale(var(--archive-preview-scale-multiplier));
  transform-origin: center;
}

.archive-preview:focus-visible {
  outline: 1px solid currentColor;
  outline-offset: 6px;
}

/* ================================================================
   WHITE END SECTION
   An opaque, full-width physical boundary in normal scroll flow. No fade.
   ================================================================ */
.bio-section {
  position: relative;
  /* Archive is layer 10; this opaque surface passes beneath its preview/type. */
  z-index: 9;
  display: flex;
  flex-direction: column;
  width: 100%;
  min-height: var(--bio-section-min-height);
  padding-top:
    calc(var(--bio-section-spacing-top) + env(safe-area-inset-top));
  padding-right: calc(var(--room-gutter) + env(safe-area-inset-right));
  padding-bottom:
    calc(var(--bio-section-spacing-bottom) + env(safe-area-inset-bottom));
  padding-left:
    calc(
      var(--room-gutter) + var(--archive-left-offset) +
      env(safe-area-inset-left)
    );
  background-color: var(--bio-section-background);
  color: var(--bio-section-color);
}

.bio-section [hidden] {
  display: none;
}

.mobile-persistent-signature {
  display: none;
}

.bio-section__grid {
  display: grid;
  grid-template-columns:
    var(--bio-column-bio-width) var(--bio-column-selected-width);
  gap: var(--bio-column-gap);
}

.bio-section__bio,
.bio-section__selected {
  min-width: 0;
}

.bio-section__label,
.bio-section__heading,
.bio-section__copy,
.bio-section__copy p,
.bio-section__selected-list,
.bio-section__contact {
  margin: 0;
}

.bio-section__label {
  margin-bottom: var(--bio-label-bottom-spacing);
  font-family: var(--bio-label-font);
  font-size: var(--bio-label-size);
  font-weight: 400;
  line-height: var(--bio-label-line-height);
}

.bio-section__heading,
.bio-section__copy {
  max-width: var(--bio-max-width);
  font-family: var(--bio-font);
  font-size: var(--bio-size);
  font-weight: 400;
  line-height: var(--bio-line-height);
}

.bio-section__heading {
  margin-bottom: var(--bio-paragraph-gap);
}

.bio-section__copy {
  display: grid;
  gap: var(--bio-paragraph-gap);
}

.bio-section__placeholder-note {
  opacity: 0.5;
}

.bio-section__selected-list {
  display: grid;
  padding: 0;
  gap: var(--selected-row-gap);
  font-family: var(--selected-font);
  font-size: var(--selected-size);
  font-weight: 400;
  line-height: var(--selected-line-height);
  list-style: none;
}

.bio-section__contact {
  display: flex;
  flex-wrap: wrap;
  margin-top: auto;
  padding-top: var(--bio-contact-top-spacing);
  align-items: baseline;
  gap: var(--bio-contact-gap);
  font-family: var(--bio-contact-font);
  font-size: var(--bio-contact-size);
  font-style: normal;
  font-weight: 400;
  line-height: var(--bio-contact-line-height);
  white-space: normal;
}

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

.bio-section__contact a:focus-visible {
  outline: 1px solid currentColor;
  outline-offset: 4px;
}

.archive-entry[data-gallery]:focus-visible {
  outline: 1px solid currentColor;
  outline-offset: 6px;
}

.project--left {
  margin-right: auto;
  margin-left: var(--project-left-edge-offset);
}

.project--right {
  margin-right: clamp(0rem, 5vw, 5.5rem);
  margin-left: auto;
}

.project--center {
  margin-right: auto;
  margin-left: auto;
}

.project__image {
  position: relative;
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: center;
  /* Zero-width border is intentional: hover adds only the paper-like edge. */
  border: 0 solid rgba(0, 0, 0, 0.95);
  box-shadow:
    0 var(--card-shadow-y) var(--card-shadow-blur) var(--card-shadow-spread)
    rgb(0 0 0 / var(--card-shadow-opacity));
  transform:
    perspective(var(--card-perspective))
    translate3d(
      var(--card-current-shift-x),
      var(--card-current-shift-y),
      var(--card-depth-z)
    )
    rotateX(var(--card-current-tilt-x))
    rotateY(var(--card-current-tilt-y))
    scale(var(--card-current-scale));
  transform-origin: center;
  transform-style: preserve-3d;
  transition:
    box-shadow var(--card-motion-smoothing) var(--ease-standard),
    transform var(--card-motion-smoothing) var(--ease-standard);
}

.project__image img {
  display: block;
  width: 100%;
  max-width: 100%;
  height: auto;
  margin-inline: auto;
  object-fit: contain;
  object-position: center;
}

/* Optional projects.json copy; absent content creates no spacing. */
.project-copy {
  display: grid;
  justify-self:
    var(--project-copy-align, var(--catalog-default-project-copy-align));
  width:
    var(--project-copy-width, var(--catalog-default-project-copy-width));
  min-width: 0;
  max-width: 100%;
  margin-top:
    var(--project-copy-gap, var(--catalog-default-project-copy-gap));
  gap:
    var(
      --project-title-description-gap,
      var(--catalog-default-project-title-description-gap)
    );
  font-weight: 400;
}

.project-copy__title,
.project-copy__subtitle,
.project-copy__description {
  display: block;
  min-width: 0;
  max-width: 100%;
  background-image:
    linear-gradient(
      var(--copy-gradient-angle, var(--catalog-default-copy-gradient-angle)),
      var(--copy-gradient-1, var(--catalog-default-copy-gradient-1)),
      var(--copy-gradient-2, var(--catalog-default-copy-gradient-2)),
      var(
        --copy-gradient-3,
        var(--copy-gradient-2, var(--catalog-default-copy-gradient-3))
      )
    );
  background-clip: text;
  color: transparent;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

.project-copy__title {
  width:
    var(--project-title-width, var(--catalog-default-project-title-width));
  font-family: var(--project-title-font, var(--font-body));
  font-synthesis: none;
  font-size:
    var(--project-title-size, var(--catalog-default-project-title-size));
  font-weight: 400;
  line-height:
    var(
      --project-title-line-height,
      var(--catalog-default-project-title-line-height)
    );
  letter-spacing:
    var(
      --project-title-letter-spacing,
      var(--catalog-default-project-title-letter-spacing)
    );
  text-align:
    var(--project-title-align, var(--catalog-default-project-title-align));
}

.project .project-copy__subtitle,
.project .project-copy__description {
  /* Featured copy remains visible. Archive entries use separate title-only
     markup and never receive these project-copy elements. */
  display: block;
  width:
    var(
      --project-description-width,
      var(--catalog-default-project-description-width)
    );
  font-family: var(--project-description-font, var(--font-body));
  font-style: italic;
  font-synthesis: none;
  font-size:
    var(
      --project-description-size,
      var(--catalog-default-project-description-size)
    );
  font-weight: 300;
  line-height:
    var(
      --project-description-line-height,
      var(--catalog-default-project-description-line-height)
    );
  letter-spacing:
    var(
      --project-description-letter-spacing,
      var(--catalog-default-project-description-letter-spacing)
    );
  text-align:
    var(
      --project-description-align,
      var(--catalog-default-project-description-align)
    );
  text-transform: none;
}

@media (hover: hover) and (pointer: fine) {
  .project:hover .project__image {
    --card-current-scale: var(--card-hover-scale);
  }
}

.project:focus-visible .project__image {
  --card-current-scale: var(--card-hover-scale);
}

/* Restored gallery focus remains accessible without preserving hover scale. */
.project.is-gallery-return-focus:focus-visible .project__image {
  --card-current-scale: 1;
}

.project:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 6px;
}

/* ================================================================
   FULL-SCREEN PROJECT GALLERY
   A single fixed room is populated from the JavaScript gallery data.
   ================================================================ */
.gallery-overlay {
  position: fixed;
  z-index: 100;
  inset: 0;
  display: grid;
  width: 100vw;
  height: 100vh;
  height: 100dvh;
  margin: 0;
  overflow: hidden;
  background: var(--gallery-overlay-bg);
  color: var(--gallery-overlay-ink);
  opacity: 0;
  pointer-events: none;
  visibility: hidden;
  transition:
    opacity var(--gallery-close-duration) var(--ease-return),
    visibility 0s linear var(--gallery-close-duration);
}

.gallery-overlay[hidden],
.gallery-overlay [hidden] {
  display: none;
}

.gallery-overlay.is-open {
  opacity: 1;
  pointer-events: auto;
  visibility: visible;
  transition:
    opacity var(--gallery-open-duration) var(--ease-enter),
    visibility 0s linear 0s;
}

.gallery-overlay__overview {
  position: absolute;
  z-index: 3;
  inset: 0;
  display: grid;
  box-sizing: border-box;
  width: 100%;
  max-width: var(--gallery-overview-max-width);
  height: 100%;
  max-height: 100%;
  margin: 0 auto;
  padding:
    var(--gallery-overview-padding-block)
    var(--gallery-overview-padding-inline);
  grid-template-columns: minmax(0, var(--gallery-overview-copy-column-width));
  align-items: center;
  column-gap: var(--gallery-overview-column-gap);
  justify-content: space-between;
  overflow: auto;
  overscroll-behavior: contain;
}

.gallery-overlay__overview.has-thumbnails {
  grid-template-columns:
    minmax(0, var(--gallery-overview-copy-column-width))
    minmax(15rem, var(--gallery-overview-thumbnail-column-width));
}

.gallery-overlay__overview-copy {
  display: grid;
  min-width: 0;
  gap: var(--gallery-overview-copy-gap);
}

.gallery-overlay__overview-title,
.gallery-overlay__overview-description {
  margin: 0;
}

.gallery-overlay__overview-title {
  font-family: var(--font-featured-project-title, var(--font-ui));
  font-size: var(--gallery-overview-title-size);
  font-weight: 400;
  letter-spacing: 0;
  line-height: var(--gallery-overview-title-line-height);
  overflow-wrap: anywhere;
}

.gallery-overlay__overview-description {
  max-width: var(--gallery-overview-copy-width);
  font-family: var(--font-featured-project-subtitle, var(--font-ui));
  font-size: var(--gallery-overview-description-size);
  font-weight: 400;
  line-height: var(--gallery-overview-description-line-height);
  opacity: 0.72;
  white-space: pre-line;
}

.gallery-overlay__overview-description:empty {
  display: none;
}

.gallery-overlay__overview-next {
  appearance: none;
  -webkit-appearance: none;
  justify-self: start;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
  font: inherit;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  opacity: 0.65;
  transition: opacity var(--motion-fast) var(--ease-quiet);
}

.gallery-overlay__overview-next:is(:hover, :focus-visible) {
  opacity: 1;
}

.gallery-overlay__overview-next:focus-visible {
  outline: 1px solid currentColor;
  outline-offset: 4px;
}

.gallery-overlay__overview-media {
  position: relative;
  box-sizing: border-box;
  min-width: 0;
  padding-left: var(--gallery-overview-divider-padding);
}

.gallery-overlay__overview-media::before {
  position: absolute;
  top: 50%;
  left: 0;
  width: 1px;
  height: var(--gallery-overview-divider-height);
  background: var(--gallery-overview-divider-color);
  content: "";
  transform: translateY(-50%);
}

.gallery-overlay__overview-thumbnails {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gallery-overview-thumbnail-gap);
}

.gallery-overlay__overview-thumbnail {
  appearance: none;
  -webkit-appearance: none;
  display: grid;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
  place-items: center;
}

.gallery-overlay__overview-thumbnail img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 8rem;
  object-fit: contain;
}

.gallery-overlay__overview-thumbnail:focus-visible {
  outline: 1px solid currentColor;
  outline-offset: 4px;
}

@media (min-width: 1200px) {
  .gallery-overlay__overview.has-thumbnails {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 0;
    justify-content: stretch;
  }

  .gallery-overlay__overview-copy {
    box-sizing: border-box;
    padding-right: var(--gallery-overview-divider-padding);
  }

  .gallery-overlay__overview-thumbnails {
    grid-template-columns: repeat(
      var(--gallery-overview-desktop-thumbnail-columns),
      minmax(0, 1fr)
    );
    gap: var(--gallery-overview-desktop-thumbnail-gap);
  }

  .gallery-overlay__overview-thumbnail img {
    max-height: var(--gallery-overview-desktop-thumbnail-max-height);
  }
}

.gallery-overlay__viewport {
  position: absolute;
  z-index: 3;
  inset: 0;
  display: grid;
  padding: clamp(4.75rem, 9vh, 7rem) clamp(4rem, 9vw, 9rem);
  place-items: center;
  pointer-events: none;
  touch-action: none;
}

.gallery-overlay__artwork {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  margin: 0;
  overflow: hidden;
}

.gallery-overlay__image {
  position: absolute;
  inset: 0;
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 100%;
  margin: auto;
  opacity: 0;
  object-fit: contain;
  pointer-events: none;
  transform-origin: center;
  transform: translate3d(0, 4px, 0);
  transition:
    opacity var(--gallery-image-transition-duration) var(--ease-standard),
    transform var(--gallery-image-transition-duration) var(--ease-standard);
}

.gallery-overlay__image.is-active {
  opacity: 1;
  transform: translate3d(0, 0, 0);
}

.gallery-overlay__video {
  position: absolute;
  z-index: 3;
  inset: 0;
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 100%;
  margin: auto;
  opacity: 0;
  object-fit: contain;
  pointer-events: none;
  transform-origin: center;
  transform: translate3d(0, 4px, 0);
  transition:
    opacity var(--gallery-image-transition-duration) var(--ease-standard),
    transform var(--gallery-image-transition-duration) var(--ease-standard);
}

.gallery-overlay__video.is-active {
  opacity: 1;
  pointer-events: auto;
  transform: translate3d(0, 0, 0);
}

.gallery-overlay__caption {
  position: fixed;
  z-index: 3;
  top:
    calc(
      var(--gallery-caption-rendered-top, 0px) +
      var(--gallery-caption-gap)
    );
  left: var(--gallery-caption-rendered-left, 0px);
  box-sizing: border-box;
  width: min(var(--gallery-caption-rendered-width, 100%), 100%);
  max-width: min(var(--gallery-caption-max-width), 100%);
  margin: 0;
  color: inherit;
  font-family: var(--font-ui);
  font-size: var(--gallery-caption-size);
  font-weight: 400;
  line-height: var(--gallery-caption-line-height);
  text-align: left;
  opacity: var(--gallery-caption-opacity);
  overflow-wrap: anywhere;
  pointer-events: none;
  visibility: hidden;
}

.gallery-overlay__caption.is-positioned {
  visibility: visible;
}

.gallery-overlay__close,
.gallery-overlay__nav {
  border: 0;
  border-radius: 0;
  background: transparent;
  color: inherit;
  font: inherit;
}

.gallery-overlay__close {
  position: absolute;
  z-index: 4;
  top: var(--room-gutter);
  right: var(--room-gutter);
  padding: 0.45rem;
  cursor: pointer;
  font-family: var(--font-ui);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
}

.gallery-overlay__nav {
  position: absolute;
  z-index: 2;
  top: 0;
  bottom: 0;
  width: 50vw;
  padding: var(--room-gutter);
  cursor: pointer;
  font-family: var(--font-ui);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
}

.gallery-overlay__nav span {
  position: absolute;
  top: 50%;
  opacity: 0.45;
  transform: translateY(-50%);
  white-space: nowrap;
  transition: opacity var(--motion-fast) var(--ease-quiet);
}

.gallery-overlay__nav--previous {
  left: 0;
  cursor: w-resize;
}

.gallery-overlay__nav--previous span {
  left: var(--room-gutter);
}

.gallery-overlay__nav--next {
  right: 0;
  cursor: e-resize;
}

.gallery-overlay__nav--next span {
  right: var(--room-gutter);
}

.gallery-overlay__nav:is(:hover, :focus-visible) span {
  opacity: 1;
}

.gallery-overlay__close:focus-visible,
.gallery-overlay__nav:focus-visible {
  outline: 1px solid currentColor;
  outline-offset: -4px;
}

.gallery-overlay__status {
  position: absolute;
  z-index: 4;
  bottom: var(--room-gutter);
  left: var(--room-gutter);
  margin: 0;
  font-family: var(--font-ui);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
}

.screen-reader-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

@media (max-width: 760px) {
  :root {
    --catalog-default-width: min(78vw, 31rem);
    --catalog-default-spacing: 16svh;
    --project-left-edge-offset: 2vw;
  }

  .project--left,
  .project--center {
    margin-right: auto;
    margin-left: var(--project-left-edge-offset);
  }

  .project--right {
    margin-right: 2vw;
    margin-left: auto;
  }

}

@media (max-width: 600px) {
  :root {
    /* CORNER INTERFACE — independent mobile composition */
    --corner-signature-width: var(--corner-signature-width-mobile);
    --corner-signature-x: var(--corner-signature-x-mobile);
    --corner-signature-y: var(--corner-signature-y-mobile);
    --contact-font: var(--contact-font-mobile);
    --contact-size: var(--contact-size-mobile);
    --contact-line-height: var(--contact-line-height-mobile);
    --contact-letter-spacing: var(--contact-letter-spacing-mobile);
    --contact-gap: var(--contact-link-gap-mobile);
    --contact-align: var(--contact-align-mobile);
    --contact-x: var(--contact-x-mobile);
    --contact-y: var(--contact-y-mobile);
    --contact-max-width: var(--contact-max-width-mobile);

    --archive-section-padding-top: var(--archive-section-padding-top-mobile);
    --archive-section-padding-bottom: var(--archive-section-padding-bottom-mobile);
    --archive-row-gap: var(--archive-row-gap-mobile);
    --archive-title-subtitle-gap: var(--archive-title-subtitle-gap-mobile);
    --archive-title-size: var(--archive-title-size-mobile);
    --archive-title-line-height: var(--archive-title-line-height-mobile);
    --archive-title-letter-spacing: var(--archive-title-letter-spacing-mobile);
    --archive-subtitle-size: var(--archive-subtitle-size-mobile);
    --archive-subtitle-line-height: var(--archive-subtitle-line-height-mobile);
    --archive-subtitle-letter-spacing:
      var(--archive-subtitle-letter-spacing-mobile);
    --archive-active-offset-x: var(--archive-active-offset-x-mobile);
    --archive-inactive-opacity: var(--archive-inactive-opacity-mobile);
    --project-left-edge-offset: 0px;

    --catalog-default-width: min(84vw, 24rem);
  }

  html,
  body {
    background: #000000;
  }

  /* Mobile Request 085 never initializes the renderer; hiding its inert DOM
     shell also guarantees that no Canvas surface enters compositing. */
  .dot-matrix-layer {
    display: none;
  }

  /* The feed is ordinary document flow. It never pins the page, owns scrolling,
     or creates a mobile Canvas/compositor surface. */
  html.mobile-project-feed-enabled,
  html.mobile-project-feed-enabled body {
    min-height: 100%;
    /* `hidden` creates a non-scrolling overflow ancestor and disables sticky
       descendants in Safari. `clip` preserves the horizontal boundary without
       stealing the viewport's vertical sticky reference. */
    overflow-x: clip;
    background-color: #000000;
  }

  /* One non-interactive CSS layer supplies the mobile atmosphere. Its oversized
     bounds absorb blur and drift without exposing an edge during Safari scroll. */
  html.mobile-project-feed-enabled body::before {
    position: fixed;
    z-index: 0;
    inset: -18vmax;
    background:
      radial-gradient(
        ellipse 72% 62% at 16% 18%,
        rgb(112 67 91 / 88%) 0%,
        rgb(112 67 91 / 0%) 72%
      ),
      radial-gradient(
        ellipse 66% 74% at 88% 40%,
        rgb(63 82 116 / 82%) 0%,
        rgb(63 82 116 / 0%) 74%
      ),
      radial-gradient(
        ellipse 76% 64% at 42% 88%,
        rgb(116 73 48 / 76%) 0%,
        rgb(116 73 48 / 0%) 72%
      ),
      linear-gradient(145deg, rgb(53 40 68 / 45%), rgb(23 35 48 / 20%));
    content: "";
    filter: blur(var(--mobile-gradient-blur));
    opacity: var(--mobile-gradient-opacity);
    pointer-events: none;
    transform: translate3d(-1.5%, -1%, 0) scale(1.04);
    transform-origin: center;
    animation:
      mobile-gradient-drift var(--mobile-gradient-speed) ease-in-out infinite;
  }

  html.mobile-project-feed-enabled .corner-interface {
    display: none;
  }

  html.mobile-project-feed-enabled .mobile-persistent-signature {
    position: fixed;
    z-index: var(--mobile-signature-z-index);
    top: calc(var(--mobile-signature-top) + env(safe-area-inset-top));
    left: calc(var(--mobile-signature-left) + env(safe-area-inset-left));
    display: block;
    width: min(
      var(--mobile-signature-width),
      calc(
        100vw - var(--mobile-signature-left) -
        env(safe-area-inset-left) - env(safe-area-inset-right)
      )
    );
    aspect-ratio: 5 / 1;
    background-color: var(--mobile-signature-color);
    opacity: var(--mobile-signature-opacity);
    pointer-events: none;
    -webkit-mask:
      url("assets/signatures/Leo_signat.png") center / contain no-repeat;
    mask:
      url("assets/signatures/Leo_signat.png") center / contain no-repeat;
  }

  html.mobile-project-feed-enabled .opening,
  html.mobile-project-feed-enabled .projects,
  html.mobile-project-feed-enabled .archive {
    display: none;
  }

  /* Shared two-row contact presentation. Each row remains intact at normal
     mobile widths and may wrap internally only when avoiding real overflow. */
  .corner-contact,
  .bio-section__contact {
    display: grid;
    max-width:
      min(
        var(--contact-max-width),
        calc(
          100vw - var(--contact-x) - var(--contact-x) -
          env(safe-area-inset-left) - env(safe-area-inset-right)
        )
      );
    align-items: baseline;
    justify-content: normal;
    justify-items: var(--contact-align-mobile);
    gap: var(--contact-row-gap-mobile) 0;
    text-align: var(--contact-align-mobile);
  }

  .contact-row {
    display: flex;
    flex-wrap: wrap;
    width: max-content;
    max-width:
      calc(
        100vw - var(--contact-x) - var(--contact-x) -
        env(safe-area-inset-left) - env(safe-area-inset-right)
      );
    align-items: baseline;
    justify-content: var(--contact-align-mobile);
    column-gap: var(--contact-link-gap-mobile);
    row-gap: calc(var(--contact-row-gap-mobile) / 2);
  }

  .contact-row a {
    white-space: nowrap;
  }

  .mobile-project-feed {
    position: relative;
    z-index: 10;
    display: block;
    box-sizing: border-box;
    width: 100%;
    padding:
      var(--mobile-project-feed-top-padding)
      0
      var(--mobile-project-feed-bottom-padding);
    background: transparent;
    color: #ffffff;
    isolation: isolate;
  }

  .mobile-project-feed__list {
    display: flex;
    width: 100%;
    flex-direction: column;
    gap: var(--mobile-project-gap);
  }

  .mobile-project-feed__project,
  .mobile-project-feed__content,
  .mobile-project-feed__media,
  .mobile-project-feed__copy {
    display: block;
    box-sizing: border-box;
    width: 100%;
    margin: 0;
  }

  /* Each Featured article owns one full-bleed, cover-derived dark environment.
     The pseudo-element's opacity never affects its artwork or typography. */
  .mobile-project-feed__list > .mobile-project-feed__project {
    /* Palette values terminate at each project article. These local defaults
       prevent a stale/shared ancestor value from recoloring sibling cards. */
    --mobile-project-background: var(--mobile-project-fallback-background);
    --mobile-project-title-color: var(--mobile-project-fallback-title);
    --mobile-project-description-color:
      var(--mobile-project-fallback-description);
    position: relative;
    padding-top: var(--mobile-featured-padding-top);
    padding-bottom: var(--mobile-featured-padding-bottom);
    background: var(--mobile-project-background-base);
    isolation: isolate;
  }

  .mobile-project-feed__list > .mobile-project-feed__project:first-child {
    padding-top:
      calc(
        var(--mobile-featured-padding-top) +
        var(--mobile-signature-opening-space) +
        env(safe-area-inset-top)
      );
  }

  .mobile-project-feed__list > .mobile-project-feed__project::before {
    position: absolute;
    z-index: 0;
    inset: 0;
    background: var(
      --mobile-project-background,
      var(--mobile-project-fallback-background)
    );
    content: "";
    opacity: 1;
    pointer-events: none;
  }

  /* Cover, miniatures and copy share this one ordinary document grid. */
  .mobile-project-feed__content {
    position: relative;
    z-index: 1;
    padding-inline: var(--mobile-project-side-inset);
  }

  .mobile-project-feed__media {
    position: relative;
    z-index: 1;
    max-width: 100%;
    line-height: 0;
  }

  .mobile-project-feed__cover-button {
    appearance: none;
    -webkit-appearance: none;
    position: relative;
    display: block;
    width: 100%;
    max-width: 100%;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    opacity: 1;
    line-height: 0;
    text-align: left;
  }

  .mobile-project-feed__cover-button:not(:disabled) {
    cursor: pointer;
  }

  .mobile-project-feed__cover-button:focus-visible,
  .mobile-project-feed__gallery-miniature:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 2px;
  }

  .mobile-project-feed__gallery-miniatures {
    display: flex;
    width: 100%;
    max-width: 100%;
    flex-wrap: wrap;
    align-items: center;
    column-gap: var(--mobile-gallery-thumb-column-gap);
    row-gap: var(--mobile-gallery-thumb-row-gap);
    margin-top: var(--mobile-gallery-thumb-margin-top);
  }

  .mobile-project-feed__gallery-miniatures[hidden] {
    display: none;
  }

  .mobile-project-feed__gallery-miniature {
    appearance: none;
    display: flex;
    width: auto;
    min-width: 0;
    max-width: 100%;
    height: var(--mobile-gallery-thumb-height);
    flex: 0 0 auto;
    padding: 0;
    overflow: visible;
    align-items: center;
    justify-content: center;
    border: 0;
    background: transparent;
    cursor: pointer;
    opacity: 0;
  }

  .mobile-project-feed__gallery-miniature.is-loaded {
    opacity: 1;
  }

  .mobile-project-feed__gallery-miniature-image {
    display: block;
    width: auto;
    max-width: 100%;
    height: var(--mobile-gallery-thumb-height);
    max-height: var(--mobile-gallery-thumb-height);
    object-fit: contain;
    opacity: var(--mobile-gallery-thumb-opacity);
    pointer-events: none;
  }

  .mobile-project-feed__cover {
    position: relative;
    z-index: 4;
    display: block;
    width: 100%;
    max-width: 100%;
    height: auto;
    max-height: var(--mobile-project-cover-max-height);
    object-fit: var(--mobile-project-cover-object-fit, contain);
    object-position:
      var(--mobile-project-cover-object-position-x, 50%)
      var(--mobile-project-cover-object-position-y, 50%);
    opacity: 0;
    pointer-events: none;
  }

  .mobile-project-feed__project.is-loaded .mobile-project-feed__cover {
    opacity: 1;
  }

  .mobile-project-feed__copy {
    position: relative;
    z-index: 2;
    margin-top: var(--mobile-project-title-gap);
    opacity: 1;
    pointer-events: auto;
  }

  .mobile-project-feed__title,
  .mobile-project-feed__description {
    max-width: 100%;
    margin: 0;
    text-align: left;
  }

  .mobile-project-feed__title {
    color: var(
      --mobile-project-title-color,
      var(--mobile-project-fallback-title)
    );
    font-family: var(--project-title-font, var(--font-body));
    font-size: var(--mobile-project-title-size);
    font-weight: 400;
    letter-spacing: var(--mobile-project-title-letter-spacing);
    line-height: var(--mobile-project-title-line-height);
  }

  .mobile-project-feed__title-text[hidden],
  .mobile-project-feed__title-button[hidden],
  .mobile-project-feed__title[hidden] {
    display: none;
  }

  .mobile-project-feed__title-button {
    display: inline;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    cursor: pointer;
    font: inherit;
    letter-spacing: inherit;
    text-align: inherit;
  }

  .mobile-project-feed__title-button:focus-visible {
    outline: 1px solid currentColor;
    outline-offset: 4px;
  }

  .mobile-project-feed__description {
    max-width: var(--mobile-project-description-max-width);
    margin-top: var(--mobile-project-description-gap);
    color: var(
      --mobile-project-description-color,
      var(--mobile-project-fallback-description)
    );
    font-family: var(--project-description-font, var(--font-body));
    font-size: var(--mobile-project-description-size);
    font-weight: 400;
    letter-spacing: var(--mobile-project-description-letter-spacing);
    line-height: var(--mobile-project-description-line-height);
  }

  .mobile-project-feed__description[hidden] {
    display: none;
  }

  /* The mobile Archive is a left-aligned title index. A two-layer cover frame
     remains centered below it and crossfades only when the title nearest the
     viewport center changes. */
  .mobile-project-archive {
    position: relative;
    z-index: 2;
    display: block;
    box-sizing: border-box;
    width: 100%;
    padding: var(--mobile-archive-padding-top) 0
      var(--mobile-archive-padding-bottom);
    background: var(--mobile-archive-background);
    color: #ffffff;
    isolation: isolate;
  }

  /* Featured and Archive consume the same complete build-time palette. This
     dedicated layer never changes content opacity. */
  .mobile-project-archive::before {
    position: absolute;
    z-index: 0;
    inset: 0;
    background-color: var(
      --mobile-archive-active-background,
      var(--mobile-project-fallback-background)
    );
    content: "";
    opacity: 0;
    pointer-events: none;
    transition:
      background-color var(--mobile-archive-background-transition-duration)
        var(--mobile-archive-background-transition-easing),
      opacity var(--mobile-archive-background-transition-duration)
        var(--mobile-archive-background-transition-easing);
  }

  .mobile-project-archive[hidden] {
    display: none;
  }

  .mobile-project-archive[data-active-palette] {
    background: var(--mobile-project-background-base);
  }

  .mobile-project-archive[data-active-palette]::before {
    opacity: 1;
  }

  .mobile-project-archive__heading {
    position: relative;
    z-index: 1;
    margin: 0;
    margin-bottom: var(--mobile-archive-heading-gap);
    padding-right:
      calc(var(--mobile-archive-title-inset) + env(safe-area-inset-right));
    padding-left:
      calc(var(--mobile-archive-title-inset) + env(safe-area-inset-left));
    font-family: var(--font-ui, Arial, Helvetica, sans-serif);
    font-size: var(--mobile-archive-heading-size);
    font-weight: 400;
    line-height: 1;
  }

  /* The list determines Archive height. Its viewport-relative runways let the
     first and last title pass through the same center activation point. */
  .mobile-project-archive__stage {
    position: relative;
    z-index: 1;
    display: block;
    width: 100%;
  }

  .mobile-project-archive__list {
    position: relative;
    z-index: 2;
    display: flex;
    box-sizing: border-box;
    width: 100%;
    margin: 0;
    padding-top: var(--mobile-archive-title-runway);
    padding-right:
      calc(var(--mobile-archive-title-inset) + env(safe-area-inset-right));
    padding-bottom: var(--mobile-archive-title-runway);
    padding-left:
      calc(var(--mobile-archive-title-inset) + env(safe-area-inset-left));
    flex-direction: column;
    align-items: stretch;
    gap: var(--mobile-archive-title-gap);
    font-size: var(--mobile-archive-title-size);
    list-style: none;
  }

  .mobile-project-archive__item {
    display: flex;
    width: 100%;
    margin: 0;
    justify-content: flex-start;
    text-align: left;
    opacity: var(--mobile-archive-title-opacity);
  }

  .mobile-project-archive__item.is-active {
    color: var(
      --mobile-archive-active-title-color,
      var(--mobile-project-fallback-title)
    );
    opacity: var(--mobile-archive-active-title-opacity);
  }

  .mobile-project-archive__title {
    appearance: none;
    -webkit-appearance: none;
    display: block;
    width: 100%;
    max-width: 100%;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    font-family: var(--font-archive-title, var(--font-body));
    font-size: var(--mobile-archive-title-size);
    font-weight: 400;
    line-height: var(--mobile-archive-title-line-height);
    text-align: left;
  }

  button.mobile-project-archive__title {
    cursor: pointer;
  }

  button.mobile-project-archive__title:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 4px;
  }

  .mobile-project-archive__preview {
    appearance: none;
    -webkit-appearance: none;
    position: sticky;
    z-index: 1;
    top: var(--mobile-archive-preview-sticky-y);
    display: block;
    width: var(--mobile-archive-preview-width);
    height: 0;
    margin: 0 auto;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    cursor: pointer;
    pointer-events: auto;
  }

  .mobile-project-archive__preview:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 6px;
  }

  .mobile-project-archive__preview-image {
    position: absolute;
    top: 0;
    left: 0;
    display: block;
    width: 100%;
    max-width: 100%;
    height: auto;
    object-fit: contain;
    opacity: 0;
    transform: translateY(-50%);
    transition:
      opacity var(--mobile-archive-preview-transition-duration)
        var(--mobile-archive-preview-transition-easing);
  }

  .mobile-project-archive__preview-image.is-active {
    opacity: var(--mobile-archive-preview-opacity);
  }

  body.gallery-open .mobile-project-feed {
    pointer-events: none;
    visibility: hidden;
  }

  .bio-section {
    min-height: var(--bio-section-min-height-mobile);
    padding-top:
      calc(
        var(--bio-section-spacing-top-mobile) + env(safe-area-inset-top)
      );
    padding-bottom:
      calc(
        var(--bio-section-spacing-bottom-mobile) +
        env(safe-area-inset-bottom)
      );
  }

  .bio-section__grid {
    grid-template-columns: 1fr;
    gap: var(--bio-column-gap-mobile);
  }

  .bio-section__label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .bio-section__heading,
  .bio-section__copy {
    max-width: var(--bio-max-width-mobile);
    font-size: var(--bio-size-mobile);
    line-height: var(--bio-line-height-mobile);
  }

  .bio-section__heading {
    margin-bottom: var(--bio-paragraph-gap-mobile);
  }

  .bio-section__copy {
    gap: var(--bio-paragraph-gap-mobile);
  }

  .bio-section__selected-list {
    gap: var(--selected-row-gap-mobile);
    font-size: var(--selected-size-mobile);
    line-height: var(--selected-line-height-mobile);
  }

  .bio-section__contact {
    padding-top: var(--bio-contact-top-spacing-mobile);
    font-size: var(--bio-contact-size-mobile);
    line-height: var(--bio-contact-line-height-mobile);
  }

  .gallery-overlay__viewport {
    padding: 4.5rem 1rem 3.75rem;
  }

  .gallery-overlay__overview {
    display: block;
    padding:
      calc(var(--gallery-overview-mobile-padding-top) + env(safe-area-inset-top))
      calc(var(--gallery-overview-mobile-padding-inline) + env(safe-area-inset-right))
      calc(var(--gallery-overview-mobile-padding-bottom) + env(safe-area-inset-bottom))
      calc(var(--gallery-overview-mobile-padding-inline) + env(safe-area-inset-left));
  }

  .gallery-overlay__overview-copy {
    gap: var(--gallery-overview-mobile-copy-gap);
  }

  .gallery-overlay__overview-title {
    font-size: var(--gallery-overview-mobile-title-size);
  }

  .gallery-overlay__overview-description {
    font-size: var(--gallery-overview-mobile-description-size);
  }

  .gallery-overlay__overview-media {
    margin-top: var(--gallery-overview-mobile-divider-gap);
    padding-top: var(--gallery-overview-mobile-thumbnail-top-gap);
    padding-left: 0;
    border-top: 1px solid var(--gallery-overview-divider-color);
    border-left: 0;
  }

  .gallery-overlay__overview-media::before {
    display: none;
  }

  .gallery-overlay__overview-thumbnails {
    grid-template-columns: repeat(
      var(--gallery-overview-mobile-thumbnail-columns),
      minmax(0, 1fr)
    );
    column-gap: var(--gallery-overview-mobile-thumbnail-column-gap);
    row-gap: var(--gallery-overview-mobile-thumbnail-row-gap);
  }

  .gallery-overlay__overview-thumbnail img {
    max-height: none;
  }

  .gallery-overlay__image,
  .gallery-overlay__video {
    max-width: calc(100vw - 2rem);
    max-height: calc(100dvh - 8.25rem);
  }
}

@keyframes mobile-gradient-drift {
  0%,
  100% {
    transform: translate3d(-1.5%, -1%, 0) scale(1.04);
  }

  50% {
    transform: translate3d(1.5%, 1.25%, 0) scale(1.08);
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  html,
  body,
  .dot-matrix-layer,
  .dot-matrix-layer::after,
  .corner-interface,
  .opening,
  .project,
  .project__image,
  .archive-entry,
  .archive-preview,
  .archive-preview__image,
  .mobile-project-archive__preview-image,
  .mobile-project-archive::before,
  .gallery-overlay,
  .gallery-overlay__media,
  .gallery-overlay__nav span {
    transition: none;
  }

  /* Reduced Motion retains the same color composition as a static layer. */
  html.mobile-project-feed-enabled body::before {
    animation: none;
    transform: translate3d(0, 0, 0) scale(1.06);
  }
}
