/*
==========================================================================
LORENZO BENTIVOGLIO — GRAPHIC DESIGN, 3D & MULTIMEDIA
DESIGN SYSTEM v2 — tokens, base, components, pages.
No framework dependency. Documented in DESIGN.md.
==========================================================================
1. Tokens        5. Components: buttons, badges, meta
2. Base          6. Components: project cards, schede stack
3. Cursor        7. Components: modal, lightbox
4. Layout        8. Page patterns & footer, motion preferences
*/

/* ==========================================================================
   1. TOKENS
   Semantic names only. Components never use raw hex values.
   ========================================================================== */
:root {
    color-scheme: dark;

    /* Surfaces & text (dark is the default world) */
    --canvas: #0A0A0A;
    --surface: #141414;
    --subtle: #202020;
    --scheda-bg: hsl(0 0% 12.84%);   /* project file (works page): the old #141414 with lightness +5 */
    --card-bg: hsl(0 0% 8.92%);      /* project card (home canvas): the canvas #0A0A0A with lightness +5 */
    --text: #F9F8F6;
    --text-muted: rgba(249, 248, 246, 0.64);
    --border: rgba(255, 255, 255, 0.14);
    --border-strong: rgba(255, 255, 255, 0.32);
    --overlay: rgba(0, 0, 0, 0.78);

    /* Brand colour. --ink is the only colour allowed on accent fills; fills use --accent-surface. */
    --accent: #e5334a;               /* accent on the canvas: text, borders, focus (4.6:1 on dark) */
    --accent-surface: #e5334a;       /* red background: ink on it is 4.6:1, enough for small text too (AA) */
    --accent-text: #e5334a;          /* accent used as text on the canvas */
    --accent-soft: rgba(229, 51, 74, 0.14);
    --ink: #0A0A0A;
    --ink-border: rgba(10, 10, 10, 0.45);
    --ink-wash: rgba(10, 10, 10, 0.1);
    --live: #34d399;

    /* Typography */
    --font-display: 'Space Grotesk', system-ui, -apple-system, 'Segoe UI', sans-serif;
    --font-serif: 'redaction-35', Georgia, 'Times New Roman', serif;
    --font-body: 'grappa-two-variable', system-ui, -apple-system, 'Segoe UI', sans-serif;
    --font-mono: 'JetBrains Mono', ui-monospace, 'Cascadia Mono', Consolas, monospace;

    --fs-meta: 0.75rem;                                   /* mono labels, 12px */
    --fs-small: 0.875rem;
    --fs-body: 1.0625rem;
    --fs-lead: clamp(1.25rem, 2vw, 1.625rem);
    --fs-quote: clamp(1.625rem, 3.2vw, 3rem);
    --fs-h2: clamp(2rem, 4.2vw, 3.75rem);
    --fs-h3: clamp(1.375rem, 2vw, 1.75rem);
    --fs-display: clamp(2.75rem, 7.4vw, 6rem);            /* display max 6rem */
    --tracking-meta: 0.08em;

    /* Space scale */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.5rem;
    --space-6: 2rem;
    --space-7: 3rem;
    --space-8: 4.5rem;
    --section-spacing: clamp(5rem, 11vw, 10rem);
    --gutter: clamp(1.5rem, 5vw, 4.5rem);
    --container-max: 1520px;
    --measure: 68ch;
    --header-height: 72px;

    /* Shape, depth, motion */
    --radius: 2px;
    --shadow-lift: 0 18px 40px -12px rgba(0, 0, 0, 0.6);
    --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
    --ease-ae: cubic-bezier(0.333, 0, 0.667, 1);   /* After Effects Easy Ease (F9): 33.3% influence, zero speed at both keyframes */
    --dur-fast: 0.18s;
    --dur-base: 0.35s;
    --focus-ring: 0 0 0 2px var(--canvas), 0 0 0 4px var(--text);
}

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

html {
    scroll-behavior: smooth;
    font-size: 16px;
    background-color: var(--canvas);
    scroll-padding-top: calc(var(--header-height) + 1rem);
}

body {
    font-family: var(--font-body);
    font-size: var(--fs-body);
    background-color: var(--canvas);
    color: var(--text);
    overflow-x: hidden;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    transition: background-color var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
}

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

a {
    color: inherit;
}

ul {
    list-style: none;
}

h1, h2, h3, h4 {
    font-family: var(--font-display);
    line-height: 1.1;
    text-wrap: balance;
}

p {
    text-wrap: pretty;
}

::selection {
    background-color: var(--accent-surface);
    color: var(--ink);
}

:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
}

.site-header :focus-visible,
.site-footer :focus-visible {
    box-shadow: 0 0 0 2px var(--accent), 0 0 0 4px var(--ink);
}

.skip-link {
    position: fixed;
    top: var(--space-3);
    left: var(--space-3);
    z-index: 100000;
    padding: var(--space-2) var(--space-4);
    background: var(--ink);
    color: var(--accent-surface);
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
    letter-spacing: var(--tracking-meta);
    text-transform: uppercase;
    text-decoration: none;
    transform: translateY(-200%);
}

.skip-link:focus {
    transform: none;
}

/* grain: a small pre-made noise tile in a fixed layer behind everything. It shows only on the bare page background:
   text, photos, cards, header and footer sit on top of it, so it never covers them. Drawn once, never repainted. */
.film-grain {
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: -1;
    opacity: 0.045;
    background-image: url("img/grain.png");
    background-size: 160px 160px;
    will-change: transform;
    transform: translateZ(0);
}

/* ==========================================================================
   3. CUSTOM CURSOR (progressive enhancement: only when JS flags a fine pointer)
   ========================================================================== */
/* Only the custom cursor is shown: every element, including ones that set their own cursor, hides the native pointer */
html.has-custom-cursor,
html.has-custom-cursor * {
    cursor: none !important;
}

.custom-cursor {
    position: fixed;
    top: 0;
    left: 0;
    width: 32px;
    height: 32px;
    border: 1.5px solid var(--accent);
    border-radius: 50%;
    pointer-events: none;
    z-index: 999999;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: var(--tracking-meta);
    color: var(--ink);
    text-transform: uppercase;
    transition: border-color var(--dur-fast) ease, background-color var(--dur-fast) ease, opacity var(--dur-fast) ease;
}

.custom-cursor.hovered-link {
    background-color: var(--accent-soft);
}

.custom-cursor.hovered-card {
    background-color: var(--accent-surface);
    font-weight: 700;
}

.custom-cursor.hovered-card::after {
    content: "OPEN";
    font-size: 0.38em; /* cancels the JS scale so the label stays ~10px */
}

/* Surface-adaptive variants (set by script.js from the element under the pointer) */
.custom-cursor.cursor-on-red {
    border-color: var(--ink);
}

.custom-cursor.cursor-on-red.hovered-link {
    background-color: var(--ink-wash);
}

.custom-cursor.cursor-on-red.hovered-card {
    background-color: var(--ink);
    color: var(--accent-surface);
}

.custom-cursor.cursor-on-light {
    border-color: var(--ink);
}

.custom-cursor.cursor-on-dark:not(.hovered-card) {
    color: var(--text);
}

/* ==========================================================================
   4. LAYOUT
   ========================================================================== */
.container {
    width: 100%;
    max-width: var(--container-max);
    margin-inline: auto;
    padding-inline: var(--gutter);
}

.section {
    padding-block: var(--section-spacing);
    position: relative;
}

.section--bordered {
    border-top: 1px solid var(--border);
}

.stack > * + * {
    margin-top: var(--stack-gap, var(--space-5));
}

.grid-12 {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: clamp(2rem, 5vw, 5rem);
    align-items: start;
}

.col-5 { grid-column: span 12; }
.col-7 { grid-column: span 12; }

@media (min-width: 1024px) {
    .col-5 { grid-column: span 5; }
    .col-7 { grid-column: span 7; }
    .sticky-col { position: sticky; top: calc(var(--header-height) + 2rem); }
}

/* ---- Site header ---- */
.site-header {
    position: fixed;
    inset: 0 0 auto 0;
    height: var(--header-height);
    background-color: var(--accent-surface);
    color: var(--ink);
    z-index: 100;
    display: flex;
    align-items: center;
    transition: transform 0.4s var(--ease-out);
}

/* Slides out of view while scrolling down, returns on any scroll up */
.site-header.is-hidden {
    transform: translateY(-100%);
    transition-duration: 0.3s;
}

.site-header .container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
}

.brand {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--space-3);
    text-decoration: none;
    color: var(--ink);
    line-height: 1.2;
}

.brand-name {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1rem;
    letter-spacing: -0.01em;
}

.header-actions {
    display: flex;
    align-items: center;
    gap: clamp(0.75rem, 2.5vw, 2rem);
}

.site-nav {
    display: flex;
    align-items: center;
    gap: clamp(1rem, 2.5vw, 2rem);
}

.nav-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    font-family: var(--font-mono);
    font-size: 0.8125rem;
    text-transform: uppercase;
    letter-spacing: var(--tracking-meta);
    color: var(--ink);
    text-decoration: none;
    border-bottom: 2px solid transparent;
    transition: border-color var(--dur-fast) var(--ease-out);
}

.nav-link:hover {
    border-bottom-color: var(--ink);
}

.nav-link[aria-current="page"] {
    border-bottom-color: var(--ink);
    font-weight: 700;                /* the current page is bold */
}

.btn.menu-btn {
    display: none;
}

@media (max-width: 767px) {
    .btn.menu-btn {
        display: inline-flex;
    }

    .site-nav {
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        flex-direction: column;
        align-items: stretch;
        gap: 0;
        padding: var(--space-2) var(--gutter) var(--space-5);
        background-color: var(--accent-surface);
        border-bottom: 1px solid var(--ink-border);
        visibility: hidden;
        opacity: 0;
        transform: translateY(-0.5rem);
        transition: opacity var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out), visibility 0s linear var(--dur-fast);
    }

    .site-nav.is-open {
        visibility: visible;
        opacity: 1;
        transform: none;
        transition-delay: 0s;
    }

    .site-nav .nav-link {
        font-size: 1rem;
        border-bottom: 1px solid var(--ink-border);
        min-height: 52px;
    }
}

/* ---- Breadcrumb ---- */
.breadcrumb {
    margin-top: var(--header-height);
    padding-block: var(--space-3);
    border-bottom: 1px solid var(--border);
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
    letter-spacing: var(--tracking-meta);
    text-transform: uppercase;
    color: var(--text-muted);
}

