/* ---------- Fonts ---------- */
@font-face {
    font-family: "Cario";
    src: url("../fonts/cario/Cario-Semibold.otf") format("opentype");
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}

/* Variable font: one file covers every weight from 100 to 900 */
@font-face {
    font-family: "Fraunces";
    src: url("../fonts/fraunces-font-family/Fraunces-VariableFont_SOFTWONKopszwght.ttf") format("truetype");
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: "Fraunces";
    src: url("../fonts/fraunces-font-family/Fraunces-Italic-VariableFont_SOFTWONKopszwght.ttf") format("truetype");
    font-weight: 100 900;
    font-style: italic;
    font-display: swap;
}

/* ---------- Colors & sizes ---------- */
:root {
    --bg-fallback: #2B180A;       /* shown if wood.png fails to load, and inside frames whose picture hasn't loaded */
    --header-fallback: #001C55;   /* shown if try.png fails to load */
    --name-gold: #eef2c0;         /* cream: intro paragraph, "Coming soon" */
    --wordmark-gold: #efe10d;     /* gold: GABRIEL OLIVEIRA in the header */

    /* Header height scales with screen width; the rem floor/ceiling keep it
       usable on tiny phones and stop it from growing huge on wide monitors. */
    --header-h: clamp(4.75rem, 8.5vw, 8.5rem);
    /* The fabric image is drawn this many times the header height. Stitch lines
       sit at ~30% and ~69% of the image, so 2.25 leaves them just inside the
       top and bottom edges (a gap of ~5% of the header height). */
    --fabric-scale: 2.25;

    /* Width of the name in the header. js/site.js measures the real value;
       this is only a stand-in until the script runs. */
    --wordmark-w: min(90vw, 40rem);

    /* ----- Exhibit sizes ----- */
    /* Full-size frame (videos 1-4, all the same size): most of the screen,
       while leaving room for the top of the next frame to show at the bottom
       of the first screen, so visitors can tell there's more.
       - Wide screens: at most 64% of the width (room for a card beside it).
       - Frame height is capped at 62% of the space below the header (frames
         are about 0.615 x as tall as wide, hence the / 0.615). */
    --frame-full: min(64vw, calc((100svh - var(--header-h)) * 0.62 / 0.615));
    --hero-gap: clamp(1.5rem, 6vh, 4rem);   /* shorter gap under video 1, so the next frame peeks in */
    --exhibit-gap: clamp(3rem, 12vh, 9rem);      /* space between exhibits */

    /* Smaller frames spread wider than the main column, using the empty
       space on either side. Each small frame's slot is half of --trio-w
       (minus the gap); 64vw leaves room for the outer cards beside them. */
    --trio-w: 64vw;
    --trio-gap: clamp(1rem, 3vw, 3rem);
    --frame-small: calc((var(--trio-w) - var(--trio-gap)) / 2);

    /* Every card on the page is the same size, like museum placards.
       Normally 22% of a full-size frame, but never wider than the tightest
       spot it has to hang in, so no card ever needs to shrink or gets cut off:
         --card-fit-side: beside Palumbo 2, between the two columns of smaller
                          frames and the screen edge
         --card-fit-wide: beside frame 3, the widest frame (fit 1.1775 x 1.03)
       (3rem = the page's side padding plus room for a scrollbar) */
    --label-gap: clamp(1rem, 2.5vw, 3rem);       /* space between a frame and its card */
    --card-fit-side: calc((100vw - 3rem - var(--frame-small) * 2.1353 - var(--trio-gap)) / 2 - var(--label-gap));
    --card-fit-wide: calc((100vw - 3rem - var(--frame-full) * 1.2128) / 2 - var(--label-gap));
    --card-w: max(6rem, min(calc(var(--frame-full) * 0.22), var(--card-fit-side), var(--card-fit-wide)));
}

/* keep phones from enlarging text on their own */
html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

/* ---------- Page background ---------- */
body {
    margin: 0;

    background-color: var(--bg-fallback);
    background-image: url("../textures/wood.png");
    background-repeat: repeat-y;
    background-position: top center;
    background-size: 100% auto;   /* always the full screen width, height keeps proportions */
}

/* ---------- Header bar ---------- */
.site-header {
    height: var(--header-h);

    background-color: var(--header-fallback);
    background-image: url("../textures/header/try.png");
    background-repeat: repeat-x;
    background-position: center;
    background-size: auto calc(var(--header-h) * var(--fabric-scale));

    box-shadow: 0 0.25rem 0.65rem rgba(0, 0, 0, 0.45);
}

.site-header .row {
    height: 100%;
}

/* Logo: a share of the header height, so it scales with the header */
.site-logo {
    height: 78%;
    width: auto;
    display: block;
}

/* ---------- Header links (right of the name) ----------
   ALL WORKS · ABOUT · CONTACT · LINKS, in the wordmark's font and gold, all
   the same size. Measured from the font, the four labels take ~19.1x their
   font size plus 3.45x for the gaps (22.55x in all), and the name ~10.7x its
   own (so it reaches 24.7vw either side of center). The links are sized to
   fill the room left between the name and the header's right edge: 1.75rem
   is the 12px of header padding they keep plus 16px of space from the name.
   On screens past ~1565px the name stops growing, so the links get
   relatively more room there. Narrower or upright screens get a MENU
   dropdown instead. */
.site-nav {
    position: relative;
    z-index: 1;                      /* above the centered name's box */
    margin-right: -0.75rem;          /* sit 12px closer to the edge than the logo does, for more room */
}
.site-nav-links {
    display: flex;
    gap: 1.15em;
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: clamp(0.8rem, calc((25.3vw - 1.75rem) / 22.55), 1.6rem);
}
.site-nav-link,
.site-nav-toggle {
    font-family: "Cario", Georgia, serif;
    font-weight: 600;
    letter-spacing: 0.06em;
    line-height: 1;
    white-space: nowrap;
    color: var(--wordmark-gold);
    text-decoration: none;
}
.site-nav-link {
    padding-bottom: 0.2em;
    border-bottom: 0.08em solid transparent;
    transition: border-color 0.2s ease;
}
.site-nav-link:hover,
.site-nav-link:focus-visible,
.site-nav-link[aria-current="page"] {
    color: var(--wordmark-gold);
    border-bottom-color: currentColor;   /* underline on hover / current page */
}
.site-nav-link:focus-visible,
.site-nav-toggle:focus-visible {
    outline: 0.12rem solid #fff;
    outline-offset: 0.2rem;
}
.site-nav-link[aria-disabled="true"] {
    cursor: default;                 /* page not made yet */
}

