/* ============================================================================
   VIMEO ELEMENT (template 1392) — video library over Cloudflare Worker
   Loaded from the clickfunnel <h:head> only when a Vimeo subarticle is present
   (see article.sps.clickfunnel.xhtml). Markup is produced by
   article.sps.clickfunnel.vimeo.xhtml + its inline JS.

   IMPORTANT — button resets:
   The clickfunnel theme styles EVERY <button> (main.css + sps.css):
       .btn, button { display:block; width:100%; ... }
       .btn, button, .btn-primary {
           background-color: var(--clr-secondary);
           color: var(--clr-secondary-contrast) !important; }
   The filters and the video cards are <button>s, so each rule below must reset
   those theme styles. The few !important flags override the theme's own
   !important colour declarations — do not remove them.

   Colours use the sps.css design tokens (with fallbacks) so the element adapts
   to the customer palette (primary/secondary/accent) and to light/dark sections:
       --clr-secondary  purple  #A64690  (matches the site's buttons)
       --clr-secondary-contrast  #fff
       --clr-black-* / --clr-white-*  opacity ramps
       (the spaces around that slash are load-bearing: an asterisk directly followed
        by a slash would close this comment right there)
   ========================================================================== */

.vimeo-section { position: relative; }

.vimeo-library {
    --vimeo-accent          : var(--clr-secondary, #A64690);
    --vimeo-accent-contrast : var(--clr-secondary-contrast, #fff);
    /* hover shade of the accent. Static fallback = the house violet darkened by 18 %;
       initAccentDark() recalculates it from the accent that is actually in effect, so
       a different --clr-secondary (or the blue swap on violet blocks) stays correct. */
    --vimeo-accent-dark     : #883976;
    --vimeo-border          : var(--clr-black-20, rgba(0, 0, 0, .2));
    /* Fill of the search field. A transparent input disappears on the flat section
       backgrounds this element sits on, so it gets a faint tint of its own instead.
       Deliberately an alpha value, not a fixed grey: it has to sit on the page
       background AND on a tinted showcase block without either turning into a patch. */
    --vimeo-input-bg        : rgba(0, 0, 0, .05);
    --vimeo-radius          : 8px;
    --vimeo-fade            : 2.5rem;   /* row edge fade, matched to the arrow width */
    text-align: center;
}

/* On dark sections the neutral border and the input fill need to be light instead of dark */
.text-light .vimeo-library,
.bg-dark-gray .vimeo-library,
.bg-black .vimeo-library {
    --vimeo-border: var(--clr-white-20, rgba(255, 255, 255, .25));
    --vimeo-input-bg: rgba(255, 255, 255, .08);
}

/* ---- tag filter pills + sort pills ---------------------------------------- */
.vimeo-library .vimeo-filter { display: flex; flex-wrap: wrap; gap: .6rem; justify-content: center; margin: 0 0 2.25rem; }
.vimeo-library .vimeo-filter:empty { display: none; }
/* the sort bar sits closer to the grid than the filter bar and carries a label */
.vimeo-library .vimeo-sort { display: flex; flex-wrap: wrap; gap: .6rem; align-items: center; justify-content: center; margin: 0 0 1.75rem; }
/* the display:flex above would otherwise defeat the [hidden] init() sets */
.vimeo-library .vimeo-sort[hidden] { display: none; }
.vimeo-library .vimeo-sort-label {
    font-family: var(--ff-accent, inherit);
    font-size: .8rem;
    font-weight: 600;
    opacity: .7;
}
.vimeo-library .vimeo-filter button,
.vimeo-library .vimeo-sort button {
    display: inline-block;
    width: auto !important;
    margin: 0;
    padding: .45rem 1.15rem;
    border: 1px solid var(--vimeo-border) !important;
    border-radius: 2rem;
    background: transparent !important;
    box-shadow: none !important;
    color: inherit !important;
    font-family: var(--ff-accent, inherit);
    font-size: .85rem;
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: normal;
    text-transform: none;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color .2s ease, border-color .2s ease, color .2s ease;
}
/* full border shorthand, not just border-color — see the note at .vimeo-tag:hover */
.vimeo-library .vimeo-filter button:hover,
.vimeo-library .vimeo-filter button:focus,
.vimeo-library .vimeo-filter button:active,
.vimeo-library .vimeo-sort button:hover,
.vimeo-library .vimeo-sort button:focus,
.vimeo-library .vimeo-sort button:active { border: 1px solid var(--vimeo-accent) !important; background: transparent !important; color: inherit !important; }
.vimeo-library .vimeo-filter button.is-active,
.vimeo-library .vimeo-sort button.is-active {
    background: var(--vimeo-accent) !important;
    border: 1px solid var(--vimeo-accent) !important;
    color: var(--vimeo-accent-contrast) !important;
}
/* the active pill keeps its fill on hover, just a shade darker */
.vimeo-library .vimeo-filter button.is-active:hover,
.vimeo-library .vimeo-filter button.is-active:focus,
.vimeo-library .vimeo-filter button.is-active:active,
.vimeo-library .vimeo-sort button.is-active:hover,
.vimeo-library .vimeo-sort button.is-active:focus,
.vimeo-library .vimeo-sort button.is-active:active {
    background: var(--vimeo-accent-dark) !important;
    border: 1px solid var(--vimeo-accent-dark) !important;
    color: var(--vimeo-accent-contrast) !important;
}

/* ---- collapsible groups --------------------------------------------------- */
.vimeo-library .vimeo-group { text-align: left; border-top: 1px solid var(--vimeo-border); }
.vimeo-library .vimeo-group:last-child { border-bottom: 1px solid var(--vimeo-border); }

/* the header is a <button>: full width is wanted here, but the theme's colour,
   padding, shadow and uppercase must still be reset */
.vimeo-library .vimeo-group-header {
    display: flex;
    align-items: center;
    gap: .75rem;
    width: 100% !important;
    margin: 0;
    padding: 1.1rem .25rem;
    border: 0 !important;
    background: transparent !important;
    box-shadow: none !important;
    color: inherit !important;
    font-family: inherit;
    font-weight: 700;
    letter-spacing: normal;
    text-transform: none;
    text-align: left;
    cursor: pointer;
}
.vimeo-library .vimeo-group-title { flex: 1 1 auto; font-size: 1.35rem; line-height: 1.2; }
.vimeo-library .vimeo-group-count {
    flex: 0 0 auto;
    min-width: 1.6rem;
    padding: .1rem .5rem;
    border-radius: 1rem;
    /* Accent fill instead of the neutral border colour: the chip was barely legible
       against the section background. The accent is safe on tinted blocks too —
       toneStyle()/pickAccent() in the template re-declare --vimeo-accent (and its
       contrast colour) on the tinted element, incl. the violet-on-violet swap to blue. */
    background: var(--vimeo-accent);
    color: var(--vimeo-accent-contrast);
    font-size: .8rem;
    font-weight: 600;
    text-align: center;
}
.vimeo-library .vimeo-group-chevron {
    flex: 0 0 auto;
    font-size: .9rem;
    transition: transform .25s ease;
}
/* Bootstrap collapse toggles aria-expanded on the header button; rotate the
   chevron when the group is collapsed (the .collapse animation is Bootstrap's) */
.vimeo-library .vimeo-group-header[aria-expanded="false"] .vimeo-group-chevron { transform: rotate(-90deg); }
.vimeo-library .vimeo-group-inner { padding-bottom: 1.75rem; }

/* local showcase description (field08, column 1) — sits under the group/row title and
   stays visible while a collapse group is closed */
.vimeo-library .vimeo-group-desc {
    max-width: 70ch;
    margin: -.35rem 0 1.1rem;
    padding: 0 .25rem;
    font-size: .9rem;
    line-height: 1.5;
    opacity: .8;
    text-align: left;
}
.vimeo-library--rows .vimeo-group-desc { margin: -.5rem 0 1rem; padding: 0; }

/* ---- grid + cards --------------------------------------------------------- */
.vimeo-library .vimeo-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 1.5rem;
    align-items: start;   /* top-align cards in a row (no stretch on uneven titles) */
}
/* The card button and the bookmark toggle are siblings (no nested buttons), so the
   wrapper is what the overlay positions itself against. */
.vimeo-library .vimeo-card-wrap { position: relative; }
.vimeo-library .vimeo-card {
    display: block;
    width: 100% !important;
    margin: 0;
    padding: 0;
    border: 0 !important;
    background: transparent !important;
    box-shadow: none !important;
    color: inherit !important;
    text-align: left;
    font-weight: normal;
    letter-spacing: normal;
    text-transform: none;
    cursor: pointer;
}
.vimeo-library .vimeo-card[disabled] {
    cursor: default;
    opacity: .55;
}

/* ---- thumbnail (16:9 responsive box) -------------------------------------- */
.vimeo-library .vimeo-thumb {
    display: block;                 /* required: <span> defaults to inline, which
                                       collapses the padding-bottom aspect box */
    position: relative;
    width: 100%;
    padding-bottom: 56.25%;
    overflow: hidden;
    border-radius: var(--vimeo-radius);
    background: #111;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .18);
}
.vimeo-library .vimeo-thumb img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform .35s ease;
}
.vimeo-library .vimeo-card:hover .vimeo-thumb img { transform: scale(1.06); }

