tiles--halves.html
<section class="tiles">
    <div class="container">
        <div class="tiles__grid -featured">
            <!-- 
                Halves grid: 4 columns at desktop
                Add any number of tiles, any combination of modifiers
            -->
            <div class="tiles__set -halves">
                <div class="tiles__tile -featured">
                    <div class="tiles__media">
                        <img src="https://images.unsplash.com/photo-1557682250-33bd709cbe85?w=800&h=800&fit=crop" alt="">
                    </div>
                    <button class="tiles__more">
                        <!--!Font Awesome Free v7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.-->
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M480 80c8.8 0 16 7.2 16 16l0 256c0 8.8-7.2 16-16 16l-320 0c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l320 0zM160 32c-35.3 0-64 28.7-64 64l0 256c0 35.3 28.7 64 64 64l320 0c35.3 0 64-28.7 64-64l0-256c0-35.3-28.7-64-64-64L160 32zm80 112a32 32 0 1 0 -64 0 32 32 0 1 0 64 0zm140.7 3.8c-4.3-7.3-12.2-11.8-20.7-11.8s-16.4 4.5-20.7 11.8l-46.5 79-17.2-24.6c-4.5-6.4-11.8-10.2-19.7-10.2s-15.2 3.8-19.7 10.2l-56 80c-5.1 7.3-5.8 16.9-1.6 24.8S191.1 320 200 320l240 0c8.6 0 16.6-4.6 20.8-12.1s4.2-16.7-.1-24.1l-80-136zM48 152c0-13.3-10.7-24-24-24S0 138.7 0 152L0 448c0 35.3 28.7 64 64 64l360 0c13.3 0 24-10.7 24-24s-10.7-24-24-24L64 464c-8.8 0-16-7.2-16-16l0-296z"/></svg>
                        View 10 More Images
                    </button>
                </div>

                <div class="tiles__tile">
                    <div class="tiles__media">
                        <img src="https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?w=400&h=400&fit=crop" alt="">
                    </div>
                </div>

                <div class="tiles__tile">
                    <div class="tiles__media">
                        <img src="https://images.unsplash.com/photo-1614850523296-d8c1af93d400?w=400&h=400&fit=crop" alt="">
                    </div>
                </div>

                <div class="tiles__tile -wide">
                    <div class="tiles__media">
                        <img src="https://images.unsplash.com/photo-1557682224-5b8590cd9ec5?w=600&h=300&fit=crop" alt="">
                    </div>
                </div>
            </div>

            <!-- 
                4-column grid: Small + Wide + Small (1+2+1 = 4 cols)
                Visually continues from the section above (no extra gap)
            -->
            <div class="tiles__set -halves">
                <div class="tiles__tile">
                    <div class="tiles__media">
                        <img src="https://images.unsplash.com/photo-1501854140801-50d01698950b?w=400&h=400&fit=crop" alt="">
                    </div>
                </div>

                <div class="tiles__tile -wide">
                    <div class="tiles__media">
                        <img src="https://images.unsplash.com/photo-1433086966358-54859d0ed716?w=800&h=400&fit=crop" alt="">
                    </div>
                </div>

                <div class="tiles__tile">
                    <div class="tiles__media">
                        <img src="https://images.unsplash.com/photo-1439066615861-d1af74d74000?w=400&h=400&fit=crop" alt="">
                    </div>
                </div>
            </div>
        </div>
    </div>
</section>
index.scss
@use "@imarc/pronto/resources/styles/imported" as *;