/* MENU button + dropdown (narrow screens only) */
.site-nav-menu {
    display: none;
}
.site-nav-toggle {
    padding: 0.45em 0.8em;
    border: 0.1em solid var(--wordmark-gold);
    border-radius: 0.3em;
    background: rgba(0, 0, 0, 0.18);
    font-size: clamp(0.75rem, 2.6vw, 1rem);
}
.site-nav-menu .dropdown-menu {
    --bs-dropdown-bg: #001C55;                    /* the header navy */
    --bs-dropdown-border-color: var(--wordmark-gold);
    --bs-dropdown-link-color: var(--wordmark-gold);
    --bs-dropdown-link-hover-color: #001C55;
    --bs-dropdown-link-hover-bg: var(--wordmark-gold);
    --bs-dropdown-link-active-color: #001C55;
    --bs-dropdown-link-active-bg: var(--wordmark-gold);
    min-width: 0;
    font-family: "Cario", Georgia, serif;
    font-weight: 600;
    letter-spacing: 0.06em;
}

@media (max-width: 1279.98px), (orientation: portrait) {
    .site-nav       { margin-right: 0; }
    .site-nav-links { display: none; }
    .site-nav-menu  { display: block; }
}

/* ---------- Gold-stamped name ---------- */
.site-name {
    --lh: 1.2;
    --tracking: 0.06em;

    /* Pinned to the exact center of the header, whatever the logo's width */
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);

    margin: 0;
    /* Browsers add letter-spacing after the LAST letter too, which pushes the
       visible text left of center. Equal padding on the left balances it. */
    padding-left: var(--tracking);
    font-family: "Cario", Georgia, serif;
    font-weight: 600;
    font-size: clamp(0.95rem, 4.6vw, 4.5rem);
    letter-spacing: var(--tracking);
    line-height: var(--lh);
    white-space: nowrap;
    color: var(--wordmark-gold);   /* used as-is if the stamp effect isn't supported */
}

@supports ((background-clip: text) or (-webkit-background-clip: text)) {
    .site-name {
        color: transparent;
        /* The letters are filled with the SAME fabric as the header, lined up
           exactly with the weave behind them, then tinted, so the color
           looks pressed into the cloth. Top layer = fabric, bottom = color. */
        background-image:
            url("../textures/header/try.png"),
            linear-gradient(var(--wordmark-gold), var(--wordmark-gold));
        background-blend-mode: soft-light;
        background-repeat: repeat-x;
        background-size:
            auto calc(var(--header-h) * var(--fabric-scale)),
            100% 100%;
        /* The header's fabric is centered on the header, and the name is
           centered in the header, so shifting up by (image height / 2) minus
           (half the name's line box) puts both weaves in the same spot. */
        --fabric-y: calc(var(--header-h) * var(--fabric-scale) / -2 + var(--lh) * 0.5em);
        background-position: center var(--fabric-y), 0 0;
        -webkit-background-clip: text;
        background-clip: text;

        /* Slight pressed-in edge: shadow top-left, faint highlight bottom-right */
        filter:
            drop-shadow(-0.02em -0.02em 0 rgba(0, 0, 0, 0.65))
            drop-shadow(0.015em 0.015em 0 rgba(255, 255, 255, 0.2));
    }
}

/* the name is a link back to the top; it keeps the name's look */
.site-name-link {
    color: inherit;
    text-decoration: none;
    cursor: pointer;
}
.site-name-link:focus-visible {
    outline: 0.12rem solid #fff;
    outline-offset: 0.15rem;
}

/* ---------- Intro paragraph ---------- */
.intro {
    /* Never wider than the name in the header, centered under it */
    max-width: var(--wordmark-w);
    margin: clamp(1.5rem, 4vh, 3rem) auto clamp(1.5rem, 4vh, 3rem);

    font-family: "Fraunces", Georgia, serif;
    font-weight: 700;
    font-size: clamp(1rem, 1.9vw, 2.1rem);
    line-height: 1.2;
    text-align: center;
    text-wrap: balance;          /* evens out the line lengths where supported */
    color: var(--name-gold);
    text-shadow: 0 0.06em 0.2em rgba(0, 0, 0, 0.6);
}

/* ---------- Exhibit: a framed video with its wall card ---------- */
/* Cards hang on the right by default; add "label-left" to an exhibit to hang
   its card on the left instead. */
.exhibit {
    /* --slot-w is the width a frame is given. Every frame is drawn at that
       width (--frame-fit: 1), so frames and their videos come out about the
       same size; a squarer frame is simply a bit taller. */
    --slot-w: var(--frame-full);
    --scale: 1;                      /* per-exhibit size adjustment (1 = as measured) */
    --frame-w: calc(var(--slot-w) * var(--frame-fit) * var(--scale));
    --frame-border: calc(var(--frame-w) * 0.06);

    /* Frame 1 (the default). Measured from frames/frame1.png:
       --frame-aspect = frame height / width
       --frame-pad    = where the opening is (top right bottom left), as % of
                        the frame's width; each side reaches ~0.3% under the
                        frame's inner edge so no gap can show
       --frame-fit    = share of the slot's width the frame uses; frames are
                        scaled so videos 1, 2 come out the same size
       Its opening is 16:9, so the video fills it exactly. */
    --frame-img: url("../frames/frame1-web.png");
    --frame-sil: url("../frames/silhouettes/frame1.png");   /* outer outline, opening filled */
    --frame-aspect: 0.5824;
    --frame-pad: 5.37% 7.98% 5.45% 7.81%;
    --frame-fit: 1.0276;

    display: grid;
    grid-template-columns: 1fr var(--frame-w) 1fr;   /* frame dead center */
    align-items: end;
    margin-bottom: var(--exhibit-gap);
}

