/* ==========================================================================
   The modelling viewports: canvas, poster fallback, and the program's chrome around them — corner
   brackets, the view read-out, the orientation gizmo, the shading and tool bars, the shape shelf, the
   modifier stack and the scene statistics. The chrome is HTML over the canvas so it stays crisp,
   selectable where it should be, and accessible where it is a control.
   ========================================================================== */

.viewport {
    position: relative;
    isolation: isolate;
}

.viewport__canvas {
    position: absolute;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
    opacity: 0;
    cursor: grab;
    /* Vertical swipes still scroll the page; sideways drags turn the model. */
    touch-action: pan-y;
    transition: opacity 900ms var(--ease-out);
}

.viewport[data-state="ready"] .viewport__canvas {
    opacity: 1;
}

.viewport__canvas[data-dragging="true"] {
    cursor: grabbing;
}

.viewport[data-tool="sculpt"] .viewport__canvas,
.viewport__canvas[data-tool="sculpt"] {
    cursor: none;
    touch-action: none;
}

/* Without WebGL: a still render in the same place. */
.viewport__poster {
    position: absolute;
    inset: 12%;
    inline-size: 76%;
    block-size: 76%;
    object-fit: contain;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur-4) var(--ease-out);
    -webkit-mask: radial-gradient(closest-side, #000 70%, transparent);
    mask: radial-gradient(closest-side, #000 70%, transparent);
}

.viewport[data-state="fallback"] .viewport__poster {
    opacity: 0.9;
}

.viewport[data-state="fallback"] .vp-bar,
.viewport[data-state="fallback"] .vp-shapes,
.viewport[data-state="fallback"] .vp-gizmo,
.viewport[data-state="fallback"] .vp-hint,
.viewport[data-state="fallback"] .vp-hud--stats {
    display: none;
}

/* The stage is the region the model is centred in; the chrome is laid out around its edges. */
.viewport__stage {
    position: absolute;
    pointer-events: none;
}

.viewport__stage > * {
    pointer-events: auto;
}

.viewport__stage > [aria-hidden="true"] {
    pointer-events: none;
}

/* ---------------------------------------------------------------- brackets */
.viewport__bracket {
    position: absolute;
    inline-size: 22px;
    block-size: 22px;
    border-color: rgb(255 255 255 / 0.22);
    border-style: solid;
    border-width: 0;
}

.viewport__bracket--tl { inset-block-start: 0; inset-inline-start: 0; border-block-start-width: 1.5px; border-inline-start-width: 1.5px; }
.viewport__bracket--tr { inset-block-start: 0; inset-inline-end: 0; border-block-start-width: 1.5px; border-inline-end-width: 1.5px; }
.viewport__bracket--bl { inset-block-end: 0; inset-inline-start: 0; border-block-end-width: 1.5px; border-inline-start-width: 1.5px; }
.viewport__bracket--br { inset-block-end: 0; inset-inline-end: 0; border-block-end-width: 1.5px; border-inline-end-width: 1.5px; }

/* ---------------------------------------------------------------- read-outs */
.vp-hud {
    position: absolute;
    font-family: var(--font-mono);
    font-size: 0.7rem;
    letter-spacing: 0.04em;
    color: var(--text-soft);
    line-height: 1.55;
}

.vp-hud b {
    color: var(--text-mute);
    font-weight: 400;
}

.vp-hud--view {
    inset-block-start: 14px;
    inset-inline-start: 64px;
    display: grid;
}

.vp-hud__title {
    color: var(--text-strong);
}

.vp-hud__line span {
    color: #ffae5c;
}

.vp-hud--stats {
    inset-block-start: 58px;
    inset-inline-start: 64px;
    display: grid;
    gap: 0;
}

.vp-hud--stats span {
    display: flex;
    justify-content: space-between;
    gap: 1.2rem;
    min-inline-size: 9.5rem;
}

.vp-hud--stats b {
    color: var(--text-strong);
    font-variant-numeric: tabular-nums;
}

.vp-hint {
    position: absolute;
    inset-block-end: 74px;
    inset-inline: 0;
    margin-inline: auto;
    inline-size: max-content;
    max-inline-size: 90%;
    padding: 0.32rem 0.7rem;
    border-radius: var(--radius-pill);
    background: rgb(10 10 15 / 0.6);
    border: 1px solid var(--line);
    font-size: 0.68rem;
    letter-spacing: 0.06em;
    color: var(--text-soft);
    text-align: center;
    opacity: 0;
    transition: opacity var(--dur-3);
}

.viewport:hover .vp-hint,
.viewport[data-tool="sculpt"] .vp-hint {
    opacity: 1;
}

/* ---------------------------------------------------------------- gizmo */
.vp-gizmo {
    position: absolute;
    inset-block-start: 58px;
    inset-inline-end: 12px;
    inline-size: 84px;
    block-size: 84px;
    overflow: visible;
}

.vp-gizmo__ring {
    fill: rgb(255 255 255 / 0.03);
    stroke: rgb(255 255 255 / 0.06);
}

.vp-gizmo__axis {
    stroke-width: 2.4;
    stroke-linecap: round;
}

.vp-gizmo__axis--x { stroke: var(--axis-x); }
.vp-gizmo__axis--y { stroke: var(--axis-y); }
.vp-gizmo__axis--z { stroke: var(--axis-z); }

.vp-gizmo__cap circle { stroke: none; }
.vp-gizmo__cap--x circle { fill: var(--axis-x); }
.vp-gizmo__cap--y circle { fill: var(--axis-y); }
.vp-gizmo__cap--z circle { fill: var(--axis-z); }

.vp-gizmo__cap text {
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 700;
    text-anchor: middle;
    fill: #101014;
}

/* ---------------------------------------------------------------- bars and buttons */
.vp-bar {
    position: absolute;
    display: flex;
    gap: 3px;
    padding: 4px;
    border-radius: 12px;
    background: rgb(18 18 27 / 0.74);
    border: 1px solid var(--line);
    box-shadow: 0 12px 30px -16px rgb(0 0 0 / 0.8);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}

.vp-bar--shading {
    inset-block-start: 10px;
    inset-inline-end: 10px;
}

.vp-bar--tools {
    inset-block-start: 10px;
    inset-inline-start: 10px;
    flex-direction: column;
}

.vp-bar__sep {
    block-size: 1px;
    margin: 3px 6px;
    background: var(--line-strong);
}

.vp-button {
    position: relative;
    display: inline-grid;
    place-items: center;
    inline-size: 38px;
    block-size: 38px;
    border-radius: 9px;
    color: var(--text-soft);
    transition: background var(--dur-2), color var(--dur-2), box-shadow var(--dur-2);
}

.vp-button svg {
    inline-size: 20px;
    block-size: 20px;
}

.vp-button:hover {
    color: var(--text-strong);
    background: rgb(255 255 255 / 0.06);
}

.vp-button[aria-pressed="true"] {
    color: var(--text-strong);
    background: var(--violet-600);
    box-shadow: 0 0 0 1px var(--violet-400) inset, 0 6px 18px -6px var(--violet-glow);
}

.vp-button .vp-button__off { display: none; }
.vp-button[aria-pressed="false"] .vp-button__on { display: none; }
.vp-button[aria-pressed="false"] .vp-button__off { display: block; }

/* Tooltips for the icon-only controls, on hover-capable pointers. */
@media (hover: hover) {
    .vp-button::after {
        content: attr(title);
        position: absolute;
        inset-block-start: 50%;
        inset-inline-start: calc(100% + 8px);
        padding: 0.28rem 0.5rem;
        border-radius: 6px;
        background: rgb(10 10 15 / 0.92);
        border: 1px solid var(--line);
        font-family: var(--font-mono);
        font-size: 0.66rem;
        letter-spacing: 0.04em;
        white-space: nowrap;
        color: var(--text-strong);
        opacity: 0;
        transform: translate(-4px, -50%);
        pointer-events: none;
        transition: opacity var(--dur-2), transform var(--dur-2) var(--ease-out);
    }

    .vp-bar--shading .vp-button::after {
        inset-block-start: calc(100% + 8px);
        inset-inline-start: 50%;
        transform: translate(-50%, -4px);
    }

    .vp-button:hover::after {
        opacity: 1;
        transform: translate(0, -50%);
    }

    .vp-bar--shading .vp-button:hover::after {
        transform: translate(-50%, 0);
    }
}

/* ---------------------------------------------------------------- shape shelf */
.vp-shapes {
    position: absolute;
    inset-block-end: 12px;
    inset-inline: 0;
    margin-inline: auto;
    display: flex;
    gap: 4px;
    inline-size: max-content;
    max-inline-size: calc(100% - 20px);
    padding: 4px;
    border-radius: var(--radius-pill);
    background: rgb(18 18 27 / 0.74);
    border: 1px solid var(--line);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    overflow-x: auto;
    scrollbar-width: none;
}

.vp-shapes::-webkit-scrollbar {
    display: none;
}

.vp-chip {
    flex: none;
    min-block-size: 34px;
    padding: 0.35rem 0.85rem;
    border-radius: var(--radius-pill);
    font-family: var(--font-mono);
    font-size: 0.72rem;
    letter-spacing: 0.04em;
    color: var(--text-soft);
    transition: background var(--dur-2), color var(--dur-2);
}

.vp-chip:hover {
    color: var(--text-strong);
    background: rgb(255 255 255 / 0.06);
}

.vp-chip[aria-pressed="true"] {
    color: #0d1402;
    background: var(--lime-500);
    font-weight: 700;
}

/* ---------------------------------------------------------------- modifier stack */
.vp-stack {
    position: absolute;
    inset-block-end: 14px;
    inset-inline-end: 12px;
    display: grid;
    gap: 3px;
    font-family: var(--font-mono);
    font-size: 0.68rem;
    letter-spacing: 0.05em;
}

.vp-stack li {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.28rem 0.6rem;
    border-radius: 7px;
    color: var(--text-mute);
    border: 1px solid transparent;
    transition: color var(--dur-3), background var(--dur-3), border-color var(--dur-3);
}

.vp-stack li span {
    color: inherit;
    opacity: 0.6;
}

.vp-stack li[data-done="true"] {
    color: var(--text-soft);
}

.vp-stack li[data-active="true"] {
    color: var(--text-strong);
    background: var(--violet-glow-soft);
    border-color: var(--line-violet);
}

.vp-stack li[data-active="true"]::after {
    content: "";
    inline-size: 6px;
    block-size: 6px;
    margin-inline-start: auto;
    border-radius: 1px;
    background: var(--lime-500);
    box-shadow: 0 0 8px var(--lime-glow);
}

/* ---------------------------------------------------------------- brush ring */
.vp-brush {
    position: absolute;
    inset-block-start: 0;
    inset-inline-start: 0;
    border-radius: 50%;
    border: 1.5px solid rgb(200 255 77 / 0.85);
    box-shadow: 0 0 0 1px rgb(0 0 0 / 0.35), inset 0 0 18px rgb(200 255 77 / 0.18);
    opacity: 0;
    transition: opacity var(--dur-2);
}

.vp-brush::after {
    content: "";
    position: absolute;
    inset: 50% auto auto 50%;
    inline-size: 4px;
    block-size: 4px;
    margin: -2px 0 0 -2px;
    border-radius: 50%;
    background: var(--lime-500);
}

.vp-brush[data-visible="true"] {
    opacity: 1;
}

/* ---------------------------------------------------------------- process viewport extras */
.vp-dims span {
    position: absolute;
    inset-block-start: 0;
    inset-inline-start: 0;
    padding: 0.18rem 0.45rem;
    border-radius: 5px;
    background: rgb(200 255 77 / 0.14);
    border: 1px solid rgb(200 255 77 / 0.45);
    font-size: 0.68rem;
    color: var(--lime-400);
    white-space: nowrap;
}

.vp-dims {
    position: absolute;
    inset: 0;
    opacity: 0;
    transition: opacity var(--dur-3);
}

.viewport[data-stage="3"] .vp-dims {
    opacity: 1;
}

.vp-export {
    position: absolute;
    inset-block-end: 16px;
    inset-inline-end: 16px;
    display: grid;
    gap: 5px;
    font-size: 0.7rem;
    color: var(--text);
    opacity: 0;
    transform: translateY(10px);
    transition: opacity var(--dur-3), transform var(--dur-3) var(--ease-out);
}

.vp-export li {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.35rem 0.6rem;
    border-radius: 8px;
    background: rgb(18 18 27 / 0.8);
    border: 1px solid var(--line);
}

.vp-export svg {
    inline-size: 14px;
    block-size: 14px;
    color: var(--violet-300);
}

.vp-export .vp-export__ok {
    margin-inline-start: auto;
    color: var(--lime-500);
}

.viewport[data-stage="4"] .vp-export {
    opacity: 1;
    transform: none;
}

.viewport[data-stage="4"] .vp-export li:nth-child(2) { transition-delay: 90ms; }

/* A framed viewport: the process band's, a window into the program. */
.viewport--framed {
    border-radius: var(--radius-l);
    border: 1px solid var(--line-strong);
    background:
        radial-gradient(70% 60% at 50% 42%, rgb(124 92 255 / 0.18), transparent 70%),
        linear-gradient(180deg, #14141f, #0b0b11);
    box-shadow: var(--shadow-card), 0 0 0 1px rgb(0 0 0 / 0.5);
    overflow: hidden;
}

.viewport--framed .viewport__stage {
    inset: 0;
}

.viewport--framed .vp-hud--view {
    inset-inline-start: 16px;
}

.viewport--framed .vp-hud--stats {
    inset-inline-start: 16px;
}

@media (max-width: 900px) {
    .vp-hud--stats,
    .vp-stack,
    .vp-hint {
        display: none;
    }

    .vp-gizmo {
        inset-block-start: auto;
        inset-block-end: 60px;
        inset-inline-end: 8px;
        inline-size: 64px;
        block-size: 64px;
    }

    .vp-button {
        inline-size: 40px;
        block-size: 40px;
    }

    .vp-hud--view {
        display: none;
    }

    .viewport--framed .vp-hud--view {
        display: grid;
        inset-block-start: 12px;
        inset-inline-start: 14px;
    }

    .vp-export {
        inset-block-end: 12px;
        inset-inline-end: 12px;
    }
}
