:root {
    --pink: #d65891;
    --purple: #421e80;
    --purple-bright: #7a4bc7;
    --gutter-mobile: 8vw; /* side gutter on phones: nav, sections, footer, menu */
}

/* No horizontal scroll. `clip` rather than `hidden`: with a non-visible
   overflow on both html and body, `hidden` turns <body> into its own scroll
   container, which breaks window scroll (Lenis, ScrollTrigger's pin on the
   homepage reveal). `clip` never creates a scroll container. The `hidden`
   line on html is a fallback for browsers without `clip`. */
html {
    overflow-x: hidden;
    overflow-x: clip;
}
body {
    margin: 0;
    font-family: 'Inter', sans-serif;
    background: black;
    color: white;
    overflow-x: clip;
}

h1, h2, h3, .section-title, #static-text, .work-name, .reveal-caption {
    font-family: 'Space Grotesk', 'Inter', sans-serif;
}

/* --- Logos --- */
.nav-logo { display: block; line-height: 0; }
.nav-logo img {
    height: 36px; width: auto; object-fit: contain; display: block;
}

.footer-logo { display: flex; align-items: center; gap: 0.5em; }
.footer-logo img {
    /* Was 18px against 12px surrounding text — visibly larger than
       everything else in the footer. Matched to the text's own size. */
    height: 12.65px; width: auto; object-fit: contain; display: block;
    /* PNG is light grey (#f6f6f6); force pure white. ~15% taller than
       the 11px text match so the thin strokes hold up. */
    filter: brightness(0) invert(1);
}
.footer-copyright { font-size: 1.1em; line-height: 1; }

/* Footer row brightness. The markup carries Tailwind's `opacity-40` on
   this row; that is neutralised here so text and wordmark can be set
   individually. Selector specificity beats both `.opacity-40` and
   `.hover:text-white:hover`. */
footer .footer-line + div { opacity: 1; color: rgba(255,255,255,0.85); }
footer .footer-logo, footer .footer-logo img { opacity: 1; }
footer .footer-line + div a:hover { color: var(--pink); }

/* --- Nav active-section highlight ---
   Nav sits under mix-blend-difference, so this color inverts against
   whatever is beneath it exactly like the existing hover accent does —
   same pink used everywhere else, so it stays legible on any background. */
nav a.nav-link.active {
    color: var(--pink);
}

/* Nav contrast scrim: a fixed dark band behind the nav so content scrolled
   under the logo and links disappears. Near-solid (0.95) down to the nav's
   bottom edge (--nav-h), then a 50px fade to transparent. --nav-h defaults
   to the nav's own size (2rem padding + 36px logo + 2rem padding; on
   <=768px 1.25rem padding + 44px menu button + 1.25rem padding) and
   mobile-nav.js overwrites it with the nav's measured height whenever that
   changes, so the solid part always covers the whole nav. */
:root {
    --nav-h: calc(4rem + 36px);
    --nav-fade: 50px;
}
@media (max-width: 768px) {
    :root { --nav-h: calc(2.5rem + 44px); }
}
.nav-top-scrim {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: calc(var(--nav-h) + var(--nav-fade));
    background: linear-gradient(180deg, rgba(0, 0, 0, 0.95) 0, rgba(0, 0, 0, 0.95) var(--nav-h), rgba(0, 0, 0, 0) 100%);
    z-index: 90;
    pointer-events: none;
}

/* i-am-you.html's hero is a bright photo directly behind the nav.
   mix-blend-difference only ever renders pure white/pink when the layer
   beneath is pure black — over a light image it inverts to a muddy
   cream/maroon instead. This page's nav drops the blend mode entirely and
   relies on solid colors + the plain dark scrim above for legibility. */
nav.nav-solid {
    mix-blend-mode: normal;
}
nav.nav-solid .nav-logo img {
    filter: brightness(0) invert(1);
}
nav.nav-solid .nav-link {
    color: #ffffff;
}
nav.nav-solid .nav-link.active,
nav.nav-solid .nav-link:hover {
    /* :hover too: the white rule above outranks the markup's Tailwind
       hover:text-[#d65891], which had silently stopped the pink hover */
    color: var(--pink);
}

/* The fixed nav is a full-width strip; only its logo, links and the phone
   menu button take clicks, so content scrolled underneath it (e.g. gallery
   tabs) stays clickable. Scoped to nav.fixed: the phone menu overlay has its
   own <nav class="mobile-menu-links"> that must keep working. */
nav.fixed { pointer-events: none; }
nav.fixed .nav-logo,
nav.fixed .nav-link,
nav.fixed .nav-toggle { pointer-events: auto; }

/* Mouse Trail Canvas forced to the top */
canvas#webgl {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    z-index: 9999;
    pointer-events: none;
}

#content { position: relative; z-index: 10; }

/* --- Aurora background --- */
.aurora-bg {
    position: fixed;
    inset: 0;
    z-index: 1;
    overflow: hidden;
    pointer-events: none;
}
.aurora-blob {
    position: absolute;
    border-radius: 50%;
    filter: blur(100px);
    will-change: transform;
}
.aurora-blob--1 {
    width: 60vw; height: 60vw;
    top: -15%; left: -15%;
    background: var(--pink);
    opacity: 0.18;
    animation: aurora-drift-a 26s ease-in-out infinite;
}
.aurora-blob--2 {
    width: 55vw; height: 55vw;
    top: 25%; right: -20%;
    background: var(--purple);
    opacity: 0.22;
    animation: aurora-drift-b 30s ease-in-out infinite;
    animation-delay: -8s;
}
.aurora-blob--3 {
    width: 50vw; height: 50vw;
    bottom: -20%; left: 15%;
    background: var(--purple-bright);
    opacity: 0.2;
    animation: aurora-drift-c 22s ease-in-out infinite;
    animation-delay: -14s;
}
.aurora-blob--4 {
    width: 42vw; height: 42vw;
    top: 55%; left: 50%;
    background: var(--purple);
    opacity: 0.19;
    animation: aurora-drift-a 28s ease-in-out infinite;
    animation-delay: -19s;
}
@keyframes aurora-drift-a {
    0%, 100% { transform: translate(0, 0) scale(1); }
    50% { transform: translate(8vw, 6vh) scale(1.15); }
}
@keyframes aurora-drift-b {
    0%, 100% { transform: translate(0, 0) scale(1); }
    50% { transform: translate(-7vw, 9vh) scale(1.1); }
}
@keyframes aurora-drift-c {
    0%, 100% { transform: translate(0, 0) scale(1); }
    50% { transform: translate(6vw, -8vh) scale(1.2); }
}

/* --- Custom Cursor (inverted + morphing) --- */
#cursor-dot, #cursor-ring {
    position: fixed;
    top: 0;
    left: 0;
    pointer-events: none;
    z-index: 10000;
    mix-blend-mode: difference;
    border-radius: 50%;
    will-change: transform;
    opacity: 0;
}

#cursor-dot {
    width: 8px;
    height: 8px;
    background: #fff;
}

#cursor-ring {
    width: 40px;
    height: 40px;
    border: 1px solid #fff;
    transition: width .3s ease, height .3s ease, background-color .3s ease, border-color .3s ease;
}

#cursor-ring.cursor-morph {
    width: 90px;
    height: 90px;
    background: rgba(255, 255, 255, 0.15);
    border-color: transparent;
}

body.has-custom-cursor #cursor-dot,
body.has-custom-cursor #cursor-ring {
    opacity: 1;
}

body.has-custom-cursor,
body.has-custom-cursor a,
body.has-custom-cursor button,
body.has-custom-cursor input,
body.has-custom-cursor textarea,
body.has-custom-cursor .work-row {
    cursor: none;
}

@media (hover: none), (pointer: coarse) {
    #cursor-dot, #cursor-ring { display: none; }
}

/* --- Hero --- */
.hero-container {
    display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100vh; width: 100vw; position: relative;
}

#static-text {
    font-weight: 700; text-transform: uppercase; font-size: 11vw; line-height: 0.9;
    letter-spacing: -0.03em; text-align: center; white-space: nowrap;
}

.hero-line { display: block; }
.hero-word { display: inline-block; }
.hero-letter { display: inline-block; will-change: transform, color; }

.scroll-cue {
    position: absolute; bottom: 3rem; left: 50%; transform: translateX(-50%);
    font-size: 10px; text-transform: uppercase; letter-spacing: 0.3em; opacity: 0.5;
    display: flex; flex-direction: column; align-items: center; gap: 8px;
}
.scroll-cue span {
    width: 1px; height: 32px; background: linear-gradient(to bottom, white, transparent);
    animation: scrollcue 1.8s ease-in-out infinite;
}
@keyframes scrollcue {
    0% { transform: scaleY(0); transform-origin: top; opacity: 0; }
    50% { transform: scaleY(1); transform-origin: top; opacity: 1; }
    51% { transform-origin: bottom; }
    100% { transform: scaleY(0); transform-origin: bottom; opacity: 0; }
}

/* --- Scroll expansion reveal --- */
.reveal-section {
    position: relative;
    height: 250vh;
}
.reveal-pin {
    height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    position: relative;
}
.reveal-media {
    position: relative;
    width: 32vw;
    height: 42vh;
    max-width: 100vw;
    max-height: 100vh;
    overflow: hidden;
    border-radius: 6px;
    will-change: width, height, border-radius;
}
.reveal-media img,
.reveal-media video {
    display: block;
    width: 100%; height: 100%; object-fit: cover; filter: grayscale(0.35) contrast(1.05);
}
.reveal-overlay {
    position: absolute; inset: 0;
    background: linear-gradient(180deg, rgba(0,0,0,0) 40%, rgba(0,0,0,0.6) 100%);
}
.reveal-caption {
    margin-top: 2rem; font-size: 12px; text-transform: uppercase; letter-spacing: 0.3em; opacity: 0.5;
}

/* --- Section titles --- */
.section-title {
    font-weight: 700; font-size: 8vw; margin-bottom: 0; line-height: 0.92; text-transform: uppercase; letter-spacing: -0.02em;
}

/* --- Work index list (hover preview) --- */
.work-header {
    display: flex; justify-content: space-between; align-items: flex-end; margin-bottom: 4rem;
}
.work-count { font-size: 11px; opacity: 0.4; letter-spacing: 0.2em; }

.work-list { border-top: 1px solid rgba(255,255,255,0.15); }

.work-row {
    display: flex;
    align-items: center;
    gap: 2.5rem;
    padding: 2rem 0;
    border-bottom: 1px solid rgba(255,255,255,0.15);
    position: relative;
    color: inherit;
    text-decoration: none;
}
.work-index { font-size: 12px; opacity: 0.4; width: 2ch; }
.work-name {
    flex: 1;
    font-size: clamp(2rem, 6vw, 5rem);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: -0.02em;
    transition: color 0.4s ease, transform 0.4s ease;
}
.work-tag {
    font-size: 11px; opacity: 0.4; text-transform: uppercase; letter-spacing: 0.2em; white-space: nowrap;
}
/* Some rows carry a longer, sentence-style subtitle instead of a short
   caps label — let those wrap naturally instead of forcing uppercase/nowrap. */
.work-tag--subtitle {
    text-transform: none;
    letter-spacing: normal;
    white-space: normal;
    max-width: 42ch;
    font-size: 12px;
}
.work-arrow {
    font-size: 1.5rem; opacity: 0; transform: translateX(-12px);
    transition: opacity 0.4s ease, transform 0.4s ease;
    color: var(--pink);
}
.work-row:hover .work-name { color: var(--pink); transform: translateX(12px); }
.work-row:hover .work-arrow { opacity: 1; transform: translateX(0); }