/* Frame 2: 3:2 opening, matching Zero Tolerance's 3:2 video, which fills it.
   Its opening is a hair narrower than frame 1's (85.94% vs 86.53% of the
   frame's width), so it's drawn 0.69% wider to give its video the same
   width as frame 1's. A bit taller than frame 1.
   Measured from frames/frame2.png. */
.exhibit.frame-2 {
    --frame-img: url("../frames/frame2-web.png");
    --frame-sil: url("../frames/silhouettes/frame2.png");   /* outer outline, opening filled */
    --frame-aspect: 0.7141;
    --frame-pad: 6.98% 6.98% 6.98% 7.08%;
    --frame-fit: 1.0069;
}
.exhibit.frame-2 .ratio { --bs-aspect-ratio: 66.8%; }   /* the opening's shape: 3:2 */

/* Frame 3: very wide 2.35:1 opening (a widescreen-film shape). The video box
   fills the whole opening instead of being 16:9: a widescreen film fills it
   exactly, a 16:9 video gets black bars at the sides from the player.
   The frame is drawn 1.1775x the slot width so its video box comes out ~5%
   wider than frame 1's, then scaled up a touch more (--scale).
   Measured from frames/frame3.png. */
.exhibit.frame-3 {
    --frame-img: url("../frames/frame3-web.png");
    --frame-sil: url("../frames/silhouettes/frame3.png");   /* outer outline, opening filled */
    --frame-aspect: 0.4952;
    --frame-pad: 7.97% 11.58% 8.53% 11.26%;
    --frame-fit: 1.1775;
    --scale: 1.03;
}

.exhibit.frame-3 .ratio {
    --bs-aspect-ratio: 42.8%;        /* the opening's shape: height / width */
}

/* Frames 4-8 work like frame 3: the video box fills the frame's whole
   opening, so a video shot in that shape fits it exactly (any other shape
   gets black bars from the player). Measured from frames/frame4-8.png. */

/* Frame 4: 2.35:1 opening, sized like video 3, then scaled up a little */
.exhibit.frame-4 {
    --frame-img: url("../frames/frame4-web.png");
    --frame-sil: url("../frames/silhouettes/frame4.png");   /* outer outline, opening filled */
    --frame-aspect: 0.453;
    --frame-pad: 3.95% 6.39% 3.95% 6.48%;
    --frame-fit: 1.0428;
    --scale: 1.06;
}
.exhibit.frame-4 .ratio { --bs-aspect-ratio: 42.9%; }

/* Frames 5-8 (smaller frames): fits chosen so all four videos are the
   same width; the 4:3 ones are a little taller than the 16:9 one */

/* Frame 5: 16:9 opening */
.exhibit.frame-5 {
    --frame-img: url("../frames/frame5-web.png");
    --frame-sil: url("../frames/silhouettes/frame5.png");   /* outer outline, opening filled */
    --frame-aspect: 0.603;
    --frame-pad: 5.43% 6.69% 6.02% 6.78%;
    --frame-fit: 1;
}

/* Frame 6: 4:3 opening */
.exhibit.frame-6 {
    --frame-img: url("../frames/frame6-web.png");
    --frame-sil: url("../frames/silhouettes/frame6.png");   /* outer outline, opening filled */
    --frame-aspect: 0.7978;
    --frame-pad: 10.4% 10.84% 10.62% 11.05%;
    --frame-fit: 1.1077;
}
.exhibit.frame-6 .ratio { --bs-aspect-ratio: 75.2%; }

/* Frame 7: 4:3 opening */
.exhibit.frame-7 {
    --frame-img: url("../frames/frame7-web.png");
    --frame-sil: url("../frames/silhouettes/frame7.png");   /* outer outline, opening filled */
    --frame-aspect: 0.7855;
    --frame-pad: 10.85% 12.32% 10.85% 11.69%;
    --frame-fit: 1.1386;
}
.exhibit.frame-7 .ratio { --bs-aspect-ratio: 74.8%; }

/* Frame 8: vertical poster frame (frames/posterframe1.png) with a 2:3
   opening, holding a film poster instead of a video */
.exhibit.frame-8 {
    --frame-img: url("../frames/posterframe1-web.png");
    --frame-sil: url("../frames/silhouettes/posterframe1.png");   /* outer outline, opening filled */
    --frame-aspect: 1.339;
    --frame-pad: 15.33% 15.18% 15.33% 15.8%;
    --frame-fit: 1;
}
.exhibit.frame-8 .ratio { --bs-aspect-ratio: 149.6%; }

/* A poster image fills the opening; any slight shape difference is trimmed
   off the edges rather than leaving gaps */
.exhibit-poster {
    object-fit: cover;
}

/* Video 1: 10% larger, sized so only a sliver of frame 2's thumbnail shows
   at the bottom of the first screen, with a shorter gap below */
.exhibit.exhibit-hero {
    --scale: 1.1;
    margin-bottom: var(--hero-gap);
}

/* The frame image is laid over the video. The box has the frame's exact
   shape; its padding places the video in the opening (padding percentages
   are fractions of the frame's width, so everything scales together). The
   opening is filled black, and the 16:9 video is centered in it. */
.exhibit-frame {
    grid-column: 2;
    grid-row: 1;
    position: relative;
    aspect-ratio: 1 / var(--frame-aspect);
    padding: var(--frame-pad);
    display: flex;
    align-items: center;
    background: var(--bg-fallback) content-box;   /* dark brown inside the opening until the picture loads */
}

.exhibit-frame .ratio {
    width: 100%;
    z-index: 0;                      /* the video sits UNDER the frame... */
    background: var(--bg-fallback);  /* dark brown if the thumbnail/poster doesn't load (covers the gold silhouette behind) */
}