/* ---- play badge ----------------------------------------------------------- */
.vimeo-library .vimeo-play {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 58px;
    height: 58px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(0, 0, 0, .55);
    color: #fff;
    font-size: 1.35rem;
    padding-left: 3px;              /* optically centre the play triangle */
    transition: background-color .2s ease, transform .2s ease;
}
.vimeo-library .vimeo-card:hover .vimeo-play {
    background: var(--vimeo-accent);
    transform: translate(-50%, -50%) scale(1.08);
}
.vimeo-library .vimeo-card[disabled] .vimeo-play { display: none; }

/* Card decoration only — the colour change on hover stays, the movement goes.
   (Row scrolling and the hover overlay are guarded separately: JS reducedMotion()
   and the media query next to .vimeo-hover-inner.) */
@media (prefers-reduced-motion: reduce) {
    .vimeo-library .vimeo-thumb img { transition: none; }
    .vimeo-library .vimeo-card:hover .vimeo-thumb img { transform: none; }
    .vimeo-library .vimeo-play { transition: background-color .2s ease; }
    .vimeo-library .vimeo-card:hover .vimeo-play { transform: translate(-50%, -50%); }
}

/* ---- duration badge ------------------------------------------------------- */
.vimeo-library .vimeo-duration {
    position: absolute;
    right: .5rem;
    bottom: .5rem;
    padding: .15rem .45rem;
    border-radius: .25rem;
    background: rgba(0, 0, 0, .8);
    color: #fff;
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .5px;
}

/* ---- card title ----------------------------------------------------------- */
.vimeo-library .vimeo-card-title {
    display: block;
    margin: .7rem 0 0;
    font-size: .95rem;
    font-weight: 300;
    line-height: 1.35;
    color: inherit !important;
    letter-spacing: normal;
    text-transform: none;
}

/* ---- states --------------------------------------------------------------- */
.vimeo-library .vimeo-status,
.vimeo-library .vimeo-empty {
    text-align: center;
    padding: 2rem 0;
}
.vimeo-library .vimeo-empty { opacity: .7; }
.vimeo-login-hint { text-align: center; }

