/* ============================================================
   HERO SLIDESHOW
   Sits inside .hero-graphic on the home page. Images are discovered
   from wwwroot/img/hero-slides - see HeroSlideService.

   Kept out of site.css, which has an unclosed block near line 3620
   that swallows any rules appended after it.
   ============================================================ */

.hero-slideshow {
    position: absolute;
    inset: 0;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;

    /* Presentation cycle. The panel starts hidden, makes an entrance after the
       intro delay, plays the set through, then withdraws and returns.
       Default state is hidden so nothing flashes before the JS runs. */
    opacity: 0;
    transform: scale(0.94) translateY(10px);
    filter: blur(6px);
    pointer-events: none;
    will-change: opacity, transform;
    transition:
        opacity 0.9s cubic-bezier(0.16, 1, 0.3, 1),
        transform 1.05s cubic-bezier(0.16, 1, 0.3, 1),
        filter 0.9s ease;
}

/* Entrance: settles up into place from slightly small and soft. */
.hero-slideshow.is-shown {
    opacity: 1;
    transform: scale(1) translateY(0);
    filter: blur(0);
    pointer-events: auto;
}

/* Exit: recedes rather than simply vanishing - shorter than the entrance so
   the pause between cycles reads as deliberate. */
.hero-slideshow.is-resting {
    opacity: 0;
    transform: scale(0.97) translateY(6px);
    filter: blur(5px);
    pointer-events: none;
    transition:
        opacity 0.65s ease,
        transform 0.8s cubic-bezier(0.4, 0, 0.2, 1),
        filter 0.65s ease;
}

/* The frame: soft 26px corners, a faint gradient edge that reads as glass,
   and depth from a wide ambient shadow rather than a hard border. */
.hero-slideshow-frame {
    position: relative;
    width: 100%;
    height: 100%;
    border-radius: 26px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.14);
    box-shadow:
        0 24px 60px rgba(0, 0, 0, 0.55),
        0 6px 18px rgba(0, 0, 0, 0.35),
        inset 0 1px 0 rgba(255, 255, 255, 0.10);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    touch-action: pan-y;
    cursor: grab;
}

.hero-slideshow-frame:active {
    cursor: grabbing;
}

/* A soft inner vignette so the artwork never collides with the frame edge
   and the controls stay legible over bright images. */
.hero-slideshow-frame::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    border-radius: inherit;
    background:
        linear-gradient(180deg, rgba(4, 10, 22, 0.22) 0%, transparent 22%, transparent 72%, rgba(4, 10, 22, 0.42) 100%);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.06);
}

.hero-slideshow-track {
    position: absolute;
    inset: 0;
}

.hero-slide {
    position: absolute;
    inset: 0;
    margin: 0;
    opacity: 0;
    visibility: hidden;
    transform: scale(1.03);
    transition: opacity 0.85s ease, transform 1.2s cubic-bezier(0.4, 0, 0.2, 1), visibility 0s linear 0.85s;
}

.hero-slide.is-active {
    opacity: 1;
    visibility: visible;
    transform: scale(1);
    transition: opacity 0.85s ease, transform 6s ease-out, visibility 0s;
}

.hero-slide img,
.hero-slide video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    /* "Little transparent" - the hero background reads through slightly. */
    opacity: 0.88;
    user-select: none;
    -webkit-user-drag: none;
}

/* Browsers show a hover toolbar (picture-in-picture, translate, cast) over any
   video. Taking the element out of hit testing removes that overlay entirely.
   Dragging is unaffected - the pointer handlers live on the frame, not here. */
.hero-slide video {
    pointer-events: none;
}

/* ---------- Arrows ---------- */
.hero-slide-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 42px;
    height: 42px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.30);
    background: rgba(10, 20, 38, 0.42);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    color: #fff;
    cursor: pointer;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease, background 0.3s ease, transform 0.3s ease;
    z-index: 3;
}

/* Visibility is driven from JS via inline styles - see hero-slideshow.js.
   Each arrow shows only while the pointer is near its own edge, and an inline
   style cannot be overridden by a cached or conflicting rule. */
.hero-slide-nav:focus-visible {
    opacity: 1 !important;
    pointer-events: auto !important;
}

.hero-slide-nav:hover {
    background: rgba(255, 255, 255, 0.92);
    color: #0b2038;
}

.hero-slide-prev { left: 14px; }
.hero-slide-next { right: 14px; }