.exhibit-frame::after {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--frame-img) center / 100% 100% no-repeat;
    z-index: 1;                      /* ...and the frame is laid over it, hiding the video's edges */
    pointer-events: none;            /* clicks go through to the video */
}

/* Layers under the frame image, bottom to top:
     ::before     the frame's solid silhouette, casting its shadow on the wall.
                  It's wordmark gold, so if the frame image ever fails to load,
                  a gold frame of the same shape shows in its place.
     .frame-glow  the same silhouette glowing gold on hover (js/previews.js adds it)
     .ratio       the thumbnail / video
   The frame image and the picture hide both silhouettes; only the shadow and
   the glow spilling past the frame's real outer edge show. */
.exhibit-frame::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    background: var(--frame-sil) center / 100% 100% no-repeat;
    pointer-events: none;
    filter: drop-shadow(0 1.2vw 1.2vw rgba(0, 0, 0, 0.6));   /* shadow on the wall */
}

/* Stand-in until the real videos are embedded */
.video-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgba(255, 255, 255, 0.6);
    font: 600 clamp(0.75rem, 1.3vw, 1.4rem) system-ui, sans-serif;
}

.exhibit-label {
    grid-row: 1;
    grid-column: 3;
    justify-self: start;
    width: var(--card-w);
    height: auto;
    margin-left: var(--label-gap);
    /* sits low on the wall, near the bottom of the frame, like a museum card */
    margin-bottom: calc(var(--frame-border) * 0.5);
    box-shadow: 0 0.4vw 1vw rgba(0, 0, 0, 0.5);
}

.exhibit.label-left .exhibit-label {
    grid-column: 1;
    justify-self: end;
    margin-left: 0;
    margin-right: var(--label-gap);
}

/* ---------- Smaller frames ---------- */
.exhibit-small {
    --slot-w: var(--frame-small);
    grid-template-columns: var(--frame-w);
    position: relative;            /* the card hangs off its outside edge */
    width: var(--frame-w);
    margin: 0 auto var(--exhibit-gap);
}

.exhibit-small .exhibit-frame {
    grid-column: 1;
}

/* The card hangs on the wall just outside the frame. It's taken out of the
   layout so it can sit in the side space without pushing the frames around. */
.exhibit-small .exhibit-label {
    position: absolute;
    bottom: 0;
    left: calc(100% + var(--label-gap));
    margin: 0 0 calc(var(--frame-border) * 0.5);
}

.exhibit-small.label-left .exhibit-label {
    left: auto;
    right: calc(100% + var(--label-gap));
    margin-right: 0;
}

/* Two columns of smaller frames:
     left:  frame 6 / A Little Love (card below it), then 7 (card on its left)
     right: frame 5 / Palumbo 2 (card on its right), "Coming soon", then 8
            (card below it)
   The columns are as wide as their top frames, and their tops line up.
   Frame 7 is centered under frame 6 (it's a bit wider, so it reaches a
   few pixels past that column's edges). */
.exhibit-pair {
    --w-left: calc(var(--frame-small) * 1.1077);   /* frame 6's width (its --frame-fit) */
    --w-right: calc(var(--frame-small) * 1.0276);  /* frame 5's width */

    display: grid;
    grid-template-columns: var(--w-left) var(--w-right);
    column-gap: var(--trio-gap);
    justify-content: center;
    align-items: start;
    margin: 0 auto var(--exhibit-gap);
}
.exhibit-col {
    display: flex;
    flex-direction: column;
    align-items: center;              /* frames share their column's center line */
    min-width: 0;
}

.exhibit-col .exhibit-small {
    margin: 0 0 var(--exhibit-gap);
}
.exhibit-col > :last-child {
    margin-bottom: 0;
}

/* "label-below": the card sits under the frame instead of beside it,
   centered under it */
.exhibit-small.label-below {
    row-gap: clamp(0.75rem, 2vh, 1.25rem);
}
.exhibit-col .exhibit-small.label-below .exhibit-label {
    position: relative;              /* in the flow, but still on the card layer */
    inset: auto;                     /* drop the side-hung cards' offsets */
    grid-row: 2;
    grid-column: 1;
    justify-self: center;
    width: var(--card-w);
    max-width: 100%;
    margin: 0;
}

/* Palumbo 2's card sits under its frame, so the gap below it is shortened:
   "Coming soon" and the poster only move down a little to make room */
.exhibit-col .exhibit-small.frame-5 {
    margin-bottom: calc(var(--exhibit-gap) * 0.4);
}

.exhibit-col .coming-soon {
    font-size: clamp(1.1rem, 3.6vw, 3.5rem);   /* fits a narrow column on phones */
}

/* ---------- Tablets & phones: narrower than 1200px, or held upright ----------
   There isn't room beside the frames, so frames grow and every card moves
   underneath its frame, on the same side it would hang on a wide screen. */
@media (max-width: 1199.98px), (orientation: portrait) {
    :root {
        --frame-full: 86vw;
        --trio-w: 84vw;          /* the 5+6 pair fits inside the page padding */
        --card-w: calc(var(--frame-full) * 0.4);
    }
    .exhibit {
        row-gap: clamp(0.75rem, 3vw, 1.5rem);
    }
    .exhibit.frame-3 {
        --frame-fit: 1.065;          /* as wide as the page allows */
    }
    /* no extra size adjustments: frames already fill the width here */
    .exhibit.exhibit-hero,
    .exhibit.frame-3,
    .exhibit.frame-4 {
        --scale: 1;
    }
    .exhibit .exhibit-label {
        grid-row: 2;
        grid-column: 2;
        justify-self: end;
        margin: 0;
    }
    .exhibit.label-left .exhibit-label {
        grid-column: 2;
        justify-self: start;
        margin: 0;
    }
    .exhibit-small .exhibit-label,
    .exhibit-small.label-left .exhibit-label,
    .exhibit-col .exhibit-small .exhibit-label {
        position: relative;          /* in the flow, but still on the card layer */
        inset: auto;                 /* drop the side-hung cards' offsets */
        grid-column: 1;
        width: var(--card-w);
        max-width: 100%;
    }
}