.work-preview {
    position: fixed;
    top: 0; left: 0;
    width: 320px;
    aspect-ratio: 4 / 3;
    border-radius: 6px;
    overflow: hidden;
    pointer-events: none;
    z-index: 60;
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.9);
    will-change: transform, opacity;
}
.work-preview img {
    width: 100%; height: 100%; object-fit: cover;
}

/* --- Focus / spotlight cards --- */
.focus-grid {
    display: grid;
    grid-template-columns: repeat(1, 1fr);
    gap: 1px;
    background: rgba(255,255,255,0.15);
}
@media (min-width: 768px) {
    .focus-grid { grid-template-columns: repeat(3, 1fr); }
}

.spotlight-card {
    position: relative;
    padding: 3rem 2rem;
    background: rgba(0, 0, 0, 0.2);
    overflow: hidden;
}
.spotlight-card::before {
    content: '';
    position: absolute;
    inset: 0;
    opacity: 0;
    transition: opacity 0.4s ease;
    background: radial-gradient(500px circle at var(--mx, 50%) var(--my, 50%), rgba(214, 88, 145, 0.18), transparent 45%);
    pointer-events: none;
}
.spotlight-card:hover::before { opacity: 1; }
.focus-index { font-size: 11px; opacity: 0.5; letter-spacing: 0.2em; }
.spotlight-card h3 {
    font-size: 1.5rem; font-weight: 500; text-transform: uppercase; margin: 1rem 0 0.75rem;
    line-height: 1.2;
    min-height: 2.4em;
    text-shadow: 0 1px 12px rgba(0, 0, 0, 0.6);
}
.spotlight-card p {
    font-size: 0.9rem; line-height: 1.5; opacity: 0.68; max-width: 32ch;
    text-shadow: 0 1px 8px rgba(0, 0, 0, 0.5);
    text-wrap: balance;
}

/* --- About --- */
.about-content {
    flex: 1 1 auto;
    max-width: 70ch;
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
}
.about-content p {
    font-size: 1.05rem;
    line-height: 1.6;
    opacity: 0.7;
    text-wrap: pretty;
}
.about-content p:first-child {
    font-size: 1.3rem;
    font-weight: 500;
    opacity: 0.9;
}

.about-photo {
    flex: 0 0 auto;
    width: 120%;
    max-width: 480px;
    max-height: calc(100vh - 200px);
    aspect-ratio: 1 / 1;
    border-radius: 6px;
    overflow: hidden;
}
.about-photo img {
    width: 100%; height: 100%; object-fit: cover; display: block;
}

/* --- Tagline --- */
.tagline-text {
    font-size: clamp(20px, 3.2vw, 65px);
    line-height: 1.1;
    min-height: 1.1em;
    font-weight: 300;
    white-space: nowrap;
}

@media (max-width: 768px) {
    .tagline-text { font-size: clamp(12px, 3.8vw, 30px); white-space: nowrap; }
}

.typewriter-text {
    background: linear-gradient(90deg, var(--pink), var(--purple-bright));
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    font-weight: 700;
}
.typewriter-cursor {
    display: inline-block;
    margin-left: 2px;
    color: var(--pink);
    font-weight: 300;
    animation: blink-cursor 1s step-end infinite;
}
@keyframes blink-cursor {
    0%, 50% { opacity: 1; }
    50.01%, 100% { opacity: 0; }
}

/* --- Contact --- */
.contact-input {
    background: transparent; border: none; border-bottom: 1px solid rgba(255,255,255,0.2);
    padding: 15px 0; outline: none; width: 100%; color: white; text-transform: uppercase; font-size: 11px;
    font-family: 'Inter', sans-serif;
    transition: border-color 0.3s ease;
}
.contact-input:focus { border-color: var(--pink); }

.send-btn {
    position: relative;
    align-self: flex-start;
    text-align: left;
    padding: 14px 26px;
    font-weight: 700;
    letter-spacing: 0.3em;
    font-size: 10px;
    text-transform: uppercase;
    color: white;
    background: #000;
    border-radius: 999px;
    isolation: isolate;
}
.send-btn::before {
    content: '';
    position: absolute;
    inset: -2px;
    z-index: -1;
    border-radius: 999px;
    background: conic-gradient(from var(--angle, 0deg), var(--pink), var(--purple-bright), var(--purple), var(--pink));
    animation: rotate-glow 4s linear infinite;
}
.send-btn::after {
    content: '';
    position: absolute;
    inset: 1px;
    z-index: -1;
    border-radius: 999px;
    background: #000;
}
@keyframes rotate-glow {
    to { --angle: 360deg; }
}
@property --angle {
    syntax: '<angle>';
    initial-value: 0deg;
    inherits: false;
}

/* --- Misc --- */
.footer-line {
    width: 100%; height: 1px; background: rgba(255,255,255,0.1);
}

/* --- Mobile nav (≤768px): hamburger + full-screen overlay (mobile-nav.js) --- */
.nav-toggle { display: none; }
.mobile-menu { display: none; }

@media (max-width: 768px) {
    nav.fixed { padding: 1.25rem var(--gutter-mobile); }

    .nav-logo img { height: 28px; }
    nav .nav-links { display: none; }

    .nav-toggle {
        position: relative;
        display: block;
        width: 44px; height: 44px;
        margin-right: -10px; /* lines sit exactly on the gutter edge; the 44px tap area overhangs it */
        padding: 0;
        background: none;
        border: 0;
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
    }
    .nav-toggle-line {
        position: absolute;
        left: 10px;
        width: 24px; height: 1.5px;
        background: #fff;
        transition: transform 0.3s ease;
    }
    .nav-toggle-line:first-child { top: calc(50% - 4.25px); }
    .nav-toggle-line:last-child  { top: calc(50% + 2.75px); }
    html.nav-open .nav-toggle-line:first-child { transform: translateY(3.5px) rotate(45deg); }
    html.nav-open .nav-toggle-line:last-child  { transform: translateY(-3.5px) rotate(-45deg); }

    .mobile-menu {
        position: fixed;
        inset: 0;
        z-index: 200;
        display: flex;
        align-items: center;
        padding: 0 var(--gutter-mobile);
        background: rgba(0, 0, 0, 0.92);
        backdrop-filter: blur(12px);
        -webkit-backdrop-filter: blur(12px);
        opacity: 0;
        visibility: hidden;
        transition: opacity 0.3s ease, visibility 0s linear 0.3s;
    }
    .mobile-menu-links {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 1.25rem;
    }
    .mobile-menu-link {
        font-family: 'Space Grotesk', 'Inter', sans-serif;
        font-weight: 500;
        font-size: clamp(2.25rem, 10vw, 3.5rem);
        line-height: 1;
        letter-spacing: -0.01em;
        text-transform: uppercase;
        color: #fff;
        opacity: 0;
        transform: translateY(12px);
        transition: opacity 0.4s ease, transform 0.4s ease, color 0.3s ease;
    }
    .mobile-menu-link.active { color: var(--pink); }

    /* Open (and while closing): nav (logo + X) is raised above the overlay;
       page scroll locked */
    html.nav-open, html.nav-open body,
    html.nav-closing, html.nav-closing body { overflow: hidden; }
    html.nav-open nav.fixed, html.nav-closing nav.fixed { z-index: 210; }
    html.nav-open .mobile-menu {
        opacity: 1;
        visibility: visible;
        transition: opacity 0.3s ease;
    }
    html.nav-open .mobile-menu-link {
        opacity: 1;
        transform: none;
        transition-delay: calc(0.08s + var(--i) * 0.05s);
    }

    /* Closing (mobile-nav.js holds .nav-closing until this finishes): links
       fade up and out last-first, then the overlay fades while the X morphs
       back into the hamburger. */
    html.nav-closing .mobile-menu-link {
        transform: translateY(-10px);
        transition: opacity 0.25s ease, transform 0.25s ease;
        transition-delay: calc(var(--ri) * 0.05s);
    }
    html.nav-closing .mobile-menu {
        transition: opacity 0.3s ease 0.2s, visibility 0s linear 0.5s;
    }
    html.nav-closing .nav-toggle-line { transition-delay: 0.2s; }
}

/* --- Mobile footer (≤640px, all pages): socials on top, © + wordmark below, centered --- */
@media (max-width: 640px) {
    #content > footer { padding: 0 var(--gutter-mobile) 2.5rem; }
    footer .footer-line + div {
        flex-direction: column-reverse;
        align-items: center;
        gap: 1rem;
        margin-top: 2rem;
        letter-spacing: 0.2em;
    }
    footer .footer-line + div > .flex { gap: 1.75rem; flex-wrap: wrap; justify-content: center; }
}

/* --- Touch devices: no hover preview or hover nudge on the work list --- */
@media (hover: none), (pointer: coarse) {
    .work-preview { display: none; }
    .work-row:hover .work-name { transform: none; }
}

/* --- Homepage, small screens (≤640px). IDs outrank the Tailwind utility
   classes in the markup (px-[10vw], py-32, gap-20, mb-12...), which is what
   lets these override them without touching desktop. --- */
@media (max-width: 640px) {
    /* One side gutter everywhere, matching the nav logo */
    #work, #focus, #about, section.tagline-section, #contact { padding-left: var(--gutter-mobile); padding-right: var(--gutter-mobile); }

    .section-title { font-size: 14vw; }

    /* Hero */
    .hero-container { height: 100vh; height: 100svh; }
    #static-text { font-size: 12.5vw; line-height: 1.2; }
    #static-text .hero-line, #static-text .hero-word, #static-text .hero-letter { line-height: inherit; }
    .scroll-cue { bottom: 1.5rem; }

    /* Scroll reveal */
    /* The pinned frame centers the video, leaving empty frame above it;
       pulling the section up 7vh (over the hero's empty bottom, below the
       Scroll cue) keeps the cue→video gap small. The video still starts
       below the fold, since the frame's top gap (~14vh) exceeds the pull. */
    .reveal-section { height: 180vh; margin-top: -7vh; }
    .reveal-media { width: 84vw; height: 72vh; }

    /* Work list: compact 2-column rows */
    #work { padding-top: 4rem; padding-bottom: 3rem; }
    .work-header { margin-bottom: 2rem; }
    .work-row {
        display: grid;
        grid-template-columns: 2ch 1fr;
        gap: 0 0.6rem; /* row gap 0: desktop's 2.5rem flex gap would split name/tag */
        align-items: start;
        padding: 1.6rem 0;
        /* Largest size that keeps "MUTEK X REEBOK X SVD" on one line at 375–393px,
           with ~10px slack for font-rendering differences */
        --work-name-size: clamp(1.4rem, 6.85vw, 1.8rem);
    }
    /* Index gets the name's line height, so its text centers on the name's first line */
    .work-index { grid-column: 1; grid-row: 1; width: auto; font-size: 11px; line-height: calc(var(--work-name-size) * 1.05); }
    .work-name {
        grid-column: 2; grid-row: 1;
        font-size: var(--work-name-size);
        line-height: 1.05;
    }
    .work-tag {
        grid-column: 2; grid-row: 2;
        font-size: 10px;
        letter-spacing: 0.15em;
        margin-top: 0.6rem;
        white-space: normal;
    }
    .work-arrow { display: none; }

    /* What I Do */
    #focus { padding-top: 3rem; }
    #focus .section-title { margin-bottom: 2rem; }
    .spotlight-card { padding: 1.75rem 1.5rem; }
    .spotlight-card h3 { font-size: 1.2rem; min-height: 0; margin: 0.6rem 0 0.5rem; }
    .spotlight-card p { font-size: 0.9rem; max-width: none; }

    /* About */
    #about { padding-top: 4rem; padding-bottom: 4rem; }
    #about .section-title { margin-bottom: 2rem; }
    #about .about-layout { gap: 2rem; }
    .about-photo { width: 100%; max-width: 100%; min-width: 0; }
    .about-content { gap: 1.1rem; }
    .about-content p { font-size: 0.95rem; line-height: 1.6; }
    .about-content p:first-child { font-size: 1.1rem; line-height: 1.45; }

    /* "Bridging the gap" tagline: phrase on its own line, may wrap;
       main.js reserves the tallest phrase's height so nothing jumps */
    section.tagline-section { padding-top: 4rem; padding-bottom: 4rem; }
    .tagline-text { font-size: 7.5vw; line-height: 1.15; white-space: normal; }
    .tagline-phrase { display: block; }

    /* Contact */
    #contact { padding-top: 4rem; padding-bottom: 3rem; gap: 2rem; }
    #contact-form { gap: 1.75rem; }
    .contact-input { font-size: 16px; } /* ≥16px stops iOS Safari zooming on focus */
    .contact-input::placeholder { font-size: 11px; text-transform: uppercase; } /* placeholder keeps the small desktop look */
}

