/* Chart section: the bubbles and the dial share one grid cell. */

section.chart, section.dial-wrapper {
    display: grid;
    grid-template: minmax(0, 1fr) / minmax(0, 1fr);
    place-items: center;
    height: 100svh;
    width: 100%;
    position: fixed;

    > * {
        grid-area: 1 / 1;
    }
}

section.dial-wrapper {
    z-index: 3;
    pointer-events: none;
}

.dial-title {
    position: fixed;
    top: 0;
    left: 0;
    margin: 1.5rem 0 0 1.5rem;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity 200ms ease;

    &.is-visible {
        opacity: 1;
    }
}

.close {
    font: inherit;
    background: none;
    border: 0;
    cursor: pointer;
    font-size: 1.25rem;
}

section.chart {
    z-index: 1;
}

section.pop-up-wrapper {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100svh;
    z-index: 5;
    pointer-events: none;
    display: grid;
    place-items: center;
    padding: 1rem;

    section.pop-up {
        width: 100%;
        max-width: 30rem;
        height: auto;
        background-color: var(--white-background);
        border: var(--border);
        border-radius: 1rem;
        padding: 1rem;
        display: grid;
        gap: 1rem;
        pointer-events: all;
        backdrop-filter: blur(20px);

        /* display: grid would otherwise override the hidden attribute */
        &[hidden] {
            display: none;
        }
    }
}


/* Bubble graphic */

section.chart .bubbles {
    position: relative;
    width: 100%;
    height: 100%;
    min-height: 0;
    isolation: isolate;
    pointer-events: all;
    animation: bubbles-in 2000ms ease both;

    .bubble-circle {
        position: absolute;
        top: 0;
        left: 0;
        will-change: transform;
        border-radius: 50%;
        mix-blend-mode: multiply;
        cursor: grab;
        touch-action: none;
        pointer-events: none;
        display: grid;
        place-content: center;
        text-align: center;
        transition: opacity 0.25s;

        &::before {
            content: "";
            position: absolute;
            inset: 0;
            z-index: -1;
            border-radius: inherit;
            background: radial-gradient(closest-side, var(--color) 5%, transparent 100%);
            filter: blur(30px);
            transition: opacity 600ms ease;
            opacity: 1;
        }

        /* The core: the circle the layout keeps apart from its neighbours,
           r × (1 − overlap), so set --hit-inset (bubbles controller) to
           overlap / 2 of the diameter. Pointer events on it count as the bubble's. */
        &::after {
            content: "";
            position: absolute;
            inset: var(--hit-inset, 20%);
            border-radius: 50%;
            pointer-events: auto;
        }

        /* Lift the bubble being aimed at, dragged or selected above its neighbours. */
        &:hover,
        &.is-dragging,
        &.is-selected {
            z-index: 1;
        }

        &.is-dragging {
            cursor: grabbing;
        }

        &.is-muted::before {
            opacity: 0;
        }
    }

    @media (prefers-reduced-motion: reduce) {
        animation: none;
        .bubble-circle,
        .bubble-circle::before { transition: none; }
    }
}


/* The dial nodes' gradient stops, set by the dial controller when a category
   is selected. Registered as colours so they can be transitioned. Opaque here;
   the node's background draws them at 50%. */
@property --node-c1 { syntax: "<color>"; inherits: false; initial-value: white; }
@property --node-c2 { syntax: "<color>"; inherits: false; initial-value: white; }
@property --node-c3 { syntax: "<color>"; inherits: false; initial-value: white; }

.dial {
    --ring-radius: min(40svh, 40vw);
    --step: calc(360deg / var(--count, 1));
    --offset: -90deg;
    display: grid;
    place-items: center;
    pointer-events: none;

    .dial-node {
        color: inherit;
        text-decoration: none;
        font-variant-numeric: lining-nums;
        animation: dial-node-in 800ms cubic-bezier(0.22, 1, 0.36, 1) both;
        animation-delay: calc(var(--i, 0) * 80ms);
        display: grid;
        cursor: pointer;
        place-items: center;
        width: 5rem;
        height: 5rem;
        border-radius: 50%;
        background: linear-gradient(135deg,
        color-mix(in srgb, var(--node-c1) 50%, transparent),
        color-mix(in srgb, var(--node-c2) 50%, transparent),
        color-mix(in srgb, var(--node-c3) 50%, transparent));
        border: 1px solid rgba(255, 255, 255, 0.75);
        text-align: center;
        backdrop-filter: blur(2px);
        grid-area: 1 / 1;
        pointer-events: auto;
        --angle: calc(var(--offset) + var(--i) * var(--step));
        --tilt-depth: 200px;
        position: relative;
        transform: rotate(var(--angle))
        translate(var(--ring-radius))
        rotate(calc(-1 * var(--angle)))
        perspective(var(--tilt-depth))
        rotateX(var(--tilt-x, 0deg))
        rotateY(var(--tilt-y, 0deg))
        translateZ(var(--tilt-lift, 0px));
        box-shadow: 0 0 0 rgb(0 0 0 / 0);
        transition: box-shadow 500ms cubic-bezier(0.22, 1, 0.36, 1),
        --node-c1 500ms, --node-c2 500ms, --node-c3 500ms;

        @media (width <= 500px)  {
            width: 12vw;
            height: 12vw;
        }

        &::after {
            content: "";
            position: absolute;
            inset: 0;
            border-radius: inherit;
            pointer-events: none;
            opacity: 0;
            transition: opacity 500ms ease;
            background: radial-gradient(circle at var(--pointer-x, 50%) var(--pointer-y, 50%),
            rgb(255 255 255 / 0.55),
            rgb(255 255 255 / 0) 65%);
        }

        /* Keep the number above the highlight. */
        > * {
            position: relative;
            z-index: 1;
        }

        /* The project's first image, faded in on hover; under the highlight
           and number (it comes before the highlight, so paints beneath it). */
        .dial-node-image {
            position: absolute;
            inset: 0;
            z-index: 0;
            width: 100%;
            height: 100%;
            object-fit: cover;
            border-radius: inherit;
            pointer-events: none;
            opacity: 0;
            transition: opacity 400ms ease;
        }

        &:is(:hover, :focus-visible) .dial-node-image {
            opacity: 0.5;
        }

        /* While tracking the pointer the transform is redriven every frame, so
           it wants to keep up; the slow easing above is for settling back. */
        &.is-tilting {
            --tilt-lift: 14px;
            transition: transform 100ms linear, box-shadow 100ms linear;
            box-shadow: calc(var(--tilt-nx, 0) * -26px)
            calc(var(--tilt-ny, 0) * -26px)
            26px rgb(0 0 0 / 0.1);

            &::after {
                opacity: 1;
                transition: opacity 150ms ease;
            }
        }

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