@fifthbell/brokaw 0.1.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +45 -0
  3. package/dist/carousels.d.ts +1 -0
  4. package/dist/carousels.js +65 -0
  5. package/dist/components/live-program/LiveProgram.d.ts +8 -0
  6. package/dist/components/live-program/LiveProgram.js +526 -0
  7. package/dist/components/live-program/assets.d.ts +14 -0
  8. package/dist/components/live-program/assets.js +14 -0
  9. package/dist/components/live-program/components/Marquee.d.ts +16 -0
  10. package/dist/components/live-program/components/Marquee.js +88 -0
  11. package/dist/components/live-program/components/MarqueeCurtain.d.ts +5 -0
  12. package/dist/components/live-program/components/MarqueeCurtain.js +30 -0
  13. package/dist/components/live-program/components/WorldClocks.d.ts +19 -0
  14. package/dist/components/live-program/components/WorldClocks.js +101 -0
  15. package/dist/components/live-program/components/slides/ArticleSlide.d.ts +14 -0
  16. package/dist/components/live-program/components/slides/ArticleSlide.js +22 -0
  17. package/dist/components/live-program/components/slides/CallsignSlide.d.ts +6 -0
  18. package/dist/components/live-program/components/slides/CallsignSlide.js +49 -0
  19. package/dist/components/live-program/components/slides/slideStyles.d.ts +1 -0
  20. package/dist/components/live-program/components/slides/slideStyles.js +64 -0
  21. package/dist/components/live-program/events.d.ts +34 -0
  22. package/dist/components/live-program/events.js +167 -0
  23. package/dist/components/live-program/hooks/useSSE.d.ts +11 -0
  24. package/dist/components/live-program/hooks/useSSE.js +67 -0
  25. package/dist/components/live-program/i18n.d.ts +4 -0
  26. package/dist/components/live-program/i18n.js +290 -0
  27. package/dist/components/live-program/segments/ArticlesSegment.d.ts +6 -0
  28. package/dist/components/live-program/segments/ArticlesSegment.js +160 -0
  29. package/dist/components/live-program/segments/EarthquakeSegment.d.ts +16 -0
  30. package/dist/components/live-program/segments/EarthquakeSegment.js +130 -0
  31. package/dist/components/live-program/segments/MarketsSegment.d.ts +12 -0
  32. package/dist/components/live-program/segments/MarketsSegment.js +87 -0
  33. package/dist/components/live-program/segments/WeatherSegment.d.ts +15 -0
  34. package/dist/components/live-program/segments/WeatherSegment.js +184 -0
  35. package/dist/components/live-program/segments/index.d.ts +6 -0
  36. package/dist/components/live-program/segments/index.js +6 -0
  37. package/dist/components/live-program/segments/types.d.ts +23 -0
  38. package/dist/components/live-program/segments/types.js +1 -0
  39. package/dist/components/live-program/segments/usePlaylistEngine.d.ts +9 -0
  40. package/dist/components/live-program/segments/usePlaylistEngine.js +108 -0
  41. package/dist/components/live-program/utils/broadcastTime.d.ts +12 -0
  42. package/dist/components/live-program/utils/broadcastTime.js +33 -0
  43. package/dist/homepage-distributor.d.ts +55 -0
  44. package/dist/homepage-distributor.js +68 -0
  45. package/dist/instagram-image-template.d.ts +8 -0
  46. package/dist/instagram-image-template.js +200 -0
  47. package/dist/outlet-config.d.ts +23 -0
  48. package/dist/outlet-config.js +23 -0
  49. package/dist/renderer.browser.d.ts +2 -0
  50. package/dist/renderer.browser.js +128 -0
  51. package/dist/renderer.core.d.ts +9 -0
  52. package/dist/renderer.core.js +353 -0
  53. package/dist/renderer.d.ts +3 -0
  54. package/dist/renderer.js +3 -0
  55. package/dist/renderer.node.d.ts +2 -0
  56. package/dist/renderer.node.js +71 -0
  57. package/dist/types/canonical-article.d.ts +247 -0
  58. package/dist/types/canonical-article.js +235 -0
  59. package/dist/utils/sofascore.d.ts +3 -0
  60. package/dist/utils/sofascore.js +31 -0
  61. package/package.json +78 -0
  62. package/src/partial-deps.json +52 -0
  63. package/src/styles/compiled.css +2 -0
  64. package/src/templates/layouts/404.hbs +5 -0
  65. package/src/templates/layouts/article-page.hbs +5 -0
  66. package/src/templates/layouts/category-page.hbs +5 -0
  67. package/src/templates/layouts/homepage.hbs +5 -0
  68. package/src/templates/layouts/link-in-bio.hbs +228 -0
  69. package/src/templates/layouts/live-story.hbs +5 -0
  70. package/src/templates/layouts/search-page.hbs +5 -0
  71. package/src/templates/partials/blocks/audio.hbs +12 -0
  72. package/src/templates/partials/blocks/data-table.hbs +23 -0
  73. package/src/templates/partials/blocks/divider.hbs +1 -0
  74. package/src/templates/partials/blocks/heading.hbs +9 -0
  75. package/src/templates/partials/blocks/image.hbs +6 -0
  76. package/src/templates/partials/blocks/info-box.hbs +8 -0
  77. package/src/templates/partials/blocks/instagram.hbs +28 -0
  78. package/src/templates/partials/blocks/key-points.hbs +8 -0
  79. package/src/templates/partials/blocks/list.hbs +13 -0
  80. package/src/templates/partials/blocks/live-update.hbs +24 -0
  81. package/src/templates/partials/blocks/pull-quote.hbs +6 -0
  82. package/src/templates/partials/blocks/rich-text.hbs +1 -0
  83. package/src/templates/partials/blocks/tiktok.hbs +15 -0
  84. package/src/templates/partials/blocks/x.hbs +74 -0
  85. package/src/templates/partials/blocks/youtube.hbs +12 -0
  86. package/src/templates/partials/components/article-main.hbs +159 -0
  87. package/src/templates/partials/components/breaking-news/live-updates-column.hbs +29 -0
  88. package/src/templates/partials/components/breaking-news.hbs +56 -0
  89. package/src/templates/partials/components/category/header.hbs +5 -0
  90. package/src/templates/partials/components/category/main-grid.hbs +55 -0
  91. package/src/templates/partials/components/category/main.hbs +7 -0
  92. package/src/templates/partials/components/category/more-grid.hbs +26 -0
  93. package/src/templates/partials/components/editorial-hero.hbs +73 -0
  94. package/src/templates/partials/components/headline.hbs +15 -0
  95. package/src/templates/partials/components/hero-editorial.hbs +1 -0
  96. package/src/templates/partials/components/hero.hbs +1 -0
  97. package/src/templates/partials/components/home/landing.hbs +111 -0
  98. package/src/templates/partials/components/home/main.hbs +63 -0
  99. package/src/templates/partials/components/home/more-stories.hbs +23 -0
  100. package/src/templates/partials/components/home/must-read.hbs +77 -0
  101. package/src/templates/partials/components/live-story/main.hbs +229 -0
  102. package/src/templates/partials/components/not-found/main.hbs +28 -0
  103. package/src/templates/partials/components/search/main.hbs +420 -0
  104. package/src/templates/partials/components/snack.hbs +92 -0
  105. package/src/templates/partials/components/spotlight-hero.hbs +59 -0
  106. package/src/templates/partials/components/trending.hbs +14 -0
  107. package/src/templates/partials/components/ui/accordion.hbs +30 -0
  108. package/src/templates/partials/components/ui/breadcrumb.hbs +16 -0
  109. package/src/templates/partials/components/ui/icon-button.hbs +19 -0
  110. package/src/templates/partials/components/ui/loading-spinner.hbs +27 -0
  111. package/src/templates/partials/components/ui/pagination.hbs +56 -0
  112. package/src/templates/partials/components/ui/scroll-area.hbs +12 -0
  113. package/src/templates/partials/components/ui/status-badge.hbs +21 -0
  114. package/src/templates/partials/footers/footer-full.hbs +79 -0
  115. package/src/templates/partials/footers/footer-minimal.hbs +5 -0
  116. package/src/templates/partials/headers/header-main.hbs +397 -0
  117. package/src/templates/partials/headers/header-minimal.hbs +16 -0
  118. package/src/templates/partials/nav/nav-categories.hbs +5 -0
  119. package/src/templates/partials/shell/doc-end.hbs +282 -0
  120. package/src/templates/partials/shell/doc-start-404.hbs +28 -0
  121. package/src/templates/partials/shell/doc-start-standard.hbs +68 -0
