/* ============================================
   HERO SECTION - Portfolio Landing
   World-class responsive implementation

   Design System:
   - Desktop: 1440px (Figma reference)
   - Tablet: 768px - 1024px
   - Mobile: < 768px

   Typography: Helvetica Neue
   Colors: #111 (primary), #fff (bg)
   ============================================ */

/* ============================================
   CSS CUSTOM PROPERTIES
   ============================================ */
:root {
    /* Colors */
    --color-primary: #ffffff;
    --color-bg: #000000;
    --color-text: #ffffff;
    --site-nav-color: #ffffff;
    --site-nav-focus-color: #ffffff;
    --color-text-muted: rgba(255, 255, 255, 0.7);
    --color-border: rgba(255, 255, 255, 0.2);
    --color-border-light: rgba(255, 255, 255, 0.1);

    /* Typography */
    --font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
    --font-size-intro: 15px;
    --font-size-nav: 18px;
    --line-height-intro: 1.3;
    --letter-spacing-intro: -0.3px;
    --letter-spacing-nav: -0.36px;

    /* Spacing */
    --spacing-page: 40px;
    --spacing-section: 30px;
    --spacing-nav-gap: 7px;

    /* Sizes */
    --profile-size: 48px;
    --profile-radius: 3px;
    --logo-cell-width: 175px;
    --logo-cell-height: 110px;
    --logo-mark-scale: 0.8;
    --main-logo-width: 600px;
    --main-logo-height: 550px;

    /* Animation */
    --transition-fast: 0.2s ease;
    --transition-medium: 0.4s ease;
    --transition-slow: 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}

/* ============================================
   RESET & BASE
   ============================================ */
*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html {
    font-size: 16px;
    -webkit-text-size-adjust: 100%;
    height: 100%;
    overflow: hidden;
    max-width: 100%;
}

body {
    font-family: var(--font-family);
    background: var(--color-bg);
    color: var(--color-text);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
    max-width: 100%;
}

img {
    display: block;
    max-width: 100%;
    height: auto;
}

a {
    color: inherit;
    text-decoration: none;
}

/* ============================================
   HERO CONTAINER
   ============================================ */
.hero {
    width: 100%;
    height: 100vh;
    height: 100dvh;
    background: var(--color-bg);
    padding: 0 var(--spacing-page);
    overflow: hidden;
}

/* ============================================
   MAIN LAYOUT
   Two-column on desktop, stacked on mobile
   ============================================ */
.main {
    max-width: 1900px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: 1fr;
    grid-template-rows: auto 1fr auto;
    gap: 0;
    justify-content: center;
    align-content: start;
    width: 100%;
    height: 100%;
    padding: 20px 0 10px 0; /* top padding: 20px mobile, 40px on tablet+ via media query */
}

/* ============================================
   LEFT CONTENT SECTION
   On mobile: split into nav at top, intro at bottom
   ============================================ */
.content {
    display: contents;
}

/* Intro Section - Image + Text */
.intro-section {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 7.5px;
    order: 3;
    padding: 10px 20px;
    flex-shrink: 0;
}

/* Profile Image */
.profile-image {
    width: var(--profile-size);
    height: var(--profile-size);
    border-radius: var(--profile-radius);
    overflow: hidden;
    flex-shrink: 0;
}

.profile-image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    border-radius: var(--profile-radius);
}

/* Intro Text */
.intro-text {
    max-width: 354px;
    font-size: var(--font-size-intro);
    font-weight: 400;
    line-height: var(--line-height-intro);
    letter-spacing: var(--letter-spacing-intro);
    color: var(--color-text);
    text-transform: uppercase;
}

.intro-line {
    margin: 0;
}

.text-regular {
    font-weight: 400;
}

.text-medium {
    font-weight: 500;
}

/* ============================================
   NAVIGATION
   ============================================ */
.hero-socials {
    position: fixed;
    right: var(--spacing-page);
    bottom: clamp(18px, 3.2vh, 42px);
    z-index: 20;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(10px, 1.4vh, 16px);
}

.hero-socials a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    color: rgba(255, 255, 255, 0.5);
    transition: color var(--transition-fast), transform var(--transition-fast);
}

/* Email is left untouched on hover — same muted color, no lift. */
.hero-socials a:not([aria-label="Email"]):hover,
.hero-socials a:not([aria-label="Email"]):focus-visible {
    color: #ffffff;
    transform: translateY(-1px);
}

.hero-socials svg {
    width: auto;
    height: 24px;
    fill: currentColor;
}

.hero-socials a[aria-label="Email"] svg {
    fill: none;
    stroke: currentColor;
}