/* --- Case study pages --- */
.case-tagline {
    display: block;
    font-size: 15px;
    text-transform: uppercase;
    letter-spacing: 0.3em;
    opacity: 0.5;
    margin-bottom: 1.5rem;
}
.case-title {
    font-family: 'Space Grotesk', 'Inter', sans-serif;
    font-weight: 700;
    font-size: clamp(2.5rem, 7vw, 6rem);
    line-height: 0.95;
    text-transform: uppercase;
    letter-spacing: -0.02em;
    margin: 0 0 3.5rem;
}
/* --- Full-bleed case hero (image + overlaid proximity-letter title) --- */
.case-hero {
    position: relative;
    width: 100%;
    height: 100vh;
    min-height: 560px;
    overflow: hidden;
}
.case-hero-media,
.case-hero-media img,
.case-hero-media video {
    width: 100%;
    height: 100%;
    display: block;
    object-fit: cover;
}
.case-hero-scrim {
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(0, 0, 0, 0.2) 0%, rgba(0, 0, 0, 0.1) 35%, rgba(0, 0, 0, 0.8) 100%);
}
.case-hero-content {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 0 10vw 4rem;
    z-index: 2;
}
.case-hero-content .case-tagline {
    opacity: 0.8;
    text-shadow: 0 2px 12px rgba(0, 0, 0, 0.6);
}
.case-hero-title {
    font-family: 'Space Grotesk', 'Inter', sans-serif;
    font-weight: 700;
    font-size: clamp(3rem, 11vw, 9rem);
    line-height: 0.9;
    text-transform: uppercase;
    letter-spacing: -0.02em;
    margin: 0.5rem 0 0;
}
@media (max-width: 640px) {
    .case-hero { height: 70vh; min-height: 420px; }
    .case-hero-content { padding: 0 var(--gutter-mobile) 2.5rem; }
}

/* Koub hero: the source photo is a light, warm-toned product shot (not a
   dark/high-contrast image like the other case studies), so this page gets
   its own object-position (the <img>-based equivalent of background-position
   for a cover-fit image) and a stronger scrim to keep the white title and
   eyebrow readable while the products at the bottom stay visible. */
.case-hero--koub .case-hero-media img { object-position: center 65%; }
.case-hero--koub .case-hero-scrim {
    background: linear-gradient(to top right, rgba(0, 0, 0, 0.65) 0%, rgba(0, 0, 0, 0) 70%);
}

.case-cover,
.case-media {
    width: 100%;
    aspect-ratio: 16 / 9;
    border-radius: 6px;
    overflow: hidden;
}
.case-cover img, .case-cover video,
.case-media img, .case-media video {
    width: 100%; height: 100%; object-fit: cover; display: block;
}

.case-body {
    padding: 2rem 10vw;
    display: flex;
    flex-direction: column;
    gap: 5rem;
}
.case-block h2 {
    font-family: 'Space Grotesk', 'Inter', sans-serif;
    font-weight: 500;
    font-size: clamp(1.5rem, 3vw, 2.25rem);
    text-transform: uppercase;
    letter-spacing: -0.01em;
    margin-bottom: 1.25rem;
}
.case-block p {
    font-size: 1.05rem;
    line-height: 1.7;
    opacity: 0.7;
    max-width: 70ch;
}
.case-block p + p { margin-top: 1.25rem; }

/* Wide text column (no side image) — used for "The Project" so the copy
   uses the majority of the page width instead of sitting in a cramped
   left-hand column. */
.case-block--wide .case-block-columns p { max-width: none; }
@media (min-width: 880px) {
    .case-block--wide .case-block-columns {
        column-count: 2;
        column-gap: 4rem;
    }
    /* Paragraphs may split across the two columns so both end at about the
       same height; at least 2 lines stay together at a split */
    .case-block--wide .case-block-columns { column-fill: balance; }
    .case-block--wide .case-block-columns p { orphans: 2; widows: 2; }
}

/* Plain two-column text block — Process left, Outcome right, no imagery.
   Sits right after "The Project", ahead of the tabbed gallery. */
.process-outcome-split {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 3rem;
}
@media (max-width: 768px) {
    .process-outcome-split { grid-template-columns: 1fr; gap: 2.5rem; }
}

/* Koub only: .case-block--wide's CSS-columns above use column-gap: 4rem,
   but this grid's own gap was 3rem — since both mechanisms split the same
   total width in half, the mismatched gap shifted where each one's second
   column starts (~8px), so Outcome didn't line up with The Project's right
   column above it. Matching the gap to 4rem here makes both column-splits
   compute an identical second-column offset. Scoped to Koub (not the base
   .process-outcome-split rule) since i-am-you.html and mutek.html weren't
   reported as having this issue and shouldn't shift unrequested. */
.process-outcome-split--koub { gap: 4rem; }
@media (max-width: 768px) {
    .process-outcome-split--koub { gap: 2.5rem; }
}

.case-solution-list { margin-top: 1rem; max-width: none; }
@media (min-width: 900px) {
    .case-solution-list { column-count: 2; column-gap: 3rem; }
    .case-solution-list li { break-inside: avoid; }
}

.case-footer-nav {
    margin: 4rem 10vw 3rem;
    padding-top: 3rem;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: 2rem;
    border-top: 1px solid rgba(255,255,255,0.15);
}
.case-nav-link {
    font-family: 'Space Grotesk', 'Inter', sans-serif;
    font-size: clamp(1.1rem, 2.2vw, 1.25rem);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: -0.01em;
    color: inherit;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 0.75rem;
    transition: color 0.4s ease;
}
.case-nav-link:hover { color: var(--pink); }
.case-nav-link .arrow { color: var(--pink); transition: transform 0.4s ease; display: inline-block; }
.case-nav-link:hover .arrow { transform: translateX(6px); }
.case-nav-link--back .arrow { transform: rotate(180deg); }
.case-nav-link--back:hover .arrow { transform: rotate(180deg) translateX(6px); }

/* Mobile-only compact bottom nav (markup lives in each case page); hidden on desktop */
.case-footer-nav-mobile { display: none; }

@media (max-width: 640px) {
    .case-body { padding: 2rem var(--gutter-mobile); gap: 3.5rem; }

    /* One row: "← All Work" left, "Next Project →" right. Desktop's two big
       links are swapped for this compact version. Content above → divider =
       .case-body's 2rem bottom padding + 0.5rem here = 2.5rem. */
    .case-footer-nav { margin: 0.5rem var(--gutter-mobile) 0; padding: 2.5rem 0; display: block; }
    .case-footer-nav > .case-nav-link { display: none; }
    .case-footer-nav-mobile {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: 1.5rem;
    }
    .case-mnav-back,
    .case-mnav-label {
        font-size: 11px;
        text-transform: uppercase;
        letter-spacing: 0.2em;
    }
    /* Two small labels, centered on each other; 44px-tall tap areas */
    .case-mnav-back,
    .case-mnav-next {
        display: inline-flex;
        align-items: center;
        min-height: 44px;
        opacity: 0.7;
        white-space: nowrap;
    }
    .case-mnav-back { gap: 0.5em; }
    .case-mnav-back .arrow, .case-mnav-label .arrow { color: var(--pink); }
}

/* --- Case study media grids (image/video sub-sections within a .case-block) --- */
.case-media-label {
    display: block;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.2em;
    opacity: 0.45;
    margin: 2rem 0 1rem;
}
.case-block > .case-media-label:first-of-type { margin-top: 1.75rem; }

.case-media-grid {
    display: grid;
    gap: 1.5rem;
}
.case-media-grid--2 { grid-template-columns: repeat(2, 1fr); }
.case-media-grid--3 { grid-template-columns: repeat(3, 1fr); }
.case-media-grid--4 { grid-template-columns: repeat(2, 1fr); }

.case-media-grid img,
.case-media-grid video {
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    border-radius: 6px;
    display: block;
}

@media (max-width: 768px) {
    .case-media-grid--3 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
    .case-media-grid--2,
    .case-media-grid--3,
    .case-media-grid--4 {
        grid-template-columns: 1fr;
    }
}

/* --- Tabbed gallery (case study media, one active tab at a time) --- */
.case-tabs {
    display: flex;
    flex-direction: column;
    gap: 2.5rem;
}

.case-tabs-bar {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 2.25rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.15);
}
.case-tab {
    position: relative;
    padding: 0 0 1.1rem;
    background: none;
    border: none;
    font-family: 'Space Grotesk', 'Inter', sans-serif;
    font-size: clamp(0.8rem, 1vw, 0.95rem);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: rgba(255, 255, 255, 0.45);
    cursor: pointer;
    transition: color 0.3s ease;
}
.case-tab::after {
    content: '';
    position: absolute;
    left: 0; right: 0; bottom: -1px;
    height: 2px;
    background: var(--pink);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.35s ease;
}
.case-tab:hover { color: rgba(255, 255, 255, 0.8); }
.case-tab.active { color: #fff; }
.case-tab.active::after { transform: scaleX(1); }

/* Fixed, identical height across all 5 tabs — switching tabs must never
   change the panel's box height, or Publications (right below) would jump
   up/down depending which tab was last open. Every tab's own layout is
   sized to fit inside this exact box (see each tab's rules below); shorter
   content (Prints, Webpage/AR) is simply centered within it rather than
   stretched. */
.case-tab-panel { display: none; }
.case-tab-panel.active {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 560px;
    overflow: hidden;
    animation: case-tab-fade 0.45s ease;
}
.case-tab-panel.active > * { max-width: 100%; max-height: 100%; }
/* Prints deliberately breaks out to 100vw (full-bleed) below — exempt it
   from the generic 100%-of-panel cap above, or that cap silently shrinks
   it right back down to the panel's own width and the breakout does
   nothing. This was the actual reason Prints never visibly got bigger
   across multiple previous attempts: the CSS was correct, this rule was
   overriding it. */
.case-tab-panel.active > .prints-bento { max-width: none; }
@media (max-width: 768px) {
    .case-tab-panel.active { height: auto; max-height: none; overflow: visible; }
}
@keyframes case-tab-fade {
    from { opacity: 0; }
    to { opacity: 1; }
}

@media (max-width: 640px) {
    .case-tabs-bar {
        flex-wrap: nowrap;
        gap: 1.5rem;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
    .case-tab { white-space: nowrap; }
}

/* --- Per-tab media: object-fit: contain everywhere, sized so tab content
   fills the intended content width on every tab (nothing stuck in a
   left-hand column with dead space beside it) --- */

/* Booth Design: left = 2x2 grid of the 4 rendered booth views (each of the
   2 source files is itself a side-by-side composite of 2 views, so each
   half is isolated via object-position — the math is exact, since each
   file's native aspect is precisely 2:1, making each half a true square).
   Right = one real installed-booth photo spanning the full height. */
/* Height-driven (not width-driven): the quad is a perfect square sized to
   the panel's fixed height, so it can never need more vertical room than
   the box provides — that's what was causing the scroll-to-see-row-2 bug.
   The photo panel then fills whatever width remains at that same height. */
/* Root-cause fix: object-fit: contain alone doesn't stop dead space — the
   CONTAINER's own aspect-ratio has to match the image's real aspect ratio,
   or contain just letterboxes inside an oversized box. Real dimensions:
   iamyou-booth-render-01/02.jpg are both exactly 2:1 (3840x1920, 1600x800)
   → quad cells are aspect-ratio: 2/1, not a forced square. booth.jpg is
   actually PORTRAIT (3024x4032 = 3:4), not landscape — that mismatch
   against the old wide cover-fit box is exactly what was clipping its
   right edge. Quad and photo don't share the same height as a result
   (quad's intrinsic height from 2:1 cells is shorter than the full panel
   height); align-items: center on the row keeps them vertically aligned. */
.booth-design-layout {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1.5rem;
    height: 100%;
    width: 100%;
}
/* Was a 2x2 grid showing each of the 2 renders twice (duplicated rows).
   Now a genuine 2-cell vertical stack — one unique image per cell,
   stacked top/bottom instead of duplicated/side-by-side. Each cell's own
   height is (available height - half the gap) / 2, with width following
   from the real 2:1 aspect ratio — same "size the container, don't just
   set object-fit" approach as elsewhere on this page. */
.booth-design-stack {
    flex: 0 0 auto;
    height: 100%;
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
}
.booth-design-stack-cell {
    flex: 0 0 auto;
    height: calc(50% - 0.45rem);
    aspect-ratio: 2 / 1;
    border-radius: 6px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.04);
    display: flex;
    align-items: center;
    justify-content: center;
}
.booth-design-stack-cell img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}
.booth-design-photo {
    flex: 0 0 auto;
    height: 100%;
    aspect-ratio: 3 / 4;
    border-radius: 6px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.04);
    display: flex;
    align-items: center;
    justify-content: center;
}
.booth-design-photo img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}
@media (max-width: 768px) {
    .booth-design-layout { flex-direction: column; height: auto; align-items: stretch; }
    .booth-design-stack { height: auto; width: 100%; }
    .booth-design-photo { flex: none; height: auto; width: 100%; aspect-ratio: 3 / 4; }
}

