PageSourceSearch

https://toveedo.com/playlists

html toveedo.com collected 2026-10-02 15:13:11 UTC 240,607 bytes, 6,791 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en" class="h-full">
3  <head>
4    <meta name="csrf-param" content="authenticity_token" />
5<meta name="csrf-token" content="05JqM02BhrDuTBurSdm29puSpBUmZiAhCkWJqj9QGv5_sKMx5dwgVdk44mQ2SgRMC4o8VI9B-LktJXGoBMIgQA" />
6    <meta charset="utf-8">
7    <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
9    <link rel="preconnect" href="https://alpha.uscreencdn.com">
10    <link rel="preconnect">
11    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&amp;display=swap">
12
13    <meta name="view-transition" content="same-origin">
14
15    
15<script src="https://assets-gke.uscreencdn.com/vite/assets/web-components-BnSq9iDb.js" crossorigin="anonymous" type="module"></script>
15<link rel="modulepreload" href="https://assets-gke.uscreencdn.com/vite/assets/preload-helper-s3Hva0Xc.js" as="script" crossorigin="anonymous">
16    
16<script src="https://assets-gke.uscreencdn.com/vite/assets/storefront_hotwire-BZ9GwY5K.js" crossorigin="anonymous" type="module"></script>
16<link rel="modulepreload" href="https://assets-gke.uscreencdn.com/vite/assets/preload-helper-s3Hva0Xc.js" as="script" crossorigin="anonymous">
17<link rel="modulepreload" href="https://assets-gke.uscreencdn.com/vite/assets/excludeTurboTrainBroadcastReactEvents-Ch9QDwMS.js" as="script" crossorigin="anonymous">
18<link rel="modulepreload" href="https://assets-gke.uscreencdn.com/vite/assets/VideoTracker-DKtiOlZs.js" as="script" crossorigin="anonymous">
19<link rel="modulepreload" href="https://assets-gke.uscreencdn.com/vite/assets/turbo.es2017-esm-CbrezRZI.js" as="script" crossorigin="anonymous">
20<link rel="modulepreload" href="https://assets-gke.uscreencdn.com/vite/assets/_commonjsHelpers-BosuxZz1.js" as="script" crossorigin="anonymous"><link rel="stylesheet" href="https://assets-gke.uscreencdn.com/vite/assets/storefront_hotwire-DtHu4oK3.css" media="screen" />
21    <link rel="stylesheet" href="https://assets-gke.uscreencdn.com/vite/assets/tailwind-CeQmPIAS.css" media="all" />
22    <link rel="stylesheet" href="https://assets-gke.uscreencdn.com/vite/assets/storefront_common-D_5IJA0x.css" media="all" />
23
24      
24<script>
25        window.hotwireCatalog = true
26      </script>
26
27    
27<script>
28      window.apiUrl = "https://api.uscreencdn.com"
29      window.apiOrigin = "torahtreasure"
30    </script>
30
31
32    
32<script>
33//<![CDATA[
34window.gon={};gon.global={"uppy_companion_url":"/uppy","assets_cdn_url":"https://alpha.uscreencdn.com","mixpanel_token":"44e8d04b49529b306bd4a1c79afcc56e"};gon.feature_flags=["themeless","themeless_catalog_visual_fixes","ai_storefront_related_videos","network_spam_detection","calendar_collection_scheduling","checkout_donations","hotwire_catalog","rich_user_profile","passwordless_sign_up","rudolph_subscription_plans","content_moderation","automations","external_checkout","custom_google_cast_receiver","hubspot_hand_raise","email_capture","refer_to_uscreen","billing_sales_tax_on_fees","developer_apps_ui","users_mcp_permissions","apps_update_requests","account_creation_required","banner_with_live_stream_overage","paypal_beta","client_emails_footer","community_notifications_v1","new_video_get_access_page","real_time_apple_notifications","real_time_amazon_notifications","real_time_android_notifications","force_shortened_checkout","new_subscription_flow","pause_subscriptions","stripe_subscriptions","stripe_tax_collection","dm_attachments_in_app","live_chat_with_react","ai_video_recommendations_waitlist","mcp_waitlist","ai_video_recommendations","mobile_featured_category_thumbnail_style","audiences","prompt_app_updates","ai_storefront_related_video_collections","email_topics","headless_api","videos_bulk_all_matching","webhook_auto_disable","ai_storefront_schema_free_recommendations","launch_dashboard_growth_ab_test"];gon.settings={"primary_color":"#41d0ffff","commenting":false,"my_library":false,"stats_id":"c43v645rpolt89529v2pesifn","analytics_env_id":"production","chapter_style":"thumbnails","store_title":"Toveedo","continue_watching":true,"mark_as_watched":false,"live_event_feed_link":null,"locale":"en","autoplay":true,"uplayer":true,"show_notifications_center":false,"time_format":null,"local_timezone":null};gon.currency="USD";gon.locale="en";gon.country="US";gon.stripe="pk_live_DImPqz7QOOyx70XCA9DSifxb";gon.recaptcha_v3_pub_key="6LenX-EZAAAAAAITxgGIXKB3S2OVKsM5r5tg0wKL";gon.store_id=556;gon.writing_direction="ltr";
35//]]>
36</script>
36
37
38    
38<script>
39      var sentryDsn = 'https://[email protected]/4509910289350656'
40      var sentryStorefrontActive = true
41      var sentryStorefrontSampleRate = 1.0
42      var railsEnv = 'production'
43      var analyticsHost = 'https://stats.uscreen.io'
44      var uscreenStoreId = 556
45      var isUscreenUserImpersonated = false
46      var analyticsConfig = null
47      var storeId = 556
48    </script>
48
49
50      <link
51  rel="icon"
52  href="https://alpha.uscreencdn.com/images/favicontypes/662/lxdymwvws1srejfy94nq_t.png"
53>
54<link
55  rel="apple-touch-icon"
56  sizes="180x180"
57  href="https://alpha.uscreencdn.com/images/favicontypes/662/lxdymwvws1srejfy94nq_t.png"
58>
59
60
61    
61<script
62  type="module"
63  crossorigin
64  src="https://cdn.jsdelivr.net/npm/@uscreentv/[email protected]/+esm"
65></script>
65
66
67      <title>Toveedo</title>
68<meta name="description" content="">
69<!-- Twitter Card data -->
70<meta name="twitter:card" content="summary" />
71<meta name="twitter:title" content="Toveedo" />
72<meta name="twitter:description" content="" />
73<meta name="twitter:image" content="https://alpha.uscreencdn.com/450xnull/images/logotypes/662/null_2fk3gmtm2vrzkxuqp7burq_toveedo-blue.png?auto=webp" />
74<!-- Open Graph data -->
75<meta property="og:title" content="Toveedo" >
76<meta property="og:type" content="website" />
77<meta property="og:url" content="https://toveedo.com/playlists" >
78<meta property="og:image" content="https://alpha.uscreencdn.com/1110xnull/images/logotypes/662/null_2fk3gmtm2vrzkxuqp7burq_toveedo-blue.png?auto=webp" >
79<meta property="og:image:width" content="740" >
80<meta property="og:image:height" content="420" >
81<meta property="og:description" content="" >
82<meta property="og:site_name" content="Toveedo" />
83<link rel="canonical" href="https://toveedo.com/playlists" />
84<script type = 'application/ld+json' >
85  {
86    "@context": "https://schema.org",
87    "@type": "Organization",
88    "url": "https://toveedo.com",
89    "@id": "https://toveedo.com/#organization",
90    "name": "Toveedo",
91    "logo": "https://alpha.uscreencdn.com/450xnull/images/logotypes/662/null_2fk3gmtm2vrzkxuqp7burq_toveedo-blue.png?auto=webp"
92  }
93</script>
93
94
95
96
97    <style>
98    :root {
99        --primary: #41d0ffff;
100        --primary-rgb: 65, 208, 255;
101        --contrast-text-color: #FFFFFF;
102        --contrast-to-primary-color: #fff;
103    }
104</style>
105<style id="custom-theme-styles" media="all">
106    body.light {
107        --main-color-h: 0;
108        --main-color-s: 100;
109        --main-color-l: 100;
110        --ds-bg-main: hsl(0, 100%, 100%);
111
112        --ds-bg-default: hsl(var(--main-color-h), calc(var(--main-color-s) * 1%), 96%);
113        --ds-bg-inset: hsl(var(--main-color-h), calc(var(--main-color-s) * 1%), 91%);
114        --ds-bg-overlay: hsl(var(--main-color-h), calc(var(--main-color-s) * 1%), 98%);
115        --ds-bg-subtle: hsl(var(--main-color-h), calc(var(--main-color-s) * 1%), 91%);
116
117        --ds-border-default: hsl(var(--main-color-h), calc(var(--main-color-s) * 1%), 85%);
118        --ds-fg-default: hsl(var(--main-color-h), calc(var(--main-color-s) * 1%), 8%);
119        --ds-fg-muted: hsl(var(--main-color-h), calc(var(--main-color-s) * 1%), 25%);
120        --ds-fg-subtle: hsl(var(--main-color-h), calc(var(--main-color-s) * 1%), 50%);
121    }
122
123    body.dark {
124        --main-color-h: 0;
125        --main-color-s: 100;
126        --main-color-l: 0;
127        --ds-bg-main: hsl(0, 100%, 0%);
128
129        --ds-bg-default: hsl(var(--main-color-h), calc(var(--main-color-s) * 1%), 10%);
130        --ds-bg-overlay: hsl(var(--main-color-h), calc(var(--main-color-s) * 1%), 2%);
131        --ds-bg-inset: hsl(var(--main-color-h), calc(var(--main-color-s) * 1%), 6%);
132        --ds-bg-subtle: hsl(var(--main-color-h), calc(var(--main-color-s) * 1%), 15%);
133
134        --ds-border-default: hsl(var(--main-color-h), calc(var(--main-color-s) * 1%), 20%);
135        --ds-fg-default: hsl(var(--main-color-h), calc(var(--main-color-s) * 1%), 98%);
136        --ds-fg-muted: hsl(var(--main-color-h), calc(var(--main-color-s) * 1%), 70%);
137        --ds-fg-subtle: hsl(var(--main-color-h), clamp(7%, calc(calc(var(--main-color-s) - 10) * 1%), 100%), 60%);
138    }
139
140    body.dark,
141    body.light {
142        --main-color-h: 0;
143        --main-color-s: 0;
144        --main-color-l: 100;
145        --ds-bg-main: hsl(0, 0%, 100%);
146    }
147</style>
148
149    <!-- Feature: Toveedo global Uscreen head customizations. Tag: catalog arrows, header/footer sync, profile helpers, player watermark. -->
150<style>
151  [data-program-video-target="shareCtaContainer"] .flex.flex-col.items-center.relative.gap-4.w-full.h-full.justify-center.px-4 {
152    display: none;
153  }
154
155  :root {
156    --card-shadow-height: 0px;
157  }
158
159  #catalog_filters > div {
160    background-color: #41d0ff47;
161    position: relative;
162  }
163  #catalog_filters > div:before,
164  #catalog_filters > div:after {
165    content: '';
166    position: absolute;
167    background-color: #41d0ff47;
168    width: 100%;
169    height: 1rem;
170  }
171  #catalog_filters > div:before {
172    top: -1rem;
173  }
174  #catalog_filters > div:after {
175    bottom: -1rem;
176  }
177  #add_to_calendar {
178    display: none;
179  }
180  [data-test="filters-list"] ds-select {
181    display: flex;
182    justify-content: center;
183    align-items: center;
184    gap: .5rem;
185  }
186  [data-test="filters-list"] ds-select::after {
187    content: "";
188    display: block;
189    width: 32px;
190    height: 32px;
191    background: #41d0ff url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M16.3049 14.9248C17.367 13.5671 18 11.8575 18 10C18 5.58172 14.4183 2 10 2C5.58172 2 2 5.58172 2 10C2 14.4183 5.58172 18 10 18C11.8399 18 13.5348 17.3788 14.8864 16.3348L18.2965 19.7107C18.689 20.0992 19.3222 20.096 19.7107 19.7036C20.0993 19.3111 20.0961 18.6779 19.7036 18.2894L16.3049 14.9248ZM16 10C16 13.3137 13.3137 16 10 16C6.68629 16 4 13.3137 4 10C4 6.68629 6.68629 4 10 4C13.3137 4 16 6.68629 16 10Z' fill='%23fff'/%3E%3C/svg%3E")
192      center / 24px 24px no-repeat;
193    border-radius: 4px;
194  }
195  [data-custom="content-card"] {
196    // zoom: 1.25;
197  }
198  .category-group ds-icon[name="chevron-right"],
199  .category-group ds-icon[name="chevron-left"] {
200    visibility: visible !important;
201    opacity: 0;
202  }
203  .category-group .catalog-row-overflow {
204    overflow: visible;
205  }
206  .category-group [slot="next-button"] {
207    background: url('https://unode1.s3.amazonaws.com/assets%2F%2Fassets%2F15576%2F%2Fp8sbaktgr1eya4y9z9bv_arrow_
207new-next-1.1778771546.svg') 0% 62% no-repeat !important;
208    background-size: 23px !important;
209    position: relative;
210  }
211  .category-group [slot="next-button"]:before {
212    content: "";
213    display: block;
214    position: absolute;
215    bottom: 0;
216    right: 0;
217    width: 200%;
218    height: var(--card-shadow-height);
219    background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) 77%);
220    z-index: -1;
221  }
222  .category-group [slot="prev-button"] {
223    background: url('https://unode1.s3.amazonaws.com/assets%2F%2Fassets%2F15576%2F%2Ftz649pbtlwmfy0ougiyg_arrow_new-prev-1.1778771539.svg') 60% 62% no-repeat !important;
224    background-size: 23px  !important;
225    display: block !important;
226  }
227  .category-group [slot="prev-button"]:before {
228    content: "";
229    display: block;
230    position: absolute;
231    bottom: 0;
232    left: 0;
233    width: 200%;
234    height: var(--card-shadow-height);
235    background: linear-gradient(270deg, rgba(0, 0, 0, 0) 33%, rgba(0, 0, 0, 1) 92%);
236    z-index: -1;
237  }
238  .catalog-constrained .catalog-area, .catalog-constrained .catalog-filter-preloader, .catalog-constrained .catalog-max-width {
239    max-width: none;
240  }
241  .toveedo-uscreen-header-dropdown {
242    display: none !important;
243  }
244  #website-links a.text-ds-default {
245    color: #fff !important;
246  }
247  #website-links {
248    margin-right: 0;
249  }
250  .w-full.border-b.border-ds-default.bg-ds-main > .flex.w-max.min-w-full {
251    display: none;
252  }
253  [data-controller="themeless-featured-slider"] > ds-swiper + div {
254    zoom: 2.5;
255    overflow: visible;
256  }
257  [data-controller="themeless-featured-slider"] .aspect-\[19\/8\] {
258    aspect-ratio: 19 / 6;
259  }
260  [data-controller="themeless-featured-slider"]
261    [data-themeless-featured-slider-target="paginationItem"]
262    button {
263    position: relative;
264  }
265  [data-controller="themeless-featured-slider"]
266    [data-themeless-featured-slider-target="paginationItem"]
267    button:before {
268    content: "";
269    width: 120%;
270    height: 40px;
271    top: -20px;
272    left: 10%;
273    position: absolute;
274    display: block;
275  }
276</style>
277
278<!-- Feature: Sync Toveedo content-card image height to --card-shadow-height for catalog arrow fades. Tag: Uscreen content-card sizing, ResizeObserver, Turbo-safe lifecycle. -->
279<script>
280  (function () {
281    var SWIPER_CARD_IMAGE_SELECTOR =
282      'swiper-slide:not(.hidden) [data-custom="content-card"] .card-image-container img';
283    var CARD_IMAGE_SELECTOR =
284      '[data-custom="content-card"] .card-image-container img';
285    var CSS_VAR_NAME = "--card-shadow-height";
286    var currentImage = null;
287    var imageLoadHandler = null;
288    var resizeObserver = null;
289    var mutationObserver = null;
290    var syncFrame = 0;
291    var lastHeight = "";
292
293    function findSampleImage() {
294      return (
295        document.querySelector(SWIPER_CARD_IMAGE_SELECTOR) ||
296        document.querySelector(CARD_IMAGE_SELECTOR)
297      );
298    }
299
300    function setShadowHeight(image) {
301      if (!image || !image.isConnected) return false;
302
303      var height = image.getBoundingClientRect().height;
304      if (!(height > 0)) return false;
305
306      var nextHeight = Math.round(height * 100) / 100 + "px";
307      if (nextHeight !== lastHeight) {
308        document.documentElement.style.setProperty(CSS_VAR_NAME, nextHeight);
309        lastHeight = nextHeight;
310      }
311
312      return true;
313    }
314
315    function disconnectImageObserver() {
316      if (currentImage && imageLoadHandler) {
317        currentImage.removeEventListener("load", imageLoadHandler);
318      }
319
320      if (resizeObserver) {
321        resizeObserver.disconnect();
322        resizeObserver = null;
323      }
324
325      currentImage = null;
326      imageLoadHandler = null;
327    }
328
329    function watchImage(image) {
330      if (!image || image === currentImage) return;
331
332      disconnectImageObserver();
333      currentImage = image;
334      imageLoadHandler = scheduleSync;
335      currentImage.addEventListener("load", imageLoadHandler);
336
337      if ("ResizeObserver" in window) {
338        resizeObserver = new ResizeObserver(scheduleSync);
339        resizeObserver.observe(currentImage);
340
341        var container = currentImage.closest(".card-image-container");
342        if (container) {
343          resizeObserver.observe(container);
344        }
345      }
346    }
347
348    function syncCardShadowHeight() {
349      var image = currentImage;
350
351      if (!image || !image.isConnected || !setShadowHeight(image)) {
352        image = findSampleImage();
353        if (!image) return;
354
355        watchImage(image);
356        setShadowHeight(image);
357      }
358    }
359
360    function scheduleSync() {
361      if (syncFrame) return;
362
363      syncFrame = window.requestAnimationFrame(function () {
364        syncFrame = 0;
365        syncCardShadowHeight();
366      });
367    }
368
369    function startDomObserver() {
370      if (mutationObserver || !document.documentElement) return;
371
372      mutationObserver = new MutationObserver(scheduleSync);
373      mutationObserver.observe(document.documentElement, {
374        childList: true,
375        subtree: true,
376        attributes: true,
377        attributeFilter: ["class"],
378      });
379    }
380
381    function initCardShadowHeightSync() {
382      startDomObserver();
383      scheduleSync();
384    }
385
386    document.addEventListener("turbo:load", scheduleSync);
387    document.addEventListener("turbo:render", scheduleSync);
388    document.addEventListener("turbo:frame-load", scheduleSync);
389    window.addEventListener("pageshow", scheduleSync);
390    window.addEventListener("resize", scheduleSync);
391
392    if (document.readyState === "loading") {
393      document.addEventListener("DOMContentLoaded", initCardShadowHeightSync, {
394        once: true,
395      });
396    } else {
397      initCardShadowHeightSync();
398    }
399  })();
400</script>
400
401<link rel="profile" href="https://gmpg.org/xfn/11" />
402<link
403  rel="apple-touch-icon"
404  sizes="180x180"
405  href="https://uscreen-customizations.b-cdn.net/toveedo/brand/toveedo-browser-icon.png"
406/>
407<link
408  rel="icon"
409  type="image/png"
410  sizes="32x32"
411  href="https://uscreen-customizations.b-cdn.net/toveedo/brand/toveedo-browser-icon.png"
412/>
413<link
414  rel="icon"
415  type="image/png"
416  sizes="16x16"
417  href="https://uscreen-customizations.b-cdn.net/toveedo/brand/toveedo-browser-icon.png"
418/>
419<link
420  rel="shortcut icon"
421  type="image/png"
422  href="https://uscreen-customizations.b-cdn.net/toveedo/brand/toveedo-browser-icon.png"
423/>
424<link
425  rel="manifest"
426  href="https://s3.amazonaws.com/unode1/assets/556/rDcArYznT8a4NHzQNSYy_site.webmanifest"
427/>
428<link
429  rel="mask-icon"
430  href="https://s3.amazonaws.com/unode1/assets/556/dQ4wKg5RZW8mDKlz3FD5_safari-pinned-tab.svg"
431  color="#5bbad5"
432/>
433<meta name="msapplication-TileColor" content="#ffffff" />
434<meta name="theme-color" content="#ffffff" />
435
436<script>
437  (function () {
438    var SESSION_ENDPOINT = "https://toveedo.com/api/sessions";
439    var MIN_SYNC_INTERVAL_MS = 60 * 1000;
440    var lastSyncStartedAt = 0;
441
442    function broadcastMemberState(state, syncedAt) {
443      var detail = {
444        state: state,
445        loggedIn: state === "logged_in",
446        syncedAt: syncedAt,
447      };
448
449      window.__TOVEEDO_MEMBER_STATE__ = detail;
450
451      if (typeof window.CustomEvent === "function") {
452        window.dispatchEvent(
453          new CustomEvent("toveedo:member-state-sync", { detail: detail }),
454        );
455      }
456    }
457
458    function persistMemberState(state) {
459      var syncedAt = String(Date.now());
460      broadcastMemberState(state, syncedAt);
461    }
462
463    function syncMemberState() {
464      var now = Date.now();
465
466      if (now - lastSyncStartedAt < MIN_SYNC_INTERVAL_MS) {
467        return;
468      }
469
470      lastSyncStartedAt = now;
471
472      window
473        .fetch(SESSION_ENDPOINT, {
474          credentials: "include",
475          headers: { Accept: "application/json" },
476          cache: "no-store",
477        })
478        .then(function (response) {
479          if (!response.ok) {
480            throw new Error(
481              "Session sync failed with status " + response.status,
482            );
483          }
484
485          return response.json();
486        })
487        .then(function (payload) {
488          persistMemberState(
489            payload && payload.logged === true ? "logged_in" : "guest",
490          );
491        })
492        .catch(function () {
493          if (!window.__TOVEEDO_MEMBER_STATE__) {
494            persistMemberState("guest");
495          }
496        });
497    }
498
499    syncMemberState();
500    window.addEventListener("focus", syncMemberState);
501    window.addEventListener("pageshow", syncMemberState);
502    document.addEventListener("visibilitychange", function () {
503      if (document.visibilityState === "visible") {
504        syncMemberState();
505      }
506    });
507    window.setInterval(syncMemberState, 5 * 60 * 1000);
508  })();
509</script>
509
510
511<script>
512  (function () {
513    var HEADER_API_URL = "https://home.toveedo.com/api/header-menu";
514    var HEADER_HOME_URL = "https://toveedo.com";
515    var HEADER_TARGET_SELECTOR = "#website-header #website-links";
516    var HEADER_MOBILE_TARGET_SELECTOR =
517      '[data-themeless--header-target="menuNavigation"]';
518    var HEADER_LOGO_SELECTOR = "#website-header #store-logo img";
519    var HEADER_LOGO_LINK_SELECTOR = "#website-header #store-logo";
520    var HEADER_LOGO_URL =
521      "https://uscreen-customizations.b-cdn.net/toveedo/home_hero_logo_e9cc7d78af.svg";
522    var HEADER_MARKER = "data-toveedo-uscreen-header-dropdown";
523    var HEADER_MOBILE_MARKER = "data-toveedo-uscreen-header-mobile-menu";
524    var HEADER_STYLE_MARKER = "data-toveedo-uscreen-header-dropdown-style";
525    var HEADER_SIGNATURE_ATTR = "data-toveedo-uscreen-header-signature";
526    var headerPromise = null;
527    var syncQueued = false;
528    var observer = null;
529    var documentBound = false;
530
531    function ensureHeaderStyles() {
532      if (document.head.querySelector("style[" + HEADER_STYLE_MARKER + "]")) {
533        return;
534      }
535
536      var style = document.createElement("style");
537      style.setAttribute(HEADER_STYLE_MARKER, "true");
538      style.textContent =
539        ".toveedo-uscreen-header-dropdown{position:relative;display:flex;align-items:center;height:100%;margin-right:1.25rem;flex:none;}" +
540        ".toveedo-uscreen-header-dropdown__toggle{appearance:none;border:0;background:transparent;padding:0;color:#fff;font-family:'Open Sans',sans-serif;font-size:1rem;font-weight:700;cursor:pointer;display:inline-flex;align-items:center;gap:.65rem;line-height:1;}" +
541        ".toveedo-uscreen-header-dropdown__toggle svg{display:block;transition:transform .2s ease;}" +
542        ".toveedo-uscreen-header-dropdown.is-open .toveedo-uscreen-header-dropdown__toggle svg{transform:rotate(180deg);}" +
543        ".toveedo-uscreen-header-dropdown__menu{position:absolute;top:calc(100% + .9rem);right:-1rem;z-index:150;min-width:11.5rem;padding:.6rem 0;border:1px solid rgba(255,255,255,.3);border-radius:.9rem;background:#41d0ff;box-shadow:0 18px 40px rgba(0,0,0,.16);}" +
544        ".toveedo-uscreen-header-dropdown__link{display:block;padding:.7rem 1rem;color:#fff !important;font-family:'Open Sans',sans-serif;font-size:.98rem;font-weight:700;line-height:1.35;text-decoration:none;transition:background-color .18s ease;white-space:nowrap;}" +
545        ".toveedo-uscreen-header-dropdown__link:hover,.toveedo-uscreen-header-dropdown__link:focus-visible{background:rgba(255,255,255,.1);}" +
546        ".toveedo-uscreen-header-mobile-menu{padding:0 1rem .5rem;border-bottom:1px solid rgba(255,255,255,.18);margin-bottom:.35rem;}" +
547        ".toveedo-uscreen-header-mobile-menu__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.1rem;}" +
548        ".toveedo-uscreen-header-mobile-menu__link{display:block;padding:.55rem 0;color:inherit !important;font-family:'Open Sans',sans-serif;font-size:1rem;font-weight:600;line-height:1.25;text-decoration:none;}" +
549        ".toveedo-uscreen-header-mobile-menu__link:hover,.toveedo-uscreen-header-mobile-menu__link:focus-visible{text-decoration:underline;text-underline-offset:2px;}" +
550        "@media (max-width:767px){.toveedo-uscreen-header-dropdown{display:none !important;}}";
551
552      document.head.appendChild(style);
553    }
554
555    function escapeHtml(value) {
556      return String(value || "")
557        .replace(/&/g, "&amp;")
558        .replace(/</g, "&lt;")
559        .replace(/>/g, "&gt;")
560        .replace(/"/g, "&quot;")
561        .replace(/'/g, "&#39;");
562    }
563
564    function normalizeHeaderUrl(url) {
565      if (!url) return "#";
566      if (/^(?:https?:)?\/\//i.test(url) || url.charAt(0) === "#") return url;
567      if (url.charAt(0) === "/") return HEADER_HOME_URL + url;
568      return HEADER_HOME_URL + "/" + url.replace(/^\/+/, "");
569    }
570
571    function fetchHeaderPayload() {
572      if (!headerPromise) {
573        headerPromise = window
574          .fetch(HEADER_API_URL, {
575            mode: "cors",
576            credentials: "omit",
577            headers: { Accept: "application/json" },
578            cache: "no-store",
579          })
580          .then(function (response) {
581            if (!response.ok) {
582              throw new Error(
583                "Header sync failed with status " + response.status,
584              );
585            }
586
587            return response.json();
588          })
589          .catch(function (error) {
590            headerPromise = null;
591            throw error;
592          });
593      }
594
595      return headerPromise;
596    }
597
598    function getHeaderItems(payload) {
599      return (
600        (Array.isArray(payload && payload.popupItems) && payload.popupItems) ||
601        (Array.isArray(payload && payload.items) && payload.items) ||
602        []
603      );
604    }
605
606    function getHeaderSignature(items) {
607      return JSON.stringify(
608        items.map(function (item) {
609          return {
610            label: item && item.label,
611            url: item && item.url,
612            openInNewTab: Boolean(item && item.openInNewTab),
613          };
614        }),
615      );
616    }
617
618    function loggedInMember() {
619      var memberState =
620        window.__TOVEEDO_MEMBER_STATE__ &&
621        window.__TOVEEDO_MEMBER_STATE__.state;
622      if (memberState === "logged_in") return true;
623      if (memberState === "guest") return false;
624
625      return false;
626    }
627
628    function buildHeaderMarkup(payload) {
629      var items = getHeaderItems(payload);
630      var signature = escapeHtml(getHeaderSignature(items));
631
632      var linksHtml = items
633        .map(function (item) {
634          var target =
635            item && item.openInNewTab
636              ? ' target="_blank" rel="noopener noreferrer"'
637              : "";
638
639          return (
640            '<a class="toveedo-uscreen-header-dropdown__link" href="' +
641            normalizeHeaderUrl(item && item.url) +
642            '"' +
643            target +
644            ">" +
645            escapeHtml(item && item.label) +
646            "</a>"
647          );
648        })
649        .join("");
650
651      return (
652        '<div class="toveedo-uscreen-header-dropdown" ' +
653        HEADER_MARKER +
654        '="true" ' +
655        HEADER_SIGNATURE_ATTR +
656        '="' +
657        signature +
658        '">' +
659        '<button class="toveedo-uscreen-header-dropdown__toggle" type="button" aria-expanded="false" aria-haspopup="true">' +
660        "<span>Menu</span>" +
661        '<svg width="10" height="5" viewBox="0 0 10 5" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">' +
662        '<path d="M5 5L0 0H10L5 5Z" fill="currentColor" />' +
663        "</svg>" +
664        "</button>" +
665        '<div class="toveedo-uscreen-header-dropdown__menu" hidden>' +
666        linksHtml +
667        "</div>" +
668        "</div>"
669      );
670    }
671
672    function buildMobileHeaderMarkup(payload) {
673      var items = getHeaderItems(payload);
674      var signature = escapeHtml(getHeaderSignature(items));
675
676      var linksHtml = items
677        .map(function (item) {
678          var target =
679            item && item.openInNewTab
680              ? ' target="_blank" rel="noopener noreferrer"'
681              : "";
682
683          return (
684            '<li><a class="toveedo-uscreen-header-mobile-menu__link" href="' +
685            normalizeHeaderUrl(item && item.url) +
686            '"' +
687            target +
688            ">" +
689            escapeHtml(item && item.label) +
690            "</a></li>"
691          );
692        })
693        .join("");
694
695      return (
696        '<nav class="toveedo-uscreen-header-mobile-menu" ' +
697        HEADER_MOBILE_MARKER +
698        '="true" ' +
699        HEADER_SIGNATURE_ATTR +
700        '="' +
701        signature +
702        '">' +
703        '<ul class="toveedo-uscreen-header-mobile-menu__list">' +
704        linksHtml +
705        "</ul>" +
706        "</nav>"
707      );
708    }
709
710    function closeHeaderDropdown(dropdownRoot) {
711      if (!dropdownRoot) return;
712
713      var toggle = dropdownRoot.querySelector(
714        ".toveedo-uscreen-header-dropdown__toggle",
715      );
716      var menu = dropdownRoot.querySelector(
717        ".toveedo-uscreen-header-dropdown__menu",
718      );
719
720      if (!toggle || !menu) return;
721
722      dropdownRoot.classList.remove("is-open");
723      toggle.setAttribute("aria-expanded", "false");
724      menu.hidden = true;
725    }
726
727    function openHeaderDropdown(dropdownRoot) {
728      if (!dropdownRoot) return;
729
730      var toggle = dropdownRoot.querySelector(
731        ".toveedo-uscreen-header-dropdown__toggle",
732      );
733      var menu = dropdownRoot.querySelector(
734        ".toveedo-uscreen-header-dropdown__menu",
735      );
736
737      if (!toggle || !menu) return;
738
739      dropdownRoot.classList.add("is-open");
740      toggle.setAttribute("aria-expanded", "true");
741      menu.hidden = false;
742    }
743
744    function bindHeaderDocumentEvents() {
745      if (documentBound) return;
746
747      document.addEventListener("click", function (event) {
748        Array.from(
749          document.querySelectorAll("[" + HEADER_MARKER + "]"),
750        ).forEach(function (dropdownRoot) {
751          if (!dropdownRoot.contains(event.target)) {
752            closeHeaderDropdown(dropdownRoot);
753          }
754        });
755      });
756
757      document.addEventListener("keydown", function (event) {
758        if (event.key !== "Escape") return;
759
760        Array.from(
761          document.querySelectorAll("[" + HEADER_MARKER + "]"),
762        ).forEach(function (dropdownRoot) {
763          closeHeaderDropdown(dropdownRoot);
764        });
765      });
766
767      documentBound = true;
768    }
769
770    function bindHeaderDropdown(dropdownRoot) {
771      if (
772        !dropdownRoot ||
773        dropdownRoot.dataset.toveedoDropdownBound === "true"
774      ) {
775        return;
776      }
777
778      var toggle = dropdownRoot.querySelector(
779        ".toveedo-uscreen-header-dropdown__toggle",
780      );
781      var menu = dropdownRoot.querySelector(
782        ".toveedo-uscreen-header-dropdown__menu",
783      );
784
785      if (!toggle || !menu) return;
786
787      toggle.addEventListener("click", function (event) {
788        event.preventDefault();
789        event.stopPropagation();
790
791        if (menu.hidden) {
792          Array.from(
793            document.querySelectorAll("[" + HEADER_MARKER + "]"),
794          ).forEach(function (otherDropdownRoot) {
795            if (otherDropdownRoot !== dropdownRoot) {
796              closeHeaderDropdown(otherDropdownRoot);
797            }
798          });
799          openHeaderDropdown(dropdownRoot);
800        } else {
801          closeHeaderDropdown(dropdownRoot);
802        }
803      });
804
805      dropdownRoot.dataset.toveedoDropdownBound = "true";
806      closeHeaderDropdown(dropdownRoot);
807    }
808
809    function syncHeaderLogo() {
810      var headerLogo = document.querySelector(HEADER_LOGO_SELECTOR);
811      var headerLogoLink = document.querySelector(HEADER_LOGO_LINK_SELECTOR);
812      if (!headerLogo) return;
813
814      if (headerLogo.getAttribute("src") !== HEADER_LOGO_URL) {
815        headerLogo.setAttribute("src", HEADER_LOGO_URL);
816      }
817
818      if (headerLogo.hasAttribute("srcset")) {
819        headerLogo.removeAttribute("srcset");
820      }
821
822      if (headerLogoLink) {
823        if (!headerLogoLink.dataset.toveedoDefaultHref) {
824          headerLogoLink.dataset.toveedoDefaultHref =
825            headerLogoLink.getAttribute("href") || "/";
826        }
827
828        headerLogoLink.setAttribute(
829          "href",
830          loggedInMember()
831            ? "/catalog"
832            : headerLogoLink.dataset.toveedoDefaultHref,
833        );
834      }
835    }
836
837    function syncHeaderDropdown() {
838      var target = document.querySelector(HEADER_TARGET_SELECTOR);
839      var mobileTarget = document.querySelector(HEADER_MOBILE_TARGET_SELECTOR);
840      syncHeaderLogo();
841      if (
842        (!target || !target.parentNode) &&
843        (!mobileTarget || !mobileTarget.parentNode)
844      ) {
845        return;
846      }
847
848      ensureHeaderStyles();
849
850      fetchHeaderPayload()
851        .then(function (payload) {
852          var existingDropdown = document.querySelector(
853            "[" + HEADER_MARKER + "]",
854          );
855          var markup = buildHeaderMarkup(payload);
856          var existingMobileMenu = document.querySelector(
857            "[" + HEADER_MOBILE_MARKER + "]",
858          );
859          var mobileMarkup = buildMobileHeaderMarkup(payload);
860          var nextSignature = getHeaderSignature(getHeaderItems(payload));
861
862          if (target && target.parentNode) {
863            if (existingDropdown) {
864              if (existingDropdown.previousElementSibling !== target) {
865                existingDropdown.remove();
866                target.insertAdjacentHTML("afterend", markup);
867              } else if (
868                existingDropdown.getAttribute(HEADER_SIGNATURE_ATTR) !==
869                nextSignature
870              ) {
871                existingDropdown.outerHTML = markup;
872              }
873            } else {
874              target.insertAdjacentHTML("afterend", markup);
875            }
876          }
877
878          if (mobileTarget && mobileTarget.parentNode) {
879            if (existingMobileMenu) {
880              if (existingMobileMenu.nextElementSibling !== mobileTarget) {
881                existingMobileMenu.remove();
882                mobileTarget.insertAdjacentHTML("beforebegin", mobileMarkup);
883              } else if (
884                existingMobileMenu.getAttribute(HEADER_SIGNATURE_ATTR) !==
885                nextSignature
886              ) {
887                existingMobileMenu.outerHTML = mobileMarkup;
888              }
889            } else {
890              mobileTarget.insertAdjacentHTML("beforebegin", mobileMarkup);
891            }
892          }
893
894          bindHeaderDocumentEvents();
895          bindHeaderDropdown(document.querySelector("[" + HEADER_MARKER + "]"));
896        })
897        .catch(function (error) {
898          console.error(error);
899        });
900    }
901
902    function scheduleHeaderSync() {
903      if (syncQueued) return;
904
905      syncQueued = true;
906      window.requestAnimationFrame(function () {
907        syncQueued = false;
908        syncHeaderDropdown();
909      });
910    }
911
912    function startHeaderObserver() {
913      if (observer || !document.documentElement) return;
914
915      observer = new MutationObserver(function () {
916        scheduleHeaderSync();
917      });
918
919      observer.observe(document.documentElement, {
920        childList: true,
921        subtree: true,
922      });
923    }
924
925    function initHeaderSync() {
926      startHeaderObserver();
927      scheduleHeaderSync();
928    }
929
930    document.addEventListener("turbo:load", scheduleHeaderSync);
931    document.addEventListener("turbo:render", scheduleHeaderSync);
932    document.addEventListener("turbo:frame-load", scheduleHeaderSync);
933    window.addEventListener("pageshow", scheduleHeaderSync);
934    window.addEventListener("toveedo:member-state-sync", scheduleHeaderSync);
935
936    if (document.readyState === "loading") {
937      document.addEventListener("DOMContentLoaded", initHeaderSync, {
938        once: true,
939      });
940    } else {
941      initHeaderSync();
942    }
943  })();
944</script>
944
945
946<script>
947  (function () {
948    var FOOTER_API_URL = "https://home.toveedo.com/api/footer-menu";
949    var FOOTER_HOME_URL = "https://toveedo.com";
950    var FOOTER_LOGO_URL =
951      "https://uscreen-customizations.b-cdn.net/toveedo/toveedo_footer_logo_8d654d52cc.svg";
952    var FOOTER_BACKGROUND_URL =
953      "https://uscreen-customizations.b-cdn.net/toveedo/large_toveedo_footer_wave_background_ff898d5227.png";
954    var FOOTER_MARKER = "data-toveedo-uscreen-footer";
955    var FOOTER_STYLE_MARKER = "data-toveedo-uscreen-footer-style";
956    var nativeFooterSelector = "footer.bg-ds-default";
957    var footerPromise = null;
958    var syncQueued = false;
959    var observer = null;
960
961    function ensureFooterStyles() {
962      if (document.head.querySelector("style[" + FOOTER_STYLE_MARKER + "]")) {
963        return;
964      }
965
966      var style = document.createElement("style");
967      style.setAttribute(FOOTER_STYLE_MARKER, "true");
968      style.textContent =
969        ".toveedo-uscreen-footer{margin-top:4.75rem;background:" +
970        "url('" +
971        FOOTER_BACKGROUND_URL +
972        "') no-repeat top center,linear-gradient(to bottom,#fff 0%,#fff 100%);" +
973        "background-size:cover;color:#fff;opacity:1;position:relative;z-index:2;}" +
974        ".toveedo-uscreen-footer__inner{max-width:1120px;margin:0 auto;padding:clamp(8rem,18vw,22rem) 1.5rem 4.4rem;text-align:center;}" +
975        ".toveedo-uscreen-footer__logo-link{display:inline-flex;align-items:center;justify-content:center;text-decoration:none;}" +
976        ".toveedo-uscreen-footer__logo-image{display:block;width:auto;height:auto;max-width:min(13rem,60vw);}" +
977        ".toveedo-uscreen-footer__nav{display:flex;justify-content:center;flex-wrap:wrap;gap:.95rem 1.6rem;margin-top:2rem;}" +
978        ".toveedo-uscreen-footer__nav-link{color:#fff !important;font-size:.95rem;font-weight:700;line-height:1.35;text-transform:uppercase;text-decoration:none;transition:opacity 180ms ease;}" +
979        ".toveedo-uscreen-footer__nav-link:hover,.toveedo-uscreen-footer__nav-link:focus-visible{opacity:.88;}" +
980        ".toveedo-uscreen-footer__copyright{margin:1.35rem 0 0;color:rgba(255,255,255,.92);font-size:.78rem;text-transform:uppercase;}" +
981        "footer[data-toveedo-native-footer-hidden='true']{display:none !important;}" +
982        "@media (max-width:767px){.toveedo-uscreen-footer__inner{padding-top:6rem;padding-bottom:3rem;}.toveedo-uscreen-footer__nav{flex-direction:column;gap:.65rem;}}";
983
984      document.head.appendChild(style);
985    }
986
987    function normalizeFooterUrl(url) {
988      if (!url) return "#";
989      if (/^(?:https?:)?\/\//i.test(url) || url.charAt(0) === "#") return url;
990      if (url.charAt(0) === "/") return FOOTER_HOME_URL + url;
991      return FOOTER_HOME_URL + "/" + url.replace(/^\/+/, "");
992    }
993
994    function fetchFooterPayload() {
995      if (!footerPromise) {
996        footerPromise = window
997          .fetch(FOOTER_API_URL, {
998            mode: "cors",
999            credentials: "omit",
1000            headers: { Accept: "application/json" },
1001            cache: "no-store",
1002          })
1003          .then(function (response) {
1004            if (!response.ok) {
1005              throw new Error(
1006                "Footer sync failed with status " + response.status,
1007              );
1008            }
1009
1010            return response.json();
1011          })
1012          .catch(function (error) {
1013            footerPromise = null;
1014            throw error;
1015          });
1016      }
1017
1018      return footerPromise;
1019    }
1020
1021    function buildFooterMarkup(payload) {
1022      var links = Array.isArray(payload && payload.items) ? payload.items : [];
1023      var copyrightText =
1024        (payload && payload.copyrightText) || "© 2026 All Rights Reserved.";
1025
1026      var navHtml = links
1027        .map(function (item) {
1028          var target =
1029            item && item.openInNewTab
1030              ? ' target="_blank" rel="noopener noreferrer"'
1031              : "";
1032          return (
1033            '<a class="toveedo-uscreen-footer__nav-link" href="' +
1034            normalizeFooterUrl(item && item.url) +
1035            '"' +
1036            target +
1037            ">" +
1038            String((item && item.label) || "")
1039              .replace(/&/g, "&amp;")
1040              .replace(/</g, "&lt;")
1041              .replace(/>/g, "&gt;") +
1042            "</a>"
1043          );
1044        })
1045        .join("");
1046
1047      return (
1048        '<footer class="toveedo-uscreen-footer" ' +
1049        FOOTER_MARKER +
1050        '="true">' +
1051        '<div class="toveedo-uscreen-footer__inner">' +
1052        '<a class="toveedo-uscreen-footer__logo-link" href="' +
1053        FOOTER_HOME_URL +
1054        '/">' +
1055        '<img class="toveedo-uscreen-footer__logo-image" src="' +
1056        FOOTER_LOGO_URL +
1057        '" alt="Toveedo" loading="lazy" decoding="async" />' +
1058        "</a>" +
1059        '<nav class="toveedo-uscreen-footer__nav" aria-label="Footer">' +
1060        navHtml +
1061        "</nav>" +
1062        '<p class="toveedo-uscreen-footer__copyright">' +
1063        String(copyrightText)
1064          .replace(/&/g, "&amp;")
1065          .replace(/</g, "&lt;")
1066          .replace(/>/g, "&gt;") +
1067        "</p>" +
1068        "</div>" +
1069        "</footer>"
1070      );
1071    }
1072
1073    function syncFooter() {
1074      var nativeFooter = document.querySelector(nativeFooterSelector);
1075      if (!nativeFooter || !nativeFooter.parentNode) return;
1076
1077      ensureFooterStyles();
1078
1079      fetchFooterPayload()
1080        .then(function (payload) {
1081          var existingFooter = document.querySelector(
1082            "[" + FOOTER_MARKER + "]",
1083          );
1084          var markup = buildFooterMarkup(payload);
1085
1086          if (existingFooter) {
1087            if (existingFooter.nextElementSibling !== nativeFooter) {
1088              existingFooter.remove();
1089              nativeFooter.insertAdjacentHTML("beforebegin", markup);
1090            }
1091          } else {
1092            nativeFooter.insertAdjacentHTML("beforebegin", markup);
1093          }
1094
1095          nativeFooter.setAttribute(
1096            "data-toveedo-native-footer-hidden",
1097            "true",
1098          );
1099          nativeFooter.setAttribute("aria-hidden", "true");
1100        })
1101        .catch(function (error) {
1102          console.error(error);
1103        });
1104    }
1105
1106    function scheduleFooterSync() {
1107      if (syncQueued) return;
1108
1109      syncQueued = true;
1110      window.requestAnimationFrame(function () {
1111        syncQueued = false;
1112        syncFooter();
1113      });
1114    }
1115
1116    function startFooterObserver() {
1117      if (observer || !document.documentElement) return;
1118
1119      observer = new MutationObserver(function () {
1120        scheduleFooterSync();
1121      });
1122
1123      observer.observe(document.documentElement, {
1124        childList: true,
1125        subtree: true,
1126      });
1127    }
1128
1129    function initFooterSync() {
1130      startFooterObserver();
1131      scheduleFooterSync();
1132    }
1133
1134    document.addEventListener("turbo:load", scheduleFooterSync);
1135    document.addEventListener("turbo:render", scheduleFooterSync);
1136    document.addEventListener("turbo:frame-load", scheduleFooterSync);
1137    window.addEventListener("pageshow", scheduleFooterSync);
1138
1139    if (document.readyState === "loading") {
1140      document.addEventListener("DOMContentLoaded", initFooterSync, {
1141        once: true,
1142      });
1143    } else {
1144      initFooterSync();
1145    }
1146  })();
1147</script>
1147
1148
1149<!--Facebook Pixel Code-->
1150<script>
1151  !(function (f, b, e, v, n, t, s) {
1152    if (f.fbq) return;
1153    n = f.fbq = function () {
1154      n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments);
1155    };
1156    if (!f._fbq) f._fbq = n;
1157    n.push = n;
1158    n.loaded = !0;
1159    n.version = "2.0";
1160    n.queue = [];
1161    t = b.createElement(e);
1162    t.async = !0;
1163    t.src = v;
1164    s = b.getElementsByTagName(e)[0];
1165    s.parentNode.insertBefore(t, s);
1166  })(
1167    window,
1168    document,
1169    "script",
1170    "https://connect.facebook.net/en_US/fbevents.js",
1171  );
1172  fbq("init", "628633714435515");
1173  fbq("track", "PageView");
1174</script>
1174
1175<noscript
1176  ><img
1177    height="1"
1178    width="1"
1179    style="display: none"
1180    src="https://www.facebook.com/tr?id=628633714435515&ev=PageView&noscript=1" /></noscript
1181><!--End Facebook Pixel Code-->
1182
1183<link rel="preconnect" href="https://fonts.googleapis.com" />
1184<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
1185<link
1186  href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&family=Quicksand:[email protected]&display=swap"
1187  rel="stylesheet"
1188/>
1189
1190<style>
1191  [data-themeless--header-target="menuNavigation"]
1192    a[href="https://toveedo.com/playlists"] {
1193    display: none;
1194  }
1195  [data-themeless--header-target="navigationLinks"]
1196    a[href="https://toveedo.com/playlists"]
1197    > span {
1198    border: 1px solid #fff;
1199    padding: 0.75rem 0.75rem;
1200    border-radius: 4px;
1201    background-color: rgba(255, 255, 255, 0.1);
1202    transform: background-color 0.3s;
1203  }
1204  [data-themeless--header-target="navigationLinks"]
1205    a[href="https://toveedo.com/playlists"]:hover
1206    > span {
1207    background-color: rgba(255, 255, 255, 0.3);
1208  }
1209  #main-menu > a + div {
1210    display: block;
1211  }
1212  #store-logo > img {
1213    max-height: 5rem;
1214    max-width: 14.5rem;
1215  }
1216  #website-header.h-20 {
1217    height: 5.6rem;
1218  }
1219  .themeless-featured-slide {
1220    opacity: 0;
1221  }
1222  [data-test="themeless-featured-slider"] .text-gray-900,
1223  [data-test="themeless-featured-slider"] .text-gray-700 {
1224    color: #fff !important;
1225  }
1226  [data-type="home"] {
1227    display: none;
1228  }
1229  swiper-slide.hidden {
1230    display: none;
1231  }
1232  #website-header {
1233    background-color: var(--primary);
1234  }
1235  .category-title {
1236    color: var(--primary) !important;
1237    font-weight: 600;
1238  }
1239  #website-header .text-primary {
1240    color: #fff !important;
1241  }
1242  .catalog-top-slider {
1243    background: #5ed1ff;
1244    position: relative;
1245    padding-left: 0%;
1246    padding-right: 0%;
1247  }
1248  .catalog-top-slider--relative {
1249    position: relative;
1250  }
1251  .catalog-top-slider--slide a {
1252    display: block;
1253    position: relative;
1254  }
1255  .catalog-top-slider--slide a > div {
1256    position: absolute;
1257    top: -20px;
1258    left: 0;
1259    width: 100%;
1260    height: 100%;
1261    z-index: 2;
1262    padding: 20px;
1263    text-align: center;
1264    display: flex;
1265    justify-content: center;
1266    align-items: center;
1267    line-height: 1.4;
1268    opacity: 0;
1269    transition:
1270      top 0.3s,
1271      opacity 0.3s;
1272    color: #fff !important;
1273  }
1274  .catalog-top-slider--slide a:before {
1275    content: "";
1276    position: absolute;
1277    top: 10px;
1278    left: 10px;
1279    width: calc(100% - 20px);
1280    height: calc(100% - 20px);
1281    background-color: rgba(0, 0, 0, 0.6);
1282    border-radius: 50%;
1283    z-index: 1;
1284    opacity: 0;
1285    transition: opacity 0.3s;
1286  }
1287  .catalog-top-slider--slide a:hover > div {
1288    top: 0;
1289    opacity: 1;
1290  }
1291  .catalog-top-slider--slide a:hover:before {
1292    opacity: 1;
1293  }
1294
1295  .catalog-top-slider--slide a {
1296    max-width: 150px;
1297    padding: 10px;
1298  }
1299  .catalog-top-slider--slide a img {
1300    border-radius: 50%;
1301  }
1302
1303  .catalog-top-slider--inner {
1304    max-height: 147px;
1305    overflow: hidden;
1306    opacity: 0;
1307    transition: opacity 0.3s;
1308  }
1309
1310  .catalog-top-slider--inner.slick-initialized {
1311    opacity: 1;
1312    overflow: visible;
1313  }
1314
1315  .catalog-top-slider--inner {
1316    padding-left: 100px;
1317    padding-right: 100px;
1318  }
1319  .catalog-top-slider--arrow {
1320    position: absolute;
1321    top: 0;
1322    cursor: pointer;
1323    width: 100px;
1324    height: 100%;
1325    display: flex;
1326    justify-content: center;
1327    align-items: center;
1328    background-color: #2bc2ff;
1329  }
1330  .catalog-top-slider--arrow img {
1331    max-width: 30px;
1332  }
1333  .catalog-top-slider--arrow.catalog-top-slider--arrow-left {
1334    left: 0;
1335  }
1336  .catalog-top-slider--arrow.catalog-top-slider--arrow-right {
1337    right: 0;
1338  }
1339
1340  .catalog-top-slider--arrow.slick-disabled {
1341    cursor: default;
1342    opacity: 0.4;
1343  }
1344
1345  @media only screen and (min-width: 991px) and (max-width: 1199px) {
1346  }
1347  @media only screen and (min-width: 768px) and (max-width: 992px) {
1348    .catalog-top-slider--arrow {
1349      width: 60px;
1350    }
1351    .catalog-top-slider--inner {
1352      padding-left: 60px;
1353      padding-right: 60px;
1354    }
1355    .catalog-top-slider--arrow img {
1356      max-width: 20px;
1357    }
1358  }
1359  @media only screen and (max-width: 767px) {
1360    .catalog-top-slider--arrow {
1361      width: 30px;
1362    }
1363    .catalog-top-slider--inner {
1364      padding-left: 60px;
1365      padding-right: 60px;
1366    }
1367    .catalog-top-slider--arrow img {
1368      max-width: 10px;
1369    }
1370  }
1371
1372  #page [slot="next-button"] {
1373    left: 97%;
1374    //background: rgba(0, 0, 0, 0.5)
1375      url("https://s3.us-east-1.amazonaws.com/unode1/assets%2Fassets%2F556%2Fright-arrow-shadow3x.1740639245.png")
1376      65% 56% no-repeat !important;
1377    background: rgba(0, 0, 0, 0.5)
1378      url("https://s3.us-east-1.amazonaws.com/unode1/assets%2Fassets%2F15576%2Farrow-right-new.1742208383.svg")
1379      65% 56% no-repeat !important;
1380    background-size: 28px !important;
1381    display: block !important;
1382    height: calc(100% - 22.2px);
1383    bottom: 0;
1384  }
1385  #page .ui-featured-category .swiper-button-next {
1386    left: 96%;
1387  }
1388  #page [slot="prev-button"] {
1389    right: 97%;
1390    //background: rgba(0, 0, 0, 0.5)
1391      url("https://s3.us-east-1.amazonaws.com/unode1/assets%2Fassets%2F556%2Fleft-arrow-shadow3x.1740639253.png")
1392      35% 56% no-repeat !important;
1393    background: rgba(0, 0, 0, 0.5)
1394      url("https://s3.us-east-1.amazonaws.com/unode1/assets%2Fassets%2F15576%2Farrow-left-new.1742208485.svg")
1395      35% 56% no-repeat !important;
1396    background-size: 28px !important;
1397    display: block !important;
1398    display: block !important;
1399    height: calc(100% - 22.2px);
1400    bottom: 0;
1401  }
1402
1403  .content-row [slot="next-button"] {
1404    left: auto !important;
1405    top: -21px;
1406  }
1407  .content-row [slot="prev-button"] {
1408    right: auto !important;
1409    top: -21px;
1410  }
1411  .card-title {
1412    min-height: 40px;
1413  }
1414  .content-row #continue_watching_row [slot="next-button"],
1415  .content-row #continue_watching_row [slot="prev-button"] {
1416    top: -22px;
1417  }
1418  #page [slot="next-button"] ds-icon,
1419  #page [slot="prev-button"] ds-icon {
1420    opacity: 0;
1421  }
1422
1423  .content-row .overflow-hidden {
1424    overflow: visible;
1425  }
1426
1427  .swiper-button-next svg,
1428  .swiper-button-prev svg {
1429    zoom: 2;
1430    stroke: #fff !important;
1431    opacity: 0;
1432  }
1433  .swiper-button-next svg {
1434    position: relative;
1435    left: -5px;
1436  }
1437  .swiper-button-prev svg {
1438    position: relative;
1439    right: -5px;
1440  }
1441</style>
1442
1443<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
1443
1444
1445<script>
1446  var videos = null;
1447  var blockVideoScanStarted = false;
1448
1449  let parseBlockedVideos = (value) => {
1450    try {
1451      let parsed = JSON.parse(value || "[]");
1452      return Array.isArray(parsed) ? parsed : [];
1453    } catch (error) {
1454      return [];
1455    }
1456  };
1457
1458  let detectTemplate = () => {
1459    if (!Array.isArray(videos)) return;
1460
1461    let programTitle = document.querySelector(
1462      'h1[data-area="program-title"]:not(.touched)',
1463    );
1464    if (programTitle) {
1465      videos.forEach((video) => {
1466        if (video == programTitle.innerText.trim()) {
1467          location.replace("/catalog");
1468        }
1469      });
1470      programTitle.classList.add("touched");
1471    }
1472
1473    let cardTitles = document.querySelectorAll(".card-title:not(.touched)");
1474    if (cardTitles.length) {
1475      cardTitles.forEach((cardTitle) => {
1476        cardTitle.classList.add("touched");
1477        videos.forEach((video) => {
1478          if (cardTitle.innerText.trim() === video) {
1479            cardTitle.closest("swiper-slide").classList.add("hidden");
1480          }
1481        });
1482      });
1483    }
1484    setTimeout(() => detectTemplate(), 500);
1485  };
1486
1487  let startBlockedVideoScan = () => {
1488    if (blockVideoScanStarted) return;
1489
1490    blockVideoScanStarted = true;
1491    detectTemplate();
1492  };
1493
1494  axios
1495    .get("/api/sessions", { headers: { Accept: "application/json" } })
1496    .then((response) => {
1497      let session = response.data;
1498      if (!session.logged) return;
1499
1500      axios
1501        .get("/api/users/me", { headers: { Accept: "application/json" } })
1502        .then((userResponse) => {
1503          videos = parseBlockedVideos(userResponse.data.field_1);
1504          startBlockedVideoScan();
1505        });
1506    });
1507</script>
1507
1508
1509<script>
1510  const CUSTOM_CATALOG = false;
1511</script>
vendor: 1 bytes, line 1511
1511
1512<script>
1513  var url = new URL(location.href);
1514  var search = url.search;
1515
1516  let newInfinityScript = () => {
1517    url = new URL(location.href);
1518
1519    if (url.pathname === "/catalog/search") {
1520      let content = document.querySelector("#catalog_content");
1521      if (content) {
1522        if (search !== url.search) {
1523          search = url.search;
1524          setTimeout(() => {
1525            let y =
1526              document.querySelector("#catalog_content").getBoundingClientRect()
1527                .top + window.scrollY;
1528            window.scroll({
1529              top: y,
1530              behavior: "smooth",
1531            });
1532            console.log("search != url.search");
1533          }, 500);
1534        } else {
1535          // console.log("search == url.search")
1536        }
1537      }
1538    }
1539
1540    if (location.href.includes("/catalog")) {
1541      let catalogWrapper = document.querySelector(
1542        ".catalog-area:not(.embeded-touched)",
1543      );
1544      if (catalogWrapper) {
1545        catalogWrapper.classList.add("embeded-touched");
1546        if (CUSTOM_CATALOG) {
1547          catalogWrapper.insertAdjacentHTML(
1548            "afterBegin",
1549            `
1550          <div class="content-row catalog-embeded-content">
1551            <turbo-frame id="custom_catalog" src="/pages/custom-catalog-page"></turbo-frame>
1552          </div>
1553        `,
1554          );
1555        }
1556      }
1557    }
1558
1559    setTimeout(() => newInfinityScript(), 500);
1560  };
1561  newInfinityScript();
1562</script>
1562
1563
1564<script>
1565  (function () {
1566    var FEATURED_BANNER_ROOT_SELECTOR =
1567      '[data-test="themeless-featured-slider"] [data-controller="themeless-featured-slider"]';
1568    var FEATURED_BANNER_SLIDER_SELECTOR =
1569      '[data-test="themeless-featured-slider"] ds-swiper';
1570    var FEATURED_BANNER_STYLE_MARKER =
1571      "data-toveedo-featured-banner-arrow-style";
1572    var FEATURED_BANNER_NAV_ATTR = "data-toveedo-featured-banner-nav";
1573    var FEATURED_BANNER_ARROW_ATTR = "data-toveedo-featured-banner-arrow";
1574    var syncQueued = false;
1575    var observer = null;
1576
1577    function ensureFeaturedBannerArrowStyles() {
1578      if (
1579        document.head.querySelector(
1580          "style[" + FEATURED_BANNER_STYLE_MARKER + "]",
1581        )
1582      ) {
1583        return;
1584      }
1585
1586      var style = document.createElement("style");
1587      style.setAttribute(FEATURED_BANNER_STYLE_MARKER, "true");
1588      style.textContent =
1589        ".toveedo-featured-banner-nav{position:absolute;inset:0;z-index:20;pointer-events:none;}" +
1590        ".toveedo-featured-banner-arrow{position:absolute;top:50%;transform:translateY(-50%);display:flex;align-items:center;justify-content:center;width:clamp(2.75rem,4vw,3.5rem);height:clamp(2.75rem,4vw,3.5rem);padding:0;border:1px solid rgba(255,255,255,.72);border-radius:999px;background:rgba(14,29,46,.34);color:#fff;cursor:pointer;pointer-events:auto;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);box-shadow:0 18px 36px rgba(0,0,0,.22);transition:background-color .18s ease,border-color .18s ease,transform .18s ease,opacity .18s ease;}" +
1591        ".toveedo-featured-banner-arrow:hover,.toveedo-featured-banner-arrow:focus-visible{background:rgba(14,29,46,.56);border-color:rgba(255,255,255,.92);transform:translateY(-50%) scale(1.04);}" +
1592        ".toveedo-featured-banner-arrow:focus-visible{outline:2px solid rgba(255,255,255,.9);outline-offset:2px;}" +
1593        ".toveedo-featured-banner-arrow--prev{left:clamp(.75rem,1.8vw,1.5rem);}" +
1594        ".toveedo-featured-banner-arrow--next{right:clamp(.75rem,1.8vw,1.5rem);}" +
1595        ".toveedo-featured-banner-arrow svg{display:block;width:clamp(1rem,1.8vw,1.35rem);height:clamp(1rem,1.8vw,1.35rem);}" +
1596        ".toveedo-featured-banner-nav[hidden]{display:none !important;}" +
1597        "@media (max-width:767px){.toveedo-featured-banner-arrow{width:2.65rem;height:2.65rem;box-shadow:0 12px 24px rgba(0,0,0,.18);}.toveedo-featured-banner-arrow--prev{left:.55rem;}.toveedo-featured-banner-arrow--next{right:.55rem;}}";
1598
1599      document.head.appendChild(style);
1600    }
1601
1602    function getFeaturedBannerRoot() {
1603      return document.querySelector(FEATURED_BANNER_ROOT_SELECTOR);
1604    }
1605
1606    function getFeaturedBannerSlider(root) {
1607      if (root) {
1608        return root.querySelector("ds-swiper");
1609      }
1610
1611      return document.querySelector(FEATURED_BANNER_SLIDER_SELECTOR);
1612    }
1613
1614    function getFeaturedSlideCount(slider) {
1615      if (!slider) return 0;
1616      if (slider.slides && typeof slider.slides.length === "number") {
1617        return slider.slides.length;
1618      }
1619
1620      return slider.querySelectorAll("swiper-slide").length;
1621    }
1622
1623    function moveFeaturedSlider(slider, direction) {
1624      if (!slider) return;
1625
1626      var methodName = direction === "prev" ? "slidePrev" : "slideNext";
1627      if (typeof slider[methodName] === "function") {
1628        slider[methodName]();
1629        return;
1630      }
1631
1632      if (slider._swiper && typeof slider._swiper[methodName] === "function") {
1633        slider._swiper[methodName]();
1634        return;
1635      }
1636
1637      var shadowButton =
1638        slider.shadowRoot &&
1639        slider.shadowRoot.querySelector(
1640          direction === "prev" ? ".swiper-button-prev" : ".swiper-button-next",
1641        );
1642      if (shadowButton) {
1643        shadowButton.click();
1644      }
1645    }
1646
1647    function createFeaturedBannerArrow(direction, slider) {
1648      var button = document.createElement("button");
1649      button.type = "button";
1650      button.className =
1651        "toveedo-featured-banner-arrow toveedo-featured-banner-arrow--" +
1652        direction;
1653      button.setAttribute(FEATURED_BANNER_ARROW_ATTR, direction);
1654      button.setAttribute(
1655        "aria-label",
1656        direction === "prev"
1657          ? "Previous featured slide"
1658          : "Next featured slide",
1659      );
1660      button.innerHTML =
1661        direction === "prev"
1662          ? '<svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M14.5 5L7.5 12L14.5 19" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/></svg>'
1663          : '<svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M9.5 5L16.5 12L9.5 19" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/></svg>';
1664      button.addEventListener("click", function (event) {
1665        event.preventDefault();
1666        event.stopPropagation();
1667        moveFeaturedSlider(slider, direction);
1668      });
1669
1670      return button;
1671    }
1672
1673    function syncFeaturedBannerArrows() {
1674      var root = getFeaturedBannerRoot();
1675      var slider = getFeaturedBannerSlider(root);
1676      if (!root || !slider) return;
1677
1678      ensureFeaturedBannerArrowStyles();
1679
1680      if (window.getComputedStyle(root).position === "static") {
1681        root.style.position = "relative";
1682      }
1683
1684      var nav = root.querySelector("[" + FEATURED_BANNER_NAV_ATTR + "]");
1685      if (!nav || nav.__toveedoFeaturedBannerSlider !== slider) {
1686        if (nav) {
1687          nav.remove();
1688        }
1689
1690        nav = document.createElement("div");
1691        nav.className = "toveedo-featured-banner-nav";
1692        nav.setAttribute(FEATURED_BANNER_NAV_ATTR, "true");
1693        nav.__toveedoFeaturedBannerSlider = slider;
1694        root.appendChild(nav);
1695      } else if (nav.parentNode !== root) {
1696        nav.remove();
1697        root.appendChild(nav);
1698      }
1699
1700      ["prev", "next"].forEach(function (direction) {
1701        if (
1702          !nav.querySelector(
1703            "[" + FEATURED_BANNER_ARROW_ATTR + '="' + direction + '"]',
1704          )
1705        ) {
1706          nav.appendChild(createFeaturedBannerArrow(direction, slider));
1707        }
1708      });
1709
1710      nav.hidden = getFeaturedSlideCount(slider) < 2;
1711    }
1712
1713    function scheduleFeaturedBannerSync() {
1714      if (syncQueued) return;
1715
1716      syncQueued = true;
1717      window.requestAnimationFrame(function () {
1718        syncQueued = false;
1719        syncFeaturedBannerArrows();
1720      });
1721    }
1722
1723    function startFeaturedBannerObserver() {
1724      if (observer || !document.documentElement) return;
1725
1726      observer = new MutationObserver(function () {
1727        scheduleFeaturedBannerSync();
1728      });
1729
1730      observer.observe(document.documentElement, {
1731        childList: true,
1732        subtree: true,
1733      });
1734    }
1735
1736    function initFeaturedBannerArrows() {
1737      startFeaturedBannerObserver();
1738      scheduleFeaturedBannerSync();
1739    }
1740
1741    document.addEventListener("turbo:load", scheduleFeaturedBannerSync);
1742    document.addEventListener("turbo:render", scheduleFeaturedBannerSync);
1743    document.addEventListener("turbo:frame-load", scheduleFeaturedBannerSync);
1744    window.addEventListener("pageshow", scheduleFeaturedBannerSync);
1745    window.addEventListener("resize", scheduleFeaturedBannerSync);
1746
1747    if (document.readyState === "loading") {
1748      document.addEventListener("DOMContentLoaded", initFeaturedBannerArrows, {
1749        once: true,
1750      });
1751    } else {
1752      initFeaturedBannerArrows();
1753    }
1754  })();
1755</script>
1755
1756
1757<!-- Feature: Toveedo profile tweaks, community redirect, and RCP player watermark overlay. Tag: Uscreen themeless profile tab, RCP category guard, shadow DOM player watermark, turbo-safe lifecycle. -->
1758
1759<style>
1760  #profile_form .mb-5 + .mb-5 + .mb-5,
1761  form[data-test="form-customer-info"]
1762    .mb-6.flex.flex-col
1763    + div
1764    > .mb-6.flex.flex-col:nth-of-type(2) {
1765    display: none;
1766  }
1767</style>
1768
1769<script>
1770  (function () {
1771    const API_HEADERS = { headers: { Accept: "application/json" } };
1772    const PROFILE_TAB_URL = "/pages/block-videos-page";
1773    const PROFILE_TAB_LABEL = "Video Filters";
1774    const RCP_CATEGORY_LABEL = "RCP";
1775    const WATERMARK_SELECTOR = "[data-toveedo-rcp-watermark]";
1776
1777    const state = {
1778      sessionPromise: null,
1779      userPromise: null,
1780      syncFrame: 0,
1781      domObserver: null,
1782      destroyWatermark: null,
1783      watermarkSignature: "",
1784    };
1785
1786    function normalizeText(value) {
1787      return (value || "").replace(/\s+/g, " ").trim().toUpperCase();
1788    }
1789
1790    function isProgramRoute() {
1791      return /^\/programs\//.test(window.location.pathname);
1792    }
1793
1794    function isCommunityRoute() {
1795      return window.location.pathname.indexOf("/community") === 0;
1796    }
1797
1798    function scheduleSync() {
1799      if (state.syncFrame) return;
1800
1801      state.syncFrame = window.requestAnimationFrame(function () {
1802        state.syncFrame = 0;
1803        syncFeatures();
1804      });
1805    }
1806
1807    function fetchJson(url) {
1808      if (window.axios && typeof window.axios.get === "function") {
1809        return window.axios.get(url, API_HEADERS).then(function (response) {
1810          return response.data;
1811        });
1812      }
1813
1814      return window
1815        .fetch(url, {
1816          credentials: "same-origin",
1817          headers: { Accept: "application/json" },
1818        })
1819        .then(function (response) {
1820          if (!response.ok) {
1821            throw new Error("Request failed: " + response.status);
1822          }
1823
1824          return response.json();
1825        });
1826    }
1827
1828    function hasAuthenticatedSession(session) {
1829      return Boolean(
1830        session &&
1831        (session.logged_in === true ||
1832          session.loggedIn === true ||
1833          session.user ||
1834          session.current_user ||
1835          session.user_id ||
1836          session.id ||
1837          session.email),
1838      );
1839    }
1840
1841    function getSessionUserId(session) {
1842      if (!session) return "";
1843      return (
1844        session.user_id ||
1845        session.userId ||
1846        (session.user && session.user.id) ||
1847        (session.current_user && session.current_user.id) ||
1848        session.id ||
1849        ""
1850      );
1851    }
1852
1853    function getSessionEmail(session) {
1854      if (!session) return "";
1855      return (
1856        session.email ||
1857        (session.user && session.user.email) ||
1858        (session.current_user && session.current_user.email) ||
1859        ""
1860      );
1861    }
1862
1863    function getUserId(user) {
1864      if (!user) return "";
1865      return user.id || user.user_id || user.userId || "";
1866    }
1867
1868    function getUserEmail(user) {
1869      if (!user) return "";
1870      return user.email || "";
1871    }
1872
1873    function getSession() {
1874      if (!state.sessionPromise) {
1875        state.sessionPromise = fetchJson("/api/sessions").catch(function () {
1876          return null;
1877        });
1878      }
1879
1880      return state.sessionPromise;
1881    }
1882
1883    function getCurrentUser() {
1884      if (!state.userPromise) {
1885        state.userPromise = getSession()
1886          .then(function (session) {
1887            if (!hasAuthenticatedSession(session)) return null;
1888            return fetchJson("/api/users/me").catch(function () {
1889              return null;
1890            });
1891          })
1892          .catch(function () {
1893            return null;
1894          });
1895      }
1896
1897      return state.userPromise;
1898    }
1899
1900    function resetIdentityCache() {
1901      state.sessionPromise = null;
1902      state.userPromise = null;
1903    }
1904
1905    function ensureProfileTab() {
1906      if (window.location.pathname.indexOf("/account/profile") === -1) return;
1907
1908      const tablist = document.querySelector('ul[role="tablist"]');
1909      if (!tablist) return;
1910
1911      const existingTab = tablist.querySelector("[data-toveedo-profile-tab]");
1912      if (existingTab) return;
1913
1914      const tabItem = document.createElement("li");
1915      tabItem.className = "text-center";
1916      tabItem.setAttribute("role", "presentation");
1917
1918      const link = document.createElement("a");
1919      link.href = PROFILE_TAB_URL;
1920      link.textContent = PROFILE_TAB_LABEL;
1921      link.setAttribute("role", "tab");
1922      link.setAttribute("data-toveedo-profile-tab", "true");
1923      link.style.marginBottom = "-1px";
1924      link.className =
1925        "block font-medium leading-tight py-5 cursor-pointer mr-8 text-gray-500 dark:text-gray-600";
1926
1927      tabItem.appendChild(link);
1928      tablist.appendChild(tabItem);
1929    }
1930
1931    function redirectCommunityPage() {
1932      if (!isCommunityRoute()) return false;
1933
1934      window.location.replace("/catalog");
1935      return true;
1936    }
1937
1938    function getProgramPlayer() {
1939      return document.querySelector("video-player");
1940    }
1941
1942    function hasRcpCategory() {
1943      return Array.from(
1944        document.querySelectorAll(
1945          '[data-area="program-categories"] a, [data-area="program-categories"] [data-category-item]',
1946        ),
1947      ).some(function (element) {
1948        return normalizeText(element.textContent) === RCP_CATEGORY_LABEL;
1949      });
1950    }
1951
1952    function getPlayerUserId(player) {
1953      if (!player) return "";
1954
1955      return (
1956        player.getAttribute("data-user-id") ||
1957        (player.dataset && player.dataset.userId) ||
1958        ""
1959      );
1960    }
1961
1962    function getWatermarkTarget(player) {
1963      if (!player) return null;
1964      return player.shadowRoot || player;
1965    }
1966
1967    function destroyWatermark() {
1968      state.watermarkSignature = "";
1969
1970      if (typeof state.destroyWatermark === "function") {
1971        state.destroyWatermark();
1972      }
1973
1974      state.destroyWatermark = null;
1975    }
1976
1977    function createWatermark(player, label) {
1978      const target = getWatermarkTarget(player);
1979      if (!target) return null;
1980
1981      const existing = target.querySelector
1982        ? target.querySelector(WATERMARK_SELECTOR)
1983        : null;
1984      if (existing) existing.remove();
1985
1986      const overlay = document.createElement("div");
1987      overlay.setAttribute("data-toveedo-rcp-watermark", "true");
1988      overlay.style.position = "absolute";
1989      overlay.style.inset = "0";
1990      overlay.style.zIndex = "35";
1991      overlay.style.pointerEvents = "none";
1992      overlay.style.overflow = "hidden";
1993      overlay.style.userSelect = "none";
1994
1995      const badge = document.createElement("div");
1996      badge.textContent = label;
1997      badge.style.position = "absolute";
1998      badge.style.top = "0";
1999      badge.style.left = "0";
2000      badge.style.boxSizing = "border-box";
2001      badge.style.maxWidth = "min(72%, 420px)";
2002      badge.style.padding = "0";
2003      badge.style.background = "transparent";
2004      badge.style.color = "rgba(255, 255, 255, 0.14)";
2005      badge.style.fontFamily = "inherit";
2006      badge.style.fontSize = "12px";
2007      badge.style.fontWeight = "700";
2008      badge.style.lineHeight = "1.35";
2009      badge.style.letterSpacing = "0.08em";
2010      badge.style.textTransform = "uppercase";
2011      badge.style.textAlign = "center";
2012      badge.style.whiteSpace = "normal";
2013      badge.style.wordBreak = "break-word";
2014      badge.style.textShadow = "none";
2015      badge.style.backdropFilter = "none";
2016      badge.style.WebkitBackdropFilter = "none";
2017      badge.style.opacity = "1";
2018      badge.style.transform = "translate(18px, 18px)";
2019
2020      overlay.appendChild(badge);
2021
2022      const originalInlinePosition = player.style.position;
2023      const shouldResetPosition =
2024        window.getComputedStyle(player).position === "static";
2025
2026      if (shouldResetPosition) {
2027        player.style.position = "relative";
2028      }
2029
2030      target.appendChild(overlay);
2031
2032      let destroyed = false;
2033      let moveTimer = 0;
2034      let moveFrame = 0;
2035      let resizeObserver = null;
2036
2037      function moveWatermark() {
2038        if (destroyed || !overlay.isConnected) return;
2039
2040        const width = player.clientWidth;
2041        const height = player.clientHeight;
2042        if (!width || !height) return;
2043
2044        const badgeWidth = badge.offsetWidth || 180;
2045        const badgeHeight = badge.offsetHeight || 42;
2046        const marginX = Math.max(16, Math.round(width * 0.06));
2047        const marginY = Math.max(16, Math.round(height * 0.1));
2048        const bottomClearance = Math.max(56, Math.round(height * 0.16));
2049
2050        const minX = marginX;
2051        const maxX = Math.max(minX, width - badgeWidth - marginX);
2052        const minY = marginY;
2053        const maxY = Math.max(minY, height - badgeHeight - bottomClearance);
2054
2055        const x =
2056          maxX <= minX
2057            ? Math.max(0, (width - badgeWidth) / 2)
2058            : minX + Math.random() * (maxX - minX);
2059        const y =
2060          maxY <= minY
2061            ? Math.max(0, (height - badgeHeight) / 2)
2062            : minY + Math.random() * (maxY - minY);
2063
2064        badge.style.transform =
2065          "translate(" + Math.round(x) + "px, " + Math.round(y) + "px)";
2066      }
2067
2068      function scheduleMove() {
2069        if (destroyed) return;
2070        if (moveFrame) {
2071          window.cancelAnimationFrame(moveFrame);
2072        }
2073
2074        moveFrame = window.requestAnimationFrame(function () {
2075          moveFrame = 0;
2076          moveWatermark();
2077        });
2078      }
2079
2080      if ("ResizeObserver" in window) {
2081        resizeObserver = new ResizeObserver(function () {
2082          scheduleMove();
2083        });
2084        resizeObserver.observe(player);
2085      }
2086
2087      scheduleMove();
2088      moveTimer = window.setInterval(moveWatermark, 20000);
2089
2090      return function () {
2091        destroyed = true;
2092
2093        if (moveFrame) {
2094          window.cancelAnimationFrame(moveFrame);
2095          moveFrame = 0;
2096        }
2097
2098        if (moveTimer) {
2099          window.clearInterval(moveTimer);
2100          moveTimer = 0;
2101        }
2102
2103        if (resizeObserver) {
2104          resizeObserver.disconnect();
2105          resizeObserver = null;
2106        }
2107
2108        overlay.remove();
2109
2110        if (shouldResetPosition) {
2111          player.style.position = originalInlinePosition || "";
2112        }
2113      };
2114    }
2115
2116    function resolveWatermarkLabel(player) {
2117      return getSession().then(function (session) {
2118        let email = getSessionEmail(session);
2119        let userId = getPlayerUserId(player) || getSessionUserId(session);
2120
2121        const needsUserRequest = !email || !userId;
2122
2123        if (!needsUserRequest) {
2124          return [email, userId].filter(Boolean).join(" / ");
2125        }
2126
2127        return getCurrentUser().then(function (user) {
2128          email = email || getUserEmail(user);
2129          userId = userId || getUserId(user);
2130          return [email, userId].filter(Boolean).join(" / ");
2131        });
2132      });
2133    }
2134
2135    function syncWatermark() {
2136      if (!isProgramRoute()) {
2137        destroyWatermark();
2138        return Promise.resolve();
2139      }
2140
2141      const routeToken = window.location.pathname;
2142      const categories = document.querySelector(
2143        '[data-area="program-categories"]',
2144      );
2145      const player = getProgramPlayer();
2146
2147      if (!categories || !player) {
2148        destroyWatermark();
2149        return Promise.resolve();
2150      }
2151
2152      if (!hasRcpCategory()) {
2153        destroyWatermark();
2154        return Promise.resolve();
2155      }
2156
2157      return resolveWatermarkLabel(player)
2158        .then(function (label) {
2159          if (window.location.pathname !== routeToken || !player.isConnected) {
2160            return;
2161          }
2162
2163          if (!label) {
2164            destroyWatermark();
2165            return;
2166          }
2167
2168          const signature = window.location.pathname + "::" + label;
2169          const target = getWatermarkTarget(player);
2170          const existing =
2171            target && target.querySelector
2172              ? target.querySelector(WATERMARK_SELECTOR)
2173              : null;
2174
2175          if (state.watermarkSignature === signature && existing) return;
2176
2177          destroyWatermark();
2178          state.destroyWatermark = createWatermark(player, label);
2179          state.watermarkSignature = state.destroyWatermark ? signature : "";
2180        })
2181        .catch(function () {
2182          destroyWatermark();
2183        });
2184    }
2185
2186    function syncFeatures() {
2187      if (redirectCommunityPage()) return;
2188
2189      ensureProfileTab();
2190      syncWatermark();
2191    }
2192
2193    function startObserver() {
2194      if (state.domObserver || !document.documentElement) return;
2195
2196      state.domObserver = new MutationObserver(function () {
2197        scheduleSync();
2198      });
2199
2200      state.domObserver.observe(document.documentElement, {
2201        childList: true,
2202        subtree: true,
2203      });
2204    }
2205
2206    function init() {
2207      startObserver();
2208      scheduleSync();
2209
2210      let headerLogo =
2211        "https://uscreen-customizations.b-cdn.net/toveedo/home_hero_logo_e9cc7d78af.svg";
2212      let headerLogoElement = document.querySelector(
2213        "#website-header .logo-area img",
2214      );
2215      if (headerLogoElement) {
2216        headerLogoElement.src = headerLogo;
2217      }
2218    }
2219
2220    document.addEventListener("turbo:load", function () {
2221      resetIdentityCache();
2222      scheduleSync();
2223    });
2224    document.addEventListener("turbo:render", scheduleSync);
2225    document.addEventListener("turbo:frame-load", scheduleSync);
2226    window.addEventListener("pageshow", function () {
2227      resetIdentityCache();
2228      scheduleSync();
2229    });
2230    window.addEventListener("focus", function () {
2231      resetIdentityCache();
2232      scheduleSync();
2233    });
2234
2235    if (document.readyState === "loading") {
2236      document.addEventListener("DOMContentLoaded", init, { once: true });
2237    } else {
2238      init();
2239    }
2240  })();
2241</script>
2241
2242<!-- Feature: Toveedo parental controls. Tag: field_3 hiding, test-user gate, family profile chooser, first-run setup, checkout PIN gate. -->
2243
2244<style>
2245  ds-input[name="form[field_3]"],
2246  ds-input#form_field_3,
2247  input[name="form[field_3]"],
2248  textarea[name="form[field_3]"],
2249  select[name="form[field_3]"],
2250  [name="user[field_3]"],
2251  #form_field_3,
2252  #user_field_3,
2253  [for="form_field_3"],
2254  [for="user_field_3"],
2255  .toveedo-parental-field-hidden,
2256  [data-toveedo-parental-hidden="1"] {
2257    display: none !important;
2258  }
2259
2260  .toveedo-pc-backdrop {
2261    position: fixed;
2262    inset: 0;
2263    z-index: 2147483000;
2264    display: flex;
2265    align-items: center;
2266    justify-content: center;
2267    padding: 24px;
2268    background: rgba(2, 6, 23, 0.78);
2269    backdrop-filter: blur(10px);
2270  }
2271
2272  .toveedo-pc-modal {
2273    width: min(790px, 100%);
2274    max-height: min(86vh, 780px);
2275    overflow: auto;
2276    border: 1px solid rgba(148, 163, 184, 0.32);
2277    border-radius: 14px;
2278    background: #070c18;
2279    color: #f8fafc;
2280    box-shadow: 0 24px 80px rgba(0, 0, 0, 0.4);
2281  }
2282
2283  .toveedo-pc-modal--setup {
2284    width: min(620px, 100%);
2285  }
2286
2287  .toveedo-pc-modal--pin {
2288    width: min(620px, 100%);
2289  }
2290
2291  .toveedo-pc-modal--blocked {
2292    width: min(620px, 100%);
2293  }
2294
2295  .toveedo-pc-modal--blocked .toveedo-pc-modal__body {
2296    justify-items: center;
2297    text-align: center;
2298  }
2299
2300  .toveedo-pc-modal--blocked .toveedo-pc-actions {
2301    justify-content: center;
2302  }
2303
2304  .toveedo-pc-modal__body {
2305    padding: 36px;
2306  }
2307
2308  .toveedo-pc-modal h2,
2309  .toveedo-pc-modal h3,
2310  .toveedo-pc-modal p {
2311    margin: 0;
2312  }
2313
2314  .toveedo-pc-modal h2 {
2315    font-size: 30px;
2316    line-height: 1.15;
2317    letter-spacing: 0;
2318    text-align: center;
2319  }
2320
2321  .toveedo-pc-modal p {
2322    color: #aab7ca;
2323    line-height: 1.5;
2324  }
2325
2326  .toveedo-pc-stack {
2327    display: grid;
2328    gap: 18px;
2329  }
2330
2331  .toveedo-pc-profile-grid {
2332    display: grid;
2333    grid-template-columns: repeat(3, minmax(120px, 1fr));
2334    gap: 24px 34px;
2335    max-width: 650px;
2336    margin: 0 auto;
2337  }
2338
2339  .toveedo-pc-manage-list {
2340    display: grid;
2341    gap: 12px;
2342  }
2343
2344  .toveedo-pc-manage-row {
2345    display: flex;
2346    align-items: center;
2347    gap: 14px;
2348    padding: 12px;
2349    border: 1px solid rgba(148, 163, 184, 0.24);
2350    border-radius: 12px;
2351    background: rgba(15, 23, 42, 0.72);
2352  }
2353
2354  .toveedo-pc-manage-row__body {
2355    min-width: 0;
2356    flex: 1;
2357  }
2358
2359  .toveedo-pc-manage-row strong {
2360    display: block;
2361    color: #ffffff;
2362    font-size: 16px;
2363  }
2364
2365  .toveedo-pc-section {
2366    display: grid;
2367    gap: 14px;
2368    padding: 18px;
2369    border: 1px solid rgba(148, 163, 184, 0.24);
2370    border-radius: 12px;
2371    background: rgba(15, 23, 42, 0.58);
2372  }
2373
2374  .toveedo-pc-section h3 {
2375    margin: 0;
2376    color: #ffffff;
2377    font-size: 20px;
2378    line-height: 1.2;
2379  }
2380
2381  .toveedo-pc-section-grid {
2382    display: grid;
2383    grid-template-columns: repeat(2, minmax(0, 1fr));
2384    gap: 12px;
2385  }
2386
2387  .toveedo-pc-section--restrictions {
2388    gap: 18px;
2389  }
2390
2391  .toveedo-pc-section--restrictions > h3 {
2392    font-size: 24px;
2393  }
2394
2395  .toveedo-pc-restriction-card {
2396    display: grid;
2397    gap: 14px;
2398    padding: 16px;
2399    border: 1px solid rgba(148, 163, 184, 0.22);
2400    border-radius: 12px;
2401    background: linear-gradient(
2402      180deg,
2403      rgba(15, 23, 42, 0.82),
2404      rgba(8, 13, 26, 0.72)
2405    );
2406  }
2407
2408  .toveedo-pc-restriction-card__head {
2409    display: flex;
2410    align-items: center;
2411    justify-content: space-between;
2412    gap: 12px;
2413  }
2414
2415  .toveedo-pc-restriction-card h4 {
2416    margin: 0;
2417    color: #ffffff;
2418    font-size: 19px;
2419    line-height: 1.2;
2420  }
2421
2422  .toveedo-pc-restriction-count {
2423    display: inline-flex;
2424    align-items: center;
2425    justify-content: center;
2426    min-width: 34px;
2427    min-height: 28px;
2428    padding: 0 10px;
2429    border-radius: 999px;
2430    background: rgba(56, 189, 248, 0.14);
2431    color: #7dd3fc;
2432    font-size: 12px;
2433    font-weight: 900;
2434  }
2435
2436  .toveedo-pc-filter-grid {
2437    display: grid;
2438    grid-template-columns: repeat(2, minmax(0, 1fr));
2439    gap: 10px 14px;
2440  }
2441
2442  .toveedo-pc-filter-grid--single {
2443    grid-template-columns: 1fr;
2444  }
2445
2446  .toveedo-pc-filter-row {
2447    appearance: none;
2448    display: flex;
2449    width: 100%;
2450    min-height: 58px;
2451    align-items: center;
2452    gap: 12px;
2453    padding: 10px 12px;
2454    border: 1px solid transparent;
2455    border-radius: 10px;
2456    background: rgba(15, 23, 42, 0.54);
2457    color: #f8fafc;
2458    cursor: pointer;
2459    font: inherit;
2460    text-align: left;
2461    transition:
2462      border-color 160ms ease,
2463      background-color 160ms ease,
2464      transform 160ms ease;
2465  }
2466
2467  .toveedo-pc-filter-row:hover,
2468  .toveedo-pc-filter-row:focus-visible {
2469    border-color: rgba(56, 189, 248, 0.34);
2470    outline: none;
2471    transform: translateY(-1px);
2472  }
2473
2474  .toveedo-pc-filter-row.is-blocked {
2475    border-color: rgba(244, 63, 94, 0.32);
2476    background: rgba(127, 29, 29, 0.28);
2477  }
2478
2479  .toveedo-pc-filter-icon {
2480    display: grid;
2481    width: 34px;
2482    height: 34px;
2483    flex: none;
2484    place-items: center;
2485    border-radius: 9px;
2486    background: #38bdf8;
2487    color: #06121f;
2488    font-size: 12px;
2489    font-weight: 900;
2490    letter-spacing: 0;
2491  }
2492
2493  .toveedo-pc-filter-row.is-blocked .toveedo-pc-filter-icon {
2494    background: #fb7185;
2495    color: #190b12;
2496  }
2497
2498  .toveedo-pc-filter-name {
2499    min-width: 0;
2500    flex: 1;
2501    overflow: hidden;
2502    color: #ffffff;
2503    font-weight: 800;
2504    text-overflow: ellipsis;
2505    white-space: nowrap;
2506  }
2507
2508  .toveedo-pc-rule-status {
2509    display: inline-flex;
2510    min-width: 70px;
2511    min-height: 30px;
2512    align-items: center;
2513    justify-content: center;
2514    border-radius: 999px;
2515    background: rgba(34, 197, 94, 0.14);
2516    color: #bbf7d0;
2517    font-size: 12px;
2518    font-weight: 900;
2519  }
2520
2521  .toveedo-pc-filter-row.is-blocked .toveedo-pc-rule-status {
2522    background: rgba(251, 113, 133, 0.16);
2523    color: #fecdd3;
2524  }
2525
2526  .toveedo-pc-video-combobox {
2527    position: relative;
2528    display: grid;
2529    gap: 10px;
2530  }
2531
2532  .toveedo-pc-video-search {
2533    padding-right: 42px;
2534  }
2535
2536  .toveedo-pc-video-results {
2537    position: absolute;
2538    top: calc(100% + 8px);
2539    left: 0;
2540    right: 0;
2541    z-index: 12;
2542    display: grid;
2543    max-height: 312px;
2544    gap: 6px;
2545    overflow: auto;
2546    padding: 8px;
2547    border: 1px solid rgba(148, 163, 184, 0.28);
2548    border-radius: 12px;
2549    background: #050b16;
2550    box-shadow: 0 20px 42px rgba(0, 0, 0, 0.38);
2551  }
2552
2553  .toveedo-pc-video-results[hidden] {
2554    display: none !important;
2555  }
2556
2557  .toveedo-pc-video-selected {
2558    display: grid;
2559    max-height: 230px;
2560    gap: 8px;
2561    overflow: auto;
2562    padding-right: 4px;
2563  }
2564
2565  .toveedo-pc-filter-empty {
2566    padding: 12px 2px;
2567    color: #91a2bb;
2568    font-size: 13px;
2569    font-weight: 700;
2570  }
2571
2572  .toveedo-pc-hidden-rules {
2573    display: none !important;
2574  }
2575
2576  .toveedo-pc-profile-card {
2577    min-height: 134px;
2578    border: 1px solid transparent;
2579    border-radius: 12px;
2580    background: transparent;
2581    color: inherit;
2582    cursor: pointer;
2583    text-align: center;
2584    display: grid;
2585    justify-items: center;
2586    align-content: start;
2587    padding: 8px;
2588    transition: transform 160ms ease;
2589  }
2590
2591  .toveedo-pc-profile-card:hover,
2592  .toveedo-pc-profile-card:focus-visible {
2593    outline: none;
2594    transform: translateY(-1px);
2595  }
2596
2597  .toveedo-pc-profile-card:hover .toveedo-pc-avatar,
2598  .toveedo-pc-profile-card:focus-visible .toveedo-pc-avatar {
2599    border-color: #38bdf8;
2600    box-shadow: 0 0 0 4px rgba(56, 189, 248, 0.16);
2601  }
2602
2603  .toveedo-pc-profile-card--add .toveedo-pc-avatar {
2604    border: 2px dashed rgba(148, 163, 184, 0.42);
2605    background: transparent;
2606    color: #cbd5e1;
2607    font-size: 38px;
2608  }
2609
2610  .toveedo-pc-avatar {
2611    display: grid;
2612    width: 74px;
2613    height: 74px;
2614    place-items: center;
2615    margin: 0 auto 12px;
2616    border: 2px solid transparent;
2617    border-radius: 14px;
2618    background: #18243a;
2619    font-size: 30px;
2620    font-weight: 900;
2621    line-height: 1;
2622    box-sizing: border-box;
2623    transition: border-color 160ms ease, box-shadow 160ms ease, transform 160ms ease;
2624  }
2625
2626  .toveedo-pc-profile-card strong {
2627    display: block;
2628    color: #ffffff;
2629    font-size: 15px;
2630  }
2631
2632  .toveedo-pc-profile-meta {
2633    display: block;
2634    margin-top: 4px;
2635    color: #91a2bb;
2636    font-size: 12px;
2637  }
2638
2639  .toveedo-pc-actions {
2640    display: flex;
2641    flex-wrap: wrap;
2642    gap: 10px;
2643    align-items: center;
2644  }
2645
2646  .toveedo-pc-actions--stack {
2647    flex-direction: column;
2648    justify-content: center;
2649  }
2650
2651  .toveedo-pc-button {
2652    display: inline-flex;
2653    align-items: center;
2654    justify-content: center;
2655    min-height: 44px;
2656    padding: 0 18px;
2657    border: 1px solid rgba(148, 163, 184, 0.26);
2658    border-radius: 10px;
2659    background: #101a2d;
2660    color: #f8fafc;
2661    cursor: pointer;
2662    font: inherit;
2663    font-weight: 700;
2664    text-decoration: none;
2665  }
2666
2667  .toveedo-pc-close {
2668    position: absolute;
2669    top: 16px;
2670    right: 18px;
2671    width: 38px;
2672    height: 38px;
2673    border: 0;
2674    background: transparent;
2675    color: #cbd5e1;
2676    cursor: pointer;
2677    font: inherit;
2678    font-size: 30px;
2679    line-height: 1;
2680  }
2681
2682  .toveedo-pc-form-grid {
2683    display: grid;
2684    grid-template-columns: repeat(2, minmax(0, 1fr));
2685    gap: 12px;
2686  }
2687
2688  .toveedo-pc-setup-grid {
2689    display: grid;
2690    grid-template-columns: 1fr;
2691    gap: 18px;
2692    width: min(520px, 100%);
2693    margin: 0 auto;
2694  }
2695
2696  .toveedo-pc-field {
2697    display: grid;
2698    gap: 6px;
2699  }
2700
2701  .toveedo-pc-field span {
2702    color: #aab7ca;
2703    font-size: 13px;
2704    font-weight: 700;
2705  }
2706
2707  .toveedo-pc-select {
2708    width: 100%;
2709    min-height: 46px;
2710    box-sizing: border-box;
2711    border: 1px solid rgba(148, 163, 184, 0.28);
2712    border-radius: 10px;
2713    background: #050b16;
2714    color: #f8fafc;
2715    font: inherit;
2716    padding: 0 14px;
2717  }
2718
2719  .toveedo-pc-pin-avatar {
2720    display: grid;
2721    width: 72px;
2722    height: 72px;
2723    place-items: center;
2724    justify-self: center;
2725    border-radius: 16px;
2726    background: #18243a;
2727    color: #f8fafc;
2728    font-size: 30px;
2729    font-weight: 900;
2730    line-height: 1;
2731  }
2732
2733  .toveedo-pc-pin-field {
2734    justify-items: center;
2735  }
2736
2737  .toveedo-pc-setup-grid .toveedo-pc-pin-field {
2738    justify-items: stretch;
2739  }
2740
2741  .toveedo-pc-setup-grid .toveedo-pc-pin-grid {
2742    width: 100%;
2743    grid-template-columns: repeat(4, minmax(0, 1fr));
2744  }
2745
2746  .toveedo-pc-setup-grid .toveedo-pc-pin-digit {
2747    width: 100%;
2748  }
2749
2750  .toveedo-pc-sr-only {
2751    position: absolute;
2752    width: 1px;
2753    height: 1px;
2754    padding: 0;
2755    margin: -1px;
2756    overflow: hidden;
2757    clip: rect(0, 0, 0, 0);
2758    white-space: nowrap;
2759    border: 0;
2760  }
2761
2762  .toveedo-pc-pin-grid {
2763    display: grid;
2764    grid-template-columns: repeat(4, 58px);
2765    overflow: hidden;
2766    border: 1px solid rgba(148, 163, 184, 0.3);
2767    border-radius: 12px;
2768    background: #050b16;
2769  }
2770
2771  .toveedo-pc-pin-digit {
2772    width: 58px;
2773    height: 58px;
2774    box-sizing: border-box;
2775    border: 0;
2776    border-left: 1px solid rgba(148, 163, 184, 0.24);
2777    background: transparent;
2778    color: #f8fafc;
2779    font: inherit;
2780    font-size: 24px;
2781    font-weight: 800;
2782    line-height: 1;
2783    text-align: center;
2784  }
2785
2786  .toveedo-pc-pin-digit:first-child {
2787    border-left: 0;
2788  }
2789
2790  .toveedo-pc-pin-digit:focus {
2791    outline: 2px solid #38bdf8;
2792    outline-offset: -2px;
2793    background: rgba(56, 189, 248, 0.08);
2794  }
2795
2796  .toveedo-pc-button--primary {
2797    border-color: transparent;
2798    background: #38bdf8;
2799    color: #06121f;
2800  }
2801
2802  .toveedo-pc-button--unlock {
2803    width: min(390px, 100%);
2804    border-color: transparent;
2805    background: linear-gradient(90deg, #38bdf8 0%, #a855f7 100%);
2806    color: #06121f;
2807  }
2808
2809  .toveedo-pc-button--ghost {
2810    background: transparent;
2811  }
2812
2813  .toveedo-pc-link {
2814    display: inline-flex;
2815    align-items: center;
2816    justify-content: center;
2817    border: 0;
2818    background: transparent;
2819    color: #cbd5e1;
2820    cursor: pointer;
2821    font: inherit;
2822    font-weight: 700;
2823    line-height: 1.35;
2824    text-decoration: none;
2825  }
2826
2827  .toveedo-pc-link--row {
2828    flex-basis: 100%;
2829  }
2830
2831  .toveedo-pc-actions--stack .toveedo-pc-link--row {
2832    flex-basis: auto;
2833  }
2834
2835  .toveedo-pc-link:hover,
2836  .toveedo-pc-link:focus-visible {
2837    color: #ffffff;
2838    text-decoration: underline;
2839    text-underline-offset: 3px;
2840    outline: none;
2841  }
2842
2843  .toveedo-pc-button--danger {
2844    border-color: rgba(251, 113, 133, 0.42);
2845    background: rgba(127, 29, 29, 0.22);
2846    color: #fecdd3;
2847  }
2848
2849  .toveedo-pc-input {
2850    width: 100%;
2851    min-height: 46px;
2852    box-sizing: border-box;
2853    border: 1px solid rgba(148, 163, 184, 0.28);
2854    border-radius: 10px;
2855    background: #050b16;
2856    color: #f8fafc;
2857    font: inherit;
2858    padding: 0 14px;
2859  }
2860
2861  .toveedo-pc-textarea {
2862    min-height: 92px;
2863    padding: 12px 14px;
2864    resize: vertical;
2865  }
2866
2867  .toveedo-pc-checkbox {
2868    display: flex;
2869    align-items: center;
2870    gap: 10px;
2871    color: #f8fafc;
2872    font-weight: 800;
2873  }
2874
2875  .toveedo-pc-checkbox input {
2876    width: 18px;
2877    height: 18px;
2878    accent-color: #38bdf8;
2879  }
2880
2881  .toveedo-pc-error {
2882    display: none;
2883    color: #fb7185;
2884    font-weight: 700;
2885  }
2886
2887  .toveedo-pc-error.is-visible {
2888    display: block;
2889  }
2890
2891  .toveedo-pc-switcher {
2892    position: relative;
2893    z-index: 2147482500;
2894    display: inline-flex;
2895    align-items: center;
2896    gap: 8px;
2897    min-height: 38px;
2898    max-width: 230px;
2899    border: 1px solid rgba(148, 163, 184, 0.26);
2900    border-radius: 999px;
2901    background: rgba(8, 17, 31, 0.9);
2902    color: #f8fafc;
2903    cursor: pointer;
2904    font: inherit;
2905    font-weight: 800;
2906    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.22);
2907    padding: 6px 12px 6px 7px;
2908    margin-left: 12px;
2909    flex: none;
2910    pointer-events: auto;
2911  }
2912
2913  .toveedo-pc-switcher::before {
2914    content: "";
2915    position: absolute;
2916    inset: -8px;
2917    border-radius: inherit;
2918  }
2919
2920  .toveedo-pc-switcher > * {
2921    pointer-events: none;
2922  }
2923
2924  .toveedo-pc-trigger-avatar {
2925    display: grid;
2926    width: 26px;
2927    height: 26px;
2928    place-items: center;
2929    border-radius: 999px;
2930    background: #38bdf8;
2931    color: #06121f;
2932    font-size: 13px;
2933    font-weight: 900;
2934  }
2935
2936  .toveedo-pc-trigger-name {
2937    overflow: hidden;
2938    text-overflow: ellipsis;
2939    white-space: nowrap;
2940  }
2941
2942  @media (max-width: 640px) {
2943    .toveedo-pc-backdrop {
2944      align-items: stretch;
2945      padding: 12px;
2946    }
2947
2948    .toveedo-pc-modal {
2949      max-height: calc(100vh - 24px);
2950    }
2951
2952    .toveedo-pc-modal__body {
2953      padding: 22px;
2954    }
2955
2956    .toveedo-pc-form-grid {
2957      grid-template-columns: 1fr;
2958    }
2959
2960    .toveedo-pc-section-grid {
2961      grid-template-columns: 1fr;
2962    }
2963
2964    .toveedo-pc-filter-grid {
2965      grid-template-columns: 1fr;
2966    }
2967
2968    .toveedo-pc-filter-row {
2969      min-height: 54px;
2970    }
2971
2972    .toveedo-pc-rule-status {
2973      min-width: 62px;
2974    }
2975
2976    .toveedo-pc-manage-row {
2977      align-items: flex-start;
2978      flex-direction: column;
2979    }
2980
2981    .toveedo-pc-setup-grid {
2982      grid-template-columns: 1fr;
2983    }
2984
2985    .toveedo-pc-trigger-name {
2986      display: none;
2987    }
2988
2989    .toveedo-pc-profile-grid {
2990      grid-template-columns: repeat(2, minmax(110px, 1fr));
2991      gap: 18px;
2992    }
2993
2994    .toveedo-pc-pin-grid {
2995      grid-template-columns: repeat(4, minmax(44px, 56px));
2996    }
2997
2998    .toveedo-pc-pin-digit {
2999      width: 100%;
3000    }
3001  }
3002</style>
3003
3004<script>
3005  (function () {
3006    var TEST_USER_EMAIL = "[email protected]";
3007    var FIELD_KEY = "field_3";
3008    var FORM_FIELD_NAME = "form[field_3]";
3009    var LEGACY_STORAGE_PREFIX = "toveedo_parental_";
3010    var ACTIVE_PROFILE_STORAGE_KEY = "toveedo_pc_active_profile_v1";
3011    var ACCOUNT_CACHE_STORAGE_KEY = "toveedo_pc_account_cache_v1:";
3012    var ACCOUNT_CACHE_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
3013    var CATALOG_MANIFEST_ENDPOINT =
3014      "https://home.toveedo.com/api/parental-control/catalog-manifest";
3015    var CATALOG_MANIFEST_CACHE_KEY = "toveedo_pc_catalog_manifest_v1";
3016    var CATALOG_MANIFEST_CACHE_MAX_AGE_MS = 24 * 60 * 60 * 1000;
3017    var CATALOG_MANIFEST_REVALIDATE_INTERVAL_MS = 5 * 60 * 1000;
3018    var BLOCKED_CATEGORY_STYLE_ID = "toveedo-pc-blocked-category-styles";
3019    var MODAL_ID = "toveedo-parental-control-modal";
3020    var SWITCHER_ID = "toveedo-parental-profile-switcher";
3021    var SCHEMA_VERSION = 1;
3022
3023    var state = {
3024      syncFrame: 0,
3025      sessionPromise: null,
3026      userPromise: null,
3027      contentPromises: {},
3028      observer: null,
3029      timeTicker: null,
3030      timeProfileId: "",
3031      lastUsageTickAt: 0,
3032      switcherAccount: null,
3033      switcherEmail: "",
3034      activeSelection: { email: "", profileId: "" },
3035      catalogManifest: null,
3036      catalogManifestPromise: null,
3037      catalogManifestLastFetchedAt: 0,
3038      catalogConfirmations: {},
3039      purchaseUnlocks: {},
3040      usageSeconds: {}
3041    };
3042
3043    var AGE_FILTERS = [
3044      { value: "all", minAge: 0 },
3045      { value: "1-5", minAge: 5 },
3046      { value: "3-6", minAge: 6 },
3047      { value: "6+", minAge: 6 },
3048      { value: "9+", minAge: 9 },
3049      { value: "12+", minAge: 12 }
3050    ];
3051
3052    // Replace this static manifest with the custom DB payload when the endpoint is ready.
3053    var PARENTAL_CATALOG_MANIFEST = {
3054      channels: [
3055        {
3056          id: "toveedo",
3057          label: "Toveedo",
3058          icon: "TV",
3059          videos: [
3060            { id: "welcome-to-toveedo", title: "Welcome to Toveedo" },
3061            { id: "toveedo-clubhouse", title: "Toveedo Clubhouse" },
3062            { id: "toveedo-remix", title: "Toveedo Remix" },
3063            { id: "toveedo-tablet", title: "Toveedo Tablet" }
3064          ]
3065        },
3066        {
3067          id: "chofetz-chaim",
3068          label: "Chofetz Chaim",
3069          icon: "CC",
3070          videos: [
3071            { id: "1001-voices", title: "1001 Voices" },
3072            { id: "agent-chesed", title: "Agent Chesed" },
3073            { id: "a-tree-full-of-mitzvos", title: "A Tree Full of Mitzvos - Story Time" }
3074          ]
3075        },
3076        {
3077          id: "torah-live",
3078          label: "Torah Live",
3079          icon: "TL",
3080          videos: [
3081            { id: "ahavas-hashem", title: "Ahavas Hashem - Torah Live" },
3082            { id: "asher-yaatzar", title: "Asher Yaatzar - Torah Live" },
3083            { id: "bishul-akum", title: "Bishul Akum - Torah Live" },
3084            { id: "learning-torah", title: "Learning Torah - Torah Live" }
3085          ]
3086        },
3087        {
3088          id: "chabad-kids",
3089          label: "Chabad.org/kids",
3090          icon: "CK",
3091          videos: [
3092            { id: "captain-sinai-pilot", title: "Captain Sinai Ep. 1 - Pilot" },
3093            { id: "captain-sinai-fly-away", title: "Captain Sinai Ep. 2 - Fly Away" },
3094            { id: "captain-sinai-trailer", title: "Captain Sinai - Trailer" }
3095          ]
3096        },
3097        {
3098          id: "malkali",
3099          label: "Malkali",
3100          icon: "MK",
3101          videos: [
3102            { id: "a-brivala", title: "A Brivala - Yiddish" },
3103            { id: "a-minute-tzi-shpet", title: "A Minute Tzi Shpet - Yiddish" },
3104            { id: "chodesh-nisson", title: "Chodesh Nisson In Terkvitz - Yiddish" }
3105          ]
3106        },
3107        {
3108          id: "meir-kids",
3109          label: "Meir Kids",
3110          icon: "ME",
3111          videos: [
3112            { id: "kivi-tuki-adventures", title: "Kivi & Tuki - Adventures Begin" },
3113            { id: "kivi-tuki-good-middos", title: "Kivi & Tuki - Good Middos" },
3114            { id: "derech-emunah", title: "Derech Emunah - Meir Green #TYH" }
3115          ]
3116        },
3117        {
3118          id: "shazak",
3119          label: "SHAZAK",
3120          icon: "SZ",
3121          videos: [
3122            { id: "boruch-learns-pesach", title: "Boruch learns about Pesac
3122h - Kunda" },
3123            { id: "boruch-learns-shabbos", title: "Boruch learns about Shabbos - kunda" },
3124            { id: "mitzvah-boulevard-aleph-beis", title: "Mitzvah Boulevard - Aleph Beis (Final)" }
3125          ]
3126        },
3127        {
3128          id: "hidabroot",
3129          label: "Hidabroot",
3130          icon: "HD",
3131          videos: [
3132            { id: "fish-explain-tashlich", title: "Fish explain Tashlich" },
3133            { id: "judges-judgement", title: "Judges & Judgement" },
3134            { id: "prophecies-revealed", title: "Prophecies Revealed - Torah Live" }
3135          ]
3136        },
3137        {
3138          id: "shezoli",
3139          label: "Shezoli",
3140          icon: "SH",
3141          videos: [
3142            { id: "lets-draw", title: "Let's Draw" },
3143            { id: "flower-vase-art", title: "Flower Vase Art" },
3144            { id: "fun-decorations", title: "Fun Decorations" }
3145          ]
3146        },
3147        {
3148          id: "beis-rivkah",
3149          label: "Beis Rivkah",
3150          icon: "BR",
3151          videos: [
3152            { id: "camp-bnos-yisrael-trailer", title: "Camp Bnos Yisrael #1 Trailer" },
3153            { id: "camp-bnos-yisrael-together", title: "Camp Bnos Yisrael - Together As One" },
3154            { id: "bat-mitzvah-girl", title: "Bat Mitzvah Girl - Esther Press" }
3155          ]
3156        },
3157        {
3158          id: "jem",
3159          label: "JEM",
3160          icon: "JM",
3161          videos: [
3162            { id: "the-beis-hamikdash", title: "The Beis Hamikdash - Sara Blau" },
3163            { id: "sefer-torah", title: "Sefer Torah - Torah Live" },
3164            { id: "yerushalayim", title: "Yerushalayim - Torah Live" }
3165          ]
3166        }
3167      ],
3168      categories: [
3169        { id: "education", label: "Education" },
3170        { id: "torah-study", label: "Torah Study" },
3171        { id: "music", label: "Music" },
3172        { id: "family", label: "Family" },
3173        { id: "lectures", label: "Lectures" },
3174        { id: "documentaries", label: "Documentaries" },
3175        { id: "kids-content", label: "Kids Content" }
3176      ]
3177    };
3178
3179    var PARENTAL_VIDEO_TITLES = [
3180   "Micha Gamerman - Yomim Noraim",
3181    "Micha Gamerman - Sukkos",
3182    "Micha Gamerman - Shavuos",
3183    "Micha Gamerman - Chanukah Medley",
3184    "Micha Gamerman - Purim",
3185    "Micha Gamerman - Pesach",
3186    "Dudi Knopfler – Ki B’simcha",
3187    "Ari Goldwag - Hashem Loves You",
3188    "Ari Goldwag - Shir Ushvacha - ft. Sheves Chaverim",
3189    "Ari Goldwag - Chanukah Lights",
3190    "Ari Goldwag - Am Echad",
3191    "Ari Goldwag - Today is the Day",
3192    "Ari Goldwag - Lo Nafsik Lirkod",
3193    "Agent Emes #1 - The Fish Head",
3194    "Agent Emes #5 - and the Happy Chanukah",
3195    "Agent Emes #7 - Hard to Forget Pt. 2",
3196    "Agent Emes #6 - Hard to Forget Pt. 1",
3197    "Agent Emes #10 - vs. The Karrupter",
3198    "Dudi Knopfler – Soreiku",
3199    "coming - bonus",
3200    "Bella Brocha goes to a Wedding - (For boys)",
3201    "Trailer_2.mp4",
3202    "Bella Brocha & The Talent Show - (For boys)",
3203    "Bella Brocha goes to a Wedding  - with Kol Isha",
3204    "Trailer2.mp4",
3205    "Bella Brocha & The Talent Show - with Kol Isha",
3206    "babyshark.mp4 - 192057",
3207    "Michoel Pruzansky - Shootin’ For The Moon",
3208    "Micha Gamerman - Rabim",
3209    "YBC - Yivonim - no volume",
3210    "Uncle Moishy & the Mitzvah Men! #8",
3211    "Welcome to Toveedo (Original)",
3212    "On a Roll - Finger Puppets",
3213    "Bella Brocha and The Twins - with Kol Isha",
3214    "Tricks - Can Grenade",
3215    "Toveedo - 4",
3216    "Toveedo - 2",
3217    "Toveedo - 3",
3218    "Toveedo - 1",
3219    "Dovid Pearlman - We Can't Thank You Enough",
3220    "COMING SOON: Kivi & Tuki - Trailer",
3221    "Ari Goldwag - Zeh Keili",
3222    "Ari Goldwag - For the Light",
3223    "Ari Goldwag - Ashira LaHashem",
3224    "Ari Goldwag - Smile",
3225    "Ari Goldwag- Ahalela",
3226    "Ari Goldwag - Rak Hu",
3227    "Ari Goldwag - Hafachta",
3228    "Yoey Muchnik - Light Light Light",
3229    "6 Hour Play",
3230    "Play All - Torah Town",
3231    "“I Believe in Me” (kol isha)",
3232    "Rogers Park - No Place Like Home",
3233    "Mimmy & Simmy - Sharing a Sunshine Umbrella (for women and girls)",
3234    "Eli Scheller - Mashtuka",
3235    "Eli Scheller - Just Be B'Simcha",
3236    "Shmueli Ungar - Halailah Hazeh",
3237    "Uri Davidi- Echad Ani Yodea",
3238    "Rogers Park - My Friendship Circle",
3239    "Rogers Park - Yaaleh",
3240    "Fräulein",
3241    "Benny Friedman - Hold On Tight - ft. Baruch Levine",
3242    "Interin Bild - Yiddish",
3243    "Interin Shpiel - Yiddish",
3244    "Thankful - Talent Unite",
3245    "The Shepselach - Dress Up Contest",
3246    "Dr. Wildshaar - Gragger",
3247    "The Shepselach - Good Night Shepselach",
3248    "Dr. Wildshaar - Pesach",
3249    "The Kumzits - Chanale",
3250    "Yossi & Leah’s Ranch - Horse Prepping",
3251    "The Runaways (9th of Av only)",
3252    "Team Teretz #3 - Premiering on Tuesday 9AM iy”h",
3253    "Rabbi B - Mezuzah",
3254    "Yaakov Shwekey - Baruch Hashem It’S Shabbos",
3255    "Team Teretz #4 - Trailer",
3256    "Living Lessons - Masmedei Hasiyum",
3257    "Living Lessons - Hashgacha Pratis",
3258    "Living Lessons - Chessed",
3259    "Living Lessons - Pesach",
3260    "Living Lessons - Mesiras Nefesh",
3261    "Living Lessons - Shabbos",
3262    "Living Lessons - Rosh Hashana",
3263    "Tomp3.Cc - מנדי פיאמנטה  כוחות Mendy Piamenta  Kochot_1080p",
3264    "World of Wonder- Farm Animals",
3265    "Toveedo By Kids - ROUND 2",
3266    "Where is Gayil? - CGC",
3267    "Vikar - Franciska ft. Maayan Davis",
3268    "Maoz Tzur - Franciska ft. Maayan Davis",
3269    "Yoey Muchnik - Adeh Adeh",
3270    "Benny Friedman - Rebbi It's All From You",
3271    "Mendy Piamenta - Kochot",
3272    "Dovid Pearlman - Greatest Gift",
3273    "Rogers Park - Tumb",
3274    "Shmueli Ungar - Yiten Lecha",
3275    "8th Day - Shliach  #TYH",
3276    "B'korov Mamash - Avraham Fried #TYH",
3277    "Trailer - Elegant Ella - Snow Much Fun",
3278    "Punchkees - Rambam",
3279    "Punchkees - Yaakov's Dream",
3280    "Punchkees - Secret Signs",
3281    "The Nochum Show Feat. Chaim & Tzvi",
3282    "Punchkees - 17 Tammuz",
3283    "Punchkees - Korach",
3284    "Dr. Shnitzel - Trailer",
3285    "Pisom - Trailer",
3286    "CGC 2 - Trailer (old",
3287    "Mish and Mush Trailer",
3288    "Mr. Hossenfepher - Mission Possible - Trailer",
3289    "Torah Tots Promo Video",
3290    "Where Did All These Leaves Come From - Mish & Mush",
3291    "Let's All Run - Mish & Mush - Sefardi",
3292    "Shalom - Torah Live",
3293    "Kippah - Torah Live",
3294    "Jewish Revenge 6 old",
3295    "New Live Stream",
3296    "Tantz It - Advanced",
3297    "Chaptzem - Purim Pirates - pt.1",
3298    "Sheyafutzu - Naftali Kempeh #TYH",
3299    "Avi Ilson - Eretz Israel",
3300    "Joey Newcomb - One Note Niggun",
3301    "Uri Davidi - The Connection Is You",
3302    "Untied - Trailer: Coming Motzoi Shabbos",
3303    "The Secret Room - Neteilas Yadayim",
3304    "Flower Pops",
3305    "Chaptzem - Purim Pirates - pt. 2",
3306    "Twists and Tales - Racheli's First Day",
3307    "The Shepselach - Savta Liba-a-a Comes to Visit",
3308    "Avrohom Leffler",
3309    "Sputz Kids",
3310    "Esti",
3311    "Yaakov",
3312    "Rivkin Kids",
3313    "Meira Gross",
3314    "Alone Family",
3315    "Bilvavi - Elena Tal",
3316    "Unity -  Shaindy Plotzker",
3317    "Dr Shnitzel - Solar Energy #2",
3318    "Word Power - \"Enjoy\"",
3319    "The Attic - Trailer",
3320    "Mimmy & Simmy 2 - The Grass Isn't Greener (for women and girls)",
3321    "ESL - Week 2",
3322    "ESL - Week 6",
3323    "ESL - Week 4",
3324    "ESL - Week 1",
3325    "ESL - Week 3",
3326    "ESL - Week 5",
3327    "Word Power - \"Derech Eretz\"",
3328    "Finish Line #TYH Boys",
3329    "8th Day - Get It Done! Ft. Tzvi Silberstein",
3330    "Ari Goldwag - Yisroel Love Prayer - Ft. Refael Klein",
3331    "Tour Benny Friemdan - London",
3332    "Dovid Pearlman - Nachamu - Acapella",
3333    "Dovid Lowy- Don'T Hide From Me (Acoustic Cover)",
3334    "Dovid Lowy - Yom Yom",
3335    "Dudi Knopfler - Ain Od Milvado -  ft. Shira Choir",
3336    "Eli Scheller - Kol Hamelamed",
3337    "Joey Newcomb - Freilach All The Time - ft. Benny Friedman",
3338    "Joey Newcomb - Slabodka Niggun - ft. Naftali Kempeh",
3339    "Pirchei Shomayim Choir - Anim Zemiros",
3340    "Uri Davidi - Toda Raba",
3341    "Mechel Trailer Coming Soon",
3342    "Word Power - \"Sorry\"",
3343    "Word Power - \"Honesty\"",
3344    "The Secret Room - Respect Challenge",
3345    "Word Power - \"Sincerity\"",
3346    "Toveedo Teaser",
3347    "תורה שטעטל - צו געשמיידיק",
3348    "תורה שטעטל - נייַ טראָק",
3349    "תורה שטעטל - אכרייעס",
3350    "תורה שטעטל - געדולד",
3351    "תורה שטעטל - זיכערקייַט ערשטער",
3352    "The Mystery of Chaviv - Ep 7. Joining Forces",
3353    "The Mystery of Chaviv - Ep 6. He's Ready",
3354    "Ropogos - Ep. 4 Trailer",
3355    "Word Power - Please",
3356    "Midos Power Kids - Efraim the Lazy",
3357    "Midos Power Kids - Avi the Volcano Boy",
3358    "When Zaidy Was Young 1 - Kunda",
3359    "Midos Power Kids - Yitzchak Wants It All",
3360    "The Shepselach - Momo's New Friends",
3361    "Word Power - Solidarity",
3362    "Midos Power Kids - Rosa the Fearful",
3363    "Juggling Made Easy!",
3364    "Eliyahu Juggling Final 99098",
3365    "Pocket-size Pets",
3366    "Eliyahu Animals Final 7905",
3367    "Brushbox - Cupcake",
3368    "Brushbox - Fish Tank",
3369    "Incredible Science - Balloons",
3370    "Incredible Science - Fire",
3371    "Incredible Science - Liquid Nitrogen",
3372    "Sign Language with Rabbi B - Part 1",
3373    "Sign Language with Rabbi B - Part 2",
3374    "Dr. Sensy",
3375    "Shloima & Friends",
3376    "Llama Food Craft",
3377    "Toveedo Clubhouse - Chanukah Special",
3378    "Bentzi Marcus - Chai",
3379    "Chaptzem Theme Song",
3380    "The Bal Shem Tov & Eliyahu Hanavi",
3381    "Seven/Eight - Afikoman #TYH",
3382    "I Love You Hashem - Joey Newcomb ft. Afikoman #TYH",
3383    "Tried & True CGC 3 - Trailer",
3384    "Tried and True -  CGC 3",
3385    "Woh 3 Trailer",
3386    "Woh Safari Adventure trailer",
3387    "Wonders Of Hashem Under The Sea Trailer",
3388    "Shepselach Theme Song",
3389    "Pisom Trailer",
3390    "The Secret Room - The Blame Game",
3391    "Opposite_day Trailer",
3392    "Pet_penny Trailer",
3393    "Shofar_calling Trailer",
3394    "Double_mitzvah Trailer",
3395    "No_voice Trailer",
3396    "Copy_cups Trailer",
3397    "Stunt Matzah Trailer",
3398    "First_day Trailer",
3399    "Fan-Tastic Trailer",
3400    "Sukkah Blunders Trailer",
3401    "Midnight Watch Teaser- Coming Soon!",
3402    "Pintelach Teaser- Coming Soon!",
3403    "Chaptzem Teaser- Coming Soon",
3404    "Dr. Shnitzel - Liquid Nitrogen - Part 1",
3405    "Word Power - Achdus",
3406    "Midnight Watch - Episode 1",
3407    "Chaptzem - Wild Ride - pt. 1",
3408    "The Shepselach - The Great Pacifier Hunt",
3409    "Rabbi B - A Fresh Start for Nature",
3410    "Word Power - Imagination",
3411    "Word Power - Nature",
3412    "Chaptzem - Wild Ride - pt. 2",
3413    "Billionaire  #TYH Boys",
3414    "Chaptzem - Wild Ride - pt. 3",
3415    "Word Power - Humility",
3416    "Toveedo by Kids #5 Promo",
3417    "Chaptzem - Wild Ride - pt. 4",
3418    "Hero Clip",
3419    "The Mystery of Chaviv - Ep 8. A Radical Change",
3420    "The Mystery of Chaviv - Ep 9. The Quartet",
3421    "The Mystery of Chaviv - Ep 10. Moachnet",
3422    "Ayin Tova - Mirel Bennet",
3423    "Chaptzem - Wild Ride - pt. 5",
3424    "Judeo - Kol Isha",
3425    "Rabbi B - The Four Seasons",
3426    "Word Power - Self Esteem",
3427    "The Shepselach - Shaina's Pink Nose",
3428    "Word Power - I Love You",
3429    "Word Power - Recognition",
3430    "Good Morning Rooster - Modeh Ani",
3431    "Midnight Watch - Episode 2",
3432    "V’Nahapoch Hu - Afikoman Ft. Brother Sochi #TYH",
3433    "Chaptzem Purim - Yiddish",
3434    "Word Power - S2e01 - Strength",
3435    "Adar Dance",
3436    "This Is Your Moment - Kol Isha",
3437    "Billionaire",
3438    "Ein Kelokeinu",
3439    "I'm Grateful",
3440    "Ah-Yay - Kol Isha",
3441    "Nothing Holding You Back",
3442    "B’Yachad",
3443    "Magic with Shaya",
3444    "Shirei Netzach",
3445    "Pintelach 3 - Yomim Tovim",
3446    "Ropogos- Behind the Scenes of Season 1",
3447    "Funtastic Circus with Bello",
3448    "Word Power - Gratitude",
3449    "1,2,3 - Leah Avruch",
3450    "Dr. Shnitzel - Liquid Nitrogen - Part 2",
3451    "Midnight Watch - Episode 3",
3452    "Midnight Watch - Episode 4",
3453    "The Secret Room - Honesty",
3454    "Captain Sinai Ep. 6 - Cutting the Plishti's Down to Size",
3455    "The Shepselach - The Cozy Fort Adventure",
3456    "New Studio Live Stream 59998",
3457    "Impressions (for women and girls)",
3458    "The Fifth Kos- Coming Soon!",
3459    "Judeo- Coming Soon!",
3460    "Impressions by Rachel's Place- Coming Soon!",
3461    "Ropogos Season 2 - Trailer",
3462    "Mission To Pisom",
3463    "The Fifth Kos",
3464    "Hashem's Army #TYH Boys",
3465    "Pesach Medley - Afikoman",
3466    "Ropogos - S2 Ep 1. Vacation Mode",
3467    "Fritz Loses His Wits - Reb Nachman's Stories",
3468    "Rabbi B - Learning Torah pt. 1",
3469    "Word Power - Lashon Harah",
3470    "Schnorgelovich - Keilim Mikvah",
3471    "Secret Room - Someone Else's Turn",
3472    "Who I Am - Devorah Schwartz",
3473    "The Formula - Part 1/3 (For ages 12+)",
3474    "The Formula- Trailer",
3475    "Dr. Shnitzel - Fire",
3476    "Schnorgelovich - Shiluach Hakan",
3477    "Ropogos - S2 Ep 2. Erev Shabbos Mode",
3478    "Numbers - Shiras Hayam",
3479    "Everything's Amazing - Shiras Hayam",
3480    "I Know You're There - Shiras Hayam",
3481    "Better Together - Shiras_hayam ft. Tehila Erlich",
3482    "The Formula - Part 3/3 (For ages 12+)",
3483    "The Formula - Part 2/3 (For ages 12+)",
3484    "Rabbi B - Chodesh Sivan",
3485    "Shine My Light",
3486    "Jungle - Mendy Worch # TYH Boys",
3487    "I Wanna Be Like Zusha (Acapella)",
3488    "Ahavas Yisroel - Mendy Worch & Yossi Green #TYH",
3489    "Ropogos - S2 Ep 3. The Show Must Go On",
3490    "The Shepselach - Leftover Seeds",
3491    "Fraidy Katz - Screaming Ant Mystery Pt. 1",
3492    "Fraidy Katz - Screaming Ant Mystery Pt. 2",
3493    "Midnight Watch - Episode 5",
3494    "Secret Room - Games with Cookies",
3495    "The Nochum Show - Everything Is A Lesson",
3496    "Midbar Menny - Parshas Balak",
3497    "Midbar Menny - Parshas Pinchas",
3498    "Midbar Menny - Parshas Matos-Maasei",
3499    "Midbar Menny - Parshas Devorim",
3500    "Midbar Menny - Parshas Va'eschanan",
3501    "Midbar Menny - Parshas Eikev",
3502    "Ropogos - S2 Ep 4. No Sleep, No Papers",
3503    "Toveedo by Kids #6 Promo",
3504    "Backyard Treasure (For ages 10+)",
3505    "Rabbi B - Tammuz And Summer",
3506    "The Shepselach - Shmooberry Smoothies",
3507    "Dr Shnitzel - Helmet Safety",
3508    "Keeper Of The Keilim - Trailer",
3509    "The Shepselach - Shmoo Day School",
3510    "Corn Salad - Toveedo By Kids",
3511    "Glitter Art - Toveedo By Kids",
3512    "Hashovas Avaida  - Toveedo By Kids",
3513    "How To Juggle - Toveedo By Kids",
3514    "Cinnamon Buns - Toveedo By Kids",
3515    "Lemonade - Toveedo By Kids",
3516    "Magic Ink - Toveedo By Kids",
3517    "The Plan - Toveedo By Kids",
3518    "The Miracle Dirt",
3519    "Agent Emes 2.0 - Toveedo by Kids",
3520    "The Keeper Of The Keilim",
3521    "Midos Power Kids - Ita the Presumptuous",
3522    "Midnight Watch - Episode 6 (For ages 10+)",
3523    "Midnight Watch - Episode 7 (For ages 10+)",
3524    "Secret Room - Kind Words",
3525    "Ropogos - S2 Ep 5. Pressure Flight",
3526    "The Secret Room - A Bowl of Blueberry Cream",
3527    "The Secret Room - The Great Restoration",
3528    "Never Lose Hope - Reb Nachman's Stories",
3529    "No Shtus! #TYH - Avraham Fried",
3530    "Word Power - S1e10 - Bravery",
3531    "Word Power - S2e04 - Responsibility",
3532    "Torah Town - Race Day",
3533    "Hands Off -  CGC 4",
3534    "Ropogos- Behind the Scenes of Season 2",
3535    "The Shepselach - Feel Better Momo!",
3536    "Schnorgelovich - Hashovas Aveida",
3537    "Bernoulli's Principle with Dr Shnitzel",
3538    "Midnight Watch - Episode 8",
3539    "Coming Soon: The Go's",
3540    "Chaptzem Identity Shaimos - Part 1",
3541    "Chaptzem Identity Shaimos - Part 2",
3542    "Chaptzem Identity Shaimos - Part 3",
3543    "Chaptzem Identity Shaimos - Part 4",
3544    "GO Theme Song",
3545    "The Shepselach - Gavi's Birthday",
3546    "Secret-Room-Ep39_beware-Virus",
3547    "Secret-Room-Ep41_the-Seed-Of-Kindness",
3548    "Secret-Room-Ep38_sorry",
3549    "Unit 2 For Kids",
3550    "Unit 1 For Kids",
3551    "Unit 3 For Kids",
3552    "The Gos - Ep. 1",
3553    "Echoes_of_faith (2160p)",
3554    "Anash_ep_1_4k (2160p)",
3555    "Anonymous Benefactor (recommended ages 10+)",
3556  ];
3557
3558    function normalizedString(value) {
3559      return String(value == null ? "" : value).replace(/\s+/g, " ").trim();
3560    }
3561
3562    function normalizeArray(value) {
3563      return Array.isArray(value) ? value : [];
3564    }
3565
3566    function normalizeManifestCategory(category) {
3567      var label = normalizedString(
3568        category && (category.label || category.title || category.name),
3569      );
3570      var id =
3571        category && category.id != null
3572          ? String(category.id)
3573          : normalizeText(label);
3574
3575      if (!label || !id) return null;
3576
3577      return {
3578        id: id,
3579        title: normalizedString((category && category.title) || label),
3580        label: label,
3581        permalink: normalizedString(category && category.permalink),
3582        public: !(category && category.public === false),
3583        legacyId:
3584          (category && (category.legacyId || category.legacy_id)) || null,
3585        contentCount:
3586          Number(category && (category.contentCount || category.content_count)) ||
3587          0,
3588        icon: (category && category.icon) || "CA",
3589      };
3590    }
3591
3592    function normalizeManifestVideo(video) {
3593      var title = normalizedString(
3594        video && (video.title || video.label || video.name),
3595      );
3596      var id =
3597        video && video.id != null ? String(video.id) : normalizeText(title);
3598      var categoryLabels = normalizeArray(video && video.categoryLabels)
3599        .concat(normalizeArray(video && video.category_labels))
3600        .map(normalizedString)
3601        .filter(Boolean);
3602
3603      if (!title || !id) return null;
3604
3605      return {
3606        id: id,
3607        title: title,
3608        label: title,
3609        permalink: normalizedString(video && video.permalink),
3610        contentType:
3611          (video && (video.contentType || video.content_type)) || "video",
3612        categoryIds: normalizeArray(video && video.categoryIds)
3613          .concat(normalizeArray(video && video.category_ids))
3614          .map(function (item) {
3615            return String(item == null ? "" : item).trim();
3616          })
3617          .filter(Boolean),
3618        categoryLabels: categoryLabels,
3619        releaseStage:
3620          (video && (video.releaseStage || video.release_stage)) || "",
3621        publishedAt:
3622          video && (video.publishedAt || video.published_at)
3623            ? video.publishedAt || video.published_at
3624            : null,
3625        icon: (video && video.icon) || "VI",
3626        searchText: normalizeText(
3627          [title, video && video.permalink, categoryLabels.join(" ")].join(" "),
3628        ),
3629      };
3630    }
3631
3632    function normalizeParentalCatalogManifest(payload) {
3633      var fallback = PARENTAL_CATALOG_MANIFEST || {};
3634      var source = payload || {};
3635      var categories = normalizeArray(source.categories)
3636        .map(normalizeManifestCategory)
3637        .filter(Boolean);
3638      var videos = normalizeArray(source.videos)
3639        .map(normalizeManifestVideo)
3640        .filter(Boolean);
3641
3642      if (!categories.length) {
3643        categories = normalizeArray(fallback.categories)
3644          .map(normalizeManifestCategory)
3645          .filter(Boolean);
3646      }
3647
3648      return {
3649        schemaVersion: source.schemaVersion || SCHEMA_VERSION,
3650        source: source.source || "static-fallback",
3651        syncedAt: source.syncedAt || "",
3652        totalContents: Number(source.totalContents || videos.length) || 0,
3653        categories: categories,
3654        videos: videos,
3655        channels: normalizeArray(fallback.channels),
3656      };
3657    }
3658
3659    function getCachedParentalCatalogManifest() {
3660      var cached = readStorageJson(CATALOG_MANIFEST_CACHE_KEY);
3661      var savedAt = Number(cached && cached.savedAt);
3662
3663      if (!cached || !cached.manifest || !savedAt) return null;
3664
3665      if (Date.now() - savedAt > CATALOG_MANIFEST_CACHE_MAX_AGE_MS) {
3666        removeStorageItem(CATALOG_MANIFEST_CACHE_KEY);
3667        return null;
3668      }
3669
3670      return normalizeParentalCatalogManifest(cached.manifest);
3671    }
3672
3673    function cacheParentalCatalogManifest(manifest) {
3674      if (!manifest || !manifest.categories || !manifest.videos) return;
3675
3676      writeStorageJson(CATALOG_MANIFEST_CACHE_KEY, {
3677        savedAt: Date.now(),
3678        manifest: manifest,
3679      });
3680    }
3681
3682    function getParentalCatalogManifest() {
3683      var cachedManifest = state.catalogManifest || getCachedParentalCatalogManifest();
3684
3685      if (cachedManifest) {
3686        state.catalogManifest = cachedManifest;
3687        return cachedManifest;
3688      }
3689
3690      return normalizeParentalCatalogManifest(PARENTAL_CATALOG_MANIFEST);
3691    }
3692
3693    function loadParentalCatalogManifest(forceRefresh) {
3694      if (state.catalogManifestPromise) return state.catalogManifestPromise;
3695
3696      state.catalogManifest = getParentalCatalogManifest();
3697
3698      if (
3699        !forceRefresh &&
3700        state.catalogManifestLastFetchedAt &&
3701        Date.now() - state.catalogManifestLastFetchedAt <
3702          CATALOG_MANIFEST_REVALIDATE_INTERVAL_MS
3703      ) {
3704        return Promise.resolve(state.catalogManifest);
3705      }
3706
3707      state.catalogManifestLastFetchedAt = Date.now();
3708
3709      state.catalogManifestPromise = window
3710        .fetch(CATALOG_MANIFEST_ENDPOINT, {
3711          mode: "cors",
3712          credentials: "omit",
3713          headers: { Accept: "application/json" },
3714          cache: "no-store",
3715        })
3716        .then(function (response) {
3717          if (!response.ok) {
3718            throw new Error(
3719              "Catalog manifest failed with status " + response.status,
3720            );
3721          }
3722
3723          return response.json();
3724        })
3725        .then(function (payload) {
3726          var manifest = normalizeParentalCatalogManifest(payload);
3727
3728          if (manifest.categories.length || manifest.videos.length) {
3729            state.catalogManifest = manifest;
3730            cacheParentalCatalogManifest(manifest);
3731          }
3732
3733          return state.catalogManifest;
3734        })
3735        .catch(function () {
3736          return getParentalCatalogManifest();
3737        })
3738        .then(function (manifest) {
3739          state.catalogManifestPromise = null;
3740          return manifest;
3741        });
3742
3743      return state.catalogManifestPromise;
3744    }
3745
3746    function findManifestVideo(value) {
3747      var normalized = normalizeText(value);
3748      if (!normalized) return null;
3749
3750      return normalizeArray(getParentalCatalogManifest().videos).find(function (video) {
3751        return (
3752          normalizeText(video.id) === normalized ||
3753          normalizeText(video.title) === normalized ||
3754          normalizeText(video.permalink) === normalized
3755        );
3756      });
3757    }
3758
3759    function findManifestCategory(value) {
3760      var normalized = normalizeText(value);
3761      if (!normalized) return null;
3762
3763      return normalizeArray(getParentalCatalogManifest().categories).find(function (category) {
3764        return (
3765          normalizeText(category.id) === normalized ||
3766          normalizeText(category.label) === normalized ||
3767          normalizeText(category.title) === normalized ||
3768          normalizeText(category.permalink) === normalized
3769        );
3770      });
3771    }
3772
3773    function normalizeEmail(value) {
3774      return String(value || "").trim().toLowerCase();
3775    }
3776
3777    function normalizeText(value) {
3778      return String(value || "").replace(/\s+/g, " ").trim().toLowerCase();
3779    }
3780
3781    function htmlEscape(value) {
3782      return String(value == null ? "" : value)
3783        .replace(/&/g, "&amp;")
3784        .replace(/</g, "&lt;")
3785        .replace(/>/g, "&gt;")
3786        .replace(/"/g, "&quot;")
3787        .replace(/'/g, "&#039;");
3788    }
3789
3790    function clearLegacyParentalStorage() {
3791      var storages = [];
3792
3793      try {
3794        storages.push(window.localStorage);
3795      } catch (error) {}
3796
3797      try {
3798        storages.push(window.sessionStorage);
3799      } catch (error) {}
3800
3801      storages.forEach(function (storage) {
3802        try {
3803          if (!storage) return;
3804
3805          for (var index = storage.length - 1; index >= 0; index -= 1) {
3806            var key = storage.key(index);
3807            if (key && key.indexOf(LEGACY_STORAGE_PREFIX) === 0) {
3808              storage.removeItem(key);
3809            }
3810          }
3811        } catch (error) {}
3812      });
3813    }
3814
3815    function readStorageJson(key) {
3816      try {
3817        var raw = window.localStorage && window.localStorage.getItem(key);
3818        return raw ? JSON.parse(raw) : null;
3819      } catch (error) {
3820        return null;
3821      }
3822    }
3823
3824    function writeStorageJson(key, value) {
3825      try {
3826        if (window.localStorage) {
3827          window.localStorage.setItem(key, JSON.stringify(value));
3828        }
3829      } catch (error) {}
3830    }
3831
3832    function removeStorageItem(key) {
3833      try {
3834        if (window.localStorage) {
3835          window.localStorage.removeItem(key);
3836        }
3837      } catch (error) {}
3838    }
3839
3840    function emptyAccount() {
3841      return {
3842        schemaVersion: SCHEMA_VERSION,
3843        source: "toveedo-parental-control-v1",
3844        updatedAt: "",
3845        parentPinHash: "",
3846        profiles: []
3847      };
3848    }
3849
3850    function emptyProfile(type) {
3851      return normalizeProfile({
3852        id: "profile_" + Date.now().toString(36) + "_" + Math.random().toString(36).slice(2, 7),
3853        name: type === "parent" ? "Parent" : "Kid",
3854        type: type || "kid",
3855        birthday: "",
3856        pinHash: "",
3857        rules: {
3858          blockedVideos: [],
3859          blockedChannels: [],
3860          blockedCategories: [],
3861          maxAgeRating: "all",
3862          timeLimits: {
3863            enabled: false,
3864            allowedStart: "08:00",
3865            allowedEnd: "20:00",
3866            dailyMinutes: 120
3867          }
3868        }
3869      });
3870    }
3871
3872    function normalizeProfile(profile) {
3873      profile.rules = profile.rules || {};
3874      profile.rules.blockedVideos = Array.isArray(profile.rules.blockedVideos)
3875        ? profile.rules.blockedVideos
3876        : [];
3877      profile.rules.blockedChannels = Array.isArray(profile.rules.blockedChannels)
3878        ? profile.rules.blockedChannels
3879        : [];
3880      profile.rules.blockedCategories = Array.isArray(profile.rules.blockedCategories)
3881        ? profile.rules.blockedCategories
3882        : [];
3883      profile.rules.maxAgeRating = profile.rules.maxAgeRating || "all";
3884      profile.rules.timeLimits = Object.assign(
3885        {
3886          enabled: false,
3887          allowedStart: "08:00",
3888          allowedEnd: "20:00",
3889          dailyMinutes: 120
3890        },
3891        profile.rules.timeLimits || {}
3892      );
3893      return profile;
3894    }
3895
3896    function parseAccount(rawValue) {
3897      if (!rawValue) return emptyAccount();
3898      try {
3899        var parsed = typeof rawValue === "string" ? JSON.parse(rawValue) : rawValue;
3900        if (!parsed || typeof parsed !== "object") return emptyAccount();
3901        parsed.profiles = Array.isArray(parsed.profiles) ? parsed.profiles : [];
3902        parsed.profiles.forEach(normalizeProfile);
3903        return Object.assign(emptyAccount(), parsed);
3904      } catch (error) {
3905        return emptyAccount();
3906      }
3907    }
3908
3909    function hideField3() {
3910      var selectors = [
3911        'ds-input[name="form[field_3]"]',
3912        "ds-input#form_field_3",
3913        'input[name="form[field_3]"]',
3914        'textarea[name="form[field_3]"]',
3915        'select[name="form[field_3]"]',
3916        '[name="user[field_3]"]',
3917        "#form_field_3",
3918        "#user_field_3",
3919        '[for="form_field_3"]',
3920        '[for="user_field_3"]'
3921      ];
3922
3923      document.querySelectorAll(selectors.join(",")).forEach(function (field) {
3924        var wrapper =
3925          field.closest(".w-full, .mb-6.flex.flex-col, .mb-5, .form-group, .field, [data-test]") ||
3926          field.parentElement ||
3927          field;
3928        wrapper.classList.add("toveedo-parental-field-hidden");
3929      });
3930
3931      document.querySelectorAll("p, label, span").forEach(function (node) {
3932        if (normalizeText(node.textContent) !== "parental control") return;
3933        var wrapper =
3934          node.closest(".w-full, .mb-6.flex.flex-col, .mb-5, .form-group, .field, [data-test]") ||
3935          node.parentElement ||
3936          node;
3937        wrapper.classList.add("toveedo-parental-field-hidden");
3938      });
3939    }
3940
3941    function fetchJson(url) {
3942      if (window.axios && typeof window.axios.get === "function") {
3943        return window.axios.get(url, { headers: { Accept: "application/json" } }).then(function (response) {
3944          return response.data;
3945        });
3946      }
3947
3948      return fetch(url, {
3949        credentials: "same-origin",
3950        headers: { Accept: "application/json" }
3951      }).then(function (response) {
3952        if (!response.ok) throw new Error("Request failed: " + response.status);
3953        return response.json();
3954      });
3955    }
3956
3957    function putUserField(value) {
3958      var formData = new FormData();
3959      formData.append(FORM_FIELD_NAME, value);
3960
3961      if (window.axios && typeof window.axios.put === "function") {
3962        return window.axios.put("/api/users", formData).then(function (response) {
3963          return response.data;
3964        });
3965      }
3966
3967      return fetch("/api/users", {
3968        method: "PUT",
3969        credentials: "same-origin",
3970        body: formData
3971      }).then(function (response) {
3972        if (!response.ok) throw new Error("Save failed: " + response.status);
3973        return response.text();
3974      });
3975    }
3976
3977    function hasSession(session) {
3978      return Boolean(
3979        session &&
3980          (session.logged === true ||
3981            session.logged_in === true ||
3982            session.loggedIn === true ||
3983            session.user ||
3984            session.current_user ||
3985            session.email ||
3986            session.user_id ||
3987            session.id)
3988      );
3989    }
3990
3991    function accountCacheKey(email) {
3992      return ACCOUNT_CACHE_STORAGE_KEY + normalizeEmail(email || TEST_USER_EMAIL);
3993    }
3994
3995    function cacheAccount(email, account) {
3996      if (!account || !account.profiles) return;
3997
3998      writeStorageJson(accountCacheKey(email), {
3999        savedAt: Date.now(),
4000        account: account
4001      });
4002    }
4003
4004    function getCachedAccount(email) {
4005      var cached = readStorageJson(accountCacheKey(email));
4006      var savedAt = Number(cached && cached.savedAt);
4007      if (!cached || !cached.account) return null;
4008
4009      if (!savedAt || Date.now() - savedAt > ACCOUNT_CACHE_MAX_AGE_MS) {
4010        removeStorageItem(accountCacheKey(email));
4011        return null;
4012      }
4013
4014      return parseAccount(cached.account);
4015    }
4016
4017    function clearAccountCache(email) {
4018      var normalizedEmail = normalizeEmail(email || TEST_USER_EMAIL);
4019      var storedSelection = readStorageJson(ACTIVE_PROFILE_STORAGE_KEY);
4020
4021      removeStorageItem(accountCacheKey(normalizedEmail));
4022
4023      if (
4024        !storedSelection ||
4025        normalizeEmail(storedSelection.email) === normalizedEmail
4026      ) {
4027        removeStorageItem(ACTIVE_PROFILE_STORAGE_KEY);
4028      }
4029
4030      if (normalizeEmail(state.activeSelection.email) === normalizedEmail) {
4031        state.activeSelection = {
4032          email: normalizedEmail,
4033          profileId: ""
4034        };
4035      }
4036    }
4037
4038    function accountScore(account) {
4039      if (!account) return 0;
4040      return (account.parentPinHash ? 100 : 0) + ((account.profiles || []).length || 0);
4041    }
4042
4043    function accountUpdatedAt(account) {
4044      var time = Date.parse((account && account.updatedAt) || "");
4045      return Number.isNaN(time) ? 0 : time;
4046    }
4047
4048    function chooseAccount(remoteAccount, cachedAccount) {
4049      var remoteScore = accountScore(remoteAccount);
4050      var cachedScore = accountScore(cachedAccount);
4051      var remoteUpdatedAt = accountUpdatedAt(remoteAccount);
4052      var cachedUpdatedAt = accountUpdatedAt(cachedAccount);
4053
4054      if (!remoteScore) return cachedScore ? cachedAccount : emptyAccount();
4055      if (!cachedScore) return remoteAccount;
4056
4057      if (
4058        remoteUpdatedAt &&
4059        cachedUpdatedAt &&
4060        remoteUpdatedAt !== cachedUpdatedAt
4061      ) {
4062        return remoteUpdatedAt > cachedUpdatedAt ? remoteAccount : cachedAccount;
4063      }
4064
4065      if (cachedScore > remoteScore) return cachedAccount;
4066      if (remoteScore > cachedScore) return remoteAccount;
4067
4068      return remoteAccount;
4069    }
4070
4071    function saveAccount(email, account) {
4072      account.updatedAt = new Date().toISOString();
4073      return putUserField(JSON.stringify(account)).then(function () {
4074        cacheAccount(email, account);
4075        return account;
4076      });
4077    }
4078
4079    function getSession() {
4080      if (!state.sessionPromise) {
4081        state.sessionPromise = fetchJson("/api/sessions").catch(function () {
4082          return null;
4083        });
4084      }
4085      return state.sessionPromise;
4086    }
4087
4088    function getCurrentUser() {
4089      if (!state.userPromise) {
4090        state.userPromise = getSession()
4091          .then(function (session) {
4092            if (!hasSession(session)) return null;
4093            return fetchJson("/api/users/me").catch(function () {
4094              return session || null;
4095            });
4096          })
4097          .catch(function () {
4098            return null;
4099          });
4100      }
4101      return state.userPromise;
4102    }
4103
4104    function getUserEmail(user) {
4105      return normalizeEmail(
4106        user &&
4107          (user.email ||
4108            (user.user && user.user.email) ||
4109            (user.current_user && user.current_user.email))
4110      );
4111    }
4112
4113    function getUserField(user, key) {
4114      var containers = [
4115        user,
4116        user && user.user,
4117        user && user.current_user,
4118        user && user.fields,
4119        user && user.custom_fields,
4120        user && user.customFields
4121      ];
4122
4123      for (var index = 0; index < containers.length; index += 1) {
4124        if (
4125          containers[index] &&
4126          Object.prototype.hasOwnProperty.call(containers[index], 
4126key)
4127        ) {
4128          return containers[index][key];
4129        }
4130      }
4131
4132      return undefined;
4133    }
4134
4135    function isEnabledUser(user) {
4136      return getUserEmail(user) === TEST_USER_EMAIL;
4137    }
4138
4139    function getAccountForUser(user, email) {
4140      var remoteAccountValue = getUserField(user, FIELD_KEY);
4141      var remoteFieldWasCleared =
4142        remoteAccountValue === null ||
4143        (typeof remoteAccountValue === "string" &&
4144          remoteAccountValue.trim() === "");
4145
4146      if (remoteFieldWasCleared) {
4147        clearAccountCache(email);
4148        return emptyAccount();
4149      }
4150
4151      var remoteAccount = parseAccount(remoteAccountValue);
4152      var cachedAccount = getCachedAccount(email);
4153      var account = chooseAccount(remoteAccount, cachedAccount);
4154
4155      if (accountScore(account)) {
4156        cacheAccount(email, account);
4157      }
4158
4159      return account;
4160    }
4161
4162    function getActiveSelection(email) {
4163      var normalizedEmail = normalizeEmail(email);
4164      var storedSelection = null;
4165
4166      if (normalizeEmail(state.activeSelection.email) === normalizedEmail) {
4167        return state.activeSelection.profileId || "";
4168      }
4169
4170      storedSelection = readStorageJson(ACTIVE_PROFILE_STORAGE_KEY);
4171      if (
4172        !storedSelection ||
4173        normalizeEmail(storedSelection.email) !== normalizedEmail
4174      ) {
4175        return "";
4176      }
4177
4178      state.activeSelection = {
4179        email: normalizedEmail,
4180        profileId: storedSelection.profileId || ""
4181      };
4182      return state.activeSelection.profileId || "";
4183    }
4184
4185    function setActiveSelection(email, profileId) {
4186      var normalizedEmail = normalizeEmail(email);
4187      state.activeSelection = {
4188        email: normalizedEmail,
4189        profileId: profileId || ""
4190      };
4191
4192      if (profileId) {
4193        writeStorageJson(ACTIVE_PROFILE_STORAGE_KEY, {
4194          email: normalizedEmail,
4195          profileId: profileId,
4196          selectedAt: new Date().toISOString()
4197        });
4198      } else {
4199        removeStorageItem(ACTIVE_PROFILE_STORAGE_KEY);
4200      }
4201    }
4202
4203    function getActiveProfile(account, email) {
4204      var profileId = getActiveSelection(email);
4205      return (account.profiles || []).find(function (profile) {
4206        return profile.id === profileId;
4207      });
4208    }
4209
4210    function isCatalogRoute() {
4211      return window.location.pathname.indexOf("/catalog") === 0;
4212    }
4213
4214    function isParentalModalSuppressedRoute() {
4215      return /^\/(?:join|checkout|account)(?:\/|$)/.test(window.location.pathname);
4216    }
4217
4218    function dismissParentalModal() {
4219      var existing = document.getElementById(MODAL_ID);
4220      if (existing) existing.remove();
4221    }
4222
4223    function catalogConfirmKey(email) {
4224      return normalizeEmail(email);
4225    }
4226
4227    function markCatalogConfirmed(email) {
4228      state.catalogConfirmations[catalogConfirmKey(email)] = true;
4229    }
4230
4231    function shouldConfirmOnCatalog(email) {
4232      return (
4233        isCatalogRoute() &&
4234        !getActiveSelection(email) &&
4235        state.catalogConfirmations[catalogConfirmKey(email)] !== true
4236      );
4237    }
4238
4239    function hashPin(pin) {
4240      var value = String(pin || "").trim();
4241      if (!value) return Promise.resolve("");
4242
4243      if (window.crypto && window.crypto.subtle && window.TextEncoder) {
4244        return window.crypto.subtle.digest("SHA-256", new TextEncoder().encode(value)).then(function (buffer) {
4245          return (
4246            "sha256:" +
4247            Array.from(new Uint8Array(buffer))
4248              .map(function (byte) {
4249                return byte.toString(16).padStart(2, "0");
4250              })
4251              .join("")
4252          );
4253        });
4254      }
4255
4256      return Promise.resolve("plain-fallback:" + btoa(value));
4257    }
4258
4259    function verifyPin(pin, hash) {
4260      return hashPin(pin).then(function (candidate) {
4261        return Boolean(candidate && hash && candidate === hash);
4262      });
4263    }
4264
4265    function profileLabel(profile) {
4266      return profile && profile.name ? profile.name : "Profile";
4267    }
4268
4269    function profileAvatar(profile) {
4270      var label = profileLabel(profile);
4271      if (profile && profile.type === "kid") return "K";
4272      return label ? label.charAt(0).toUpperCase() : "P";
4273    }
4274
4275    function pinBoxesHtml(id, label) {
4276      var safeLabel = label || "PIN";
4277      var labelHtml = label
4278        ? "<span>" + htmlEscape(label) + "</span>"
4279        : '<span class="toveedo-pc-sr-only">' + htmlEscape(safeLabel) + "</span>";
4280      var boxes = [0, 1, 2, 3]
4281        .map(function (index) {
4282          return (
4283            '<input class="toveedo-pc-pin-digit" data-tpc-pin-digit type="password" inputmode="numeric" maxlength="1" autocomplete="off" aria-label="' +
4284            htmlEscape(safeLabel + " digit " + (index + 1)) +
4285            '">'
4286          );
4287        })
4288        .join("");
4289
4290      return (
4291        '<label class="toveedo-pc-field toveedo-pc-pin-field">' +
4292        labelHtml +
4293        '<input class="toveedo-pc-pin-value" id="' +
4294        htmlEscape(id) +
4295        '" type="hidden" value="">' +
4296        '<div class="toveedo-pc-pin-grid" data-tpc-pin-group data-tpc-pin-target="' +
4297        htmlEscape(id) +
4298        '">' +
4299        boxes +
4300        "</div></label>"
4301      );
4302    }
4303
4304    function findPinGroup(id) {
4305      var groups = document.querySelectorAll("[data-tpc-pin-group]");
4306      for (var index = 0; index < groups.length; index += 1) {
4307        if (groups[index].getAttribute("data-tpc-pin-target") === id) {
4308          return groups[index];
4309        }
4310      }
4311
4312      return null;
4313    }
4314
4315    function syncPinGroup(group) {
4316      if (!group) return "";
4317
4318      var value = Array.from(group.querySelectorAll("[data-tpc-pin-digit]"))
4319        .map(function (input) {
4320          var digit = String(input.value || "").replace(/\D/g, "").slice(-1);
4321          input.value = digit;
4322          return digit;
4323        })
4324        .join("");
4325      var target = document.getElementById(group.getAttribute("data-tpc-pin-target"));
4326      if (target) target.value = value;
4327      return value;
4328    }
4329
4330    function setPinGroupValue(group, value) {
4331      if (!group) return;
4332
4333      var digits = String(value || "").replace(/\D/g, "").slice(0, 4).split("");
4334      Array.from(group.querySelectorAll("[data-tpc-pin-digit]")).forEac
4334h(function (input, index) {
4335        input.value = digits[index] || "";
4336      });
4337      syncPinGroup(group);
4338    }
4339
4340    function getPinValue(id) {
4341      var group = findPinGroup(id);
4342      if (group) return syncPinGroup(group);
4343
4344      var input = document.getElementById(id);
4345      return input ? String(input.value || "").replace(/\D/g, "").slice(0, 4) : "";
4346    }
4347
4348    function focusPinInput(id) {
4349      var group = findPinGroup(id);
4350      var input = group && group.querySelector("[data-tpc-pin-digit]");
4351      if (input) input.focus();
4352    }
4353
4354    function bindPinEntry(root) {
4355      if (!root || root.dataset.toveedoPinBound === "true") return;
4356
4357      root.dataset.toveedoPinBound = "true";
4358
4359      root.addEventListener("input", function (event) {
4360        var input = event.target.closest("[data-tpc-pin-digit]");
4361        if (!input) return;
4362
4363        var group = input.closest("[data-tpc-pin-group]");
4364        var digits = String(input.value || "").replace(/\D/g, "");
4365        var inputs = Array.from(group.querySelectorAll("[data-tpc-pin-digit]"));
4366        var currentIndex = inputs.indexOf(input);
4367
4368        if (digits.length > 1) {
4369          setPinGroupValue(group, digits);
4370          var nextEmpty = inputs.find(function (item) {
4371            return !item.value;
4372          });
4373          (nextEmpty || inputs[inputs.length - 1]).focus();
4374          return;
4375        }
4376
4377        input.value = digits;
4378        syncPinGroup(group);
4379
4380        if (digits && currentIndex < inputs.length - 1) {
4381          inputs[currentIndex + 1].focus();
4382        }
4383      });
4384
4385      root.addEventListener("keydown", function (event) {
4386        var input = event.target.closest("[data-tpc-pin-digit]");
4387        if (!input) return;
4388
4389        var group = input.closest("[data-tpc-pin-group]");
4390        var inputs = Array.from(group.querySelectorAll("[data-tpc-pin-digit]"));
4391        var currentIndex = inputs.indexOf(input);
4392
4393        if (event.key === "Enter") {
4394          var modal = group.closest(".toveedo-pc-modal");
4395          var actionButton =
4396            modal &&
4397            modal.querySelector(
4398              "[data-tpc-unlock], [data-tpc-parent-manage], [data-tpc-setup], [data-tpc-parent-unlock]",
4399            );
4400
4401          if (actionButton) {
4402            event.preventDefault();
4403            syncPinGroup(group);
4404            actionButton.click();
4405          }
4406          return;
4407        }
4408
4409        if (event.key === "Backspace" && !input.value && currentIndex > 0) {
4410          inputs[currentIndex - 1].focus();
4411          return;
4412        }
4413
4414        if (event.key === "ArrowLeft" && currentIndex > 0) {
4415          event.preventDefault();
4416          inputs[currentIndex - 1].focus();
4417          return;
4418        }
4419
4420        if (event.key === "ArrowRight" && currentIndex < inputs.length - 1) {
4421          event.preventDefault();
4422          inputs[currentIndex + 1].focus();
4423        }
4424      });
4425
4426      root.addEventListener("paste", function (event) {
4427        var input = event.target.closest("[data-tpc-pin-digit]");
4428        if (!input) return;
4429
4430        var clipboard = event.clipboardData || window.clipboardData;
4431        var pasted = clipboard ? clipboard.getData("text") : "";
4432        var digits = String(pasted || "").replace(/\D/g, "").slice(0, 4);
4433        if (!digits) return;
4434
4435        event.preventDefault();
4436
4437        var group = input.closest("[data-tpc-pin-group]");
4438        setPinGroupValue(group, digits);
4439
4440        var inputs = Array.from(group.querySelectorAll("[data-tpc-pin-digit]"));
4441        var nextEmpty = inputs.find(function (item) {
4442          return !item.value;
4443        });
4444        (nextEmpty || inputs[inputs.length - 1]).focus();
4445      });
4446    }
4447
4448    function openProfileChooser(account, email, options) {
4449      options = options || {};
4450      if (isParentalModalSuppressedRoute()) {
4451        dismissParentalModal();
4452        return;
4453      }
4454
4455      var existing = document.getElementById(MODAL_ID);
4456      if (existing && !options.force) return;
4457      if (existing) existing.remove();
4458      if (
4459        getActiveProfile(account, email) &&
4460        !options.force &&
4461        !options.catalogConfirm &&
4462        account.parentPinHash &&
4463        account.profiles.length
4464      ) {
4465        return;
4466      }
4467
4468      var backdrop = document.createElement("div");
4469      backdrop.id = MODAL_ID;
4470      backdrop.className = "toveedo-pc-backdrop";
4471      document.body.appendChild(backdrop);
4472      var workingAccount = account;
4473
4474      function closeModal() {
4475        if (options.catalogConfirm) markCatalogConfirmed(email);
4476        backdrop.remove();
4477        ensureSwitcher(workingAccount, email);
4478        scheduleSync();
4479      }
4480
4481      function frameHtml(title, bodyHtml, canClose, modalClass, beforeTitleHtml) {
4482        return (
4483          '<div class="toveedo-pc-modal ' +
4484          htmlEscape(modalClass || "") +
4485          '" role="dialog" aria-modal="true" aria-label="' +
4486          htmlEscape(title) +
4487          '" style="position:relative">' +
4488          (canClose ? '<button class="toveedo-pc-close" type="button" data-tpc-close aria-label="Close">x</button>' : "") +
4489          '<div class="toveedo-pc-modal__body toveedo-pc-stack">' +
4490          (beforeTitleHtml || "") +
4491          "<h2>" +
4492          htmlEscape(title) +
4493          "</h2>" +
4494          bodyHtml +
4495          "</div></div>"
4496        );
4497      }
4498
4499      function inputField(label, inputHtml) {
4500        return '<label class="toveedo-pc-field"><span>' + htmlEscape(label) + "</span>" + inputHtml + "</label>";
4501      }
4502
4503      function selectedHtml(value, selectedValue) {
4504        return String(value) === String(selectedValue) ? " selected" : "";
4505      }
4506
4507      function checkedHtml(value) {
4508        return value ? " checked" : "";
4509      }
4510
4511      function ruleItemsToLines(items) {
4512        return (Array.isArray(items) ? items : [])
4513          .map(function (item) {
4514            return String(
4515              typeof item === "string"
4516                ? item
4517                : (item && (item.title || item.label || item.value || item.id)) || "",
4518            ).trim();
4519          })
4520          .filter(Boolean)
4521          .join("\n");
4522      }
4523
4524      function textLinesToRuleItems(value, key) {
4525        var seen = {};
4526        return String(value || "")
4527          .split(/\n+/)
4528          .map(function (line) {
4529            return line.replace(/\s+/g, " ").trim();
4530          })
4531          .filter(function (line) {
4532            var normalized = normalizeText(line);
4533            if (!normalized || seen[normalized]) return false;
4534            seen[normalized] = true;
4535            return true;
4536          })
4537          .map(function (line) {
4538            var manifestItem =
4539              key === "title"
4540                ? findVideoFilterOption(line)
4541                : findCategoryFilterOption(line);
4542            var item = manifestItem
4543              ? Object.assign({}, manifestItem)
4544              : { label: line };
4545
4546            if (item.searchText) delete item.searchText;
4547            if (item.icon) delete item.icon;
4548            item[key] = item[key] || line;
4549            return item;
4550          });
4551      }
4552
4553      function ageRatingOptionsHtml(selectedValue) {
4554        return AGE_FILTERS.map(function (item) {
4555          return (
4556            '<option value="' +
4557            htmlEscape(item.value) +
4558            '"' +
4559            selectedHtml(item.value, selectedValue) +
4560            ">" +
4561            htmlEscape(item.value === "all" ? "All ages" : item.value) +
4562            "</option>"
4563          );
4564        }).join("");
4565      }
4566
4567      function activeProfileCanManage() {
4568        var activeProfile = getActiveProfile(workingAccount, email);
4569        return Boolean(activeProfile && activeProfile.type === "parent");
4570      }
4571
4572      function findWorkingProfile(profileId) {
4573        return workingAccount.profiles.find(function (profile) {
4574          return profile.id === profileId;
4575        });
4576      }
4577
4578      function ruleItemText(item) {
4579        return String(
4580          typeof item === "string"
4581            ? item
4582            : (item && (item.title || item.label || item.value || item.id)) || "",
4583        ).trim();
4584      }
4585
4586      function ruleListHasValue(items, value) {
4587        var normalized = normalizeText(value);
4588        return (Array.isArray(items) ? items : []).some(function (item) {
4589          if (typeof item === "string") {
4590            return normalizeText(item) === normalized;
4591          }
4592
4593          return [
4594            item && item.id,
4595            item && item.value,
4596            item && item.permalink,
4597            item && item.title,
4598            item && item.label,
4599          ].some(function (candidate) {
4600            return normalizeText(candidate) === normalized;
4601          });
4602        });
4603      }
4604
4605      function hiddenRuleTextarea(id, value) {
4606        return (
4607          '<textarea class="toveedo-pc-hidden-rules" id="' +
4608          htmlEscape(id) +
4609          '">' +
4610          htmlEscape(value) +
4611          "</textarea>"
4612        );
4613      }
4614
4615      function getRuleLines(id) {
4616        var field = document.getElementById(id);
4617        var seen = {};
4618        if (!field) return [];
4619
4620        return String(field.value || "")
4621          .split(/\n+/)
4622          .map(function (line) {
4623            return line.replace(/\s+/g, " ").trim();
4624          })
4625          .filter(function (line) {
4626            var normalized = normalizeText(line);
4627            if (!normalized || seen[normalized]) return false;
4628            seen[normalized] = true;
4629            return true;
4630          });
4631      }
4632
4633      function setRuleLines(id, lines) {
4634        var field = document.getElementById(id);
4635        if (!field) return;
4636
4637        field.value = lines.join("\n");
4638      }
4639
4640      function filterIconLabel(label, icon) {
4641        var fallback = String(label || "")
4642          .replace(/[^a-z0-9]/gi, "")
4643          .slice(0, 2)
4644          .toUpperCase();
4645        return icon || fallback || "FL";
4646      }
4647
4648      function restrictionRowHtml(targetId, value, label, icon, isBlocked) {
4649        return (
4650          '<button class="toveedo-pc-filter-row' +
4651          (isBlocked ? " is-blocked" : "") +
4652          '" type="button" data-tpc-filter-row data-tpc-toggle-rule data-tpc-target="' +
4653          htmlEscape(targetId) +
4654          '" data-tpc-value="' +
4655          htmlEscape(value) +
4656          '" aria-pressed="' +
4657          (isBlocked ? "true" : "false") +
4658          '">' +
4659          '<span class="toveedo-pc-filter-icon">' +
4660          htmlEscape(filterIconLabel(label, icon)) +
4661          "</span>" +
4662          '<span class="toveedo-pc-filter-name">' +
4663          htmlEscape(label) +
4664          "</span>" +
4665          '<span class="toveedo-pc-rule-status" data-tpc-rule-status>' +
4666          htmlEscape(isBlocked ? "Hidden" : "Shown") +
4667          "</span>" +
4668          "</button>"
4669        );
4670      }
4671
4672      function buildRestrictionCard(title, count, innerHtml) {
4673        return (
4674          '<div class="toveedo-pc-restriction-card">' +
4675          '<div class="toveedo-pc-restriction-card__head">' +
4676          "<h4>" +
4677          htmlEscape(title) +
4678          "</h4>" +
4679          '<span class="toveedo-pc-restriction-count">' +
4680          htmlEscape(count) +
4681          "</span>" +
4682          "</div>" +
4683          innerHtml +
4684          "</div>"
4685        );
4686      }
4687
4688      function getVideoFilterOptions() {
4689        var seen = {};
4690        var manifest = getParentalCatalogManifest();
4691        var channels = manifest.channels || [];
4692        var manifestVideos = manifest.videos || [];
4693        var options = [];
4694
4695        function addVideo(video, icon) {
4696          var label = String(
4697            typeof video === "string"
4698              ? video
4699              : video && (video.title || video.label || video.name),
4700          )
4701            .replace(/\s+/g, " ")
4702            .trim();
4703          var id =
4704            typeof video === "string" || !(video && video.id != null)
4705              ? ""
4706              : String(video.id);
4707          var key = id ? "id:" + id : "title:" + normalizeText(label);
4708          if (!key || seen[key]) return;
4709          seen[key] = true;
4710          options.push({
4711            id: id,
4712            title: label,
4713            label: label,
4714            permalink:
4715              typeof video === "string" ? "" : String((video && video.permalink) || ""),
4716            categoryIds:
4717              typeof video === "string" ? [] : normalizeArray(video && video.categoryIds),
4718            categoryLabels:
4719              typeof video === "string"
4720                ? []
4721                : normalizeArray(video && video.categoryLabels),
4722            contentType:
4723              typeof video === "string" ? "video" : video && video.contentType,
4724            icon: icon || (video && video.icon) || "VI",
4725            searchText: normalizeText(
4726              [
4727                label,
4728                typeof video === "string" ? "" : video && video.permalink,
4729                typeof video === "string"
4730                  ? ""
4731                  : normalizeArray(video && video.categoryLabels).join(" "),
4732              ].join(" "),
4733            )
4734          });
4735        }
4736
4737        if (manifestVideos.length) {
4738          manifestVideos.forEach(function (video) {
4739            addVideo(video, "VI");
4740          });
4741        } else {
4742          (PARENTAL_VIDEO_TITLES || []).forEach(function (title) {
4743            addVideo(title, "VI");
4744          });
4745
4746          channels.forEach(function (channel) {
4747            (channel.videos || []).forEach(function (video) {
4748              addVideo(video, channel.icon || "VI");
4749            });
4750          });
4751        }
4752
4753        return options;
4754      }
4755
4756      function findVideoFilterOption(value) {
4757        var normalized = normalizeText(value);
4758        if (!normalized) return null;
4759
4760        return getVideoFilterOptions().find(function (video) {
4761          return (
4762            normalizeText(video.id) === normalized ||
4763            normalizeText(video.title) === normalized ||
4764            normalizeText(video.permalink) === normalized
4765          );
4766        });
4767      }
4768
4769      function getCategoryFilterOptions() {
4770        return (getParentalCatalogManifest().categories || [])
4771          .map(function (category) {
4772            var option = normalizeManifestCategory(category);
4773            if (!option) return null;
4774
4775            option.searchText = normalizeText(
4776              [
4777                option.label,
4778                option.title,
4779                option.permalink,
4780                option.id,
4781              ].join(" "),
4782            );
4783
4784            return option;
4785          })
4786          .filter(Boolean);
4787      }
4788
4789      function findCategoryFilterOption(value) {
4790        var normalized = normalizeText(value);
4791        if (!normalized) return null;
4792
4793        return getCategoryFilterOptions().find(function (category) {
4794          return (
4795            normalizeText(category.id) === normalized ||
4796            normalizeText(category.label) === normalized ||
4797            normalizeText(category.title) === normalized ||
4798            normalizeText(category.permalink) === normalized
4799          );
4800        });
4801      }
4802
4803      function videoSearchMatches(option, query) {
4804        var terms = normalizeText(query).split(" ").filter(Boolean);
4805        if (!terms.length) return true;
4806
4807        return terms.every(function (term) {
4808          return option.searchText.indexOf(term) !== -1;
4809        });
4810      }
4811
4812      function categorySearchMatches(option, query) {
4813        var terms = normalizeText(query).split(" ").filter(Boolean);
4814        if (!terms.length) return true;
4815
4816        return terms.every(function (term) {
4817          return option.searchText.indexOf(term) !== -1;
4818        });
4819      }
4820
4821      function videoRowsHtml(options, blockedLines) {
4822        return options
4823          .map(function (video) {
4824            return restrictionRowHtml(
4825              "toveedo-pc-edit-blocked-videos",
4826              video.title,
4827              video.title,
4828              video.icon,
4829              blockedLines.indexOf(normalizeText(video.title)) !== -1,
4830            );
4831          })
4832          .join("");
4833      }
4834
4835      function selectedVideoRowsHtml(lines) {
4836        if (!lines.length) {
4837          return '<div class="toveedo-pc-filter-empty">No hidden videos selected.</div>';
4838        }
4839
4840        return lines
4841          .map(function (title) {
4842            return restrictionRowHtml(
4843              "toveedo-pc-edit-blocked-videos",
4844              title,
4845              title,
4846              "VI",
4847              true,
4848            );
4849          })
4850          .join("");
4851      }
4852
4853      function categoryRowsHtml(options, blockedLines) {
4854        return options
4855          .map(function (category) {
4856            var isBlocked =
4857              blockedLines.indexOf(normalizeText(category.label)) !== -1 ||
4858              blockedLines.indexOf(normalizeText(category.id)) !== -1;
4859
4860            return restrictionRowHtml(
4861              "toveedo-pc-edit-blocked-categories",
4862              category.label,
4863              category.label,
4864              category.icon || "CA",
4865              isBlocked,
4866            );
4867          })
4868          .join("");
4869      }
4870
4871      function selectedCategoryRowsHtml(lines) {
4872        if (!lines.length) {
4873          return '<div class="toveedo-pc-filter-empty">No hidden categories selected.</div>';
4874        }
4875
4876        return lines
4877          .map(function (line) {
4878            var category = findCategoryFilterOption(line);
4879            var label = (category && category.label) || line;
4880
4881            return restrictionRowHtml(
4882              "toveedo-pc-edit-blocked-categories",
4883              label,
4884              label,
4885              (category && category.icon) || "CA",
4886              true,
4887            );
4888          })
4889          .join("");
4890      }
4891
4892      function renderVideoSearchResults(query) {
4893        var results = backdrop.querySelector("[data-tpc-video-results]");
4894        var input = backdrop.querySelector("[data-tpc-video-search]");
4895        if (!results || !input) return;
4896
4897        var blockedLines = getRuleLines("toveedo-pc-edit-blocked-videos").map(
4898          normalizeText,
4899        );
4900        var matches = getVideoFilterOptions()
4901          .filter(function (video) {
4902            return videoSearchMatches(video, query);
4903          })
4904          .slice(0, 20);
4905
4906        results.innerHTML = matches.length
4907          ? videoRowsHtml(matches, blockedLines)
4908          : '<div class="toveedo-pc-filter-empty">No matching videos.</div>';
4909        results.hidden = false;
4910        input.setAttribute("aria-expanded", "true");
4911      }
4912
4913      function refreshSelectedVideoRows() {
4914        var selected = backdrop.querySelector("[data-tpc-selected-videos]");
4915        if (!selected) return;
4916
4917        selected.innerHTML = selectedVideoRowsHtml(
4918          getRuleLines("toveedo-pc-edit-blocked-videos"),
4919        );
4920      }
4921
4922      function refreshVideoFilterUi(query) {
4923        var input = backdrop.querySelector("[data-tpc-video-search]");
4924        var results = backdrop.querySelector("[data-tpc-video-results]");
4925        refreshSelectedVideoRows();
4926
4927        if (
4928          input &&
4929          results &&
4930          (!results.hidden || document.activeElement === input)
4931        ) {
4932          renderVideoSearchResults(query || input.value || "");
4933        }
4934      }
4935
4936      function renderCategorySearchResults(query) {
4937        var results = backdrop.querySelector("[data-tpc-category-results]");
4938        var input = backdrop.querySelector("[data-tpc-category-search]");
4939        if (!results || !input) return;
4940
4941        var blockedLines = getRuleLines("toveedo-pc-edit-blocked-categories").map(
4942          normalizeText,
4943        );
4944        var matches = getCategoryFilterOptions()
4945          .filter(function (category) {
4946            return categorySearchMatches(category, query);
4947          })
4948          .slice(0, 20);
4949
4950        results.innerHTML = matches.length
4951          ? categoryRowsHtml(matches, blockedLines)
4952          : '<div class="toveedo-pc-filter-empty">No matching categories.</div>';
4953        results.hidden = false;
4954        input.setAttribute("aria-expanded", "true");
4955      }
4956
4957      function refreshSelectedCategoryRows() {
4958        var selected = backdrop.querySelector("[data-tpc-selected-categories]");
4959        if (!selected) return;
4960
4961        selected.innerHTML = selectedCategoryRowsHtml(
4962          getRuleLines("toveedo-pc-edit-blocked-categories"),
4963        );
4964      }
4965
4966      function refreshCategoryFilterUi(query) {
4967        var input = backdrop.querySelector("[data-tpc-category-search]");
4968        var results = backdrop.querySelector("[data-tpc-category-results]");
4969        refreshSelectedCategoryRows();
4970
4971        if (
4972          input &&
4973          results &&
4974          (!results.hidden || document.activeElement === input)
4975        ) {
4976          renderCategorySearchResults(query || input.value || "");
4977        }
4978      }
4979
4980      function closeVideoSearchResults() {
4981        var results = backdrop.querySelector("[data-tpc-video-results]");
4982        var input = backdrop.querySelector("[data-tpc-video-search]");
4983        if (results) results.hidden = true;
4984        if (input) input.setAttribute("aria-expanded", "false");
4985      }
4986
4987      function closeCategorySearchResults() {
4988        var results = backdrop.querySelector("[data-tpc-category-results]");
4989        var input = backdrop.querySelector("[data-tpc-category-search]");
4990        if (results) results.hidden = true;
4991        if (input) input.setAttribute("aria-expanded", "false");
4992      }
4993
4994      function buildVideoFiltersHtml(rules) {
4995        var videos = getVideoFilterOptions();
4996        var selectedLines = ruleItemsToLines(rules.blockedVideos)
4997          .split(/\n+/)
4998          .map(function (line) {
4999            return line.trim();
5000          })
5001          .filter(Boolean);
5002
5003        return buildRestrictionCard(
5004          "Video Filters",
5005          String(videos.length),
5006          '<div class="toveedo-pc-video-combobox" data-tpc-video-combobox>' +
5007            '<input class="toveedo-pc-input toveedo-pc-video-search" data-tpc-video-search type="search" autocomplete="off" placeholder="Search video titles" aria-label="Search video titles" aria-expanded="false">' +
5008            '<div class="toveedo-pc-video-results" data-tpc-video-results hidden></div>' +
5009            "</div>" +
5010            '<div class="toveedo-pc-video-selected" data-tpc-selected-videos>' +
5011            selectedVideoRowsHtml(selectedLines) +
5012            "</div>",
5013        );
5014      }
5015
5016      function buildCategoryFiltersHtml(rules) {
5017        var categories = getCategoryFilterOptions();
5018        var selectedLines = ruleItemsToLines(rules.blockedCategories)
5019          .split(/\n+/)
5020          .map(function (line) {
5021            return line.trim();
5022          })
5023          .filter(Boolean);
5024
5025        return buildRestrictionCard(
5026          "Categories",
5027          String(categories.length),
5028          '<div class="toveedo-pc-video-combobox" data-tpc-category-combobox>' +
5029            '<input class="toveedo-pc-input toveedo-pc-video-search" data-tpc-category-search type="search" autocomplete="off" placeholder="Search categories" aria-label="Search categories" aria-expanded="false">' +
5030            '<div class="toveedo-pc-video-results" data-tpc-category-results hidden></div>' +
5031            "</div>" +
5032            '<div class="toveedo-pc-video-selected" data-tpc-selected-categories>' +
5033            selectedCategoryRowsHtml(selectedLines) +
5034            "</div>",
5035        );
5036      }
5037
5038      function buildContentRestrictionsHtml(rules) {
5039        return (
5040          '<div class="toveedo-pc-section toveedo-pc-section--restrictions">' +
5041          "<h3>Content Restrictions</h3>" +
5042          hiddenRuleTextarea(
5043            "toveedo-pc-edit-blocked-videos",
5044            ruleItemsToLines(rules.blockedVideos),
5045          ) +
5046          hiddenRuleTextarea(
5047            "toveedo-pc-edit-blocked-categories",
5048            ruleItemsToLines(rules.blockedCategories),
5049          ) +
5050          buildVideoFiltersHtml(rules) +
5051          buildCategoryFiltersHtml(rules) +
5052          "</div>"
5053        );
5054      }
5055
5056      function setRestrictionRowState(row, isBlocked) {
5057        var status = row && row.querySelector("[data-tpc-rule-status]");
5058        if (!row) return;
5059
5060        row.classList.toggle("is-blocked", isBlocked);
5061        row.setAttribute("aria-pressed", isBlocked ? "true" : "false");
5062        if (status) status.textContent = isBlocked ? "Hidden" : "Shown";
5063      }
5064
5065      function optionMatchesRuleLine(option, line) {
5066        if (!option) return false;
5067
5068        return [
5069          option.id,
5070          option.value,
5071          option.permalink,
5072          option.title,
5073          option.label,
5074        ].some(function (candidate) {
5075          return normalizeText(candidate) === normalizeText(line);
5076        });
5077      }
5078
5079      function ruleLineMatchesValue(line, value, targetId) {
5080        if (normalizeText(line) === normalizeText(value)) return true;
5081
5082        if (targetId === "toveedo-pc-edit-blocked-videos") {
5083          return (
5084            optionMatchesRuleLine(findVideoFilterOption(line), value) ||
5085            optionMatchesRuleLine(findVideoFilterOption(value), line)
5086          );
5087        }
5088
5089        if (targetId === "toveedo-pc-edit-blocked-categories") {
5090          return (
5091            optionMatchesRuleLine(findCategoryFilterOption(line), value) ||
5092            optionMatchesRuleLine(findCategoryFilterOption(value), line)
5093          );
5094        }
5095
5096        return false;
5097      }
5098
5099      function toggleRestrictionRule(row) {
5100        var targetId = row.getAttribute("data-tpc-target");
5101        var value = row.getAttribute("data-tpc-value") || "";
5102        var lines = getRuleLines(targetId);
5103        var existingIndex = -1;
5104
5105        lines.some(function (line, index) {
5106          if (!ruleLineMatchesValue(line, value, targetId)) return false;
5107          existingIndex = index;
5108          return true;
5109        });
5110
5111        if (existingIndex >= 0) {
5112          lines.splice(existingIndex, 1);
5113          setRuleLines(targetId, lines);
5114          setRestrictionRowState(row, false);
5115          return;
5116        }
5117
5118        lines.push(value);
5119        setRuleLines(targetId, lines);
5120        setRestrictionRowState(row, true);
5121      }
5122
5123      function renderSetup(errorMessage) {
5124        var body =
5125          '<p style="text-align:center">Create the parent profile and PIN first. You can add family members in the next step.</p>' +
5126          '<div class="toveedo-pc-setup-grid">' +
5127          inputField("Parent name", '<input class="toveedo-pc-input" id="toveedo-pc-setup-name" value="Parent">') +
5128          pinBoxesHtml("toveedo-pc-setup-pin", "Parent PIN") +
5129          pinBoxesHtml("toveedo-pc-setup-pin-confirm", "Confirm PIN") +
5130          "</div>" +
5131          '<p class="toveedo-pc-error ' +
5132          (errorMessage ? "is-visible" : "") +
5133          '">' +
5134          htmlEscape(errorMessage || "") +
5135          "</p>" +
5136          '<div class="toveedo-pc-actions" style="justify-content:center">' +
5137          '<button class="toveedo-pc-button toveedo-pc-button--primary" data-tpc-setup>Create Parent Profile</button>' +
5138          "</div>";
5139        backdrop.innerHTML = frameHtml("Set up profiles", body, false, "toveedo-pc-modal--setup");
5140        focusPinInput("toveedo-pc-setup-pin");
5141      }
5142
5143      function renderChoose(errorMessage) {
5144        if (!workingAccount.parentPinHash || !workingAccount.profiles.length) {
5145          renderSetup(errorMessage);
5146          return;
5147        }
5148
5149        var canClose = Boolean(getActiveProfile(workingAccount, email));
5150        var canManage = activeProfileCanManage();
5151        var addProfileCard = canManage
5152          ? '<button class="toveedo-pc-profile-card toveedo-pc-profile-card--add" data-tpc-add-profile>' +
5153            '<span class="toveedo-pc-avatar">+</span><strong>Add Profile</strong><span class="toveedo-pc-profile-meta">Parent only</span></button>'
5154          : "";
5155        var body =
5156          '<div class="toveedo-pc-profile-grid">' +
5157          workingAccount.profiles
5158            .map(function (profile) {
5159              return (
5160                '<button class="toveedo-pc-profile-card" data-tpc-profile="' +
5161                htmlEscape(profile.id) +
5162                '">' +
5163                '<span class="toveedo-pc-avatar">' +
5164                htmlEscape(profileAvatar(profile)) +
5165                "</span>" +
5166                "<strong>" +
5167                htmlEscape(profileLabel(profile)) +
5168                '</strong><span class="toveedo-pc-profile-meta">' +
5169                htmlEscape(profile.type === "parent" ? "Parent" : "Kid") +
5170                "</span></button>"
5171              );
5172            })
5173            .join("") +
5174          addProfileCard +
5175          "</div>" +
5176          '<p class="toveedo-pc-error ' +
5177          (errorMessage ? "is-visible" : "") +
5178          '">' +
5179          htmlEscape(errorMessage || "") +
5180          "</p>" +
5181          '<div class="toveedo-pc-actions" style="justify-content:center">' +
5182          '<button class="toveedo-pc-button" type="button" data-tpc-manage-profiles>Manage Profiles</button>' +
5183          (canManage
5184            ? '<button class="toveedo-pc-button" type="button" data-tpc-add-profile>Add Profile</button>'
5185            : "") +
5186          "</div>" +
5187          "";
5188        backdrop.innerHTML = frameHtml("Who's watching?", body, canClose);
5189      }
5190
5191      function renderPin(profile, errorMessage) {
5192        var avatarHtml =
5193          '<div class="toveedo-pc-pin-avatar">' +
5194          htmlEscape(profileAvatar(profile)) +
5195          "</div>";
5196        var body =
5197          '<p style="text-align:center">Please enter your 4-digit profile PIN to continue</p>' +
5198          pinBoxesHtml("toveedo-pc-profile-pin", "") +
5199          '<p class="toveedo-pc-error ' +
5200          (errorMessage ? "is-visible" : "") +
5201          '">' +
5202          htmlEscape(errorMessage || "") +
5203          "</p>" +
5204          '<div class="toveedo-pc-actions toveedo-pc-actions--stack">' +
5205          '<button class="toveedo-pc-button toveedo-pc-button--unlock" data-tpc-unlock="' +
5206          htmlEscape(profile.id) +
5207          '">Unlock Profile</button>' +
5208          '<a class="toveedo-pc-link toveedo-pc-link--row" href="#profiles" data-tpc-back>&larr; Back to profiles</a>' +
5209          "</div>";
5210        backdrop.innerHTML = frameHtml(
5211          "Enter PIN for " + profileLabel(profile),
5212          body,
5213          Boolean(getActiveProfile(workingAccount, email)),
5214          "toveedo-pc-modal--pin",
5215          avatarHtml
5216        );
5217        focusPinInput("toveedo-pc-profile-pin");
5218      }
5219
5220      function renderParentGate(errorMessage, nextAction) {
5221        nextAction = nextAction || "add";
5222        var body =
5223          '<p style="text-align:center">Enter the 4-digit parent PIN to add or manage family profiles.</p>' +
5224          pinBoxesHtml("toveedo-pc-parent-manage-pin", "") +
5225          '<p class="toveedo-pc-error ' +
5226          (errorMessage ? "is-visible" : "") +
5227          '">' +
5228          htmlEscape(errorMessage || "") +
5229          "</p>" +
5230          '<div class="toveedo-pc-actions toveedo-pc-actions--stack">' +
5231          '<button class="toveedo-pc-button toveedo-pc-button--unlock" data-tpc-parent-manage="' +
5232          htmlEscape(nextAction) +
5233          '">Continue</button>' +
5234          '<a class="toveedo-pc-link toveedo-pc-link--row" href="#profiles" data-tpc-back>&larr; Back to profiles</a>' +
5235          "</div>";
5236        backdrop.innerHTML = frameHtml("Parent PIN", body, false, "toveedo-pc-modal--pin");
5237        focusPinInput("toveedo-pc-parent-manage-pin");
5238      }
5239
5240      function renderManageProfiles(message, isError) {
5241        var canClose = Boolean(getActiveProfile(workingAccount, email));
5242        var body =
5243          '<div class="toveedo-pc-manage-list">' +
5244          workingAccount.profiles
5245            .map(function (profile) {
5246              return (
5247                '<div class="toveedo-pc-manage-row">' +
5248                '<span class="toveedo-pc-avatar" style="margin:0">' +
5249                htmlEscape(profileAvatar(profile)) +
5250                "</span>" +
5251                '<div class="toveedo-pc-manage-row__body"><strong>' +
5252                htmlEscape(profileLabel(profile)) +
5253                '</strong><span class="toveedo-pc-profile-meta">' +
5254                htmlEscape(profile.type === "parent" ? "Parent" : "Kid") +
5255                "</span></div>" +
5256                '<button class="toveedo-pc-button" type="button" data-tpc-edit-profile="' +
5257                htmlEscape(profile.id) +
5258                '">Edit Settings</button>' +
5259                "</div>"
5260              );
5261            })
5262            .join("") +
5263          "</div>" +
5264          '<p class="toveedo-pc-error ' +
5265          (message && isError ? "is-visible" : "") +
5266          '">' +
5267          htmlEscape(isError ? message : "") +
5268          "</p>" +
5269          (message && !isError ? '<p style="text-align:center;color:#86efac;font-weight:700">' + htmlEscape(message) + "</p>" : "") +
5270          '<div class="toveedo-pc-actions" style="justify-content:center">' +
5271          (activeProfileCanManage()
5272            ? '<button class="toveedo-pc-button toveedo-pc-button--primary" data-tpc-add-profile>Add Profile</button>'
5273            : "") +
5274          '<a class="toveedo-pc-link toveedo-pc-link--row" href="#profiles" data-tpc-back>&larr; Back to profiles</a>' +
5275          "</div>";
5276        backdrop.innerHTML = frameHtml("Manage Profiles", body, canClose);
5277      }
5278
5279      function renderProfileEditor(profileId, message, isError) {
5280        var profile = findWorkingProfile(profileId);
5281        if (!profile) {
5282          renderManageProfiles("Profile no longer exists.", true);
5283          return;
5284        }
5285
5286        normalizeProfile(profile);
5287
5288        var rules = profile.rules || {};
5289        var limits = rules.timeLimits || {};
5290        var canClose = Boolean(getActiveProfile(workingAccount, email));
5291        var avatarHtml =
5292          '<div class="toveedo-pc-pin-avatar">' +
5293          htmlEscape(profileAvatar(profile)) +
5294          "</div>";
5295        var body =
5296          '<div class="toveedo-pc-actions">' +
5297          '<button class="toveedo-pc-button toveedo-pc-button--ghost" t
5297ype="button" data-tpc-manage-profiles>Back to Manage</button>' +
5298          "</div>" +
5299          '<div class="toveedo-pc-section">' +
5300          "<h3>Profile Information</h3>" +
5301          '<div class="toveedo-pc-section-grid">' +
5302          inputField(
5303            "Name",
5304            '<input class="toveedo-pc-input" id="toveedo-pc-edit-name" value="' +
5305              htmlEscape(profile.name || "") +
5306              '">',
5307          ) +
5308          inputField(
5309            "Birthday",
5310            '<input class="toveedo-pc-input" id="toveedo-pc-edit-birthday" type="date" value="' +
5311              htmlEscape(profile.birthday || "") +
5312              '">',
5313          ) +
5314          inputField(
5315            "Profile type",
5316            '<select class="toveedo-pc-select" id="toveedo-pc-edit-type">' +
5317              '<option value="kid"' +
5318              selectedHtml("kid", profile.type || "kid") +
5319              ">Kid</option>" +
5320              '<option value="parent"' +
5321              selectedHtml("parent", profile.type || "kid") +
5322              ">Parent</option>" +
5323              "</select>",
5324          ) +
5325          inputField(
5326            "Max age rating",
5327            '<select class="toveedo-pc-select" id="toveedo-pc-edit-age-rating">' +
5328              ageRatingOptionsHtml(rules.maxAgeRating || "all") +
5329              "</select>",
5330          ) +
5331          "</div>" +
5332          '<div class="toveedo-pc-actions">' +
5333          '<button class="toveedo-pc-button toveedo-pc-button--danger" type="button" data-tpc-delete-profile="' +
5334          htmlEscape(profile.id) +
5335          '">Delete Profile</button>' +
5336          "</div>" +
5337          "</div>" +
5338          '<div class="toveedo-pc-section">' +
5339          "<h3>Profile PIN</h3>" +
5340          pinBoxesHtml("toveedo-pc-edit-pin", "New PIN") +
5341          "</div>" +
5342          buildContentRestrictionsHtml(rules) +
5343          '<div class="toveedo-pc-section">' +
5344          "<h3>Time Limits</h3>" +
5345          '<label class="toveedo-pc-checkbox"><input id="toveedo-pc-edit-time-enabled" type="checkbox"' +
5346          checkedHtml(limits.enabled) +
5347          ">Enable time limits</label>" +
5348          '<div class="toveedo-pc-section-grid">' +
5349          inputField(
5350            "Allowed start",
5351            '<input class="toveedo-pc-input" id="toveedo-pc-edit-time-start" type="time" value="' +
5352              htmlEscape(limits.allowedStart || "08:00") +
5353              '">',
5354          ) +
5355          inputField(
5356            "Allowed end",
5357            '<input class="toveedo-pc-input" id="toveedo-pc-edit-time-end" type="time" value="' +
5358              htmlEscape(limits.allowedEnd || "20:00") +
5359              '">',
5360          ) +
5361          inputField(
5362            "Daily minutes",
5363            '<input class="toveedo-pc-input" id="toveedo-pc-edit-daily-minutes" type="number" min="0" step="15" value="' +
5364              htmlEscape(limits.dailyMinutes || 120) +
5365              '">',
5366          ) +
5367          "</div></div>" +
5368          '<p class="toveedo-pc-error ' +
5369          (message && isError ? "is-visible" : "") +
5370          '">' +
5371          htmlEscape(isError ? message : "") +
5372          "</p>" +
5373          (message && !isError ? '<p style="text-align:center;color:#86efac;font-weight:700">' + htmlEscape(message) + "</p>" : "") +
5374          '<div class="toveedo-pc-actions" style="justify-content:center">' +
5375          '<button class="toveedo-pc-button toveedo-pc-button--primary" type="button" data-tpc-save-profile="' +
5376          htmlEscape(profile.id) +
5377          '">Save Settings</button>' +
5378          '<button class="toveedo-pc-button" type="button" data-tpc-manage-profiles>Back to Manage</button>' +
5379          "</div>";
5380
5381        backdrop.innerHTML = frameHtml(
5382          profileLabel(profile) + " Settings",
5383          body,
5384          canClose,
5385          "",
5386          avatarHtml,
5387        );
5388        focusPinInput("toveedo-pc-edit-pin");
5389      }
5390
5391      function renderFreshProfileEditor(profileId) {
5392        return loadParentalCatalogManifest(true).then(function () {
5393          renderProfileEditor(profileId, "", false);
5394        });
5395      }
5396
5397      function renderAddProfile(message, isError) {
5398        var body =
5399          '<p style="text-align:center">Create another profile for this account.</p>' +
5400          '<div class="toveedo-pc-form-grid">' +
5401          inputField("Name", '<input class="toveedo-pc-input" id="toveedo-pc-new-name" placeholder="Sarah">') +
5402          inputField(
5403            "Profile type",
5404            '<select class="toveedo-pc-select" id="toveedo-pc-new-type"><option value="kid">Kid</option><option value="parent">Parent</option></select>'
5405          ) +
5406          inputField("Birthday", '<input class="toveedo-pc-input" id="toveedo-pc-new-birthday" type="date">') +
5407          pinBoxesHtml("toveedo-pc-new-pin", "Profile PIN") +
5408          "</div>" +
5409          '<p class="toveedo-pc-error ' +
5410          (message && isError ? "is-visible" : "") +
5411          '">' +
5412          htmlEscape(isError ? message : "") +
5413          "</p>" +
5414          (message && !isError ? '<p style="text-align:center;color:#86efac;font-weight:700">' + htmlEscape(message) + "</p>" : "") +
5415          '<div class="toveedo-pc-actions" style="justify-content:center">' +
5416          '<button class="toveedo-pc-button toveedo-pc-button--primary" data-tpc-save-new-profile>Add Profile</button>' +
5417          '<button class="toveedo-pc-button toveedo-pc-button--ghost" data-tpc-finish>Finish</button>' +
5418          '<a class="toveedo-pc-link toveedo-pc-link--row" href="#profiles" data-tpc-back>&larr; Back to profiles</a>' +
5419          "</div>";
5420        backdrop.innerHTML = frameHtml("Add Profile", body, Boolean(getActiveProfile(workingAccount, email)));
5421      }
5422
5423      renderChoose("");
5424      bindPinEntry(backdrop);
5425
5426      backdrop.addEventListener("input", function (event) {
5427        var videoSearch = event.target.closest("[data-tpc-video-search]");
5428        var categorySearch = event.target.closest("[data-tpc-category-search]");
5429
5430        if (videoSearch) {
5431          renderVideoSearchResults(videoSearch.value);
5432          return;
5433        }
5434
5435        if (categorySearch) {
5436          renderCategorySearchResults(categorySearch.value);
5437        }
5438      });
5439
5440      backdrop.addEventListener("focusin", function (event) {
5441        var videoSearch = event.target.closest("[data-tpc-video-search]");
5442        var categorySearch = event.target.closest("[data-tpc-category-search]");
5443
5444        if (videoSearch) {
5445          renderVideoSearchResults(videoSearch.value);
5446          return;
5447        }
5448
5449        if (categorySearch) {
5450          renderCategorySearchResults(categorySearch.value);
5451        }
5452      });
5453
5454      backdrop.addEventListener("keydown", function (event) {
5455        var videoSearch = event.target.closest("[data-tpc-video-search]");
5456        var categorySearch = event.target.closest("[data-tpc-category-search]");
5457        var firstResult = null;
5458        if (!videoSearch && !categorySearch) return;
5459
5460        if (event.key === "Escape") {
5461          if (videoSearch) closeVideoSearchResults();
5462          if (categorySearch) closeCategorySearchResults();
5463          return;
5464        }
5465
5466        if (event.key !== "Enter") return;
5467
5468        firstResult = backdrop.querySelector(
5469          videoSearch
5470            ? "[data-tpc-video-results] [data-tpc-toggle-rule]"
5471            : "[data-tpc-category-results] [data-tpc-toggle-rule]",
5472        );
5473        if (!firstResult) return;
5474
5475        event.preventDefault();
5476        firstResult.click();
5477      });
5478
5479      backdrop.addEventListener("click", function (event) {
5480        var closeButton = event.target.closest("[data-tpc-close]");
5481        if (closeButton) {
5482          closeModal();
5483          return;
5484        }
5485
5486        var finishButton = event.target.closest("[data-tpc-finish]");
5487        if (finishButton) {
5488          closeModal();
5489          return;
5490        }
5491
5492        var backButton = event.target.closest("[data-tpc-back]");
5493        if (backButton) {
5494          event.preventDefault();
5495          renderChoose("");
5496          return;
5497        }
5498
5499        var restrictionRow = event.target.closest("[data-tpc-toggle-rule]");
5500        if (restrictionRow) {
5501          var isVideoRule =
5502            restrictionRow.getAttribute("data-tpc-target") ===
5503            "toveedo-pc-edit-blocked-videos";
5504          var isCategoryRule =
5505            restrictionRow.getAttribute("data-tpc-target") ===
5506            "toveedo-pc-edit-blocked-categories";
5507          event.preventDefault();
5508          toggleRestrictionRule(restrictionRow);
5509          if (isVideoRule) {
5510            refreshVideoFilterUi();
5511          }
5512          if (isCategoryRule) {
5513            refreshCategoryFilterUi();
5514          }
5515          return;
5516        }
5517
5518        if (!event.target.closest("[data-tpc-video-combobox]")) {
5519          closeVideoSearchResults();
5520        }
5521
5522        if (!event.target.closest("[data-tpc-category-combobox]")) {
5523          closeCategorySearchResults();
5524        }
5525
5526        var profileButton = event.target.closest("[data-tpc-profile]");
5527        if (profileButton) {
5528          var profileId = profileButton.getAttribute("data-tpc-profile");
5529          var profile = workingAccount.profiles.find(function (item) {
5530            return item.id === profileId;
5531          });
5532          if (!profile) return;
5533          if (profile.pinHash) {
5534            renderPin(profile, "");
5535            return;
5536          }
5537          setActiveSelection(email, profile.id);
5538          closeModal();
5539          return;
5540        }
5541
5542        if (event.target.closest("[data-tpc-add-profile]")) {
5543          var activeProfile = getActiveProfile(workingAccount, email);
5544          if (activeProfile && activeProfile.type === "parent") {
5545            renderAddProfile("");
5546          } else {
5547            renderChoose("Switch to a parent profile to add profiles.");
5548          }
5549          return;
5550        }
5551
5552        if (event.target.closest("[data-tpc-manage-profiles]")) {
5553          if (activeProfileCanManage()) {
5554            renderManageProfiles("");
5555          } else {
5556            renderParentGate("", "manage");
5557          }
5558          return;
5559        }
5560
5561        var editProfileButton = event.target.closest("[data-tpc-edit-profile]");
5562        if (editProfileButton) {
5563          if (activeProfileCanManage()) {
5564            renderFreshProfileEditor(
5565              editProfileButton.getAttribute("data-tpc-edit-profile"),
5566            );
5567          } else {
5568            renderParentGate(
5569              "",
5570              "edit:" + editProfileButton.getAttribute("data-tpc-edit-profile"),
5571            );
5572          }
5573          return;
5574        }
5575
5576        var unlockButton = event.target.closest("[data-tpc-unlock]");
5577        if (unlockButton) {
5578          var unlockProfile = workingAccount.profiles.find(function (item) {
5579            return item.id === unlockButton.getAttribute("data-tpc-unlock");
5580          });
5581          verifyPin(getPinValue("toveedo-pc-profile-pin"), unlockProfile && unlockProfile.pinHash).then(function (ok) {
5582            if (!ok) {
5583              renderPin(unlockProfile, "Incorrect PIN.");
5584              return;
5585            }
5586            setActiveSelection(email, unlockProfile.id);
5587            closeModal();
5588          });
5589          return;
5590        }
5591
5592        var parentManageButton = event.target.closest("[data-tpc-parent-manage]");
5593        if (parentManageButton) {
5594          var parentManageAction =
5595            parentManageButton.getAttribute("data-tpc-parent-manage") || "add";
5596          verifyPin(getPinValue("toveedo-pc-parent-manage-pin"), workingAccount.parentPinHash).then(function (ok) {
5597            if (!ok) {
5598              renderParentGate("Incorrect parent PIN.", parentManageAction);
5599              return;
5600            }
5601
5602            if (parentManageAction === "manage") {
5603              renderManageProfiles("");
5604              return;
5605            }
5606
5607            if (parentManageAction.indexOf("edit:") === 0) {
5608              renderFreshProfileEditor(parentManageAction.slice(5));
5609              return;
5610            }
5611
5612            renderAddProfile("");
5613          });
5614          return;
5615        }
5616
5617        if (event.target.closest("[data-tpc-setup]")) {
5618          var parentName = (document.getElementById("toveedo-pc-setup-name") || {}).value || "Parent";
5619          var pin = getPinValue("toveedo-pc-setup-pin");
5620          var confirmPin = getPinValue("toveedo-pc-setup-pin-confirm");
5621          if (pin.length !== 4) {
5622            renderSetup("Use a 4-digit parent PIN.");
5623            return;
5624          }
5625          if (pin !== confirmPin) {
5626            renderSetup("The PIN confirmation does not match.");
5627            return;
5628          }
5629          hashPin(pin).then(function (pinHash) {
5630            workingAccount = emptyAccount();
5631            workingAccount.parentPinHash = pinHash;
5632            var parent = emptyProfile("parent");
5633            parent.name = parentName;
5634            parent.pinHash = pinHash;
5635            workingAccount.profiles.push(parent);
5636            setActiveSelection(email, parent.id);
5637            return saveAccount(email, workingAccount)
5638              .then(function () {
5639                renderAddProfile("Parent profile created. Add family members now.", false);
5640              })
5641              .catch(function (error) {
5642                renderSetup(error.message || "Could not save parent profile.");
5643              });
5644          });
5645          return;
5646        }
5647
5648        var deleteProfileButton = event.target.closest("[data-tpc-delete-profile]");
5649        if (deleteProfileButton) {
5650          var deleteProfileId = deleteProfileButton.getAttribute("data-tpc-delete-profile");
5651          var deleteProfile = findWorkingProfile(deleteProfileId);
5652          if (!deleteProfile) {
5653            renderManageProfiles("Profile no longer exists.", true);
5654            return;
5655          }
5656
5657          if (workingAccount.profiles.length < 2) {
5658            renderProfileEditor(deleteProfileId, "Keep at least one profile on this account.", true);
5659            return;
5660          }
5661
5662          if (
5663            deleteProfile.type === "parent" &&
5664            workingAccount.profiles.filter(function (profile) {
5665              return profile.type === "parent" && profile.id !== deleteProfileId;
5666            }).length < 1
5667          ) {
5668            renderProfileEditor(deleteProfileId, "Keep at least one parent profile.", true);
5669            return;
5670          }
5671
5672          if (
5673            !window.confirm(
5674              "Delete " + profileLabel(deleteProfile) + "? This cannot be undone.",
5675            )
5676          ) {
5677            return;
5678          }
5679
5680          workingAccount.profiles = workingAccount.profiles.filter(function (profile) {
5681            return profile.id !== deleteProfileId;
5682          });
5683
5684          if (getActiveSelection(email) === deleteProfileId) {
5685            setActiveSelection(email, workingAccount.profiles[0].id);
5686          }
5687
5688          saveAccount(email, workingAccount)
5689            .then(function () {
5690              ensureSwitcher(workingAccount, email);
5691              renderManageProfiles("Profile deleted.", false);
5692            })
5693            .catch(function (error) {
5694              workingAccount.profiles.push(deleteProfile);
5695              renderProfileEditor(deleteProfileId, error.message || "Could not delete profile.", true);
5696            });
5697          return;
5698        }
5699
5700        var saveProfileButton = event.target.closest("[data-tpc-save-profile]");
5701        if (saveProfileButton) {
5702          var editProfileId = saveProfileButton.getAttribute("data-tpc-save-profile");
5703          var editProfile = findWorkingProfile(editProfileId);
5704          if (!editProfile) {
5705            renderManageProfiles("Profile no longer exists.", true);
5706            return;
5707          }
5708
5709          var editNameInput = document.getElementById("toveedo-pc-edit-name");
5710          var editBirthdayInput = document.getElementById("toveedo-pc-edit-birthday");
5711          var editTypeInput = document.getElementById("toveedo-pc-edit-type");
5712          var editAgeRatingInput = document.getElementById("toveedo-pc-edit-age-rating");
5713          var editTimeEnabledInput = document.getElementById("toveedo-pc-edit-time-enabled");
5714          var editTimeStartInput = document.getElementById("toveedo-pc-edit-time-start");
5715          var editTimeEndInput = document.getElementById("toveedo-pc-edit-time-end");
5716          var editDailyMinutesInput = document.getElementById("toveedo-pc-edit-daily-minutes");
5717          var editName = (editNameInput ? editNameInput.value : "").trim();
5718          var editType = editTypeInput ? editTypeInput.value : editProfile.type || "kid";
5719          var editPin = getPinValue("toveedo-pc-edit-pin");
5720
5721          if (!editName) {
5722            renderProfileEditor(editProfileId, "Enter a profile name.", true);
5723            return;
5724          }
5725
5726          if (editPin && editPin.length !== 4) {
5727            renderProfileEditor(editProfileId, "Use a 4-digit profile PIN.", true);
5728            return;
5729          }
5730
5731          if (editType === "kid" && !editProfile.pinHash && !editPin) {
5732            renderProfileEditor(editProfileId, "Set a 4-digit PIN for kid profiles.", true);
5733            return;
5734          }
5735
5736          if (
5737            editProfile.type === "parent" &&
5738            editType !== "parent" &&
5739            workingAccount.profiles.filter(function (profile) {
5740              return profile.type === "parent" && profile.id !== editProfileId;
5741            }).length < 1
5742          ) {
5743            renderProfileEditor(editProfileId, "Keep at least one parent profile.", true);
5744            return;
5745          }
5746
5747          function persistEditedProfile(pinHash) {
5748            editProfile.name = editName;
5749            editProfile.type = editType;
5750            editProfile.birthday = editBirthdayInput ? editBirthdayInput.value : "";
5751            editProfile.rules = editProfile.rules || {};
5752            editProfile.rules.maxAgeRating = editAgeRatingInput
5753              ? editAgeRatingInput.value
5754              : "all";
5755            editProfile.rules.blockedVideos = textLinesToRuleItems(
5756              (document.getElementById("toveedo-pc-edit-blocked-videos") || {}).value,
5757              "title",
5758            );
5759            editProfile.rules.blockedChannels = [];
5760            editProfile.rules.blockedCategories = textLinesToRuleItems(
5761              (document.getElementById("toveedo-pc-edit-blocked-categories") || {}).value,
5762              "label",
5763            );
5764            editProfile.rules.timeLimits = {
5765              enabled: Boolean(editTimeEnabledInput && editTimeEnabledInput.checked),
5766              allowedStart: editTimeStartInput ? editTimeStartInput.value || "08:00" : "08:00",
5767              allowedEnd: editTimeEndInput ? editTimeEndInput.value || "20:00" : "20:00",
5768              dailyMinutes: Math.max(
5769                0,
5770                Number(editDailyMinutesInput ? editDailyMinutesInput.value : 120) || 0,
5771              ),
5772            };
5773
5774            if (pinHash) {
5775              editProfile.pinHash = pinHash;
5776              if (editProfile.type === "parent") {
5777                workingAccount.parentPinHash = pinHash;
5778              }
5779            }
5780
5781            normalizeProfile(editProfile);
5782
5783            return saveAccount(email, workingAccount)
5784              .then(function () {
5785                ensureSwitcher(workingAccount, email);
5786                renderProfileEditor(editProfileId, "Settings saved.", false);
5787              })
5788              .catch(function (error) {
5789                renderProfileEditor(editProfileId, error.message || "Could not save profile.", true);
5790              });
5791          }
5792
5793          if (editPin) {
5794            hashPin(editPin).then(persistEditedProfile);
5795          } else {
5796            persistEditedProfile("");
5797          }
5798          return;
5799        }
5800
5801        if (event.target.closest("[data-tpc-save-new-profile]")) {
5802          var nameInput = document.getElementById("toveedo-pc-new-name");
5803          var typeInput = document.getElementById("toveedo-pc-new-type");
5804          var birthdayInput = document.getElementById("toveedo-pc-new-birthday");
5805          var newPin = getPinValue("toveedo-pc-new-pin");
5806          var name = (nameInput ? nameInput.value : "").trim();
5807          if (!name) {
5808            renderAddProfile("Enter a profile name.", true);
5809            return;
5810          }
5811          if (newPin.length !== 4) {
5812            renderAddProfile("Use a 4-digit profile PIN.", true);
5813            return;
5814          }
5815          var nextProfile = emptyProfile(typeInput ? typeInput.value : "kid");
5816          nextProfile.name = name;
5817          nextProfile.birthday = birthdayInput ? birthdayInput.value : "";
5818          hashPin(newPin).then(function (pinHash) {
5819            if (pinHash) nextProfile.pinHash = pinHash;
5820            workingAccount.profiles.push(nextProfile);
5821            saveAccount(email, workingAccount)
5822              .then(function () {
5823                renderChoose("");
5824              })
5825              .catch(function (error) {
5826                workingAccount.profiles = workingAccount.profiles.filter(function (profile) {
5827                  return profile.id !== nextProfile.id;
5828                });
5829                renderAddProfile(error.message || "Could not save profile.", true);
5830              });
5831          });
5832        }
5833      });
5834    }
5835
5836    function ensureSwitcher(account, email) {
5837      if (!account) return;
5838      var header = document.querySelector("#website-header");
5839      var host =
5840        header &&
5841        (header.querySelector(".relative.flex") ||
5842          header.querySelector('[data-themeless--header-target="menuNavigation"]') ||
5843          header);
5844      if (!host) return;
5845
5846      state.switcherAccount = account;
5847      state.switcherEmail = email;
5848
5849      var active = getActiveProfile(account, email);
5850      var switcher = document.getElementById(SWITCHER_ID);
5851      if (!switcher) {
5852        switcher = document.createElement("button");
5853        switcher.id = SWITCHER_ID;
5854        switcher.type = "button";
5855        switcher.className = "toveedo-pc-switcher";
5856      }
5857      if (switcher.parentElement !== host) host.appendChild(switcher);
5858      switcher.onclick = function () {
5859        openProfileChooser(account, email, { force: true });
5860      };
5861      var label = active ? profileLabel(active) : account.parentPinHash ? "Choose profile" : "Set up profiles";
5862      switcher.innerHTML =
5863        '<span class="toveedo-pc-trigger-avatar">' +
5864        htmlEscape(active ? profileAvatar(active) : "P") +
5865        '</span><span class="toveedo-pc-trigger-name">' +
5866        htmlEscape(label) +
5867        "</span>";
5868    }
5869
5870    function handleSwitcherClick(event) {
5871      var switcher = document.getElementById(SWITCHER_ID);
5872      if (!switcher) return;
5873
5874      var rect = switcher.getBoundingClientRect();
5875      var padding = 8;
5876      var insideSwitcher =
5877        event.clientX >= rect.left - padding &&
5878        event.clientX <= rect.right + padding &&
5879        event.clientY >= rect.top - padding &&
5880        event.clientY <= rect.bottom + padding;
5881
5882      if (!insideSwitcher) return;
5883
5884      var account = state.switcherAccount;
5885      var email = state.switcherEmail || TEST_USER_EMAIL;
5886      if (!account) return;
5887
5888      event.preventDefault();
5889      event.stopImmediatePropagation();
5890      openProfileChooser(account, email, { force: true });
5891    }
5892
5893    function cssAttributeValue(value) {
5894      return String(value == null ? "" : value)
5895        .replace(/\\/g, "\\\\")
5896        .replace(/"/g, '\\"');
5897    }
5898
5899    function syncBlockedCategoryStyles(profile) {
5900      var style = document.getElementById(BLOCKED_CATEGORY_STYLE_ID);
5901      var ids = [];
5902
5903      if (profile && profile.type !== "parent") {
5904        ids = blockedIndex(profile).categoryIds.filter(Boolean);
5905      }
5906
5907      if (!ids.length) {
5908        if (style) style.remove();
5909        return;
5910      }
5911
5912      if (!style) {
5913        style = document.createElement("style");
5914        style.id = BLOCKED_CATEGORY_STYLE_ID;
5915        document.head.appendChild(style);
5916      }
5917
5918      style.textContent = ids
5919        .map(function (id) {
5920          var escapedId = cssAttributeValue(id);
5921
5922          return (
5923            '.category-group[data-category-id="' +
5924            escapedId +
5925            '"],' +
5926            '#category_id ds-select-option[name="' +
5927            escapedId +
5928            '"],' +
5929            'ds-select[name="category_id"] ds-select-option[name="' +
5930            escapedId +
5931            '"],' +
5932            '#category_id ds-select-option[value="' +
5933            escapedId +
5934            '"],' +
5935            'ds-select[name="category_id"] ds-select-option[value="' +
5936            escapedId +
5937            '"],' +
5938            '#category_id ds-select-option[data-value="' +
5939            escapedId +
5940            '"],' +
5941            'ds-select[name="category_id"] ds-select-option[data-value="' +
5942            escapedId +
5943            '"]{display:none!important;}'
5944          );
5945        })
5946        .join("\n");
5947    }
5948
5949    function ensureFamilyTab() {
5950      if (window.location.pathname.indexOf("/account") !== 0) return;
5951      if (document.querySelector('[data-toveedo-parental-tab="1"]')) return;
5952
5953      var tabHost =
5954        document.querySelector("#profile_form") ||
5955        document.querySelector('[href="/pages/block-videos-page"]') ||
5956        document.querySelector("main") ||
5957        document.body;
5958      var anchorParent = tabHost.closest("div") || tabHost.parentElement || document.body;
5959      var link = document.createElement("button");
5960      link.type = "button";
5961      link.textContent = "Family Profiles";
5962      link.setAttribute("data-toveedo-parental-tab", "1");
5963      link.style.cssText =
5964        "display:inline-flex;align-items:center;min-height:38px;padding:0 14px;margin:8px 8px 8px 0;border-radius:8px;background:#38bdf8;color:#06121f;font-weight:800;text-decoration:none;";
5965      link.addEventListener("click", openCurrentFamilyModal);
5966      anchorParent.insertBefore(link, anchorParent.firstChild);
5967    }
5968
5969    function blockedIndex(profile) {
5970      var rules = (profile && profile.rules) || {};
5971      var items = [].concat(rules.blockedVideos || []);
5972      var categories = rules.blockedCategories || [];
5973      var categoryEntries = categories.map(function (item) {
5974        var lookupValue =
5975          typeof item === "string"
5976            ? item
5977            : item &&
5978              (item.id || item.value || item.permalink || item.label || item.title);
5979
5980        return {
5981          item: item,
5982          manifestCategory: findManifestCategory(lookupValue),
5983        };
5984      });
5985
5986      return {
5987        titles: items.map(function (item) {
5988          return normalizeText(
5989            typeof item === "string" ? item : item && (item.title || item.label),
5990          );
5991        }),
5992        ids: items.map(function (item) {
5993          if (typeof item === "string") return "";
5994          return String(item.id || item.value || "");
5995        }),
5996        permalinks: items.map(function (item) {
5997          if (typeof item === "string") return "";
5998          return normalizeText(item.permalink || "");
5999        }),
6000        categoryIds: categoryEntries.map(function (entry) {
6001          var item = entry.item;
6002          if (typeof item !== "string" && item && (item.id || item.value)) {
6003            return String(item.id || item.value || "");
6004          }
6005
6006          return entry.manifestCategory ? String(entry.manifestCategory.id || "") : "";
6007        }),
6008        categoryLabels: categoryEntries
6009          .map(function (entry) {
6010            var item = entry.item;
6011            var manifestCategory = entry.manifestCategory;
6012            return [
6013              typeof item === "string"
6014                ? item
6015                : item && (item.label || item.title),
6016              item && item.permalink,
6017              manifestCategory && manifestCategory.label,
6018              manifestCategory && manifestCategory.title,
6019              manifestCategory && manifestCategory.permalink,
6020            ];
6021          })
6022          .reduce(function (result, values) {
6023            values.forEach(function (value) {
6024              var normalized = normalizeText(value);
6025              if (normalized) result.push(normalized);
6026            });
6027            return result;
6028          }, [])
6029      };
6030    }
6031
6032    function textHasBlockedTitle(text, index) {
6033      var normalized = normalizeText(text);
6034      return index.titles.some(function (title) {
6035        return title && (normalized === title || normalized.indexOf(title) !== -1);
6036      });
6037    }
6038
6039    function signatureIsBlocked(signature, index) {
6040      var normalized = normalizeText(signature);
6041      return (
6042        index.ids.some(function (id) {
6043          return id && signature.indexOf(id) !== -1;
6044        }) ||
6045        index.permalinks.some(function (permalink) {
6046          return permalink && normalized.indexOf(permalink) !== -1;
6047        }) ||
6048        index.categoryIds.some(function (id) {
6049          return id && signature.indexOf("category_id=" + id) !== -1;
6050        }) ||
6051        index.categoryLabels.some(function (label) {
6052          return label && normalized.indexOf(label) !== -1;
6053        })
6054      );
6055    }
6056
6057    function hideBlockedCards(profile) {
6058      if (!profile || profile.type === "parent") return;
6059
6060      var index = blockedIndex(profile);
6061      var selector = [
6062        '[data-custom="content-card"]',
6063        "swiper-slide[data-card]",
6064        ".card-title",
6065        'a[href*="/programs/"]',
6066        'a[href*="category_id="]'
6067      ].join(",");
6068
6069      document.querySelectorAll(selector).forEach(function (node) {
6070        var card =
6071          node.closest("swiper-slide, [data-custom='content-card'], article, li, .card, .content-card") ||
6072          node;
6073        if (!card || card.getAttribute("data-toveedo-parental-hidden") === "1") return;
6074
6075        var href = node.href || (node.querySelector && node.querySelector("a[href]") ? node.querySelector("a[href]").href : "");
6076        var dataCard = card.getAttribute("data-card") || node.getAttribute("data-card") || "";
6077        var text = node.textContent || card.textContent || "";
6078        var signature = [href, dataCard, text].join(" ");
6079
6080        if (signatureIsBlocked(signature, index) || textHasBlockedTitle(text, index)) {
6081          card.setAttribute("data-toveedo-parental-hidden", "1");
6082        }
6083      });
6084
6085      index.categoryIds.forEach(function (id) {
6086        if (!id) return;
6087        document.querySelectorAll('[data-category-id="' + id.replace(/"/g, "") + '"]').forEach(function (node) {
6088          node.setAttribute("data-toveedo-parental-hidden", "1");
6089        });
6090      });
6091    }
6092
6093    function isProgramRoute() {
6094      return /^\/programs\/[^/]+/.test(window.location.pathname);
6095    }
6096
6097    function currentProgramSlug() {
6098      var match = window.location.pathname.match(/^\/programs\/([^/]+)/);
6099      return match ? decodeURIComponent(match[1]) : "";
6100    }
6101
6102    function fetchCurrentProgram(slug) {
6103      if (!slug) return Promise.resolve(null);
6104      if (!state.contentPromises[slug]) {
6105        state.contentPromises[slug] = fetchJson("/api/contents/" + encodeURIComponent(slug)).catch(function () {
6106          return null;
6107        });
6108      }
6109      return state.contentPromises[slug];
6110    }
6111
6112    function ageFromRating(value) {
6113      var rating = AGE_FILTERS.find(function (item) {
6114        return item.value === value;
6115      });
6116      return rating ? rating.minAge : 0;
6117    }
6118
6119    function extractMinAge(value) {
6120      var text = normalizeText(value);
6121      var match = text.match(/(?:ages?\s*)?(\d{1,2})\s*\+/);
6122      return match ? Number(match[1]) : 0;
6123    }
6124
6125    function profileAge(profile) {
6126      if (!profile || !profile.birthday) return null;
6127      var birthday = new Date(profile.birthday + "T00:00:00");
6128      if (Number.isNaN(birthday.getTime())) return null;
6129      var now = new Date();
6130      var age = now.getFullYear() - birthday.getFullYear();
6131      var beforeBirthday =
6132        now.getMonth() < birthday.getMonth() ||
6133        (now.getMonth() === birthday.getMonth() && now.getDate() < birthday.getDate());
6134      return beforeBirthday ? age - 1 : age;
6135    }
6136
6137    function detailIsBlocked(detail, profile) {
6138      var index = blockedIndex(profile);
6139      var slug = currentProgramSlug();
6140      var manifestVideo = findManifestVideo(slug);
6141      var titleNode = document.querySelector('h1[data-area="program-title"], h1');
6142      var title =
6143        (detail && (detail.title || detail.name)) ||
6144        (manifestVideo && manifestVideo.title) ||
6145        (titleNode ? titleNode.textContent : "");
6146      var id =
6147        (detail && (detail.id || detail.content_id || detail.contentId)) ||
6148        (manifestVideo && manifestVideo.id);
6149      var categories =
6150        (detail && (detail.categories || detail.category || detail.tags)) ||
6151        (manifestVideo &&
6152          (manifestVideo.categoryLabels || []).concat(
6153            manifestVideo.categoryIds || [],
6154          )) ||
6155        [];
6156      var categoryText = Array.isArray(categories)
6157        ? categories
6158            .map(function (item) {
6159              return typeof item === "string" ? item : item && (item.title || item.name || item.label || item.id);
6160            })
6161            .join(" ")
6162        : String(categories || "");
6163      var age = Math.max(
6164        extractMinAge(title),
6165        extractMinAge(categoryText),
6166        extractMinAge(detail && JSON.stringify(detail))
6167      );
6168      var signature = [
6169        slug,
6170        title,
6171        id || "",
6172        manifestVideo && manifestVideo.permalink,
6173        categoryText,
6174      ].join(" ");
6175
6176      if (signatureIsBlocked(signature, index) || textHasBlockedTitle(title, index)) return true;
6177
6178      if (age) {
6179        var childAge = profileAge(profile);
6180        var ratingCap = ageFromRating(profile.rules && profile.rules.maxAgeRating);
6181        if (childAge != null && childAge < age) return true;
6182        if (ratingCap && age > ratingCap) return true;
6183      }
6184
6185      return false;
6186    }
6187
6188    function pauseMedia() {
6189      document.querySelectorAll("video, audio").forEach(function (media) {
6190        if (media && typeof media.pause === "function") media.pause();
6191      });
6192    }
6193
6194    function showBlockedModal(message) {
6195      if (isParentalModalSuppressedRoute()) {
6196        dismissParentalModal();
6197        return;
6198      }
6199
6200      pauseMedia();
6201      var existing = document.getElementById(MODAL_ID);
6202      if (existing) existing.remove();
6203      var backdrop = document.createElement("div");
6204      backdrop.id = MODAL_ID;
6205      backdrop.className = "toveedo-pc-backdrop";
6206      backdrop.innerHTML =
6207        '<div class="toveedo-pc-modal toveedo-pc-modal--blocked" role="dialog" aria-modal="true" aria-label="Content blocked">' +
6208        '<div class="toveedo-pc-modal__body toveedo-pc-stack">' +
6209        "<div><h2>Content unavailable</h2><p>" +
6210        htmlEscape(message || "This profile is not allowed to view this content.") +
6211        "</p></div>" +
6212        '<div class="toveedo-pc-actions">' +
6213        '<button class="toveedo-pc-button toveedo-pc-button--primary" data-tpc-switch>Switch profile</button>' +
6214        '<a class="toveedo-pc-button" href="/catalog">Back to catalog</a>' +
6215        "</div></div></div>";
6216      document.body.appendChild(backdrop);
6217      backdrop.addEventListener("click", function (event) {
6218        if (!event.target.closest("[data-tpc-switch]")) return;
6219        if (state.switcherAccount) {
6220          openProfileChooser(
6221            state.switcherAccount,
6222            state.switcherEmail || TEST_USER_EMAIL,
6223            { force: true }
6224          );
6225        }
6226      });
6227    }
6228
6229    function guardProgramRoute(profile) {
6230      if (!profile || profile.type === "parent" || !isProgramRoute()) return;
6231      if (detailIsBlocked(null, profile)) {
6232        showBlockedModal("This item is blocked for the selected profile.");
6233        return;
6234      }
6235      var slug = currentProgramSlug();
6236      fetchCurrentProgram(slug).then(function (detail) {
6237        if (detail && detailIsBlocked(detail, profile)) {
6238          showBlockedModal("This item is blocked for the selected profile.");
6239        }
6240      });
6241    }
6242
6243    function minutesFromTime(value) {
6244      var parts = String(value || "00:00").split(":");
6245      return Number(parts[0] || 0) * 60 + Number(parts[1] || 0);
6246    }
6247
6248    function nowMinutes() {
6249      var now = new Date();
6250      return now.getHours() * 60 + now.getMinutes();
6251    }
6252
6253    function isInsideTimeWindow(start, end) {
6254      var current = nowMinutes();
6255      var startMinutes = minutesFromTime(start || "00:00");
6256      var endMinutes = minutesFromTime(end || "23:59");
6257      if (startMinutes <= endMinutes) return current >= startMinutes && current <= endMinutes;
6258      return current >= startMinutes || current <= endMinutes;
6259    }
6260
6261    function usageKey(profile) {
6262      var today = new Date();
6263      var month = String(today.getMonth() + 1).padStart(2, "0");
6264      var day = String(today.getDate()).padStart(2, "0");
6265      return profile.id + ":" + today.getFullYear() + "-" + month + "-" + day;
6266    }
6267
6268    function getUsageSeconds(profile) {
6269      return Number(state.usageSeconds[usageKey(profile)] || 0);
6270    }
6271
6272    function addUsageSeconds(profile, seconds) {
6273      state.usageSeconds[usageKey(profile)] = getUsageSeconds(profile) + seconds;
6274    }
6275
6276    function findPlayingMedia() {
6277      var media = Array.from(document.querySelectorAll("video, audio")).find(function (item) {
6278        return item && !item.paused && !item.ended;
6279      });
6280      if (media) return media;
6281      var players = document.querySelectorAll("video-player, uscreen-video-player");
6282      for (var index = 0; index < players.length; index += 1) {
6283        var root = players[index].shadowRoot;
6284        var nested = root && root.querySelector("video");
6285        if (nested && !nested.paused && !nested.ended) return nested;
6286      }
6287      return null;
6288    }
6289
6290    function timeLimitMessage(profile) {
6291      var limits = profile.rules && profile.rules.timeLimits;
6292      if (!limits || !limits.enabled) return "";
6293      if (!isInsideTimeWindow(limits.allowedStart, limits.allowedEnd)) {
6294        return "This profile is outside its allowed viewing hours.";
6295      }
6296      var allowance = Number(limits.dailyMinutes || 0) * 60;
6297      if (allowance > 0 && getUsageSeconds(profile) >= allowance) {
6298        return "This profile reached its daily viewing limit.";
6299      }
6300      return "";
6301    }
6302
6303    function trackTimeLimits(profile) {
6304      if (state.timeProfileId === (profile && profile.id)) return;
6305      if (state.timeTicker) clearInterval(state.timeTicker);
6306      state.timeTicker = null;
6307      state.timeProfileId = profile && profile.id ? profile.id : "";
6308      state.lastUsageTickAt = Date.now();
6309
6310      if (!profile || profile.type === "parent" || !(profile.rules && profile.rules.timeLimits && profile.rules.timeLimits.enabled)) return;
6311
6312      state.timeTicker = setInterval(function () {
6313        var message = timeLimitMessage(profile);
6314        if (message) {
6315          showBlockedModal(message);
6316          return;
6317        }
6318
6319        if (!findPlayingMedia()) {
6320          state.lastUsageTickAt = Date.now();
6321          return;
6322        }
6323
6324        var now = Date.now();
6325        var elapsed = Math.min(30, Math.max(0, Math.round((now - state.lastUsageTickAt) / 1000)));
6326        state.lastUsageTickAt = now;
6327        if (elapsed) addUsageSeconds(profile, elapsed);
6328
6329        message = timeLimitMessage(profile);
6330        if (message) showBlockedModal(message);
6331      }, 15000);
6332
6333      var initialMessage = timeLimitMessage(profile);
6334      if (initialMessage && isProgramRoute()) showBlockedModal(initialMessage);
6335    }
6336
6337    function isPurchaseRoute() {
6338      return /\/checkout|\/orders|\/complete_order|\/payments|\/gift/.test(window.location.pathname);
6339    }
6340
6341    function purchaseUnlockKey() {
6342      return window.location.pathname + window.location.search;
6343    }
6344
6345    function showPurchaseGate(account) {
6346      if (isParentalModalSuppressedRoute()) {
6347        dismissParentalModal();
6348        return;
6349      }
6350      if (!account.parentPinHash) return;
6351
6352      var existing = document.getElementById(MODAL_ID);
6353      if (existing) return;
6354
6355      var backdrop = document.createElement("div");
6356      backdrop.id = MODAL_ID;
6357      backdrop.className = "toveedo-pc-backdrop";
6358      backdrop.innerHTML =
6359        '<div class="toveedo-pc-modal toveedo-pc-modal--pin" role="dialog" aria-modal="true" aria-label="Parent PIN required">' +
6360        '<div class="toveedo-pc-modal__body toveedo-pc-stack">' +
6361        "<div><h2>Parent PIN required</h2><p>Enter the parent PIN to continue checkout or make a purchase.</p></div>" +
6362        pinBoxesHtml("toveedo-pc-parent-pin", "") +
6363        '<p class="toveedo-pc-error" id="toveedo-pc-parent-pin-error">Incorrect parent PIN.</p>' +
6364        '<div class="toveedo-pc-actions" style="justify-content:center">' +
6365        '<button class="toveedo-pc-button toveedo-pc-button--unlock" data-tpc-parent-unlock>Continue</button>' +
6366        '<a class="toveedo-pc-button" href="/catalog">Back to catalog</a>' +
6367        "</div></div></div>";
6368      document.body.appendChild(backdrop);
6369      bindPinEntry(backdrop);
6370      focusPinInput("toveedo-pc-parent-pin");
6371      backdrop.addEventListener("click", function (event) {
6372        if (!event.target.closest("[data-tpc-parent-unlock]")) return;
6373        verifyPin(getPinValue("toveedo-pc-parent-pin"), account.parentPinHash).then(function (ok) {
6374          if (!ok) {
6375            var error = document.getElementById("toveedo-pc-parent-pin-error");
6376            if (error) error.classList.add("is-visible");
6377            return;
6378          }
6379          state.purchaseUnlocks[purchaseUnlockKey()] = true;
6380          backdrop.remove();
6381        });
6382      });
6383    }
6384
6385    function enforcePurchaseProtection(account, profile) {
6386      if (isParentalModalSuppressedRoute()) return;
6387      if (!profile || profile.type !== "kid") return;
6388      if (!isPurchaseRoute()) return;
6389      if (state.purchaseUnlocks[purchaseUnlockKey()] === true) return;
6390      showPurchaseGate(account);
6391    }
6392
6393    function isPurchaseTrigger(target) {
6394      if (!target || !target.closest) return false;
6395      return Boolean(
6396        target.closest('a[href*="/checkout"], a[href*="/orders"], a[href*="/gift"]') ||
6397          (isPurchaseRoute() &&
6398            target.closest('button[type="submit"], input[type="submit"], #submit-button, ds-button#submit-button'))
6399      );
6400    }
6401
6402    function handlePurchaseClick(event) {
6403      if (isParentalModalSuppressedRoute()) return;
6404      if (!isPurchaseTrigger(event.target)) return;
6405
6406      var account = state.switcherAccount;
6407      var email = state.switcherEmail || TEST_USER_EMAIL;
6408      var active = account && getActiveProfile(account, email);
6409      if (!active || active.type !== "kid" || state.purchaseUnlocks[purchaseUnlockKey()] === true) return;
6410      event.preventDefault();
6411      event.stopImmediatePropagation();
6412      showPurchaseGate(account);
6413    }
6414
6415    function applyRules(account, email) {
6416      if (!account) return;
6417      ensureFamilyTab();
6418      ensureSwitcher(account, email);
6419      if (isParentalModalSuppressedRoute()) {
6420        dismissParentalModal();
6421        syncBlockedCategoryStyles(null);
6422        trackTimeLimits(null);
6423        return;
6424      }
6425
6426      if (!account.parentPinHash || !account.profiles.length) {
6427        syncBlockedCategoryStyles(null);
6428        openProfileChooser(account, email);
6429        return;
6430      }
6431
6432      openProfileChooser(
6433        account,
6434        email,
6435        shouldConfirmOnCatalog(email) ? { catalogConfirm: true } : {}
6436      );
6437
6438      var active = getActiveProfile(account, email);
6439      if (!active) return;
6440      syncBlockedCategoryStyles(active);
6441      hideBlockedCards(active);
6442      guardProgramRoute(active);
6443      enforcePurchaseProtection(account, active);
6444      trackTimeLimits(active);
6445    }
6446
6447    function openCurrentFamilyModal() {
6448      getCurrentUser().then(function (user) {
6449        if (!isEnabledUser(user)) return;
6450        var account = getAccountForUser(user, TEST_USER_EMAIL);
6451        ensureFamilyTab();
6452        ensureSwitcher(account, TEST_USER_EMAIL);
6453        openProfileChooser(account, TEST_USER_EMAIL, { force: true });
6454      });
6455    }
6456
6457    function scheduleSync() {
6458      hideField3();
6459      if (state.syncFrame) return;
6460      state.syncFrame = window.requestAnimationFrame(function () {
6461        state.syncFrame = 0;
6462        syncFeatures();
6463      });
6464    }
6465
6466    function syncFeatures() {
6467      hideField3();
6468      getCurrentUser().then(function (user) {
6469        if (isEnabledUser(user)) {
6470          loadParentalCatalogManifest().then(function () {
6471            var account = getAccountForUser(user, TEST_USER_EMAIL);
6472            applyRules(account, TEST_USER_EMAIL);
6473          });
6474          return;
6475        }
6476
6477        if (user && getUserEmail(user)) return;
6478      });
6479    }
6480
6481    function resetIdentityCache() {
6482      state.sessionPromise = null;
6483      state.userPromise = null;
6484    }
6485
6486    function startObserver() {
6487      if (state.observer || !document.documentElement) return;
6488      state.observer = new MutationObserver(function () {
6489        hideField3();
6490        scheduleSync();
6491      });
6492      state.observer.observe(document.documentElement, { childList: true, subtree: true });
6493    }
6494
6495    function init() {
6496      clearLegacyParentalStorage();
6497      hideField3();
6498      startObserver();
6499      loadParentalCatalogManifest().then(scheduleSync);
6500      scheduleSync();
6501    }
6502
6503    document.addEventListener("click", handlePurchaseClick, true);
6504    document.addEventListener("click", handleSwitcherClick, true);
6505    document.addEventListener("toveedo:open-parental-control", openCurrentFamilyModal);
6506    document.addEventListener("turbo:load", function () {
6507      resetIdentityCache();
6508      scheduleSync();
6509    });
6510    document.addEventListener("turbo:render", scheduleSync);
6511    document.addEventListener("turbo:frame-load", scheduleSync);
6512    window.addEventListener("pageshow", function () {
6513      resetIdentityCache();
6514      scheduleSync();
6515    });
6516
6517    if (document.readyState === "loading") {
6518      document.addEventListener("DOMContentLoaded", init, { once: true });
6519    } else {
6520      init();
6521    }
6522  })();
6523</script>
6523
6524<!-- 
6524<script id="ze-snippet" src="https://static.zdassets.com/ekr/snippet.js?key=998791a4-73b2-4f32-973f-e1b10c144bc6"> </script>
6524 -->
6525
6526<!-- REFERSION TRACKING: BEGIN -->
6527<!-- 
6527<script src="//www.refersion.com/tracker/v3/pub_c7986d812f548f3be371.js"></script>
vendor: 1 bytes, line 6527
6527
6528<script>_refersion();</script>
6528 -->
6529<!-- REFERSION TRACKING: END -->
6530
6531<!-- <style>
6532  /* temp fix attempt center logo in reduce churn page */
6533  body > div.px-2.md\:px-0.root > div.logo-area > div {
6534    justify-content: center;
6535  }
6536</style> -->
6537
6538
6539  </head>
6540  <body
6541    dir="ltr"
6542    class="light themeless group/body min-h-screen flex flex-col catalog-constrained"
6543  >
6544    
6545    <turbo-frame id="website_modal"></turbo-frame>    <div id="flash_messages">
6546</div>
6547
6548      <div class="sticky top-0 z-[100]">
6549
6550
6551
6552        
6553 
6554        
6555        <header id="website-header"
6556  class="sticky top-0 z-[100] flex bg-ds-main h-20 border-b border-ds-default"
6557  data-controller="themeless--header"
6558>
6559  <div class="container flex justify-between items-center my-auto">
6560    <div class="flex justify-start w-[8.75rem] flex-none">
6561      <a class="max-w-36 me-auto text-sm md:text-base text-ds-default" id="store-logo" data-type="main_logo" href="/">
6562          <img alt="Toveedo" src="https://alpha.uscreencdn.com/images/logotypes/662/null_2fk3gmtm2vrzkxuqp7burq_toveedo-blue.png" />
6563</a>    </div>
6564
6565    <nav id="website-links" class="h-full min-w-0 mx-auto hidden md:flex justify-center -mb-px" data-themeless--header-target="navigation">
6566      <ul class="h-full flex justify-start space-x-4 invisible" data-themeless--header-target="navigationLinks">
6567
6568          <li class="relative group/item">
6569            <a class="flex items-center min-w-max overflow-y-hidden text-center px-4 pt-8 pb-7 h-full border-b border-b-4 hover:text-primary font-medium border-transparent text-ds-default" target="_self" data-type="home" href="/"><span class="flex items-center"><span>Home</span></span></a>
6570          </li>
6571
6572          <li class="relative group/item">
6573            <a class="flex items-center min-w-max overflow-y-hidden text-center px-4 pt-8 pb-7 h-full border-b border-b-4 hover:text-primary font-medium border-transparent text-ds-default" target="_self" href="https://toveedo.com/playlists"><span class="flex items-center"><span>Playlists</span></span></a>
6574          </li>
6575      </ul>
6576    </nav>
6577
6578    <div class="flex gap-x-2 items-center justify-end relative flex-none">
6579
6580
6581      <ds-button style="--font-size: var(--font-size-4-5)" class="hidden lg:block" size="big" variant="regular" href="/sign_in">Sign in</ds-button>
6582          <ds-button style="--font-size: var(--font-size-4-5)" size="big" variant="primary" href="/join">Join</ds-button>
6583
6584    <div class="relative flex items-center">
6585      <input type="checkbox" id="menu-toggle" class="peer hidden" data-themeless--header-target="toggle" data-action="change->themeless--header#onMenuToggle">
6586      <label for="menu-toggle" class="overlay hidden peer-checked:block fixed inset-0 "></label>
6587      <label for="menu-toggle" class="cursor-pointer flex items-center justify-center p-2 rounded bg-ds-subtle hover:opacity-80 lg:hidden w-12"
6588        data-themeless--header-target="toggleBurger"
6589      >
6590        <ds-icon class="text-ds-default block p-1" name="burger" size="24"></ds-icon>
6591        <ds-icon class="text-ds-default hidden p-1" name="cross" size="24"></ds-icon>
6592      </label>
6593
6594      <div id="main-menu" class="invisible" data-themeless--header-target="menu">
6595        <div class="overflow-hidden relative box-border h-full flex w-full">
6596          <nav class="h-auto max-h-full w-full min-h-0 overflow-y-auto px-4 py-2 border-ds-default" data-themeless--header-target="menuNavigation">
6597            <ul class="flex flex-col space-y-1">
6598                <li class="text-base md:text-sm font-normal leading-tight md:leading-none">
6599                  <a class="block py-2 h-10 md:h-8 hover:underline" href="/sign_in">Sign in</a>
6600                </li>
6601                <li class="text-base md:text-sm font-normal leading-tight md:leading-none">
6602                  <a class="block py-2 min-h-10 md:min-h-8 hover:underline underline-offset-2" target="_self" data-type="home" href="/"><span class="flex items-center justify-items-stretch"><span>Home</span></span></a>
6603                </li>
6604                <li class="text-base md:text-sm font-normal leading-tight md:leading-none">
6605                  <a class="block py-2 min-h-10 md:min-h-8 hover:underline underline-offset-2" target="_self" href="https://toveedo.com/playlists"><span class="flex items-center justify-items-stretch"><span>Playlists</span></span></a>
6606                </li>
6607              <ds-viewport data-action="change->themeless--header#onScrollAnchorChange">
6608                <div class="w-full h-[1px]"></div>
6609              </ds-viewport>
6610            </ul>
6611          </nav>
6612          <div aria-hidden="true" class="absolute top-0 left-0 right-0 bottom-0 pointer-events-none opacity-1 translate-y-0 aria-hidden:translate-y-10 aria-hidden:opacity-0 transition-all" style="box-shadow: 0px -60px 30px -32px var(--ds-bg-overlay) inset;" data-themeless--header-target="menuNavigationScrollShadow"></div>
6613        </div>
6614        <div class="p-4 border-ds-default border-t bg-ds-overlay text-xs font-normal">
6615          <div class="flex flex-wrap gap-y-2">
6616              <a class="block w-full mb-2 text-primary hover:underline underline-offset-2" data-turbo="true" data-turbo-frame="website_modal" href="/about/apps">Get the app -&gt;</a>
6617              <a class="text-ds-muted text-sm md:text-[11px]" href="/terms">
6618                <span class="hover:underline underline-offset-2">Terms</span>
6619</a>              <span class="flex items-center font-medium mx-1 last:hidden">∙</span>
6620              <a class="text-ds-muted text-sm md:text-[11px]" href="/privacy">
6621                <span class="hover:underline underline-offset-2">Privacy</span>
6622</a>              <span class="flex items-center font-medium mx-1 last:hidden">∙</span>
6623              <a class="text-ds-muted text-sm md:text-[11px]" href="/pages/faq">
6624                <span class="hover:underline underline-offset-2">FAQ</span>
6625</a>              <span class="flex items-center font-medium mx-1 last:hidden">∙</span>
6626              <a class="text-ds-muted text-sm md:text-[11px]" href="/gift_cards/new">
6627                <span class="hover:underline underline-offset-2">Buy gift card</span>
6628</a>              <span class="flex items-center font-medium mx-1 last:hidden">∙</span>
6629              <a class="text-ds-muted text-sm md:text-[11px]" href="/gift_card_redemptions/new">
6630                <span class="hover:underline underline-offset-2">Claim gift card</span>
6631</a>              <span class="flex items-center font-medium mx-1 last:hidden">∙</span>
6632          </div>
6633        </div>
6634      </div>
6635    </div>
6636  </div>
6637  </div>
6638</header>
6639
6640
6641      </div>
6642
6643        <div class="w-full border-b border-ds-default bg-ds-main overflow-x-auto z-[20]">
6644    <div class="flex w-max min-w-full justify-center p-4 gap-2">
6645        <a class="text-ds-default bg-ds-subtle px-3 py-1.5 gap-2 flex items-center rounded-lg hover:bg-primary hover:text-ds-inverted transition-colors duration-200 shrink-0" href="/catalog" onclick="window.CatalogAnalytics('clickOnWebSection', 'browse')">
6646            <ds-icon name="globe" size="16px"></ds-icon>
6647            Browse
6648        </a>
6649        <a class="text-ds-default bg-ds-subtle px-3 py-1.5 gap-2 flex items-center rounded-lg hover:bg-primary hover:text-ds-inverted transition-colors duration-200 shrink-0" href="/favorites" onclick="window.CatalogAnalytics('clickOnWebSection', 'favorites')">
6650            <ds-icon name="heart-outlined" size="16px"></ds-icon>
6651
6652            Favorites
6653        </a>
6654        <a class="text-ds-default bg-ds-subtle px-3 py-1.5 gap-2 flex items-center rounded-lg hover:bg-primary hover:text-ds-inverted transition-colors duration-200 shrink-0 !bg-primary !text-ds-inverted" href="/playlists" onclick="window.CatalogAnalytics('clickOnWebSection', 'playlists')">
6655            <ds-icon name="play-list" size="16px"></ds-icon>
6656
6657            Playlists
6658        </a>
6659        <a class="text-ds-default bg-ds-subtle px-3 py-1.5 gap-2 flex items-center rounded-lg hover:bg-primary hover:text-ds-inverted transition-colors duration-200 shrink-0" href="/watch_history" onclick="window.CatalogAnalytics('clickOnWebSection', 'watch_history')">
6660            <ds-icon name="clock" size="16px"></ds-icon>
6661
6662            Watch history
6663        </a>
6664    </div>
6665  </div>
6666
6667
6668      <main class="flex-1 bg-ds-default relative" data-controller="catalog-scroll-position">
6669        <turbo-frame data-turbo-prefetch="false" id="playlists_section">
6670  <div hidden="hidden" data-controller="scrat-analytics" data-scrat-analytics-category-value="playlists" data-scrat-analytics-event-value="view_playlists"></div>
6671  
6672<div class="bg-ds-inset">
6673  <div class="container">
6674    <div class="flex justify-between items-start py-9">
6675      <h1 class="text-ds-title-1-semi-bold">
6676        Playlists
6677      </h1>
6678
6679      
6680
6681    </div>
6682  </div>
6683</div>
6684  <div class="container" id="playlists_container">
6685      
6686<div class="flex flex-col items-center justify-center text-center mx-auto py-12 md:py-24 max-w-96 h-full">
6687  <svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 96 96" fill="none" class="block dark:hidden">
6688  <path d="M35.1963 29.5L35.2012 29.6025C35.2525 30.1067 35.6786 30.5 36.1963 30.5H38.2656C38.8409 30.5 39.4066 30.5706 39.9521 30.7061C40.4679 30.8341 40.9882 30.5362 41.1455 30.0361C41.7355 30.2638 42.2963 30.5612 42.8164 30.9209C42.4918 31.3322 42.5388 31.9309 42.9346 32.2852C43.3534 32.6601 43.7302 33.0878 44.0537 33.5635L44.9883 34.9385C45.2988 35.395 45.9213 35.5136 46.3779 35.2031V35.2021L47.1211 36.2969H47.1221C46.6654 36.6074 46.5469 37.2298 46.8574 37.6865L47.792 39.0605C48.2078 39.672 48.6926 40.2227 49.2314 40.7051C49.6429 41.0734 50.2752 41.0384 50.6436 40.627C50.6574 40.6115 50.6689 40.5942 50.6816 40.5781C51.2019 40.9381 51.7633 41.235 52.3535 41.4629C52.3472 41.4828 52.341 41.5029 52.3359 41.5234C52.2029 42.0594 52.5295 42.6013 53.0654 42.7344C53.7673 42.9087 54.495 43 55.2344 43H57.9395C58.4569 42.9998 58.8823 42.6065 58.9336 42.1025L58.9395 42H62.3486L62.3535 42.1025C62.4049 42.6067 62.831 43 63.3486 43H68.7578C69.2754 42.9999 69.7006 42.6066 69.752 42.1025L69.7578 42H73.167L73.1719 42.1025C73.2232 42.6067 73.6493 43 74.167 43H76.8711C77.9789 43 79.0114 43.252 79.9248 43.6953C80.4024 43.9271 80.9717 43.7438 81.2295 43.2881C82.6967 44.2445 83.8182 45.6648 84.4092 47.3135C83.9065 47.4589 83.5971 47.9722 83.7119 48.4902C83.9041 49.3574 83.9332 50.2791 83.7656 51.2178L83.6816 51.6211L82.9072 54.8711C82.7793 55.4084 83.1112 55.9482 83.6484 56.0762L82.5645 60.6299C82.0272 60.502 81.4874 60.8339 81.3594 61.3711L79.8125 67.8711C79.6846 68.4081 80.0159 68.947 80.5527 69.0752L79.4688 73.6299C78.965 73.5101 78.4594 73.7946 78.293 74.2734L78.2646 74.3711L77.4912 77.6211C77.329 78.3024 77.0703 78.9398 76.7324 79.5205L76.583 79.7656C76.2975 80.2129 76.4127 80.8003 76.835 81.1094C76.1193 81.9706 75.2301 82.6731 74.2266 83.1699C74.0238 82.6875 73.4788 82.4391 72.9775 82.6133C72.2549 82.8644 71.481 83 70.6807 83H67.6299C67.0777 83.0001 66.6299 83.4478 66.6299 84H62.5283C62.5283 83.4478 62.0804 83.0002 61.5283 83H55.4258C54.8735 83 54.4258 83.4477 54.4258 84H50.3232C50.3232 83.4477 49.8755 83 49.3232 83H43.2217C42.6694 83 42.2217 83.4477 42.2217 84H38.1191C38.1191 83.4477 37.6714 83 37.1191 83H31.0176C30.4653 83 30.0176 83.4477 30.0176 84H25.915C25.915 83.4477 25.4673 83 24.915 83H21.8643C20.7741 83 19.7558 82.7549 18.8516 82.3232C18.3727 82.0948 17.8038 82.2814 17.5488 82.7383C16.1051 81.8103 14.9887 80.4353 14.3789 78.8311C14.8794 78.6763 15.1796 78.1577 15.0547 77.6416C14.8191 76.6679 14.7896 75.6212 15.0146 74.5547L15.6924 71.3467C15.8064 70.8063 15.4603 70.2752 14.9199 70.1611L14.9189 70.1602L15.8604 65.7012L15.8613 65.7021C16.4016 65.816 16.9319 65.47 17.0459 64.9297L18.4004 58.5127C18.5141 57.9725 18.1682 57.4421 17.6279 57.3281L17.627 57.3271L18.5684 52.8672L18.5693 52.8682C19.0759 52.9749 19.5733 52.6781 19.7275 52.1953L19.7539 52.0967L21.1084 45.6797C21.2223 45.1394 20.8762 44.6092 20.3359 44.4951L20.335 44.4941L21.2764 40.0342L21.2773 40.0352C21.8176 40.149 22.3479 39.803 22.4619 39.2627L23.1387 36.0547C23.3073 35.2555 23.6081 34.5134 24.0146 33.8486C24.2916 33.3956 24.1644 32.8103 23.7354 32.5098C24.4561 31.6075 25.3649 30.8705 26.3965 30.3516C26.6019 30.8334 27.148 31.0787 27.6484 30.9014C28.3828 30.6408 29.1715 30.5 29.9883 30.5H32.0576C32.5752 30.4999 33.0014 30.1066 33.0527 29.6025L33.0576 29.5H35.1963Z" fill="#F5F5F5" stroke="#E5E5E5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 6"></path>
6689  <rect x="51.238" y="18.3378" width="34" height="43" rx="3" transform="rotate(26.0751 51.238 18.3378)" fill="white" stroke="#E5E5E5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 6"></rect>
6690  <path d="M53.5508 27.2626L73.3116 36.9327" stroke="#E5E5E5" stroke-width="2" stroke-linecap="round" stroke-dasharray="4 4"></path>
6691  <path d="M50.9131 32.6519L70.6739 42.322" stroke="#E5E5E5" stroke-width="2" stroke-linecap="round" stroke-dasharray="4 4"></path>
6692  <path d="M48.2754 38.0412L68.0362 47.7113" stroke="#E5E5E5" stroke-width="2" stroke-linecap="round" stroke-dasharray="4 4"></path>
6693  <path d="M45.6387 43.4305L65.3995 53.1006" stroke="#E5E5E5" stroke-width="2" stroke-linecap="round" stroke-dasharray="4 4"></path>
6694  <path d="M43.001 48.8199L53.7796 54.0944" stroke="#E5E5E5" stroke-width="2" stroke-linecap="round" stroke-dasharray="4 4"></path>
6695  <rect x="11.9816" y="22.1959" width="34" height="43" rx="3" transform="rotate(-13.0752 11.9816 22.1959)" fill="white" stroke="#E5E5E5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 6"></rect>
6696  <path d="M19.4092 27.6571L40.8388 22.68" stroke="#E5E5E5" stroke-width="2" stroke-linecap="round" stroke-dasharray="6 6"></path>
6697  <path d="M20.7666 33.5015L42.1962 28.5245" stroke="#E5E5E5" stroke-width="2" stroke-linecap="round" stroke-dasharray="6 6"></path>
6698  <path d="M22.124 39.3459L43.5537 34.3689" stroke="#E5E5E5" stroke-width="2" stroke-linecap="round" stroke-dasharray="6 6"></path>
6699  <path d="M23.4814 45.1904L44.9111 40.2133" stroke="#E5E5E5" stroke-width="2" stroke-linecap="round" stroke-dasharray="6 6"></path>
6700  <path d="M24.8389 51.0349L36.5278 48.3201" stroke="#E5E5E5" stroke-width="2" stroke-linecap="round" stroke-dasharray="6 6"></path>
6701  <path d="M75.9717 69.457L76.3652 72.4736H76.3662C75.8186 72.5451 75.4325 73.0471 75.5039 73.5947L75.8301 76.0947C75.9642 77.123 75.8691 78.1191 75.5889 79.0381C75.4342 79.5454 75.703 80.0803 76.1924 80.2646C75.5333 81.7339 74.442 82.9768 73.0703 83.8203C72.8242 83.3588 72.2595 83.1608 71.7764 83.3799C70.9
6701012 83.7767 69.9258 84 68.8887 84H65.835C65.2827 84 64.835 84.4477 64.835 85H60.7266C60.7266 84.4477 60.2788 84 59.7266 84H53.6182C53.0661 84.0002 52.6182 84.4479 52.6182 85H48.5107C48.5107 84.4478 48.0629 84.0001 47.5107 84H41.4023C40.8501 84.0001 40.4023 84.4478 40.4023 85H36.2949C36.2949 84.4479 35.847 84.0003 35.2949 84H29.1865C28.6342 84 28.1865 84.4477 28.1865 85H24.0781C24.0781 84.4477 23.6304 84 23.0781 84H20.0244C19.1577 84 18.3257 83.8417 17.5566 83.5518L17.459 83.5205C16.9896 83.3959 16.4943 83.6293 16.293 84.0752C15.179 83.4869 14.2175 82.6428 13.4902 81.6143C13.9353 81.3391 14.0964 80.7631 13.8467 80.2949L13.707 80.0186C13.3957 79.3671 13.1811 78.6571 13.083 77.9053L12.7568 75.4053C12.6853 74.8577 12.1833 74.4706 11.6357 74.542L11.2422 71.5254C11.7898 71.454 12.1759 70.9529 12.1045 70.4053L11.4531 65.4053L11.4346 65.3047C11.3186 64.8112 10.8445 64.476 10.3311 64.543L9.9375 61.5264C10.4851 61.4549 10.8722 60.9529 10.8008 60.4053L10.1484 55.4053L10.1299 55.3047C10.0139 54.8113 9.54072 54.4751 9.02734 54.542L8.63379 51.5254C9.18141 51.4539 9.56752 50.9529 9.49609 50.4053L9.16992 47.9053C9.05256 47.0054 9.11033 46.1301 9.31445 45.3096L9.41113 44.9619C9.56597 44.4542 9.29681 43.9183 8.80664 43.7344C9.46574 42.2654 10.5573 41.0222 11.9287 40.1787C12.1585 40.611 12.6674 40.8121 13.1279 40.6572L13.2236 40.6201C14.0988 40.2233 15.0742 40 16.1113 40H19.165C19.7173 40 20.165 39.5523 20.165 39H24.2734L24.2783 39.1025C24.3297 39.6067 24.7558 40 25.2734 40H31.3818C31.8993 39.9998 32.3246 39.6065 32.376 39.1025L32.3818 39H36.4893C36.4893 39.5522 36.9371 39.9999 37.4893 40H43.5977C44.1153 39.9999 44.5415 39.6066 44.5928 39.1025L44.5977 39H48.7051C48.7051 39.5521 49.153 39.9997 49.7051 40H55.8135C56.3658 40 56.8135 39.5523 56.8135 39H60.9219L60.9268 39.1025C60.9781 39.6067 61.4042 40 61.9219 40H64.9756C65.8423 40 66.6743 40.1583 67.4434 40.4482C67.94 40.6355 68.4908 40.401 68.7061 39.9238C69.8201 40.512 70.7813 41.3563 71.5088 42.3848C71.0639 42.66 70.9037 43.237 71.1533 43.7051C71.5403 44.4302 71.8049 45.2352 71.917 46.0947L72.2432 48.5947C72.3146 49.1421 72.8159 49.5281 73.3633 49.457L73.7568 52.4736C73.2095 52.5453 72.8241 53.0473 72.8955 53.5947L73.5469 58.5947C73.6183 59.1423 74.1204 59.5274 74.668 59.4561L75.0615 62.4727V62.4736C74.514 62.5452 74.1278 63.0472 74.1992 63.5947L74.8516 68.5947C74.923 69.142 75.4244 69.5279 75.9717 69.457Z" fill="#F5F5F5" stroke="#E5E5E5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 6"></path>
6702</svg>
6703
6704  <svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 96 96" fill="none" class="hidden dark:!block">
6705<path d="M35.1963 29.5L35.2012 29.6025C35.2525 30.1067 35.6786 30.5 36.1963 30.5H38.2656C38.8409 30.5 39.4066 30.5706 39.9521 30.7061C40.4679 30.8341 40.9882 30.5362 41.1455 30.0361C41.7355 30.2638 42.2963 30.5612 42.8164 30.9209C42.4918 31.3322 42.5388 31.9309 42.9346 32.2852C43.3534 32.6601 43.7302 33.0878 44.0537 33.5635L44.9883 34.9385C45.2988 35.395 45.9213 35.5136 46.3779 35.2031V35.2021L47.1211 36.2969H47.1221C46.6654 36.6074 46.5469 37.2298 46.8574 37.6865L47.792 39.0605C48.2078 39.672 48.6926 40.2227 49.2314 40.7051C49.6429 41.0734 50.2752 41.0384 50.6436 40.627C50.6574 40.6115 50.6689 40.5942 50.6816 40.5781C51.2019 40.9381 51.7633 41.235 52.3535 41.4629C52.3472 41.4828 52.341 41.5029 52.3359 41.5234C52.2029 42.0594 52.5295 42.6013 53.0654 42.7344C53.7673 42.9087 54.495 43 55.2344 43H57.9395C58.4569 42.9998 58.8823 42.6065 58.9336 42.1025L58.9395 42H62.3486L62.3535 42.1025C62.4049 42.6067 62.831 43 63.3486 43H68.7578C69.2754 42.9999 69.7006 42.6066 69.752 42.1025L69.7578 42H73.167L73.1719 42.1025C73.2232 42.6067 73.6493 43 74.167 43H76.8711C77.9789 43 79.0114 43.252 79.9248 43.6953C80.4024 43.9271 80.9717 43.7438 81.2295 43.2881C82.6967 44.2445 83.8182 45.6648 84.4092 47.3135C83.9065 47.4589 83.5971 47.9722 83.7119 48.4902C83.9041 49.3574 83.9332 50.2791 83.7656 51.2178L83.6816 51.6211L82.9072 54.8711C82.7793 55.4084 83.1112 55.9482 83.6484 56.0762L82.5645 60.6299C82.0272 60.502 81.4874 60.8339 81.3594 61.3711L79.8125 67.8711C79.6846 68.4081 80.0159 68.947 80.5527 69.0752L79.4688 73.6299C78.965 73.5101 78.4594 73.7946 78.293 74.2734L78.2646 74.3711L77.4912 77.6211C77.329 78.3024 77.0703 78.9398 76.7324 79.5205L76.583 79.7656C76.2975 80.2129 76.4127 80.8003 76.835 81.1094C76.1193 81.9706 75.2301 82.6731 74.2266 83.1699C74.0238 82.6875 73.4788 82.4391 72.9775 82.6133C72.2549 82.8644 71.481 83 70.6807 83H67.6299C67.0777 83.0001 66.6299 83.4478 66.6299 84H62.5283C62.5283 83.4478 62.0804 83.0002 61.5283 83H55.4258C54.8735 83 54.4258 83.4477 54.4258 84H50.3232C50.3232 83.4477 49.8755 83 49.3232 83H43.2217C42.6694 83 42.2217 83.4477 42.2217 84H38.1191C38.1191 83.4477 37.6714 83 37.1191 83H31.0176C30.4653 83 30.0176 83.4477 30.0176 84H25.915C25.915 83.4477 25.4673 83 24.915 83H21.8643C20.7741 83 19.7558 82.7549 18.8516 82.3232C18.3727 82.0948 17.8038 82.2814 17.5488 82.7383C16.1051 81.8103 14.9887 80.4353 14.3789 78.8311C14.8794 78.6763 15.1796 78.1577 15.0547 77.6416C14.8191 76.6679 14.7896 75.6212 15.0146 74.5547L15.6924 71.3467C15.8064 70.8063 15.4603 70.2752 14.9199 70.1611L14.9189 70.1602L15.8604 65.7012L15.8613 65.7021C16.4016 65.816 16.9319 65.47 17.0459 64.9297L18.4004 58.5127C18.5141 57.9725 18.1682 57.4421 17.6279 57.3281L17.627 57.3271L18.5684 52.8672L18.5693 52.8682C19.0759 52.9749 19.5733 52.6781 19.7275 52.1953L19.7539 52.0967L21.1084 45.6797C21.2223 45.1394 20.8762 44.6092 20.3359 44.4951L20.335 44.4941L21.2764 40.0342L21.2773 40.0352C21.8176 40.149 22.3479 39.803 22.4619 39.2627L23.1387 36.0547C23.3073 35.2555 23.6081 34.5134 24.0146 33.8486C24.2916 33.3956 24.1644 32.8103 23.7354 32.5098C24.4561 31.6075 25.3649 30.8705 26.3965 30.3516C26.6019 30.8334 27.148 31.0787 27.6484 30.9014C28.3828 30.6408 29.1715 30.5 29.9883 30.5H32.0576C32.5752 30.4999 33.0014 30.1066 33.0527 29.6025L33.0576 29.5H35.1963Z" fill="#141414" stroke="#252525" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 6"></path>
6706<rect x="51.2383" y="18.3378" width="34" height="43" rx="3" transform="rotate(26.0751 51.2383 18.3378)" fill="black" stroke="#252525" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 6"></rect>
6707<path d="M53.5508 27.2626L73.3116 36.9326" stroke="#252525" stroke-width="2" stroke-linecap="round" stroke-dasharray="4 4"></path>
6708<path d="M50.9136 32.6519L70.6744 42.3219" stroke="#252525" stroke-width="2" stroke-linecap="round" stroke-dasharray="4 4"></path>
6709<path d="M48.2762 38.0413L68.0371 47.7113" stroke="#252525" stroke-width="2" stroke-linecap="round" stroke-dasharray="4 4"></path>
6710<path d="M45.6389 43.4305L65.3997 53.1006" stroke="#252525" stroke-width="2" stroke-linecap="round" stroke-dasharray="4 4"></path>
6711<path d="M43.0016 48.8198L53.7802 54.0944" stroke="#252525" stroke-width="2" stroke-linecap="round" stroke-dasharray="4 4"></path>
6712<rect x="11.9816" y="22.196" width="34" height="43" rx="3" transform="rotate(-13.0752 11.9816 22.196)" fill="black" stroke="#252525" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 6"></rect>
6713<path d="M19.4095 27.6571L40.8392 22.68" stroke="#252525" stroke-width="2" stroke-linecap="round" stroke-dasharray="6 6"></path>
6714<path d="M20.767 33.5016L42.1966 28.5245" stroke="#252525" stroke-width="2" stroke-linecap="round" stroke-dasharray="6 6"></path>
6715<path d="M22.1244 39.3459L43.554 34.3689" stroke="#252525" stroke-width="2" stroke-linecap="round" stroke-dasharray="6 6"></path>
6716<path d="M23.4817 45.1904L44.9113 40.2134" stroke="#252525" stroke-width="2" stroke-linecap="round" stroke-dasharray="6 6"></path>
6717<path d="M24.8391 51.0349L36.528 48.3202" stroke="#252525" stroke-width="2" stroke-linecap="round" stroke-dasharray="6 6"></path>
6718<path d="M75.9717 69.457L76.3652 72.4736H76.3662C75.8186 72.5451 75.4325 73.0471 75.5039 73.5947L75.8301 76.0947C75.9642 77.123 75.8691 78.1191 75.5889 79.0381C75.4342 79.5454 75.703 80.0803 76.1924 80.2646C75.5333 81.7339 74.442 82.9768 73.0703 83.8203C72.8242 83.3588 72.2595 83.1608 71.7764 83.3799C70.9012 83.7767 69.9258 84 68.8887 84H65.835C65.2827 84 64.835 84.4477 64.835 85H60.7266C60.7266 84.4477 60.2788 84 59.7266 84H53.6182C53.0661 84.0002 52.6182 84.4479 52.6182 85H48.5107C48.5107 84.4478 48.0629 84.0001 47.5107 84H41.4023C40.8501 84.0001 40.4023 84.4478 40.4023 85H36.2949C36.2949 84.4479 35.847 84.0003 35.2949 84H29.1865C28.6342 84 28.1865 84.4477 28.1865 85H24.0781C24.0781 84.4477 23.6304 84 23.0781 84H20.0244C19.1577 84 18.3257 83.8417 17.5566 83.5518L17.459 83.5205C16.9896 83.3959 16.4943 83.6293 16.293 84.0752C15.179 83.4869 14.2175 82.6428 13.4902 81.6143C13.9353 81.3391 14.0964 80.7631 13.8467 80.2949L13.707 80.0186C13.3957 79.3671 13.1811 78.6571 13.083 77.9053L12.7568 75.4053C12.6853 74.8577 12.1833 74.4706 11.6357 74.542L11.2422 71.5254C11.7898 71.454 12.1759 70.9529 12.1045 70.4053L11.4531 65.4053L11.4346 65.3047C11.3186 64.8112 10.8445 64.476 10.3311 64.543L9.9375 61.5264C10.4851 61.4549 10.8722 60.9529 10.8008 60.4053L10.1484 55.4053L10.1299 55.3047C10.0139 54.8113 9.54072 54.4751 9.02734 54.542L8.63379 51.5254C9.18141 51.4539 9.56752 50.9529 9.49609 50.4053L9.16992 47.9053C9.05256 47.0054 9.11033 46.1301 9.31445 45.3096L9.41113 44.9619C9.56597 44.4542 9.29681 43.9183 8.80664 43.7344C9.46574 42.2654 10.5573 41.0222 11.9287 40.1787C12.1585 40.611 12.6674 40.8121 13.1279 40.6572L13.2236 40.6201C14.0988 40.2233 15.0742 40 16.1113 40H19.165C19.7173 40 20.165 39.5523 20.165 39H24.2734L24.2783 39.1025C24.3297 39.6067 24.7558 40 25.2734 40H31.3818C31.8993 39.9998 32.3246 39.6065 32.376 39.1025L32.3818 39H36.4893C36.4893 39.5522 36.9371 39.9999 37.4893 40H43.5977C44.1153 39.9999 44.5415 39.6066 44.5928 39.1025L44.5977 39H48.7051C48.7051 39.5521 49.153 39.9997 49.7051 40H55.8135C56.3658 40 56.8135 39.5523 56.8135 39H60.9219L60.9268 39.1025C60.9781 39.6067 61.4042 40 61.9219 40H64.9756C65.8423 40 66.6743 40.1583 67.4434 40.4482C67.94 40.6355 68.4908 40.401 68.7061 39.9238C69.8201 40.512 70.7813 41.3563 71.5088 42.3848C71.0639 42.66 70.9037 43.237 71.1533 43.7051C71.5403 44.4302 71.8049 45.2352 71.917 46.0947L72.2432 48.5947C72.3146 49.1421 72.8159 49.5281 73.3633 49.457L73.7568 52.4736C73.2095 52.5453 72.8241 53.0473 72.8955 53.5947L73.5469 58.5947C73.6183 59.1423 74.1204 59.5274 74.668 59.4561L75.0615 62.4727V62.4736C74.514 62.5452 74.1278 63.0472 74.1992 63.5947L74.8516 68.5947C74.923 69.142 75.4244 69.5279 75.9717 69.457Z" fill="#141414" stroke="#252525" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 6"></path>
6719</svg>
6720
6721
6722  <p class="text-ds-muted text-ds-body-2-regular md:mt-3">
6723    You don’t have any playlists yet. Become a member and create your first playlist.
6724  </p>
6725
6726    <ds-button href="https://toveedo.com/join" variant="primary" size="base" class="mt-6" data-turbo="false">
6727      Subscribe
6728    </ds-button>
6729</div>
6730
6731
6732  </div>
6733</turbo-frame>
6734      </main>
6735
6736      <footer class="px-[3%] py-8 lg:py-6 w-full bg-ds-main border-t border-ds-default bg-ds-default text-ds-muted text-ds-base-regular">
6737  <div class="container flex flex-col space-y-4 justify-center">
6738    <div class="flex flex-wrap justify-center items-center space-y-2 space-x-2 text-center md:text-left rtl:md:text-right">
6739        <p class="mt-2 flex justify-center space-x-2 w-full md:w-fit text-center text-sm font-normal leading-5 text-ds-muted">
6740          <span id="store-title">© 2026 Toveedo</span>
6741          <span class="ms-2 text-sm font-normal leading-5 text-ds-muted hidden md:inline-block">∙</span>
6742        </p>
6743          <p class="text-sm font-normal leading-5 text-ds-muted">
6744            <a class="hover:underline underline-offset-2" target="_self" href="/terms">Terms</a>
6745          </p>
6746          <p class="text-sm font-normal leading-5 text-ds-muted last-of-type:hidden">∙</p>
6747          <p class="text-sm font-normal leading-5 text-ds-muted">
6748            <a class="hover:underline underline-offset-2" target="_self" href="/privacy">Privacy</a>
6749          </p>
6750          <p class="text-sm font-normal leading-5 text-ds-muted last-of-type:hidden">∙</p>
6751          <p class="text-sm font-normal leading-5 text-ds-muted">
6752            <a class="hover:underline underline-offset-2" target="_self" href="/pages/faq">FAQ</a>
6753          </p>
6754          <p class="text-sm font-normal leading-5 text-ds-muted last-of-type:hidden">∙</p>
6755          <p class="text-sm font-normal leading-5 text-ds-muted">
6756            <a class="hover:underline underline-offset-2" target="_self" href="/gift_cards/new">Buy gift card</a>
6757          </p>
6758          <p class="text-sm font-normal leading-5 text-ds-muted last-of-type:hidden">∙</p>
6759          <p class="text-sm font-normal leading-5 text-ds-muted">
6760            <a class="hover:underline underline-offset-2" target="_self" href="/gift_card_redemptions/new">Claim gift card</a>
6761          </p>
6762          <p class="text-sm font-normal leading-5 text-ds-muted last-of-type:hidden">∙</p>
6763          <div class="mt-4 md:!ms-4 w-full md:w-fit text-center text-primary hover:underline underline-offset-2 leading-5">
6764            <a class="text-sm text-primary font-medium" data-turbo="true" data-turbo-frame="website_modal" href="/about/apps">Get the app -&gt;</a>
6765          </div>
6766      </div>
6767
6768        <div class="flex justify-center space-x-4 rtl:space-x-reverse">
6769            <ds-button only-icon href="https://www.linkedin.com/in/toveedo" target="_blank">
6770              <ds-icon name='linkedin' size="16px"></ds-icon>
6771            </ds-button>
6772            <ds-button only-icon href="https://www.youtube.com/@torahtreasure" target="_blank">
6773              <ds-icon name='youtube' size="16px"></ds-icon>
6774            </ds-button>
6775            <ds-button only-icon href="https://www.instagram.com/toveedo_/" target="_blank">
6776              <ds-icon name='instagram' size="16px"></ds-icon>
6777            </ds-button>
6778            <ds-button only-icon href="https://www.facebook.com/toveedo" target="_blank">
6779              <ds-icon name='facebook' size="16px"></ds-icon>
6780            </ds-button>
6781        </div>
6782  </div>
6783  <div class="flex mt-0 md:mt-4 items-center justify-center">
6784    
6785  </div>
6786</footer>
6787
6788
6789
6790  </body>
6791</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.