/* ---------- Phones & tablets: their own layout ----------
   Everything in here applies ONLY to screens narrower than 1200px or in
   portrait orientation (taller than wide): phones and tablets either way
   up. A computer screen in landscape, 1200px or wider, keeps the layout
   above untouched. On a narrow screen every card sits centered beneath
   its painting at a readable size, and frames 5-8 stack in a single column
   (two columns would be too narrow to hold readable cards underneath). */
@media (max-width: 1199.98px), (orientation: portrait) {
    :root {
        --card-w: min(52vw, 15rem);  /* about 200px on a phone */
    }

    /* every card: centered under its frame */
    .exhibit .exhibit-label,
    .exhibit.label-left .exhibit-label {
        justify-self: center;
    }
    .exhibit {
        row-gap: clamp(1rem, 4vw, 1.5rem);
    }

    /* frames 5-8: one column, in frame order (Palumbo 2, A Little Love,
       Reflections, "Coming soon", Vat '26) */
    .exhibit-pair {
        display: flex;
        flex-direction: column;
        align-items: center;
    }
    .exhibit-col {
        display: contents;           /* the columns step aside; their contents line up in one */
    }
    .exhibit-pair .exhibit-col .exhibit-small {
        --slot-w: 78vw;              /* most of the screen width */
        margin: 0 0 var(--exhibit-gap);
    }
    .exhibit-pair .exhibit-col .frame-8 {
        margin-bottom: 0;
    }
    .exhibit-pair .frame-5    { order: 1; }
    .exhibit-pair .frame-6    { order: 2; }
    .exhibit-pair .frame-7    { order: 3; }
    .exhibit-pair .coming-soon { order: 4; font-size: clamp(1.6rem, 6vw, 2.5rem); }
    .exhibit-pair .frame-8    { order: 5; }
}

/* ---------- "Coming soon" text ---------- */
.coming-soon {
    margin: 0 0 clamp(1.25rem, 4vh, 2.5rem);
    font-family: "Fraunces", Georgia, serif;
    font-weight: 800;
    font-style: italic;
    font-size: clamp(1.6rem, 3.6vw, 3.5rem);
    letter-spacing: 0.02em;
    line-height: 1.1;
    text-align: center;
    color: var(--name-gold);
    text-shadow: 0 0.06em 0.2em rgba(0, 0, 0, 0.6);
}

/* ---------- Placeholder thumbnails in the frames ---------- */
/* Solid red stand-in until real thumbnails exist, with a play symbol so it
   reads as something to click */
.video-thumb {
    display: flex;
    align-items: center;
    justify-content: center;
    background: #b3121b;
}
.video-thumb::before {
    content: "";
    position: absolute;
    width: 18%;
    aspect-ratio: 1;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.35);
    box-shadow: 0 0.3em 0.9em rgba(0, 0, 0, 0.35);
    transition: transform 0.2s ease;
}
.video-thumb::after {
    content: "";
    position: absolute;
    width: 7%;
    aspect-ratio: 1;
    margin-left: 1.2%;               /* a play triangle looks centered when nudged right */
    background: rgba(255, 255, 255, 0.92);
    clip-path: polygon(0 0, 100% 50%, 0 100%);
    transition: transform 0.2s ease;
}

/* ---------- Film gallery (js/gallery.js) ---------- */
/* Frames and cards on the wall open the gallery */
.exhibit-frame[role="button"],
.exhibit-label {
    cursor: pointer;
}
.exhibit-frame[role="button"]:hover .video-thumb::before,
.exhibit-frame[role="button"]:hover .video-thumb::after,
.exhibit-frame[role="button"]:focus-visible .video-thumb::before,
.exhibit-frame[role="button"]:focus-visible .video-thumb::after {
    transform: scale(1.12);
}
.exhibit-frame[role="button"]:focus-visible {
    outline: 0.2rem solid var(--wordmark-gold);
    outline-offset: 0.3rem;
}
.exhibit-label {
    /* cards hang on a layer above the frames' wall shadows and hover glow,
       so a frame never darkens a card beneath it */
    position: relative;
    z-index: 3;
    /* if the card image doesn't load, a plain white card of the same shape */
    aspect-ratio: 16 / 9;
    background: #fff;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.exhibit-label:hover,
.exhibit-label:focus-visible {
    transform: translateY(-0.2rem);
    box-shadow: 0 0.8vw 1.6vw rgba(0, 0, 0, 0.6);
}
.exhibit-label:focus-visible {
    outline: 0.2rem solid var(--wordmark-gold);
    outline-offset: 0.2rem;
}

/* The darkened page with the film and its card.
   The film gets every bit of space the arrows, the card and the edges don't
   need: its width and height limits below are worked out from these sizes. */
.gallery {
    --g-arrow: clamp(2.5rem, 5vw, 4rem);         /* arrow button size */
    --g-gap: clamp(0.5rem, 1.5vw, 1.5rem);       /* space between arrows and film */
    --g-pad-x: clamp(0.5rem, 1.5vw, 1.5rem);     /* space at the screen's sides */
    --g-pad-top: clamp(1rem, 3vh, 2rem);         /* the × sits above the right arrow, not the film */
    --g-pad-bottom: clamp(0.75rem, 2.5vh, 1.5rem);
    --g-stack-gap: clamp(0.5rem, 1.5vh, 1rem);   /* between film and card */
    /* card: never smaller than ~240px wide, so its small lines stay readable */
    --g-card-w: clamp(15rem, 17vw, 20rem);
    --g-card-h: calc(var(--g-card-w) * 9 / 16);

    /* the most room the film can have */
    --g-max-w: calc(100vw - 2 * (var(--g-pad-x) + var(--g-arrow) + var(--g-gap)) - 1rem);
    --g-max-h: calc(100svh - var(--g-pad-top) - var(--g-pad-bottom) - var(--g-stack-gap) - var(--g-card-h));

    position: fixed;
    inset: 0;
    z-index: 3000;                   /* above the header and everything else */
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--g-gap);
    padding: var(--g-pad-top) var(--g-pad-x) var(--g-pad-bottom);
    background: rgba(0, 0, 0, 0.9);
    animation: gallery-fade 0.2s ease;
}
.gallery[hidden] {
    display: none;
}
@keyframes gallery-fade {
    from { opacity: 0; }
}