/* Booth Experience: the source Vimeo clip is a portrait 9:16 recording, not
   16:9 — the video keeps that real ratio so the player fills it with no
   pillarboxing, at the shared fixed height. Video and the photo stack now
   sit directly adjacent (row shrink-wraps to its own content + centers) —
   the previous flex-grow-to-fill-full-width approach left the stack's
   tiles centered in a much wider column than they needed, which read as a
   big gap between the video and the images. */
.booth-exp-tab-grid {
    display: flex;
    align-items: stretch;
    justify-content: center;
    gap: 1.5rem;
    height: 100%;
    width: fit-content;
    margin: 0 auto;
}
.booth-exp-tab-video {
    position: relative;
    flex: 0 0 auto;
    height: 100%;
    aspect-ratio: 9 / 16;
    border-radius: 6px;
    overflow: hidden;
    background: #000;
}
.booth-exp-tab-video iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}
/* Corrected approach: stretching a narrower-aspect tile to match a wider
   tile's width WHILE keeping height fixed is what created dead space —
   once width and height are both externally forced, aspect-ratio has
   nothing left to compute and the image (contain) letterboxes inside the
   mismatched box. Fix: pick a shared WIDTH instead, and let each tile's
   HEIGHT come from ITS OWN exact aspect ratio (width: 100%; aspect-ratio
   set; height omitted so it's derived, not fixed). Both tiles end up the
   same width with zero dead space and zero cropping; heights differ
   slightly (283px / 261px) and align-self: flex-start keeps the column
   from being stretched by the row to the video's full 560px height. Width
   425px solved so both tiles' derived heights + gap sum to ~559px, just
   under the shared panel height. */
.booth-exp-tab-photos {
    flex: 0 0 auto;
    align-self: flex-start;
    width: 425px;
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
}
.booth-exp-photo-tile {
    width: 100%;
    border-radius: 6px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.04);
}
.booth-exp-photo-tile:nth-child(1) { aspect-ratio: 3 / 2; }
.booth-exp-photo-tile:nth-child(2) { aspect-ratio: 1.626; }
.booth-exp-photo-tile img { width: 100%; height: 100%; object-fit: contain; display: block; }
@media (max-width: 768px) {
    .booth-exp-tab-grid { flex-direction: column; height: auto; width: 100%; }
    .booth-exp-tab-video { height: auto; width: 60%; margin: 0 auto; }
    .booth-exp-tab-photos { width: 100%; height: auto; flex-direction: row; justify-content: center; }
    .booth-exp-photo-tile { height: 140px; }
}

/* Shared WIDTH capped the same for all 3 tiles, but the images have
   different aspect ratios (1.5 / 1.493 / 1.592) — at one shared width,
   only the tile whose aspect happens to match gets full-height coverage;
   the other two end up with empty space on the SIDES (their height:auto
   comes out shorter than the shared-width tile, and something has to
   give — in this case it was side padding since width was the fixed
   dimension). Flipping to a shared HEIGHT with width: auto fixes this
   symmetrically: each tile's width is now individually derived from its
   own image's aspect ratio at that one shared height, so no tile is ever
   wider or narrower than what its own image actually needs.
   flex: 0 0 auto (no grow, NO shrink) is deliberate: the <img> is sized
   by its own intrinsic aspect ratio (width: auto), not stretched to the
   container — if flex-shrink narrowed the box below what the image
   needs, the image would overflow its own overflow:hidden box and get
   visibly cropped on the sides. Height 240px chosen so all 3 tiles'
   derived widths + 2×20px gaps sum to ~1140px, safely under the ~1152px
   content area with no risk of the row itself overflowing either. */
.prints-bento {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 20px;
    width: 100%;
}
.prints-tile {
    /* Height is viewport-relative, not a fixed px, because the target
       (.case-tabs-bar / the tab content area) is itself 80vw wide
       (case-body's 10vw padding on each side) — a fixed px height only
       ever matches that width at one specific viewport size. This solves
       for whatever height makes the row's total width (3 tiles + 2×20px
       gaps) equal 80vw at ANY viewport: (80vw - 40px) / sum-of-aspects,
       where sum-of-aspects = 1.5 + 0.7547 + 0.7502 = 3.00491. */
    flex: 0 0 auto;
    height: calc((80vw - 40px) / 3.00491);
    width: auto;
    overflow: hidden;
    border-radius: 6px;
    background: rgba(255, 255, 255, 0.04);
}
.prints-tile img, .prints-tile video { height: 100%; width: auto; object-fit: contain; display: block; }
.prints-tile img { cursor: zoom-in; }
/* Vimeo embeds have no intrinsic size to derive a width from (unlike img/
   video), so the ratio is hardcoded to the standard 16:9 the player renders
   at; height stays the shared fixed dimension and width is derived from
   that ratio, keeping the same "fix one dimension, let the other follow"
   pattern as the img/video tiles instead of stretching to fill the tile. */
.prints-tile iframe { height: 100%; width: auto; aspect-ratio: 16 / 9; border: 0; display: block; }
@media (max-width: 640px) {
    .prints-bento { flex-direction: column; align-items: center; width: 100%; margin-left: 0; }
    .prints-tile { height: auto; width: 80%; }
    .prints-tile img, .prints-tile video { width: 100%; height: auto; }
    .prints-tile iframe { width: 100%; height: auto; }
}

/* Webpage and AR screen: single centered, contained mockup (laptop + phone) */
.tab-media-single {
    max-width: 900px;
    margin: 0 auto;
    height: 560px;
    border-radius: 6px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.04);
    display: flex;
    align-items: center;
    justify-content: center;
}
.tab-media-single img { width: 100%; height: 100%; object-fit: contain; }
.tab-media-single picture { display: contents; }
/* Phones-only swipe layer over the Booth Experience Vimeo player */
.vimeo-swipe-layer { display: none; }
@media (max-width: 768px) {
    .tab-media-single { height: 380px; }
}

/* 3D Avatars: 3 items — portrait booth-mannequin photo, landscape phone-AR
   photo, landscape walking-avatar clip. Height-driven like Booth Design and
   Booth Experience: both the tall tile and the 2-up stack derive their
   width from the SAME shared panel height via aspect-ratio, so neither
   column can end up arbitrarily bigger than the other, and the stack tiles
   can never exceed the fixed height (no more bottom-of-viewport cropping).
   width: fit-content + margin: auto removes the leftover dead zone. */
.avatars-layout {
    display: flex;
    align-items: stretch;
    gap: 1.5rem;
    height: 100%;
    width: fit-content;
    margin: 0 auto;
}
.avatars-tall-tile {
    flex: 0 0 auto;
    height: 100%;
    aspect-ratio: 1242 / 2688;
    border-radius: 6px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.04);
    display: flex;
    align-items: center;
    justify-content: center;
}
.avatars-tall-tile img { width: 100%; height: 100%; object-fit: contain; }
/* Root-cause fix: the previous fixed width: 485px + a shared, approximate
   aspect-ratio: 16/9 forced both tiles into an identical box even though
   the photo (1.626:1) isn't actually 16:9 (1.778:1) — that ~9% mismatch
   was the dead space. Explicit height per tile (half the panel height,
   minus half the gap) + each tile's own EXACT real aspect ratio removes
   it entirely; width is no longer forced, so no natural-image-width
   fallback risk (both dimensions are already fully determined by height
   + aspect-ratio, with nothing left for the browser to guess at). */
/* Same corrected approach as Booth Experience's stack: shared WIDTH, each
   tile's height derived from its own exact aspect ratio (not stretched at
   a fixed height) — that's what removes the dead space this tab was
   being used as the "this looks right" reference for, even though it had
   the identical latent issue at a slightly smaller, less obvious gap.
   Width 463px solved so both tiles' derived heights + gap sum to ~559px. */
.avatars-stack {
    flex: 0 0 auto;
    align-self: flex-start;
    width: 463px;
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
}
.avatars-stack-tile {
    width: 100%;
    border-radius: 6px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.04);
}
.avatars-stack-tile:nth-child(1) { aspect-ratio: 1.626; }
.avatars-stack-tile:nth-child(2) { aspect-ratio: 854 / 480; }
.avatars-stack-tile img, .avatars-stack-tile video { width: 100%; height: 100%; object-fit: contain; display: block; }
@media (max-width: 640px) {
    .avatars-layout { flex-direction: column; align-items: center; height: auto; width: 100%; }
    .avatars-tall-tile { height: auto; width: 60%; max-width: 220px; margin: 0 auto; }
    .avatars-stack { height: auto; width: 100%; }
}

/* --- Publications: 2x2 grid, all 4 tiles the same fixed-height card so
   the mismatched native embed sizes (FB/LinkedIn portrait-ish, YouTube
   16:9) don't produce a lopsided layout. Sized so the whole grid fits
   within a normal viewport height without scrolling. --- */
#publications { scroll-margin-top: 140px; }
.pub-grid-2x2 {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1.5rem;
}
.pub-card { display: flex; flex-direction: column; gap: 0.6rem; }
.pub-label {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.2em;
    opacity: 0.45;
}
.pub-card-embed {
    position: relative;
    width: 100%;
    height: 300px;
    border-radius: 6px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.1);
}
.pub-card-embed iframe {
    position: absolute; inset: 0; width: 100%; height: 100%; border: 0;
}
.pub-card-link {
    position: relative;
    display: block;
    width: 100%;
    height: 300px;
    border-radius: 6px;
    overflow: hidden;
    text-decoration: none;
    color: inherit;
}
.pub-card-link img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.4s ease;
}
.pub-card-link:hover img { transform: scale(1.05); }
.pub-card-link-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: flex-end;
    padding: 1.5rem;
    background: linear-gradient(180deg, rgba(0, 0, 0, 0) 45%, rgba(0, 0, 0, 0.8) 100%);
}
.pub-card-link-text {
    font-family: 'Space Grotesk', 'Inter', sans-serif;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: -0.01em;
    font-size: 1rem;
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    transition: color 0.4s ease;
}
.pub-card-link .arrow { color: var(--pink); transition: transform 0.4s ease; display: inline-block; }
.pub-card-link:hover .pub-card-link-text { color: var(--pink); }
.pub-card-link:hover .arrow { transform: translateX(6px); }

