/* ───────────────────────────────────────────────────────────────────────
   scroll-cue.css — component/scroll-cue.cpt.php

   A pill at the foot of the viewport, inviting the reader into whatever is
   under the fold. It is the page's one call to action, so it is the page's
   one **inverted** chip: ink where the page is paper, paper where the page is
   ink. That is the editorial accent pattern the modals already use, and it is
   what lets the cue sit legibly over photographs as well as over the page.

   THIS IS THE ONE THING ON THE SITE THAT MOVES ON ITS OWN, and the exception
   is deliberate. Everywhere else motion is reader-driven, because motion
   nobody asked for is noise. A scroll invitation is the case that rule cannot
   serve: a reader who has not moved their pointer anywhere near this pill is
   exactly the reader it exists for, and a hover-only affordance says nothing
   to them. So it has two idle effects — a sheen that crosses it, and a
   chevron that leans down — and both are built to be ignorable:

     · They run on a long cycle with a long rest. The sweep is 15% of a 5.4s
       loop; the rest of the loop is nothing at all. Something that moves
       every five seconds reads as alive; something that moves constantly
       reads as a banner ad.
     · They are paused, in CSS, whenever the cue is not shown (`.is-on` is
       what the script toggles), so nothing animates off screen.
     · They do not exist at all under `prefers-reduced-motion`, and they can
       be turned off per instance with `$cue_quiet`.
   ─────────────────────────────────────────────────────────────────────── */

.scroll-cue {
    position: fixed;
    left: 50%;
    bottom: clamp(0.6rem, 1.8vh, 1.35rem);
    transform: translateX(-50%);
    z-index: 900;                 /* under the fixed toggles (1000), over the page */

    /* The sheen is a child that travels the full width of the pill; this is
       what keeps it inside the rounded edge. */
    overflow: hidden;
    isolation: isolate;

    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    height: 2.45rem;
    padding: 0 1.05rem;
    border: none;
    border-radius: var(--radius-full, 999px);
    text-decoration: none;
    cursor: pointer;

    /* Inverted against the page, in both themes: --ed-ink is the *text*
       colour, so painting with it gives a dark chip on the light theme and a
       cream one on the dark theme, each with the page's own surface as its
       label. Never assume --ed-ink is dark. */
    background: var(--ed-ink, var(--text-primary));
    color: var(--ed-paper, var(--bg-elevated));
    box-shadow: 0 3px 14px rgba(0, 0, 0, 0.16), 0 1px 4px rgba(0, 0, 0, 0.10);

    /* The gloss that crosses it. White on the dark chip; on the cream chip of
       the dark theme white would be invisible, so it inverts too and the
       sweep reads as a passing shadow rather than a passing light. Same
       gesture, opposite ink — which is the whole trick of this palette. */
    --cue-sheen: rgba(255, 255, 255, 0.42);

    transition: opacity 0.32s var(--ease-out, ease), transform 0.32s var(--ease-out, ease),
                box-shadow 0.2s, background 0.2s;
}

[data-theme="dark"] .scroll-cue {
    --cue-sheen: rgba(0, 0, 0, 0.26);
    box-shadow: 0 3px 14px rgba(0, 0, 0, 0.40), 0 1px 4px rgba(0, 0, 0, 0.22);
}

.scroll-cue__label {
    font-family: var(--ed-mono, var(--font-mono));
    font-size: 0.7rem;
    font-weight: 500;
    letter-spacing: 0.13em;
    text-transform: uppercase;
    white-space: nowrap;
    color: inherit;
}

.scroll-cue__icon {
    font-size: 1.05rem;
    line-height: 1;
    transition: transform 0.2s var(--ease-out, ease);
}

/* ───── The sheen ───────────────────────────────────────────────────
   A band of light on a slant, parked off the left edge and sent across the
   chip once a cycle. It is a sibling layer rather than a background-position
   animation because a gradient's position cannot be composited on the GPU,
   and this runs while the reader is doing something else. */
