/* ------------------------------------------------------------------------------------ */
/* ------------------------------- HOME HERO + INTRO LOADER --------------------------- */
/* ------------------------------------------------------------------------------------ */

/* TT Modernoir is a TRIAL font (evaluation only): buy a web licence from TypeType before going live */
@font-face {
    font-family: 'TT Modernoir';
    src: url('../fonts/tt-modernoir-demibold.woff') format('woff');
    font-weight: 600;
    font-style: normal;
    font-display: block;
}

:root {
    --font-deco: 'TT Modernoir', 'Montserrat', sans-serif;
    --font-pixel: 'VT323', 'Space Mono', monospace;
    --font-serif-italic: 'Instrument Serif', Georgia, serif;
    --paint-paper: #faf8f2;           /* matches the paint artwork's off-white */
    /* atomic-age accents: deep teal + burnt orange, both ~4.3:1 against the white panel */
    --accent-teal: #2E8570;
    --accent-orange: #C95A1E;
    --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
    /* One screen height in px for the (unscaled) pinned stage. Set by hero.js. */
    --hero-vh: 100vh;
}

/* --------------------------------------- INTRO LOADER ----------------------------------- */

.intro-loader {
    position: fixed;
    inset: 0;
    z-index: 10000;
    display: none;
    place-items: center;
    background: var(--bg-paper);
    clip-path: inset(0 0 0 0);
    transition: clip-path 1.1s var(--ease-out-expo);
}
html.is-loading .intro-loader,
.intro-loader.is-leaving { display: grid; }
html.is-loading body { overflow: hidden; }
.intro-loader.is-leaving { clip-path: inset(0 0 100% 0); }

.intro-loader__inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 22px;
    transition: transform 1.1s var(--ease-out-expo), opacity 0.6s ease;
}
.intro-loader.is-leaving .intro-loader__inner { transform: translateY(-60px) scale(0.92); opacity: 0; }

.atom {
    width: min(300px, 62vw);
    height: auto;
    display: block;
    overflow: visible;
}
.atom__orbit {
    stroke-dasharray: 100 100;
    stroke-dashoffset: 100;
    animation: atom-orbit-draw 1.3s var(--ease-out-expo) forwards;
}
.atom__orbit:nth-child(2) { animation-delay: 0.12s; }
.atom__orbit:nth-child(3) { animation-delay: 0.24s; }
@keyframes atom-orbit-draw { to { stroke-dashoffset: 0; } }