/* ---- reveal after the fetch ------------------------------------------------
   The Worker call can take several seconds. Until it returns there is nothing to
   search, sort or filter, so the whole control chrome stays out of the way and only
   the spinner shows; init() then adds .is-ready and everything fades in together.
   .is-ready is set ONLY on the success path and only when at least one video came
   back — an error message or an empty library therefore no longer gets a search
   field and a "Verlauf löschen" button stacked above it.
   The sort bar keeps its own [hidden] attribute (it also encodes "more than one
   video"); it just joins the same animation when init() unhides it. */
.vimeo-library:not(.is-ready) .vimeo-search,
.vimeo-library:not(.is-ready) .vimeo-filter,
.vimeo-library:not(.is-ready) .vimeo-watchctl { display: none; }

/* ---- consent gate ----------------------------------------------------------
   Until consent only the cc-embed placeholder is visible; the inline script removes
   .is-gated and only then fetches the list (see css/cc-embed.css for the box). */
.vimeo-library.is-gated > :not(.vimeo-gate) { display: none !important; }
.vimeo-library .vimeo-gate[hidden] { display: none; }
.vimeo-library .vimeo-gate { min-height: 220px; }
.vimeo-library .vimeo-gate .cc-embed__ph { min-height: 220px; border-radius: var(--vimeo-radius); }

@keyframes vimeo-fade-in {
    from { opacity: 0; transform: translateY(-.25rem); }
    to   { opacity: 1; transform: none; }
}
.vimeo-library.is-ready .vimeo-search,
.vimeo-library.is-ready .vimeo-filter,
.vimeo-library.is-ready .vimeo-sort,
.vimeo-library.is-ready .vimeo-watchctl,
.vimeo-library.is-ready .vimeo-groups {
    animation: vimeo-fade-in .35s ease both;
}
/* the groups come last so the controls are settled before the thumbnails arrive */
.vimeo-library.is-ready .vimeo-groups { animation-delay: .1s; }

@media (prefers-reduced-motion: reduce) {
    .vimeo-library.is-ready .vimeo-search,
    .vimeo-library.is-ready .vimeo-filter,
    .vimeo-library.is-ready .vimeo-sort,
    .vimeo-library.is-ready .vimeo-watchctl,
    .vimeo-library.is-ready .vimeo-groups { animation: none; }
}

/* ===========================================================================
   FULL WIDTH (field07 = 5)
   The library breaks out of the content container; the first card still lines
   up with the page text via the inline padding below.
   ========================================================================== */
.vimeo-section .vimeo-fullwidth { padding-left: 0; padding-right: 0; }
.vimeo-section .vimeo-fullwidth > .row { margin-left: 0; margin-right: 0; }
.vimeo-section .vimeo-fullwidth > .row > .col-12 { padding-left: 0; padding-right: 0; }
.vimeo-fullwidth .vimeo-library {
    --vimeo-edge: clamp(1rem, 5vw, 4rem);
}
.vimeo-fullwidth .vimeo-library .vimeo-filter,
.vimeo-fullwidth .vimeo-library .vimeo-sort,
.vimeo-fullwidth .vimeo-library .vimeo-search,
.vimeo-fullwidth .vimeo-library .vimeo-watchctl,
.vimeo-fullwidth .vimeo-library .vimeo-row-title,
.vimeo-fullwidth .vimeo-library .vimeo-group,
.vimeo-fullwidth .vimeo-library .vimeo-grid,
/* only in rows mode — in collapse mode the description inherits the padding of its
   .vimeo-group parent, which is already in this list */
.vimeo-fullwidth .vimeo-library--rows .vimeo-group-desc {
    padding-left: var(--vimeo-edge);
    padding-right: var(--vimeo-edge);
}
.vimeo-fullwidth .vimeo-library .vimeo-row-track {
    padding-left: var(--vimeo-edge);
    padding-right: var(--vimeo-edge);
    scroll-padding-left: var(--vimeo-edge);
}

/* ===========================================================================
   SEARCH BAR (field34 = Ja)
   ========================================================================== */
.vimeo-library .vimeo-search {
    position: relative;
    max-width: 30rem;
    margin: 0 auto 2.25rem;
}
.vimeo-library .vimeo-search-input {
    width: 100%;
    padding: .7rem 2.8rem .7rem 1.3rem;
    border: 1px solid var(--vimeo-border);
    border-radius: 2rem;
    /* faint fill + inset shadow so the field reads as an input on a flat section
       background; see --vimeo-input-bg for why this is an alpha value */
    background: var(--vimeo-input-bg);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, .06);
    color: inherit;
    font-size: .95rem;
    line-height: 1.3;
    -webkit-appearance: none;
    appearance: none;
}
.vimeo-library .vimeo-search-input::-webkit-search-cancel-button { display: none; }
.vimeo-library .vimeo-search-input:focus {
    outline: none;
    border-color: var(--vimeo-accent);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, .06), 0 0 0 3px rgba(127, 127, 127, .18);
}
/* One control, two faces: the magnifier is a plain hint while the field is empty
   (not clickable, not focusable — see syncSearchIcon()), the cross takes over as
   soon as something is typed and resets the search. */
.vimeo-library .vimeo-search-clear {
    position: absolute;
    top: 50%;
    right: .5rem;
    transform: translateY(-50%);
    width: auto !important;
    margin: 0;
    padding: .35rem .6rem;
    border: 0 !important;
    background: transparent !important;
    box-shadow: none !important;
    color: inherit !important;
    opacity: .6;
    cursor: default;
    pointer-events: none;
}
.vimeo-library .vimeo-search.is-clearable .vimeo-search-clear {
    cursor: pointer;
    pointer-events: auto;
}
.vimeo-library .vimeo-search.is-clearable .vimeo-search-clear:hover,
.vimeo-library .vimeo-search.is-clearable .vimeo-search-clear:focus { opacity: 1; }
.vimeo-library .vimeo-search .vimeo-search-ico-clear,
.vimeo-library .vimeo-search.is-clearable .vimeo-search-ico-find { display: none; }
.vimeo-library .vimeo-search.is-clearable .vimeo-search-ico-clear { display: inline-block; }

