/* ---- Desktop: single non-scrolling viewport, fixed 1440x900 canvas
   scaled to fit, same mechanism ported into every case-study page's
   "more projects" ending. ---- */
.desktop-landing {
  position: relative;
  width: 100%;
  height: 100vh;
  overflow: hidden;
}
.canvas-inner {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 1440px;
  height: 900px;
  transform: translate3d(-50%, -50%, 0) scale(1);
}
.desktop-landing .bg-grid { position: absolute; inset: 0; z-index: 0; pointer-events: none; }

.desktop-landing .project-frame {
  position: absolute;
  background: none;
  border: 1px solid transparent;
  padding: 0;
  z-index: 3;
  transition: padding .2s ease, border-color .2s ease, background-color .2s ease;
}
.desktop-landing .project-frame:hover {
  background: #fff;
  border-color: var(--ink);
  padding: 5px;
}
@keyframes ld-float-1 { 0%, 100% { transform: translate3d(0,0, 0); } 50% { transform: translate3d(11px, -13px, 0); } }
@keyframes ld-float-2 { 0%, 100% { transform: translate3d(0,0, 0); } 50% { transform: translate3d(-12px, 9px, 0); } }
@keyframes ld-float-3 { 0%, 100% { transform: translate3d(0,0, 0); } 50% { transform: translate3d(9px, 12px, 0); } }
@keyframes ld-float-4 { 0%, 100% { transform: translate3d(0,0, 0); } 50% { transform: translate3d(-10px, -8px, 0); } }
.desktop-landing .float-1 { animation: ld-float-1 7s ease-in-out infinite; }
.desktop-landing .float-2 { animation: ld-float-2 8.5s ease-in-out infinite; }
.desktop-landing .float-3 { animation: ld-float-3 6.5s ease-in-out infinite; }
.desktop-landing .float-4 { animation: ld-float-4 9s ease-in-out infinite; }
/* keeps the animated node on its own stable compositor layer so the
   browser doesn't repeatedly re-rasterize the image at a lower
   resolution and snap back — the momentary blur/sharpen flicker.
   translate3d (in the keyframes) forces GPU compositing; backface-
   visibility/perspective pin that layer so it doesn't get redrawn at
   a fractional pixel offset each frame. */
.desktop-landing .project-frame {
  will-change: transform;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  perspective: 1000px;
}
.desktop-landing .project-frame img { backface-visibility: hidden; -webkit-backface-visibility: hidden; }
@media (prefers-reduced-motion: reduce) {
  .desktop-landing .project-frame { animation: none !important; }
}
.canvas-inner:has(.project-frame:hover) .project-frame { animation-play-state: paused; }

.desktop-landing .frame-inner { width: 100%; height: 100%; overflow: hidden; position: relative; }
/* every card is now sized (js/frame-size.js) to match its own image's
   real aspect ratio, so cover never actually needs to crop anything —
   kept as a safety net for sub-pixel rounding only */
.desktop-landing .project-frame img { width: 100%; height: 100%; object-fit: cover; display: block; }
.desktop-landing .frame-expand {
  position: absolute; top: -9px; right: -9px; width: 18px; height: 18px;
  background: #fff; border: 1px solid var(--ink);
  display: flex; align-items: center; justify-content: center;
  color: var(--ink); z-index: 6;
}
/* overlays the node itself on hover; z-index below .frame-expand so
   the corner expand-icon square stays visible instead of getting
   covered by this white box */
.desktop-landing .frame-info {
  position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: space-between;
  background: #fff; padding: 14px; z-index: 5; opacity: 0;
  transition: opacity .2s ease; pointer-events: none;
}
.desktop-landing .project-frame:hover .frame-info { opacity: 1; }
.desktop-landing .info-row {
  display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
  padding: 4px 0; border-bottom: 1px solid var(--line);
  font-family: 'B612 Mono', ui-monospace, monospace; font-size: 11px; color: var(--ink);
}
.desktop-landing .info-row:last-child { border-bottom: none; }
.desktop-landing .info-row .info-label { color: var(--muted); text-align: left; white-space: nowrap; flex: none; }
/* value can wrap instead of overflowing the card when it's long
   (e.g. a combined role like "UX/UI and web design + no-code build") */
.desktop-landing .info-row span:not(.info-label) { text-align: right; flex: 1; min-width: 0; }
.desktop-landing .frame-desc {
  font-family: 'IBM Plex Sans', Helvetica, Arial, sans-serif;
  text-transform: none;
  font-size: 11px; line-height: 1.4; letter-spacing: 0.1px; color: var(--muted);
  margin-top: 8px;
}

