/* Timeline: pause → draw outer lines → draw inner circle → dock → show text + start marquee */
:root {
    --draw-delay: 300ms;
    --lines-duration: 700ms;
    --circle-duration: 400ms;
    --dock-duration: 500ms;
    --fade-duration: 250ms;
    --draw-ease: ease-in-out;
    --circle-overlap: 150ms; /* circle starts while the outer lines finish */

    --circle-start: calc(var(--draw-delay) + var(--lines-duration) - var(--circle-overlap)); /* 850ms */
    --dock-start: calc(var(--circle-start) + var(--circle-duration));      /* 1250ms */
    --reveal-start: calc(var(--dock-start) + var(--dock-duration));        /* 1750ms */

    /* Where the full logo ends up */
    --logo-width: 63.2px; /* keeps "301" at its original size */
    --logo-height: calc(var(--logo-width) * 133 / 184.6);
    --logo-offset: 24px;

    --accent: #F7A8C8;
    --footnote-over-marquee: var(--accent);
    --font: "Inter", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
}

body {
    margin: 0;
    min-height: 100vh;
    background: #fff;
    overflow: hidden;
}

/* Two identical copies; sliding the track up by -50% lines copy two up exactly where copy one started, so the loop is seamless. */
.marquee {
    position: fixed;
    inset: 0;
    display: flex;
    justify-content: flex-end;
    align-items: flex-start;
    overflow: hidden;
    /* the gradient below blends against this, so the text needs an opaque white backdrop */
    background: #fff;
    opacity: 0;
    animation: logo-fade-in var(--fade-duration) ease-out var(--reveal-start) forwards;
}

.marquee-track {
    display: flex;
    flex-shrink: 0;
    /* text turned 90° clockwise, reading top to bottom; the flex row now runs vertically too */
    writing-mode: vertical-rl;
    white-space: nowrap;
    /* the text runs vertically, so font size sets the strip's width */
    font: 900 50vw/1 var(--font);
    animation: marquee 20s linear var(--reveal-start) infinite;
}

.marquee-track span {
    padding-inline-end: 0.25em;
}

/*
 * Drifting colour blobs laid over the text. Lighten keeps the white page white and
 * swaps the black text for whatever colour is underneath, so the text acts as a mask.
 */
.marquee-gradient {
    position: absolute;
    inset: 0;
    pointer-events: none;
    mix-blend-mode: lighten;
    background-color: var(--accent);
    background-image:
        radial-gradient(closest-side, #FF5A1F, transparent),
        radial-gradient(closest-side, #6B3CFF, transparent),
        radial-gradient(closest-side, #FFC83D, transparent);
    background-size: 90vw 80vh, 80vw 90vh, 70vw 70vh;
    background-repeat: no-repeat;
    animation:
        gradient-drift 16s ease-in-out infinite alternate,
        gradient-hue 24s linear infinite;
}

/*
 * The whole full logo (184.6×133 viewBox) is one element. It starts large with the
 * mark centred in the viewport, then shrinks into the top-left corner.
 * The mark's centre sits at (38.6, 94.2) in viewBox units, i.e. 20.91% / 51.03%
 * of the logo's width, which is what the start position is computed from.
 */
.logo {
    --start-width: 190px; /* mark ≈ 78px */

    position: fixed;
    z-index: 1;
    left: var(--logo-offset);
    top: var(--logo-offset);
    width: var(--logo-width);
    aspect-ratio: 184.6 / 133;
    opacity: 0;
    animation:
        logo-fade-in var(--fade-duration) forwards,
        logo-dock var(--dock-duration) ease-in-out var(--dock-start) backwards;
}

.logo-mark {
    fill: none;
    stroke: currentColor;
    stroke-width: 3;
    stroke-miterlimit: 10;
}

/*
 * Each path is drawn from its start point: the three outer lines start at their
 * outer ends and run counterclockwise, the inner circle starts left and runs clockwise.
 */
.logo-line,
.logo-circle {
    stroke-dasharray: 1.02;
    stroke-dashoffset: 1.02;
}

.logo-line {
    animation: logo-draw var(--lines-duration) var(--draw-ease) var(--draw-delay) forwards;
}

.logo-circle {
    animation: logo-draw var(--circle-duration) var(--draw-ease) var(--circle-start) forwards;
}

.logo-text {
    opacity: 0;
    animation: logo-fade-in var(--fade-duration) ease-out var(--reveal-start) forwards;
}

/* Sits right of the docked logo, bottom-aligned with the "301" baseline */
.tagline {
    position: fixed;
    z-index: 1;
    left: calc(var(--logo-offset) + var(--logo-width) + 8px);
    top: var(--logo-offset);
    height: var(--logo-height);
    margin: 0;
    display: flex;
    align-items: flex-end;
    font: 600 12px/1 var(--font);
    opacity: 0;
    animation: logo-fade-in var(--fade-duration) ease-out var(--reveal-start) forwards;
}

/*
 * The footnote's children are fixed individually: a fixed parent would form its own
 * stacking context and the text could only blend with that, not with the marquee.
 * White + difference renders black on the white page and white over the marquee.
 */
.footnote > * {
    position: fixed;
    z-index: 1;
    left: var(--logo-offset);
    margin: 0;
    opacity: 0;
    animation: logo-fade-in var(--fade-duration) ease-out var(--reveal-start) forwards;
}

.footnote p {
    bottom: var(--logo-offset);
    font: 600 12px/1 var(--font);
    color: #fff;
    mix-blend-mode: difference;
}

/* Duplicate on top: multiply leaves the black text black and tints the white (over-marquee) text */
.footnote .footnote-tint {
    color: var(--footnote-over-marquee);
    mix-blend-mode: multiply;
}

.email {
    /* sits 8px above the 12px footnote line */
    bottom: calc(var(--logo-offset) + 12px + 8px);
    display: flex;
    color: var(--accent);
}

.email svg {
    width: 14px;
    height: 14px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: square;
    stroke-linejoin: miter;
}

/* on the svg: the link's own opacity is held by its fade-in animation */
.email:hover svg,
.email:focus-visible svg {
    opacity: 0.7;
}

@keyframes logo-fade-in {
    to { opacity: 1; }
}

@keyframes logo-dock {
    from {
        width: var(--start-width);
        left: calc(50vw - var(--start-width) * 0.2091);
        top: calc(50vh - var(--start-width) * 0.5103);
    }
}

@keyframes logo-draw {
    to { stroke-dashoffset: 0; }
}

@keyframes gradient-drift {
    0%   { background-position: 0% 0%, 100% 20%, 30% 100%; }
    50%  { background-position: 100% 40%, 0% 100%, 80% 0%; }
    100% { background-position: 40% 100%, 70% 0%, 0% 50%; }
}

@keyframes gradient-hue {
    to { filter: hue-rotate(360deg); }
}

@keyframes marquee {
    to { transform: translateY(-50%); }
}

@media (prefers-reduced-motion: reduce) {
    .logo,
    .logo-text,
    .tagline,
    .footnote > *,
    .marquee {
        animation: none;
        opacity: 1;
    }

    .marquee-track,
    .marquee-gradient,
    .logo-line,
    .logo-circle {
        animation: none;
    }

    .logo-line,
    .logo-circle {
        stroke-dashoffset: 0;
    }
}