@media (max-width: 768px) {
    .pub-grid-2x2 { grid-template-columns: 1fr; }
    .pub-card-embed, .pub-card-link { height: 260px; }
}

/* --- Design Dump grid --- */
.dump-tagline {
    margin-top: 1.5rem;
    font-size: clamp(18px, 1.4vw, 20px);
    line-height: 1.5;
    opacity: 0.5;
    max-width: 60ch;
}

.dump-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 2.25rem;
}
@media (max-width: 1024px) {
    .dump-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
    .dump-grid { grid-template-columns: 1fr; }
}

.dump-card {
    display: flex;
    flex-direction: column;
    border-radius: 6px;
    overflow: hidden;
    background: rgba(0, 0, 0, 0.35);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border: 1px solid rgba(255, 255, 255, 0.1);
    box-shadow: 0 20px 40px rgba(0, 0, 0, 0.35);
    transition: transform 0.4s ease, border-color 0.4s ease, box-shadow 0.4s ease;
    cursor: pointer;
}
.dump-card:hover {
    transform: scale(1.025);
    border-color: var(--pink);
    box-shadow: 0 0 0 1px rgba(214, 88, 145, 0.4), 0 25px 50px rgba(0, 0, 0, 0.45);
}

/* Image block: tag pills + "Click to View" button over the image */
.dump-media {
    position: relative;
    aspect-ratio: 4 / 3;
    overflow: hidden;
}
.dump-img {
    position: absolute; inset: 0;
    width: 100%; height: 100%; object-fit: cover;
    transition: transform 0.6s ease;
}
.dump-card:hover .dump-img { transform: scale(1.07); }

/* Darkening layer on hover so the button reads over any image */
.dump-media::after {
    content: '';
    position: absolute; inset: 0;
    z-index: 2;
    background: rgba(0, 0, 0, 0.25);
    opacity: 0;
    transition: opacity 0.35s ease;
    pointer-events: none;
}
.dump-card:hover .dump-media::after { opacity: 1; }

.dump-pills {
    position: absolute;
    top: 1rem; left: 1rem; right: 1rem;
    z-index: 4;
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    pointer-events: none;
}
.dump-pill {
    max-width: 100%;
    overflow-wrap: anywhere;
    padding: 0.4em 0.9em;
    font-family: 'Inter', sans-serif;
    font-size: 10px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: #fff;
    background: rgba(0, 0, 0, 0.45);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: 999px;
}

/* "Click to View": dark pill with a blurred brand-gradient glow behind the label */
.dump-view-btn {
    position: absolute;
    top: 50%; left: 50%;
    z-index: 3;
    height: 44px;
    padding: 0 1.4rem;
    border-radius: 999px;
    background: #0b0b0f;
    overflow: hidden;
    display: inline-flex;
    align-items: center;
    pointer-events: none;
    opacity: 0;
    transform: translate(-50%, -40%);
    transition: opacity 0.35s ease, transform 0.35s ease;
}
.dump-view-glow {
    position: absolute; inset: 0;
    background: linear-gradient(90deg, var(--purple-bright), var(--purple), var(--pink));
    filter: blur(8px);
    opacity: 0.4;
    transition: opacity 0.5s ease;
}
.dump-view-label {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: #fff;
    font-family: 'Inter', sans-serif;
    font-size: 11px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.15em;
    white-space: nowrap;
}
.dump-view-arrow {
    color: rgba(255, 255, 255, 0.9);
    transition: transform 0.3s ease;
}
.dump-card:hover .dump-view-btn { opacity: 1; transform: translate(-50%, -50%); }
.dump-card:hover .dump-view-glow { opacity: 0.8; }
.dump-card:hover .dump-view-arrow { transform: translate(2px, -2px); }

/* Label wording: "Click to View" for a mouse, "Tap to View" on touch screens */
.dump-view-text--tap { display: none; }
@media (hover: none) and (pointer: coarse) {
    .dump-view-text--click { display: none; }
    .dump-view-text--tap { display: inline; }
}

/* Touch: no hover, so the button is always shown and the overlay is dropped */
@media (hover: none) {
    .dump-view-btn { opacity: 1; transform: translate(-50%, -50%); }
    .dump-media::after { display: none; }
}

/* Text block: sits below the image, on the card's own glass background */
.dump-content {
    padding: 1.5rem 1.5rem 1.75rem;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}
/* Every card is the same height: the title always takes exactly 2 lines and
   the description exactly 3 (reserved with min-height, cut with an ellipsis
   if longer), so titles and descriptions start at the same height in every
   card of every row */
.dump-title {
    font-family: 'Space Grotesk', 'Inter', sans-serif;
    font-weight: 500;
    font-size: 1.15rem;
    line-height: 1.3;
    text-transform: uppercase;
    letter-spacing: -0.01em;
    min-height: calc(2 * 1.3em);
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
}
.dump-excerpt {
    font-size: 0.88rem;
    line-height: 1.55;
    opacity: 0.55;
    min-height: calc(3 * 1.55em);
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    overflow: hidden;
}

/* --- Global lightbox for case-tab-panel images (shared, driven by main.js) --- */
.lightbox-overlay {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.9);
    cursor: zoom-out;
    animation: lightbox-fade 0.2s ease;
}
.lightbox-img {
    max-width: 90vw;
    max-height: 90vh;
    object-fit: contain;
    cursor: default;
}
.lightbox-close {
    position: fixed;
    top: 24px;
    right: 32px;
    background: none;
    border: none;
    color: #fff;
    font-size: 2.5rem;
    line-height: 1;
    opacity: 0.8;
    cursor: pointer;
    transition: opacity 0.2s ease;
}
.lightbox-close:hover { opacity: 1; }
/* Everything Else page variant: blurred backdrop + Vimeo frame sized from data-ratio (--r) */
.dump-lightbox {
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
}
.dump-lightbox-frame {
    width: min(90vw, calc(85vh * var(--r)));
    height: min(calc(90vw / var(--r)), 85vh);
    border: 0;
    border-radius: 6px;
    background: #000;
}
.dump-lightbox-img { max-height: 85vh; }
@keyframes lightbox-fade {
    from { opacity: 0; }
    to { opacity: 1; }
}

/* A Digital Eye gallery: 2 rows of 2, video + 3 images. Same "hug"
   technique as the I AM YOU Prints tab: within a row every tile shares one
   height and takes its width from its own real aspect ratio, so nothing is
   cropped, stretched or letterboxed. Each row's height is
   (content width - gap) / (sum of that row's aspect ratios), so both rows
   span exactly the content column. 100cqw = the gallery's own width (the
   text column), which unlike vw doesn't include a desktop scrollbar.
   Ratios: video 16:9; digitaleye_1 1536x1024 = 1.5;
   digitaleye_front 2400x1662 = 1.44404; digitaleye_2 2400x1277 = 1.8794.
   Row gap = column gap. Phones (<=640px) use the carousel further down. */
.deye-grid {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
}
.deye-grid-row {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 1.5rem;
    height: 340px;
}
.deye-grid-cell {
    height: 100%;
    width: auto;
    border-radius: 6px;
    overflow: hidden;
}
.deye-grid-cell img {
    height: 100%;
    width: auto;
    object-fit: contain;
    display: block;
}
.deye-grid-cell iframe {
    height: 100%;
    width: 100%;
    aspect-ratio: 426 / 240;
    border: 0;
    display: block;
}
@media (min-width: 641px) {
    .deye-grid { container-type: inline-size; }
    .deye-grid-row { justify-content: flex-start; }
    .deye-grid-row:nth-child(1) { height: calc((100cqw - 1.5rem) / (16 / 9 + 1.5)); }
    .deye-grid-row:nth-child(2) { height: calc((100cqw - 1.5rem) / (1.44404 + 1.8794)); }
    .deye-grid-cell { flex: none; }
    .deye-video-card { aspect-ratio: 16 / 9; }
    .deye-video-card iframe { aspect-ratio: auto; }
}
@media (max-width: 640px) {
    .deye-grid-row { flex-direction: column; height: auto; }
    .deye-grid-cell { height: auto; width: 90%; max-width: 420px; margin: 0 auto; }
    .deye-grid-cell img { width: 100%; height: auto; }
}

/* --- Koub gallery (Logo System / Bilingual Wordmark / Signage / Packaging /
   Merch & Print). Same "hug" pattern used everywhere else: a shared height,
   width: auto per tile, each tile's own real aspect ratio deriving its width.
   Signage, Packaging and Merch & Print each need their row's total derived
   width to land at the panel's own content width (~1152px at the site's
   1440px reference viewport, i.e. 80vw minus the two 10vw side paddings), so
   each row uses its own reduced shared height (see per-row comments) instead
   of the full 560px .case-tab-panel height — the panel itself stays 560px
   and simply centers the shorter row inside it, same as Booth Design. */

/* Logo System / Bilingual Wordmark: single image, hugging its own aspect
   ratio at the full panel height (a width:auto variant of .tab-media-single,
   which forces a fixed 900px box instead). */
.koub-media-hug {
    height: 100%;
    width: auto;
    max-width: 100%;
    margin: 0 auto;
    border-radius: 6px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.04);
    display: flex;
    align-items: center;
    justify-content: center;
}
.koub-media-hug img { height: 100%; width: auto; object-fit: contain; display: block; cursor: zoom-in; }
/* Social Concept: <picture> (swaps the grid for a 1px placeholder on phones)
   is layout-transparent, so the grid <img> sizes exactly as before */
.koub-social-grid picture { display: contents; }
/* The 9-post carousel is phones-only */
.koub-social-carousel { display: none; }

/* Signage: lightbox sign (4500x3000, 3:2) at full row height; frame sign and
   awning (both 4000x3000, 4:3) stacked to its right at half height each.
   Row height solved at 525px so 1.5*525 + 24 (gap) + (4/3)*((525-14.4)/2)
   ~= 1152px, the panel's content width at 1440px. */
.koub-signage-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1.5rem;
    height: 525px;
    width: fit-content;
    margin: 0 auto;
}
.koub-signage-lightbox {
    flex: 0 0 auto;
    height: 100%;
    width: auto;
    border-radius: 6px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.04);
}
.koub-signage-stack {
    flex: 0 0 auto;
    height: 100%;
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
}
.koub-signage-stack-cell {
    flex: 0 0 auto;
    height: calc(50% - 0.45rem);
    width: auto;
    border-radius: 6px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.04);
}
.koub-signage-lightbox img,
.koub-signage-stack-cell img { height: 100%; width: auto; object-fit: contain; display: block; cursor: zoom-in; }

/* Packaging & Merch (merged): 7 images in 2 rows, same hug pattern as
   everywhere else (shared height per row, width: auto per tile). Panel stays
   the site's fixed 560px; each row's own height is solved independently so
   its total derived width lands within the ~1152px tab-bar content width at
   the 1440px reference viewport (the two rows land at different heights
   because they have different tile counts/aspect ratios).
   Row 1 — cups (4000x3000, 4:3), glass (3333x5000 portrait, 2:3), bag
   (6000x4500, 4:3), stickers (4000x3000, 4:3): sum of ratios 4.6666, so
   4.6666*231 + 3*24 (gaps) ~= 1150px. Height: 231px.
   Row 2 — tote lettering, tote pattern (both 3000x2000, 3:2) and loyalty
   card (4500x3000, 3:2): sum of ratios 4.5, so 4.5*245 + 2*24 (gaps) ~=
   1150.5px. Height: 245px. */