/* Stack the mono icon and the colored hover icon in the same spot,
   same size, so swapping them on hover is purely a color change. */
.hero-socials .social-icon-stack {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 0;
}

.hero-socials .social-icon-mono,
.hero-socials .social-icon-color {
    transition: opacity var(--transition-fast);
}

.hero-socials .social-icon-color {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    /* fill (not contain) so a 1:1 brand asset stretches to the mono's
       24:23 box exactly — prevents a tiny size jump on hover. */
    object-fit: fill;
    opacity: 0;
    pointer-events: none;
}

/* Only fade the mono icon out when there is a colored overlay to swap in
   (Instagram and LinkedIn). Otherwise the icon would just disappear. */
.hero-socials a:has(.social-icon-color):hover .social-icon-mono,
.hero-socials a:has(.social-icon-color):focus-visible .social-icon-mono {
    opacity: 0;
}

.hero-socials a:hover .social-icon-color,
.hero-socials a:focus-visible .social-icon-color {
    opacity: 1;
}

/* The LinkedIn brand SVG has more aggressive rounded corners than the mono
   silhouette, which makes it read slightly smaller at this size. Scale up
   to match the mono's perceived footprint. */
.hero-socials a[aria-label="LinkedIn"] .social-icon-color {
    transform: scale(1.06);
}

/* ============================================
   LOGOS SECTION
   ============================================ */
.logos-section {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 0;
    width: 100%;
    max-width: 100%;
    order: 2;
    min-height: 0;
    overflow: visible;
}

/* Main Logo Display */
.main-logo {
    width: 100%;
    max-width: 100%;
    flex: 1;
    min-height: 0;
    position: relative;
    overflow: visible;
    /* Particle canvas bleeds outward by this percentage on each side
       so repelled particles don't get cropped at the edges. JS reads
       this value to size the WebGL drawing buffer and compensate zoom. */
    --canvas-bleed: 8%;
}

#ambient-particle-canvas,
#particle-canvas {
    position: fixed;
    inset: 0;
    width: 100vw;
    height: 100vh;
    height: 100dvh;
    pointer-events: none;
}

#ambient-particle-canvas {
    z-index: 1;
}

#particle-canvas {
    z-index: 1;
}

/* ============================================
   LOGO GRID
   3x2 grid, responsive scaling
   ============================================ */
.logo-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-template-rows: repeat(2, auto);
    width: min(100%, 498px);
    margin-inline: auto;
    gap: 1px;
    padding: 1px;
    background: var(--color-border);
    position: relative;
    flex-shrink: 0;
}

.logo-grid::after {
    content: none;
}

/* Logo Cell */
.logo-cell {
    aspect-ratio: 175 / 110;
    min-width: 0;
    display: grid;
    place-items: center;
    position: relative;
    background: var(--color-bg);
    padding: clamp(12px, 1.4vw, 18px);
    cursor: pointer;
    border: none;
    font: inherit;
    color: inherit;
    appearance: none;
    -webkit-appearance: none;
    transition: box-shadow 0.35s ease, background-color 0.35s ease;
}

/* Active cell - use box-shadow for full border effect */
.logo-cell-active {
    box-shadow: inset 0 0 0 2px var(--color-primary);
    z-index: 1;
}

/* Logo wrapper - consistent size container */
.logo-wrapper {
    display: flex;
    align-items: center;
    justify-content: center;
    width: calc(100% * var(--logo-mark-scale));
    height: calc(100% * var(--logo-mark-scale));
    min-height: 0;
    opacity: 0.10;
    transition: opacity 0.35s ease;
}

/* Logo SVGs - use color for opacity control */
.logo-img {
    display: block;
    width: 100%;
    height: 100%;
    color: rgba(255, 255, 255, 1);
    transition: color 0.35s ease, transform 0.35s ease;
}
.logo-img path {
    fill: #ffffff;
}

/* Active cell content - full opacity */
.logo-cell-active .logo-wrapper {
    opacity: 1;
}

/* Hover effect — only on cells that are still readable in the spotlight band. */
.logo-cell[data-rail-distance="1"]:hover .logo-wrapper,
.logo-cell[data-rail-distance="2"]:hover .logo-wrapper,
.logo-cell[data-rail-distance="3"]:hover .logo-wrapper {
    opacity: 0.95;
}

.logo-cell[data-rail-distance="1"]:hover .logo-img,
.logo-cell[data-rail-distance="2"]:hover .logo-img,
.logo-cell[data-rail-distance="3"]:hover .logo-img {
    transform: scale(1.02);
}

/* ============================================
   MOBILE LAYOUT TUNING (< 768px)
   ============================================ */