.breadcrumb .container {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.breadcrumb a {
    text-decoration: none;
}

.breadcrumb a:hover {
    color: var(--accent-text);
}

.breadcrumb [aria-current="page"] {
    color: var(--text);
}

/* ==========================================================================
   5. COMPONENTS — BUTTONS, BADGES, META
   ========================================================================== */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    min-height: 44px;
    padding: 0.6rem 1.15rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    background: transparent;
    color: var(--text);
    font-family: var(--font-mono);
    font-size: 0.8125rem;
    letter-spacing: var(--tracking-meta);
    text-transform: uppercase;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}

.btn:hover {
    background-color: var(--accent-surface);
    border-color: var(--accent-surface);
    color: var(--ink);
}

.btn--solid {
    background-color: var(--accent-surface);
    border-color: var(--accent-surface);
    color: var(--ink);
}

.btn--solid:hover {
    background-color: transparent;
    color: var(--accent-text);
}

/* Variant for controls that sit on an accent-coloured surface (header, footer) */
.btn--ink {
    border-color: var(--ink-border);
    color: var(--ink);
}

.btn--ink:hover {
    background-color: var(--ink);
    border-color: var(--ink);
    color: var(--accent-surface);
}

.btn--sm {
    min-height: 44px;
    padding-inline: 0.85rem;
}

.btn-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
}

.badge {
    display: inline-block;
    padding: 0.25rem 0.65rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    letter-spacing: var(--tracking-meta);
    text-transform: uppercase;
    color: var(--text);
}

.badge--accent {
    background-color: var(--accent-surface);
    border-color: var(--accent-surface);
    color: var(--ink);
    font-weight: 600;
}

.meta {
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
    letter-spacing: var(--tracking-meta);
    text-transform: uppercase;
    color: var(--text-muted);
}

.meta strong {
    color: var(--text);
    font-weight: 500;
}

/* Reads as plain text; it is a link to the contact page */
.hero__status {
    color: inherit;
    text-decoration: none;
}

.text-accent { color: var(--accent-text); }

.live-dot {
    display: inline-block;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background-color: var(--live);
    animation: pulse 2.4s ease-in-out infinite;
}

@keyframes pulse {
    50% { opacity: 0.35; }
}

/* ==========================================================================
   6. COMPONENTS — PROJECT CARDS & SCHEDE STACK
   ========================================================================== */

.project-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    width: min(62vw, 980px);
    cursor: pointer;
    transition: transform 0.45s var(--ease-out);
}

.project-card:nth-child(odd) { align-self: flex-start; }
.project-card:nth-child(even) { align-self: flex-end; }

.project-card:hover,
.project-card:focus-visible {
    transform: translateY(-8px);
}

.project-card__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3);
}

.project-card__media {
    height: min(60vh, 640px);
    overflow: hidden;
    background-color: var(--surface);
}

.project-card__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.project-card__foot {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--space-5);
}

.project-card__title {
    font-size: var(--fs-h3);
    font-weight: 700;
}

.project-card__desc {
    margin-top: var(--space-1);
    font-family: var(--font-serif);
    font-style: italic;
    font-size: 1.25rem;
    line-height: 1.3;
    color: var(--text-muted);
    max-width: 52ch;
}

.project-card__cta {
    white-space: nowrap;
}

@media (max-width: 800px) {
    .project-card {
        width: 100%;
        align-self: stretch !important;
    }

    .project-card__media {
        height: auto;
        aspect-ratio: 4 / 3;
    }

    .project-card__foot {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--space-3);
    }
}

/* ---- Schede progetti: perspective-cascaded cards ---- */
.schede-stage {
    perspective: 1400px;
    perspective-origin: 50% 70%;
    width: 100%;
    max-width: 1240px;
    margin-inline: auto;
    padding: var(--space-6) var(--space-4);
}

.schede-stack {
    --scheda-body: clamp(260px, 42vh, 440px);
    display: flex;
    flex-direction: column;
    transform-style: preserve-3d;
}

.scheda {
    position: relative;
    margin-top: calc(-0.2 * (var(--scheda-body) + 41px) - 0.8rem);   /* cards sit 20% closer; their height is unchanged */
    background-color: var(--scheda-bg);
    border: 1px solid var(--border);
    border-radius: 6px;
    overflow: hidden;
    cursor: pointer;
    box-shadow: var(--shadow-lift);
    transform: rotateX(-12deg);
    transform-origin: center bottom;
    transition: transform var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}

.scheda:first-child {
    margin-top: 0;
}

.scheda:hover,
.scheda:focus-visible {
    transform: rotateX(-12deg) translateY(-14px);
    border-color: var(--accent);
    box-shadow: 0 28px 48px -14px rgba(0, 0, 0, 0.6);
    z-index: 50;
}

.scheda__bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    padding: 0.65rem 1.25rem;
    background-color: color-mix(in srgb, var(--scheda-bg) 90%, #fff);
    border-bottom: 1px solid var(--border);
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--text-muted);
    background-color: color-mix(in srgb, var(--scheda-bg) 95%, #fff);
}

.scheda__bar strong {
    flex: 1;
    color: var(--text);
    font-weight: 500;
}

.scheda__close {
    color: var(--accent-text);
    font-weight: 600;
}

.scheda__body {
    height: var(--scheda-body, clamp(260px, 42vh, 440px));   /* a large preview of the cover */
    overflow: hidden;
    background-color: var(--scheda-bg);
}

.scheda__body img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: top center;
}

@media (max-width: 640px) {
    .scheda__bar span:last-child { display: none; }
    .schede-stack { --scheda-body: clamp(200px, 34vh, 320px); }
}

/* ==========================================================================
   7. COMPONENTS — MODAL, LIGHTBOX
   ========================================================================== */
.modal {
    position: fixed;
    inset: 0;
    background-color: var(--overlay);
    backdrop-filter: blur(10px);
    z-index: 9000;
    display: flex;
    justify-content: flex-end;
    visibility: hidden;
    opacity: 0;
    pointer-events: none;   /* a closed overlay must never swallow clicks, even during its fade-out */
    transition: opacity var(--dur-base) var(--ease-out), visibility 0s linear var(--dur-base);
}

.modal.is-open {
    visibility: visible;
    opacity: 1;
    pointer-events: auto;
    transition-delay: 0s;
}

.modal__drawer {
    width: 100%;
    max-width: none;
    height: 100%;
    background-color: var(--canvas);
    overflow: auto;
    overscroll-behavior: contain;
    transform: translateX(100%);
    transition: transform 0.4s var(--ease-out);
    padding: clamp(1.5rem, 5vw, 4.5rem);
    display: flex;
    flex-direction: column;
    overflow-x: auto;
    overflow-y: hidden;
    padding: clamp(1rem, 2.5vw, 2rem);
    padding-block: 1rem 3.25rem;
}

.modal.is-open .modal__drawer {
    transform: none;
}

.modal__top {
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    padding-bottom: var(--space-5);
    margin-bottom: var(--space-5);
    border-bottom: 1px solid var(--border);
    background-color: var(--canvas);
    position: fixed;
    z-index: 5;
    display: block;
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    top: auto;
    bottom: calc(1.5rem + var(--sb, 0px));   /* same gap as from the right edge, measured above the scrollbar */
    right: 1.5rem;
    left: auto;                      /* an older rule pinned it to the left edge */
}

.case h2 {
    margin-top: var(--space-3);
    font-size: var(--fs-h2);
    font-weight: 700;
    letter-spacing: -0.02em;
}

.case__quote {
    margin-top: var(--space-3);
    font-family: var(--font-serif);
    font-style: italic;
    font-size: var(--fs-lead);
    line-height: 1.3;
    color: var(--text-muted);
}

.case__facts {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-4);
    padding-block: var(--space-4);
    margin-block: var(--space-5);
    border-block: 1px solid var(--border);
}

@media (min-width: 640px) {
    .case__facts { grid-template-columns: 1fr 1fr 2fr; }
}

.case__label {
    display: block;
    margin-bottom: var(--space-1);
}

.case__heading {
    margin-bottom: var(--space-2);
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
    font-weight: 600;
    letter-spacing: var(--tracking-meta);
    text-transform: uppercase;
    color: var(--accent-text);
}

.case__narrative {
    max-width: var(--measure);
    color: var(--text-muted);
    max-width: min(var(--measure), 62ch);
    line-height: 1.7;
    letter-spacing: 0.005em;
}

.case__specs {
    margin-top: var(--space-6);
    padding: var(--space-5);
    border: 1px solid var(--border);
    background-color: var(--surface);
}

.case__specs dl {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
    gap: var(--space-4);
}

.case__specs dd {
    font-family: var(--font-mono);
    font-size: var(--fs-small);
    margin-top: var(--space-1);
}

.case__gallery {
    display: flex;
    gap: 3rem;                       /* from one photo to the next */
    align-items: center;
}

.shot {
    display: block;
    flex: 0 0 85vh;
    width: 85vh;                     /* a photo is as wide as 85% of the viewport height */
    padding: 0;
    text-align: left;
    background-color: transparent;
    border: 0;
    color: inherit;
    cursor: pointer;
}

.shot__img {
    display: block;
    width: 100%;
    overflow: hidden;
    background-color: var(--surface);
    border: 1px solid var(--border);
}

/* keeps the row from collapsing while a photo is still loading */
.shot__img:not(.is-loaded) {
    min-height: 30vh;
}

.shot__img img {
    display: block;
    width: 100%;
    height: auto;                    /* the photo keeps its own proportions */
}

.shot__cap {
    display: grid;
    gap: var(--space-1);
    margin-top: 1rem;                /* from the image to its caption */
    padding: 0;
    width: 0;
    min-width: 100%;
}

.shot:hover .shot__img {
    border-color: var(--accent);
}

.lightbox {
    pointer-events: none;
    position: fixed;
    inset: 0;
    z-index: 99999;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: var(--space-4);
    background-color: var(--overlay);
    backdrop-filter: blur(14px);
    visibility: hidden;
    opacity: 0;
    transition: opacity var(--dur-base) var(--ease-out), visibility 0s linear var(--dur-base);
}

.lightbox.is-open {
    visibility: visible;
    opacity: 1;
    pointer-events: auto;
    transition-delay: 0s;
}

.lightbox__bar {
    position: absolute;
    top: var(--space-5);
    right: var(--space-5);
    display: flex;
    align-items: center;
    gap: var(--space-4);
}

.lightbox img {
    max-width: 100%;
    max-height: 85vh;
    object-fit: contain;
}

/* ==========================================================================
   8. PAGE PATTERNS
   ========================================================================== */