.koub-pm-grid {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.9rem;
}
.koub-pm-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1.5rem;
    width: fit-content;
    margin: 0 auto;
}
.koub-pm-row--1 { height: 231px; }
.koub-pm-row--2 { height: 245px; }
.koub-pm-tile {
    flex: 0 0 auto;
    height: 100%;
    width: auto;
    border-radius: 6px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.04);
}
.koub-pm-tile img { height: 100%; width: auto; object-fit: contain; display: block; cursor: zoom-in; }

@media (max-width: 768px) {
    .koub-media-hug { height: auto; width: 90%; max-width: 420px; }
    .koub-signage-row {
        flex-direction: column;
        height: auto;
        width: 100%;
    }
    .koub-pm-row {
        flex-direction: column;
        height: auto;
        width: 100%;
    }
    .koub-signage-lightbox, .koub-signage-stack,
    .koub-pm-tile {
        height: auto;
        width: 90%;
        max-width: 420px;
        margin: 0 auto;
    }
    .koub-signage-stack-cell {
        height: auto;
        width: 100%;
    }
    .koub-media-hug img,
    .koub-signage-lightbox img, .koub-signage-stack-cell img,
    .koub-pm-tile img {
        width: 100%;
        height: auto;
    }
}


/* ==========================================================================
   Case-study pages, mobile (≤640px). Placed last so it overrides the older
   ≤768px per-tab rules above. Desktop is untouched.
   ========================================================================== */

/* Aurora glow on case pages. The desktop blobs are sized in vw but blurred a
   fixed 100px, so on a ~390px screen each blob is ~200px wide under a 100px
   blur (smeared to near-nothing), and positioned mostly off-screen. Mobile
   gets 3 big, lighter-blurred blobs placed around the viewport edges
   (the layer is fixed, so the glow stays behind content while scrolling).
   Animation stays transform-only. */
@media (max-width: 640px) {
    .aurora-bg--case .aurora-blob { filter: blur(60px); }
    .aurora-bg--case .aurora-blob--4 { display: none; }
    .aurora-bg--case .aurora-blob--1 { width: 110vw; height: 110vw; top: -30vw; left: -50vw; opacity: 0.3; }
    .aurora-bg--case .aurora-blob--2 { width: 120vw; height: 120vw; top: 30%; left: auto; right: -65vw; opacity: 0.5; }
    .aurora-bg--case .aurora-blob--3 { width: 110vw; height: 110vw; top: auto; bottom: -45vw; left: -35vw; opacity: 0.35; }
}

/* Tabs bar (all case pages with tabs): horizontal swipe only, no scrollbar,
   no grey rule (only the active tab's pink underline), edge fades that
   main.js toggles (.is-scrolled / .is-at-end) as the bar scrolls. */
@media (max-width: 640px) {
    .case-tabs-bar {
        overflow-x: auto;
        overflow-y: hidden;
        overscroll-behavior-x: contain;
        scrollbar-width: none;
        border-bottom: 0;
        --fade-l: 0px;
        --fade-r: 2.5rem;
        -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 var(--fade-l), #000 calc(100% - var(--fade-r)), transparent 100%);
        mask-image: linear-gradient(90deg, transparent 0, #000 var(--fade-l), #000 calc(100% - var(--fade-r)), transparent 100%);
    }
    .case-tabs-bar::-webkit-scrollbar { display: none; }
    .case-tabs-bar.is-scrolled { --fade-l: 2.5rem; }
    .case-tabs-bar.is-at-end { --fade-r: 0px; }
    .case-tab { -webkit-tap-highlight-color: transparent; }
    .case-tab::after { bottom: 0; }
    /* Pink focus outline for keyboard users only. :focus-visible alone isn't
       enough: some browsers (iOS Safari) match it after a tap, which drew the
       pink box around a tapped tab. main.js sets html.kbd-nav on Tab/arrow
       keys and clears it on any pointer/touch. */
    .case-tab:focus, .case-tab:focus-visible { outline: none; }
    html.kbd-nav .case-tab:focus-visible { outline: 2px solid var(--pink); outline-offset: -2px; }
}

/* --- Koub (≤640px) --- */
@media (max-width: 640px) {
    /* Hero: like desktop, the photo starts at the very top of the page with
       the nav (and its fade) on top of it. Natural shape, but at least 48svh
       tall; when the natural height is less (it is on phones: 1.79:1), cover
       fills that height, keeping the products in frame. The photo fades into
       the page background over its last 48px (mask); the title and label
       sit outside that mask and stay fully opaque. */
    .page-koub .case-hero { height: auto; min-height: 0; padding-top: 0; }
    .page-koub .case-hero-media {
        height: auto;
        -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 48px), transparent 100%);
        mask-image: linear-gradient(180deg, #000 calc(100% - 48px), transparent 100%);
    }
    .page-koub .case-hero-media img {
        width: 100%;
        height: auto;
        min-height: 40vh;
        min-height: 40svh;
        object-fit: cover;
        object-position: center 60%;
    }
    /* Text gradient: a pseudo-element on the photo wrapper (the separate
       .case-hero-scrim element is switched off on phones). It sits above the
       photo (z-index 1) and below the text (.case-hero-content, z-index 2),
       and is inside the wrapper's 48px bottom-fade mask, so it fades into
       the page together with the photo. */
    .page-koub .case-hero-scrim { display: none; }
    .page-koub .case-hero-media { position: relative; }
    .page-koub .case-hero-media::after {
        content: "";
        position: absolute;
        inset: 0;
        pointer-events: none;
        z-index: 1;
        background: linear-gradient(to top, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.5) 20%, rgba(0, 0, 0, 0.22) 38%, rgba(0, 0, 0, 0) 55%);
    }
    .page-koub .case-hero-content { z-index: 2; }
    .page-koub .case-hero-content { padding: 0 var(--gutter-mobile) 0.75rem; }
    .page-koub .case-hero-content .case-tagline {
        margin-bottom: 0;
        letter-spacing: 0.25em;
        opacity: 1;
        color: #fff;
        text-shadow: 0 1px 12px rgba(0, 0, 0, 0.45);
    }
    .page-koub .case-hero-title {
        margin-top: 0.5rem;
        font-size: clamp(2.25rem, 11vw, 3rem);
        text-shadow: 0 1px 12px rgba(0, 0, 0, 0.45);
    }

    /* Body text matches the homepage About paragraphs */
    .page-koub .case-block p, .page-iay .case-block p { font-size: 0.95rem; line-height: 1.6; }
    .page-koub .case-block p + p, .page-iay .case-block p + p { margin-top: 1.1rem; }

    /* Panels size to their own content (no reserved height), so the
       counter/image always sits 2.5rem above the divider */
    .page-koub .case-tab-panel.active {
        flex-direction: column;
        justify-content: flex-start;
        align-items: stretch;
    }
    .page-koub .case-tab-panel.active > * { width: 100%; max-width: 100%; }

    /* One image-area height for every tab (see --carousel-h below), plus the
       counter line (an invisible placeholder on single-image tabs), so the
       divider/nav/footer never move when switching tabs. */
    .page-koub {
        --carousel-widest: 1.5;
        --carousel-h: calc((100vw - 2 * var(--gutter-mobile)) * 0.8 / var(--carousel-widest));
    }
    .carousel-counter--placeholder { visibility: hidden; }

    /* Single-image tabs: same height as a carousel slide, left-aligned; an
       image wider than the content width is scaled to fit and centered
       vertically in the same --carousel-h box */
    .page-koub .koub-media-hug {
        width: 100%;
        max-width: none;
        height: var(--carousel-h);
        margin: 0;
        display: flex;
        align-items: center;
        justify-content: flex-start;
        background: none;
        border-radius: 0;
        overflow: visible;
    }
    .page-koub .koub-media-hug img { width: auto; height: auto; max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 6px; }
    .page-koub .koub-social-grid { display: none; }
    .page-koub .koub-social-carousel { display: flex; }

    /* Multi-image tabs: horizontal scroll-snap carousel. Rows/stacks are
       flattened (display: contents) so every image is one slide.
       Every image shares one height; each slide's width follows its own
       image's ratio (no frame, no bars). --carousel-h (set on .page-koub
       above) puts the widest carousel image (3:2: sign lightbox, totes,
       loyalty card) at 80% of the content width: 0.8 × 84vw ÷ 1.5 = 44.8vw
       (176px at 393px wide). The widest single image, the 1.79:1 wordmark /
       logo system, is 94% of the content width at that height, so it fits.
       The track starts exactly at the text margin (so the snapped image's
       left edge lines up with the text and earlier images are clipped, never
       peeking into the gutter) and bleeds to the right screen edge, where
       the next image peeks in. */
    .page-koub [data-carousel] {
        display: flex;
        flex-direction: row;
        justify-content: flex-start; /* desktop Signage row centers; that would push overflow off the unreachable left */
        align-items: flex-start;
        gap: 0.75rem;
        width: auto;
        max-width: none;
        height: auto;
        margin: 0 calc(-1 * var(--gutter-mobile)) 0 0;
        padding: 0;
        overflow-x: auto;
        overflow-y: hidden;
        overscroll-behavior-x: contain;
        scroll-snap-type: x mandatory;
        scroll-padding-left: 0;
        scrollbar-width: none;
    }
    .page-koub .case-tab-panel.active > [data-carousel] { width: auto; max-width: none; }
    .page-koub [data-carousel]::-webkit-scrollbar { display: none; }
    /* Trailing spacer: lets the last image snap to the left margin too
       (mandatory snapping never rests past the last snap point) */
    .page-koub [data-carousel]::after { content: ''; flex: 0 0 calc(100vw - 2 * var(--gutter-mobile)); }
    .page-koub .koub-signage-stack,
    .page-koub .koub-pm-row { display: contents; }
    .page-koub .koub-signage-lightbox,
    .page-koub .koub-signage-stack-cell,
    .page-koub .koub-pm-tile,
    .page-koub .koub-social-slide {
        flex: 0 0 auto;
        width: auto;
        max-width: none;
        height: var(--carousel-h);
        margin: 0;
        aspect-ratio: auto;
        background: none;
        scroll-snap-align: start;
    }
    .page-koub .koub-social-slide { border-radius: 6px; overflow: hidden; }
    .page-koub .koub-signage-lightbox img,
    .page-koub .koub-signage-stack-cell img,
    .page-koub .koub-pm-tile img,
    .page-koub .koub-social-slide img { height: 100%; width: auto; max-width: none; object-fit: contain; display: block; cursor: zoom-in; }
    /* Lazy images have no intrinsic size until loaded; reserve the square box
       so the track (and counter) are correct before they arrive */
    .page-koub .koub-social-slide img { aspect-ratio: 1 / 1; }
}

/* Carousel "1 / 7" counter (created by main.js; mobile only) */
.carousel-counter { display: none; }
@media (max-width: 640px) {
    .carousel-counter {
        display: block;
        margin-top: 0.9rem;
        font-size: 11px;
        text-transform: uppercase;
        letter-spacing: 0.2em;
        opacity: 0.6;
        font-variant-numeric: tabular-nums;
    }
}

/* Lightbox, mobile gallery mode (main.js): 44px close target, prev/next,
   counter; page scroll locked while open */
