/* ========================================
   HOME — VIEWFINDER HERO

   The organising idea: an FPV pilot flies looking at an OSD —
   telemetry pinned to the edges of the goggle frame, never across
   the middle of the shot. So this screen is the viewfinder. Corner
   brackets mark the frame, controls hug the corners, and the whole
   centre stays empty for the footage.

   Two type roles, deliberately opposed:
     Fraunces  the two service names — the only warm, drawn thing
               on the screen, so the eye lands there first
     mono      every label around them — the instrument vernacular
               this subject actually uses

   Everything below the hero is unchanged and still uses the
   shared components.
   ======================================== */

body {
    /* Almost none. With no copy over the footage there is nothing to
       protect, so the video runs close to full strength; the corner
       clusters get their own local vignette below instead of dimming
       the entire frame. */
    --scrim: 0.2;
}

.bg-poster {
    background-image: url('/images/herobg-poster.jpg');
    background-size: cover;
    background-position: center;
}


/* ============================================================
   FRAME
   ============================================================ */
.viewfinder {
    position: relative;
    min-height: 100svh;
    margin-block-start: calc(-1 * var(--nav-height));
    padding: calc(var(--nav-height) + var(--space-6)) var(--gutter) var(--space-8);
    display: grid;
    grid-template-columns: auto auto;
    grid-template-rows: 1fr auto;
    align-items: end;
    overflow: hidden;
}

/* Local vignette. Keeps the bottom clusters legible without putting
   a scrim over the whole shot — the sky and horizon stay bright. */
.viewfinder::after {
    content: '';
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    height: 46%;
    background: linear-gradient(to top, rgba(4, 4, 4, 0.78) 0%, rgba(4, 4, 4, 0.28) 45%, transparent 100%);
    pointer-events: none;
    z-index: 0;
}

.viewfinder > * {
    position: relative;
    z-index: var(--z-base);
}


/* ---- Corner brackets ---- */
.vf-frame {
    position: absolute;
    /* Twice the nav height: the hero is pulled up by -nav-height, so an
       inset of nav+16 put the top brackets 16px from the top of the
       screen — behind an 80px nav. This was wrong on desktop too. */
    inset: calc(var(--nav-height) * 2 + var(--space-2)) var(--gutter) var(--space-6);

    /* ---- Sit the brackets OUTSIDE the content, not on it ----

       .viewfinder pads its content by --gutter and this frame was
       inset by --gutter too, so the left and right brackets landed on
       exactly the same x as .vf-entries and .vf-aside — flush against
       them at every width, by construction rather than by accident. A
       viewfinder bracket reads as a frame around the shot; touching
       the thing it frames makes it read as a border on a box.

       Pulled out by --space-5, with max() as the floor. The gutter
       collapses to 20px on a phone, where subtracting 24 would put
       the brackets past the edge of the screen — and a bracket needs
       its own margin from the viewport as much as from the copy. The
       floor concedes clearance there instead, which is the right way
       round: on a narrow screen the frame is close to everything
       anyway. */
    inset-inline: max(var(--space-3), calc(var(--gutter) - var(--space-5)));

    pointer-events: none;
    z-index: var(--z-base);
}

.vf-corner {
    position: absolute;
    width: 22px;
    height: 22px;
    border: 1px solid var(--edge-bone);
    opacity: 0.55;
}

.vf-corner--tl { top: 0;    left: 0;  border-inline-end: 0; border-block-end: 0; }
.vf-corner--tr { top: 0;    right: 0; border-inline-start: 0; border-block-end: 0; }
.vf-corner--bl { bottom: 0; left: 0;  border-inline-end: 0; border-block-start: 0; }
.vf-corner--br { bottom: 0; right: 0; border-inline-start: 0; border-block-start: 0; }


/* ============================================================
   SERVICE ENTRIES — bottom left
   ============================================================ */
.vf-entries {
    grid-column: 1;
    grid-row: 2;
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
    justify-self: start;
}

.vf-entry {
    display: block;
    width: fit-content;
    padding-block-start: var(--space-3);
    /* The rule is the entry's own baseline: it grows on hover, so the
       hit target announces itself without a box or a fill. */
    border-block-start: 1px solid var(--edge-soft);
    transition: border-color var(--dur-mid) var(--ease-out);
}

.vf-entry:hover {
    border-block-start-color: var(--bone-300);
}