.gallery-stage {
    margin: 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--g-stack-gap);
}

/* A fixed-size screen area above the card: the same size for every film, so
   the card and arrows never move. Each film is as large as fits inside it,
   at its own shape, and centered in it. */
.gallery-screen {
    flex: none;
    width: var(--g-max-w);
    height: var(--g-max-h);
    display: flex;
    align-items: center;
    justify-content: center;
}
.gallery-media {
    --aspect: 16 / 9;                /* set per film from data-aspect */
    aspect-ratio: var(--aspect);
    width: min(100%, calc(var(--g-max-h) * (var(--aspect))));
    background: var(--bg-fallback);  /* dark brown until the player loads */
    box-shadow: 0 1.5vw 4vw rgba(0, 0, 0, 0.7);
}
.gallery-media iframe,
.gallery-media video,
.gallery-media img {
    display: block;
    width: 100%;
    height: 100%;
    border: 0;
    object-fit: contain;
}

.gallery-card {
    flex: none;
    width: var(--g-card-w);
    height: auto;
    aspect-ratio: 16 / 9;            /* white card of the same shape if the image doesn't load */
    background: #fff;
    box-shadow: 0 0.6vw 1.6vw rgba(0, 0, 0, 0.6);
}
.gallery-card[hidden] {
    display: none;
}

/* A written description in the card's place (works page): title largest,
   the role beneath it, then any extra details. It uses the space the card
   would, so films stay the same size and in the same place. */
.gallery-info {
    flex: none;
    width: var(--g-max-w);
    height: var(--g-card-h);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap: 0.35em;
    overflow: hidden;
    text-align: center;
    color: var(--name-gold);
    font-family: "Fraunces", Georgia, serif;
}
.gallery-info[hidden],
.gallery-info [hidden] {
    display: none;
}
.gallery-info-title {
    margin: 0;
    font-weight: 900;
    font-size: clamp(1.4rem, 2.4vw, 2.6rem);
    line-height: 1.1;
    letter-spacing: 0.01em;
    text-wrap: balance;
}
.gallery-info-role {
    margin: 0;
    font-style: italic;
    font-weight: 500;
    font-size: clamp(1rem, 1.4vw, 1.5rem);
    line-height: 1.25;
}
.gallery-info-text {
    margin: 0.25em 0 0;
    font-weight: 400;
    font-size: clamp(0.9rem, 1.1vw, 1.2rem);
    line-height: 1.35;
    opacity: 0.85;
}

/* "3 / 8" sits in the top-left corner, opposite the ×, so it costs no height */
.gallery-count {
    position: absolute;
    top: clamp(0.75rem, 2vh, 1.5rem);
    left: clamp(0.75rem, 2vw, 1.5rem);
    color: rgba(255, 255, 255, 0.7);
    font: 0.95rem/1.4 system-ui, sans-serif;
}

/* Arrows and close button */
.gallery-arrow,
.gallery-close {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
    line-height: 1;
    cursor: pointer;
    transition: background 0.15s ease;
}
.gallery-arrow:hover,
.gallery-close:hover {
    background: rgba(255, 255, 255, 0.25);
}
.gallery-arrow:focus-visible,
.gallery-close:focus-visible {
    outline: 0.15rem solid var(--wordmark-gold);
    outline-offset: 0.15rem;
}
.gallery-arrow {
    width: clamp(2.5rem, 5vw, 4rem);
    height: clamp(2.5rem, 5vw, 4rem);
    font-size: clamp(1.8rem, 3.5vw, 3rem);
    padding-bottom: 0.15em;          /* the arrow glyphs sit low; nudge them to center */
}
.gallery-close {
    position: absolute;
    top: clamp(0.75rem, 2vh, 1.5rem);
    right: clamp(0.75rem, 2vw, 1.5rem);
    width: clamp(2.5rem, 4vw, 3.25rem);
    height: clamp(2.5rem, 4vw, 3.25rem);
    font-size: clamp(1.6rem, 2.6vw, 2.2rem);
    padding-bottom: 0.1em;
}

/* Phones: the film takes the full width and the arrows move below the card,
   so the height budget also covers the × above and the arrow row below */
@media (max-width: 575.98px) {
    .gallery {
        --g-pad-top: 4rem;
        --g-card-w: min(75vw, 20rem);
        --g-max-w: calc(100vw - 2 * var(--g-pad-x));
        --g-max-h: calc(100svh - var(--g-pad-top) - var(--g-pad-bottom)
                        - 2 * var(--g-stack-gap) - var(--g-card-h) - var(--g-arrow) - var(--g-gap));
        flex-wrap: wrap;
        align-content: center;
    }
    .gallery-stage {
        order: -1;
        flex: 0 0 100%;
    }
}

/* ---------- Thumbnails and hover previews (js/previews.js) ---------- */
/* A still thumbnail fills the opening; a short silent clip sits on top of it,
   invisible until the frame is hovered, then fades in and loops */
.exhibit-thumb,
.exhibit-loop {
    object-fit: cover;
}
.exhibit-loop {
    opacity: 0;
    transition: opacity 0.25s ease;  /* a quick, soft cross-fade from the still */
    pointer-events: none;
}
.exhibit-frame.is-previewing .exhibit-loop {
    opacity: 1;
}

/* Hovering a frame: a glow in the wordmark gold around the frame's OUTER
   edge only, following its real shape (carved corners included). It comes
   from the filled silhouette, so the opening never glows. Only its opacity
   changes, so it fades in smoothly without redrawing anything. */