/* ---- Hero ---- */
.hero {
    padding-top: calc(var(--header-height) + clamp(3rem, 7vw, 6rem));
    padding-bottom: clamp(3.5rem, 8vw, 7rem);
    border-bottom: 1px solid var(--border);
}

.hero--sub {
    padding-top: clamp(3rem, 7vw, 6rem);
}

.hero__top {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    margin-bottom: var(--space-6);
}

.hero__top > div {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3) var(--space-4);
}

.hero__title {
    font-size: var(--fs-display);
    font-weight: 700;
    line-height: 0.94;
    letter-spacing: -0.035em;
    text-transform: uppercase;
}

/* Reveal: each word slides in from the left out of a mask (no colour blocks, those belong to the highlighted word only) */
.rv {
    display: inline-block;
    overflow: hidden;
    vertical-align: bottom;
    padding-bottom: 0.12em;           /* room for descenders such as the comma */
    margin-bottom: -0.12em;
}

.rv__in {
    display: inline-block;
    animation: rv-in 0.75s var(--ease-ae) calc(0.05s + var(--d) * 0.1s) backwards;
}

@keyframes rv-in {
    from { transform: translateX(-110%); }   /* enters from the left, inside its mask */
}

@media (prefers-reduced-motion: reduce) {
    .rv__in { animation: none; }
}

/* Highlighted word: each letter gets its own marker block, one after another; the letter shows only inside it */
.hero__mark .ch {
    display: inline-block;
    color: var(--ink);
    background-image: linear-gradient(var(--accent-surface), var(--accent-surface));
    background-repeat: no-repeat;
    background-position: left center;
    background-size: 100% 100%;
    animation: hero-letter 0.55s var(--ease-ae) calc(0.7s + var(--i) * 0.11s) both;
}

.hero__mark .ch--first { padding-left: 0.12em; }
.hero__mark .ch--last { padding-right: 0.12em; }

/* The letter is invisible until its red block has covered it, then it appears in ink */
@keyframes hero-letter {
    0%   { background-size: 0% 100%;   color: transparent; }
    55%  { background-size: 100% 100%; color: transparent; }
    80%  { background-size: 100% 100%; color: var(--ink); }
    100% { background-size: 100% 100%; color: var(--ink); }
}

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

@media (prefers-reduced-motion: reduce) {
    .hero__mark .ch { animation: none; }
}

.hero__payoff {
    margin-top: var(--space-5);
    font-family: var(--font-display);
    font-size: clamp(1.125rem, 2.2vw, 1.75rem);
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--accent-text);
}

.hero__quote {
    margin-top: var(--space-6);
    max-width: 30em;
    font-family: var(--font-serif);
    font-style: italic;
    font-size: var(--fs-quote);
    line-height: 1.2;
}


/* ---- Section heading (no eyebrow: the heading carries itself) ---- */
.section-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--space-4) var(--space-6);
    margin-bottom: clamp(2.5rem, 5vw, 4.5rem);
    padding-bottom: var(--space-5);
    border-bottom: 1px solid var(--border);
}

.section-head h2 {
    font-size: var(--fs-h2);
    font-weight: 700;
    letter-spacing: -0.025em;
}

.lead {
    font-family: var(--font-serif);
    font-style: italic;
    font-size: var(--fs-lead);
    line-height: 1.3;
    color: var(--text-muted);
    max-width: 44ch;
    font-weight: 400;
}

/* ---- Long-form text ---- */
.prose {
    max-width: var(--measure);
    font-size: var(--fs-body);
    color: var(--text-muted);
}

.prose > * + * {
    margin-top: var(--space-5);
}

.prose strong {
    color: var(--text);
    font-weight: 600;
}

.prose .pull {
    font-family: var(--font-serif);
    font-style: italic;
    font-size: var(--fs-lead);
    line-height: 1.35;
}

/* ---- Spec lists ---- */
.spec-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    gap: var(--space-6);
    padding-top: var(--space-6);
    margin-top: var(--space-7);
    border-top: 1px solid var(--border);
}

.spec-grid h3 {
    margin-bottom: var(--space-3);
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
    font-weight: 500;
    letter-spacing: var(--tracking-meta);
    text-transform: uppercase;
    color: var(--text-muted);
}

.spec-list li {
    padding-block: var(--space-2);
    border-bottom: 1px solid var(--border);
    font-family: var(--font-mono);
    font-size: var(--fs-small);
}

/* ---- Portrait ---- */
.portrait {
    position: relative;
    aspect-ratio: 4 / 5;
    overflow: hidden;
    background-color: var(--surface);
    border: 1px solid var(--border);
}

.portrait img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.portrait__caption {
    position: absolute;
    inset: auto 0 0 0;
    display: grid;
    gap: var(--space-1);
    padding: var(--space-4);
    background-color: var(--ink);
    color: #F9F8F6;
}

.portrait__caption strong {
    font-family: var(--font-display);
    font-size: 1.25rem;
}

.portrait__caption .meta {
    color: rgba(249, 248, 246, 0.72);
}

/* ---- Contact channels ---- */
.channels {
    border-top: 1px solid var(--border);
}

.channel {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--space-4);
    padding-block: var(--space-5);
    border-bottom: 1px solid var(--border);
    text-decoration: none;
    transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}

.channel > :first-child {
    transition: transform var(--dur-base) var(--ease-out);
}

.channel:hover,
.channel:focus-visible {
    background-color: var(--accent-surface);
    color: var(--ink);
}

.channel:hover > :first-child,
.channel:focus-visible > :first-child {
    transform: translateX(var(--space-4));
}

.channel__name {
    display: block;
    font-family: var(--font-display);
    font-size: var(--fs-h3);
    font-weight: 700;
    overflow-wrap: anywhere;
}

.channel:hover .meta,
.channel:focus-visible .meta {
    color: var(--ink);
}

.email-display {
    font-family: var(--font-display);
    font-size: clamp(1.5rem, 4.6vw, 3.75rem);
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: 1.05;
    overflow-wrap: anywhere;
}

/* ---- Closing CTA band ---- */
.cta-band {
    display: grid;
    gap: var(--space-5);
    padding-block: clamp(4rem, 8vw, 7rem);
}

.cta-band__links {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    border-top: 1px solid var(--border);
}

.cta-band__links a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-5) var(--space-4);
    border-bottom: 1px solid var(--border);
    font-family: var(--font-display);
    font-size: var(--fs-h3);
    font-weight: 700;
    text-decoration: none;
    transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}

.cta-band__links a:hover,
.cta-band__links a:focus-visible {
    background-color: var(--accent-surface);
    color: var(--ink);
}

/* ---- Footer (always on accent, always ink text) ---- */
.site-footer {
    background-color: var(--accent-surface);
    color: var(--ink);
    padding-top: clamp(4rem, 9vw, 7rem);
    padding-bottom: clamp(2.5rem, 6vw, 5rem);
    padding-top: clamp(5rem, 12vw, 10rem);
}

.site-footer .meta,
.site-footer .meta strong {
    color: var(--ink);
}

.footer-call {
    margin-bottom: var(--space-7);
    margin-bottom: clamp(4rem, 9vw, 7rem);
}

.footer-call h2 {
    font-size: clamp(1.125rem, 2.4vw, 1.75rem);
    margin-block: var(--space-4) var(--space-5);
    font-family: var(--font-display);
    font-size: clamp(2.75rem, 9vw, 8.5rem);
    font-weight: 700;
    line-height: 0.92;
    letter-spacing: -0.04em;
    text-transform: none;
}

.footer-grid {
    display: grid;
    gap: var(--space-5);
    margin-bottom: var(--space-7);
}

@media (min-width: 768px) {
    .footer-grid { grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); }
}

.status-panel {
    display: flex;
    flex-direction: column;
    height: 100%;
    border: 1px solid var(--ink);
}

.status-panel__head {
    padding: var(--space-2) var(--space-4);
    background-color: var(--ink);
    color: var(--accent-surface);
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
    letter-spacing: var(--tracking-meta);
    text-transform: uppercase;
}

.status-panel__body {
    flex: 1;
    padding: var(--space-4);
    font-family: var(--font-mono);
    font-size: var(--fs-small);
    letter-spacing: var(--tracking-meta);
    line-height: 1.8;
    text-transform: uppercase;
}

.status-panel__banner {
    padding: var(--space-3) var(--space-4);
    background-color: var(--ink);
    color: var(--accent-surface);
    border-top: 1px solid var(--ink);
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
    font-weight: 600;
    letter-spacing: var(--tracking-meta);
    text-transform: uppercase;
}

.footer-legal {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    padding-top: var(--space-5);
    border-top: 1px solid var(--ink-border);
}

.footer-legal nav {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-5);
    column-gap: clamp(2rem, 4vw, 4rem);
    row-gap: var(--space-1);
}

.footer-legal a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    text-decoration: none;
    border-bottom: 1px solid transparent;
}

.footer-legal a:hover {
    border-bottom-color: var(--ink);
}

.swatch {
    display: inline-flex;
    gap: var(--space-1);
    vertical-align: middle;
    margin-left: var(--space-2);
}

.swatch i {
    width: 0.75rem;
    height: 0.75rem;
    background-color: var(--ink);
}

.swatch i + i {
    background-color: transparent;
    outline: 1px solid var(--ink);
}

/* ==========================================================================
   MOTION & INPUT PREFERENCES
   Reduced motion keeps every state change (colour, border, visibility) and
   drops only travel: transforms and pulsing.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }

    .live-dot {
        animation: none;
    }

    .project-card:hover,
    .project-card:focus-visible,
    .scheda:hover,
    .scheda:focus-visible {
        transform: none;
    }

    .scheda,
    .scheda:hover {
        transform: rotateX(-12deg);
    }

    .modal__drawer {
        transform: none;
        transition: none;
    }

    .site-nav {
        transform: none;
    }

    .channel:hover > :first-child,
    .channel:focus-visible > :first-child {
        transform: none;
    }
}

@media (hover: none) and (pointer: coarse) {
    .custom-cursor {
        display: none;
    }
}

/* ==========================================================================
   UTILITIES (only the few the pages need)
   ========================================================================== */
.br-sm { display: none; }
@media (min-width: 640px) { .br-sm { display: inline; } }
.u-mb-4 { margin-bottom: var(--space-4); }
.u-mt-6 { margin-top: var(--space-6); }
.cta-band .lead { max-width: none; }

/* ==========================================================================
   WORKS SPACE: a draggable canvas of project cards (home page)
   Without JS the viewport simply scrolls natively.
   ========================================================================== */