.hero-slide-prev:hover { transform: translateY(-50%) translateX(-2px); }
.hero-slide-next:hover { transform: translateY(-50%) translateX(2px); }

/* ---------- Dots ---------- */
.hero-slide-dots {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 16px;
    display: flex;
    justify-content: center;
    gap: 8px;
    z-index: 3;
}

.hero-slide-dot {
    width: 8px;
    height: 8px;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.42);
    cursor: pointer;
    transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}

.hero-slide-dot:hover {
    background: rgba(255, 255, 255, 0.75);
}

.hero-slide-dot.is-active {
    width: 24px;
    background: linear-gradient(90deg, #22D3EE, #8B5CF6);
}

/* Touch handling is done in JS. A media query here would override the inline
   styles on any device reporting no hover - including touchscreen laptops,
   where it forced both arrows permanently visible. */

/* Responsive.
   The slideshow stays absolutely positioned at every size - .hero-graphic is a
   fixed-height box, so making this relative pushed it past the bottom of that
   box and .hero-section's overflow:hidden clipped it away on phones.
   Size is controlled by the container instead. */
@media (max-width: 991px) {
    .hero-graphic {
        height: 340px;
        margin-top: 2.5rem;
    }

    .hero-slide-nav {
        width: 36px;
        height: 36px;
    }
}

@media (max-width: 576px) {
    .hero-graphic {
        height: 240px;
        margin-top: 2rem;
    }

    .hero-slideshow-frame {
        border-radius: 18px;
    }

    .hero-slide-dots {
        bottom: 10px;
    }

    .hero-slide-dot {
        width: 7px;
        height: 7px;
    }

    .hero-slide-dot.is-active {
        width: 20px;
    }

    .hero-slide-prev { left: 8px; }
    .hero-slide-next { right: 8px; }
}

/* ============================================================
   FULL-BLEED HERO
   The slideshow moved out of .hero-graphic and now spans the whole
   hero section as its backdrop. A scrim sits between the media and the
   copy so the headline stays readable over any frame of any slide.

   Everything here is scoped to .hero-section-cinematic and gated on
   :has(.hero-slideshow) - with no media in the folder the partial
   renders nothing and the hero keeps its original height and layout.
   ============================================================ */

.hero-section-cinematic:has(.hero-slideshow) {
    min-height: 92vh;
    /* Trimmed from 150/90 to buy the advertisement panel its extra height
       without pushing the whole hero further down the page. */
    padding: 125px 0 75px 0;
}

/* Backdrop layer: the whole black area, edge to edge on all four sides. */
.hero-section-cinematic .hero-slideshow-backdrop {
    position: absolute;
    inset: 0;
    z-index: 0;
}

/* No frame and no corners - the media reaches the edge of the section on
   every side, so there is nothing to round or outline. */
.hero-section-cinematic .hero-slideshow-backdrop .hero-slideshow-frame {
    border-radius: 0;
    border: 0;
    background: transparent;
    box-shadow: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}

.hero-section-cinematic .hero-slideshow-backdrop .hero-slideshow-frame::after {
    /* Only a soft bottom fade into the next section - the scrim does the rest. */
    background: linear-gradient(180deg, rgba(0, 0, 0, 0.55) 0%, transparent 26%, transparent 68%, rgba(0, 0, 0, 0.9) 100%);
    box-shadow: none;
}

/* Brighter than the boxed version: the scrim now controls contrast, so the
   media itself no longer has to be dimmed to keep the copy legible. */
.hero-section-cinematic .hero-slide img,
.hero-section-cinematic .hero-slide video {
    opacity: 1;
}

/* The scrim. Heavy on the left where the words sit, clearing towards the
   right so the artwork is seen. The second gradient keeps the fixed navbar
   readable and blends the bottom edge into the black page below. */
.hero-scrim {
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    /* Fades out with the media during the rest phase - see the rest block below. */
    transition: opacity 0.65s ease;
    background:
        linear-gradient(90deg,
            rgba(0, 0, 0, 0.94) 0%,
            rgba(0, 0, 0, 0.88) 26%,
            rgba(0, 0, 0, 0.62) 46%,
            rgba(0, 0, 0, 0.30) 68%,
            rgba(0, 0, 0, 0.48) 100%),
        linear-gradient(180deg,
            rgba(0, 0, 0, 0.72) 0%,
            transparent 22%,
            transparent 72%,
            rgba(0, 0, 0, 0.85) 100%);
}

/* Copy sits above both the media and the scrim. */
.hero-section-cinematic .hero-content {
    z-index: 3;
}

.hero-section-cinematic .container {
    position: relative;
    z-index: 2;
}

/* The floating dots were decoration for an empty right column. Over live
   media they are just noise. The column still holds the advertisement panel,
   so it keeps its height. */
.hero-section-cinematic:has(.hero-slideshow-backdrop) .floating-elements {
    opacity: 0;
    transition: opacity 0.8s ease;
}

/* Taller top and bottom - the panel's width follows from this via its
   aspect-ratio, so height is the only dial that needs turning. */
.hero-section-cinematic:has(.hero-slideshow) .hero-graphic {
    height: 570px;
}

/* The dotted circle is competing with the artwork - keep it as a hint.

   It also has to be pushed below the advertisement panel and taken out of hit
   testing. It is an 800x560 box anchored to the bottom right of the section,
   at the same z-index the panel had - and being generated content of the
   section it paints after the section's children. So it covered the panel's
   bottom right corner, which is where the Next arrow lives: the arrow was
   drawn underneath it and the circle swallowed the clicks. The Previous arrow
   was untouched, being on the opposite side. */
.hero-section-cinematic:has(.hero-slideshow-backdrop)::after {
    opacity: 0.18;
    z-index: 1;
    pointer-events: none;
    transition: opacity 0.8s ease;
}

/* ---------- The rest phase: hand the hero back to the old design ----------
   While the backdrop has withdrawn there is nothing behind the copy, so the
   original treatment returns for those ten seconds - scrim gone, floating dots
   back, dotted circle at full strength, copy no longer dimmed.

   Tied to the backdrop alone (.hero-slideshow-backdrop.is-resting). The
   advertisement panel runs its own clock and must not drag the hero back to
   the old design when it happens to be resting.

   :has() takes the specificity of its most specific argument, so these
   outrank the plain :has(.hero-slideshow-backdrop) rules above. */
.hero-section-cinematic:has(.hero-slideshow-backdrop.is-resting) .hero-scrim {
    opacity: 0;
}

.hero-section-cinematic:has(.hero-slideshow-backdrop.is-resting) .floating-elements {
    opacity: 1;
}

.hero-section-cinematic:has(.hero-slideshow-backdrop.is-resting)::after {
    opacity: 0.5;
}

/* Nothing to read the copy against any more, and nothing to look past it at. */
.hero-section-cinematic:has(.hero-slideshow-backdrop.is-resting) .hero-content {
    opacity: 1;
}

/* ---------- Copy: dimmed until pointed at ----------
   The hero's own container is widened out of the centred Bootstrap one, then
   given a left gutter that scales with the viewport - so the copy sits clear
   of the edge without drifting towards the middle on a very wide screen. */
@media (min-width: 992px) {
    .hero-section-cinematic .container {
        max-width: 100%;
        padding-left: 7%;
        padding-right: 3.5rem;
    }
}

/* At rest the words sit back so the artwork leads; pointing at them brings
   them fully up. Focus counts too, so tabbing to the button never leaves the
   text dimmed. Dropped entirely below 992px - a touch screen has no hovering
   pointer, so the copy would simply stay faded there for good. */
.hero-section-cinematic .hero-content {
    opacity: 0.62;
    transition: opacity 0.45s ease, transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

.hero-section-cinematic .hero-content:hover,
.hero-section-cinematic .hero-content:focus-within {
    opacity: 1;
}

.hero-section-cinematic .hero-title {
    text-shadow: 0 2px 24px rgba(0, 0, 0, 0.6);
}

.hero-section-cinematic .hero-subtitle {
    font-size: 1.05rem;
    line-height: 1.7;
    max-width: 34ch;
    color: rgba(255, 255, 255, 0.92);
    text-shadow: 0 1px 16px rgba(0, 0, 0, 0.7);
}

/* ---------- Controls, repositioned for a full-width stage ----------
   Scoped to the backdrop: the advertisement panel is a fraction of the size
   and gets its own, smaller set further down. */
.hero-section-cinematic .hero-slideshow-backdrop .hero-slide-dots {
    bottom: 34px;
    left: auto;
    right: 48px;
    justify-content: flex-end;
}

/* Always on screen, just held back. Hiding them until hovered meant hovering
   a target that could not be seen - there was nothing to aim at. They now sit
   at 55% and come fully up the moment the pointer is on them.
   JS does not touch these (data-arrow-reveal="self" on the partial); its
   inline styles would otherwise win over everything here. */
.hero-section-cinematic .hero-slideshow-backdrop .hero-slide-nav {
    width: 60px;
    height: 60px;
    border-width: 2px;
    border-color: rgba(255, 255, 255, 0.55);
    background: rgba(6, 14, 28, 0.62);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.45);
    opacity: 0.55;
    pointer-events: auto;
    transition: opacity 0.18s ease, background 0.25s ease, transform 0.25s ease,
                box-shadow 0.25s ease, border-color 0.25s ease;
}

.hero-section-cinematic .hero-slide-nav:hover,
.hero-section-cinematic .hero-slide-nav:focus-visible {
    opacity: 1;
}

/* While the panel is resting there is nothing to navigate - keep the invisible
   buttons out of hit testing so they cannot be hovered over the old design. */
.hero-slideshow.is-resting .hero-slide-nav {
    pointer-events: none;
}

.hero-section-cinematic .hero-slideshow-backdrop .hero-slide-nav svg {
    width: 26px;
    height: 26px;
    stroke-width: 2.6;
}

/* Clearly answers the pointer: fills in, brightens and grows. */
.hero-section-cinematic .hero-slide-nav:hover {
    background: #fff;
    border-color: #fff;
    color: #0b2038;
    box-shadow: 0 8px 30px rgba(34, 211, 238, 0.45);
}

/* Set in from the left edge: the far left of the backdrop is under the
   heaviest part of the scrim, where an arrow would be all but invisible. */
.hero-section-cinematic .hero-slideshow-backdrop .hero-slide-prev {
    left: 9%;
}

.hero-section-cinematic .hero-slideshow-backdrop .hero-slide-next {
    right: 40px;
}

/* The advertisement panel occupies the right-hand half from 992px up, and at
   right:40px the backdrop's own next arrow ran underneath it - two next arrows
   overlapping in the same place, one of them unreachable. That is why Next
   appeared not to work. Keep the backdrop's controls clear of the panel. */
@media (min-width: 992px) {
    .hero-section-cinematic:has(.hero-slideshow-ads) .hero-slideshow-backdrop .hero-slide-next {
        right: 53%;
    }

    .hero-section-cinematic:has(.hero-slideshow-ads) .hero-slideshow-backdrop .hero-slide-dots {
        right: 53%;
    }
}

.hero-section-cinematic .hero-slide-prev:hover {
    transform: translateY(-50%) translateX(-3px) scale(1.08);
}

.hero-section-cinematic .hero-slide-next:hover {
    transform: translateY(-50%) translateX(3px) scale(1.08);
}

/* ============================================================
   ADVERTISEMENT PANEL (slider 2)
   A framed panel layered over the backdrop, in the right-hand column where
   the original boxed slideshow used to sit - a little larger than that
   version was. Media comes from wwwroot/img/hero-ads; an empty folder
   renders nothing at all and the hero is unaffected.

   It runs its own clock. Nothing here is linked to the backdrop's cycle.
   ============================================================ */

.hero-slideshow-ads {
    position: absolute;
    inset: 0;
    z-index: 2;                 /* over the backdrop and the scrim, under the copy */
    display: flex;
    align-items: center;
    justify-content: center;
}

/* The frame comes back for this one - it is a panel sitting on the hero, so
   it needs an edge and corners to read as one.

   The frame takes the shape of the advertisements rather than the shape of
   the column. Filling the column left tall black bars either side of every
   portrait ad; sizing the frame to 4:5 and letting the width follow the
   height means the panel ends where the artwork ends. */
.hero-slideshow-ads .hero-slideshow-frame {
    /* Starting shape only. The script measures each slide and sets width and
       height in pixels to match that slide's own proportions - see
       data-fit-frame in hero-slideshow.js. A portrait ad gets a tall frame, a
       wide one gets a short frame, and neither is letterboxed.
       These values are what shows for the moment before the first image has
       reported its size, and if scripting is off. */
    height: 100%;
    width: auto;
    aspect-ratio: 4 / 5;
    max-width: 100%;
    max-height: 100%;
    border-radius: 22px;
    background: #05080f;

    /* ---- Perspective Float (chosen option C) ----
       A soft card, not a raised bezel: a thin light rim and a directional drop
       shadow, and the whole card tilted slightly in 3D so it reads like the
       reference icon rather than a flat rectangle.

       The tilt lives here, on the frame, while the Grow & Turn lives on the
       parent panel - two different elements, so the two never fight over the
       one transform property. The frame is flat by default and eases into the
       tilt only once the panel is shown (see .is-shown below), so it settles
       into its pose after arriving rather than tilting through the turn. */
    border: 1px solid rgba(255, 255, 255, 0.12);
    box-shadow:
        24px 34px 55px -18px rgba(0, 0, 0, 0.80),
        0 8px 20px rgba(0, 0, 0, 0.40);

    transform: perspective(1400px) rotateY(0deg) rotateX(0deg);

    /* Width and height animate so the frame reshapes into the next ad rather
       than jumping; transform eases the tilt in and out. */
    transition: box-shadow 0.4s ease,
                transform 0.85s cubic-bezier(0.22, 1, 0.32, 1),
                width 0.55s cubic-bezier(0.4, 0, 0.2, 1),
                height 0.55s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Tilt settles in once the panel has taken the stage. Keyed to the panel's
   is-shown, so during the pre-intro and the rest phase the card is flat and
   only the Grow & Turn is seen. */
.hero-slideshow-ads.is-shown .hero-slideshow-frame {
    transform: perspective(1400px) rotateY(-9deg) rotateX(2deg);
}

/* With the frame now matching the media exactly there is nothing to letterbox,
   so the slide can fill it edge to edge. contain still guards the moment
   before a slide has been measured, and any file with an extreme shape that
   gets clamped by the limits in the script. */
.hero-slideshow-ads .hero-slide img,
.hero-slideshow-ads .hero-slide video {
    object-fit: contain;
}

/* Pointing at the panel eases it upright and lifts it a little - the card
   turns to face you and the shadow lengthens. Keeps the tilt in the transform
   so hover does not fight the settled pose; only softens it and adds a lift. */
.hero-slideshow-ads.is-shown .hero-slideshow-frame:hover {
    transform: perspective(1400px) rotateY(-4deg) rotateX(1deg) translateY(-5px);
    box-shadow:
        30px 42px 66px -18px rgba(0, 0, 0, 0.85),
        0 12px 26px rgba(0, 0, 0, 0.45),
        0 0 60px rgba(34, 211, 238, 0.14);
}

/* ---------- Grow & Turn ----------
   Pivots about its own centre, so it grows out from small while turning
   upright at the same time - like a coin spun flat onto a table. This is the
   difference from an arc swing: origin is 50% 50%, not a point below, so it
   spins in place rather than rolling in from a corner.
   The backdrop fades and zooms; this turns, so the two entrances never read
   as the same movement twice. */
.hero-slideshow-ads {
    transform-origin: 50% 50%;
    transform: rotate(-90deg) scale(0.28);
    opacity: 0;
    filter: blur(4px);
    /* Unhurried on purpose - the turn is the point, so it is given time. */
    transition:
        opacity 0.8s ease,
        transform 1.45s cubic-bezier(0.22, 1.1, 0.32, 1),   /* slight overshoot */
        filter 0.8s ease;
}

.hero-slideshow-ads.is-shown {
    transform: rotate(0deg) scale(1);
    opacity: 1;
    filter: blur(0);
}

/* Two ways the panel turns out, both the entrance run backwards:
     .is-resting  - the ten-second rest between full passes
     .is-turning  - the brief out-and-in around an automatic move to the next
                    item, so every item arrives with the same Grow & Turn.
   The exit duration here must match TURN_EXIT_MS in hero-slideshow.js. */
.hero-slideshow-ads.is-resting,
.hero-slideshow-ads.is-turning {
    transform: rotate(-75deg) scale(0.3);
    opacity: 0;
    filter: blur(4px);
    transition:
        opacity 0.55s ease,
        transform 0.85s cubic-bezier(0.4, 0, 0.6, 1),
        filter 0.55s ease;
}

/* ---------- Panel controls: scaled to the panel, not the hero ----------
   Hidden until the pointer is over the panel, then both appear together.
   Unlike the backdrop there is an obvious thing to hover here - the panel
   itself - so nothing is being hunted for. */
.hero-slideshow-ads .hero-slide-nav {
    width: 38px;
    height: 38px;
    opacity: 0;
    pointer-events: none;
    background: rgba(6, 14, 28, 0.55);
    border-color: rgba(255, 255, 255, 0.4);
    transition: opacity 0.22s ease, background 0.25s ease, transform 0.25s ease;
    z-index: 5;
}

.hero-slideshow-ads .hero-slideshow-frame:hover .hero-slide-nav {
    opacity: 0.85;
    pointer-events: auto;
}

.hero-slideshow-ads .hero-slide-nav:hover,
.hero-slideshow-ads .hero-slide-nav:focus-visible {
    opacity: 1;
    pointer-events: auto;
}

.hero-slideshow-ads .hero-slide-prev { left: 12px; }
.hero-slideshow-ads .hero-slide-next { right: 12px; }

.hero-slideshow-ads .hero-slide-dots {
    bottom: 14px;
    left: 0;
    right: 0;
    justify-content: center;
}

/* ---------- Responsive ---------- */
@media (max-width: 991px) {
    .hero-section-cinematic:has(.hero-slideshow) {
        min-height: 78vh;
        padding: 120px 0 70px 0;
    }

    /* Holds the advertisement panel, so it keeps a usable height - but a good
       deal less than the 470px it gets on a desktop. */
    .hero-section-cinematic:has(.hero-slideshow) .hero-graphic {
        height: 380px;
        margin-top: 1.5rem;
    }

    /* Grow & Turn starts from a smaller scale here so the turning corners stay
       inside the narrower column; the angle is unchanged - it spins in place,
       so a wide turn does not throw the panel sideways the way an arc would. */
    .hero-slideshow-ads {
        transform: rotate(-90deg) scale(0.34);
    }

    .hero-slideshow-ads.is-resting,
    .hero-slideshow-ads.is-turning {
        transform: rotate(-75deg) scale(0.36);
    }

    /* Softer shadow and a gentler tilt on a narrow column - a 9-degree turn
       would push the near corner past the column edge at this width. */
    .hero-slideshow-ads .hero-slideshow-frame {
        border-radius: 16px;
        box-shadow:
            16px 22px 38px -14px rgba(0, 0, 0, 0.75),
            0 6px 16px rgba(0, 0, 0, 0.40);
    }

    .hero-slideshow-ads.is-shown .hero-slideshow-frame {
        transform: perspective(1200px) rotateY(-6deg) rotateX(1.5deg);
    }

    /* Hover-to-reveal is useless on a touch screen, so the panel's arrows stay
       visible here. Keyed to width, not to (hover: none) - that feature also
       matches touchscreen laptops, which is what pinned the arrows on before. */
    .hero-slideshow-ads .hero-slide-nav {
        opacity: 0.6;
        pointer-events: auto;
    }

    .hero-scrim {
        inset: 0;
    }

    /* Media behind text on a narrow screen needs a top-down scrim, not a
       left-right one - there is no free space to the side any more. */
    .hero-scrim {
        background:
            linear-gradient(180deg,
                rgba(0, 0, 0, 0.9) 0%,
                rgba(0, 0, 0, 0.72) 40%,
                rgba(0, 0, 0, 0.55) 62%,
                rgba(0, 0, 0, 0.9) 100%);
    }

    .hero-section-cinematic .hero-content {
        padding-left: 0;
        max-width: 100%;
        opacity: 1;            /* no hovering pointer here - never dim the copy */
    }

    /* The full-size arrows would crowd a phone screen. */
    .hero-section-cinematic .hero-slide-nav {
        width: 46px;
        height: 46px;
    }

    .hero-section-cinematic .hero-slide-nav svg {
        width: 22px;
        height: 22px;
    }

    .hero-section-cinematic .hero-title {
        font-size: 2.4rem;
        white-space: normal;   /* the desktop rule forces one line and overflows */
    }

    .hero-section-cinematic .hero-subtitle {
        max-width: 100%;
        font-size: 1rem;
    }

    .hero-section-cinematic .hero-slide-dots {
        right: 0;
        left: 0;
        bottom: 18px;
        justify-content: center;
    }
}

@media (max-width: 576px) {
    .hero-section-cinematic:has(.hero-slideshow) {
        min-height: 72vh;
        padding: 110px 0 60px 0;
    }

    .hero-section-cinematic:has(.hero-slideshow) .hero-graphic {
        height: 120px;
    }

    .hero-section-cinematic .hero-title {
        font-size: 1.95rem;
    }

    .hero-section-cinematic .hero-slide-prev { left: 10px; }
    .hero-section-cinematic .hero-slide-next { right: 10px; }
}

@media (prefers-reduced-motion: reduce) {
    .hero-slide,
    .hero-slide.is-active {
        transition: opacity 0.2s linear;
        transform: none;
    }

    /* Keep the cycle, drop the movement and blur. */
    .hero-slideshow,
    .hero-slideshow.is-shown,
    .hero-slideshow.is-resting {
        transform: none;
        filter: none;
        transition: opacity 0.3s linear;
    }
}