.frame-glow {
    position: absolute;
    inset: 0;
    z-index: 0;
    background: var(--frame-sil) center / 100% 100% no-repeat;
    pointer-events: none;
    filter:
        drop-shadow(0 0 0.35vw rgba(239, 225, 13, 0.85))
        drop-shadow(0 0 1.1vw rgba(239, 225, 13, 0.45));
    opacity: 0;
    transition: opacity 0.25s ease;
}
/* mouse hover only on devices with a real mouse (on touch screens a tap
   would leave it stuck on); touch screens use .is-touching from js/previews.js */
@media (hover: hover) {
    .exhibit-frame:hover .frame-glow {
        opacity: 1;
    }
}
.exhibit-frame:focus-visible .frame-glow,
.exhibit-frame.is-touching .frame-glow {
    opacity: 1;
}

/* holding a finger on a frame previews it, so don't pop up the phone's
   long-press menu or start selecting text */
.exhibit-frame {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
}

/* ---------- About section (home page) ---------- */
/* Section heading: same look as the works page's category titles */
.section-title {
    margin: 0 0 clamp(1.5rem, 4vh, 2.75rem);
    font-family: "Fraunces", Georgia, serif;
    font-weight: 900;
    font-size: clamp(2.25rem, 6vw, 5.5rem);
    line-height: 1.05;
    letter-spacing: 0.02em;
    text-align: center;
    color: var(--name-gold);
    text-shadow: 0 0.04em 0.15em rgba(0, 0, 0, 0.6);
}

.about {
    width: min(92vw, 80rem);
    margin: 0 auto;
    padding: clamp(1rem, 4vh, 3rem) 0 clamp(3rem, 10vh, 7rem);
    /* the sticky header mustn't cover the heading when the ABOUT link jumps here */
    scroll-margin-top: var(--header-h);
}

/* paragraph on the left, photo on the right */
.about-body {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(1.5rem, 4vw, 4rem);
    align-items: start;              /* text and photo share a top edge */
}
.about-text {
    margin: 0;
    font-family: "Fraunces", Georgia, serif;
    font-size: clamp(1rem, 1.25vw, 1.35rem);
    line-height: 1.6;
    text-align: justify;             /* words spread out to meet both edges */
    hyphens: manual;                 /* never break a word across lines */
    -webkit-hyphens: manual;
    color: var(--name-gold);
    text-shadow: 0 0.05em 0.2em rgba(0, 0, 0, 0.6);
}
/* two paragraphs in one block, a blank line's space between them */
.about-text p {
    margin: 0;
}
.about-text p + p {
    margin-top: 1em;
}
/* side by side, js/site.js sizes the text so the block is exactly as tall
   as the photo; the first and last lines meet its top and bottom edges */
.about-text.is-fitted {
    line-height: 1.5;
}
.about-photo {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 1600 / 1066;       /* keeps its space while loading */
    object-fit: cover;
    background: var(--bg-fallback);
    border-radius: 0.25rem;
    box-shadow: 0 1vw 2.5vw rgba(0, 0, 0, 0.6);
}

/* phones, tablets, narrow windows: paragraph first, photo below it */
@media (max-width: 1199.98px), (orientation: portrait) {
    .about-body {
        grid-template-columns: 1fr;
    }
    /* lines this short can't be justified without big gaps between words */
    .about-text {
        text-align: left;
    }
}

/* ---------- Contact section (home page) ---------- */
.contact {
    width: 92vw;                    /* spans the screen, with a small margin each side */
    margin: 0 auto;
    padding: clamp(1rem, 4vh, 3rem) 0 clamp(3rem, 10vh, 7rem);
    scroll-margin-top: var(--header-h);
}

.contact-form {
    display: flex;
    flex-direction: column;
    font-family: "Fraunces", Georgia, serif;
}
.contact-label {
    margin: clamp(1rem, 2.5vh, 1.5rem) 0 0.4rem;
    font-size: clamp(1rem, 1.25vw, 1.35rem);
    font-weight: 700;
    color: var(--name-gold);
    text-shadow: 0 0.05em 0.2em rgba(0, 0, 0, 0.6);
}
.contact-label:first-child {
    margin-top: 0;
}
.contact-field {
    width: 100%;
    padding: 0.75em 0.9em;
    border: 0.1rem solid rgba(238, 242, 192, 0.45);
    border-radius: 0.3rem;
    background: rgba(238, 242, 192, 0.92);   /* cream, so typing is easy to read */
    color: var(--bg-fallback);               /* the dark brown */
    font: inherit;
    font-size: clamp(1rem, 1.1vw, 1.2rem);
    box-shadow: inset 0 0.1rem 0.3rem rgba(0, 0, 0, 0.2);
}
.contact-field:focus {
    outline: 0.15rem solid var(--wordmark-gold);
    outline-offset: 0.1rem;
}
.contact-message {
    min-height: 12rem;
    resize: vertical;
}
/* after a failed Send, mark the fields that still need fixing */
.contact-form.was-checked .contact-field:invalid {
    border-color: #ff6b5e;
    box-shadow: 0 0 0 0.15rem rgba(255, 107, 94, 0.5);
}

.contact-honey {
    position: absolute;
    left: -9999px;                   /* off screen: only bots find it */
}
.contact-send:disabled {
    opacity: 0.6;
    cursor: wait;
}

.contact-actions {
    display: flex;
    flex-direction: column;          /* full-width Send, its status message underneath */
    gap: 1rem;
    margin-top: clamp(1.25rem, 3vh, 2rem);
}
.contact-send {
    width: 100%;
    padding: 0.8em 1em;
    border: 0.1em solid var(--wordmark-gold);
    border-radius: 0.3em;
    background: var(--wordmark-gold);        /* gold by default... */
    color: #001C55;                          /* ...with navy lettering */
    /* the wordmark's font, in capitals, like the header links */
    font-family: "Cario", Georgia, serif;
    font-weight: 600;
    font-size: clamp(1.1rem, 1.5vw, 1.6rem);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    cursor: pointer;
    transition: background 0.2s ease, color 0.2s ease;
}
.contact-send:hover,
.contact-send:focus-visible {
    background: transparent;                 /* on hover: just the gold outline and lettering */
    color: var(--wordmark-gold);
}
.contact-send:focus-visible {
    background: transparent;
    color: var(--wordmark-gold);
}
.contact-send:focus-visible {
    outline: 0.15rem solid #fff;
    outline-offset: 0.15rem;
}
.contact-status {
    margin: 0;
    font-size: clamp(0.95rem, 1.1vw, 1.15rem);
    color: var(--name-gold);
    text-shadow: 0 0.05em 0.2em rgba(0, 0, 0, 0.6);
}