.space {
    --card-edge: color-mix(in srgb, var(--canvas) 82%, #000);   /* the canvas colour, slightly darker */
    padding-top: var(--section-spacing); padding-bottom: clamp(3rem, 7vw, 6rem);
    overflow-x: clip; }
.space__bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3) var(--space-5); margin-bottom: var(--space-5); }
.space__title { font-size: var(--fs-h2); font-weight: 700; letter-spacing: -0.025em; }
.space__hint { flex: 1 1 24rem; max-width: 60ch; text-transform: none; letter-spacing: 0.02em; line-height: 1.6; }

/* The canvas is exactly one screen wide and two screens tall */
.space__viewport {
    position: relative;
    width: 100vw;
    margin-left: calc(50% - 50vw);
    height: 200vh;
    overflow: auto;
    background-color: var(--canvas);   /* same black as the sections above and below */
}

.space__board { position: relative; width: 100%; height: 100%; }

.space .project-card {
    --cw: min(var(--w), 72vw);
    position: absolute;
    /* keep every card inside the canvas at any screen size */
    left: clamp(0px, var(--x), calc(100% - var(--cw)));
    top: var(--y);
    width: var(--cw);
    align-self: auto;
    gap: var(--space-2);
    padding: var(--space-3);
    background-color: var(--card-bg);
    border: 1px solid var(--card-edge);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lift);
    translate: var(--dx, 0px) var(--dy, 0px);
    rotate: var(--r, 0deg);
    transition: transform 0.3s var(--ease-out), box-shadow 0.3s var(--ease-out), border-color 0.2s var(--ease-out);
}

.space .project-card:hover,
.space .project-card:focus-visible { transform: translateY(-6px); border-color: var(--accent); }
/* The cover decides the shape: the card takes the image's own proportions, nothing is cropped */
.space .project-card__media { height: auto; aspect-ratio: auto; background: transparent; }
.space .project-card__media img { width: 100%; height: auto; object-fit: initial; padding: 0; }
.space .project-card__title { font-size: 1.25rem; }
.space .project-card__desc { font-size: 1rem; }
.space .project-card__foot { flex-direction: column; align-items: flex-start; gap: var(--space-2); }
.space img { -webkit-user-drag: none; user-select: none; }

/* Enhanced mode: JS moves cards by pointer; vertical scroll always belongs to the page */
.space.is-enhanced .space__viewport { overflow: visible; touch-action: pan-y; user-select: none; }   /* cards may be dragged beyond the screen edges */
.space.is-enhanced .project-card { cursor: grab; touch-action: none; }
.space .project-card.is-dragging { transition: box-shadow 0.2s var(--ease-out); transform: scale(1.02) rotate(-0.6deg); box-shadow: 0 30px 56px -16px rgba(0, 0, 0, 0.7); cursor: grabbing; border-color: var(--accent); }

@media (prefers-reduced-motion: reduce) {
    .space .project-card:hover, .space .project-card:focus-visible, .space .project-card.is-dragging { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .site-header, .site-header.is-hidden { transition: none; }
}

/* ==========================================================================
   PROJECT VIEW: one horizontal row. Text first, then the photos.
   ========================================================================== */

.case--row {
    display: flex;
    gap: 3rem;
    width: max-content;
    height: 100%;
    min-height: 0;
    align-items: center;
    padding-bottom: 0;
}

.case__intro {
    flex: 0 0 min(34rem, 85vw);
    min-width: 0;
    max-height: 100%;
    overflow-x: hidden;
    overflow-y: auto;                /* taller than the screen: it scrolls on hover (the bar is hidden) */
    padding-right: var(--space-3);
}

.case__scroll {
    margin-top: var(--space-6);
}

/* A single, very wide artwork (the unfolded leporello): fixed height, width follows, row centred in the view */
.case--tall {
    align-items: center;
    min-height: 0;
}

.case--tall .shot {
    flex: 0 0 auto;
    width: auto;
}

.case--tall .shot__img {
    width: auto;
}

.case--tall .shot__img img {
    width: auto;
    max-width: none;
    height: var(--photo-h);
}

/* ==========================================================================
   PROJECT VIEW GRID (horizontal, fits one screen: no vertical scrolling)
   The close button floats; the row fills the drawer; no photo is taller than 85vh.
   ========================================================================== */

/* the label stays for screen readers (aria-labelledby) but is not drawn */
.modal__top > .meta {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

#case-modal-content {
    flex: 1 1 auto;
    min-height: 0;
    width: max-content;
}

.shot__img img {
    max-height: 85vh;
}

/* portrait photos: 85vh tall, as wide as their proportions need */
.shot.is-portrait {
    flex: 0 0 auto;
    width: auto;
}

.shot.is-portrait .shot__img {
    width: auto;
}

.shot.is-portrait .shot__img img {
    width: auto;
    height: 85vh;
    max-width: none;
}

/* Works page: the files are grouped by type */
.schede-group + .schede-group {
    margin-top: clamp(4rem, 9vw, 7rem);
}

.schede-group__title {
    font-size: var(--fs-h3);
    font-weight: 600;
    margin-bottom: clamp(1.5rem, 4vw, 3.5rem);
}

.schede-group__title .meta {
    margin-left: var(--space-2);
}

/* Project view: a square back arrow, bottom right */

.modal__back {
    width: 3.25rem;
    height: 3.25rem;
    min-height: 0;
    padding: 0;
    background-color: var(--canvas);
    border-color: var(--border-strong);
}

/* Project photos: at least 85vh tall (and no more), so height decides and the width follows each photo's proportions */
.shot,
.shot.is-portrait {
    flex: 0 0 auto;
    width: auto;
}

.shot__img,
.shot.is-portrait .shot__img {
    width: auto;
}

.shot__img img,
.shot.is-portrait .shot__img img {
    width: auto;
    height: 85vh;
    min-height: 85vh;
    max-height: 85vh;
    max-width: none;
}

.shot__img:not(.is-loaded) {
    min-height: 85vh;
    min-width: min(85vh, 70vw);      /* placeholder until the photo arrives */
}

/* ==========================================================================
   SCROLLBARS: the browser's own bars are hidden, scrolling itself is untouched.
   A flat, square bar in the design system replaces them (see initScrollbars).
   ========================================================================== */
html,
* {
    scrollbar-width: none;
}

*::-webkit-scrollbar {
    display: none;
}

.sb {
    position: fixed;
    z-index: 90;
    background-color: color-mix(in srgb, var(--canvas) 80%, transparent);
    border: 1px solid var(--border);
    touch-action: none;
}

.sb[hidden] {
    display: none;
}

.sb__thumb {
    position: absolute;
    top: 0;
    left: 0;
    background-color: var(--accent-surface);
    cursor: grab;
    transition: background-color var(--dur-fast) var(--ease-out);
}

.sb__thumb:hover,
.sb.is-dragging .sb__thumb {
    background-color: var(--accent);
}

.sb.is-dragging .sb__thumb {
    cursor: grabbing;
}

/* the bars lie on the bottom edge of the site, edge to edge */
.sb--x {
    left: 0;
    width: 100vw;                    /* as wide as the viewport */
    bottom: 0;
    height: 10px;
    border-width: 1px 0 0;
}

.sb--x .sb__thumb {
    height: 100%;
}

/* project view: the same slim completion bar as the pages, on the bottom edge */
.sb--project {
    z-index: 6;
    height: 2px;
    background-color: transparent;
    border: 0;
    cursor: pointer;
}

.sb--project .sb__thumb {
    width: 0;
    height: 100%;
    background-color: var(--accent-surface);
    cursor: pointer;
}

.sb--project:hover .sb__thumb,
.sb--project.is-dragging .sb__thumb {
    background-color: var(--text);
}

/* room under the photos for that bar */

@media (hover: none) and (pointer: coarse) {
    .sb { display: none; }
}

/* Works page schede: covers are aligned to the top edge, not centred */

/* A long text flows into two columns instead of shrinking */
.case__intro.is-wide {
    flex-basis: min(64rem, 92vw);
    height: 100%;
    columns: 2 22rem;
    column-gap: 3rem;
    column-fill: auto;
}

.case__intro.is-wide > * {
    break-inside: avoid;
}

.case__intro.is-wide .case__narrative {
    break-inside: auto;
}

/* Projects with a flip-through book: a poster first, the iframe only when asked (keeps the site light) */
.case__flipbook {
    flex: 0 0 auto;
    display: grid;
    gap: var(--space-3);
    /* the stage is as wide as the open book allows and exactly as tall as the book + its 56px control bar */
    --book-h: 80vh;
    --book-w: min(calc((var(--book-h) - 56px) * var(--book-ratio, 2.824)), 92vw);
    width: var(--book-w);
}

.case__flipbook-stage {
    position: relative;
    height: calc(var(--book-w) / var(--book-ratio, 2.824) + 56px);   /* no frame, no fill: the book sits directly on the page */
}

.case__flipbook iframe {
    display: block;
    width: 100%;
    height: 100%;
    border: 0;
}

.case__flipbook-poster {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    width: 100%;
    padding: 0;
    border: 0;
    background-color: transparent;
    color: inherit;
    cursor: pointer;
}

.case__flipbook-poster img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    opacity: 0.6;
}

.case__flipbook-poster .btn {
    position: relative;
    background-color: var(--canvas);
}

/* Logo placeholder, left of the name. Drop a file at img/logo.svg and it replaces the box. */
.brand__logo {
    flex: none;
    display: grid;
    place-items: center;
    width: 2.5rem;
    height: 2.5rem;
    border: 1px dashed var(--ink-border);
}

.brand__logo img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.brand__logo [hidden] {
    display: none;
}

.brand__placeholder {
    font-family: var(--font-mono);
    font-size: 0.5625rem;
    font-weight: 600;
    letter-spacing: var(--tracking-meta);
}

/* Font download: a link once the file exists, a quiet "coming soon" until then */
.case__download {
    margin-top: var(--space-5);
}

.case__download.is-pending {
    border-style: dashed;
    color: var(--text-muted);
    cursor: not-allowed;
}

.case__download.is-pending:hover {
    background-color: transparent;
    border-color: var(--border-strong);
    color: var(--text-muted);
}

/* The frame is exactly as wide as its photo: a long caption never widens it (no empty strip beside tall photos) */

.shot__cap > .meta {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The text is one column under the heading. When there is more below, its edge fades out. */
.case__intro.is-scrollable:not(.is-end) {
    -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 4rem), transparent);
    mask-image: linear-gradient(to bottom, #000 calc(100% - 4rem), transparent);
}