@@ -0,0 +1,111 @@
1
+ <div class='grid grid-cols-12 lg:grid-cols-12 gap-6 px-6'>
2
+ <div class='col-span-12 lg:col-span-9 xl:col-span-6 pt-6 lg:pt-8 space-y-12'>
3
+ {{#with homepageSlots.landing.headline1}}
4
+ <section class='lg:col-span-12 xl:col-span-8 flex flex-col'>
5
+ <a href='{{url}}' class='relative flex-shrink-0 block'>
6
+ <img src='{{featuredImage.url}}' alt='{{featuredImage.alt}}' class='w-full h-[400px] object-cover rounded' fetchpriority='high' />
7
+ </a>
8
+
9
+ <div class='mt-4 flex-grow flex flex-col'>
10
+ <div class='flex items-center text-slate-500 dark:text-slate-400 text-xs mb-4'>
11
+ <span class='uppercase font-bold tracking-wider'>{{#with (lookup categories 0)}}{{name}}{{/with}}</span>
12
+ <span class='mx-2'>•</span>
13
+ <span class='article-time' data-timestamp='{{updatedAt}}'>{{formatDate updatedAt}}</span>
14
+ </div>
15
+
16
+ <h1 class='text-4xl font-bold font-encode text-slate-900 dark:text-slate-100 mb-4 leading-11'>
17
+ <a href='{{url}}' class='hover:text-[#b21100] dark:hover:text-[#ff2e1a] transition-colors'>{{title}}</a>
18
+ </h1>
19
+
20
+ <p class='text-slate-600 dark:text-slate-400 text-2xl mb-4 font-serif leading-8'>{{excerpt}}</p>
21
+
22
+ <div class='grid grid-cols-1 md:grid-cols-2 gap-6 mt-4 border-t border-slate-200 dark:border-slate-800 pt-6 flex-grow'>
23
+ {{#each ../homepageSlots.landing.sub1}}
24
+ {{> components/snack
25
+ url=url
26
+ title=title
27
+ excerpt=excerpt
28
+ showExcerpt=false
29
+ image=featuredImage.url
30
+ alt=featuredImage.alt
31
+ readTime=(formatDate updatedAt)
32
+ imageSize='w-24 h-24'
33
+ imageClasses=''
34
+ titleTextSize='text-lg'
35
+ titleFontWeight='font-medium'
36
+ titleClasses='font-encode'
37
+ }}
38
+ {{/each}}
39
+ </div>
40
+ </div>
41
+ </section>
42
+ {{/with}}
43
+ </div>
44
+
45
+ <div class='col-span-12 md:col-span-7 lg:col-span-3 pt-6 lg:pt-8 space-y-12'>
46
+ <section class='lg:col-span-1 xl:col-span-4 flex flex-col h-full justify-between'>
47
+ {{#with homepageSlots.landing.card5}}
48
+ <div class='bg-black text-white mb-6 flex-grow flex flex-col'>
49
+ <div class='flex-grow min-h-[250px] bg-cover bg-center flex flex-col justify-end' style='background-image: linear-gradient(to top, rgba(0,0,0,1), rgba(0,0,0,0.7) 50%, transparent 100%), url("{{featuredImage.url}}");'>
50
+ <div class='px-4'>
51
+ <span class='bg-[#b21100] text-white px-3 py-2 text-xs tracking-[1px] font-bold uppercase inline-block mb-2'>{{#with (lookup categories 0)}}{{name}}{{/with}}</span>
52
+ <h2 class='text-2xl font-bold font-encode mb-2'>
53
+ <a href='{{url}}' class='hover:text-slate-300 transition-colors'>{{title}}</a>
54
+ </h2>
55
+ </div>
56
+ </div>
57
+ <div class='px-4 pb-4 flex-shrink-0'>
58
+ <p class='text-sm'>{{excerpt}}</p>
59
+ <span class='text-xs text-slate-500 dark:text-slate-400 mt-2 block'>{{formatDate updatedAt}}</span>
60
+ </div>
61
+ </div>
62
+ {{/with}}
63
+
64
+ {{#with homepageSlots.landing.headline6}}
65
+ <div class='flex flex-col'>
66
+ <a href='{{url}}' class='mb-4 flex-shrink-0 h-[180px] block'>
67
+ <img src='{{featuredImage.url}}' width='500' height='200' alt='{{featuredImage.alt}}' class='w-full h-full object-cover rounded' />
68
+ </a>
69
+ <div class='flex items-center text-slate-500 dark:text-slate-400 text-sm mb-2'>
70
+ <span class='uppercase font-bold'>{{#with (lookup categories 0)}}{{name}}{{/with}}</span>
71
+ <span class='mx-2'>•</span>
72
+ <span>{{formatDate updatedAt}}</span>
73
+ </div>
74
+ <h2 class='text-xl font-bold font-encode mb-2 text-slate-900 dark:text-slate-100'>
75
+ <a href='{{url}}' class='hover:text-[#b21100] dark:hover:text-[#ff2e1a] transition-colors'>{{title}}</a>
76
+ </h2>
77
+ <p class='text-slate-600 dark:text-slate-400 flex-grow'>{{excerpt}}</p>
78
+ </div>
79
+ {{/with}}
80
+ </section>
81
+ </div>
82
+
83
+ <aside class='col-span-12 md:col-span-5 lg:col-span-12 xl:col-span-3 pt-6'>
84
+ <div class='space-y-10'>
85
+ <div class='space-y-6'>
86
+ <div class='flex items-center justify-between border-b border-slate-300 dark:border-slate-700 pb-2'>
87
+ <h3 class='kicker text-red-700 dark:text-red-500 text-lg'>Top Stories</h3>
88
+ </div>
89
+ </div>
90
+
91
+ <div class='space-y-6 lg:grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-1 lg:gap-6 lg:space-y-0'>
92
+ {{#each homepageSlots.landing.topStories}}
93
+ {{> components/snack
94
+ url=url
95
+ title=title
96
+ image=featuredImage.url
97
+ alt=featuredImage.alt
98
+ readTime=(formatDate updatedAt)
99
+ showExcerpt=false
100
+ className='pb-4 border-b border-slate-200 dark:border-slate-800'
101
+ imageSize='w-20 h-20'
102
+ imageClasses='bg-slate-200 grayscale hover:grayscale-0 transition-all'
103
+ titleTextSize='text-xl'
104
+ titleFontWeight='font-bold'
105
+ titleClasses='font-serif leading-snug'
106
+ }}
107
+ {{/each}}
108
+ </div>
109
+ </div>
110
+ </aside>
111
+ </div>
@@ -0,0 +1,63 @@
1
+ <div class='min-h-screen font-sans text-slate-900 dark:text-slate-100 antialiased'>
2
+ {{#unless (eq showHero false)}}
3
+ {{#if hero}}
4
+ {{> components/spotlight-hero
5
+ title=(coalesce heroTitle title)
6
+ slug=(coalesce heroSlug slug)
7
+ excerpt=(coalesce heroExcerpt excerpt)
8
+ hero=hero
9
+ slides=heroSlides
10
+ related=(coalesce heroRelated homepageSlots.landing.sub1)
11
+ categories=(coalesce heroCategories categories)
12
+ }}
13
+ {{else}}
14
+ {{#if heroSlides}}
15
+ {{> components/spotlight-hero
16
+ title=(coalesce heroTitle title)
17
+ slug=(coalesce heroSlug slug)
18
+ excerpt=(coalesce heroExcerpt excerpt)
19
+ hero=hero
20
+ slides=heroSlides
21
+ related=(coalesce heroRelated homepageSlots.landing.sub1)
22
+ categories=(coalesce heroCategories categories)
23
+ }}
24
+ {{/if}}
25
+ {{/if}}
26
+ {{/unless}}
27
+
28
+ <main class='max-w-[1440px] mx-auto min-h-screen'>
29
+ {{#unless (eq showTrending false)}}
30
+ {{> components/trending}}
31
+ {{/unless}}
32
+
33
+ {{#if showEditorialHero}}
34
+ {{> components/editorial-hero
35
+ title=(coalesce heroTitle title)
36
+ slug=(coalesce heroSlug slug)
37
+ excerpt=(coalesce heroExcerpt excerpt)
38
+ hero=hero
39
+ slides=heroSlides
40
+ related=(coalesce heroRelated homepageSlots.landing.sub1)
41
+ categories=(coalesce heroCategories categories)
42
+ }}
43
+ {{/if}}
44
+
45
+ {{#unless (eq showBreakingNews false)}}
46
+ {{#if breakingNews}}
47
+ {{> components/breaking-news breakingNews}}
48
+ {{/if}}
49
+ {{/unless}}
50
+
51
+ {{#unless (eq showLanding false)}}
52
+ {{> components/home/landing}}
53
+ {{/unless}}
54
+
55
+ {{#unless (eq showMustRead false)}}
56
+ {{> components/home/must-read}}
57
+ {{/unless}}
58
+
59
+ {{#unless (eq showMoreStories false)}}
60
+ {{> components/home/more-stories}}
61
+ {{/unless}}
62
+ </main>
63
+ </div>
@@ -0,0 +1,23 @@
1
+ <div class='py-12 px-6'>
2
+ <div class='flex items-center gap-2 mb-6 border-l-4 border-[#b21100] pl-4'>
3
+ <h2 class='text-2xl font-bold tracking-tight font-serif'>More Stories</h2>
4
+ </div>
5
+ <div class='grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-12'>
6
+ {{#each homepageSlots.moreStories}}
7
+ {{> components/snack
8
+ url=url
9
+ title=title
10
+ excerpt=excerpt
11
+ categories=categories
12
+ readTime=(formatDate updatedAt)
13
+ showImage=false
14
+ metaTextSize='text-xs'
15
+ titleTextSize='text-lg'
16
+ titleFontWeight='font-bold'
17
+ titleClasses='font-encode'
18
+ excerptTextSize='text-lg'
19
+ excerptClasses='font-serif leading-relaxed'
20
+ }}
21
+ {{/each}}
22
+ </div>
23
+ </div>
@@ -0,0 +1,77 @@
1
+ <div class='grid grid-cols-12 lg:grid-cols-12 gap-6 px-6'>
2
+ <div class='col-span-12 lg:col-span-12 xl:col-span-9 pt-6 lg:pt-8 space-y-12'>
3
+ <div class='grid grid-cols-2 gap-6'>
4
+ <div class='col-span-2'>
5
+ <div class='flex items-center gap-2 mb-6 border-l-4 border-[#b21100] pl-4'>
6
+ <h2 class='text-2xl font-bold tracking-tight font-serif'>Must Read</h2>
7
+ </div>
8
+ {{#with homepageSlots.mustRead.lead}}
9
+ <article class='grid grid-cols-1 md:grid-cols-2 gap-6 items-start'>
10
+ <a href='{{url}}' class='block aspect-video overflow-hidden bg-slate-100'>
11
+ <img src='{{featuredImage.url}}' alt='{{featuredImage.alt}}' class='w-full h-full object-cover transition-transform duration-500 hover:scale-105' />
12
+ </a>
13
+ <div class='space-y-3'>
14
+ <div class='flex items-center text-xs font-bold uppercase tracking-wider text-[#b21100]'>
15
+ <span>{{#with (lookup categories 0)}}{{name}}{{/with}}</span>
16
+ </div>
17
+ <h3 class='headline text-3xl font-bold font-serif leading-tight'>
18
+ <a href='{{url}}' class='hover:underline decoration-[#b21100]'>{{title}}</a>
19
+ </h3>
20
+ <p class='text-slate-600 dark:text-slate-400 font-serif leading-relaxed line-clamp-3 text-xl'>{{excerpt}}</p>
21
+ <span class='text-s text-slate-500 dark:text-slate-400 block font-sans'>{{formatDate updatedAt}}</span>
22
+ </div>
23
+ </article>
24
+ {{/with}}
25
+ </div>
26
+
27
+ {{#with homepageSlots.mustRead.headline16}}
28
+ <div class='col-span-1'>
29
+ <article class='group'>
30
+ <a href='{{url}}' class='block mb-4 overflow-hidden aspect-[3/2] bg-slate-100'>
31
+ <img src='{{featuredImage.url}}' alt='{{featuredImage.alt}}' class='w-full h-full object-cover transition-transform duration-500 group-hover:scale-105' />
32
+ </a>
33
+ <div class='space-y-2'>
34
+ <span class='text-xs font-bold text-[#b21100] uppercase tracking-wider'>{{#with (lookup categories 0)}}{{name}}{{/with}}</span>
35
+ <h3 class='text-2xl font-bold font-serif leading-tight group-hover:underline'>
36
+ <a href='{{url}}'>{{title}}</a>
37
+ </h3>
38
+ </div>
39
+ </article>
40
+ </div>
41
+ {{/with}}
42
+
43
+ {{#with homepageSlots.mustRead.headline17}}
44
+ <div class='col-span-1'>
45
+ <article class='group'>
46
+ <a href='{{url}}' class='block mb-4 overflow-hidden aspect-[3/2] bg-slate-100'>
47
+ <img src='{{featuredImage.url}}' alt='{{featuredImage.alt}}' class='w-full h-full object-cover transition-transform duration-500 group-hover:scale-105' />
48
+ </a>
49
+ <div class='space-y-2'>
50
+ <span class='text-xs font-bold text-[#0066cc] uppercase tracking-wider'>{{#with (lookup categories 0)}}{{name}}{{/with}}</span>
51
+ <h3 class='text-2xl font-bold font-serif leading-tight group-hover:underline'>
52
+ <a href='{{url}}'>{{title}}</a>
53
+ </h3>
54
+ </div>
55
+ </article>
56
+ </div>
57
+ {{/with}}
58
+ </div>
59
+ </div>
60
+
61
+ <aside class='col-span-12 xl:col-span-3 pt-6'>
62
+ <div class='space-y-10'>
63
+ <div class='space-y-6 md:grid grid-cols-2 xl:grid-cols-1 lg:gap-6 lg:space-y-0'>
64
+ {{#each homepageSlots.mustRead.sidebar}}
65
+ {{> components/snack
66
+ url=url
67
+ title=title
68
+ readTime=(formatDate updatedAt)
69
+ showImage=false
70
+ showExcerpt=false
71
+ className='pb-4 border-b border-slate-200 dark:border-slate-800 last:border-0'
72
+ }}
73
+ {{/each}}
74
+ </div>
75
+ </div>
76
+ </aside>
77
+ </div>
@@ -0,0 +1,229 @@
1
+ <main class='min-h-screen pb-16'>
2
+
3
+ {{!-- Hero Image --}}
4
+ {{#if featuredImage.url}}
5
+ <section class='relative w-full overflow-hidden'>
6
+ <div class='hidden lg:block absolute inset-0 pointer-events-none' aria-hidden='true'>
7
+ <img
8
+ src='{{featuredImage.url}}'
9
+ alt=''
10
+ class='w-full h-full object-cover scale-125 opacity-90'
11
+ style='filter: blur(16px);'
12
+ />
13
+ </div>
14
+
15
+ <div class='relative max-w-screen-xl mx-auto px-0 lg:px-6 xl:px-8'>
16
+ <figure
17
+ class='relative overflow-hidden lg:rounded-lg'
18
+ style='box-shadow: -34px 0 36px -26px rgba(0,0,0,0.55), -74px 0 74px -62px rgba(0,0,0,0.4), 34px 0 36px -26px rgba(0,0,0,0.55), 74px 0 74px -62px rgba(0,0,0,0.4);'
19
+ >
20
+ {{#if media}}
21
+ <div data-carousel='live-story-hero' class='relative'>
22
+ <div class='carousel-slide active opacity-100 transition-opacity duration-700'>
23
+ <img
24
+ src='{{featuredImage.url}}'
25
+ alt='{{featuredImage.alt}}'
26
+ class='w-full h-auto object-cover object-center'
27
+ style='max-height:520px;'
28
+ fetchpriority='high'
29
+ />
30
+ </div>
31
+ {{#each media}}
32
+ <div class='carousel-slide hidden opacity-0 transition-opacity duration-700'>
33
+ <img
34
+ src='{{url}}'
35
+ alt='{{alt}}'
36
+ class='w-full h-auto object-cover object-center'
37
+ style='max-height:520px;'
38
+ loading='lazy'
39
+ />
40
+ </div>
41
+ {{/each}}
42
+ <div class='absolute inset-x-0 bottom-4 z-20 flex items-center justify-center gap-2'>
43
+ <button type='button' class='carousel-dot w-2.5 h-2.5 rounded-full active' aria-label='Show image 1'></button>
44
+ {{#each media}}
45
+ <button type='button' class='carousel-dot w-2.5 h-2.5 rounded-full' aria-label='Show image'></button>
46
+ {{/each}}
47
+ </div>
48
+ <button
49
+ type='button'
50
+ class='carousel-next absolute right-3 top-1/2 -translate-y-1/2 z-20 w-9 h-9 rounded-full bg-black/55 text-white text-lg leading-none flex items-center justify-center'
51
+ aria-label='Next image'
52
+ >
53
+ &rsaquo;
54
+ </button>
55
+ </div>
56
+ {{else}}
57
+ <img
58
+ src='{{featuredImage.url}}'
59
+ alt='{{featuredImage.alt}}'
60
+ class='w-full h-auto object-cover object-center'
61
+ style='max-height:520px;'
62
+ fetchpriority='high'
63
+ />
64
+ {{/if}}
65
+ </figure>
66
+ </div>
67
+ </section>
68
+ {{/if}}
69
+
70
+ <div class='max-w-screen-xl mx-auto px-4 xl:px-8'>
71
+
72
+ {{!-- Story Header --}}
73
+ <header class='pt-8 pb-8 border-b border-slate-200 dark:border-slate-700'>
74
+ <div class='flex items-center gap-3 mb-4'>
75
+ <span class='inline-flex items-center px-3 py-1.5 bg-[#cc0000] text-white text-xs font-bold tracking-[0.08em] uppercase leading-none'>LIVE</span>
76
+ {{#with (lookup categories 0)}}
77
+ <span class='text-xs font-bold uppercase tracking-wider text-[#b21100] dark:text-[#ff2e1a]'>{{name}}</span>
78
+ {{/with}}
79
+ {{#if status}}
80
+ {{#if (eq status "live")}}
81
+ {{> 'components/ui/status-badge' variant="live" label=status}}
82
+ {{else if (eq status "ended")}}
83
+ {{> 'components/ui/status-badge' variant="offline" label=status}}
84
+ {{else if (eq status "archived")}}
85
+ {{> 'components/ui/status-badge' variant="offline" label=status}}
86
+ {{else}}
87
+ {{> 'components/ui/status-badge' variant="info" label=status}}
88
+ {{/if}}
89
+ {{/if}}
90
+ {{#if updatedAt}}
91
+ <span class='text-xs text-slate-500 dark:text-slate-400'>Last updated: <span class='article-time' data-timestamp='{{updatedAt}}'>{{formatDate updatedAt}}</span></span>
92
+ {{/if}}
93
+ </div>
94
+
95
+ <h1 class='text-3xl xl:text-5xl font-bold font-encode text-slate-900 dark:text-slate-100 leading-tight mb-4 max-w-4xl'>
96
+ {{title}}
97
+ </h1>
98
+
99
+ {{#if excerpt}}
100
+ <p class='text-xl text-slate-600 dark:text-slate-400 font-serif leading-relaxed mb-6 max-w-3xl'>
101
+ {{excerpt}}
102
+ </p>
103
+ {{/if}}
104
+ </header>
105
+
106
+ {{!-- Body Grid --}}
107
+ <div class='pt-8 xl:grid xl:grid-cols-12 xl:gap-12'>
108
+
109
+ {{!-- Feed Column --}}
110
+ <div class='xl:col-span-8'>
111
+
112
+ {{!-- Key Points Summary (kept in template, temporarily hidden) --}}
113
+ {{#if liveStory.keyPoints}}
114
+ <div class='hidden mb-10 rounded-lg overflow-hidden border border-slate-200 dark:border-slate-700'>
115
+ <div class='px-6 py-3 bg-[#cc0000]'>
116
+ <h2 class='text-sm font-bold tracking-[0.06em] uppercase text-white leading-none'>Here's the latest</h2>
117
+ </div>
118
+ <div class='px-6 py-5 bg-slate-50 dark:bg-slate-800'>
119
+ <ul class='space-y-3'>
120
+ {{#each liveStory.keyPoints}}
121
+ <li class='flex items-start gap-3'>
122
+ <span class='w-2 h-2 rounded-full bg-[#cc0000] flex-shrink-0 mt-2'></span>
123
+ <p class='text-base leading-relaxed text-slate-700 dark:text-slate-300'>{{this}}</p>
124
+ </li>
125
+ {{/each}}
126
+ </ul>
127
+ </div>
128
+ </div>
129
+ {{/if}}
130
+
131
+ {{!-- SofaScore Match Momentum --}}
132
+ {{#with (sofascoreWidgetUrl sofascore_id) as |widgetUrl|}}
133
+ <div class='mb-10 rounded-lg overflow-hidden border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900'>
134
+ <div class='px-6 py-3 bg-slate-100 dark:bg-slate-800 border-b border-slate-200 dark:border-slate-700'>
135
+ <h2 class='text-sm font-bold tracking-[0.06em] uppercase text-slate-700 dark:text-slate-200 leading-none'>Match Momentum</h2>
136
+ </div>
137
+ <div class='p-4'>
138
+ <iframe
139
+ width='100%'
140
+ height='286'
141
+ src='{{widgetUrl}}'
142
+ title='SofaScore Attack Momentum'
143
+ frameborder='0'
144
+ scrolling='no'
145
+ loading='lazy'
146
+ referrerpolicy='no-referrer-when-downgrade'
147
+ style='border:0;'
148
+ ></iframe>
149
+ {{#with (sofascoreMatchUrl sofascore_id) as |matchUrl|}}
150
+ <div style='font-size:12px;font-family:Arial,sans-serif'>
151
+ <a href='{{matchUrl}}' target='_blank' rel='noreferrer'>{{title}} Live Score</a>
152
+ </div>
153
+ {{/with}}
154
+ </div>
155
+ </div>
156
+ {{/with}}
157
+
158
+ {{!-- Live Updates Timeline --}}
159
+ <div>
160
+ {{#each body}}
161
+ {{#if (eq type 'liveUpdate')}}
162
+ <div class='relative pl-9 pb-10'>
163
+ <div class='absolute left-0 top-[5px] w-4 h-4 rounded-full bg-[#4FC3F7] ring-4 ring-white dark:ring-slate-950 z-10'></div>
164
+ {{#unless @last}}
165
+ <div class='absolute left-[7px] top-5 bottom-0 w-0.5 bg-slate-200 dark:bg-slate-700'></div>
166
+ {{/unless}}
167
+ <div class='flex flex-col gap-1'>
168
+ <time class='text-sm font-semibold text-[#0ea5e9] dark:text-[#4FC3F7]'>{{formatDate timestamp}}</time>
169
+ {{#if headline}}
170
+ <h2 class='text-xl font-bold font-encode text-slate-900 dark:text-slate-100 leading-snug mt-1'>
171
+ {{headline}}
172
+ </h2>
173
+ {{/if}}
174
+ {{#if html}}
175
+ <div class='text-base leading-relaxed text-slate-700 dark:text-slate-300 mt-2 [&_img]:w-full [&_img]:h-auto [&_img]:rounded-lg [&_img]:mt-3'>
176
+ {{{html}}}
177
+ </div>
178
+ {{/if}}
179
+ {{#if media}}
180
+ <div class='mt-4 grid grid-cols-1 sm:grid-cols-2 gap-3'>
181
+ {{#each media}}
182
+ <figure class='overflow-hidden rounded-lg border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900'>
183
+ <img src='{{url}}' alt='{{alt}}' class='w-full h-auto object-cover' loading='lazy' />
184
+ {{#if caption}}
185
+ <figcaption class='px-3 py-2 text-xs text-slate-500 dark:text-slate-400'>
186
+ {{caption}}
187
+ </figcaption>
188
+ {{/if}}
189
+ </figure>
190
+ {{/each}}
191
+ </div>
192
+ {{/if}}
193
+ </div>
194
+ </div>
195
+ {{else}}
196
+ <div class='relative pl-9 pb-6'>
197
+ <div class='absolute left-[5px] top-[5px] w-2.5 h-2.5 rounded-full bg-slate-300 dark:bg-slate-600 z-10'></div>
198
+ {{#unless @last}}
199
+ <div class='absolute left-[9px] top-4 bottom-0 w-0.5 bg-slate-200 dark:bg-slate-700'></div>
200
+ {{/unless}}
201
+ <div>
202
+ {{> (lookup . 'type')}}
203
+ </div>
204
+ </div>
205
+ {{/if}}
206
+ {{/each}}
207
+ </div>
208
+
209
+ </div>
210
+
211
+ {{!-- Sidebar --}}
212
+ <aside class='xl:col-span-4 mt-10 xl:mt-0'>
213
+ <div class='sticky top-6'>
214
+ {{#if articles.[0]}}
215
+ <h3 class='text-xs font-bold uppercase tracking-[0.12em] text-slate-500 dark:text-slate-400 mb-4 pb-2 border-b border-slate-200 dark:border-slate-700'>
216
+ Related Articles
217
+ </h3>
218
+ <div>
219
+ {{#each (slice articles 0 6)}}
220
+ {{> components/snack showExcerpt=true}}
221
+ {{/each}}
222
+ </div>
223
+ {{/if}}
224
+ </div>
225
+ </aside>
226
+
227
+ </div>
228
+ </div>
229
+ </main>
@@ -0,0 +1,28 @@
1
+ <main class='flex-1 container mx-auto px-4 py-16'>
2
+ <div class='max-w-2xl mx-auto text-center'>
3
+ <div class='mb-8'>
4
+ <h1 class='text-9xl font-bold text-[#b21100] dark:text-[#ff2e1a]' aria-label='Page not found error'>404</h1>
5
+ </div>
6
+
7
+ <h2 class='text-4xl font-bold text-slate-900 dark:text-slate-100 mb-4'>Page Not Found</h2>
8
+
9
+ <p class='text-xl text-slate-600 dark:text-slate-400 mb-8 font-serif leading-relaxed'>
10
+ We couldn't find the page you're looking for. The article or page you're trying to access may have been moved, deleted, or never existed.
11
+ </p>
12
+
13
+ <a href='{{logoLink}}' class='inline-flex items-center gap-2 bg-[#b21100] hover:bg-[#8a0d00] dark:bg-[#ff2e1a] dark:hover:bg-[#cc2515] text-white font-bold py-3 px-6 rounded transition-colors'>
14
+ <span>Go to Homepage</span>
15
+ </a>
16
+
17
+ <div class='mt-12 pt-8 border-t border-slate-200 dark:border-slate-800'>
18
+ <p class='text-sm text-slate-600 dark:text-slate-400 mb-4'>Or explore our categories:</p>
19
+ <div class='flex flex-wrap justify-center gap-4'>
20
+ {{#if navigation.categories}}
21
+ {{#each navigation.categories}}
22
+ <a href='/{{slug}}' class='text-[#b21100] dark:text-[#ff2e1a] hover:underline font-semibold'>{{name}}</a>
23
+ {{/each}}
24
+ {{/if}}
25
+ </div>
26
+ </div>
27
+ </div>
28
+ </main>