.scroll-cue::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(105deg,
        transparent 34%,
        var(--cue-sheen) 50%,
        transparent 66%);
    transform: translateX(-130%);
    pointer-events: none;
}

@keyframes scroll-cue-sheen {
    0%   { transform: translateX(-130%); }
    15%  { transform: translateX(130%); }
    100% { transform: translateX(130%); }
}

/* A lean, not a bounce: the chevron goes down and comes back, on the same
   cycle as the sheen and a beat behind it, so the pill reads as one gesture
   rather than as two things fidgeting. */
@keyframes scroll-cue-lean {
    0%, 74%, 100% { transform: translateY(0); }
    82%           { transform: translateY(3px); }
    90%           { transform: translateY(0); }
}

.scroll-cue.is-on::after {
    animation: scroll-cue-sheen 5.4s cubic-bezier(0.4, 0.05, 0.25, 1) infinite;
}
.scroll-cue.is-on .scroll-cue__icon {
    animation: scroll-cue-lean 5.4s ease-in-out infinite;
}

/* Hovered, the reader has arrived and the idle invitation has done its job:
   both loops stop and the chevron holds its lean under the pointer. */
.scroll-cue:hover::after,
.scroll-cue:focus-visible::after,
.scroll-cue:hover .scroll-cue__icon,
.scroll-cue:focus-visible .scroll-cue__icon { animation: none; }

.scroll-cue:hover,
.scroll-cue:focus-visible {
    box-shadow: 0 6px 22px rgba(0, 0, 0, 0.22), 0 2px 8px rgba(0, 0, 0, 0.12);
    transform: translate(-50%, -2px);
}
.scroll-cue:hover .scroll-cue__icon,
.scroll-cue:focus-visible .scroll-cue__icon { transform: translateY(3px); }
.scroll-cue:active { transform: translate(-50%, 0); }
.scroll-cue:focus-visible { outline: 2px solid var(--ed-ink, currentColor); outline-offset: 3px; }

/* `$cue_quiet`: the same chip without the two idle loops, for a page where a
   moving call to action would be wrong. */
.scroll-cue--quiet::after,
.scroll-cue--quiet .scroll-cue__icon { animation: none !important; }

/* ───── Shown and hidden ────────────────────────────────────────────
   With the script out it is simply a link that is always there, which is
   correct and costs nothing. With the script in, it starts hidden and is
   revealed only while its target is off screen — so on a short window, where
   the section below is already visible at load, it never appears at all
   rather than appearing for one frame and leaving. The idle animations hang
   off `.is-on` for the same reason: nothing loops while it is not shown. */
/* Written as the *hidden* state rather than as a pair, and that is a cascade
   decision, not a style one: `.has-js .scroll-cue.is-on` would out-specify
   `.scroll-cue:hover` and quietly cancel the hover lift below. Stated this
   way, the shown cue is governed by the base rule and hover keeps its say. */
.has-js .scroll-cue:not(.is-on) {
    opacity: 0;
    transform: translate(-50%, 10px);
    pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
    .scroll-cue,
    .scroll-cue__icon { transition: none; }
    .scroll-cue::after,
    .scroll-cue .scroll-cue__icon { animation: none !important; }
    .has-js .scroll-cue { transform: translateX(-50%); }
    .scroll-cue:hover,
    .scroll-cue:focus-visible { transform: translateX(-50%); }
    .scroll-cue:hover .scroll-cue__icon,
    .scroll-cue:focus-visible .scroll-cue__icon { transform: none; }
}

/* Narrow: the chip tightens but keeps its words. An icon-only circle was the
   first version and it invited nothing — on a phone especially, the label is
   the part doing the work. */
@media (max-width: 560px) {
    .scroll-cue {
        height: 2.3rem;
        gap: 0.45rem;
        padding: 0 0.85rem;
    }
    .scroll-cue__label { font-size: 0.64rem; letter-spacing: 0.11em; }
}