/* Page progress bar: lies on the bottom edge of the nav bar and fills from 0 to 100%. When the nav bar slides away it stays, at the top edge. */
.sb--page {
    top: calc(var(--header-height) - 2px);   /* flush with the bottom edge of the nav bar, whole pixels only */
    bottom: auto;
    left: 0;
    width: 100vw;
    height: 2px;
    z-index: 150;
    transition: top 0.4s var(--ease-out);
    background-color: transparent;
    border: 0;
    cursor: pointer;
}

.sb--page .sb__thumb {
    width: 0;
    height: 100%;
    background-color: var(--ink);          /* on the accent header */
    cursor: pointer;
}

.sb--page:hover .sb__thumb,
.sb--page.is-dragging .sb__thumb {
    background-color: var(--text);
}

/* nav bar scrolled away: the bar stays, moves to the top edge and takes the accent colour */
html.header-hidden .sb--page {
    top: 0;
}

html.header-hidden .sb--page .sb__thumb {
    background-color: var(--accent-surface);
}

@media (prefers-reduced-motion: reduce) {
    .sb--page { transition: none; }
}

/* Looping video in a project: same frame as the photos, 85vh tall, width from its own proportions */
.shot--video {
    flex: 0 0 auto;
    width: auto;
    margin: 0;
}

.shot__video {
    width: auto;
    background-color: #000;
    cursor: pointer;
}

.shot__video video {
    display: block;
    height: 85vh;
    width: auto;
    max-width: none;
    aspect-ratio: auto 16 / 9;
    background-color: #000;
}

/* ==========================================================================
   3D BOOK: a real book built from CSS planes (no library). Pages keep the
   proportions of the project (--ratio), --depth is the spine thickness.
   The cover is the project's own cover, the back is its back cover.
   ========================================================================== */
.space .project-card__media--book,
.project-card__media--book {
    position: relative;
    aspect-ratio: var(--box, 4 / 3);
    background: radial-gradient(ellipse at 50% 62%, color-mix(in srgb, var(--surface) 70%, #fff 6%) 0%, var(--surface) 70%);
}

.scheda__body .book3d {
    position: absolute;
    inset: 0;
}

.scheda__body {
    position: relative;
}

.project-card__media--book .book3d {
    position: absolute;
    inset: 0;
}

.book3d {
    container-type: size;
    display: grid;
    place-items: center;
    perspective: 1900px;
    perspective-origin: 36% 28%;        /* not centred: the view is a little off axis */
    overflow: hidden;
}

.book3d__obj {
    /* the book lies on its back, cover up, seen from above at an angle. Size: whatever fits both the width and
       the height of the frame once tilted (cos 33deg = .84, sin 33deg = .54, tilt 56deg: cos = .56, sin = .83) */
    --h: min(
        calc(var(--fit, 0.9) * 100cqw / (var(--ratio) * 0.84 + 0.54)),
        calc(var(--fit, 0.9) * 100cqh / (0.56 * (0.84 + 0.54 * var(--ratio)) + 0.83 * var(--depth)))
    );
    --w: calc(var(--h) * var(--ratio));
    --d: calc(var(--h) * var(--depth));
    position: relative;
    width: var(--w);
    height: var(--h);
    transform-style: preserve-3d;
    transform: translate3d(3%, -4%, 0) rotateX(var(--rx, 56deg)) rotateY(var(--ry, -4deg)) rotateZ(var(--rz, -33deg));
    transition: transform 0.35s var(--ease-out);
}

.book3d__face {
    position: absolute;
    backface-visibility: hidden;
}

.book3d__front,
.book3d__back {
    inset: 0;
    background-color: #1a1a1a;
}

.book3d__front img,
.book3d__back img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: fill;                 /* the cover file already has the page's proportions */
}

.book3d__front {
    transform: translateZ(calc(var(--d) / 2));
}

/* hinge and sheen on the front cover */
.book3d__front::after {
    content: "";
    position: absolute;
    inset: 0;
    background:
        linear-gradient(90deg, rgba(0, 0, 0, 0.42) 0, rgba(255, 255, 255, 0.1) 2.2%, rgba(0, 0, 0, 0.12) 4%, transparent 9%),
        linear-gradient(115deg, rgba(255, 255, 255, 0.14), transparent 38%);
    pointer-events: none;
}

.book3d__back {
    transform: rotateY(180deg) translateZ(calc(var(--d) / 2));
}

/* spine: the cover's left edge, stretched */
.book3d__spine {
    top: 0;
    left: calc(50% - var(--d) / 2);
    width: var(--d);
    height: 100%;
    background-size: 480% 100%;
    background-position: 0 50%;
    background-color: #1a1a1a;
    transform: rotateY(-90deg) translateZ(calc(var(--w) / 2));
}

.book3d__spine::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.1) 50%, rgba(0, 0, 0, 0.45));
}

/* page block: fore edge, top, bottom */
.book3d__edge,
.book3d__top,
.book3d__bottom {
    background-color: #e4dfd2;
}

.book3d__edge {
    top: 0;
    left: calc(50% - var(--d) / 2);
    width: var(--d);
    height: 100%;
    background-image: repeating-linear-gradient(90deg, #efebe0 0 1px, #cfc9b9 1px 2px);
    transform: rotateY(90deg) translateZ(calc(var(--w) / 2 - 1px));
}

.book3d__top,
.book3d__bottom {
    left: 0;
    width: 100%;
    height: var(--d);
    top: calc(50% - var(--d) / 2);
    background-image: repeating-linear-gradient(180deg, #efebe0 0 1px, #cfc9b9 1px 2px);
}

.book3d__top {
    transform: rotateX(90deg) translateZ(calc(var(--h) / 2 - 1px));
}

.book3d__bottom {
    transform: rotateX(-90deg) translateZ(calc(var(--h) / 2 - 1px));
}

/* soft shadow on the surface the book lies on, pushed a little down and to the right */
.book3d__shadow {
    inset: 0;
    background: rgba(0, 0, 0, 0.6);
    filter: blur(calc(var(--h) * 0.035));
    transform: translateZ(calc(var(--d) / -2 - 2px)) translate(5%, 4%);
    backface-visibility: visible;
}

@media (prefers-reduced-motion: reduce) {
    .book3d__obj { transition: none; }
}

/* ==========================================================================
   PROJECT LAYOUTS: two-row grid, poster fan, seamless strip, cropped panels,
   hover swap, enlarged view. Each one is chosen per project (layout in script.js).
   ========================================================================== */

/* more air between a category title and its first file */

/* Home 3D book: the frame hugs the book and takes the card's own colour */
.project-card__media--book,
.space .project-card__media--book {
    background: var(--card-bg);
}

/* ---- Two rows of small tiles (3D scenes). A portrait picture takes both rows. ---- */
.case--grid2 .case__gallery--grid2 {
    --row-h: 34vh;
    --gap: 1rem;
    display: grid;
    grid-template-rows: repeat(2, var(--row-h));
    grid-auto-flow: column;
    grid-auto-columns: max-content;
    gap: var(--gap);
    align-content: center;
}

.case--grid2 .case__gallery--grid2 .shot {
    flex: none;
    width: calc(var(--row-h) * var(--ar));
    height: var(--row-h);
}

.case--grid2 .case__gallery--grid2 .shot.shot--tall {
    grid-row: span 2;
    height: calc(var(--row-h) * 2 + var(--gap));
    width: calc((var(--row-h) * 2 + var(--gap)) * var(--ar));
}

.case--grid2 .case__gallery--grid2 .shot .shot__img {
    width: 100%;
    height: 100%;
    min-width: 0;
    min-height: 0;
}

.case--grid2 .case__gallery--grid2 .shot .shot__img img {
    width: 100%;
    height: 100%;
    min-height: 0;
    max-height: none;
    object-fit: cover;
}

.case--grid2 .shot--video .shot__video video {
    height: 70vh;                    /* as tall as the two rows of tiles */
}

/* ---- Poster fan: a third of each poster shows; the one under the pointer opens out ---- */
.case--fan .case__gallery--fan {
    display: flex;
    align-items: flex-start;
    gap: 0;
}

.fan__slot {
    --pw: calc(85vh * var(--ar));     /* the poster's full width */
    --m: 3rem;                        /* breathing room on both sides of an open poster */
    position: relative;
    z-index: var(--i);
    flex: none;
    width: calc(var(--pw) * 0.3);
    transition: width 0.6s var(--ease-ae);
}

.fan__slot:last-child {
    width: var(--pw);
}

/* the stacking order never changes, not even while a poster opens: later posters stay on top of earlier ones
   and simply slide out of the way */
.fan__slot:hover,
.fan__slot:focus-within {
    width: calc(var(--pw) + var(--m));
}

.case--fan .fan__poster {
    display: block;
    width: var(--pw);
    height: 85vh;
    transition: transform 0.6s var(--ease-ae);
    box-shadow: -18px 0 36px -14px rgba(0, 0, 0, 0.7), 0 0 0 0 var(--canvas);
}

.fan__slot:hover .fan__poster,
.fan__slot:focus-within .fan__poster {
    transform: translateX(var(--m));
    box-shadow: -18px 0 36px -14px rgba(0, 0, 0, 0.7), calc(var(--m) * -1) 0 0 0 var(--canvas);
}

.case--fan .case__gallery--fan .fan__poster .shot__img {
    width: 100%;
    height: 100%;
    min-width: 0;
    min-height: 0;
}

.case--fan .case__gallery--fan .fan__poster .shot__img img {
    width: 100%;
    height: 100%;
    min-height: 0;
    max-height: none;
    object-fit: cover;
}

/* captions: only the open poster shows one */
.fan__cap {
    display: grid;
    gap: var(--space-1);
    width: var(--pw);
    margin: 1rem 0 0 var(--m);
    opacity: 0;
    transition: opacity 0.35s var(--ease-out);
    pointer-events: none;
    margin-left: 0;
}

.fan__slot:hover .fan__cap,
.fan__slot:focus-within .fan__cap {
    opacity: 1;
}

/* ---- Seamless strip (sweatshirt photos): no gaps, no frames, no captions ---- */
.case--seamless .case__gallery--seamless {
    gap: 0;
    align-items: center;
}

.case--seamless .case__gallery--seamless .shot {
    flex: none;
    width: calc(85vh * var(--ar));
    height: 85vh;
}

.case--seamless .case__gallery--seamless .shot .shot__img {
    width: 100%;
    height: 100%;
    min-width: 0;
    min-height: 0;
    border: 0;
    background: none;
}

.case--seamless .case__gallery--seamless .shot .shot__img img {
    width: 100%;
    height: 100%;
}

/* ---- Cropped panels (vector art): each picture sits in the same frame it has on the cover ---- */
.case--crop .case__gallery .shot--crop .shot__img {
    width: calc(85vh * var(--cr));
}

.case--crop .case__gallery .shot--crop .shot__img img {
    width: 100%;
    height: 85vh;
    object-fit: cover;
    object-position: var(--cp, 50% 50%);
}

/* ---- Hover swap: a second picture fades in over the first ---- */
.shot__img--swap {
    position: relative;
}

.shot .shot__img--swap img + img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    min-height: 0;
    max-height: none;
    object-fit: cover;
    opacity: 0;
    transition: opacity 0.6s var(--ease-ae);
}

.shot:hover .shot__img--swap img + img,
.shot:focus-visible .shot__img--swap img + img {
    opacity: 1;
}

/* ---- "Show enlarged" on an image that has a bigger version ---- */
.shot--zoom {
    position: relative;
    margin: 0;
}

.shot__zoom {
    position: absolute;
    left: 1rem;
    top: calc(85vh - 3.75rem);
    background-color: var(--canvas);
    opacity: 0;
    transform: translateY(6px);
    transition: opacity 0.3s var(--ease-out), transform 0.3s var(--ease-out), background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}

.shot--zoom:hover .shot__zoom,
.shot--zoom:focus-within .shot__zoom {
    opacity: 1;
    transform: none;
}

@media (hover: none) {
    .shot__zoom { opacity: 1; transform: none; }
}

/* ---- Enlarged view: a see-through layer over the whole page; the image zooms and drags ---- */
.zoomview {
    position: fixed;
    inset: 0;
    z-index: 99990;
    display: grid;
    place-items: center;
    overflow: hidden;
    background-color: color-mix(in srgb, var(--canvas) 52%, transparent);
    backdrop-filter: blur(16px);
    opacity: 0;
    visibility: hidden;
    cursor: grab;
    touch-action: none;
    transition: opacity var(--dur-base) var(--ease-out), visibility 0s linear var(--dur-base);
}

.zoomview.is-open {
    opacity: 1;
    visibility: visible;
    transition-delay: 0s;
}

.zoomview.is-dragging {
    cursor: grabbing;
}

.zoomview__img {
    display: block;
    max-width: none;
    transform-origin: 50% 50%;
    user-select: none;
    -webkit-user-drag: none;
}

.zoomview__tools {
    position: fixed;
    left: 1.5rem;
    bottom: 1.5rem;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2);
    background-color: var(--canvas);
    border: 1px solid var(--border-strong);
}