.vf-entry-meta {
    display: block;
    font-family: var(--font-mono);
    font-size: var(--fs-micro);
    letter-spacing: var(--track-label);
    text-transform: uppercase;
    color: var(--text-lo);
    margin-block-end: var(--space-2);
    transition: color var(--dur-mid) var(--ease-out);
}

.vf-entry:hover .vf-entry-meta {
    color: var(--bone-400);
}

.vf-entry-name {
    display: inline-flex;
    align-items: baseline;
    gap: var(--space-3);
    font-family: var(--font-display);
    font-variation-settings: var(--display-axes);
    font-size: clamp(2rem, 4.4vw, 3.5rem);
    font-weight: var(--weight-semi);
    letter-spacing: var(--track-display);
    line-height: 1;
    color: var(--text-hi);
    transition: color var(--dur-mid) var(--ease-out);
}

.vf-entry:hover .vf-entry-name {
    color: var(--bone-200);
}

.vf-arrow {
    width: 0.42em;
    height: 0.42em;
    flex-shrink: 0;
    align-self: center;
    color: var(--bone-400);
    transition: transform var(--dur-mid) var(--ease-out);
}

.vf-entry:hover .vf-arrow {
    transform: translate(3px, -3px);
}

.vf-entry:focus-visible {
    outline: 2px solid var(--bone-300);
    outline-offset: 6px;
}


/* ============================================================
   ASIDE — bottom right: sound, then feeds
   ============================================================ */
.vf-aside {
    grid-column: 2;
    grid-row: 2;
    justify-self: end;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: var(--space-5);
}

/* ---- Rules between the three rows ----

   The cluster was three right-aligned items of different widths with
   nothing but a gap between them: legible, but ragged, and the review
   mark's own hairline only spanned its own text so it read as an
   underline rather than a divider.

   Both lower rows now stretch to the cluster's width — set by whichever
   row is widest, which is Follow — so their rules run the same length
   and the cluster reads as a small ledger: sound, then the ask, then
   the feeds. Type stays right-aligned inside them, so the ragged edge
   is on the left where it belongs.

   No rule above Sound. Three lines would make a table out of what is
   meant to be a quiet corner, and the top edge is already implied by
   the vignette. */
.vf-aside .review-mark,
.vf-aside .vf-social {
    width: 100%;
}

/* text-align, not just width. The mark's label line is a flex row
   that justifies itself to the end, but its value line is
   inline-flex — an inline box, positioned by the parent's text
   alignment. Widening the block without this sends the label right
   and the action left, splitting the two halves of one object. */
.vf-aside .review-mark {
    text-align: right;
}

.vf-aside .vf-social {
    justify-content: flex-end;
    padding-block-start: var(--space-3);
    border-block-start: 1px solid var(--edge-soft);
}

/* ---- Sound ---- */
.vf-sound {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);
    padding: 0;
    font-family: var(--font-mono);
    font-size: var(--fs-micro);
    letter-spacing: var(--track-label);
    text-transform: uppercase;
    color: var(--text-lo);
    transition: color var(--dur-mid) var(--ease-out);
}

.vf-sound:hover {
    color: var(--bone-300);
}

.vf-sound.is-hidden {
    opacity: 0;
    pointer-events: none;
}

/* Three bars that idle flat and rise while sound is available —
   a level meter, which is what an OSD would actually show. */
.vf-bars {
    display: inline-flex;
    align-items: flex-end;
    gap: 2px;
    height: 11px;
}

.vf-bars i {
    display: block;
    width: 2px;
    height: 3px;
    background: var(--bone-400);
    animation: vf-level 1.1s var(--ease-in-out) infinite;
}

.vf-bars i:nth-child(2) { animation-delay: 0.16s; }
.vf-bars i:nth-child(3) { animation-delay: 0.32s; }

@keyframes vf-level {
    0%, 100% { height: 3px; }
    50%      { height: 11px; }
}

/* ---- Feeds ---- */
.vf-social {
    display: flex;
    align-items: center;
    gap: var(--space-4);
}

.vf-social-label {
    font-family: var(--font-mono);
    font-size: var(--fs-micro);
    letter-spacing: var(--track-label);
    text-transform: uppercase;
    color: var(--text-faint);
    /* Hairline tying the label to the marks */
    padding-inline-end: var(--space-4);
    border-inline-end: 1px solid var(--edge-faint);
}

.vf-social a {
    font-size: var(--fs-lg);
    line-height: 1;
    color: var(--text-mid);
    transition:
        color var(--dur-mid) var(--ease-out),
        transform var(--dur-mid) var(--ease-out);
}