.atom__halo { fill: var(--bg-paper); }
.atom__teeth { fill: #c8951f; }
.atom__gear, .atom__tool { will-change: transform; }
.atom__tool { opacity: 0; }

.intro-loader__count {
    font-family: 'Space Mono', monospace;
    font-size: 11px;
    letter-spacing: 0.24em;
    color: var(--ink);
    opacity: 0.55;
    font-variant-numeric: tabular-nums;
}

/* --------------------------------------- HERO PANEL ----------------------------------- */

.hero.panel-section {
    padding: 0;
    margin-bottom: var(--space-10);
    overflow: clip;            /* the drifting title must not spill over the casing */
}

.hero__intro {
    position: relative;
    z-index: 1;
    padding: 64px 44px 0;
    display: flex;
    flex-direction: column;
    align-items: center;
}

/* Two stacked copies: an ink outline underneath, the solid fill on top (built by hero.js) */
.hero__title {
    position: relative;
    margin: 0 0 56px;
    text-align: center;
    font-family: var(--font-deco);
    font-weight: 600;
    font-size: 128px;
    line-height: 0.9;
    letter-spacing: 0.005em;
    text-transform: uppercase;
}
.hero__line { display: block; white-space: nowrap; }

.hero__and {
    font-family: var(--font-serif-italic);
    font-style: italic;
    font-weight: 400;
    text-transform: none;
    font-size: 0.82em;
    letter-spacing: -0.01em;
    margin-right: 0.06em;
}

.hero__title-outline { color: transparent; -webkit-text-stroke: 1.5px var(--ink); }
.hero__title-fill { position: absolute; inset: 0; color: var(--ink); }
/* accent words: coloured fill inside the ink outline, like an offset-printed poster */
.hero__title-fill .hero__accent--teal { color: var(--accent-teal); }
.hero__title-fill .hero__accent--orange { color: var(--accent-orange); }

/* .hero__char wraps the scroll fade (departure); its inner span carries the load reveal */
.hero__char { display: inline-block; }
.hero__char > span { display: inline-block; }

.hero__tags {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    row-gap: 6px;
}
.hero__tags li {
    padding: 0 22px;
    font-family: var(--font-header);
    font-weight: 500;
    font-size: 14px;
    line-height: 1;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    white-space: nowrap;
}
.hero__tags li + li { border-left: 1.5px solid var(--ink); }

.hero__bio {
    /* visually hidden: the typed copy in the paint window is decorative */
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

/* --------------------------------------- PINNED STAGE ----------------------------------- */
/* The casing is scaled with a transform, and a sticky element inside a scaled box creeps by
   (scale − 1) × scroll, which a scroll handler can only chase a frame late (jitter).
   .hero__unscale applies the inverse scale, so everything inside it is laid out in true
   screen px and the browser's own sticky pins it exactly. hero.js sets --hero-s (the casing
   scale), --hero-vh (screen height in px) and the stage's top offset. */

.hero__track {
    position: relative;
    z-index: 2;
    height: calc(var(--hero-vh) * 2.5);
}

.hero__stage {
    position: sticky;
    top: 0;
    height: var(--hero-vh);
    display: grid;
    place-items: center;
}

@media (min-width: 901px) {
    .hero__unscale {
        width: calc(100% * var(--hero-s, 1));
        margin-left: calc(50% * (1 - var(--hero-s, 1)));
        /* the box reserves layout height × scale on screen; shed the excess */
        margin-bottom: calc(var(--hero-vh) * 2.5 * (1 / var(--hero-s, 1) - 1));
        transform: scale(calc(1 / var(--hero-s, 1)));
        transform-origin: top center;
    }
}

/* --------------------------------------- PAINT WINDOW ----------------------------------- */

.paint {
    position: relative;
    margin: 0;
    width: min(calc(620px * var(--hero-s, 1)), calc((var(--hero-vh) - 56px) * 0.6704));
    aspect-ratio: 1027 / 1532;
    container-type: inline-size;
    /* hard offset shadow, same as the site's cards */
    filter: drop-shadow(10px 10px 0 rgba(0,0,0,0.12));
}

.paint__img {
    display: block;
    width: 100%;
    height: 100%;
    user-select: none;
    -webkit-user-drag: none;
}

/* "A" text tool pressed state (sits over the toolbar cell) */
.paint__tool {
    position: absolute;
    left: 11.2%;
    top: 32.4%;
    width: 7.4%;
    height: 4.9%;
    border: 0.45cqw solid #000;
    box-shadow: inset 0.5cqw 0.5cqw 0 rgba(0,0,0,0.35);
    background: rgba(0,0,0,0.06);
    opacity: 0;
}
.paint.is-tool .paint__tool { opacity: 1; }

/* Status bar overlay */
.paint__status {
    position: absolute;
    left: 3.6%;
    top: 92.6%;
    width: 85.5%;
    height: 3.9%;
    display: flex;
    align-items: center;
    padding-left: 0.9%;
    background: var(--paint-paper);
    font-family: var(--font-pixel);
    font-size: 3.7cqw;
    line-height: 1;
    white-space: nowrap;
    overflow: hidden;
    color: #000;
}

/* The text box: a dashed rubber band while dragging, then it grows a line at a time */
.paint__box {
    position: absolute;
    left: 24.6%;
    top: 36.6%;
    width: calc(var(--box-w, 0) * 68.4%);
    height: calc(var(--box-h, 0) * 7.2cqw);
    outline: 0.3cqw dashed #000;
    opacity: 0;
}
.paint.is-drawing .paint__box { opacity: 1; }
.paint.is-typing .paint__box {
    width: 68.4%;
    height: auto;
    min-height: 7.2cqw;
    background: var(--paint-paper);
}

.paint__handle {
    position: absolute;
    width: 1.3cqw;
    height: 1.3cqw;
    left: calc(var(--hx) * 100%);
    top: calc(var(--hy) * 100%);
    transform: translate(-50%, -50%);
    background: var(--paint-paper);
    border: 0.3cqw solid #000;
    opacity: 0;
}
.paint.is-typing .paint__handle { opacity: 1; }

.paint__text {
    margin: 0;
    padding: 1.4cqw 2.2cqw 1.6cqw;
    font-family: var(--font-pixel);
    font-size: 3.55cqw;
    line-height: 1.04;
    letter-spacing: 0.01em;
    color: #000;
    text-align: left;
    display: none;
}
.paint.is-typing .paint__text { display: block; }

.paint__caret {
    display: inline-block;
    width: 0.5em;
    height: 0.95em;
    margin-right: -0.5em;
    vertical-align: -0.12em;
    background: #000;
    animation: paint-caret 1s steps(1) infinite;
}
.paint.is-scrubbing .paint__caret { animation: none; }
@keyframes paint-caret { 50% { opacity: 0; } }

.paint__cursor {
    position: absolute;
    left: 0;
    top: 0;
    width: 2.6cqw;
    height: auto;
    overflow: visible;
    pointer-events: none;
    opacity: 0;
    transform: translate(calc(var(--cx, 60) * 1cqw), calc(var(--cy, 50) * 1cqw)) scale(var(--cs, 1));
    transform-origin: 0 0;
    transition: opacity 0.2s ease;
}
.paint.is-pointing .paint__cursor { opacity: 1; }

/* --------------------------------------- INTRO REVEAL ----------------------------------- */
/* Initial states only exist with JS (html.js); hero.js adds .hero-in when the loader leaves.
   Letters fade in one by one, outline first with the fill trailing behind it. */

html.js .hero__title-outline .hero__char > span,
html.js .hero__title-fill .hero__char > span { opacity: 0; transform: translateY(0.06em); }
html.js .hero__tags li { opacity: 0; transform: translateY(10px); }
html.js .hero__stage .paint { clip-path: inset(50% 50% 50% 50%); }
html.js .hero__stage .paint__img { transform: scale(0.86); }

html.js.hero-in .hero__char > span {
    opacity: 1;
    transform: none;
    transition: opacity 0.7s ease, transform 0.9s var(--ease-out-expo);
    transition-delay: calc(0.1s + var(--i, 0) * 0.035s);
}
html.js.hero-in .hero__title-fill .hero__char > span {
    transition-delay: calc(0.45s + var(--i, 0) * 0.035s);
}
html.js.hero-in .hero__tags li {
    opacity: 1; transform: none;
    transition: opacity 0.6s ease, transform 0.9s var(--ease-out-expo);
    transition-delay: calc(1.05s + var(--i, 0) * 0.07s);
}
/* the paint window opens out of nothing while the artwork zooms in to size */
html.js.hero-in .hero__stage .paint {
    clip-path: inset(0 -24px -24px 0);
    transition: clip-path 1.4s var(--ease-out-expo) 1.2s;
}
html.js.hero-in .hero__stage .paint__img {
    transform: none;
    transition: transform 1.8s var(--ease-out-expo) 1.2s;
}

/* --------------------------------------- SCROLL DEPARTURE ----------------------------------- */
/* The title block leaves faster than the page scrolls (and fades, its fill draining letter by
   letter), so the rising paint window never reaches it. Compositor-driven where supported;
   hero.js drives the same motion from the scroll handler otherwise. */

@supports (animation-timeline: scroll()) {
    .hero__intro {
        animation: hero-intro-depart linear both;
        animation-timeline: scroll(root);
        animation-range: 0px var(--depart-end, 700px);
    }
    .hero__title-fill .hero__char {
        animation: hero-char-drain linear both;
        animation-timeline: scroll(root);
        animation-range:
            calc(var(--i, 0) * var(--drain-step, 8px))
            calc(var(--drain-len, 120px) + var(--i, 0) * var(--drain-step, 8px));
    }
}
@keyframes hero-intro-depart {
    0%   { transform: translate3d(0, 0, 0); opacity: 1; }
    25%  { opacity: 1; }
    85%  { opacity: 0; }
    100% { transform: translate3d(0, var(--depart-y, -500px), 0); opacity: 0; }
}
@keyframes hero-char-drain {
    to { opacity: 0; }
}

/* --------------------------------------- PHONES ----------------------------------- */
/* The 1000px casing is scaled down (--ui-scale), so small UI text is sized in on-screen px
   (divided by the scale). No pin here: the window scrolls in flow and plays as it passes. */

@media (max-width: 900px) {
    .hero__intro { padding: calc(36px / var(--ui-scale, 1)) 36px 0; }

    .hero__title {
        font-size: calc(clamp(30px, 8.6vw, 72px) / var(--ui-scale, 1));
        margin-bottom: calc(26px / var(--ui-scale, 1));
    }
    .hero__title-outline { -webkit-text-stroke-width: calc(1px / var(--ui-scale, 1)); }

    .hero__tags { row-gap: calc(8px / var(--ui-scale, 1)); }
    .hero__tags li {
        font-size: calc(10px / var(--ui-scale, 1));
        padding: 0 calc(9px / var(--ui-scale, 1));
    }
    .hero__tags li + li { border-left-width: calc(1px / var(--ui-scale, 1)); }

    .hero__track { height: auto; }
    .hero__stage {
        position: relative;
        height: auto;
        display: block;
        padding: calc(28px / var(--ui-scale, 1)) 36px calc(36px / var(--ui-scale, 1));
    }
    .paint { width: 100%; filter: none; }
}

/* --------------------------------------- HOME SCROLL REVEALS ----------------------------------- */
/* Navigation dial + communication module. hero.js adds .is-revealing once a section is in view.
   Individual translate / scale / rotate properties are used so the existing transforms
   (dial centring, window orbits, button presses) are left alone. The reveal transitions
   only live on .is-revealing, which hero.js removes afterwards so hover/press styles return. */

html.js [data-reveal] { --reveal-ease: var(--ease-out-expo); }

/* Navigation station */
html.js [data-reveal="nav"]:not(.is-revealed) { opacity: 0; translate: 0 60px; }
html.js [data-reveal="nav"]:not(.is-revealed) .nav-dial { translate: 0 22%; }
html.js [data-reveal="nav"]:not(.is-revealed) .nav-window__frame { opacity: 0; scale: 0.4; }
html.js [data-reveal="nav"]:not(.is-revealed) .nav-dial__arcText { opacity: 0; }

html.js [data-reveal="nav"].is-revealing {
    opacity: 1; translate: 0 0;
    transition: opacity 0.7s ease, translate 1.1s var(--reveal-ease);
}
html.js [data-reveal="nav"].is-revealing .nav-dial {
    translate: 0 0;
    transition: translate 1.4s var(--reveal-ease) 0.15s;
}
html.js [data-reveal="nav"].is-revealing .nav-window__frame {
    opacity: 1; scale: 1;
    transition: opacity 0.5s ease, scale 0.9s cubic-bezier(0.34, 1.56, 0.64, 1);
}
html.js [data-reveal="nav"].is-revealing .nav-window--left .nav-window__frame   { transition-delay: 0.45s; }
html.js [data-reveal="nav"].is-revealing .nav-window--center .nav-window__frame { transition-delay: 0.55s; }
html.js [data-reveal="nav"].is-revealing .nav-window--right .nav-window__frame  { transition-delay: 0.65s; }
html.js [data-reveal="nav"].is-revealing .nav-dial__arcText {
    opacity: 1;
    transition: opacity 0.8s ease 0.6s;
}

/* Communication module */
html.js [data-reveal="contact"]:not(.is-revealed) .contact-plate { opacity: 0; translate: 0 -40px; }
html.js [data-reveal="contact"]:not(.is-revealed) .contact-mainplate { opacity: 0; translate: 0 60px; }
html.js [data-reveal="contact"]:not(.is-revealed) .contact-field { opacity: 0; translate: -24px 0; }
html.js [data-reveal="contact"]:not(.is-revealed) .social-btn { opacity: 0; scale: 0.3; }
html.js [data-reveal="contact"]:not(.is-revealed) .tx-btn { opacity: 0; scale: 0.5; rotate: -120deg; }
html.js [data-reveal="contact"]:not(.is-revealed) .tx-label { opacity: 0; translate: 0 10px; }

html.js [data-reveal="contact"].is-revealing .contact-plate {
    opacity: 1; translate: 0 0;
    transition: opacity 0.6s ease 0.25s, translate 1s var(--reveal-ease) 0.25s;
}
html.js [data-reveal="contact"].is-revealing .contact-mainplate {
    opacity: 1; translate: 0 0;
    transition: opacity 0.6s ease, translate 1.1s var(--reveal-ease);
}
html.js [data-reveal="contact"].is-revealing .contact-field {
    opacity: 1; translate: 0 0;
    transition: opacity 0.6s ease, translate 0.9s var(--reveal-ease);
}
html.js [data-reveal="contact"].is-revealing .contact-field:nth-child(1) { transition-delay: 0.45s; }
html.js [data-reveal="contact"].is-revealing .contact-field:nth-child(2) { transition-delay: 0.55s; }
html.js [data-reveal="contact"].is-revealing .contact-field:nth-child(3) { transition-delay: 0.65s; }
html.js [data-reveal="contact"].is-revealing .social-btn {
    opacity: 1; scale: 1;
    transition: opacity 0.4s ease, scale 0.7s cubic-bezier(0.34, 1.56, 0.64, 1);
}
html.js [data-reveal="contact"].is-revealing .social-btn:nth-child(1) { transition-delay: 0.6s; }
html.js [data-reveal="contact"].is-revealing .social-btn:nth-child(2) { transition-delay: 0.68s; }
html.js [data-reveal="contact"].is-revealing .social-btn:nth-child(3) { transition-delay: 0.76s; }
html.js [data-reveal="contact"].is-revealing .tx-btn {
    opacity: 1; scale: 1; rotate: 0deg;
    transition: opacity 0.5s ease 0.8s, scale 1s cubic-bezier(0.34, 1.56, 0.64, 1) 0.8s, rotate 1.2s var(--reveal-ease) 0.8s;
}
html.js [data-reveal="contact"].is-revealing .tx-label {
    opacity: 1; translate: 0 0;
    transition: opacity 0.6s ease 1s, translate 0.8s var(--reveal-ease) 1s;
}

/* --------------------------------------- REDUCED MOTION ----------------------------------- */

@media (prefers-reduced-motion: reduce) {
    .hero__track { height: auto; }
    .hero__stage { position: relative; height: auto; padding-block: 40px; }
    .hero__unscale { transform: none; width: auto; margin: 0; }
    .hero__intro, .hero__title-fill .hero__char { animation: none; }
    .paint__caret { animation: none; }
    html.js .hero *, html.js .hero *::before { transition: none !important; }
    html.js [data-reveal], html.js [data-reveal] * { transition: none !important; }
}
