{"id":2171,"date":"2026-09-20T20:48:29","date_gmt":"2026-09-21T00:48:29","guid":{"rendered":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/?page_id=2171"},"modified":"2026-09-20T21:28:17","modified_gmt":"2026-09-21T01:28:17","slug":"worship-videos","status":"publish","type":"page","link":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/worship-videos\/","title":{"rendered":"Worship Videos"},"content":{"rendered":"<!-- ========================================\r\n     YOUTUBE PLAYLIST PLAYER (full screen, desktop + mobile)\r\n     Paste into WP Code Lite as an HTML snippet.\r\n     Edit only the two variables near the top of the script.\r\n     ======================================== -->\r\n\r\n<style>\r\n  \/* ===== Colors ===== *\/\r\n  :root {\r\n    --ypp-bg: #0f0e0d;\r\n    --ypp-surface: #1a1918;\r\n    --ypp-surface-2: #211f1e;\r\n    --ypp-border: #3a3735;\r\n    --ypp-divider: #2e2c2a;\r\n    --ypp-text: #e8e6e3;\r\n    --ypp-text-muted: #9a9895;\r\n    --ypp-text-faint: #6a6865;\r\n    --ypp-primary: #ff3e3e;\r\n    --ypp-primary-hover: #ff5252;\r\n    --ypp-primary-highlight: #3a1e1e;\r\n  }\r\n\r\n  \/* ===== Reset (scoped) ===== *\/\r\n  .ypp-app *,\r\n  .ypp-app *::before,\r\n  .ypp-app *::after {\r\n    box-sizing: border-box;\r\n    margin: 0;\r\n    padding: 0;\r\n  }\r\n\r\n  \/* ===== App shell: fills the screen below your site header =====\r\n     Width and --ypp-top are set by the script at the bottom.\r\n     dvh keeps the height correct when a phone's address bar hides or shows. *\/\r\n  .ypp-app {\r\n    --ypp-space-1: 0.25rem;\r\n    --ypp-space-2: 0.5rem;\r\n    --ypp-space-3: 0.75rem;\r\n    --ypp-space-4: 1rem;\r\n    --ypp-space-6: 1.5rem;\r\n    --ypp-radius-sm: 0.375rem;\r\n    --ypp-radius-md: 0.5rem;\r\n    --ypp-radius-lg: 0.75rem;\r\n    --ypp-transition: 180ms cubic-bezier(0.16, 1, 0.3, 1);\r\n\r\n    box-sizing: border-box;\r\n    position: relative;\r\n    width: 100%;\r\n    height: calc(100vh - var(--ypp-top, 0px));\r\n    height: calc(100dvh - var(--ypp-top, 0px));\r\n    min-height: 320px;\r\n    margin: 0;\r\n    padding: 0;\r\n    display: flex;\r\n    flex-direction: column;\r\n    overflow: hidden;\r\n\r\n    font-family: 'Inter', system-ui, -apple-system, sans-serif;\r\n    font-size: 16px;\r\n    line-height: 1.6;\r\n    color: var(--ypp-text);\r\n    background: var(--ypp-bg);\r\n    -webkit-text-size-adjust: 100%;\r\n  }\r\n\r\n  .ypp-app button {\r\n    font: inherit;\r\n    color: inherit;\r\n    cursor: pointer;\r\n    border: none;\r\n    background: none;\r\n    -webkit-tap-highlight-color: transparent;\r\n    touch-action: manipulation;\r\n  }\r\n\r\n  .ypp-app button:focus-visible {\r\n    outline: 2px solid var(--ypp-primary);\r\n    outline-offset: 2px;\r\n  }\r\n\r\n  \/* ===== Main Layout (desktop and landscape: video left, playlist right) ===== *\/\r\n  .ypp-main {\r\n    display: flex;\r\n    flex: 1;\r\n    min-height: 0;\r\n  }\r\n\r\n  .ypp-player-section {\r\n    flex: 1;\r\n    min-width: 0;\r\n    min-height: 0;\r\n    display: flex;\r\n    flex-direction: column;\r\n    gap: var(--ypp-space-3);\r\n    padding: var(--ypp-space-4);\r\n  }\r\n\r\n  \/* The wrapper takes all leftover height; YouTube letterboxes the video inside it *\/\r\n  .ypp-player-wrap {\r\n    position: relative;\r\n    flex: 1;\r\n    min-height: 0;\r\n    width: 100%;\r\n    background: #000;\r\n    border-radius: var(--ypp-radius-lg);\r\n    overflow: hidden;\r\n  }\r\n\r\n  .ypp-app .ypp-player-wrap iframe {\r\n    position: absolute;\r\n    top: 0; left: 0;\r\n    width: 100%; height: 100%;\r\n    max-width: none;\r\n    border: 0;\r\n  }\r\n\r\n  .ypp-placeholder {\r\n    position: absolute;\r\n    inset: 0;\r\n    display: flex;\r\n    flex-direction: column;\r\n    align-items: center;\r\n    justify-content: center;\r\n    gap: var(--ypp-space-3);\r\n    color: var(--ypp-text-muted);\r\n    text-align: center;\r\n    padding: var(--ypp-space-6);\r\n  }\r\n\r\n  .ypp-placeholder svg { width: 56px; height: 56px; opacity: 0.4; }\r\n  .ypp-placeholder p { font-size: 0.875rem; max-width: 36ch; }\r\n\r\n  .ypp-now-playing {\r\n    display: none;\r\n    flex-direction: column;\r\n    gap: 2px;\r\n  }\r\n\r\n  .ypp-now-playing.active { display: flex; }\r\n\r\n  .ypp-np-title {\r\n    font-size: 1.125rem;\r\n    font-weight: 700;\r\n    line-height: 1.3;\r\n  }\r\n\r\n  .ypp-np-meta {\r\n    font-size: 0.8125rem;\r\n    color: var(--ypp-text-muted);\r\n    display: flex;\r\n    align-items: center;\r\n    gap: var(--ypp-space-3);\r\n  }\r\n\r\n  .ypp-np-badge {\r\n    background: var(--ypp-primary-highlight);\r\n    color: var(--ypp-primary);\r\n    padding: 2px 8px;\r\n    border-radius: 9999px;\r\n    font-size: 0.6875rem;\r\n    font-weight: 600;\r\n    text-transform: uppercase;\r\n    letter-spacing: 0.04em;\r\n  }\r\n\r\n  \/* ===== Playlist Sidebar ===== *\/\r\n  .ypp-playlist {\r\n    width: clamp(280px, 28vw, 420px);\r\n    flex-shrink: 0;\r\n    min-height: 0;\r\n    display: flex;\r\n    flex-direction: column;\r\n    background: var(--ypp-surface);\r\n    border-left: 1px solid var(--ypp-border);\r\n    overflow: hidden;\r\n  }\r\n\r\n  .ypp-pl-header {\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: space-between;\r\n    padding: var(--ypp-space-3) var(--ypp-space-4);\r\n    border-bottom: 1px solid var(--ypp-divider);\r\n  }\r\n\r\n  .ypp-app .ypp-pl-header h3 {\r\n    font-size: 0.9375rem;\r\n    font-weight: 600;\r\n    display: flex;\r\n    align-items: center;\r\n    gap: var(--ypp-space-2);\r\n    margin: 0;\r\n  }\r\n\r\n  .ypp-pl-header .ypp-count {\r\n    font-size: 0.6875rem;\r\n    color: var(--ypp-text-muted);\r\n    background: var(--ypp-surface-2);\r\n    padding: 2px 8px;\r\n    border-radius: 9999px;\r\n    font-weight: 500;\r\n    display: none;\r\n  }\r\n\r\n  .ypp-pl-header .ypp-count.show { display: inline-block; }\r\n\r\n  .ypp-pl-controls {\r\n    display: flex;\r\n    gap: var(--ypp-space-2);\r\n  }\r\n\r\n  .ypp-app .ypp-pl-controls button {\r\n    width: 32px;\r\n    height: 32px;\r\n    padding: 0;\r\n    border-radius: var(--ypp-radius-md);\r\n    background: var(--ypp-surface-2);\r\n    border: 1px solid var(--ypp-border);\r\n    color: var(--ypp-text-muted);\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    transition: color var(--ypp-transition), border-color var(--ypp-transition);\r\n  }\r\n\r\n  .ypp-app .ypp-pl-controls button:hover { color: var(--ypp-text); border-color: var(--ypp-text-faint); }\r\n  .ypp-app .ypp-pl-controls button.active { color: var(--ypp-primary); border-color: var(--ypp-primary); }\r\n  .ypp-app .ypp-pl-controls button svg { width: 15px; height: 15px; }\r\n\r\n  .ypp-pl-list {\r\n    flex: 1;\r\n    min-height: 0;\r\n    overflow-y: auto;\r\n    overscroll-behavior: contain;\r\n    -webkit-overflow-scrolling: touch;\r\n    padding: var(--ypp-space-2);\r\n    display: flex;\r\n    flex-direction: column;\r\n    gap: var(--ypp-space-1);\r\n  }\r\n\r\n  .ypp-pl-list::-webkit-scrollbar { width: 5px; }\r\n  .ypp-pl-list::-webkit-scrollbar-track { background: transparent; }\r\n  .ypp-pl-list::-webkit-scrollbar-thumb {\r\n    background: var(--ypp-border);\r\n    border-radius: 3px;\r\n  }\r\n\r\n  .ypp-item {\r\n    display: flex;\r\n    gap: var(--ypp-space-3);\r\n    padding: var(--ypp-space-2);\r\n    border-radius: var(--ypp-radius-md);\r\n    cursor: pointer;\r\n    align-items: flex-start;\r\n    transition: background var(--ypp-transition);\r\n    -webkit-tap-highlight-color: transparent;\r\n    touch-action: manipulation;\r\n  }\r\n\r\n  .ypp-item:hover { background: var(--ypp-surface-2); }\r\n  .ypp-item.active { background: var(--ypp-primary-highlight); }\r\n  .ypp-item.active .ypp-item-title { color: var(--ypp-primary); }\r\n\r\n  .ypp-item-thumb {\r\n    position: relative;\r\n    width: 110px;\r\n    aspect-ratio: 16 \/ 9;\r\n    border-radius: var(--ypp-radius-sm);\r\n    overflow: hidden;\r\n    flex-shrink: 0;\r\n    background: var(--ypp-surface-2);\r\n  }\r\n\r\n  .ypp-app .ypp-item-thumb img {\r\n    display: block;\r\n    width: 100%;\r\n    height: 100%;\r\n    max-width: none;\r\n    object-fit: cover;\r\n  }\r\n\r\n  .ypp-item-thumb .ypp-dur {\r\n    position: absolute;\r\n    bottom: 3px; right: 3px;\r\n    background: rgba(0,0,0,0.8);\r\n    color: #fff;\r\n    font-size: 10px;\r\n    font-weight: 600;\r\n    padding: 1px 5px;\r\n    border-radius: 3px;\r\n  }\r\n\r\n  .ypp-item-thumb .ypp-playing {\r\n    position: absolute;\r\n    inset: 0;\r\n    background: rgba(0,0,0,0.55);\r\n    display: none;\r\n    align-items: center;\r\n    justify-content: center;\r\n  }\r\n\r\n  .ypp-item.active .ypp-playing { display: flex; }\r\n  .ypp-playing svg { width: 22px; height: 22px; color: var(--ypp-primary); }\r\n\r\n  .ypp-item-info {\r\n    flex: 1; min-width: 0;\r\n    display: flex;\r\n    flex-direction: column;\r\n    gap: 2px;\r\n    padding-top: 2px;\r\n  }\r\n\r\n  .ypp-item-title {\r\n    font-size: 0.8125rem;\r\n    font-weight: 500;\r\n    line-height: 1.35;\r\n    display: -webkit-box;\r\n    -webkit-line-clamp: 2;\r\n    -webkit-box-orient: vertical;\r\n    overflow: hidden;\r\n  }\r\n\r\n  .ypp-item-meta {\r\n    font-size: 0.6875rem;\r\n    color: var(--ypp-text-muted);\r\n  }\r\n\r\n  \/* ===== States ===== *\/\r\n  .ypp-state {\r\n    display: flex;\r\n    flex-direction: column;\r\n    align-items: center;\r\n    justify-content: center;\r\n    gap: var(--ypp-space-3);\r\n    padding: 3rem var(--ypp-space-6);\r\n    text-align: center;\r\n    color: var(--ypp-text-muted);\r\n  }\r\n\r\n  .ypp-state svg { width: 44px; height: 44px; opacity: 0.3; }\r\n  .ypp-state p { font-size: 0.8125rem; max-width: 28ch; }\r\n  .ypp-state.error p { color: var(--ypp-primary); }\r\n\r\n  \/* ===== Skeleton ===== *\/\r\n  .ypp-skel {\r\n    display: flex;\r\n    gap: var(--ypp-space-3);\r\n    padding: var(--ypp-space-2);\r\n  }\r\n\r\n  .ypp-skel-thumb {\r\n    width: 110px;\r\n    aspect-ratio: 16 \/ 9;\r\n    border-radius: var(--ypp-radius-sm);\r\n    flex-shrink: 0;\r\n    background: var(--ypp-surface-2);\r\n    animation: ypp-shimmer 1.5s infinite;\r\n  }\r\n\r\n  .ypp-skel-lines {\r\n    flex: 1;\r\n    display: flex;\r\n    flex-direction: column;\r\n    gap: var(--ypp-space-2);\r\n    padding-top: 4px;\r\n  }\r\n\r\n  .ypp-skel-line {\r\n    height: 11px;\r\n    border-radius: 4px;\r\n    background: var(--ypp-surface-2);\r\n    animation: ypp-shimmer 1.5s infinite;\r\n  }\r\n\r\n  .ypp-skel-line.short { width: 60%; }\r\n\r\n  @keyframes ypp-shimmer {\r\n    0%, 100% { opacity: 0.3; }\r\n    50% { opacity: 0.6; }\r\n  }\r\n\r\n  \/* ===== Phones and tablets held upright: video on top, playlist below ===== *\/\r\n  @media (orientation: portrait) {\r\n    .ypp-app { min-height: 480px; }\r\n    .ypp-main { flex-direction: column; }\r\n    .ypp-player-section { flex: none; padding: 0; gap: 0; }\r\n    .ypp-player-wrap { flex: none; aspect-ratio: 16 \/ 9; border-radius: 0; }\r\n    .ypp-now-playing {\r\n      padding: var(--ypp-space-3) var(--ypp-space-4);\r\n      border-bottom: 1px solid var(--ypp-divider);\r\n    }\r\n    .ypp-np-title { font-size: 1rem; }\r\n    .ypp-playlist { width: 100%; flex: 1; border-left: 0; }\r\n  }\r\n\r\n  \/* ===== Phones held sideways: tighter spacing, slimmer sidebar ===== *\/\r\n  @media (orientation: landscape) and (max-height: 520px) {\r\n    .ypp-player-section { padding: var(--ypp-space-2); gap: var(--ypp-space-2); }\r\n    .ypp-playlist { width: clamp(240px, 36vw, 320px); }\r\n    .ypp-np-title { font-size: 0.9375rem; }\r\n    .ypp-item-thumb, .ypp-skel-thumb { width: 96px; }\r\n  }\r\n\r\n  \/* ===== Touch screens: bigger tap targets ===== *\/\r\n  @media (pointer: coarse) {\r\n    .ypp-app .ypp-pl-controls button { width: 44px; height: 44px; }\r\n    .ypp-app .ypp-pl-controls button svg { width: 18px; height: 18px; }\r\n    .ypp-item { padding: 0.625rem var(--ypp-space-2); }\r\n    .ypp-item-title { font-size: 0.875rem; }\r\n  }\r\n<\/style>\r\n\r\n<div class=\"ypp-app\" id=\"ypp-app\">\r\n  <div class=\"ypp-main\">\r\n\r\n    <!-- Player -->\r\n    <div class=\"ypp-player-section\">\r\n      <div class=\"ypp-player-wrap\">\r\n        <div id=\"ypp-player\"><\/div>\r\n        <div class=\"ypp-placeholder\" id=\"ypp-placeholder\">\r\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"><rect x=\"2\" y=\"4\" width=\"20\" height=\"16\" rx=\"3\"\/><path d=\"M10 9l5 3-5 3V9z\" fill=\"currentColor\"\/><\/svg>\r\n          <p id=\"ypp-placeholder-text\">Loading playlist...<\/p>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"ypp-now-playing\" id=\"ypp-np\">\r\n        <div class=\"ypp-np-title\" id=\"ypp-np-title\"><\/div>\r\n        <div class=\"ypp-np-meta\" id=\"ypp-np-meta\"><\/div>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <!-- Playlist Sidebar -->\r\n    <div class=\"ypp-playlist\">\r\n      <div class=\"ypp-pl-header\">\r\n        <h3>\r\n          <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01\"\/><\/svg>\r\n          Up Next\r\n        <\/h3>\r\n        <div style=\"display:flex;align-items:center;gap:6px;\">\r\n          <span class=\"ypp-count\" id=\"ypp-count\">0<\/span>\r\n          <div class=\"ypp-pl-controls\">\r\n            <button id=\"ypp-shuffle\" title=\"Shuffle\" aria-label=\"Shuffle\">\r\n              <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M16 3h5v5M4 20L21 3M21 16v5h-5M15 15l6 6M4 4l5 5\"\/><\/svg>\r\n            <\/button>\r\n            <button id=\"ypp-repeat\" title=\"Repeat\" aria-label=\"Repeat\">\r\n              <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M17 1l4 4-4 4\"\/><path d=\"M3 11V9a4 4 0 0 1 4-4h14M7 23l-4-4 4-4\"\/><path d=\"M21 13v2a4 4 0 0 1-4 4H3\"\/><\/svg>\r\n            <\/button>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"ypp-pl-list\" id=\"ypp-list\"><\/div>\r\n    <\/div>\r\n\r\n  <\/div>\r\n<\/div>\r\n\r\n<script>\r\n(function () {\r\n  'use strict';\r\n\r\n  \/\/ ========================================\r\n  \/\/  EDIT THESE TWO LINES ONLY\r\n  \/\/  Paste your Playlist ID and YouTube Data API v3 key between the quotes.\r\n  \/\/  (A full playlist URL also works in place of the ID.)\r\n  \/\/ ========================================\r\n  var PLAYLIST_ID = 'PLb903T2V_vYAn544u_6rhs_ws0sVCNNzo';\r\n  var API_KEY     = 'AIzaSyC-QuUhhc6clTK3o0nFSdQ9wtVMXCKU5so';\r\n  \/\/ ========================================\r\n\r\n  var app = document.getElementById('ypp-app');\r\n  var player = null;\r\n  var playerReady = false;\r\n  var pendingVideoId = null;\r\n  var playlistData = [];\r\n  var currentIndex = 0;\r\n  var isShuffled = false;\r\n  var isRepeating = false;\r\n  var shuffledOrder = [];\r\n\r\n  \/\/ ===== Fit to screen =====\r\n  \/\/ Stretches the app to the full browser width (breaking out of the theme's\r\n  \/\/ centered content column) and tells the CSS how far down the page it starts,\r\n  \/\/ so its height fills the rest of the screen.\r\n  function fit() {\r\n    var vw = document.documentElement.clientWidth;\r\n    app.style.setProperty('width', vw + 'px', 'important');\r\n    app.style.setProperty('max-width', 'none', 'important');\r\n    app.style.setProperty('margin-right', '0px', 'important');\r\n    app.style.setProperty('margin-left', '0px', 'important');\r\n\r\n    var rect = app.getBoundingClientRect();\r\n    var scrollY = window.pageYOffset || document.documentElement.scrollTop || 0;\r\n\r\n    app.style.setProperty('margin-left', (-rect.left) + 'px', 'important');\r\n    app.style.setProperty('--ypp-top', Math.max(0, Math.round(rect.top + scrollY)) + 'px');\r\n  }\r\n\r\n  var fitTimer = null;\r\n  function scheduleFit() {\r\n    clearTimeout(fitTimer);\r\n    fitTimer = setTimeout(fit, 100);\r\n  }\r\n\r\n  fit();\r\n  window.addEventListener('load', function () { fit(); setTimeout(fit, 400); });\r\n  window.addEventListener('resize', scheduleFit);\r\n  window.addEventListener('orientationchange', function () { setTimeout(fit, 250); });\r\n\r\n  \/\/ ===== Load YouTube IFrame API =====\r\n  var tag = document.createElement('script');\r\n  tag.src = 'https:\/\/www.youtube.com\/iframe_api';\r\n  var firstScript = document.getElementsByTagName('script')[0];\r\n  firstScript.parentNode.insertBefore(tag, firstScript);\r\n\r\n  \/\/ ===== Helpers =====\r\n  function escapeHtml(text) {\r\n    var div = document.createElement('div');\r\n    div.textContent = text || '';\r\n    return div.innerHTML;\r\n  }\r\n\r\n  function parseDuration(iso) {\r\n    var m = iso.match(\/PT(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)S)?\/);\r\n    if (!m) return '';\r\n    var h = parseInt(m[1] || 0);\r\n    var mi = parseInt(m[2] || 0);\r\n    var s = parseInt(m[3] || 0);\r\n    if (h > 0) return h + ':' + String(mi).padStart(2, '0') + ':' + String(s).padStart(2, '0');\r\n    return mi + ':' + String(s).padStart(2, '0');\r\n  }\r\n\r\n  function extractPlaylistId(input) {\r\n    var urlMatch = input.match(\/[?&]list=([^&]+)\/);\r\n    if (urlMatch) return urlMatch[1];\r\n    return input.trim();\r\n  }\r\n\r\n  \/\/ ===== Player =====\r\n  \/\/ autoplay = true: start playing right away\r\n  \/\/ autoplay = false: load the video and wait for the visitor to press play\r\n  function createPlayer(videoId, autoplay) {\r\n    document.getElementById('ypp-placeholder').style.display = 'none';\r\n\r\n    if (player) {\r\n      if (!playerReady) { pendingVideoId = videoId; return; }\r\n      if (autoplay) player.loadVideoById(videoId);\r\n      else player.cueVideoById(videoId);\r\n      return;\r\n    }\r\n\r\n    player = new YT.Player('ypp-player', {\r\n      width: '100%',\r\n      height: '100%',\r\n      videoId: videoId,\r\n      playerVars: {\r\n        autoplay: autoplay ? 1 : 0,\r\n        playsinline: 1,   \/\/ keeps iPhones from forcing full screen on play\r\n        rel: 0,\r\n        modestbranding: 1\r\n      },\r\n      events: {\r\n        onReady: function () {\r\n          playerReady = true;\r\n          if (pendingVideoId) {\r\n            player.loadVideoById(pendingVideoId);\r\n            pendingVideoId = null;\r\n          }\r\n        },\r\n        onStateChange: function (e) {\r\n          if (e.data === YT.PlayerState.ENDED) {\r\n            if (isRepeating) { player.seekTo(0); player.playVideo(); }\r\n            else playNext();\r\n          }\r\n        }\r\n      }\r\n    });\r\n  }\r\n\r\n  function playVideo(index, autoplay) {\r\n    currentIndex = index;\r\n    var video = playlistData[index];\r\n    if (!video) return;\r\n    createPlayer(video.videoId, autoplay !== false);\r\n    updateNowPlaying(video);\r\n    updateActiveItem();\r\n  }\r\n\r\n  function playNext() {\r\n    if (!playlistData.length) return;\r\n    var next;\r\n    if (isShuffled) {\r\n      var pos = shuffledOrder.indexOf(currentIndex);\r\n      if (pos < shuffledOrder.length - 1) next = shuffledOrder[pos + 1];\r\n      else if (isRepeating) next = shuffledOrder[0];\r\n      else return;\r\n    } else {\r\n      if (currentIndex < playlistData.length - 1) next = currentIndex + 1;\r\n      else if (isRepeating) next = 0;\r\n      else return;\r\n    }\r\n    playVideo(next);\r\n  }\r\n\r\n  function playPrevious() {\r\n    if (!playlistData.length) return;\r\n    var prev;\r\n    if (isShuffled) {\r\n      var pos = shuffledOrder.indexOf(currentIndex);\r\n      if (pos > 0) prev = shuffledOrder[pos - 1];\r\n      else prev = shuffledOrder[shuffledOrder.length - 1];\r\n    } else {\r\n      if (currentIndex > 0) prev = currentIndex - 1;\r\n      else prev = playlistData.length - 1;\r\n    }\r\n    playVideo(prev);\r\n  }\r\n\r\n  function toggleShuffle() {\r\n    isShuffled = !isShuffled;\r\n    document.getElementById('ypp-shuffle').classList.toggle('active', isShuffled);\r\n    if (isShuffled) {\r\n      var indices = playlistData.map(function (_, i) { return i; });\r\n      var current = indices.splice(currentIndex, 1)[0];\r\n      for (var i = indices.length - 1; i > 0; i--) {\r\n        var j = Math.floor(Math.random() * (i + 1));\r\n        var tmp = indices[i]; indices[i] = indices[j]; indices[j] = tmp;\r\n      }\r\n      shuffledOrder = [current].concat(indices);\r\n    }\r\n  }\r\n\r\n  function toggleRepeat() {\r\n    isRepeating = !isRepeating;\r\n    document.getElementById('ypp-repeat').classList.toggle('active', isRepeating);\r\n  }\r\n\r\n  \/\/ ===== UI =====\r\n  function updateNowPlaying(video) {\r\n    var np = document.getElementById('ypp-np');\r\n    document.getElementById('ypp-np-title').textContent = video.title;\r\n    document.getElementById('ypp-np-meta').innerHTML =\r\n      '<span class=\"ypp-np-badge\">Now Playing<\/span> <span>' +\r\n      escapeHtml(video.channelTitle || '') + '<\/span>';\r\n    np.classList.add('active');\r\n  }\r\n\r\n  function updateActiveItem() {\r\n    var list = document.getElementById('ypp-list');\r\n    var items = list.querySelectorAll('.ypp-item');\r\n    items.forEach(function (item, i) {\r\n      item.classList.toggle('active', i === currentIndex);\r\n    });\r\n\r\n    \/\/ Scroll only the playlist (never the whole page) to keep the active item in view\r\n    var active = items[currentIndex];\r\n    if (!active) return;\r\n    var lr = list.getBoundingClientRect();\r\n    var ar = active.getBoundingClientRect();\r\n    if (ar.top < lr.top || ar.bottom > lr.bottom) {\r\n      var target = list.scrollTop + (ar.top - lr.top) - (lr.height - ar.height) \/ 2;\r\n      list.scrollTo({ top: Math.max(0, target), behavior: 'smooth' });\r\n    }\r\n  }\r\n\r\n  function renderPlaylist(items) {\r\n    playlistData = items;\r\n    var list = document.getElementById('ypp-list');\r\n    var countEl = document.getElementById('ypp-count');\r\n    countEl.textContent = items.length;\r\n    countEl.classList.add('show');\r\n    list.innerHTML = '';\r\n\r\n    items.forEach(function (video, index) {\r\n      var item = document.createElement('div');\r\n      item.className = 'ypp-item';\r\n      item.dataset.index = index;\r\n      item.innerHTML =\r\n        '<div class=\"ypp-item-thumb\">' +\r\n          '<img decoding=\"async\" src=\"' + video.thumbnail + '\" alt=\"\" loading=\"lazy\" \/>' +\r\n          '<span class=\"ypp-dur\">' + (video.duration || '') + '<\/span>' +\r\n          '<div class=\"ypp-playing\"><svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M8 5v14l11-7z\"\/><\/svg><\/div>' +\r\n        '<\/div>' +\r\n        '<div class=\"ypp-item-info\">' +\r\n          '<div class=\"ypp-item-title\">' + escapeHtml(video.title) + '<\/div>' +\r\n          '<div class=\"ypp-item-meta\">' + escapeHtml(video.channelTitle || '') + '<\/div>' +\r\n        '<\/div>';\r\n      item.addEventListener('click', function () { playVideo(index); });\r\n      list.appendChild(item);\r\n    });\r\n  }\r\n\r\n  function renderSkeleton() {\r\n    var list = document.getElementById('ypp-list');\r\n    list.innerHTML = '';\r\n    for (var i = 0; i < 8; i++) {\r\n      var item = document.createElement('div');\r\n      item.className = 'ypp-skel';\r\n      item.innerHTML =\r\n        '<div class=\"ypp-skel-thumb\"><\/div>' +\r\n        '<div class=\"ypp-skel-lines\">' +\r\n          '<div class=\"ypp-skel-line\"><\/div>' +\r\n          '<div class=\"ypp-skel-line short\"><\/div>' +\r\n        '<\/div>';\r\n      list.appendChild(item);\r\n    }\r\n  }\r\n\r\n  function showError(msg) {\r\n    var list = document.getElementById('ypp-list');\r\n    list.innerHTML =\r\n      '<div class=\"ypp-state error\">' +\r\n        '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"><circle cx=\"12\" cy=\"12\" r=\"10\"\/><path d=\"M12 8v4M12 16h.01\"\/><\/svg>' +\r\n        '<p>' + escapeHtml(msg) + '<\/p>' +\r\n      '<\/div>';\r\n    var ph = document.getElementById('ypp-placeholder-text');\r\n    if (ph) ph.textContent = 'Unable to load the playlist.';\r\n  }\r\n\r\n  \/\/ ===== YouTube Data API =====\r\n  function fetchPlaylist(playlistId, apiKey) {\r\n    var baseUrl = 'https:\/\/www.googleapis.com\/youtube\/v3\/playlistItems';\r\n    var params = new URLSearchParams({\r\n      part: 'snippet,contentDetails',\r\n      maxResults: '50',\r\n      playlistId: playlistId,\r\n      key: apiKey\r\n    });\r\n\r\n    var allItems = [];\r\n    var nextPageToken = '';\r\n\r\n    function fetchPage() {\r\n      if (nextPageToken) params.set('pageToken', nextPageToken);\r\n\r\n      return fetch(baseUrl + '?' + params.toString())\r\n        .then(function (res) { return res.json(); })\r\n        .then(function (data) {\r\n          if (data.error) throw new Error('API Error: ' + data.error.message);\r\n\r\n          data.items.forEach(function (item) {\r\n            allItems.push({\r\n              videoId: item.contentDetails.videoId,\r\n              title: item.snippet.title,\r\n              thumbnail: (item.snippet.thumbnails.medium || item.snippet.thumbnails.default).url,\r\n              channelTitle: item.snippet.videoOwnerChannelTitle || item.snippet.channelTitle,\r\n              position: item.snippet.position\r\n            });\r\n          });\r\n\r\n          nextPageToken = data.nextPageToken || '';\r\n          if (nextPageToken) return fetchPage();\r\n          return allItems;\r\n        });\r\n    }\r\n\r\n    return fetchPage().then(function (items) {\r\n      \/\/ Fetch durations\r\n      var videoIds = items.map(function (v) { return v.videoId; }).join(',');\r\n      return fetch('https:\/\/www.googleapis.com\/youtube\/v3\/videos?part=contentDetails,snippet&id=' + videoIds + '&key=' + apiKey)\r\n        .then(function (res) { return res.json(); })\r\n        .then(function (data) {\r\n          if (data.items) {\r\n            var map = {};\r\n            data.items.forEach(function (item) {\r\n              map[item.id] = {\r\n                duration: parseDuration(item.contentDetails.duration),\r\n                channelTitle: item.snippet.channelTitle\r\n              };\r\n            });\r\n            items.forEach(function (v) {\r\n              var d = map[v.videoId];\r\n              if (d) { v.duration = d.duration; v.channelTitle = d.channelTitle; }\r\n            });\r\n          }\r\n          return items;\r\n        });\r\n    });\r\n  }\r\n\r\n  function loadPlaylist(playlistInput, apiKeyInput) {\r\n    var playlistId = extractPlaylistId(playlistInput);\r\n    renderSkeleton();\r\n\r\n    fetchPlaylist(playlistId, apiKeyInput)\r\n      .then(function (items) {\r\n        if (!items.length) { showError('No videos found in this playlist.'); return; }\r\n        renderPlaylist(items);\r\n        \/\/ Load the first video without autoplay, since browsers block\r\n        \/\/ sound-on autoplay before the visitor has interacted with the page.\r\n        playVideo(0, false);\r\n      })\r\n      .catch(function (err) {\r\n        showError(err.message || 'Failed to load playlist. Check your playlist ID and API key.');\r\n      });\r\n  }\r\n\r\n  \/\/ ===== Event Listeners =====\r\n  document.getElementById('ypp-shuffle').addEventListener('click', toggleShuffle);\r\n  document.getElementById('ypp-repeat').addEventListener('click', toggleRepeat);\r\n\r\n  \/\/ Keyboard shortcuts\r\n  document.addEventListener('keydown', function (e) {\r\n    if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;\r\n    if (!player || !playerReady) return;\r\n    if (e.key === ' ' || e.key === 'k') {\r\n      e.preventDefault();\r\n      if (player.getPlayerState() === YT.PlayerState.PLAYING) player.pauseVideo();\r\n      else player.playVideo();\r\n    } else if (e.key === 'ArrowRight' || e.key === 'n') {\r\n      playNext();\r\n    } else if (e.key === 'ArrowLeft' || e.key === 'p') {\r\n      playPrevious();\r\n    }\r\n  });\r\n\r\n  \/\/ ===== Auto-load =====\r\n  if (!PLAYLIST_ID || !API_KEY) {\r\n    showError('Add your Playlist ID and API key at the top of the script.');\r\n    return;\r\n  }\r\n\r\n  var started = false;\r\n  var checkReady = setInterval(function () {\r\n    \/\/ Wait until YouTube's player library is fully ready\r\n    if (window.YT && window.YT.Player) {\r\n      clearInterval(checkReady);\r\n      started = true;\r\n      loadPlaylist(PLAYLIST_ID, API_KEY);\r\n    }\r\n  }, 200);\r\n\r\n  setTimeout(function () {\r\n    if (!started) {\r\n      clearInterval(checkReady);\r\n      showError('The YouTube player could not be loaded. Please refresh the page.');\r\n    }\r\n  }, 10000);\r\n})();\r\n<\/script>\r\n\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"class_list":["post-2171","page","type-page","status-publish","hentry"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/sermons.alliancechristiancenter.org\/sermons\/worship-videos\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"-\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Worship Videos -\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/sermons.alliancechristiancenter.org\/sermons\/worship-videos\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-09-21T00:48:29+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-09-21T01:28:17+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Worship Videos -\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/sermons.alliancechristiancenter.org\\\/sermons\\\/worship-videos\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/sermons.alliancechristiancenter.org\\\/sermons#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/sermons.alliancechristiancenter.org\\\/sermons\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/sermons.alliancechristiancenter.org\\\/sermons\\\/worship-videos\\\/#listItem\",\"name\":\"Worship Videos\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/sermons.alliancechristiancenter.org\\\/sermons\\\/worship-videos\\\/#listItem\",\"position\":2,\"name\":\"Worship Videos\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/sermons.alliancechristiancenter.org\\\/sermons#listItem\",\"name\":\"Home\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/sermons.alliancechristiancenter.org\\\/sermons\\\/#organization\",\"url\":\"https:\\\/\\\/sermons.alliancechristiancenter.org\\\/sermons\\\/\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/sermons.alliancechristiancenter.org\\\/sermons\\\/worship-videos\\\/#webpage\",\"url\":\"https:\\\/\\\/sermons.alliancechristiancenter.org\\\/sermons\\\/worship-videos\\\/\",\"name\":\"Worship Videos -\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/sermons.alliancechristiancenter.org\\\/sermons\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/sermons.alliancechristiancenter.org\\\/sermons\\\/worship-videos\\\/#breadcrumblist\"},\"datePublished\":\"2026-09-20T20:48:29-04:00\",\"dateModified\":\"2026-09-20T21:28:17-04:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/sermons.alliancechristiancenter.org\\\/sermons\\\/#website\",\"url\":\"https:\\\/\\\/sermons.alliancechristiancenter.org\\\/sermons\\\/\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/sermons.alliancechristiancenter.org\\\/sermons\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Worship Videos -","description":"","canonical_url":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/worship-videos\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BreadcrumbList","@id":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/worship-videos\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/sermons.alliancechristiancenter.org\/sermons#listItem","position":1,"name":"Home","item":"https:\/\/sermons.alliancechristiancenter.org\/sermons","nextItem":{"@type":"ListItem","@id":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/worship-videos\/#listItem","name":"Worship Videos"}},{"@type":"ListItem","@id":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/worship-videos\/#listItem","position":2,"name":"Worship Videos","previousItem":{"@type":"ListItem","@id":"https:\/\/sermons.alliancechristiancenter.org\/sermons#listItem","name":"Home"}}]},{"@type":"Organization","@id":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/#organization","url":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/"},{"@type":"WebPage","@id":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/worship-videos\/#webpage","url":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/worship-videos\/","name":"Worship Videos -","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/#website"},"breadcrumb":{"@id":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/worship-videos\/#breadcrumblist"},"datePublished":"2026-09-20T20:48:29-04:00","dateModified":"2026-09-20T21:28:17-04:00"},{"@type":"WebSite","@id":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/#website","url":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/","inLanguage":"en-US","publisher":{"@id":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/#organization"}}]},"og:locale":"en_US","og:site_name":"-","og:type":"article","og:title":"Worship Videos -","og:url":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/worship-videos\/","article:published_time":"2026-09-21T00:48:29+00:00","article:modified_time":"2026-09-21T01:28:17+00:00","twitter:card":"summary_large_image","twitter:title":"Worship Videos -"},"aioseo_meta_data":{"post_id":"2171","title":null,"description":null,"keywords":null,"keyphrases":{"focus":{"keyphrase":"","score":0,"analysis":{"keyphraseInTitle":{"score":0,"maxScore":9,"error":1}}},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"WebPage","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"created":"2026-09-21 00:48:29","updated":"2026-09-21 01:28:48","seo_analyzer_scan_date":null,"focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/sermons.alliancechristiancenter.org\/sermons\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tWorship Videos\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/sermons.alliancechristiancenter.org\/sermons"},{"label":"Worship Videos","link":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/worship-videos\/"}],"_links":{"self":[{"href":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/wp-json\/wp\/v2\/pages\/2171","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/wp-json\/wp\/v2\/comments?post=2171"}],"version-history":[{"count":2,"href":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/wp-json\/wp\/v2\/pages\/2171\/revisions"}],"predecessor-version":[{"id":2184,"href":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/wp-json\/wp\/v2\/pages\/2171\/revisions\/2184"}],"wp:attachment":[{"href":"https:\/\/sermons.alliancechristiancenter.org\/sermons\/wp-json\/wp\/v2\/media?parent=2171"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}