.vf-social a:hover {
    color: var(--bone-300);
    transform: translateY(-3px);
}


/* ============================================================
   SCROLL CUE — centre bottom, no label
   ============================================================ */
.vf-cue {
    grid-column: 1 / -1;
    grid-row: 2;
    justify-self: center;
    align-self: end;
    width: 1px;
    height: 46px;
    background: linear-gradient(to bottom, transparent, var(--edge-bone));
    animation: vf-cue 2.8s var(--ease-in-out) infinite;
    pointer-events: none;
}

@keyframes vf-cue {
    0%, 100% { opacity: 0.2; transform: scaleY(0.55); transform-origin: bottom; }
    50%      { opacity: 0.9; transform: scaleY(1);    transform-origin: bottom; }
}


/* ============================================================
   TAP TARGET — touch devices enable sound anywhere
   ============================================================ */
.tap-overlay {
    position: absolute;
    inset: 0;
    z-index: 0;
    background: transparent;
    border: none;
    cursor: pointer;
}

.tap-overlay.is-hidden {
    display: none;
}

/* Desktop enables sound on first click anywhere, handled in
   bg-video.js — the overlay is only needed on touch. */
@media (min-width: 769px) {
    .tap-overlay {
        display: none;
    }
}


/* ============================================================
   ACQUIRE — the frame comes up like a feed locking on.
   One short sequence on load, nothing after.
   ============================================================ */
@media (prefers-reduced-motion: no-preference) {
    .vf-corner,
    .vf-entry,
    .vf-aside,
    .vf-cue {
        animation: vf-in var(--dur-slow) var(--ease-out) backwards;
    }

    .vf-corner            { animation-delay: 0.10s; }
    .vf-entry:nth-child(1){ animation-delay: 0.34s; }
    .vf-entry:nth-child(2){ animation-delay: 0.44s; }
    .vf-aside             { animation-delay: 0.54s; }
    .vf-cue               { animation-delay: 0.70s; }

    /* The cue keeps its own loop once it has arrived */
    .vf-cue {
        animation:
            vf-in var(--dur-slow) var(--ease-out) 0.70s backwards,
            vf-cue 2.8s var(--ease-in-out) 1.2s infinite;
    }
}

@keyframes vf-in {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}


/* ============================================================
   NARROW
   Corners cannot sit side by side on a phone, so the clusters
   stack and the cue steps aside.
   ============================================================ */
@media (max-width: 720px) {
    .viewfinder {
        grid-template-columns: 1fr;
        grid-template-rows: 1fr auto auto;
        row-gap: var(--space-6);
    }

    .vf-entries {
        grid-column: 1;
        grid-row: 2;
        gap: var(--space-4);
    }

    /* Sound and feeds share one row once the corners collapse */
    .vf-aside {
        grid-column: 1;
        grid-row: 3;
        justify-self: start;
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        width: 100%;
        gap: var(--space-4);
    }

    /* The cue competes with the clusters for the same bottom edge here,
       and a phone user does not need to be told the page scrolls. */
    .vf-cue {
        display: none;
    }

    .viewfinder::after {
        height: 62%;
    }

    .vf-corner {
        width: 16px;
        height: 16px;
    }
}

/* Landscape phones: barely any height, so the frame stops reserving a
   full screen and the type steps down rather than pushing the clusters
   off the bottom. */
@media (max-height: 520px) and (orientation: landscape) {
    .viewfinder {
        min-height: auto;
        padding-block: calc(var(--nav-height) + var(--space-5)) var(--space-6);
        row-gap: var(--space-4);
    }

    .vf-entry-name {
        font-size: 1.75rem;
    }

    .vf-entries {
        gap: var(--space-3);
    }

    .vf-cue {
        display: none;
    }
}

@media (max-width: 400px) {
    /* "Follow" and its divider are the first thing to go — the marks
       are self-explanatory and the row needs the width. */
    .vf-social-label {
        display: none;
    }

    .vf-entry-name {
        font-size: 1.9rem;
    }
}

/* ---- Touch targets ----
   Icon-only links are visually small on purpose. Where the pointer is
   coarse they still need a 44px hit area, so the box grows without the
   icon changing size. Negative margin keeps the visual spacing intact. */
@media (pointer: coarse) {
    .vf-social a {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-width: 44px;
        min-height: 44px;
        margin-block: -10px;
    }

    .vf-social {
        gap: var(--space-2);
    }

    .vf-sound {
        min-height: 44px;
    }
}