.lightbox-prev, .lightbox-next, .lightbox-counter { display: none; }
@media (max-width: 640px) {
    html.lightbox-open, html.lightbox-open body { overflow: hidden; }
    .lightbox-overlay { touch-action: pan-y pinch-zoom; }
    .lightbox-img { max-width: 92vw; max-height: 78vh; border-radius: 6px; }
    .lightbox-close {
        top: calc(env(safe-area-inset-top, 0px) + 10px);
        right: 10px;
        width: 44px; height: 44px;
        display: flex; align-items: center; justify-content: center;
        font-size: 2rem;
        -webkit-tap-highlight-color: transparent;
    }
    .lightbox-prev, .lightbox-next {
        position: fixed;
        bottom: calc(env(safe-area-inset-bottom, 0px) + 1.25rem);
        width: 44px; height: 44px;
        display: flex; align-items: center; justify-content: center;
        border-radius: 999px;
        border: 1px solid rgba(255, 255, 255, 0.2);
        background: rgba(0, 0, 0, 0.4);
        color: #fff;
        font-size: 1.1rem;
        -webkit-tap-highlight-color: transparent;
    }
    .lightbox-prev { left: var(--gutter-mobile); }
    .lightbox-next { right: var(--gutter-mobile); }
    .lightbox-prev:disabled, .lightbox-next:disabled { opacity: 0.25; }
    .lightbox-counter {
        display: block;
        position: fixed;
        left: 50%;
        bottom: calc(env(safe-area-inset-bottom, 0px) + 1.25rem + 14px);
        transform: translateX(-50%);
        font-size: 11px;
        text-transform: uppercase;
        letter-spacing: 0.2em;
        opacity: 0.6;
        font-variant-numeric: tabular-nums;
    }
    .lightbox-overlay.is-single .lightbox-prev,
    .lightbox-overlay.is-single .lightbox-next,
    .lightbox-overlay.is-single .lightbox-counter { display: none; }
}


/* --- I AM YOU (≤640px) --- */
@media (max-width: 640px) {
    /* Hero: same rules as the finished Koub hero (photo from the very top
       behind the nav, min 40svh with cover only when needed, one bottom
       gradient gone by 55%, 48px soft fade into the page, 90px nav fade). */
    .page-iay .case-hero { height: auto; min-height: 0; padding-top: 0; }
    .page-iay .case-hero-media {
        position: relative;
        height: auto;
        -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 48px), transparent 100%);
        mask-image: linear-gradient(180deg, #000 calc(100% - 48px), transparent 100%);
    }
    .page-iay .case-hero-media img {
        width: 100%;
        height: auto;
        min-height: 40vh;
        min-height: 40svh;
        object-fit: cover;
        object-position: 30% 40%; /* keeps the left face (eyes, nose) in frame */
    }
    .page-iay .case-hero-scrim { display: none; }
    .page-iay .case-hero-media::after {
        content: "";
        position: absolute;
        inset: 0;
        pointer-events: none;
        z-index: 1;
        background: linear-gradient(to top, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.5) 20%, rgba(0, 0, 0, 0.22) 38%, rgba(0, 0, 0, 0) 55%);
    }
    .page-iay .case-hero-content { z-index: 2; padding: 0 var(--gutter-mobile) 0.75rem; }
    .page-iay .case-hero-content .case-tagline {
        font-size: 12px;
        letter-spacing: 0.15em; /* one line at 375–393px */
        white-space: nowrap;
        margin-bottom: 0;
        opacity: 1;
        color: #fff;
        text-shadow: 0 1px 12px rgba(0, 0, 0, 0.45);
    }
    .page-iay .case-hero-title {
        margin-top: 0.5rem;
        font-size: clamp(2.25rem, 11vw, 3rem);
        text-shadow: 0 1px 12px rgba(0, 0, 0, 0.45);
    }

    /* Gallery: every slide in every tab is the same card as MUTEK's "Final
       Installation" photo: 80% of the content width (~67vw) at 264:338;
       media fill it (cover) around a per-image focus point (--pos, set
       inline in the markup). */
    .page-iay { --iay-card-w: calc((100vw - 2 * var(--gutter-mobile)) * 0.8); }

    .page-iay .case-tab-panel.active {
        flex-direction: column;
        justify-content: flex-start;
        align-items: stretch;
    }
    .page-iay .case-tab-panel.active > * { width: 100%; max-width: 100%; }

    /* Carousels: same component as Koub. Track starts on the text margin,
       bleeds to the right screen edge; trailing spacer lets the last card
       snap to the margin too. */
    .page-iay [data-carousel] {
        display: flex;
        flex-direction: row;
        justify-content: flex-start;
        align-items: flex-start;
        gap: 0.75rem;
        width: auto;
        max-width: none;
        height: auto;
        margin: 0 calc(-1 * var(--gutter-mobile)) 0 0;
        padding: 0;
        overflow-x: auto;
        overflow-y: hidden;
        overscroll-behavior-x: contain;
        scroll-snap-type: x mandatory;
        scrollbar-width: none;
    }
    .page-iay .case-tab-panel.active > [data-carousel] { width: auto; max-width: none; }
    .page-iay [data-carousel]::-webkit-scrollbar { display: none; }
    .page-iay [data-carousel]::after { content: ''; flex: 0 0 calc(100vw - 2 * var(--gutter-mobile)); }
    .page-iay .booth-design-stack,
    .page-iay .booth-exp-tab-photos,
    .page-iay .avatars-stack { display: contents; }

    .page-iay .booth-design-stack-cell,
    .page-iay .booth-design-photo,
    .page-iay .booth-exp-tab-video,
    .page-iay .booth-exp-photo-tile,
    .page-iay .prints-tile,
    .page-iay .avatars-tall-tile,
    .page-iay .avatars-stack-tile,
    .page-iay .tab-media-single {
        position: relative;
        flex: 0 0 var(--iay-card-w);
        width: var(--iay-card-w);
        max-width: none;
        height: auto;
        aspect-ratio: 264 / 338;
        margin: 0;
        border-radius: 6px;
        overflow: hidden;
        background: none;
        display: block;
        scroll-snap-align: start;
    }
    .page-iay .booth-design-stack-cell img,
    .page-iay .booth-design-photo img,
    .page-iay .booth-exp-photo-tile img,
    .page-iay .prints-tile img,
    .page-iay .avatars-tall-tile img,
    .page-iay .avatars-stack-tile img,
    .page-iay .avatars-stack-tile video {
        width: 100%;
        height: 100%;
        max-width: none;
        max-height: none;
        object-fit: cover;
        object-position: var(--pos, 50% 50%);
        border-radius: 0;
        display: block;
    }
    .page-iay .case-tab-panel img { cursor: zoom-in; }

    /* Booth Experience: the 9:16 Vimeo player fills the card like cover
       (full card width, so its own ratio means no bars). It's anchored to the
       card's bottom so the player's control bar stays visible; the overflow
       is trimmed from the top. */
    .page-iay .booth-exp-tab-video iframe {
        position: absolute;
        inset: auto auto 0 0;
        width: 100%;
        height: auto;
        aspect-ratio: 9 / 16;
    }
    .page-iay .vimeo-swipe-layer {
        display: block;
        position: absolute;
        top: 0; left: 0; right: 0;
        bottom: 48px; /* player's control bar stays directly reachable */
        z-index: 2;
        background: transparent;
        border: 0;
        padding: 0;
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
    }

    /* Webpage and AR screen: no card. The (tightly cropped) mockup runs
       the full content width, centered vertically in a box exactly as tall
       as the other tabs' cards, so the tab height doesn't change. The
       laptop is 80.7% of the file's width; scale(1.06) brings it to ~85.5%
       of the content width, and the devices (3.8%–96.3% of the file) still
       end ~1% inside the box on each side, so nothing is cut. */
    .page-iay .case-tab-panel.active > .tab-media-single { flex: none; width: 100%; max-width: 100%; }
    .page-iay .tab-media-single {
        aspect-ratio: auto;
        height: calc(var(--iay-card-w) * 338 / 264);
        overflow: visible;
        border-radius: 0;
        display: flex;
        align-items: center;
        justify-content: center;
    }
    .page-iay .tab-media-single img {
        width: 100%;
        height: auto;
        object-fit: contain;
        border-radius: 6px;
        transform: scale(1.06);
        transform-origin: center;
    }

    /* Publications: compact link rows replace the embeds and the case-study
       card (embeds aren't even loaded on phones, see main.js) */
    .page-iay .pub-grid-2x2 { display: none; }
    .pub-rows { display: block; }
    .pub-row {
        display: flex;
        align-items: center;
        gap: 1rem;
        min-height: 72px;
        padding: 0.75rem 0;
        color: inherit;
        text-decoration: none;
        -webkit-tap-highlight-color: transparent;
    }
    .pub-row + .pub-row { border-top: 1px solid rgba(255, 255, 255, 0.15); }
    .pub-row-thumb {
        flex: 0 0 72px;
        width: 72px;
        height: 72px;
        border-radius: 8px;
        object-fit: cover;
        display: block;
    }
    .pub-row-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 0.3rem; }
    .pub-row-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.2em; }
    .pub-row-platform { font-size: 0.85rem; opacity: 0.6; }
    .pub-row-arrow { flex: 0 0 auto; color: var(--pink); font-size: 1.1rem; }
}
/* The rows are phones-only */
@media (min-width: 641px) {
    .pub-rows { display: none; }
}

/* --- MUTEK (≤640px): same components as Koub / I AM YOU --- */
@media (max-width: 640px) {
    /* Hero: same rules as the Koub / I AM YOU heroes */
    .page-mutek .case-hero { height: auto; min-height: 0; padding-top: 0; }
    .page-mutek .case-hero-media {
        position: relative;
        height: auto;
        -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 48px), transparent 100%);
        mask-image: linear-gradient(180deg, #000 calc(100% - 48px), transparent 100%);
    }
    .page-mutek .case-hero-media img {
        width: 100%;
        height: auto;
        min-height: 40vh;
        min-height: 40svh;
        object-fit: cover;
        object-position: 50% 50%;
    }
    .page-mutek .case-hero-scrim { display: none; }
    .page-mutek .case-hero-media::after {
        content: "";
        position: absolute;
        inset: 0;
        pointer-events: none;
        z-index: 1;
        background: linear-gradient(to top, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.5) 20%, rgba(0, 0, 0, 0.22) 38%, rgba(0, 0, 0, 0) 55%);
    }
    .page-mutek .case-hero-content { z-index: 2; padding: 0 var(--gutter-mobile) 0.75rem; }
    .page-mutek .case-hero-content .case-tagline {
        font-size: 12px;
        letter-spacing: 0.12em; /* one line at 375–393px (a character longer than I AM YOU's) */
        white-space: nowrap;
        margin-bottom: 0;
        opacity: 1;
        color: #fff;
        text-shadow: 0 1px 12px rgba(0, 0, 0, 0.45);
    }
    .page-mutek .case-hero-title {
        margin-top: 0.5rem;
        font-size: clamp(2.25rem, 11vw, 3rem);
        text-shadow: 0 1px 12px rgba(0, 0, 0, 0.45);
    }

    /* Body text: same as the other case pages */
    .page-mutek .case-block p { font-size: 0.95rem; line-height: 1.6; }
    .page-mutek .case-block p + p { margin-top: 1.1rem; }

    /* Gallery: I AM YOU's card carousel, same card (80% of the content
       width at 264:338 = 264x338 at 393px) */
    .page-mutek { --card-w: calc((100vw - 2 * var(--gutter-mobile)) * 0.8); }
    .page-mutek .case-tab-panel.active {
        flex-direction: column;
        justify-content: flex-start;
        align-items: stretch;
    }
    .page-mutek .case-tab-panel.active > * { width: 100%; max-width: 100%; }
    .page-mutek [data-carousel] {
        display: flex;
        flex-direction: row;
        justify-content: flex-start;
        align-items: flex-start;
        gap: 0.75rem;
        width: auto;
        max-width: none;
        height: auto;
        margin: 0 calc(-1 * var(--gutter-mobile)) 0 0;
        padding: 0;
        overflow-x: auto;
        overflow-y: hidden;
        overscroll-behavior-x: contain;
        scroll-snap-type: x mandatory;
        scrollbar-width: none;
    }
    .page-mutek .case-tab-panel.active > [data-carousel] { width: auto; max-width: none; }
    .page-mutek [data-carousel]::-webkit-scrollbar { display: none; }
    .page-mutek [data-carousel]::after { content: ''; flex: 0 0 calc(100vw - 2 * var(--gutter-mobile)); }
    .page-mutek .prints-tile {
        position: relative;
        flex: 0 0 var(--card-w);
        width: var(--card-w);
        max-width: none;
        height: auto;
        aspect-ratio: 264 / 338;
        margin: 0;
        border-radius: 6px;
        overflow: hidden;
        background: none;
        display: block;
        scroll-snap-align: start;
    }
    .page-mutek .prints-tile img {
        width: 100%;
        height: 100%;
        max-width: none;
        object-fit: cover;
        object-position: var(--pos, 50% 50%);
        display: block;
        cursor: zoom-in;
    }

    /* Final Installation video (16:9) filling the portrait card like cover:
       full card height, width from its ratio; the visible window (44% of
       the frame's width) is centered on the shoes, ~57% across the frame:
       offset = (0.57 - 0.22) / (1 - 0.44) = 62.5% of the overflow */
    .page-mutek .mutek-video-card { background: #000; }
    .page-mutek .mutek-video-card iframe {
        position: absolute;
        top: 0;
        height: 100%;
        width: calc(var(--card-w) * 338 / 264 * 16 / 9);
        aspect-ratio: auto;
        left: calc((var(--card-w) - var(--card-w) * 338 / 264 * 16 / 9) * 0.625);
        border: 0;
    }
    .page-mutek .vimeo-swipe-layer {
        display: block;
        position: absolute;
        top: 0; left: 0; right: 0;
        bottom: 48px; /* player's control bar stays directly reachable */
        z-index: 2;
        background: transparent;
        border: 0;
        padding: 0;
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
    }
}