.tiles {
    $b: &;

    padding: 2rem 0;

    &__grid {
        --columns: 1;
        --gap: var(--root-gap, 1rem);

        display: grid;
        gap: var(--gap);
        grid-template-columns: repeat(var(--columns), 1fr);
        grid-auto-flow: dense;

        @include at(md) {
            --columns: 2;
        }

        @include at(lg) {
            --columns: 4;
        }
    }

    &__tile {
        background-color: var(--tile-bg, var(--color-gray-100, #f5f5f5));
        display: grid;
        overflow: hidden;
        position: relative;

        // Position for content tiles
        &.-has-content {
            align-items: end;
        }
    }

    &__media {
        height: 100%;
        left: 0;
        position: absolute;
        top: 0;
        width: 100%;

        img,
        video {
            height: 100%;
            object-fit: cover;
            width: 100%;
        }
    }

    &__content {
        display: flex;
        flex-direction: column;
        gap: 1.5rem;
        max-width: 32rem;
        padding: 2rem;
        position: relative;
        z-index: 1;
    }

    &__heading {
        color: inherit;
        font-family: var(--root-font-family-heading);
        font-size: clamp(2rem, 5vw, 3.5rem);
        font-weight: 700;
        line-height: 1.1;
        margin: 0;
    }

    &__description {
        line-height: 1.5;
        margin: 0;
    }

    &__actions {
        display: flex;
        flex-wrap: wrap;
        gap: 1rem;
        margin-block-start: 0.5rem;
    }

    // Dark theme for tiles with dark backgrounds
    &__tile.-dark {
        color: #fff;

        #{$b}__heading,
        #{$b}__description {
            color: inherit;
        }

        .button.-outline {
            border-color: currentColor;
            color: inherit;

            &:hover {
                background-color: #fff;
                border-color: #fff;
                color: #000;
            }
        }
    }

    // Light theme for tiles with light backgrounds
    &__tile.-light {
        color: var(--root-color, #333);
    }

    // Featured layout container
    &__grid.-featured {
        display: flex;
        flex-direction: column;
        gap: var(--gap);
    }

    // ==========================================================================
    // Tile Sets - Flexible grid layouts
    // 
    // Set modifiers define the column structure:
    //   -thirds  : 3-column grid at desktop (for 1/3 + 2/3 style layouts)
    //   -halves  : 4-column grid at desktop (for 50/50 style layouts)
    //
    // Tile modifiers control spanning (work in any set):
    //   -featured : Spans 2 columns × 2 rows (large square)
    //   -wide     : Spans 2 columns × 1 row (horizontal banner)
    //   -tall     : Spans 1 column × 2 rows (vertical banner)
    //   (default) : 1 column × 1 row (small square)
    //
    // Tiles flow in DOM order with dense packing to fill gaps.
    // Add as many tiles as needed - the grid adapts automatically.
    // ==========================================================================
    &__set {
        container-type: inline-size;
        display: grid;
        gap: var(--gap);
        grid-auto-flow: dense;

        // Thirds: 3-column grid
        &.-thirds {
            --_tile-size: 100cqi; // Mobile: full width
            grid-template-columns: 1fr;

            @include at(md) {
                --_tile-size: calc((100cqi - var(--gap)) / 2);
                grid-template-columns: repeat(2, 1fr);
            }

            @include at(lg) {
                --_tile-size: calc((100cqi - var(--gap) * 2) / 3);
                grid-template-columns: repeat(3, 1fr);
            }

            // Staggered layout: uses -short (1 row) and -fill (2 rows) tiles
            // No explicit row heights - tiles define their own heights via aspect-ratio/min-height
            &.-staggered {
                // Short height = tile-width × 9/16
                --_short-height: calc(var(--_tile-size) * 0.5625);
                
                #{$b}__tile.-fill {
                    // Fill = 2 shorts + 1 gap
                    min-height: calc(var(--_short-height) * 2 + var(--gap));
                    aspect-ratio: auto;
                }
            }
        }

        // Halves: 4-column grid (good for 50/50 layouts with sub-divisions)
        &.-halves {
            --_tile-size: 100cqi; // Mobile: full width
            grid-template-columns: 1fr;

            @include at(md) {
                --_tile-size: calc((100cqi - var(--gap)) / 2);
                grid-template-columns: repeat(2, 1fr);
            }

            @include at(lg) {
                --_tile-size: calc((100cqi - var(--gap) * 3) / 4);
                grid-template-columns: repeat(4, 1fr);
            }
        }

        // =======================================================================
        // Tile modifiers - control spanning behavior
        // Small/Featured tiles use aspect-ratio: 1 for square
        // Wide/Tall tiles stretch to fill their grid area
        // =======================================================================

        // Default: 1×1 square tile
        #{$b}__tile {
            aspect-ratio: 1;
        }

        // Featured: Large 2×2 tile (still square)
        #{$b}__tile.-featured {
            grid-column: span 2;
            grid-row: span 2;
            aspect-ratio: 1;

            @include at(md, max-width) {
                grid-column: span 1;
                grid-row: span 1;
            }
        }

        // Wide: Horizontal 2×1 tile
        #{$b}__tile.-wide {
            grid-column: span 2;
            aspect-ratio: auto;
            align-self: stretch;
            // Minimum height ensures correct sizing when alone in a row
            min-height: var(--_tile-size, 200px);

            @include at(md, max-width) {
                grid-column: span 1;
                aspect-ratio: 1;
                min-height: unset;
            }
        }

        // Tall: Vertical 1×2 tile
        // Same width as a square tile, spans 2 rows
        #{$b}__tile.-tall {
            grid-row: span 2;
            aspect-ratio: auto;
            align-self: stretch;
            // Minimum height ensures correct sizing when determining grid flow
            min-height: calc(var(--_tile-size, 200px) * 2 + var(--gap));

            @include at(md, max-width) {
                grid-row: span 1;
                aspect-ratio: 1;
                min-height: unset;
            }
        }

        // Short: Compressed height tile (16:9 landscape)
        // Height = 9/16 of normal tile (56.25%)
        #{$b}__tile.-short {
            aspect-ratio: 16 / 9;

            @include at(md, max-width) {
                aspect-ratio: 1;
            }
        }

        // Fill: Spans 2 grid rows, pairs with -short tiles
        #{$b}__tile.-fill {
            grid-row: span 2;
            aspect-ratio: auto;
            align-self: stretch;

            @include at(md, max-width) {
                grid-row: span 1;
                aspect-ratio: 1;
            }
        }
    }

    // "View more" button - positioned within tile content
    &__more {
        align-items: center;
        align-self: flex-end;
        background: #fff;
        border-radius: 4px;
        border: none;
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
        color: #0066ff;
        cursor: pointer;
        display: inline-flex;
        font-size: 0.875rem;
        font-weight: 500;
        gap: 0.5rem;
        margin: auto 2rem 2rem auto; // Push to bottom-right with tile padding
        padding: 0.5rem 1rem;
        position: relative;
        transition: box-shadow var(--root-duration-fast, 150ms) var(--root-ease-out);
        white-space: nowrap;
        z-index: 2;

        &:hover {
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
        }

        svg,
        .icon {
            fill: currentColor;
            height: 1em;
            width: 1em;
        }
    }

    // Gradient overlay for better text readability
    &__overlay {
        background: linear-gradient(
            to top,
            rgba(0, 0, 0, 0.7) 0%,
            rgba(0, 0, 0, 0.3) 50%,
            rgba(0, 0, 0, 0) 100%
        );
        inset: 0;
        position: absolute;
        z-index: 0;
    }
}