.zoomview__level {
    min-width: 3.5em;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.zoomview__hint {
    position: fixed;
    left: 1.5rem;
    top: 1.5rem;
    max-width: calc(100vw - 3rem);
    padding: var(--space-2) var(--space-3);
    background-color: var(--canvas);
    border: 1px solid var(--border);
}

.zoomview__close {
    position: fixed;
    right: 1.5rem;
    bottom: 1.5rem;
}

/* ==========================================================================
   GALLERY PAGE: three rows of photographs that scroll by themselves
   ========================================================================== */
.gallery__head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-2) var(--space-5);
    padding-block: var(--space-3) var(--space-4);
}

.gallery__head h1 {
    font-size: clamp(2rem, 4vw, 3rem);
    font-weight: 700;
    letter-spacing: -0.025em;
    line-height: 1;
}

.gallery__rows {
    display: grid;
    gap: 0.75rem;
    padding-bottom: 0.75rem;
    overflow: hidden;
    grid-template-rows: repeat(3, var(--row-h));
    height: auto;
}

.gallery__row {
    min-height: 0;
    overflow: hidden;
}

.gallery__track {
    display: flex;
    width: max-content;
    height: 100%;
    animation: gallery-run var(--dur, 120s) linear infinite var(--dir, normal);
    animation-duration: calc(var(--dur, 120s) * 1.5);   /* bigger photos, same visual speed */
}

/* the track holds the photos twice, so half its width is exactly one full turn */
@keyframes gallery-run {
    to { transform: translateX(-50%); }
}

.gallery.is-paused .gallery__track {
    animation-play-state: paused;
}

.gallery__item {
    flex: none;
    height: 100%;
    aspect-ratio: var(--ar);
    margin-right: 0.75rem;           /* a margin, not a gap: the half-width loop stays exact */
    padding: 0;
    border: 0;
    overflow: hidden;
    background-color: var(--surface);
    cursor: pointer;
}

.gallery__item img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.gallery__item:hover,
.gallery__item:focus-visible {
    outline: 1px solid var(--accent);
    outline-offset: -1px;
}

.gallery__pause {
    position: fixed;
    z-index: 60;
    transition: opacity var(--dur-base) var(--ease-out);
    right: 1rem;
    bottom: 4.25rem;
}

.gallery__pause.is-away {
    opacity: 0;
    pointer-events: none;
}

.gallery__pause .icon-play,
.gallery__pause[aria-pressed="true"] .icon-pause {
    display: none;
}

.gallery__pause[aria-pressed="true"] .icon-play {
    display: block;
}

@media (prefers-reduced-motion: reduce) {
    .gallery__track { animation: none; }
    .gallery__row { overflow-x: auto; }
    .fan__slot, .case--fan .fan__poster { transition: none; }
}

/* a piece's own sections: air between a paragraph and the next heading */
.case__intro .case__narrative + .case__heading {
    margin-top: var(--space-5);
}

/* gallery rows fill the screen under the heading */

/* gallery photos 50% larger: each row is 1.5 times the height that filled the screen, so the page scrolls down through the three rows */
.gallery {
    --row-h: calc((max(26rem, 100svh - var(--header-height) - 11rem) - 2.25rem) / 3 * 1.5);   /* 1.5 x the first version of the rows */
}

/* ==========================================================================
   PHOTO SHOOT REQUEST (photogallery page)
   ========================================================================== */
.shoot__grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
    gap: var(--space-7, 4rem) clamp(2rem, 6vw, 6rem);
    align-items: start;
}

.shoot__intro h2 {
    margin-block: var(--space-3) var(--space-4);
    font-size: var(--fs-h2);
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.03em;
}

.shoot__types {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-top: var(--space-5);
    padding: 0;
    list-style: none;
}

.shoot__types li {
    padding: 0.35rem 0.75rem;
    border: 1px solid var(--border-strong);
}

.shoot__form {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-4);
}

.field {
    display: grid;
    gap: var(--space-2);
}

.field--wide {
    grid-column: 1 / -1;
}

.field input,
.field select,
.field textarea {
    width: 100%;
    min-height: 2.75rem;
    padding: 0.6rem 0.8rem;
    font: inherit;
    color: var(--text);
    background-color: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: 0;
    font-size: 1rem;
}

.field textarea {
    resize: vertical;
}

.field input::placeholder,
.field textarea::placeholder {
    color: var(--text-muted);
}

.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.shoot__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-4);
}

.shoot__note {
    flex: 1 1 18rem;
    max-width: 44ch;
}

@media (max-width: 800px) {
    .shoot__grid,
    .shoot__form { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   TYPESET: small refinements inside the existing faces and scale
   ========================================================================== */
/* balanced headings and quotes, no one-word last lines in paragraphs */
h1, h2, h3,
.project-card__title,
.case__quote {
    text-wrap: balance;
}

p,
.case__narrative,
.project-card__desc,
.lead {
    text-wrap: pretty;
}

/* ids, years, counters and zoom levels line up */
.meta,
.badge,
.scheda__bar,
.case__facts {
    font-variant-numeric: tabular-nums;
}

/* light text on a dark surface: a little more leading and air than the same text on white */

/* 11px labels move up to the system's 12px meta size */
.badge,
.scheda__bar {
    font-size: var(--fs-meta);
}

/* ==========================================================================
   FOOTER: a loud closing statement on the accent
   ========================================================================== */

.footer-call__lead {
    max-width: 38ch;
    margin-bottom: var(--space-6);
    font-size: var(--fs-lead);
    line-height: 1.4;
}

.site-footer .btn-row .btn {
    min-height: 3.25rem;
    padding-inline: 1.75rem;
    font-size: var(--fs-small);
}

/* ==========================================================================
   HOME: short bio and a sneak peek of the photogallery
   ========================================================================== */
.about-peek__grid {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: var(--space-6) clamp(2rem, 6vw, 6rem);
    align-items: start;
}

.about-peek h2 {
    margin-top: var(--space-3);
    font-size: var(--fs-h2);
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.03em;
}

.about-peek__text {
    display: grid;
    gap: var(--space-4);
    justify-items: start;
    max-width: 62ch;
}

.about-peek__text p {
    color: var(--text-muted);
    line-height: 1.7;
}

.about-peek__text strong {
    color: var(--text);
}

.peek__head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--space-4);
    margin-bottom: var(--space-5);
}

.peek h2 {
    margin-top: var(--space-3);
    font-size: var(--fs-h2);
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.03em;
}

/* one row, full width, always running; it slows down under the pointer (see initPeekRow) */
.peek__row {
    height: clamp(14rem, 36vh, 26rem);
}

.peek__row .gallery__item {
    display: block;
}

.peek__row .gallery__track {
    animation-duration: calc(var(--dur, 60s) * 1.5);
}

