/* ============================================
   FLIP PHOTO CAROUSEL MODULE (Swiper-based)
   Single display mode: flip (a single slide
   that flips around a horizontal axis). Runtime
   values come from CSS custom properties
   (--pc-radius, --pc-aspect-ratio,
   --pc-main-height) set inline by the renderer.
   The carousel mechanics are driven by the Swiper
   library's flip effect; this stylesheet only
   styles the module shell, slides, captions, and
   controls.
   ============================================ */

.flip-photo-carousel-viewport {
    /* Clip wrapper. The Swiper root inside is overflow:visible so the flipping
       slide and its face shadows read in full while the slide turns; this outer
       viewport clips any spill exactly at the module boundary so the carousel
       never reads wider than its module-wrapper (matching every other module).
       box-sizing:border-box keeps the padding inside the 100% width. This
       wrapper is also the containing block for the nav arrows and pagination
       dots, which are rendered as SIBLINGS of the Swiper root (not inside it).
       position:relative makes the absolute arrows anchor to the module box; the
       --swiper-navigation-* tokens live here so Swiper's own
       .swiper-button-prev/next rules size and place the arrows against this
       wrapper. */
    box-sizing: border-box;
    position: relative;
    width: 100%;
    overflow: hidden;
    --swiper-navigation-size: 44px;
    --swiper-navigation-sides-offset: 8px;
    /* The arrows anchor against this viewport (their containing block). Swiper
       applies `top: var(--swiper-navigation-top-offset, 50%)` to its prev/next
       buttons (with a negative margin-top to vertically center the button on
       that top), so this token IS the button's absolute top — it must keep its
       50% base. The viewport height = padding-top + slide height + padding-bottom
       (the bottom padding reserves the dots band). A plain 50% centers against
       the whole box and drifts down as the bottom padding grows, so half the
       (top − bottom) padding difference is subtracted from 50% to land the
       arrows on the SLIDE's vertical center instead. The padding values are
       dynamic (sized from the slide's perspective-overshoot at the 90° flip
       transit via --pc-viewport-pad-*), so the correction reads the SAME custom
       properties to stay on the slide center at every padding size. The extra
       -4px nudges the arrows slightly above the geometric center (the aesthetic
       buffer kept from the fixed-padding layout). */
    --swiper-navigation-top-offset: calc(50% + (var(--pc-viewport-pad-top, 16px) - var(--pc-viewport-pad-bottom, 48px)) / 2 - 4px);
    --swiper-navigation-color: var(--text-ink);
    /* Top/bottom padding so the flipping slide has breathing room above and the
       dots band sits clear below the slide. The values are sized from the slide's
       perspective-overshoot at the 90° flip transit by the data prep
       (flipViewportPaddingFor) and ride in as --pc-viewport-pad-* on this
       element. The defaults (16px / 48px) match the no-overshoot case and only
       apply if the renderer never set the custom property. No floor shadow exists
       for the flip effect (unlike the cube), so there is no shadow headroom to
       reserve. */
    padding: var(--pc-viewport-pad-top, 16px) 0 var(--pc-viewport-pad-bottom, 48px);
}

.flip-photo-carousel {
    --pc-radius: 18px;
    /* Fixed-height slide. The height is set by --pc-main-height and the width is
       derived from the admin aspect_ratio via the CSS `aspect-ratio` property.
       object-fit:cover crops each image to fill the box, so every slide reads as
       one uniform tile regardless of the source aspect ratio. Default is
       landscape (16 / 9) for photo content; the renderer overrides it from the
       setting. */
    --pc-main-height: 360px;
    /* The renderer overrides --pc-main-height from the admin main_height setting
       (inline on the root). This declaration remains the fallback for any
       carousel rendered without that token. */
    --pc-aspect-ratio: 16 / 9;
    /* Slide elevation. Tinted toward Ink (green-grey) per the design system's
       shadow vocabulary rather than pure black. A distinct dark-mode value is
       layered under the dark-theme block below so the shadow stays visible
       against the charcoal-teal canvas instead of dissolving into it. */
    --pc-shadow: 0 8px 20px rgba(26, 36, 33, 0.16);
    --pc-shadow-active: 0 12px 28px rgba(26, 36, 33, 0.22);
    box-sizing: border-box;
    position: relative;
    /* The flip effect needs a fixed-size container so the slide keeps its
       dimensions while it flips. The width mirrors the derived slide width
       (main-height × aspect-ratio) so the centered slide fills the stage; the
       height tracks the slide height. margin:auto centers the stage inside the
       clip viewport. */
    width: calc(var(--pc-main-height, 360px) * var(--pc-aspect-ratio, 16 / 9));
    height: var(--pc-main-height, 360px);
    max-width: 100%;
    margin: 0 auto;
}

