
.gfi-abstract { --gfi-cols-desktop:4; --gfi-cols-tablet:3; --gfi-cols-mobile:2; --gfi-gap:8px; --gfi-radius:6px; margin:1.25rem 0; }
.gfi-abstract-title { margin:0 0 .55rem; }
.gfi-abstract-description { margin:0 0 .85rem; }
.gfi-abstract-grid { gap:var(--gfi-gap); }
.gfi-layout-grid .gfi-abstract-grid, .gfi-layout-featured .gfi-abstract-grid { display:grid; grid-template-columns:repeat(var(--gfi-cols-desktop), minmax(0,1fr)); }
.gfi-layout-masonry .gfi-abstract-grid { column-count:var(--gfi-cols-desktop); column-gap:var(--gfi-gap); }
.gfi-layout-single .gfi-abstract-grid { display:block; max-width:min(100%, 900px); }
.gfi-layout-single .gfi-abstract-item img { width:100%; height:auto; aspect-ratio:auto; object-fit:contain; }
.gfi-abstract-item { position:relative; display:block; width:100%; padding:0; margin:0; border:0; background:transparent; cursor:pointer; overflow:hidden; border-radius:var(--gfi-radius); }
.gfi-layout-masonry .gfi-abstract-item { margin:0 0 var(--gfi-gap); break-inside:avoid; }
.gfi-abstract-item img { display:block; width:100%; height:auto; border-radius:inherit; }
.gfi-layout-grid .gfi-abstract-item img { aspect-ratio:1 / 1; object-fit:cover; }
.gfi-layout-featured .gfi-abstract-item img { aspect-ratio:4 / 3; object-fit:cover; }
.gfi-layout-featured .gfi-abstract-item:first-child { grid-column:span 2; grid-row:span 2; }
.gfi-layout-featured .gfi-abstract-item:first-child img { height:100%; aspect-ratio:auto; object-fit:cover; }
.gfi-more-overlay { position:absolute; inset:0; display:grid; place-items:center; background:rgba(0,0,0,.48); color:#fff; font-size:clamp(1.25rem,4vw,2.2rem); font-weight:700; }
.gfi-abstract-footer { display:flex; align-items:center; justify-content:space-between; gap:.75rem; margin-top:.65rem; }
.gfi-photo-count { opacity:.72; font-size:.92em; }
.gfi-view-all, .gfi-modal-close, .gfi-viewer-close, .gfi-viewer-prev, .gfi-viewer-next { border:1px solid currentColor; background:transparent; border-radius:999px; padding:.45rem .9rem; cursor:pointer; font:inherit; }
.gfi-modal { position:fixed; inset:0; z-index:100000; display:none; background:rgba(12,12,12,.96); color:#fff; }
.gfi-modal.is-open { display:block; }
.gfi-modal-shell { height:100%; overflow:auto; padding:1rem; }
.gfi-modal-header { position:sticky; top:0; z-index:2; display:flex; justify-content:flex-end; padding:.25rem 0 .75rem; background:rgba(12,12,12,.92); }
.gfi-modal-close { color:#fff; }
.gfi-modal-status { padding:2rem; text-align:center; }
.gfi-modal-grid {
    display:grid;
    grid-template-columns:repeat(var(--gfi-cols-desktop), minmax(0,1fr));
    gap:var(--gfi-gap);
    align-items:start;
}
.gfi-modal-item { display:block; width:100%; margin:0; border:0; padding:0; background:transparent; cursor:zoom-in; border-radius:var(--gfi-radius); overflow:hidden; }
.gfi-modal-item img { width:100%; height:auto; display:block; }
.gfi-photo-viewer { position:fixed; inset:0; z-index:100001; display:none; background:rgba(0,0,0,.94); color:#fff; padding:1rem; }
.gfi-photo-viewer.is-open { display:block; }
.gfi-photo-viewer-shell { height:100%; display:grid; grid-template-rows:auto 1fr auto; gap:1rem; }
.gfi-photo-viewer-header, .gfi-photo-viewer-footer { display:flex; align-items:center; justify-content:space-between; gap:.75rem; }
.gfi-photo-viewer-stage { display:grid; grid-template-columns:auto 1fr auto; align-items:center; gap:.75rem; min-height:0; }
.gfi-viewer-image-wrap { display:grid; place-items:center; min-height:0; }
.gfi-viewer-image-wrap img { max-width:95vw; max-height:78vh; object-fit:contain; }
.gfi-viewer-counter { opacity:.82; font-size:.95em; }
.gfi-viewer-meta { min-height:1.25em; font-size:.95em; opacity:.82; }
@media (max-width:900px) { .gfi-layout-grid .gfi-abstract-grid, .gfi-layout-featured .gfi-abstract-grid { grid-template-columns:repeat(var(--gfi-cols-tablet), minmax(0,1fr)); } .gfi-layout-masonry .gfi-abstract-grid { column-count:var(--gfi-cols-tablet); } .gfi-modal-grid { grid-template-columns:repeat(var(--gfi-cols-tablet), minmax(0,1fr)); } }
@media (max-width:600px) { .gfi-layout-grid .gfi-abstract-grid, .gfi-layout-featured .gfi-abstract-grid { grid-template-columns:repeat(var(--gfi-cols-mobile), minmax(0,1fr)); } .gfi-layout-masonry .gfi-abstract-grid { column-count:var(--gfi-cols-mobile); } .gfi-modal-grid { grid-template-columns:repeat(var(--gfi-cols-mobile), minmax(0,1fr)); } .gfi-layout-featured .gfi-abstract-item:first-child { grid-column:span min(2, var(--gfi-cols-mobile)); } .gfi-photo-viewer-stage { grid-template-columns:1fr; grid-template-rows:auto 1fr auto; } .gfi-viewer-prev, .gfi-viewer-next { justify-self:center; } }


.gfi-modal-header {
    align-items: center;
    gap: .75rem;
}

.gfi-modal-progress {
    flex: 1;
    min-width: 0;
    opacity: .85;
    font-size: .95em;
}

.gfi-modal-status[hidden],
.gfi-modal-grid[hidden] {
    display: none !important;
}

.gfi-modal-item {
    position: relative;
    display: block;
    overflow: hidden;
    background: linear-gradient(110deg, rgba(255,255,255,.06) 8%, rgba(255,255,255,.14) 18%, rgba(255,255,255,.06) 33%);
    background-size: 200% 100%;
    animation: gfi-skeleton 1.1s linear infinite;
}

.gfi-modal-item.is-loaded,
.gfi-modal-item.is-error {
    animation: none;
    background: rgba(255,255,255,.04);
}

.gfi-modal-item img {
    width: 100%;
    height: 100%;
    display: block;
    object-fit: cover;
    opacity: 0;
    transition: opacity .25s ease;
}

.gfi-modal-item.is-loaded img {
    opacity: 1;
}

@keyframes gfi-skeleton {
    to {
        background-position-x: -200%;
    }
}


/*
 * 2.1.2 — Selected Photos ordering fix
 *
 * CSS multi-column masonry lays items out top-to-bottom, then left-to-right.
 * That is undesirable for manually curated photos because the visible order
 * no longer matches the order chosen in Gutenberg.
 *
 * Selected Photos therefore uses a row-major grid when "Masonry" is selected:
 * items are always read left-to-right, then top-to-bottom, while each image
 * keeps its natural aspect ratio.
 */
.gfi-selected-render.gfi-layout-masonry .gfi-abstract-grid {
    column-count: initial;
    column-gap: initial;
    display: grid;
    grid-template-columns: repeat(var(--gfi-cols-desktop), minmax(0, 1fr));
    gap: var(--gfi-gap);
    align-items: start;
}

.gfi-selected-render.gfi-layout-masonry .gfi-abstract-item {
    margin: 0;
    break-inside: auto;
    align-self: start;
}

.gfi-selected-render.gfi-layout-masonry .gfi-abstract-item img {
    width: 100%;
    height: auto;
    aspect-ratio: auto;
    object-fit: contain;
}

@media (max-width: 900px) {
    .gfi-selected-render.gfi-layout-masonry .gfi-abstract-grid {
        grid-template-columns: repeat(var(--gfi-cols-tablet), minmax(0, 1fr));
    }
}

@media (max-width: 600px) {
    .gfi-selected-render.gfi-layout-masonry .gfi-abstract-grid {
        grid-template-columns: repeat(var(--gfi-cols-mobile), minmax(0, 1fr));
    }
}


/* 2.2.0 — Justified Rows
 * Preserves left-to-right reading order while fitting mixed aspect ratios
 * into balanced rows. JavaScript calculates the exact item widths/heights.
 */
.gfi-layout-justified .gfi-abstract-grid {
    display: flex;
    flex-wrap: wrap;
    gap: var(--gfi-gap);
    align-items: flex-start;
}

.gfi-layout-justified .gfi-abstract-item {
    flex: 0 0 auto;
    margin: 0;
    overflow: hidden;
}

.gfi-layout-justified .gfi-abstract-item img {
    width: 100%;
    height: 100%;
    display: block;
    object-fit: cover;
}

.gfi-layout-justified .gfi-abstract-item.gfi-justified-unmeasured {
    flex: 1 1 220px;
}

.gfi-selected-render.gfi-layout-justified .gfi-abstract-grid {
    display: flex;
    flex-wrap: wrap;
    gap: var(--gfi-gap);
    align-items: flex-start;
}

.gfi-selected-render.gfi-layout-justified .gfi-abstract-item {
    margin: 0;
}


/* 2.3.4 — All Photos popup ordering
 * The popup no longer uses CSS multi-column layout, which fills vertically.
 * CSS Grid preserves DOM order: left-to-right, then top-to-bottom.
 */
.gfi-modal-grid {
    column-count:initial !important;
    column-gap:initial;
}


/* 2.3.5 — All Photos popup justified rows
 * Preserve DOM order left-to-right while allowing mixed portrait/landscape
 * images to share balanced rows according to their natural aspect ratios.
 */
.gfi-modal-grid {
    display:flex !important;
    flex-wrap:wrap;
    align-items:flex-start;
    grid-template-columns:none !important;
    gap:var(--gfi-gap);
}

.gfi-modal-item {
    flex:0 0 auto;
    width:auto;
    margin:0;
}

.gfi-modal-item img {
    width:100%;
    height:100%;
    object-fit:cover;
}

@media (max-width:600px) {
    .gfi-modal-grid {
        grid-template-columns:none !important;
    }
}