/* ---------- Contact details + social icons (under the contact form) ---------- */
.contact-card {
    margin-top: clamp(3rem, 9vh, 6rem);
    scroll-margin-top: calc(var(--header-h) + 1.5rem);   /* the LINKS header link lands here */
    text-align: center;
    color: var(--name-gold);
    text-shadow: 0 0.05em 0.2em rgba(0, 0, 0, 0.6);
}
.contact-card p {
    margin: 0;
}
/* the name again, in the wordmark's font and gold */
.contact-card-name {
    font-family: "Cario", Georgia, serif;
    font-weight: 600;
    font-size: clamp(1.75rem, 4vw, 3.5rem);
    letter-spacing: 0.06em;
    line-height: 1.1;
    color: var(--wordmark-gold);
    margin-bottom: clamp(0.75rem, 2vh, 1.25rem) !important;
}
.contact-card-line,
.contact-card-refs {
    font-family: "Fraunces", Georgia, serif;
    font-size: clamp(1rem, 1.3vw, 1.4rem);
    line-height: 1.7;
}
.contact-card-line a {
    color: inherit;
    text-decoration: none;
    border-bottom: 0.06em solid transparent;
    transition: border-color 0.2s ease;
}
.contact-card-line a:hover,
.contact-card-line a:focus-visible {
    border-bottom-color: currentColor;
}
.contact-card-refs {
    margin-top: clamp(0.75rem, 2vh, 1.25rem) !important;
    font-size: clamp(0.85rem, 1vw, 1.1rem);
    font-weight: 700;
    letter-spacing: 0.12em;
}

.social-icons {
    display: flex;
    justify-content: center;
    gap: clamp(1.5rem, 4vw, 3rem);
    margin: clamp(1.5rem, 4vh, 2.5rem) 0 0;
    padding: 0;
    list-style: none;
}
.social-icon {
    position: relative;
    display: block;
    width: clamp(2.25rem, 3.2vw, 3rem);
    aspect-ratio: 1;
    filter: drop-shadow(0 0.1rem 0.25rem rgba(0, 0, 0, 0.5));
    transition: transform 0.2s ease;
}
/* the cream icon, with its coloured version on top fading in on hover,
   so the colour seems to fill the icon */
.social-icon img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
}
.social-icon .icon-hover {
    opacity: 0;
    transition: opacity 0.3s ease;
}
.social-icon:hover .icon-hover,
.social-icon:focus-visible .icon-hover {
    opacity: 1;
}
.social-icon:hover,
.social-icon:focus-visible {
    transform: translateY(-0.15rem);
}
.social-icon:focus-visible {
    outline: 0.15rem solid #fff;
    outline-offset: 0.3rem;
    border-radius: 0.3rem;
}

/* Second header logo (Mindhammer), right beside the Sun Dog logo. Its solid
   letters are drawn a bit shorter so the two logos look balanced. Below
   600px wide there's no room for both left of the centered name, so it hides. */
.site-logo-mh {
    height: 58%;
    margin-left: clamp(0.6rem, 1.2vw, 1.25rem);
}
@media (max-width: 599.98px) {
    .site-logo-mh {
        display: none;
    }
}

/* ---------- Sun dog pictures either side of the contact details ----------
   sundogv7 (night) on the left and right, the right one mirrored so both
   face the middle; hovering either cross-fades it to sundogv8 (day). */
.contact-card {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    grid-template-areas: "left info right";
    align-items: center;
    column-gap: clamp(1.5rem, 4vw, 4rem);
}
.contact-card-info { grid-area: info; }
.sundog-left  { grid-area: left;  justify-self: end; }
.sundog-right { grid-area: right; justify-self: start; }

.sundog {
    position: relative;
    width: clamp(6rem, 11vw, 13rem);
    aspect-ratio: 605 / 700;
    filter: drop-shadow(0 0.6vw 1.2vw rgba(0, 0, 0, 0.55));
}
.sundog img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
}
.sundog-mirrored img {
    transform: scaleX(-1);           /* faces the middle */
}
.sundog .sundog-hover {
    opacity: 0;
    transition: opacity 0.4s ease;
}
/* computers: cross-fade while the mouse is over it */
@media (hover: hover) {
    .sundog:hover .sundog-hover {
        opacity: 1;
    }
}
/* touch screens: each tap flips it instantly (js/site.js adds .is-flipped) */
.sundog.is-flipped .sundog-hover {
    opacity: 1;
}
.sundog.is-tapped .sundog-hover {
    transition: none;                /* a hard switch, no fade */
}

/* Phones: no room either side of the details, so the pair sits underneath,
   side by side, still facing each other */
@media (max-width: 575.98px) {
    .contact-card {
        grid-template-columns: 1fr 1fr;
        grid-template-areas:
            "info info"
            "left right";
        row-gap: 2rem;
        column-gap: 1.25rem;
    }
    .sundog {
        width: min(36vw, 9rem);
    }
}

/* ---------- Phones & tablets: nothing may be wider than the screen ----------
   The About and Contact sections fill the page's width (inside its side
   padding) instead of 92% of the screen plus that padding, and nothing is
   allowed to push the page sideways. Computers are unaffected. */
@media (max-width: 1199.98px), (orientation: portrait) {
    body {
        overflow-x: clip;
    }
    .about,
    .contact {
        width: 100%;
    }
}