.flip-photo-carousel *,
.flip-photo-carousel *::before,
.flip-photo-carousel *::after {
    box-sizing: border-box;
}

/* ============================================
   SWIPER SHELL OVERRIDE
   The root is the Swiper viewport. Do NOT set
   transform / perspective / transform-style on
   .swiper or .swiper-wrapper here — Swiper's flip
   effect applies the 3D perspective itself, and
   overriding it breaks the flip.
   ============================================ */

/* Flip viewport. overflow:visible lets the flipping slide and its box-shadow
   lift spill past the root edge so the slide reads in full while it turns —
   the slide's shadow lift and the flipEffect slide shadows would otherwise be
   clipped at the stage boundary and the slide would look "trapped" in its box
   with no depth. This mirrors the cube, coverflow and stacked-cards modules,
   which all keep the Swiper root visible for the same 3D-spill reason. The
   outer .flip-photo-carousel-viewport clips that spill at the module boundary
   so the carousel still respects its module-wrapper width. */
.flip-photo-carousel--flip.swiper {
    overflow: visible;
}

.flip-photo-carousel__wrapper.swiper-wrapper {
    align-items: center;
}

/* ============================================
   SLIDE BASE
   ============================================ */

.flip-photo-carousel__item.swiper-slide {
    position: relative;
    display: block;
    /* Fixed-height tile. The height is set by --pc-main-height and the width is
       derived from the admin aspect_ratio via the CSS `aspect-ratio` property;
       object-fit:cover on the image fills the box regardless of the source
       aspect ratio. width:auto lets the aspect-ratio derive the rendered width
       from the fixed height. */
    width: auto;
    height: var(--pc-main-height, 360px);
    aspect-ratio: var(--pc-aspect-ratio, 16 / 9);
    border-radius: var(--pc-radius);
    overflow: hidden;
    background: transparent;
    text-decoration: none;
    color: inherit;
}