/* --- A Digital Eye (≤640px): same components as the other case pages --- */
@media (max-width: 640px) {
    /* Hero: same rules as Koub / I AM YOU / MUTEK */
    .page-de .case-hero { height: auto; min-height: 0; padding-top: 0; }
    .page-de .case-hero-media {
        position: relative;
        height: auto;
        -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 48px), transparent 100%);
        mask-image: linear-gradient(180deg, #000 calc(100% - 48px), transparent 100%);
    }
    .page-de .case-hero-media img {
        width: 100%;
        height: auto;
        min-height: 40vh;
        min-height: 40svh;
        object-fit: cover;
        object-position: 50% 50%; /* the concentric-ring artwork is centered */
    }
    .page-de .case-hero-scrim { display: none; }
    .page-de .case-hero-media::after {
        content: "";
        position: absolute;
        inset: 0;
        pointer-events: none;
        z-index: 1;
        background: linear-gradient(to top, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.5) 20%, rgba(0, 0, 0, 0.22) 38%, rgba(0, 0, 0, 0) 55%);
    }
    .page-de .case-hero-content { z-index: 2; padding: 0 var(--gutter-mobile) 0.75rem; }
    .page-de .case-hero-content .case-tagline {
        font-size: 12px;
        letter-spacing: 0.13em; /* one line at 375–393px with a few px to spare */
        white-space: nowrap;
        margin-bottom: 0;
        opacity: 1;
        color: #fff;
        text-shadow: 0 1px 12px rgba(0, 0, 0, 0.45);
    }
    .page-de .case-hero-title {
        margin-top: 0.5rem;
        font-size: clamp(2.25rem, 11vw, 3rem);
        text-shadow: 0 1px 12px rgba(0, 0, 0, 0.45);
    }

    /* Body text (incl. the Solution list) same as the other case pages; the
       desktop line break in the Solution intro would strand a short line */
    .page-de .case-block p { font-size: 0.95rem; line-height: 1.6; }
    .page-de .case-block p + p { margin-top: 1.1rem; }
    .page-de .case-block p br { display: none; }
    .page-de .case-solution-list { font-size: 0.95rem; line-height: 1.6; }

    /* Gallery: the other pages' card carousel, but with one fixed WIDE card
       (88% of the content width at 3:2) since every image is landscape. The
       2x2 grid's rows are flattened into one track. The section gap above is
       trimmed to MUTEK's 40px (tab bar to cards). */
    .page-de .case-block.deye-gallery { margin-top: -1rem; }
    .page-de { --card-w: calc((100vw - 2 * var(--gutter-mobile)) * 0.88); }
    .page-de .deye-grid[data-carousel] {
        display: flex;
        flex-direction: row;
        justify-content: flex-start;
        align-items: flex-start;
        gap: 0.75rem;
        margin: 0 calc(-1 * var(--gutter-mobile)) 0 0;
        padding: 0;
        overflow-x: auto;
        overflow-y: hidden;
        overscroll-behavior-x: contain;
        scroll-snap-type: x mandatory;
        scrollbar-width: none;
    }
    .page-de .deye-grid[data-carousel]::-webkit-scrollbar { display: none; }
    .page-de .deye-grid[data-carousel]::after { content: ''; flex: 0 0 calc(100vw - 2 * var(--gutter-mobile)); }
    .page-de .deye-grid[data-carousel] + .carousel-counter { margin-top: 0.75rem; }
    .page-de .deye-grid-row { display: contents; }
    .page-de .deye-grid-cell {
        position: relative;
        flex: 0 0 var(--card-w);
        width: var(--card-w);
        max-width: none;
        height: auto;
        aspect-ratio: 3 / 2;
        margin: 0;
        border-radius: 6px;
        overflow: hidden;
        scroll-snap-align: start;
    }
    .page-de .deye-grid-cell img {
        width: 100%;
        height: 100%;
        object-fit: cover;
        object-position: var(--pos, 50% 50%);
        display: block;
        cursor: zoom-in;
    }

    /* "Eight" spread (1.88:1): cover would cut the book's edges, so it's
       zoomed out to show 92% of the width (the whole book, 5-95% across);
       the thin strips above/below are filled by a blurred copy of the same
       image, so the grey backdrop continues */
    .page-de .deye-fit::before {
        content: '';
        position: absolute;
        inset: -12px;
        background: url(assets/digitaleye_2.webp) 50% 50% / cover no-repeat;
        filter: blur(8px);
    }
    .page-de .deye-fit img {
        position: absolute;
        top: 50%;
        left: 50%;
        width: 108.7%; /* 1 / 0.92 */
        max-width: none;
        height: auto;
        transform: translate(-50%, -50%);
        /* its top/bottom edges fade into the blurred copy (backdrop only) */
        -webkit-mask-image: linear-gradient(to bottom, transparent, #000 12%, #000 88%, transparent);
        mask-image: linear-gradient(to bottom, transparent, #000 12%, #000 88%, transparent);
    }

    /* AR demo video (16:9) filling the 3:2 card like cover: full card height,
       width from its ratio; the visible window (84% of the frame's width) is
       aligned right so the book (~42-75% across the frame) sits centered */
    .page-de .deye-video-card { background: #000; }
    .page-de .deye-video-card iframe {
        position: absolute;
        top: 0;
        height: 100%;
        width: calc(var(--card-w) * 2 / 3 * 16 / 9);
        aspect-ratio: auto;
        left: calc(var(--card-w) - var(--card-w) * 2 / 3 * 16 / 9);
        border: 0;
    }
    .page-de .vimeo-swipe-layer {
        display: block;
        position: absolute;
        top: 0; left: 0; right: 0;
        bottom: 48px; /* player's control bar stays directly reachable */
        z-index: 2;
        background: transparent;
        border: 0;
        padding: 0;
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
    }
}

/* ==========================================================================
   MOBILE — EVERYTHING ELSE PAGE (.page-ee)
   ========================================================================== */
@media (max-width: 640px) {
    /* Title starts 1.5rem below the nav bar (84px tall: 2rem padding + logo);
       intro and cards share the nav logo's left edge (the mobile gutter);
       2rem from the subtitle to the first card */
    .page-ee .ee-intro {
        padding: calc(84px + 1.5rem) var(--gutter-mobile) 2rem;
    }
    .page-ee .ee-cards { padding-left: var(--gutter-mobile); padding-right: var(--gutter-mobile); }
}

/* ==========================================================================
   SMALL LAPTOPS (769px–1512px, e.g. MacBook 13" at ~1200x650 to 1470x830)
   Laptop-only fixes; phones and large desktops (1920px) are unaffected.
   ========================================================================== */
@media (min-width: 769px) and (max-width: 1512px) {
    /* Homepage Work list: every name AND every tag on one line. The tag keeps
       its natural width (tighter 0.12em tracking; the longest, "Web | Branding
       | Print | Motion — Collection", is 335px) and the name is what flexes.
       Font size: the longest name (~10.81em) + the longest tag + index (15px)
       + arrow (24px) + 3 gaps (120px) + the 12px hover shift fit in the 80vw
       content width when size <= (80vw - 506px) / 10.81 = 7.4vw - 46.8px;
       7.4vw - 48px leaves a little extra (41px at 1200, 61px at 1470). */
    .work-name {
        font-size: clamp(1.5rem, 7.4vw - 48px, 5rem);
        white-space: nowrap;
    }
    .work-tag, .work-tag--subtitle {
        white-space: nowrap;
        max-width: none;
        width: auto;
        flex-shrink: 0;
        letter-spacing: 0.12em;
    }
    /* Below 1000px (tablets) a one-row fit would make the names unreadably
       small, so long tags wrap to 2 lines there instead */
    @media (max-width: 999px) {
        .work-name { font-size: clamp(1.5rem, min(4.7vw, 7.4vw - 32px), 5rem); }
        .work-tag, .work-tag--subtitle { white-space: normal; max-width: 20em; flex-shrink: 1; }
    }

    /* Homepage "What I Do": all three card titles on one line
       ("Interactive Installations" is the longest, ~13.3em). From 1000px up
       it always fits, so the 2-line height reservation is dropped there;
       narrower (tablets) it can still wrap, so the reservation stays and
       the three paragraphs keep starting level. */
    .spotlight-card { padding-left: 1.5rem; padding-right: 1.5rem; }
    .spotlight-card h3 { font-size: clamp(1rem, 1.6vw, 1.5rem); }
    @media (min-width: 1000px) {
        .spotlight-card h3 { min-height: 0; }
    }

    /* Homepage About: a smaller square photo (32% of the content width,
       still top-aligned with the first paragraph) and a slightly smaller
       gap; the text takes all the freed width, so it runs to fewer lines
       (22 -> 16 at 1280px). Text size unchanged. */
    #about .about-layout { gap: 3.5rem; }
    .about-photo {
        flex: 0 0 32%;
        width: 32%;
        max-width: none;
        max-height: none;
    }
    .about-content { flex: 1 1 0; min-width: 0; max-width: none; }

    /* Gallery tab bars (Koub, I AM YOU, MUTEK): one row, never wrapping;
       if the tabs ever outgrow the bar it scrolls sideways like on phones.
       The bottom rule becomes an inset line (+1px padding) so the scroll
       container can't clip the active tab's pink underline: same pixels. */
    .case-tabs-bar {
        flex-wrap: nowrap;
        column-gap: 1.75rem;
        overflow-x: auto;
        overflow-y: hidden;
        scrollbar-width: none;
        border-bottom: 0;
        padding-bottom: 1px;
        box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.15);
    }
    .case-tabs-bar::-webkit-scrollbar { display: none; }
    .case-tab { white-space: nowrap; flex: none; }
}