@media (max-width: 767px) {
    .hero {
        padding: 0;
    }

    .main {
        display: flex;
        flex-direction: column;
        align-items: stretch;
        height: 100%;
        padding: calc(env(safe-area-inset-top, 0px) + 16px) 0 calc(env(safe-area-inset-bottom, 0px) + 16px);
    }

    /* Remove profile + about copy on mobile main screen */
    .intro-section {
        display: none;
    }

    /* Keep particle area centered, grid fixed to bottom */
    .logos-section {
        flex: 1 1 auto;
        justify-content: space-between;
        align-items: center;
        min-height: 0;
        padding: 0 20px;
    }

    .main-logo {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 100%;
        flex: 1 1 0;
    }

    .logo-grid {
        width: min(100%, 504px);
        margin-top: 12px;
        margin-bottom: 0;
    }

    .hero-socials {
        display: none;
    }

    .hero:not(.instant) .site-nav-logo,
    .hero:not(.instant) .site-nav-links,
    .hero:not(.instant) .main-logo,
    .hero:not(.instant) .logo-grid {
        animation: none;
        opacity: 1;
        filter: none;
    }

    .hero:not(.instant) .main-logo {
        transform: translate(-50%, -50%);
    }

    .hero:not(.instant) .logo-grid {
        transform: translateX(calc(var(--rail-shift) * -1));
    }
}

/* ============================================
   TABLET BREAKPOINT (768px - 1024px)
   ============================================ */
@media (min-width: 768px) {
    :root {
        --spacing-page: 40px;
    }

    .main {
        grid-template-columns: 1fr;
        grid-template-rows: 1fr;
        align-items: stretch;
        align-content: stretch;
        gap: 0;
        padding: 40px 0 20px 0;
        position: relative;
    }

    .content {
        position: absolute;
        left: 0;
        top: 40px;
        bottom: 20px;
        width: min(374px, 36vw);
        display: flex;
        flex-direction: column;
        justify-content: flex-end;
        z-index: 2;
    }

    .intro-section {
        align-items: flex-start;
        text-align: left;
        order: unset;
        padding: 0 0 20px 0;
        gap: 7.5px;
    }

    .logos-section {
        justify-content: center;
        width: 100%;
        max-width: min(100%, 900px);
        justify-self: center;
        flex: unset;
        padding-top: 0;
    }

    .main-logo {
        width: 100%;
        max-width: var(--main-logo-width);
        height: var(--main-logo-height);
        aspect-ratio: unset;
    }

    .logo-grid {
        max-width: min(426px, 30.24vw);
    }

}

/* ============================================
   DESKTOP BREAKPOINT (1024px+)
   ============================================ */
@media (min-width: 1024px) {
    .content {
        width: 374px;
    }

    .logo-grid {
        max-width: min(498px, 30.24vw);
    }
}

/* ============================================
   LARGE DESKTOP (1440px+)
   ============================================ */
@media (min-width: 1440px) {
}

/* ============================================
   SMALL MOBILE (< 480px)
   ============================================ */
@media (max-width: 479px) {
    :root {
        --spacing-page: 20px;
        --font-size-intro: 12px;
        --font-size-nav: 14px;
        --profile-size: 40px;
    }

    .intro-text {
        max-width: 100%;
    }

    .logo-grid {
        width: 100%;
    }

    .main {
        padding-top: calc(env(safe-area-inset-top, 0px) + 12px);
    }

    .logos-section {
        padding: 0 12px;
    }
}

/* ============================================
   ANIMATIONS
   Smooth blur + slide + fade reveal system.
   Uses easeOutQuart for a soft, decelerating feel.
   ============================================ */
@keyframes blurFadeUp {
    0% {
        opacity: 0;
        filter: blur(14px);
        transform: translate3d(0, 24px, 0);
    }
    60% {
        filter: blur(2px);
    }
    100% {
        opacity: 1;
        filter: blur(0);
        transform: translate3d(0, 0, 0);
    }
}

@keyframes blurFadeDown {
    0% {
        opacity: 0;
        filter: blur(14px);
        transform: translate3d(0, -20px, 0);
    }
    60% {
        filter: blur(2px);
    }
    100% {
        opacity: 1;
        filter: blur(0);
        transform: translate3d(0, 0, 0);
    }
}

@keyframes blurFadeLeft {
    0% {
        opacity: 0;
        filter: blur(12px);
        transform: translate3d(-28px, 0, 0);
    }
    60% {
        filter: blur(2px);
    }
    100% {
        opacity: 1;
        filter: blur(0);
        transform: translate3d(0, 0, 0);
    }
}