.desktop-landing .bottombar {
  position: fixed;
  left: 30px; right: 30px;
  bottom: 30px;
  padding: 0;
  z-index: 10;
  /* the flex row's own box spans the full width at a fixed height,
     including the empty gap between .bottom-left and .canvas-status —
     without this, that empty space (which sits directly over the
     bottom-most project-frame nodes) swallows hover/click before it
     ever reaches them. Only the actual visible content should. */
  pointer-events: none;
}
.desktop-landing .bottombar > * { pointer-events: auto; }
.desktop-landing .canvas-status { }

@media (max-width: 767px) {
  .desktop-landing { display: none; }
}

/* ---- Mobile: plain scrolling stack ---- */
.mobile-landing {
  display: none;
  --tagbg: #ECEBE6;
}
@media (max-width: 767px) {
  .mobile-landing { display: block; }
}

/* topbar stays the shared fixed/frost-on-scroll element from base.css
   (position:fixed at 24px on mobile, gets .over-media on scroll —
   wired up in js/landing.js since site.js isn't loaded on this page) */
.mobile-landing .monogram-center { display: none; }
.mobile-landing .rightgroup { gap: 18px; }

/* the hero — topbar, photo, then bio+links — is exactly one viewport
   tall: photo and bio+links sit inside it (topbar floats fixed above,
   so this just reserves clearance for it), bio+links pinned to the
   bottom via margin-top:auto, with the empty space between them
   growing/shrinking with the screen. Projects start on the next
   screen, below this one. */
.mobile-hero {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  /* photo and bio+links are kept close together and the pair is centred in
     the viewport-tall hero (rather than pushed to opposite ends) */
  justify-content: center;
}

.mobile-photo { padding: 90px 24px 0; flex: none; }
/* matches the About page's photo — the smaller base .photo size
   (130x194) rather than a mobile-specific larger crop */
.mobile-photo .photo { overflow: hidden; }

.bio-block {
  display: flex;
  flex-direction: column;
  padding: 36px 24px 40px;
}
.bio-block .status { margin-bottom: 18px; }
.bio-block .bio {
  font-family: 'IBM Plex Sans', Helvetica, Arial, sans-serif;
  text-transform: none;
  font-size: 19px; line-height: 1.55; letter-spacing: -0.1px; color: var(--ink);
  max-width: 340px; margin-bottom: 22px;
}
.links-row { display: flex; align-items: center; gap: 20px; }
.about-link { font-size: 12px; }

/* .mobile-projects / .mobile-card rules now live in
   css/mobile-projects.css, shared with the case-study pages */

/* landing bio: 18px regular, first sentence always on line one (nowrap),
   second sentence starts line two. On mobile the first sentence may
   wrap, since 24px caps can't fit in a phone-width column. */
/* box is exactly as wide as the first sentence; the second wraps inside it */
.desktop-landing .corner-bio { width: min-content; max-width: none; }
.desktop-landing .canvas-status, .desktop-landing .status { flex: none; white-space: nowrap; }
.desktop-landing .bio { font-size: 18px; font-weight: 400; line-height: 1.3; letter-spacing: -0.2px; }
.bio-line { white-space: nowrap; }
.bio-block .bio { font-size: 18px; font-weight: 400; }
.bio-block .bio .bio-line { white-space: normal; }

/* decorative sticker on the desktop canvas: plain, slight tilt; a
   small "coming soon" plate appears on hover (the project page isn't
   published yet). The tilt lives on the image so the plate stays level. */
.desktop-landing .sticker-pasamontana,
.desktop-landing .sticker-hood {
  position: absolute;
  z-index: 4;
}
.desktop-landing .sticker-pasamontana { left: 1280px; top: 397px; width: 52px; }
.desktop-landing .sticker-hood { left: 146px; top: 333px; width: 112px; }
.desktop-landing .sticker-hood .sticker { transform: rotate(8deg); }
.desktop-landing .sticker {
  display: block; width: 100%; height: auto;
  transform: rotate(-11deg);
  user-select: none;
}
.desktop-landing .sticker-tip {
  position: absolute;
  left: 50%; top: calc(100% + 8px);
  transform: translateX(-50%);
  white-space: nowrap;
  padding: 5px 8px;
  background: #fff;
  border: 1px solid var(--ink);
  font-family: 'B612 Mono', ui-monospace, monospace;
  font-size: 11px; letter-spacing: 0.3px; color: var(--ink);
  opacity: 0; pointer-events: none;
  transition: opacity .2s ease;
}
.desktop-landing .sticker-pasamontana:hover .sticker-tip,
.desktop-landing .sticker-hood:hover .sticker-tip { opacity: 1; }

/* pixelate-on-hover canvas over the corner photo (js/photo-pixelate.js) */
.desktop-landing .bottombar .photo { position: relative; }
.desktop-landing .photo-pixels {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; pointer-events: none;
}
.desktop-landing .photo-link { display: block; width: 100%; height: 100%; }