/* ===========================================================================
   WATCH-STATE CONTROLS (field35 = 1 oder 2)
   ========================================================================== */
.vimeo-library .vimeo-watchctl {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: .5rem 1.25rem;
    margin: -1rem 0 2rem;
    font-size: .82rem;
}
.vimeo-library .vimeo-watch-label {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    margin: 0;
    font-weight: 600;
    cursor: pointer;
}
.vimeo-library .vimeo-watch-label input { width: auto; margin: 0; }
.vimeo-library .vimeo-watch-clear {
    width: auto !important;
    margin: 0;
    padding: .3rem .9rem;
    border: 1px solid var(--vimeo-border) !important;
    border-radius: 2rem;
    background: transparent !important;
    box-shadow: none !important;
    color: inherit !important;
    font-family: inherit;
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: normal;
    text-transform: none;
    cursor: pointer;
}
.vimeo-library .vimeo-watch-clear:hover,
.vimeo-library .vimeo-watch-clear:focus,
.vimeo-library .vimeo-watch-clear:active { border: 1px solid var(--vimeo-accent) !important; }
.vimeo-library .vimeo-watch-hint { opacity: .7; }
.vimeo-progress-form { display: none; }

/* ===========================================================================
   WATCH BADGES — seen marker, progress bar, "Neu"
   Deliberately NOT scoped to .vimeo-library: badgesHtml() also renders these into
   the hover preview, and that layer hangs off <body>, outside the library element.
   ========================================================================== */
