{!! $bundle->getArticleTitle() !!}
+{!! $section->getArticleTitle() !!}
+ @endif +diff --git a/app/Classes/Link.php b/app/Classes/Link.php
index e66e47a..332f7b2 100644
--- a/app/Classes/Link.php
+++ b/app/Classes/Link.php
@@ -171,10 +171,19 @@ private function fetchIsDead()
foreach (['head', 'get'] as $method) {
try {
- if (Http::throw()->{$method}($this->url)->ok()) {
+ $result = Http::{$method}($this->url);
+
+ if ($result->ok()) {
$isDead = false;
break;
}
+
+ if ($result->status() === 403) {
+ $isDead = false;
+ break;
+ }
+
+ $reason = strval($result->status());
} catch (Exception $ex) {
$reason = $ex->getMessage();
}
@@ -271,6 +280,11 @@ private function fetchTitle(): string
$this->checked()->format('d/m/Y'),
$this->reason()
);
+ } else {
+ $title .= sprintf(
+ ' (vérifié le %s) ',
+ $this->checked()->format('d/m/Y')
+ );
}
$title .= sprintf(' : %s', $this->url);
diff --git a/app/ImageFilters/ListItem.php b/app/ImageFilters/ListItem.php
index 4e596aa..a8ea8fb 100644
--- a/app/ImageFilters/ListItem.php
+++ b/app/ImageFilters/ListItem.php
@@ -9,7 +9,7 @@ class ListItem implements ModifierInterface
{
public function apply(ImageInterface $image): ImageInterface
{
- $image->coverDown(720, 400);
+ $image->coverDown(600, 400);
return $image;
}
diff --git a/app/Services/BundleRenderers/Renderers/BaseRenderer.php b/app/Services/BundleRenderers/Renderers/BaseRenderer.php
index e50483f..f0e09b5 100644
--- a/app/Services/BundleRenderers/Renderers/BaseRenderer.php
+++ b/app/Services/BundleRenderers/Renderers/BaseRenderer.php
@@ -25,9 +25,9 @@ public function __construct(protected Bundle $bundle)
*/
public function renderCard()
{
- return view('article-card', [
- 'bundle' => $this->bundle,
- ]);
+ $this->prepareRenderCard();
+
+ return view('article-card', $this->viewData);
}
/**
@@ -64,6 +64,28 @@ protected function prepareRender()
$this->handlePagination();
}
+ /**
+ * Renders a HTML card view of the bundle
+ */
+ protected function prepareRenderCard()
+ {
+ $coverRef = $this->bundle->metadata()->get('cover');
+ $cover = null;
+
+ if (!empty($coverRef)) {
+ $cover = $this->bundle->attachments(AttachmentsManager::Images)->getComponentByRef($coverRef, 'listitem', ['nolink' => true]);
+ }
+
+ $date = $this->bundle->metadata()->get('date');
+
+ if (!empty($date)) {
+ data_set($this->viewData, 'date', Carbon::parse($date));
+ }
+
+ data_set($this->viewData, 'cover', $cover ? $cover->render() : null);
+ data_set($this->viewData, 'section', $this->bundle->getSection());
+ }
+
/**
* Pre-fill view with data used by all renderers
*/
diff --git a/app/Services/Markdown/Linter.php b/app/Services/Markdown/Linter.php
index 7644694..27c1a05 100644
--- a/app/Services/Markdown/Linter.php
+++ b/app/Services/Markdown/Linter.php
@@ -21,6 +21,8 @@ class Linter
*/
private $phraseEndingChars = ['.', '!', '?'];
+ private $htmlPlaceholders = [];
+
/**
* Constructor takes markdown content and prepares it for formatting.
*
@@ -38,6 +40,9 @@ public function __construct(?string $markdown = '')
*/
public function format(): string
{
+ return $this->markdown;
+ $this->markdown = $this->replaceHtmlWithPlaceholders($this->markdown);
+
if (empty($this->markdown)) {
return $this->markdown;
}
@@ -50,14 +55,30 @@ public function format(): string
return $this->formatBlock($block, $type);
}, $blocks);
- return implode("\n\n", $processedBlocks);
+ $result = implode("\n\n", $processedBlocks);
+ $result = $this->restoreHtmlFromPlaceholders($result);
+
+ return $result;
+ }
+
+ private function restoreHtmlFromPlaceholders($text)
+ {
+ return str_replace(array_keys($this->htmlPlaceholders), array_values($this->htmlPlaceholders), $text);
+ }
+
+ private function replaceHtmlWithPlaceholders($text)
+ {
+ $index = 0;
+
+ return preg_replace_callback('/<([a-zA-Z0-9\-]+)([^>]*)>(.*?)<\/\1>/s', function ($matches) use (&$index) {
+ $placeholder = "";
+ $this->htmlPlaceholders[$placeholder] = $matches[0]; // Store the whole match
+ $index++;
+
+ return $placeholder;
+ }, $text);
}
- /**
- * Segment the markdown into blocks based on empty lines, respecting code blocks and multi-line HTML.
- *
- * @return array Array of blocks, each containing markdown content.
- */
private function segmentMarkdown(): array
{
$blocks = [];
@@ -116,10 +137,6 @@ private function determineBlockType(string $block): string
return 'code';
}
- if (preg_match('/^\s*<[^>]+>/', trim($block))) {
- return 'html';
- }
-
if (preg_match('/^\s*#/', trim($block))) {
return 'header';
}
@@ -160,8 +177,6 @@ private function formatBlock(string $block, string $type): string
switch ($type) {
case 'code':
return $this->formatCodeBlock($block);
- case 'html':
- return $this->formatHtmlBlock($block);
case 'header':
return $this->formatHeaderBlock($block);
case 'table':
@@ -195,12 +210,6 @@ private function formatCodeBlock(string $block): string
return implode("\n", $lines);
}
- private function formatHtmlBlock(string $block): string
- {
- // HTML-specific formatting
- return $block;
- }
-
private function formatFootnoteBlock(string $block): string
{
// HTML-specific formatting
@@ -215,7 +224,7 @@ private function formatHeaderBlock(string $block): string
private function formatTableBlock(string $block): string
{
- // HTML-specific formatting
+ // Table formatting
return $block;
}
diff --git a/app/View/Components/Chat/Me.php b/app/View/Components/Chat/Me.php
new file mode 100644
index 0000000..273cbc3
--- /dev/null
+++ b/app/View/Components/Chat/Me.php
@@ -0,0 +1,26 @@
+ $this->data,
+ ]);
+ }
+}
diff --git a/app/View/Components/Paginator.php b/app/View/Components/Paginator.php
new file mode 100644
index 0000000..19a23de
--- /dev/null
+++ b/app/View/Components/Paginator.php
@@ -0,0 +1,25 @@
+data);
+ }
+}
diff --git a/app/View/Components/ReadMore.php b/app/View/Components/ReadMore.php
new file mode 100644
index 0000000..99cb0ad
--- /dev/null
+++ b/app/View/Components/ReadMore.php
@@ -0,0 +1,42 @@
+urls)) {
+ $this->urls = [$this->urls];
+ }
+
+ $bundles = [];
+
+ foreach ($urls as $url) {
+ $bundles[] = new Bundle($url, Storage::disk(env('CONTENT_DISK')));
+ }
+
+ $this->bundles = $bundles;
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ */
+ public function render(): View|Closure|string
+ {
+ return view('components.read-more', [
+ 'bundles' => $this->bundles,
+ ]);
+ }
+}
diff --git a/app/View/Components/SiteFooter.php b/app/View/Components/SiteFooter.php
new file mode 100644
index 0000000..da77b44
--- /dev/null
+++ b/app/View/Components/SiteFooter.php
@@ -0,0 +1,26 @@
+ false,
'heading_class' => '',
'fragment_prefix' => '',
- 'insert' => 'before',
+ 'insert' => 'after',
'min_heading_level' => 2,
'max_heading_level' => 6,
'title' => 'Lien direct',
diff --git a/config/pagination.php b/config/pagination.php
new file mode 100644
index 0000000..7da19d6
--- /dev/null
+++ b/config/pagination.php
@@ -0,0 +1,5 @@
+ 12,
+];
diff --git a/resources/css/app.css b/resources/css/app.css
index a0534f7..34fdd6a 100644
--- a/resources/css/app.css
+++ b/resources/css/app.css
@@ -1,2 +1,35 @@
-* {
+@import "@fontsource/quicksand";
+@import "reset";
+@import "utilities";
+@import "links";
+@import "site-header";
+@import "figure";
+@import "article-main";
+@import "chat";
+@import "footnotes";
+@import "details";
+@import "tables";
+@import "article-list";
+@import "paginator";
+@import "drop";
+@import "site-footer";
+@import "form";
+
+:root {
+ --body-width: 800px;
+ --design-width: calc(800px + 4rem);
+}
+
+html,
+body {
+ width: 100vw;
+ height: 100vh;
+ background-color: #030712;
+ color: #e4f1fe;
+}
+
+body {
+ font-family: "Quicksand";
+ margin: auto;
+ font-size: 24px;
}
diff --git a/resources/css/article-list.css b/resources/css/article-list.css
new file mode 100644
index 0000000..35b7fee
--- /dev/null
+++ b/resources/css/article-list.css
@@ -0,0 +1,99 @@
+.article-list {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ width: 100%;
+ margin: auto;
+ padding: 1rem;
+ gap: 2rem;
+
+ .article-card-link {
+ text-decoration: none;
+ border: solid 2px #00101f;
+ border-radius: .5em;
+ color: #6c7a89;
+ box-shadow: 0 1px 1rem #000;
+ background: #01010c radial-gradient(at bottom center, #00101f, #000614, #01010c) no-repeat;
+
+ .article-card {
+ font-size: 1rem;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ width: 100%;
+ height: 100%;
+
+ figure {
+ width: 100%;
+ margin: 0;
+
+ img {
+ border-radius: .5rem .5rem 0 0;
+ }
+ }
+
+ h2 {
+ text-align: center;
+ color: #a8b4bd;
+ flex-grow: 1;
+ align-content: center;
+ margin: .5rem;
+ }
+
+ &:hover {
+ h2 {
+ color: #fff;
+ }
+ }
+
+ .article-card-body {
+ text-align: center;
+ margin-bottom: .5rem;
+ }
+ }
+
+ &:hover {
+ box-shadow: 0 1px 1em #021127;
+ border: solid 2px #021127;
+
+ figure {
+ img {
+ opacity: 1;
+ }
+ }
+ }
+
+ .ribbon {
+ position: absolute;
+ top: 0;
+ right: 0;
+ padding: 5px 10px;
+ font-size: 0.5em;
+ border-top-right-radius: 1em;
+ border-bottom-left-radius: 1em;
+ box-shadow: 0 2px 3px rgba(0, 0, 0, 0.2);
+
+ &.sponsored {
+ background-color: #4a5568;
+ color: #ffffff;
+ }
+
+ &.dead {
+ background-color: #ff0000;
+ color: #ffffff;
+ font-weight: bold;
+ }
+ }
+ }
+}
+
+@media only screen and (max-width: 799px) {
+ .article-list {
+ grid-template-columns: repeat(2, 1fr);
+ }
+}
+
+@media only screen and (max-width: 399px) {
+ .article-list {
+ grid-template-columns: repeat(1, 1fr);
+ }
+}
diff --git a/resources/css/article-main.css b/resources/css/article-main.css
new file mode 100644
index 0000000..a134ed0
--- /dev/null
+++ b/resources/css/article-main.css
@@ -0,0 +1,190 @@
+#article-main {
+ margin: auto;
+ padding: 1rem 0;
+ line-height: 175%;
+
+ > header {
+ margin: auto;
+ text-align: center;
+ color: #6c7a89;
+
+ h1 {
+ font-size: 2.5rem;
+ color: #fff;
+ line-height: 125%;
+ padding: 0 1em;
+ }
+ }
+
+ > #article-body {
+ margin-top: 2rem;
+ }
+
+ > #article-body,
+ .markdown-body {
+ display: flex;
+ flex-direction: column;
+ gap: 1.5rem;
+
+ .table-of-contents {
+ margin: 2rem auto;
+ line-height: 150%;
+ width: var(--design-width);
+ font-size: .8em;
+
+ ol {
+ padding-left: 1rem;
+ }
+
+ li + li {
+ margin: 0;
+ }
+ }
+
+ blockquote {
+ border-left: 4px solid #60a5fa;
+ padding: 0.5rem 1rem;
+ margin: 1rem auto;
+ color: #e4f1fe;
+ background-color: #021127;
+ text-align: justify;
+ max-width: var(--design-width);
+ width: 100%;
+ border-radius: .5rem;
+
+ p + p {
+ padding-top: 1rem;
+ }
+ }
+
+ > h2,
+ > h3,
+ > h4,
+ > h5,
+ > h6 {
+ width: var(--design-width);
+ margin: 1rem auto;
+ text-align: left;
+ gap: .5rem;
+ padding-bottom: .2rem;
+ position: relative;
+
+ .heading-permalink {
+ position: absolute;
+ top: 0;
+ right: 0;
+ font-size: .75rem;
+ }
+ }
+
+ > h2 {
+ font-size: 2.25rem;
+ color: #ff6347;
+ border-bottom: solid 1px #ff6347;
+ }
+
+ > h3 {
+ font-size: 2rem;
+ color: #ff8c00;
+ border-bottom: solid 1px #ff8c00;
+ }
+
+ > h4 {
+ font-size: 1.75rem;
+ color: #ffa500;
+ border-bottom: dotted 1px #ffa500;
+ }
+
+ > h5 {
+ font-size: 1.5rem;
+ color: #ffd700;
+ }
+
+ > h6 {
+ font-size: 1.25rem;
+ color: #ffff00;
+ }
+
+ hr {
+ width: var(--design-width);
+ border: none;
+ height: 1px;
+ background: linear-gradient(to right, #030712 0%, #030712 20%, #1a1f33 50%, #030712 80%, #030712 100%);
+ margin: 20px 0;
+ margin: 1em auto;
+ }
+
+ ol,
+ ul {
+ max-width: var(--body-width);
+ width: 100%;
+ margin: auto;
+
+ li {
+ text-align: justify;
+ }
+
+ li + li {
+ margin-top: .5em;
+ }
+ }
+
+ > p {
+ text-align: justify;
+ max-width: var(--body-width);
+ width: 100%;
+ margin: auto;
+ }
+
+ pre.shiki {
+ font-size: .8em;
+ line-height: 150%;
+ overflow: auto;
+ border: solid 2px #112;
+ border-radius: .5rem;
+ width: var(--design-width);
+ max-height: 80vh;
+ margin: 1em auto;
+
+ > code {
+ counter-reset: step;
+ counter-increment: step 0;
+
+ .line::before {
+ user-select: none;
+ content: counter(step);
+ counter-increment: step;
+ width: 3rem;
+ margin-right: 1rem;
+ display: inline-block;
+ text-align: right;
+ color: #6c7a89;
+ padding-left: .5rem;
+ padding-right: .5rem;
+ background-color: #112;
+ }
+ }
+ }
+
+ :not(pre.shiki):not(h2):not(h3):not(h4):not(h5):not(h6) {
+ code {
+ background-color: #000;
+ color: #aaa;
+ font-size: .8em;
+ border: solid 1px #223;
+ padding: .2rem;
+ border-radius: .25rem;
+ }
+ }
+
+ strong {
+ color: #fff;
+ font-weight: 900;
+ }
+
+ sup {
+ line-height: 100%;
+ margin-left: .2rem;
+ }
+ }
+}
diff --git a/resources/css/chat.css b/resources/css/chat.css
new file mode 100644
index 0000000..4c3814d
--- /dev/null
+++ b/resources/css/chat.css
@@ -0,0 +1,32 @@
+.chat {
+ background-color: #282828;
+ border: 1px solid #444;
+ border-radius: 8px;
+ padding: 10px;
+ margin: 20px auto;
+ width: var(--design-width);
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
+ font-size: .8em;
+ line-height: 125%;
+}
+
+.chat-me,
+.chat-other {
+ padding: 8px 12px;
+ border-radius: 15px;
+ margin-bottom: 4px;
+ color: #fff;
+ display: block;
+ max-width: 70%;
+}
+
+.chat-me {
+ background-color: #3178c6;
+ align-self: flex-end;
+ margin-left: auto;
+}
+
+.chat-other {
+ background-color: #4b5563;
+ align-self: flex-start;
+}
diff --git a/resources/css/details.css b/resources/css/details.css
new file mode 100644
index 0000000..8e4a12d
--- /dev/null
+++ b/resources/css/details.css
@@ -0,0 +1,22 @@
+.spoiler {
+ border-left: 4px solid #d08770;
+ margin: 1rem auto;
+ color: #e4f1fe;
+ background-color: #564d33;
+ max-width: var(--design-width);
+ width: 100%;
+ border-radius: .5rem;
+
+ summary {
+ user-select: none;
+ cursor: pointer;
+ display: block;
+ padding-left: 1rem;
+ font-weight: bold;
+
+ &:hover {
+ text-decoration: underline;
+ color: #fff;
+ }
+ }
+}
diff --git a/resources/css/drop.css b/resources/css/drop.css
new file mode 100644
index 0000000..2578867
--- /dev/null
+++ b/resources/css/drop.css
@@ -0,0 +1,79 @@
+.drop {
+ padding: 2px 5px;
+ display: block;
+ color: #6c7a89;
+ text-decoration: none;
+ white-space: nowrap;
+ position: relative;
+
+ summary {
+ display: block;
+ cursor: pointer;
+ user-select: none;
+ }
+
+ summary::-webkit-details-marker {
+ display: none;
+ }
+
+ summary::after {
+ margin-left: .5em;
+ font-family: monospace;
+ content: '▶';
+ }
+
+ &.down {
+ summary ~ * {
+ top: 2em;
+ }
+
+ &[open] {
+ summary::after {
+ font-family: monospace;
+ content: '▼';
+ }
+ }
+ }
+
+ &.up {
+ summary ~ * {
+ bottom: 2em;
+ }
+
+ &[open] {
+ summary::after {
+ font-family: monospace;
+ content: '▲';
+ }
+ }
+ }
+
+ summary ~ * {
+ z-index: 100;
+ position: absolute;
+ border: solid 2px #00101f;
+ border-radius: .5em;
+ background: #01010c radial-gradient(at bottom center, #00101f, #000614, #01010c) no-repeat;
+ box-shadow: 0 1px 1em #000;
+ max-height: 50vh;
+ overflow: auto;
+ left: 30%;
+ }
+
+ nav a {
+ display: block;
+ padding: .2em 3em;
+ color: #6c7a89;
+ text-decoration: none;
+
+ &.selected {
+ color: orange;
+ }
+
+ &:hover {
+ color: #fff;
+ text-decoration: underline;
+ background: #01010c radial-gradient(at bottom center, #00101f, #000614, #01010c) no-repeat;
+ }
+ }
+}
diff --git a/resources/css/figure.css b/resources/css/figure.css
new file mode 100644
index 0000000..d72d699
--- /dev/null
+++ b/resources/css/figure.css
@@ -0,0 +1,39 @@
+figure {
+ width: var(--design-width);
+ margin: 1rem auto;
+
+ img,
+ video {
+ max-width: 100%;
+ max-height: 80vh;
+ height: auto;
+ margin: auto;
+ border-radius: .5rem;
+ opacity: .5;
+
+ &:hover {
+ opacity: 1;
+ }
+
+ &.bg-white {
+ background-color: #fff;
+ }
+ }
+
+ audio {
+ margin: auto;
+ display: block;
+ }
+
+ figcaption {
+ line-height: 125%;
+ margin: .75rem auto;
+ text-align: center;
+ color: #a8b4bd;
+ font-size: .85em;
+
+ p {
+ text-align: center !important;
+ }
+ }
+}
diff --git a/resources/css/footnotes.css b/resources/css/footnotes.css
new file mode 100644
index 0000000..8ef23b2
--- /dev/null
+++ b/resources/css/footnotes.css
@@ -0,0 +1,28 @@
+.footnote-ref {
+ font-size: .8rem;
+}
+
+.footnotes {
+ font-size: 1rem;
+ line-height: 1.4;
+ color: #ccc;
+ background-color: #1e2230;
+ border-top: 1px solid #444;
+ padding: 10px 20px;
+ margin-top: 20px;
+ width: 100%;
+ box-sizing: border-box;
+}
+
+.footnotes hr {
+ display: none;
+}
+
+.footnotes ol {
+ padding-left: 20px;
+ list-style-type: decimal;
+}
+
+.footnotes li {
+ margin-bottom: 5px;
+}
diff --git a/resources/css/form.css b/resources/css/form.css
new file mode 100644
index 0000000..8cac71c
--- /dev/null
+++ b/resources/css/form.css
@@ -0,0 +1,35 @@
+form {
+ width: var(--design-width);
+ margin: auto;
+
+ input[type=checkbox] {
+ display: none;
+ }
+
+ input[type=email] {
+ display: block;
+ border-radius: .5rem;
+ color: #fff;
+ background-color: #1a1f33;
+ border: none;
+ margin: auto;
+ padding: .2rem .5rem;
+ text-align: center;
+ }
+
+ input[type=submit] {
+ display: block;
+ border-radius: .5rem;
+ color: #fff;
+ background-color: #1a1f33;
+ border: none;
+ margin: .5rem auto;
+ padding: .2rem 1rem;
+ cursor: pointer;
+
+ &:hover {
+ background-color: darkgreen;
+ text-decoration: none;
+ }
+ }
+}
diff --git a/resources/css/links.css b/resources/css/links.css
new file mode 100644
index 0000000..6ab1e25
--- /dev/null
+++ b/resources/css/links.css
@@ -0,0 +1,31 @@
+a {
+ color: #60a5fa;
+
+ &:hover {
+ color: #bfdbfe;
+ }
+
+ &.external {
+ color: #34d399;
+
+ &:hover {
+ color: #a7f3d0;
+ }
+ }
+
+ &.affiliate {
+ color: #e879f9;
+
+ &:hover {
+ color: #f5d0fe;
+ }
+ }
+
+ &.dead {
+ color: #ff0000;
+
+ &:hover {
+ color: #ffa07a;
+ }
+ }
+}
diff --git a/resources/css/paginator.css b/resources/css/paginator.css
new file mode 100644
index 0000000..dfcdf3f
--- /dev/null
+++ b/resources/css/paginator.css
@@ -0,0 +1,52 @@
+.paginator {
+ color: #6c7a89;
+ text-align: center;
+ background: #01010c radial-gradient(at bottom center, #00101f, #000614, #01010c) no-repeat;
+ box-shadow: 0 1px 1rem #000;
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ border-radius: .5rem;
+ border: solid 2px #00101f;
+ margin: 1rem;
+ padding: .5rem 1rem;
+
+ &.up {
+ margin-top: 2rem;
+ }
+
+ &.down {
+ margin-bottom: 2rem;
+ }
+
+ a {
+ color: #ccc;
+ text-decoration: none;
+ display: block;
+
+ &:hover {
+ color: #fff;
+ }
+ }
+
+ > details {
+ grid-column: 2;
+ }
+
+ .left {
+ text-align: left;
+ grid-column: 1;
+ }
+
+ .right {
+ text-align: right;
+ grid-column: 3;
+ }
+
+ .paginator-filters {
+ grid-column: 1 / 4;
+ font-size: .6rem;
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+ }
+}
diff --git a/resources/css/site-footer.css b/resources/css/site-footer.css
new file mode 100644
index 0000000..54c9b7e
--- /dev/null
+++ b/resources/css/site-footer.css
@@ -0,0 +1,16 @@
+body > footer {
+ background-color: #001;
+ padding: 2rem;
+ font-size: 1rem;
+
+ nav {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ a {
+ text-decoration: none;
+ margin: 0 2rem;
+ }
+ }
+}
diff --git a/resources/css/site-header.css b/resources/css/site-header.css
new file mode 100644
index 0000000..8b7fea6
--- /dev/null
+++ b/resources/css/site-header.css
@@ -0,0 +1,42 @@
+body > header {
+ margin: auto;
+ text-align: center;
+
+ nav {
+ margin: .5rem auto 1rem auto;
+ text-align: center;
+ font-family: sans-serif;
+ text-transform: uppercase;
+ font-size: .6em;
+
+ a {
+ color: #6c7a89;
+ display: inline-block;
+ padding: .5rem 1rem;
+ text-decoration: none;
+
+ &:hover {
+ color: #e4f1fe;
+ text-decoration: none;
+ }
+ }
+ }
+
+ #logo {
+ display: block;
+ width: 256px;
+ height: 256px;
+ margin: auto;
+ border-radius: 100%;
+ background-image: var(--logo-large-url);
+ text-decoration: none;
+ border: solid 2px #00101f;
+ box-shadow: 0 0 1rem #000;
+
+ &:hover {
+ background-image: var(--logo-large-hover-url);
+ box-shadow: 0 0 1rem #006bc3;
+ text-decoration: none;
+ }
+ }
+}
diff --git a/resources/css/tables.css b/resources/css/tables.css
new file mode 100644
index 0000000..848f919
--- /dev/null
+++ b/resources/css/tables.css
@@ -0,0 +1,27 @@
+table {
+ width: var(--design-width); /* Utilise toute la largeur disponible */
+ border-collapse: collapse; /* Les bordures des cellules sont fusionnées */
+ margin: 1em auto; /* Espacement autour du tableau */
+ background-color: #282c34; /* Fond sombre pour les tableaux */
+ color: #e4f1fe; /* Texte en couleur claire pour un bon contraste */
+ box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15); /* Ombre subtile pour un effet de profondeur */
+ font-size: 1rem;
+ line-height: 125%;
+}
+
+th,
+td {
+ border: 1px solid #3a3f4b; /* Bordures des cellules en gris sombre */
+ padding: 8px 12px; /* Padding pour rendre le texte plus lisible */
+ text-align: left; /* Alignement du texte à gauche */
+ vertical-align: middle; /* Alignement vertical au milieu */
+}
+
+th {
+ background-color: #1c2028; /* Fond des entêtes un peu plus distinct */
+ font-weight: bold; /* Texte en gras pour les entêtes */
+}
+
+tbody tr:nth-child(odd) {
+ background-color: #32363f; /* Alternance de couleurs pour les lignes */
+}
diff --git a/resources/css/utilities.css b/resources/css/utilities.css
new file mode 100644
index 0000000..dd0e421
--- /dev/null
+++ b/resources/css/utilities.css
@@ -0,0 +1,3 @@
+.hidden {
+ display: none;
+}
diff --git a/resources/views/article-card.blade.php b/resources/views/article-card.blade.php
new file mode 100644
index 0000000..4a96e93
--- /dev/null
+++ b/resources/views/article-card.blade.php
@@ -0,0 +1,16 @@
+
+ {!! $section->getArticleTitle() !!}{!! $bundle->getArticleTitle() !!}
+