@keyframes blurFadeRight {
    0% {
        opacity: 0;
        filter: blur(12px);
        transform: translate3d(28px, 0, 0);
    }
    60% {
        filter: blur(2px);
    }
    100% {
        opacity: 1;
        filter: blur(0);
        transform: translate3d(0, 0, 0);
    }
}

@keyframes blurScaleIn {
    0% {
        opacity: 0;
        filter: blur(20px);
        transform: scale(0.92);
    }
    55% {
        filter: blur(3px);
    }
    100% {
        opacity: 1;
        filter: blur(0);
        transform: scale(1);
    }
}

@keyframes blurScaleInCentered {
    0% {
        opacity: 0;
        filter: blur(20px);
        transform: translate(-50%, -50%) scale(0.92);
    }
    55% {
        filter: blur(3px);
    }
    100% {
        opacity: 1;
        filter: blur(0);
        transform: translate(-50%, -50%) scale(1);
    }
}

@keyframes blurFadeUpRail {
    0% {
        opacity: 0;
        filter: blur(14px);
        transform: translateX(calc(var(--rail-shift) * -1)) translateY(20px);
    }
    60% {
        filter: blur(2px);
    }
    100% {
        opacity: 1;
        filter: blur(0);
        transform: translateX(calc(var(--rail-shift) * -1)) translateY(0);
    }
}

@keyframes blurFadeRightMeta {
    0% {
        opacity: 0;
        filter: blur(12px);
        transform: translateY(-50%) translateX(28px);
    }
    60% {
        filter: blur(2px);
    }
    100% {
        opacity: 1;
        filter: blur(0);
        transform: translateY(-50%) translateX(0);
    }
}

@keyframes blurFadeUpCenteredMeta {
    0% {
        opacity: 0;
        filter: blur(14px);
        transform: translateX(-50%) translateY(20px);
    }
    60% {
        filter: blur(2px);
    }
    100% {
        opacity: 1;
        filter: blur(0);
        transform: translateX(-50%) translateY(0);
    }
}

/* Initial load — pre-animation hidden state on every animated element */
.hero:not(.instant) .site-nav-logo,
.hero:not(.instant) .site-nav-links,
.hero:not(.instant) .profile-image,
.hero:not(.instant) .intro-line,
.hero:not(.instant) .main-logo,
.hero:not(.instant) .logo-grid,
.hero:not(.instant) .hero-socials a {
    opacity: 0;
    will-change: opacity, transform, filter;
}

/* Easing token shared by every reveal */
.hero.loaded .site-nav-logo,
.hero.loaded .site-nav-links,
.hero.loaded .profile-image,
.hero.loaded .intro-line,
.hero.loaded .main-logo,
.hero.loaded .logo-grid,
.hero.loaded .hero-socials a {
    animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
    animation-fill-mode: forwards;
}

/* Top nav — drops in from above with a soft blur */
.hero.loaded .site-nav-logo {
    animation: blurFadeDown 0.9s 0.05s forwards;
}

.hero.loaded .site-nav-links {
    animation: blurFadeDown 1s 0.18s forwards;
}

/* Intro column — staggered upward reveal */
.hero.loaded .profile-image {
    animation: blurScaleIn 1.1s 0.25s forwards;
}

.hero.loaded .intro-line {
    animation: blurFadeUp 1s forwards;
}

.hero.loaded .intro-line:nth-child(1) { animation-delay: 0.40s; }
.hero.loaded .intro-line:nth-child(2) { animation-delay: 0.52s; }
.hero.loaded .intro-line:nth-child(3) { animation-delay: 0.64s; }
.hero.loaded .intro-line:nth-child(4) { animation-delay: 0.76s; }

/* Logo showcase — soft scale + blur reveal */
.hero.loaded .main-logo {
    animation: blurScaleIn 1.4s 0.3s forwards;
}

.hero.loaded .logo-grid {
    animation: blurFadeUp 1.1s 0.6s forwards;
}

/* Social links — slide in from the left, last */
.hero.loaded .hero-socials a {
    animation: blurFadeLeft 0.9s forwards;
}

.hero.loaded .hero-socials a:nth-child(1) { animation-delay: 0.95s; }
.hero.loaded .hero-socials a:nth-child(2) { animation-delay: 1.05s; }
.hero.loaded .hero-socials a:nth-child(3) { animation-delay: 1.15s; }
.hero.loaded .hero-socials a:nth-child(4) { animation-delay: 1.25s; }

/* Instant mode (returning visitor) — skip the choreography.
   We only target the parent of the CTA (.site-nav-links), so the CTA's
   rainbow animation keeps running unaffected. */
.hero.instant .site-nav-logo,
.hero.instant .site-nav-links,
.hero.instant .profile-image,
.hero.instant .intro-line,
.hero.instant .main-logo,
.hero.instant .logo-grid,
.hero.instant .hero-socials a {
    animation: none;
    opacity: 1;
    transform: none;
    filter: none;
}

