.puzzle {
    display: block;
    width: 100%;
    position: relative;
    user-select: none;
    -webkit-user-select: none;
    line-height: 0;

    /* neutral backdrop that blends with any image */
    background-color: var(--puzzle-bg, #e8e5df);
    background-image: repeating-linear-gradient(
            45deg,
            rgba(0, 0, 0, .030) 0 8px,
            rgba(0, 0, 0, 0) 8px 16px
    );
}

.puzzle__svg--outlines {
    pointer-events: none;
    contain: strict; /* tells the browser nothing outside affects it */
}

.puzzle.puzzle--plain {
    background-image: none;
}

.puzzle__svg {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
}

/* image layer */
.puzzle__piece-image {
    opacity: 0;
    transition: opacity var(--puzzle-reveal-duration, 400ms) ease;
}

.puzzle__piece-image.is-revealed {
    opacity: 1;
}

/* outline layer — visible when unrevealed, fades out on reveal */
.puzzle__piece-outline {
    fill: none;
    stroke: var(--puzzle-outline-color, rgba(40, 40, 40, 0.55));
    stroke-width: var(--puzzle-outline-width, 1.5); /* in viewBox units — tune to taste */
    stroke-linejoin: round;
    stroke-linecap: round;
    opacity: 1;
    transition: opacity var(--puzzle-reveal-duration, 400ms) ease;
}

.puzzle__piece-outline.is-revealed {
    opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
    .puzzle__piece-image,
    .puzzle__piece-outline {
        transition-duration: 1ms;
    }
}