.flip-photo-carousel__image {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* ============================================
   CAPTION OVERLAY (title + description)
   A bottom gradient band over the image, painted onto the slide face itself.
   The caption rides the face it belongs to: while a slide is the active face
   its caption stays visible, and as the slide flips away its caption leaves
   together with the image — there is no separate show/hide. This mirrors the
   image itself, so the caption never appears or disappears independently of
   its slide.
   ============================================ */

.flip-photo-carousel__caption {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 40px 15px 15px;
    background: linear-gradient(to top, rgba(0, 0, 0, 1), transparent);
    color: #ffffff;
    z-index: 2;
    /* pointer-events:none lets the whole band sit over the image without
       blocking drag; the title link re-enables its own events. */
    pointer-events: none;
}

.flip-photo-carousel__title {
    display: block;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-weight: 600;
    color: #ffffff;
    line-height: 1.4;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Title as a link: only this element is clickable inside the overlay. */
.flip-photo-carousel__title--link {
    text-decoration: none;
    transition: color 0.2s ease;
    pointer-events: auto;
    cursor: pointer;
}

.flip-photo-carousel__title--link:hover {
    color: rgba(255, 255, 255, 0.85);
    text-decoration: underline;
}

.flip-photo-carousel__desc {
    font-weight: 600;
    text-decoration: none;
    line-height: 1.4;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    padding-bottom: 15px;
    margin-top: 6px;
    font-size: 0.75rem;
    color: rgba(255, 255, 255, 0.9);
}

/* ============================================
   FLIP MODE SHADOWS
   The slideShadows toggle (flipEffect.slideShadows) gates the inner depth
   shadow Swiper paints on the two faces of the flipping slide; the base slide
   keeps its box-shadow lift so each tile reads as a solid framed surface.
   Unlike the cube effect, the flip effect has NO outer floor shadow, so there
   is no separate .swiper-*-shadow element to style here.
   ============================================ */

/* Slide elevation is gated on the --has-shadows modifier (set by the renderer
   from the admin "slide shadows" toggle). With shadows off, the tile rests on a
   hairline edge alone. The active slide earns a slightly stronger lift to read
   as the focal point. */
.flip-photo-carousel--flip.flip-photo-carousel--has-shadows .flip-photo-carousel__item {
    box-shadow: var(--pc-shadow);
}

.flip-photo-carousel--flip.flip-photo-carousel--has-shadows .flip-photo-carousel__item.swiper-slide-active {
    box-shadow: var(--pc-shadow-active);
}

/* Dark mode: the light-mode shadow tint (green-grey on a near-black field)
   dissolves and the slide looks flat. Lift the opacity and shift the tint
   toward true black so the slide separates from the charcoal-teal canvas
   instead of disappearing into it. Active stays a step stronger than rest. */
[data-bs-theme="dark"] {
    --pc-shadow: 0 8px 22px rgba(0, 0, 0, 0.55);
    --pc-shadow-active: 0 12px 30px rgba(0, 0, 0, 0.65);
}

/* ============================================
   NAVIGATION ARROWS
   Mirrors the other photo carousels' arrows so all
   share an identical control style.
   ============================================ */

/* The arrows carry Swiper's .swiper-button-prev/next classes too, so Swiper
   already provides position/top/size/placement via the --swiper-navigation-*
   tokens set on the clip viewport above (the arrows' containing block, since
   they live as siblings of the Swiper root). Only the visual layer (face,
   color, reveal-on-hover) is layered on top — no left/right/margin overrides
   needed, which avoids any specificity clash with Swiper's selectors. */
.flip-photo-carousel__nav {
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.9);
    box-shadow: var(--shadow-sm);
    opacity: 0;
    transition: background 0.2s ease, box-shadow 0.2s ease, opacity 0.2s ease;
}

/* Reveal arrows on hover over the whole module. The arrows are siblings of the
   Swiper root (inside the viewport), so the :hover is scoped to the viewport —
   the element that contains both the carousel and the arrows. */
.flip-photo-carousel-viewport:hover .flip-photo-carousel__nav {
    opacity: 1;
}

.flip-photo-carousel__nav:hover {
    background: #fff;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}

.flip-photo-carousel__nav:focus-visible {
    outline: 3px solid var(--accent-color, #c2683f);
    outline-offset: 3px;
}

.flip-photo-carousel__nav svg {
    width: 20px;
    height: 20px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* Disabled arrow: a dimmed-but-visible control (0.3 opacity) rather than fully
   hidden, so the user reads it as "no more slides in that direction" instead of
   the control vanishing. Swiper's own .35 opacity is overridden here. */
.flip-photo-carousel__nav.swiper-button-disabled {
    opacity: 0.3;
    cursor: not-allowed;
    pointer-events: none;
}

.flip-photo-carousel-viewport:hover .flip-photo-carousel__nav.swiper-button-disabled {
    opacity: 0.3;
}

/* Dark mode: dark button face with a light icon. */
[data-bs-theme="dark"] .flip-photo-carousel__nav {
    background: rgba(30, 30, 30, 0.9);
    color: #d7dedb;
}

[data-bs-theme="dark"] .flip-photo-carousel__nav:hover {
    background: #161c1a;
}

/* ============================================
   DOT INDICATORS
   Swiper renders .swiper-pagination-bullet inside
   the .flip-photo-carousel__dots container. Styled
   to mirror the other photo carousels' indicator look.
   ============================================ */

.flip-photo-carousel__dots.swiper-pagination {
    /* Absolutely positioned at the bottom of the clip viewport so the dots row
       does NOT add to the viewport's flow height. This keeps the viewport height
       equal to the Swiper root height, which is what the nav arrows' top:50%
       centers against — otherwise the dots (~36px) push the vertical midpoint
       down and the arrows sit below the slide center. */
    position: absolute;
    left: 0;
    right: 0;
    bottom: 14px;
    display: flex;
    justify-content: center;
    gap: 8px;
    padding: 0;
    --swiper-pagination-bullet-horizontal-gap: 0;
}

.flip-photo-carousel__dots .swiper-pagination-bullet {
    width: 10px;
    height: 10px;
    margin: 0;
    border: none;
    border-radius: 50%;
    background: var(--border-strong, #c4ccc8);
    opacity: 1;
    /* Swiper defaults inactive bullets to transform:scale(.33); reset to none so
       the dots read as full-size circles. */
    transform: none;
    transition: background 0.2s ease, transform 0.2s ease;
}

.flip-photo-carousel__dots .swiper-pagination-bullet:hover {
    background: var(--text-muted);
}

.flip-photo-carousel__dots .swiper-pagination-bullet-active {
    background: var(--cc-dot-active-color, var(--primary-color));
    transform: scale(1.2);
}

[data-bs-theme="dark"] .flip-photo-carousel__dots .swiper-pagination-bullet {
    background: var(--border-strong);
}

[data-bs-theme="dark"] .flip-photo-carousel__dots .swiper-pagination-bullet:hover {
    background: var(--text-muted);
}

[data-bs-theme="dark"] .flip-photo-carousel__dots .swiper-pagination-bullet-active {
    background: var(--cc-dot-active-color, var(--primary-color));
}

/* ============================================
   REDUCED MOTION
   Strip transitions for users who prefer reduced
   motion; behavior stays intact (Swiper speed is
   set to 0 by the engine).
   ============================================ */

@media (prefers-reduced-motion: reduce) {
    .flip-photo-carousel__nav,
    .flip-photo-carousel__dots .swiper-pagination-bullet {
        transition: none !important;
    }

    .flip-photo-carousel__dots .swiper-pagination-bullet-active {
        transform: none;
    }
}

/* ============================================
   RESPONSIVE — narrow screens.
   Breakpoint matches the other photo carousels
   (767px) so the arrow icon size shift is
   identical across all of them.
   ============================================ */

@media (max-width: 767px) {
    .flip-photo-carousel-viewport {
        /* Switch the viewport padding to the mobile-sized pair. The data prep
           computes the desktop padding from the full slide height, but on a phone
           the slide shrinks to 200px (see the --pc-main-height rule below), so
           the desktop padding would be too generous. Reassigning the SAME custom
           properties (rather than overriding padding-top/bottom directly) keeps
           the base padding rule unchanged AND lets the nav-offset calc above
           recompute from the mobile values automatically. !important is required
           for the same reason as --pc-main-height below: the renderer sets these
           inline on the viewport, and inline custom-property declarations win
           over a plain media-query rule. NOTE: flip mobile height is 200px, NOT
           220px like cards. */
        --pc-viewport-pad-top: var(--pc-viewport-pad-top-mobile, 16px) !important;
        --pc-viewport-pad-bottom: var(--pc-viewport-pad-bottom-mobile, 48px) !important;
    }

    .flip-photo-carousel {
        /* Smaller slide on narrow screens so the slide still fits within the
           viewport without dominating it. !important is required because the
           renderer sets --pc-main-height inline on the root from the admin
           main_height setting; inline custom-property declarations win over a
           plain media-query rule, so without !important the mobile shrink would
           be ignored and a large slide would overflow narrow viewports. The
           200px here is the mobile slide height. */
        --pc-main-height: 200px !important;
    }

    .flip-photo-carousel__nav svg {
        width: 16px;
        height: 16px;
    }

    .flip-photo-carousel__caption {
        padding: 30px 12px 12px;
    }

    .flip-photo-carousel__title {
        font-size: 0.85rem;
    }

}