/* ============================================
   SPLASH SCREEN
   ============================================ */
.splash-screen {
    position: fixed;
    inset: 0;
    z-index: 100;
    background: #fafafa;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background-color 0.5s ease;
}

.splash-screen.splash-bg-black {
    background: #000;
}

.splash-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 40px;
}

.splash-image {
    width: 294px;
    height: 294px;
    object-fit: cover;
    opacity: 0;
    transform: translateY(20px);
    transition: opacity 0.8s ease, transform 0.8s ease;
}

.splash-text {
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
    font-size: 18px;
    color: #111;
    text-align: center;
    text-transform: uppercase;
    letter-spacing: -0.36px;
    line-height: normal;
    width: 460px;
    max-width: 90vw;
}

.splash-line {
    margin: 0;
    opacity: 0;
    transform: translateY(20px);
    transition: opacity 0.8s ease, transform 0.8s ease;
}

/* Appear state */
.splash-screen.splash-appear .splash-image {
    opacity: 1;
    transform: translateY(0);
}

.splash-screen.splash-appear .splash-line {
    opacity: 1;
    transform: translateY(0);
}

.splash-screen.splash-appear .splash-line:nth-child(1) { transition-delay: 0.1s; }
.splash-screen.splash-appear .splash-line:nth-child(2) { transition-delay: 0.2s; }
.splash-screen.splash-appear .splash-line:nth-child(3) { transition-delay: 0.3s; }
.splash-screen.splash-appear .splash-line:nth-child(4) { transition-delay: 0.4s; }

/* Fade-out state */
.splash-screen.splash-fade .splash-image,
.splash-screen.splash-fade .splash-line {
    opacity: 0;
    transform: translateY(-10px);
    transition: opacity 0.6s ease, transform 0.6s ease;
    transition-delay: 0s;
}

/* Responsive */
@media (max-width: 479px) {
    .splash-image {
        width: 200px;
        height: 200px;
    }
    .splash-text {
        font-size: 14px;
    }
}

/* ============================================
   ACCESSIBILITY
   ============================================ */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

/* Screen-reader only utility */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ============================================
   PAGE TRANSITIONS
   Blur out/in when cycling between logo pages
   ============================================ */
.logo-grid.page-exit .logo-wrapper {
    opacity: 0 !important;
    filter: blur(4px);
    transition: opacity 0.5s ease, filter 0.5s ease;
}

.logo-grid.page-enter .logo-wrapper {
    opacity: 0;
    filter: blur(4px);
    transition: none;
}

.logo-grid.page-enter-active .logo-wrapper {
    opacity: 0.2;
    filter: blur(0px);
    transition: opacity 0.5s ease, filter 0.5s ease;
}

.logo-grid.page-enter-active .logo-cell-active .logo-wrapper {
    opacity: 1;
    filter: blur(0px);
}

/* Body-level clone for simultaneous crossfade (isolated from .logo-grid cascade) */
.crossfade-clone {
    position: fixed;
    pointer-events: none;
    z-index: 10;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-template-rows: repeat(2, auto);
    gap: 1px;
    padding: 1px;
    background: var(--color-border);
    transition: opacity 0.5s ease, filter 0.5s ease;
}

.crossfade-clone.fade-out {
    opacity: 0;
    filter: blur(4px);
}

.hero-socials a:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
    border-radius: 4px;
}

.logo-cell:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: -2px;
}

/* High contrast mode support */
@media (prefers-contrast: high) {
    :root {
        --color-border: rgba(17, 17, 17, 0.5);
        --color-border-light: rgba(17, 17, 17, 0.3);
    }

    .logo-img {
        filter: none;
    }
}

/* ============================================
   HOMEPAGE ART-DIRECTED LAYOUT
   Reference: black stage, centered particle mark, left socials,
   right project label, bottom logo rail.
   ============================================ */
.hero {
    --stage-pad-x: clamp(24px, 2.45vw, 50px);
    --nav-bottom-y: clamp(62px, 7.5vh, 86px);
    --rail-top-y: calc(100dvh - clamp(86px, 10.6vh, 116px));
    --stage-center-y: calc((var(--nav-bottom-y) + var(--rail-top-y)) / 2);
    --hero-logo-size: clamp(354px, 29.2vw, 598px);
    --hero-logo-half: clamp(177px, 14.6vw, 299px);
    --project-side-gap: clamp(96px, 9vw, 200px);
    padding: 0 var(--stage-pad-x);
}

.main {
    max-width: none;
    position: relative;
    display: block;
    padding: 0;
}

