ui/sckparteditor.razor.scss
// SCK PART EDITOR — a dev panel, so it reads as one.
//
// ⚠️ MODELLED ON RecoilTuner.razor.scss, NOT SHARING IT. Razor components scope their own styles;
// a shared sheet would make either tuner's tweak silently change the other. Same argument
// SoulBoxTuner already makes about its copy.
//
// ⚠️ NARROWER THAN THE OTHER TUNERS, AND LEFT-ALIGNED, because the thing being judged is a
// viewmodel — it lives in the bottom RIGHT of the screen, and a panel wide enough to cover it
// would hide the only feedback the sliders have.

.tuner {
    position: absolute;
    width: 100%;
    height: 100%;
    pointer-events: none;
    align-items: flex-start;
    justify-content: flex-start;

    // ⚠️ TIGHTER TOP MARGIN THAN THE OTHER TUNERS. This panel grew a whole-gun section and a
    // per-piece section on top of the list; 50px of dead space above it was 50px the controls
    // could not use.
    padding: 24px 0 24px 30px;
    font-family: Inter;

    // ⛔ NOT `display: none`. A zero-opacity panel keeps its layout, so the rows do not reflow on
    // the frame it opens.
    &.hidden {
        opacity: 0;
        pointer-events: none;
    }
}

.panel {
    flex-direction: column;
    width: 440px;

    // ⛔ IT SCROLLS, BECAUSE IT NO LONGER FITS. With the pieces list, the per-piece rows, the
    // whole-gun rows and the paste line, the panel runs past the bottom of the screen — and
    // everything below the cut was simply unreachable, including the line you copy the result from.
    // A dev panel that can grow needs a scroll long before it looks like it needs one.
    max-height: 100%;
    overflow-y: scroll;
    background-color: rgba(8, 10, 12, 0.92);
    border: 1px solid rgba(255, 255, 255, 0.10);
    border-radius: 4px;
    padding: 14px 16px 16px;

    // ⚠️ The ROOT is pointer-events:none so the game keeps the mouse everywhere else; only the
    // panel itself takes clicks, or the sliders cannot be dragged.
    pointer-events: all;
}

.head {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 10px;
    padding-bottom: 8px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.12);

    .title {
        font-size: 13px;
        font-weight: 600;
        letter-spacing: 1.6px;
        color: rgba(228, 234, 240, 1);
    }

    .close {
        font-size: 20px;
        color: rgba(150, 160, 172, 1);
        padding: 0 4px;
        cursor: pointer;

        &:hover { color: rgba(235, 240, 245, 1); }
    }
}

// Where the rig got to this frame. Always present, because "nothing is happening" needs a
// sentence as much as a failure does.
.state {
    font-size: 11.5px;
    font-family: Consolas;
    color: rgba(140, 160, 180, 1);
    margin-bottom: 8px;
    word-break: break-word;

    &.bad { color: rgba(236, 140, 120, 1); }
}

.warn {
    font-size: 12.5px;
    color: rgba(226, 180, 110, 1);
    margin-bottom: 10px;
}

.group {
    font-size: 11px;
    letter-spacing: 1.1px;
    color: rgba(128, 140, 154, 1);
    margin: 12px 0 4px;
    padding-bottom: 4px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

// ⚠️ CAPPED AND SCROLLING. Seventeen rows at full height would push the sliders off the bottom of
// the screen, and the sliders are the point of the panel.
// ⚠️ SHORTER NOW THAT THE PANEL ITSELF SCROLLS. Two nested scroll regions both wanting the
// wheel is worse than one, so the list keeps only enough height to show a handful of pieces and
// the panel takes the rest.
.list {
    flex-direction: column;
    max-height: 132px;
    overflow: scroll;
}

.item {
    flex-direction: row;
    align-items: center;
    height: 24px;
    padding: 0 8px;
    border-radius: 3px;
    cursor: pointer;

    &:hover { background-color: rgba(255, 255, 255, 0.06); }

    // ⚠️ THE SAME ORANGE THE RIG TINTS THE PART WITH. The list and the gun have to agree about
    // which piece is selected, and two different highlight colours would be two questions.
    &.sel {
        background-color: rgba(230, 120, 40, 0.22);
        border: 1px solid rgba(240, 150, 70, 0.45);
    }

    .nm {
        width: 62px;
        font-size: 12.5px;
        color: rgba(224, 230, 236, 1);
        font-family: Consolas;
    }

    .rel {
        flex-grow: 1;
        font-size: 11.5px;
        color: rgba(128, 140, 154, 1);
    }

    // Marks a piece whose numbers no longer match the file on disk — so Print's output is
    // predictable before you press it.
    .dot {
        font-size: 10px;
        color: rgba(150, 210, 170, 1);
    }
}

.row {
    flex-direction: row;
    align-items: center;

    // ⚠️ TALLER THAN THE ENTRY IT HOLDS. At 28px — the entry's own height — the box plus its
    // borders did not fit and the text inside never appeared.
    height: 34px;

    .label {
        width: 52px;
        font-size: 12.5px;
        color: rgba(160, 170, 182, 1);
    }

    .s {
        flex-grow: 1;
        margin: 0 10px;
    }

    // ⚠️ TYPEABLE, NOT JUST A READOUT. A slider cannot hit 0.004 or paste a value from the lua,
    // and both are things this panel exists to do.
    //
    // ⛔ COPIED FROM ToolPanel's `.entry`, WHICH WORKS, RATHER THAN STYLED TO TASTE. My first
    // version was 22px tall with `text-align: right` and a Consolas face, and it rendered an empty
    // box — the border drew, the number never did. A `TextEntry` lays its text out in an inner
    // panel, so it does not survive being squeezed or having its alignment overridden from here.
    // Match the proven one; do not redecorate it.
    .entry {
        width: 82px;
        height: 28px;
        padding: 0px 8px;
        font-size: 14px;
        color: #ffd479;
        background-color: rgba( 0, 0, 0, 0.45 );
        border: 1px solid rgba( 255, 255, 255, 0.12 );
        border-radius: 4px;

        &:hover { border-color: rgba( 255, 255, 255, 0.28 ); }
        &:focus { border-color: #ffd479; color: #fff; }
    }
}

// The line you paste. Monospace because it is data, green because it is the answer rather than
// the input — the sliders above are what you set, this is what the bake will read.
.out {
    margin-top: 10px;
    padding: 8px 10px;
    background-color: rgba(0, 0, 0, 0.45);
    border: 1px solid rgba(255, 255, 255, 0.07);
    border-radius: 3px;
    font-family: Consolas;
    font-size: 11px;
    color: rgba(150, 210, 170, 1);
    word-break: break-all;
}

.buttons {
    flex-direction: row;
    flex-wrap: wrap;
    margin-top: 12px;
}

.btn {
    padding: 7px 12px;
    margin: 0 6px 6px 0;
    background-color: rgba(255, 255, 255, 0.07);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 3px;
    font-size: 12px;
    letter-spacing: 0.6px;
    color: rgba(224, 230, 236, 1);
    cursor: pointer;

    &:hover { background-color: rgba(255, 255, 255, 0.13); }

    &.copy {
        background-color: rgba(70, 130, 100, 0.35);
        border-color: rgba(120, 200, 160, 0.35);
    }

    // ⚠️ AN ON STATE THAT IS NOT JUST THE LABEL. "Baked hidden" and "Baked shown" differ by a
    // word; at a glance, mid-drag, the colour is what actually reads.
    &.on {
        background-color: rgba(80, 120, 180, 0.35);
        border-color: rgba(130, 175, 235, 0.40);
    }
}