.vimeo-new {
    position: absolute;
    top: .5rem;
    left: .5rem;
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    padding: .15rem .5rem;
    border-radius: .25rem;
    background: var(--vimeo-accent, #A64690);
    color: var(--vimeo-accent-contrast, #fff);
    font-size: .7rem;
    font-weight: 700;
    letter-spacing: .3px;
    text-transform: uppercase;
}
/* „already seen": icon only, opposite corner from „Neu" so both can show at once */
.vimeo-seen {
    position: absolute;
    top: .5rem;
    right: .5rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.55rem;
    height: 1.55rem;
    border-radius: 50%;
    background: rgba(0, 0, 0, .72);
    color: #fff;
    font-size: .72rem;
    line-height: 1;
}
/* how much of the video has been watched — sits on the bottom edge of the thumb */
.vimeo-progress {
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    height: 4px;
    background: rgba(255, 255, 255, .25);
}
.vimeo-progress > span {
    display: block;
    height: 100%;
    background: var(--vimeo-accent, #A64690);
}
/* watched cards recede a little until hovered */
.vimeo-library .vimeo-card.is-watched .vimeo-thumb img { opacity: .68; }
.vimeo-library .vimeo-card.is-watched:hover .vimeo-thumb img { opacity: 1; }

/* ===========================================================================
   NETFLIX ROWS (field33 = Ja)
   Native horizontal scrolling (touch) + arrow buttons on fine pointers.
   ========================================================================== */
.vimeo-library--rows .vimeo-row { margin: 0 0 2.5rem; text-align: left; }
.vimeo-library--rows .vimeo-row-title {
    display: flex;
    /* center, not baseline: on a shared baseline the much smaller count sits on the
       title's baseline and reads as bottom-aligned */
    align-items: center;
    gap: .6rem;
    margin: 0 0 .85rem;
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.2;
}
/* Rows mode (the default) prints the count next to the showcase title as plain text.
   opacity .55 on top of the inherited text colour made it the least legible thing in
   the row — the accent colour at full opacity keeps it quiet but readable, and follows
   the branding table like every other accented detail. */
.vimeo-library--rows .vimeo-row-count {
    font-size: .75rem;
    font-weight: 600;
    color: var(--vimeo-accent);
}
.vimeo-library--rows .vimeo-row-wrap { position: relative; }
.vimeo-library--rows .vimeo-row-track {
    display: flex;
    gap: 1rem;
    overflow-x: auto;
    overflow-y: hidden;
    padding-bottom: .5rem;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
.vimeo-library--rows .vimeo-row-track::-webkit-scrollbar { display: none; }
.vimeo-library--rows .vimeo-row-track:focus-visible { outline: 2px solid var(--vimeo-accent); outline-offset: 4px; }
.vimeo-library--rows .vimeo-row-item {
    flex: 0 0 clamp(180px, 22vw, 320px);
    scroll-snap-align: start;
}
.vimeo-library--rows .vimeo-row-nav {
    position: absolute;
    top: 0;
    bottom: .5rem;
    z-index: 3;
    width: 2.75rem !important;
    margin: 0;
    padding: 0;
    border: 0 !important;
    background: rgba(0, 0, 0, .45) !important;
    box-shadow: none !important;
    color: #fff !important;
    font-size: 1.35rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0;
    transition: opacity .2s ease, background-color .2s ease;
}
.vimeo-library--rows .vimeo-row-prev { left: 0; border-radius: 0 var(--vimeo-radius) var(--vimeo-radius) 0; }
.vimeo-library--rows .vimeo-row-next { right: 0; border-radius: var(--vimeo-radius) 0 0 var(--vimeo-radius); }
.vimeo-library--rows .vimeo-row-wrap:hover .vimeo-row-nav,
.vimeo-library--rows .vimeo-row-nav:focus-visible { opacity: 1; }
.vimeo-library--rows .vimeo-row-nav:hover { background: rgba(0, 0, 0, .7) !important; }
/* no hover on touch: keep the arrows out of the way entirely */
@media (hover: none), (pointer: coarse) {
    .vimeo-library--rows .vimeo-row-nav { display: none !important; }
}

/* ---- edge fade ------------------------------------------------------------
   Softens the side where the row continues. Driven by the same has-prev /
   has-next classes as the arrows (set in update() in bindRows), so a row that
   sits at either end keeps its first/last card at full opacity. */
.vimeo-library--rows .has-prev .vimeo-row-track {
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 var(--vimeo-fade));
            mask-image: linear-gradient(to right, transparent 0, #000 var(--vimeo-fade));
}
.vimeo-library--rows .has-next .vimeo-row-track {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - var(--vimeo-fade)), transparent 100%);
            mask-image: linear-gradient(to right, #000 calc(100% - var(--vimeo-fade)), transparent 100%);
}
.vimeo-library--rows .has-prev.has-next .vimeo-row-track {
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 var(--vimeo-fade),
                                        #000 calc(100% - var(--vimeo-fade)), transparent 100%);
            mask-image: linear-gradient(to right, transparent 0, #000 var(--vimeo-fade),
                                        #000 calc(100% - var(--vimeo-fade)), transparent 100%);
}

/* In rows mode the card itself stays completely still — the enlarged version is
   the hover overlay, so the old thumbnail zoom would read as a double animation. */
.vimeo-library--rows .vimeo-card:hover .vimeo-thumb img { transform: none; }
.vimeo-library--rows .vimeo-card:hover .vimeo-play { background: rgba(0, 0, 0, .55); transform: translate(-50%, -50%); }

/* Touch: der Tap auf die Karte oeffnet die Vorschau, abgespielt wird nur ueber das
   Play-Abzeichen (siehe bindCards()). Damit ist es dort kein blosser Aufhuebscher mehr,
   sondern das eigentliche Bedienelement — die Akzentfarbe hebt es vom uebrigen Thumbnail
   ab, so wie auf dem Desktop der Hover-Zustand.
   Die :hover-Variante steht mit in der Auswahl, weil manche Touch-Browser :hover nach
   einem Tap haengen lassen und die Regel eine Zeile darueber sonst gewinnen wuerde. */
@media (hover: none), (pointer: coarse) {
    .vimeo-library--rows .vimeo-card .vimeo-play,
    .vimeo-library--rows .vimeo-card:hover .vimeo-play {
        background: var(--vimeo-accent);
    }
}

/* ---- hover preview layer (body-level, so the scroller cannot clip it) ------ */
.vimeo-hover {
    position: fixed;
    z-index: 1900;
    display: none;
    text-align: left;
    font-family: inherit;
}
.vimeo-hover.is-open { display: block; }
.vimeo-hover-inner {
    --vimeo-accent          : var(--clr-secondary, #A64690);
    --vimeo-accent-contrast : var(--clr-secondary-contrast, #fff);
    --vimeo-accent-dark     : #883976;
    --vimeo-radius          : 8px;
    overflow: hidden;
    border-radius: var(--vimeo-radius);
    background: #1a1a1a;
    color: #fff;
    box-shadow: rgba(0, 0, 0, .75) 0 3px 10px;   /* as Netflix */
    /* Grows out of the card: the JS sets --vimeo-hover-from to
       cardWidth / overlayWidth, so the start state covers exactly the card
       footprint and the growth is the full 1 : 1.5 step, not a hint of one.
       Closing is deliberately much quicker than opening (Netflix does the same) —
       a slow shrink back reads as lag when the pointer has already moved on. */
    opacity: 0;
    transform: scale(var(--vimeo-hover-from, .7)) translateZ(0);
    transform-origin: 50% 50%;
    transition: opacity .12s ease, transform .14s cubic-bezier(.5, 0, .1, 1);
    will-change: transform;
}
.vimeo-hover.is-visible .vimeo-hover-inner {
    opacity: 1;
    transform: scale(1) translateZ(0);
    transition: opacity .18s ease, transform .3s cubic-bezier(.5, 0, .1, 1);
}
@media (prefers-reduced-motion: reduce) {
    .vimeo-hover-inner { transition: none; opacity: 1; transform: none; }
}
.vimeo-hover .vimeo-thumb {
    display: block;
    position: relative;
    width: 100%;
    padding-bottom: 56.25%;
    overflow: hidden;
    background: #111;
    cursor: pointer;
}
.vimeo-hover .vimeo-thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.vimeo-hover .vimeo-play {
    position: absolute; top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    display: flex; align-items: center; justify-content: center;
    width: 54px; height: 54px;
    padding-left: 3px;
    border-radius: 50%;
    background: rgba(0, 0, 0, .55);
    color: #fff; font-size: 1.25rem;
}
.vimeo-hover .vimeo-duration {
    position: absolute; right: .5rem; bottom: .5rem;
    padding: .15rem .45rem; border-radius: .25rem;
    background: rgba(0, 0, 0, .8); color: #fff; font-size: .72rem; font-weight: 600;
}
/* badge geometry now comes from the unscoped rules above; the overlay only has to
   supply the accent colour, since --vimeo-accent is declared on .vimeo-library and
   this layer is not inside it (it is re-declared on .vimeo-hover-inner). */
.vimeo-hover-body { padding: .85rem 1rem 1rem; }
.vimeo-hover-title { font-size: 1rem; font-weight: 700; line-height: 1.3; }
.vimeo-hover-meta {
    display: flex; flex-wrap: wrap; gap: .25rem .75rem;
    margin: .35rem 0 0;
    font-size: .78rem; opacity: .75;
}
.vimeo-hover-seen { color: #7ddb7d; opacity: 1; font-weight: 600; }
.vimeo-hover-tags,
.vimeo-details-tags { display: flex; flex-wrap: wrap; gap: .3rem; margin: .6rem 0 0; }

/* clickable tag chips (hover block + details view) */
.vimeo-tag {
    width: auto !important;
    margin: 0;
    padding: .12rem .55rem;
    border: 1px solid rgba(255, 255, 255, .3) !important;
    border-radius: 1rem;
    background: transparent !important;
    box-shadow: none !important;
    color: #fff !important;
    font-family: inherit;
    font-size: .7rem;
    font-weight: 500;
    line-height: 1.5;
    letter-spacing: normal;
    text-transform: none;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color .2s ease, border-color .2s ease;
}
/* The theme drops the border on ANY button hover
   (sps.css: `button:hover, button:focus, button:active { border: none !important; }`),
   which made bordered controls shrink by 2px on hover. Overriding border-color alone
   is not enough — `border: none` also kills the style, so the whole shorthand has to be
   restated here, and the selector needs to out-specify `button:hover`. */
.vimeo-hover-tags .vimeo-tag:hover,
.vimeo-hover-tags .vimeo-tag:focus,
.vimeo-hover-tags .vimeo-tag:active,
.vimeo-details-tags .vimeo-tag:hover,
.vimeo-details-tags .vimeo-tag:focus,
.vimeo-details-tags .vimeo-tag:active {
    border: 1px solid var(--vimeo-accent, #A64690) !important;
    background: var(--vimeo-accent, #A64690) !important;
    color: var(--vimeo-accent-contrast, #fff) !important;
}

.vimeo-hover-actions { display: flex; align-items: center; gap: .5rem; margin: .85rem 0 0; }
/* Details sits on the right edge of the block */
.vimeo-hover-actions .vimeo-hover-details { margin-left: auto; }
/* All three (Abspielen, Details, Merken) share one box: same display model, same
   padding, same font, same line-height — otherwise a block-level button and an
   inline-flex one end up different heights even with identical padding. */
.vimeo-hover-actions button {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    width: auto !important;
    margin: 0;
    padding: .4rem .85rem;
    border: 1px solid rgba(255, 255, 255, .3) !important;
    border-radius: 2rem;
    background: transparent !important;
    box-shadow: none !important;
    color: #fff !important;
    font-family: inherit;
    font-size: .78rem;
    font-weight: 600;
    line-height: 1.25;
    letter-spacing: normal;
    text-transform: none;
    white-space: nowrap;
    cursor: pointer;
}
/* the icons must not drag the line box around either */
.vimeo-hover-actions button i { font-size: 1em; line-height: 1; }
/* Icon-only buttons (Details, Merken): square, i.e. exactly as wide as the row is high,
   so they read as a pair of round chips next to the labelled "Abspielen".
   The height stays content-driven (same font-size, line-height and vertical padding as
   the labelled sibling); aspect-ratio then derives the width from it, so all three keep
   one height and nothing has to be hard-coded in px.
   Older browsers without aspect-ratio simply get a tighter, non-square button — the
   overflow that cut "Gemerkt" off is already gone through the dropped labels. */
.vimeo-hover-actions button.is-icon {
    padding-inline: .4rem;
    aspect-ratio: 1;
    justify-content: center;
    gap: 0;
}
/* keeps its border on hover as well — see the note at .vimeo-tag:hover */
.vimeo-hover-actions button:hover,
.vimeo-hover-actions button:focus,
.vimeo-hover-actions button:active {
    border: 1px solid #fff !important;
    background: rgba(255, 255, 255, .12) !important;
    color: #fff !important;
}
.vimeo-hover-actions .vimeo-hover-play {
    border: 1px solid var(--vimeo-accent) !important;
    background: var(--vimeo-accent) !important;
    color: var(--vimeo-accent-contrast) !important;
}
.vimeo-hover-actions .vimeo-hover-play:hover,
.vimeo-hover-actions .vimeo-hover-play:focus,
.vimeo-hover-actions .vimeo-hover-play:active {
    border: 1px solid var(--vimeo-accent-dark) !important;
    background: var(--vimeo-accent-dark) !important;
    color: var(--vimeo-accent-contrast) !important;
}

/* ---- details view inside the modal ---------------------------------------- */
.vimeo-modal-details { display: none; }
.vimeo-modal.is-details .vimeo-modal-embed { display: none; }
.vimeo-modal.is-details .vimeo-modal-details { display: block; }
.vimeo-details {
    display: flex;
    flex-wrap: wrap;
    max-height: 86vh;
    overflow-y: auto;
    border-radius: var(--vimeo-radius, 8px);
    background: #1a1a1a;
    color: #fff;
    text-align: left;
}
/* left column: preview image, then tags, then the play button */
.vimeo-details-side { flex: 1 1 280px; min-width: 240px; padding: 1.5rem 0 1.5rem 1.5rem; }
.vimeo-details-thumb { overflow: hidden; border-radius: var(--vimeo-radius, 8px); }
.vimeo-details-thumb img { display: block; width: 100%; height: auto; }
.vimeo-details-body { flex: 1 1 320px; padding: 1.5rem; }
@media (max-width: 575px) {
    .vimeo-details-side { padding: 1rem 1rem 0; }
    .vimeo-details-body { padding: 1rem; }
}
.vimeo-details-body h3 { margin: 0 0 .5rem; font-size: 1.35rem; line-height: 1.25; color: #fff; }
.vimeo-details-meta {
    display: flex; flex-wrap: wrap; gap: .25rem .9rem;
    margin: 0 0 .9rem;
    font-size: .8rem; opacity: .75;
}
.vimeo-details-text { font-size: .9rem; line-height: 1.5; max-height: 45vh; overflow-y: auto; }
/* The box is a tab stop (tabindex="0" in openDetails) because it scrolls, so it needs a
   visible focus ring — same treatment as the row scroller. */
.vimeo-details-text:focus-visible {
    outline: 2px solid var(--vimeo-accent, #A64690);
    outline-offset: 4px;
}
.vimeo-details-play {
    display: block;
    width: auto !important;
    margin: 1rem 0 0;
    padding: .5rem 1.2rem;
    border: 0 !important;
    border-radius: 2rem;
    background: var(--vimeo-accent, #A64690) !important;
    box-shadow: none !important;
    color: var(--vimeo-accent-contrast, #fff) !important;
    font-family: inherit;
    font-size: .85rem;
    font-weight: 700;
    letter-spacing: normal;
    text-transform: none;
    cursor: pointer;
}
.vimeo-details-play:hover,
.vimeo-details-play:focus,
.vimeo-details-play:active {
    background: var(--vimeo-accent-dark, #883976) !important;
    color: var(--vimeo-accent-contrast, #fff) !important;
}

/* ---- fullscreen player modal ---------------------------------------------- */
.vimeo-modal { display: none; position: fixed; inset: 0; z-index: 2000; }
/* flex-centre the dialog vertically & horizontally while open */
.vimeo-modal.is-open { display: flex; align-items: center; justify-content: center; padding: 2rem 0; }
.vimeo-modal-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, .85); }
.vimeo-modal-dialog {
    position: relative;
    width: 92%;
    max-width: 960px;
    margin: 0;
}
/* Details view zooms out of the clicked preview: the JS sets the start transform
   from the two bounding boxes and adds .is-zooming for the run back to identity.
   The class is removed afterwards so dragging/resizing never animates the dialog. */
.vimeo-modal-dialog.is-zooming {
    transition: transform .3s cubic-bezier(.5, 0, .1, 1), opacity .22s ease;
    will-change: transform;
}
@media (prefers-reduced-motion: reduce) {
    .vimeo-modal-dialog.is-zooming { transition: none; }
}
.vimeo-modal-embed { position: relative; height: 0; padding-bottom: 56.25%; }
.vimeo-modal-embed iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
    border-radius: var(--vimeo-radius);
    background: #000;               /* opaque fill while the Vimeo player loads */
}
.vimeo-modal-close {
    position: absolute;
    z-index: 5;                     /* stays clickable above the details box */
    top: -2.75rem;
    right: 0;
    width: auto !important;
    margin: 0;
    padding: .25rem .5rem;
    border: 0 !important;
    background: transparent !important;
    box-shadow: none !important;
    color: #fff !important;
    font-size: 1.75rem;
    line-height: 1;
    cursor: pointer;
}

/* ===========================================================================
   CUSTOM COLOURS (field03/field04 for the whole section,
   field08 columns 3+4 per showcase block)
   The values arrive as the inline custom properties --vimeo-tone-bg and
   --vimeo-tone-fg; the resolver in article.sps.clickfunnel.vimeo.xhtml sets
   them (named colour or hex, with the readable text colour derived from the
   background). The generous padding is the point of the exercise: the colour
   must never sit flush against a heading or the first row of thumbnails.
   ========================================================================== */
.vimeo-section.has-tint {
    background: var(--vimeo-tone-bg) !important;
    color: var(--vimeo-tone-fg) !important;
    padding-top: 3rem;
    padding-bottom: 3rem;
}
/* headings and rich text inside the section inherit instead of keeping the
   theme colour they were given by main.css/sps.css */
.vimeo-section.has-tint h1,
.vimeo-section.has-tint h2,
.vimeo-section.has-tint h3,
.vimeo-section.has-tint h4,
.vimeo-section.has-tint p,
.vimeo-section.has-tint li,
.vimeo-section.has-tint .vimeo-library { color: inherit !important; }

/* per-showcase block */
.vimeo-library .vimeo-group.has-tint,
.vimeo-library--rows .vimeo-row.has-tint {
    background: var(--vimeo-tone-bg);
    color: var(--vimeo-tone-fg);
    /* The neutral border is derived from the page background and would vanish on a
       coloured block. A mid grey with alpha reads on a light and on a dark tint alike. */
    --vimeo-border: rgba(127, 127, 127, .45);
    border-radius: var(--vimeo-radius);
    padding: 1.75rem;
    margin-bottom: 2.5rem;
}
/* Two tinted blocks in sequence have to touch — a gap would let the section
   background run between them like a stripe. The classes come from joinClass() in
   the template (CSS cannot look ahead, and :has() is avoided for older browsers):
   the shared edge loses the margin and its rounded corners, so the two colours meet
   in a clean line. Against a NON-tinted neighbour the 2.5 rem stay. */
.vimeo-library .vimeo-group.has-tint.is-joined-next,
.vimeo-library--rows .vimeo-row.has-tint.is-joined-next {
    margin-bottom: 0;
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
}
.vimeo-library .vimeo-group.has-tint.is-joined-prev,
.vimeo-library--rows .vimeo-row.has-tint.is-joined-prev {
    border-top-left-radius: 0;
    border-top-right-radius: 0;
}

.vimeo-library .vimeo-group.has-tint h3,
.vimeo-library .vimeo-group.has-tint .vimeo-group-header,
.vimeo-library--rows .vimeo-row.has-tint h3 { color: inherit !important; }
/* No count override for tinted blocks any more: both counts now follow --vimeo-accent,
   and toneStyle() re-declares that variable (plus --vimeo-accent-contrast, and the
   violet-on-violet swap to blue) ON the tinted element itself. The old translucent grey
   was only needed while the chip was filled with --vimeo-border, which is derived from
   the page background and vanished on a coloured block. */
/* collapse variant: the top border of the first group would cut the tint in half */
.vimeo-library .vimeo-group.has-tint { border-top: 0; }
.vimeo-library .vimeo-group.has-tint:last-child { border-bottom: 0; }
.vimeo-library .vimeo-group.has-tint .vimeo-group-inner { padding-bottom: 0; }

/* Full-bleed rows: the colour band runs edge to edge, the content keeps the
   inline padding all rows have (--vimeo-edge). */
.vimeo-fullwidth .vimeo-library .vimeo-group.has-tint,
.vimeo-fullwidth .vimeo-library--rows .vimeo-row.has-tint {
    border-radius: 0;
    padding-left: 0;
    padding-right: 0;
}
.vimeo-fullwidth .vimeo-library .vimeo-group.has-tint > .vimeo-group-header,
.vimeo-fullwidth .vimeo-library .vimeo-group.has-tint > .collapse .vimeo-grid,
.vimeo-fullwidth .vimeo-library--rows .vimeo-row.has-tint > .vimeo-row-title {
    padding-left: var(--vimeo-edge);
    padding-right: var(--vimeo-edge);
}

/* Rich text below the videos (field08, column 5). The width and the centring come
   from the page's own grid — the markup is container > row justify-content-center >
   col-12, exactly like the heading and the intro text of this element — so nothing
   here sets a width, and the --vimeo-edge padding of the full-bleed rows must NOT be
   applied to it either. */
.vimeo-library .vimeo-group-html {
    /* auto left/right, otherwise this rule would beat .container's own centring */
    margin: 1.5rem auto 0;
    font-size: .95rem;
    line-height: 1.6;
    text-align: left;
    color: inherit;
}
.vimeo-library .vimeo-group-html :last-child { margin-bottom: 0; }
.vimeo-library .vimeo-group-html a:not(.btn) { color: inherit; text-decoration: underline; }

/* ===========================================================================
   MERKLISTE (field39) — bookmark toggle on the card, in the hover preview
   and in the details view
   ========================================================================== */
.vimeo-library .vimeo-later {
    position: absolute;
    z-index: 3;                     /* above the thumbnail, below the hover overlay */
    top: .5rem;
    right: .5rem;
    width: auto !important;
    min-width: 0;
    margin: 0;
    padding: .3rem .5rem;
    border: 0 !important;
    border-radius: .3rem;
    background: rgba(0, 0, 0, .55) !important;
    box-shadow: none !important;
    color: #fff !important;
    font-size: .85rem;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
    opacity: 0;                     /* revealed on hover/focus — see below */
    transition: opacity .2s ease, background-color .2s ease;
    cursor: pointer;
}
/* Always visible once the video is on the list (otherwise the state would be
   invisible on touch devices), and always visible while the card is touched. */
.vimeo-library .vimeo-card-wrap:hover .vimeo-later,
.vimeo-library .vimeo-later:focus,
.vimeo-library .vimeo-later.is-on { opacity: 1; }
@media (hover: none) {
    .vimeo-library .vimeo-later { opacity: 1; }
}
.vimeo-library .vimeo-later:hover { background: rgba(0, 0, 0, .8) !important; }
.vimeo-library .vimeo-later.is-on { background: var(--vimeo-accent) !important; }
.vimeo-library .vimeo-later.is-on:hover { background: var(--vimeo-accent-dark) !important; }
/* The eye marker sits top right as well, so the bookmark steps aside when it is
   there. .is-watched is exactly the state that shows the eye and is kept in sync
   by refreshWatchMarkers(); a sibling selector avoids :has() for older browsers. */
.vimeo-library .vimeo-card.is-watched + .vimeo-later { right: 2.6rem; }

/* Labelled variant in the hover preview: deliberately almost NO styling of its own.
   It is a sibling of „Abspielen"/„Details" inside .vimeo-hover-actions and inherits
   that block's button look, so the three read as one set — only the overlay bits of
   .vimeo-later are undone here.
   NOTE do not re-add `border: 0` here. .vimeo-hover-actions button carries a 1px
   border and :hover only recolours it; overriding it to zero made the button grow by
   2px the moment the pointer arrived — that was the „jump". */
.vimeo-hover .vimeo-later--lg {
    position: static;
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    opacity: 1;
}
/* filled while it is on — the same treatment .vimeo-hover-play gets */
.vimeo-hover .vimeo-later--lg.is-on {
    border: 1px solid var(--vimeo-accent) !important;
    background: var(--vimeo-accent) !important;
    color: var(--vimeo-accent-contrast) !important;
}
.vimeo-hover .vimeo-later--lg.is-on:hover,
.vimeo-hover .vimeo-later--lg.is-on:focus,
.vimeo-hover .vimeo-later--lg.is-on:active {
    border: 1px solid var(--vimeo-accent-dark) !important;
    background: var(--vimeo-accent-dark) !important;
    color: var(--vimeo-accent-contrast) !important;
}

/* Details view: the outlined counterpart of .vimeo-details-play — same shape and
   metrics, so the two stack as a pair. The 1px border is present in every state and
   only changes colour, so nothing resizes on hover here either. */
.vimeo-modal .vimeo-later--lg {
    position: static;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    width: auto !important;
    margin: .75rem 0 0;
    padding: .5rem 1.2rem;
    border: 1px solid rgba(255, 255, 255, .35) !important;
    border-radius: 2rem;
    background: transparent !important;
    box-shadow: none !important;
    color: #fff !important;
    font-family: inherit;
    font-size: .85rem;
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: normal;
    text-transform: none;
    opacity: 1;
    cursor: pointer;
}
.vimeo-modal .vimeo-later--lg:hover,
.vimeo-modal .vimeo-later--lg:focus,
.vimeo-modal .vimeo-later--lg:active {
    border: 1px solid #fff !important;
    background: rgba(255, 255, 255, .12) !important;
    color: #fff !important;
}
.vimeo-modal .vimeo-later--lg.is-on {
    border: 1px solid var(--vimeo-accent, #A64690) !important;
    background: var(--vimeo-accent, #A64690) !important;
    color: var(--vimeo-accent-contrast, #fff) !important;
}
.vimeo-modal .vimeo-later--lg.is-on:hover,
.vimeo-modal .vimeo-later--lg.is-on:focus,
.vimeo-modal .vimeo-later--lg.is-on:active {
    border: 1px solid var(--vimeo-accent-dark, #883976) !important;
    background: var(--vimeo-accent-dark, #883976) !important;
    color: var(--vimeo-accent-contrast, #fff) !important;
}