.content {
    display: contents;
}

.intro-section {
    display: none;
}

.logos-section {
    position: relative;
    display: block;
    width: 100%;
    height: 100%;
    max-width: none;
    overflow: visible;
}

.main-logo {
    position: absolute;
    left: 50%;
    top: var(--stage-center-y);
    width: var(--hero-logo-size);
    height: var(--hero-logo-size);
    max-width: none;
    transform: translate(-50%, -50%);
    flex: none;
    overflow: visible;
    --canvas-bleed: 22%;
}

.particle-fallback {
    position: absolute;
    left: 50%;
    top: 50%;
    z-index: 0;
    width: min(68%, 360px);
    height: min(68%, 360px);
    object-fit: contain;
    opacity: 0;
    visibility: hidden;
    transform: translate(-50%, -50%);
    filter: brightness(0) invert(1);
}

.hero-particles-failed .particle-fallback {
    opacity: 0.92;
    visibility: visible;
}

.project-meta {
    position: absolute;
    left: calc(50% + var(--hero-logo-half) + var(--project-side-gap));
    top: var(--stage-center-y);
    width: min(390px, 22vw);
    color: #fff;
    pointer-events: none;
    transform: translateY(-50%);
    --meta-swap-duration: 800ms;
    --meta-enter-duration: 720ms;
    --meta-swap-blur: 2.5px;
}

.project-title {
    margin: 0 0 6px;
    font-size: clamp(18px, 1.22vw, 25px);
    line-height: 1.12;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    transform: translateY(0);
    filter: blur(0);
    opacity: 1;
    transition:
        transform var(--meta-enter-duration) cubic-bezier(0.22, 1, 0.36, 1),
        filter var(--meta-enter-duration) cubic-bezier(0.22, 1, 0.36, 1),
        opacity var(--meta-enter-duration) cubic-bezier(0.22, 1, 0.36, 1);
    will-change: transform, filter, opacity;
}

.project-tags {
    margin: 0;
    color: rgba(255, 255, 255, 0.86);
    font-size: clamp(14px, 0.98vw, 20px);
    line-height: 1.2;
    font-weight: 400;
    letter-spacing: 0;
    transform: translateY(0);
    filter: blur(0);
    opacity: 1;
    transition:
        transform var(--meta-enter-duration) cubic-bezier(0.22, 1, 0.36, 1),
        filter var(--meta-enter-duration) cubic-bezier(0.22, 1, 0.36, 1),
        opacity var(--meta-enter-duration) cubic-bezier(0.22, 1, 0.36, 1);
    will-change: transform, filter, opacity;
}

.project-meta > .project-title,
.project-meta > .project-tags {
    position: relative;
    z-index: 1;
}

.project-meta-ghost {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    color: inherit;
    pointer-events: none;
    z-index: 2;
}

.project-meta-ghost .project-title,
.project-meta-ghost .project-tags {
    transition:
        transform var(--meta-swap-duration) cubic-bezier(0.22, 1, 0.36, 1),
        filter var(--meta-swap-duration) cubic-bezier(0.22, 1, 0.36, 1),
        opacity var(--meta-swap-duration) cubic-bezier(0.22, 1, 0.36, 1);
}

/* Outgoing: text blurs UP and fades out. */
.project-meta.is-leaving .project-title,
.project-meta.is-leaving .project-tags,
.project-meta-ghost.is-leaving .project-title,
.project-meta-ghost.is-leaving .project-tags {
    transform: translateY(-50%);
    filter: blur(var(--meta-swap-blur));
    opacity: 0;
}

/* Incoming start: text snaps BELOW + blurred + invisible (no transition so it doesn't
   slide from the leaving position). When `is-entering` is removed, the normal transitions
   resume and the text resolves up into its natural state. */
.project-meta.is-entering .project-title,
.project-meta.is-entering .project-tags {
    transform: translateY(50%);
    filter: blur(var(--meta-swap-blur));
    opacity: 0;
    transition: none !important;
}

.hero-socials {
    position: fixed;
    left: var(--stage-pad-x);
    top: var(--stage-center-y);
    right: auto;
    bottom: auto;
    transform: translateY(-50%);
    z-index: 20;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(14px, 1.7vh, 22px);
}

.hero-socials a {
    width: 25px;
    height: 25px;
    color: rgba(255, 255, 255, 0.45);
}

.hero-socials svg {
    height: 22px;
}