@media (max-width: 800px) {
    .about-peek__grid { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   FOOTER: never taller than the screen. Type and spacing follow the viewport height.
   (On small or short screens the footer simply stacks at its natural height.)
   ========================================================================== */
@media (min-width: 800px) and (min-height: 700px) {
    .site-footer {
        max-height: 100vh;
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        padding-block: clamp(1.5rem, 5vh, 3.5rem);
    }

    .site-footer > .container {
        display: flex;
        flex-direction: column;
        gap: 3vh;
    }

    .footer-call {
        margin-bottom: 0;
    }

    .footer-call h2 {
        margin-block: 1.5vh 2vh;
        font-size: min(9vw, 12.5vh);
    }

    .footer-call__lead {
        margin-bottom: 3vh;
        font-size: clamp(1rem, 2.6vh, 1.5rem);
    }

    .site-footer .btn-row .btn {
        min-height: clamp(2.5rem, 6vh, 3.25rem);
    }

    .footer-grid {
        margin-bottom: 0;
        gap: 2vh 1.5rem;
    }

    .status-panel__body {
        padding: 1.5vh 1rem;
        line-height: 1.6;
    }

    .footer-legal {
        padding-top: 1.5vh;
    }

    .footer-legal a {
        min-height: 2.5rem;
    }
}

/* ---- "More to see": the arrows slide in one after the other when the band comes into view ---- */
.cta-band.arrow-ready .cta-band__links a > [aria-hidden="true"] {
    display: inline-block;
    opacity: 0;
    transform: translateX(-1.4em);
    transition: opacity 0.5s var(--ease-ae), transform 0.7s var(--ease-ae);
    transition-delay: calc(var(--n, 0) * 140ms + 200ms);
}

.cta-band.arrow-ready.is-in .cta-band__links a > [aria-hidden="true"] {
    opacity: 1;
    transform: none;
}

/* "Get in touch": the one nav item that is a button, not a link */
.nav-link.nav-link--cta {
    gap: 0.5rem;
    min-height: 2.5rem;
    padding: 0 1rem;
    background-color: var(--ink);
    color: var(--accent);           /* red on the black button: 4.6:1 */
    border: 1px solid var(--ink);
    border-bottom-color: var(--ink);
    transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}

.nav-link.nav-link--cta::after {
    content: "↗";
    font-weight: 700;
}

.nav-link.nav-link--cta:hover,
.nav-link.nav-link--cta:focus-visible {
    background-color: transparent;
    color: var(--ink);
}

@media (max-width: 767px) {
    .site-nav .nav-link.nav-link--cta {
        justify-content: center;
        margin-top: var(--space-3);
        min-height: 3rem;
        border-bottom: 1px solid var(--ink);
    }
}

/* Devil mode: a small switch in the lower right corner. It does not do anything yet, and says so. */
.devil-toggle {
    position: fixed;
    bottom: 1rem;
    z-index: 60;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    height: 2.5rem;
    min-width: 2.5rem;
    padding: 0 0.6rem;
    background-color: color-mix(in srgb, var(--canvas) 85%, transparent);
    color: var(--text-muted);
    border: 1px dashed var(--border-strong);
    cursor: not-allowed;
    transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
    left: auto;
    right: 1rem;
    flex-direction: row-reverse;
}

.devil-toggle:hover,
.devil-toggle:focus-visible {
    color: var(--accent);
    border-color: var(--accent);
}

.devil-toggle__tip {
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
    letter-spacing: var(--tracking-meta);
    text-transform: uppercase;
    white-space: nowrap;
    color: var(--text);
}

.devil-toggle__tip:empty {
    display: none;
}

/* home: "See all" sits beside the section title */
.space__all {
    margin-right: auto;
}

/* one reading rhythm for text on dark: 1.7 everywhere paragraphs run */
.prose p {
    line-height: 1.7;
}

/* Poster fan: no margin on the left of an open poster. It opens in place and only the right side gets room. */

.fan__slot:hover .fan__poster,
.fan__slot:focus-within .fan__poster {
    transform: none;
    box-shadow: -18px 0 36px -14px rgba(0, 0, 0, 0.7), 0 0 0 0 var(--canvas);
}

/* projects whose pictures read as one sheet (Tragic Sigils): no gap between them */
.case--tight .case__gallery {
    gap: 0;
}

.case--tight .case__gallery .shot__img {
    border: 0;
}

/* ==========================================================================
   HERO DESK: four project files lying on one another at the right of the title,
   the same files as the cards further down. Hover spreads them; each opens its project.
   ========================================================================== */
.hero .container {
    position: relative;
}

.desk {
    position: relative;
    width: 100%;
    aspect-ratio: 1.5;
    margin: clamp(2rem, 6vw, 3rem) 0 0;
    padding: 0;
    list-style: none;
}

.desk__file {
    position: absolute;
    left: calc(var(--i) * 15%);
    top: calc(var(--i) * 9%);
    width: var(--fw, 44%);
    rotate: calc((var(--i) - 1.5) * 3deg);
    transition: translate 0.35s var(--ease-out), rotate 0.35s var(--ease-out), scale 0.35s var(--ease-out);
    animation: desk-drop 0.7s var(--ease-out) calc(0.9s + var(--i) * 0.12s) backwards;
}

/* each file is laid on the desk after the title has come in */
@keyframes desk-drop {
    from { opacity: 0; translate: 0 -1.5rem; }
}

.desk__file a {
    display: block;
    color: var(--text-muted);
    text-decoration: none;
    background-color: var(--card-bg);
    border: 1px solid var(--border);
    box-shadow: var(--shadow-lift);
    transition: border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}

.desk__bar {
    display: block;
    padding: 0.4rem 0.55rem;
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    letter-spacing: var(--tracking-meta);
    border-bottom: 1px solid var(--border);
}

/* each file takes the proportions of the picture it carries */
.desk__file img {
    display: block;
    width: 100%;
    height: auto;
}

/* the file under the pointer is drawn from the pile like a card from a deck: up and straight. It keeps its place in
   the pile (the files above it stay above), and waits for the one before to drop back, so two are never up at once. */
.desk__file.is-up,
.desk__file:focus-within {
    translate: 0 -34%;
    rotate: 0deg;
    transition: translate 0.5s var(--ease-out) 0.12s, rotate 0.5s var(--ease-out) 0.12s;
}

.desk__file.is-up a,
.desk__file:focus-within a {
    box-shadow: 0 30px 50px -18px rgba(0, 0, 0, 0.75);
}

.desk__file a:hover,
.desk__file a:focus-visible {
    color: var(--accent);
    border-color: var(--accent);
}

.desk__file a:focus-visible {
    box-shadow: 0 0 0 2px var(--canvas), 0 0 0 4px var(--accent), var(--shadow-lift);
}

/* wide screens: the desk sits beside the title, over the orbits, and the quote leaves it room */
@media (min-width: 901px) {
    .desk {
        position: absolute;
        top: 4rem;
        right: calc(var(--gutter) + 2rem);
        width: min(34vw, 480px);
        margin: 0;
    }

    .hero:has(.desk) .hero__quote {
        max-width: min(30em, 58%);
    }
}

@media (prefers-reduced-motion: reduce) {
    .desk__file { animation: none; transition: none; }
}

/* ==========================================================================
   KEYBOARD FOCUS ON CARDS: a full ring, not only the 1px edge
   ========================================================================== */
.space .project-card:focus-visible {
    box-shadow: 0 0 0 2px var(--canvas), 0 0 0 4px var(--accent), var(--shadow-lift);
}

.scheda:focus-visible {
    box-shadow: 0 0 0 2px var(--canvas), 0 0 0 4px var(--accent), 0 28px 48px -14px rgba(0, 0, 0, 0.6);
}

/* ==========================================================================
   HOME CARDS ON PHONES: one clear column, nothing to drag, nothing overlapping
   ========================================================================== */
@media (max-width: 760px) {
    .space__viewport {
        width: auto;
        height: auto;
        margin-left: 0;
        padding-inline: var(--gutter);
        overflow: visible;
    }

    .space__board {
        display: grid;
        gap: var(--space-6);
        height: auto;
        transform: none !important;
    }

    .space .project-card,
    .space.is-enhanced .project-card {
        position: relative;
        left: auto;
        top: auto;
        width: 100%;
        translate: none;
        rotate: none;
        cursor: pointer;
        touch-action: auto;
    }

    .space .project-card:hover { transform: none; }
    .space__hint, #space-reset { display: none; }
}

/* ==========================================================================
   CV LINK: until the PDF is online it says so and does nothing
   ========================================================================== */
[data-cv].is-pending {
    cursor: not-allowed;
}

.cv-soon {
    opacity: 0.75;
}

/* ==========================================================================
   DEVIL SWITCH: out of the way once the footer is on screen
   ========================================================================== */
.devil-toggle {
    transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out), opacity 0.3s var(--ease-out), visibility 0.3s;
}

html.footer-in-view .devil-toggle {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

/* ==========================================================================
   PHONES: lighter pages. The grain overlay blends over the whole screen on every frame: off.
   ========================================================================== */
@media (max-width: 760px), (pointer: coarse) {
    .film-grain { display: none; }
}

/* two-row tiles with detail notes: the frame and its button fill the tile */
.case--grid2 .case__gallery--grid2 .shot--notes .shot__frame,
.case--grid2 .case__gallery--grid2 .shot--notes .shot__open {
    display: block;
    width: 100%;
    height: 100%;
}

/* home cards gliding to their place when the layout is put in order or shuffled */
.space .project-card.is-arranging {
    transition: translate 0.7s var(--ease-out), rotate 0.7s var(--ease-out), box-shadow 0.3s var(--ease-out);
}

@media (prefers-reduced-motion: reduce) {
    .space .project-card.is-arranging { transition: none; }
}

/* home bio: a short stop between the works and the photos, not a full section */
.section.about-peek {
    padding-block: clamp(2.5rem, 5vw, 4.5rem);
}

.about-peek__grid {
    gap: var(--space-4) clamp(2rem, 5vw, 4.5rem);
    align-items: center;
}

.about-peek h2 {
    font-size: clamp(1.75rem, 3.2vw, 2.75rem);
}

.about-peek__text {
    gap: var(--space-3);
    max-width: 58ch;
}

.section.peek {
    padding-top: clamp(2.5rem, 5vw, 4.5rem);
}

/* ==========================================================================
   PROJECT VIEW: two rows that use the whole height, the "+N more" tile, browsing in the lightbox
   ========================================================================== */
.case--grid2 .case__gallery--grid2 {
    --row-h: calc((100dvh - 7.5rem - var(--gap)) / 2);
}

.case--grid2 .shot--video .shot__video video {
    height: calc(var(--row-h) * 2 + var(--gap));
}

/* the renders kept out of the row: one tile, the first of them dimmed under a count */
.shot--more {
    position: relative;
}

.shot--more .shot__img img {
    filter: brightness(0.32) grayscale(0.5);
    transition: filter var(--dur-base) var(--ease-out);
}

.shot--more:hover .shot__img img,
.shot--more:focus-visible .shot__img img {
    filter: brightness(0.5) grayscale(0.2);
}

.shot--more__label {
    position: absolute;
    inset: 0;
    display: grid;
    place-content: center;
    justify-items: center;
    gap: var(--space-1);
    pointer-events: none;
}

.shot--more__label b {
    font-family: var(--font-display);
    font-size: clamp(2rem, 4vw, 3.5rem);
    font-weight: 700;
    line-height: 1;
    color: var(--accent);
}

.lightbox__nav {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.lightbox__nav[hidden] {
    display: none;
}

.lightbox__count {
    min-width: 4.5em;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   PROJECT VIEW ON PHONES: one column that scrolls down, not a row that scrolls sideways
   ========================================================================== */
@media (max-width: 760px) {
    .modal__drawer {
        display: block;
        overflow-x: hidden;
        overflow-y: auto;
        padding: 1rem var(--gutter) 6rem;
    }

    #case-modal-content {
        width: auto;
    }

    .case--row {
        flex-direction: column;
        align-items: stretch;
        width: 100%;
        height: auto;
        gap: var(--space-6);
    }

    .case__intro {
        flex: none;
        max-height: none;
        overflow: visible;
        padding-right: 0;
    }

    .case__intro.is-scrollable:not(.is-end) {
        -webkit-mask-image: none;
        mask-image: none;
    }

    .case__scroll {
        display: none;
    }

    .case .case__gallery,
    .case--grid2 .case__gallery--grid2,
    .case--seamless .case__gallery--seamless,
    .case--fan .case__gallery--fan {
        display: flex;
        flex-direction: column;
        gap: var(--space-4);
        width: 100%;
        height: auto;
    }

    .case--seamless .case__gallery--seamless,
    .case--tight .case__gallery {
        gap: 0;
    }

    .case .shot,
    .case--grid2 .case__gallery--grid2 .shot,
    .case--grid2 .case__gallery--grid2 .shot.shot--tall,
    .case--tall .shot,
    .case .shot.is-portrait,
    .case--seamless .case__gallery--seamless .shot,
    .case .shot--video,
    .fan__slot,
    .case--fan .fan__poster {
        flex: none;
        width: 100%;
        height: auto;
        transform: none;
    }

    .case .shot__img,
    .case--grid2 .case__gallery--grid2 .shot .shot__img,
    .case--tall .shot__img,
    .case .shot.is-portrait .shot__img,
    .case--seamless .case__gallery--seamless .shot .shot__img,
    .case--fan .case__gallery--fan .fan__poster .shot__img,
    .case--crop .case__gallery .shot--crop .shot__img {
        width: 100%;
        height: auto;
    }

    .case .shot__img img,
    .case--grid2 .case__gallery--grid2 .shot .shot__img img,
    .case--tall .shot__img img,
    .case .shot.is-portrait .shot__img img,
    .case--seamless .case__gallery--seamless .shot .shot__img img,
    .case--fan .case__gallery--fan .fan__poster .shot__img img,
    .case--crop .case__gallery .shot--crop .shot__img img {
        width: 100%;
        height: auto;
        max-height: none;
        object-fit: contain;
    }

    .case .shot__video video,
    .case--grid2 .shot--video .shot__video video {
        width: 100%;
        height: auto;
    }

    .fan__cap {
        position: static;
        opacity: 1;
        margin-top: var(--space-2);
    }

    .case__flipbook {
        width: 100%;
    }

    .case__flipbook iframe {
        height: 72vh;
    }
}

@media (max-width: 760px) {
    .fan__slot { --pw: 100%; }
    .fan__cap { width: 100%; }
    .case--fan .fan__poster .shot__img { aspect-ratio: auto; }
}

/* ==========================================================================
   ARCHIVE FILES (works page): a drawer of index cards.
   The cards sit on the right, overlapping, each showing its bar and a strip of the cover. The one pointed at
   (or focused) straightens and slides out to the left, in front of the others, showing its whole cover.
   Room is kept on the right for the drawer index.
   ========================================================================== */
.schede-stage {
    max-width: none;
    padding: var(--space-5) clamp(1rem, 7vw, 7.5rem) var(--space-6) 0;
    perspective: 1800px;
    perspective-origin: 30% 40%;
}

.schede-stack {
    --scheda-body: clamp(300px, 46vh, 460px);
    --bar-h: 3rem;
    --peek: 6.25rem;                 /* how much of each card shows in the drawer */
    align-items: flex-end;
}

.schede-stack .scheda {
    width: min(64%, 880px);
    margin-top: calc(var(--peek) - var(--scheda-body) - var(--bar-h));
    transform: rotateX(-10deg);
    transform-origin: center bottom;
    /* going back into the drawer: slow and soft, 1.5s, so fast pointer moves never make it jump */
    transition: transform 1.5s var(--ease-out), border-color 0.6s var(--ease-out), box-shadow 0.6s var(--ease-out);
}

.schede-stack .scheda:first-child {
    margin-top: 0;
}

.schede-stack .scheda:hover,
.schede-stack .scheda:focus-visible,
.schede-stack .scheda.is-out {
    z-index: auto;                   /* the drawer order never changes */
}

.schede-stack .scheda:hover {
    transform: rotateX(-10deg);
    border-color: var(--border-strong);
    box-shadow: var(--shadow-lift);
}

/* pulled out to the left. It keeps its place in the drawer, at the same tilt and depth as the others: the cards in front
   of it stay in front, like the files of the hero, and once out its cover shows on the free side. */
.schede-stack .scheda.is-out,
.schede-stack .scheda:focus-visible {
    transform: rotateX(-10deg) translateX(-58%);
    border-color: var(--accent);
    box-shadow: 0 34px 60px -20px rgba(0, 0, 0, 0.75);
}

.schede-stack .scheda:focus-visible {
    box-shadow: 0 0 0 2px var(--canvas), 0 0 0 4px var(--accent), 0 34px 60px -20px rgba(0, 0, 0, 0.75);
}

/* the bar: code, title, then what the file holds */
.schede-stack .scheda__bar {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    align-items: center;
    gap: var(--space-3) var(--space-4);
    min-height: var(--bar-h);
    padding: 0 1.1rem;
}

.schede-stack .scheda__bar strong {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.scheda__info,
.scheda__media {
    color: var(--text-muted);
    white-space: nowrap;
}

.schede-stack .scheda__bar .scheda__media {
    display: block;
}

.scheda__media {
    padding-left: var(--space-3);
    color: var(--accent-text);
    border-left: 1px solid var(--border);
}

.schede-stack .scheda__body {
    height: var(--scheda-body);
}

/* phones and touch screens: a plain column of whole cards */
@media (max-width: 760px), (hover: none) {
    .schede-stage {
        padding: var(--space-4) 0;
    }

    .schede-stack {
        align-items: stretch;
        gap: var(--space-5);
    }

    .schede-stack .scheda,
    .schede-stack .scheda:hover,
    .schede-stack .scheda.is-out {
        width: 100%;
        margin-top: 0;
        transform: none;
    }
}

@media (max-width: 760px) {
    .schede-stack {
        --scheda-body: clamp(200px, 34vh, 300px);
    }

    .schede-stack .scheda__bar {
        grid-template-columns: auto minmax(0, 1fr);
        padding: var(--space-3) var(--space-4);
    }

    .schede-stack .scheda__bar strong {
        white-space: normal;
    }

    .scheda__info,
    .scheda__media {
        grid-column: 1 / -1;
        white-space: normal;
    }

    .scheda__media {
        padding-left: 0;
        border-left: 0;
    }
}

@media (prefers-reduced-motion: reduce) {
    .schede-stack .scheda,
    .schede-stack .scheda.is-out {
        transition: none;
    }
}

/* archive files: smaller 4:3 cards; every cover (landscape or square) fills its card, centred */
.schede-stack .scheda__body img {
    object-fit: cover;
    object-position: center center;
}

@media (min-width: 761px) and (hover: hover) {
    .schede-stack {
        --card-w: clamp(420px, 44vw, 620px);
        --scheda-body: calc(var(--card-w) * 0.75);
    }

    .schede-stack .scheda {
        width: var(--card-w);
    }

    /* out of the drawer it slides almost its whole width, so the cover shows nearly in full */
    .schede-stack .scheda.is-out,
    .schede-stack .scheda:focus-visible {
        transform: rotateX(-10deg) translateX(-82%);
    }

    /* a narrower card: the bar keeps code, title and contents; year and software are in the project view */
    .schede-stack .scheda__bar {
        grid-template-columns: auto minmax(0, 1fr) auto;
    }

    .schede-stack .scheda__info {
        display: none;
    }
}

/* the cards in a drawer step down to the right, 1rem each, like a staircase: the last one sits on the right edge */
@media (min-width: 761px) and (hover: hover) {
    .schede-stack .scheda:nth-last-child(2) { margin-right: 1rem; }
    .schede-stack .scheda:nth-last-child(3) { margin-right: 2rem; }
    .schede-stack .scheda:nth-last-child(4) { margin-right: 3rem; }
    .schede-stack .scheda:nth-last-child(5) { margin-right: 4rem; }
    .schede-stack .scheda:nth-last-child(6) { margin-right: 5rem; }
}

/* archive: the drawers sit closer to one another (the cards inside a drawer keep their spacing) */
.schede-group + .schede-group {
    margin-top: clamp(1.5rem, 3vw, 2.5rem);
}

.schede-group__title {
    margin-bottom: clamp(0.75rem, 1.5vw, 1.25rem);
}

.schede-stack {
    padding-bottom: 0;
}

.schede-group .schede-stage {
    padding-top: var(--space-3);
    padding-bottom: 0;
}

/* wide screens: the drawer title sits in the free space on the left, level with the first card, so it takes no height */
@media (min-width: 1100px) and (hover: hover) {
    .schede-group {
        position: relative;
    }

    .schede-group__title {
        position: absolute;
        top: 0;
        left: 0;
        margin: 0;
    }

    .schede-group .schede-stage {
        padding-top: 0;
    }
}

/* home: every card the same height. The picture takes whatever the text leaves, filling its frame;
   titles and descriptions keep to two lines so the text never pushes a card taller than the others */
.space .project-card {
    height: var(--card-h, 32rem);
}

.space .project-card__media,
.space .project-card__media--book {
    flex: 1 1 0;
    min-height: 0;
    height: auto;
    aspect-ratio: auto;
}

.space .project-card__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.space .project-card__title,
.space .project-card__desc {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
}

@media (max-width: 760px) {
    .space .project-card { --card-h: 30rem; }
}

/* home bio: the title lines up with the top of the paragraph */
.about-peek__grid {
    align-items: start;
}

.about-peek h2 {
    margin-top: 0;
}

/* the page colour lives on the root only, so the grain layer (behind everything) shows through the bare background */
body {
    background-color: transparent;
}

/* coming out of the drawer: a little quicker than going back */
.schede-stack .scheda.is-out {
    transition: transform 0.9s var(--ease-out), border-color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}

/* Selected works: the canvas of cards is page background too, so the grain shows through it */
.space__viewport {
    background-color: transparent;
}

/* contact: two addresses, each with a short line saying what it is for */
.email-note {
    margin-top: var(--space-2);
}

.email-display.email-display--second {
    margin-top: var(--space-5);
    font-size: clamp(1.15rem, 2.3vw, 1.9rem);
}