.logo-grid {
    --rail-cell: clamp(72px, 7.6vw, 124px);
    --rail-gap: clamp(44px, 5vw, 96px);
    --rail-shift: 0px;
    position: fixed;
    left: 0;
    bottom: clamp(28px, 5.35vh, 58px);
    width: max-content;
    max-width: none;
    margin: 0;
    padding: 0;
    display: flex;
    align-items: center;
    gap: var(--rail-gap);
    background: transparent;
    border: 0;
    transform: translateX(calc(var(--rail-shift) * -1));
    transition: transform 850ms cubic-bezier(0.22, 1, 0.36, 1);
    will-change: transform;
}

.crossfade-clone {
    display: flex;
    gap: var(--rail-gap);
    padding: 0;
    background: transparent;
}

.logo-cell {
    flex: 0 0 var(--rail-cell);
    width: var(--rail-cell);
    height: clamp(38px, 3.9vw, 58px);
    padding: 0;
    background: transparent;
    cursor: pointer;
}

.logo-cell-active {
    box-shadow: none;
}

.logo-wrapper {
    width: 100%;
    height: 100%;
    opacity: 0;
    transform: scale(0.86);
    transform-origin: center;
    transition:
        opacity 0.9s cubic-bezier(0.22, 1, 0.36, 1),
        transform 1.2s cubic-bezier(0.22, 1, 0.36, 1);
    will-change: opacity, transform;
}

/* Rail spotlight: center fully lit, two cells either side fade out — the first
   neighbour reads clearly, the second is half-eaten by the dark. */
.logo-cell[data-rail-distance="1"] .logo-wrapper {
    opacity: 0.30;
    transform: scale(0.92);
}
.logo-cell[data-rail-distance="2"] .logo-wrapper {
    opacity: 0.10;
    transform: scale(0.86);
}
.logo-cell[data-rail-distance="3"] .logo-wrapper,
.logo-cell[data-rail-distance="4"] .logo-wrapper,
.logo-cell[data-rail-distance="5"] .logo-wrapper,
.logo-cell[data-rail-distance="99"] .logo-wrapper {
    opacity: 0;
}
.logo-cell[data-rail-distance="3"],
.logo-cell[data-rail-distance="4"],
.logo-cell[data-rail-distance="5"],
.logo-cell[data-rail-distance="99"] {
    pointer-events: none;
}

.logo-cell-active .logo-wrapper,
.logo-cell[data-rail-distance="0"] .logo-wrapper {
    opacity: 1 !important;
    transform: scale(1.1);
}

.logo-img {
    max-width: 100%;
    max-height: 100%;
    color: #fff;
}

.hero:not(.instant) .project-meta {
    opacity: 0;
    will-change: opacity, transform, filter;
}

.hero.loaded:not(.instant) .project-meta {
    opacity: 1;
    filter: none;
    animation-name: blurFadeRightMeta;
    animation-duration: 1.1s;
    animation-delay: 0.55s;
    animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
    animation-fill-mode: backwards;
}

.hero.loaded:not(.instant) .main-logo {
    opacity: 1;
    filter: none;
    transform: translate(-50%, -50%);
    animation-name: blurScaleInCentered;
    animation-duration: 1.4s;
    animation-delay: 0.3s;
    animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
    animation-fill-mode: backwards;
}

.hero.loaded:not(.instant) .logo-grid {
    opacity: 1;
    filter: none;
    animation-name: blurFadeUpRail;
    animation-duration: 1.1s;
    animation-delay: 0.6s;
    animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
    animation-fill-mode: backwards;
}

/* Page-wide intro blur — the whole stage starts softly blurred and resolves
   into focus right after the splash fades out. Pairs with the per-element
   blur reveals to give the page a layered "coming into focus" entrance.
   Kept moderate (8px) because .main-logo adds another 20px during the same
   window, so the composited blur is plenty without tanking the GPU. */
.hero:not(.instant) {
    transition: filter 1.6s cubic-bezier(0.22, 1, 0.36, 1);
    filter: blur(8px);
    will-change: filter;
}

.hero.loaded:not(.instant) {
    filter: blur(0);
}

.hero.instant .project-meta {
    animation: none;
    opacity: 1;
    filter: none;
}

.hero.instant .main-logo {
    transform: translate(-50%, -50%);
}

.hero.instant .logo-grid {
    transform: translateX(calc(var(--rail-shift) * -1));
}

@media (max-width: 1180px) {
    .hero {
        --hero-logo-size: min(52.7vw, 490px);
        --hero-logo-half: min(26.4vw, 245px);
    }

    .main-logo {
        width: var(--hero-logo-size);
        height: var(--hero-logo-size);
    }

    .project-meta {
        left: 50%;
        top: calc(var(--stage-center-y) + min(26.4vw, 196px));
        width: min(520px, 78vw);
        text-align: center;
        transform: translateX(-50%);
    }

    .hero.loaded:not(.instant) .project-meta {
        animation-name: blurFadeUpCenteredMeta;
    }

}

@media (max-width: 900px) {
    .logo-grid {
        --mobile-rail-side: clamp(24px, 6.8vw, 30px);
        --rail-cell: clamp(58px, 17vw, 76px);
        --rail-gap: max(44px, calc((100vw - (2 * var(--mobile-rail-side)) - (3 * var(--rail-cell))) / 2));
        bottom: calc(env(safe-area-inset-bottom, 0px) + clamp(20px, 5.2vh, 50px));
    }

    .crossfade-clone {
        gap: var(--rail-gap);
    }

    .logo-cell {
        height: clamp(38px, 9.6vw, 54px);
    }

    .hero-socials {
        display: none;
    }
}

/* Portrait phones — recenter the stage so the logo, meta, and rail share
   the available height instead of clustering in the middle with dead space
   above and below. */
@media (max-width: 640px) {
    .hero {
        --stage-pad-x: 14px;
        --nav-bottom-y: clamp(76px, 10vh, 96px);
        --rail-top-y: calc(100dvh - clamp(142px, 19vh, 184px));
        /* Keep the particle mark inside the usable phone viewport. The
           canvas still bleeds, so the stage itself needs a conservative cap. */
        --hero-logo-size: min(92vw, 43vh, 420px);
        --hero-logo-half: calc(var(--hero-logo-size) / 2);
        /* Keep the visual center slightly above the mathematical middle so
           the logo, meta, and rail read as one composition on tall phones. */
        --stage-center-y: calc(var(--nav-bottom-y) + (var(--rail-top-y) - var(--nav-bottom-y)) * 0.38);
    }

    .main-logo {
        width: var(--hero-logo-size);
        height: var(--hero-logo-size);
        --canvas-bleed: 24%;
    }

    .project-meta {
        /* Sit the meta just under the logo with a small breathing gap rather
           than tied to a viewport-width fraction. */
        top: calc(var(--stage-center-y) + var(--hero-logo-half) + clamp(14px, 2.8vh, 22px));
        width: min(340px, calc(100vw - 28px));
        max-width: calc(100vw - 28px);
        transform: translateX(-50%);
        text-align: center;
    }

    .project-title {
        font-size: clamp(16px, 4.1vw, 18px);
        line-height: 1.12;
        text-wrap: balance;
        overflow-wrap: anywhere;
    }

    .project-tags {
        font-size: clamp(13px, 3.3vw, 15px);
        text-wrap: balance;
    }

    .logo-grid {
        --mobile-rail-side: clamp(24px, 6.8vw, 30px);
        --rail-cell: clamp(58px, 17vw, 76px);
        --rail-gap: max(44px, calc((100vw - (2 * var(--mobile-rail-side)) - (3 * var(--rail-cell))) / 2));
        bottom: calc(env(safe-area-inset-bottom, 0px) + clamp(20px, 5.2vh, 50px));
    }

    .crossfade-clone {
        gap: var(--rail-gap);
    }
}

/* Tiny phones (≤360px) — keep the logo readable without crowding the rail. */
@media (max-width: 360px) {
    .hero {
        --hero-logo-size: min(90vw, 42vh, 340px);
    }

    .project-title {
        font-size: 16px;
    }

    .project-tags {
        font-size: 12px;
    }
}

/* Short landscape phones — when there's almost no vertical room, scale the
   logo by height so the rail and meta still fit without overlap. */
@media (max-width: 900px) and (max-height: 520px) and (orientation: landscape) {
    .hero {
        --nav-bottom-y: clamp(44px, 10vh, 60px);
        --rail-top-y: calc(100dvh - clamp(72px, 16vh, 96px));
        --hero-logo-size: min(38vh, 38vw, 240px);
        --hero-logo-half: calc(var(--hero-logo-size) / 2);
    }

    .project-meta {
        top: calc(var(--stage-center-y) + var(--hero-logo-half) + 6px);
        width: min(360px, 60vw);
    }

    .logo-grid {
        bottom: calc(env(safe-area-inset-bottom, 0px) + 10px);
    }
}

@media (max-width: 640px) and (max-height: 620px) {
    .hero {
        --nav-bottom-y: clamp(62px, 10vh, 76px);
        --rail-top-y: calc(100dvh - clamp(96px, 18vh, 116px));
        --hero-logo-size: min(88vw, 40vh, 320px);
        --stage-center-y: calc(var(--nav-bottom-y) + (var(--rail-top-y) - var(--nav-bottom-y)) * 0.36);
    }

    .project-meta {
        top: calc(var(--stage-center-y) + var(--hero-logo-half) + clamp(10px, 2vh, 16px));
    }
}
