diff --git a/UPDATE.md b/UPDATE.md
index fe8923ae62f1df7a40c18e59edfc2139f7c711e7..1185b00b58d6e393a2100519ae53c4f7234f0faa 100644
--- a/UPDATE.md
+++ b/UPDATE.md
@@ -59,7 +59,7 @@ performance improvements âš¡.
 ### Where can I find my _Castopod Host_ version?
 
 Go to your _Castopod Host_ admin panel, the version is displayed on the bottom
-right corner.
+left corner.
 
 Alternatively, you can find the version in the `app > Config > Constants.php`
 file.
diff --git a/app/Entities/Episode.php b/app/Entities/Episode.php
index 57c4e672b8381cd6759e7626d31c06b651265758..80286775bf7f0262be4d2c59801af572bc27fe6e 100644
--- a/app/Entities/Episode.php
+++ b/app/Entities/Episode.php
@@ -275,7 +275,7 @@ class Episode extends Entity
             ]);
             $transcript->setFile($file);
 
-            $this->attributes['transcript_id'] = (new MediaModel())->saveMedia($transcript);
+            $this->attributes['transcript_id'] = (new MediaModel('transcript'))->saveMedia($transcript);
         }
 
         return $this;
@@ -313,7 +313,7 @@ class Episode extends Entity
             ]);
             $chapters->setFile($file);
 
-            $this->attributes['chapters_id'] = (new MediaModel())->saveMedia($chapters);
+            $this->attributes['chapters_id'] = (new MediaModel('chapters'))->saveMedia($chapters);
         }
 
         return $this;
diff --git a/app/Entities/Media/BaseMedia.php b/app/Entities/Media/BaseMedia.php
index 5dbed8799d2c06ee0102938f6dc4b22b4d775bba..6417095cce68e35398a17920e955b344ecba22fe 100644
--- a/app/Entities/Media/BaseMedia.php
+++ b/app/Entities/Media/BaseMedia.php
@@ -20,7 +20,6 @@ use CodeIgniter\Files\File;
  * @property string $file_directory
  * @property string $file_extension
  * @property string $file_name
- * @property string $file_name_with_extension
  * @property int $file_size
  * @property string $file_mimetype
  * @property array|null $file_metadata
@@ -80,7 +79,6 @@ class BaseMedia extends Entity
             $this->attributes['file_name'] = $filename;
             $this->attributes['file_directory'] = $dirname;
             $this->attributes['file_extension'] = $extension;
-            $this->attributes['file_name_with_extension'] = "{$filename}.{$extension}";
         }
     }
 
diff --git a/app/Entities/Media/Transcript.php b/app/Entities/Media/Transcript.php
index 2a06ef1d4c94bf2c40c78cfaa461b16f6a2ea63b..bbdb35aadfb3dd8b6716b0bbcbc3bb171bd69b71 100644
--- a/app/Entities/Media/Transcript.php
+++ b/app/Entities/Media/Transcript.php
@@ -10,7 +10,65 @@ declare(strict_types=1);
 
 namespace App\Entities\Media;
 
+use App\Libraries\TranscriptParser;
+use CodeIgniter\Files\File;
+
 class Transcript extends BaseMedia
 {
     protected string $type = 'transcript';
+
+    protected ?string $json_path = null;
+
+    protected ?string $json_url = null;
+
+    public function initFileProperties(): void
+    {
+        parent::initFileProperties();
+
+        if ($this->file_path && $this->file_metadata && array_key_exists('json_path', $this->file_metadata)) {
+            helper('media');
+
+            $this->json_path = media_path($this->file_metadata['json_path']);
+            $this->json_url = media_base_url($this->file_metadata['json_path']);
+        }
+    }
+
+    public function setFile(File $file): self
+    {
+        parent::setFile($file);
+
+        $content = file_get_contents(media_path($this->attributes['file_path']));
+
+        if ($content === false) {
+            return $this;
+        }
+
+        $metadata = [];
+        if ($fileMetadata = lstat((string) $file)) {
+            $metadata = $fileMetadata;
+        }
+
+        $transcriptParser = new TranscriptParser();
+        $jsonFilePath = $this->attributes['file_directory'] . '/' . $this->attributes['file_name'] . '.json';
+        if (($transcriptJson = $transcriptParser->loadString($content)->parseSrt()) && file_put_contents(
+            media_path($jsonFilePath),
+            $transcriptJson
+        )) {
+            // set metadata (generated json file path)
+            $metadata['json_path'] = $jsonFilePath;
+        }
+
+        $this->attributes['file_metadata'] = json_encode($metadata);
+
+        return $this;
+    }
+
+    public function deleteFile(): void
+    {
+        parent::deleteFile();
+
+        if ($this->json_path) {
+            unlink($this->json_path);
+        }
+    }
 }
diff --git a/app/Helpers/misc_helper.php b/app/Helpers/misc_helper.php
index a270890745b01a1eb0e1e25887c97f28ad0deb64..133302e3d581336c025091bcc4f7d6ce6c6747b6 100644
--- a/app/Helpers/misc_helper.php
+++ b/app/Helpers/misc_helper.php
@@ -206,3 +206,64 @@ if (! function_exists('podcast_uuid')) {
 }
 
 //--------------------------------------------------------------------
+
+
+if (! function_exists('file_upload_max_size')) {
+
+    /**
+     * Returns a file size limit in bytes based on the PHP upload_max_filesize and post_max_size Adapted from:
+     * https://stackoverflow.com/a/25370978
+     */
+    function file_upload_max_size(): float
+    {
+        static $max_size = -1;
+
+        if ($max_size < 0) {
+            // Start with post_max_size.
+            $post_max_size = parse_size((string) ini_get('post_max_size'));
+            if ($post_max_size > 0) {
+                $max_size = $post_max_size;
+            }
+
+            // If upload_max_size is less, then reduce. Except if upload_max_size is
+            // zero, which indicates no limit.
+            $upload_max = parse_size((string) ini_get('upload_max_filesize'));
+            if ($upload_max > 0 && $upload_max < $max_size) {
+                $max_size = $upload_max;
+            }
+        }
+        return $max_size;
+    }
+}
+
+if (! function_exists('parse_size')) {
+    function parse_size(string $size): float
+    {
+        $unit = (string) preg_replace('~[^bkmgtpezy]~i', '', $size); // Remove the non-unit characters from the size.
+        $size = (float) preg_replace('~[^0-9\.]~', '', $size); // Remove the non-numeric characters from the size.
+        if ($unit !== '') {
+            // Find the position of the unit in the ordered string which is the power of magnitude to multiply a kilobyte by.
+            return round($size * pow(1024, (float) stripos('bkmgtpezy', $unit[0])));
+        }
+
+        return round($size);
+    }
+}
+
+if (! function_exists('format_bytes')) {
+    /**
+     * Adapted from https://stackoverflow.com/a/2510459
+     */
+    function formatBytes(float $bytes, int $precision = 2): string
+    {
+        $units = ['B', 'KiB', 'MiB', 'GiB', 'TiB'];
+
+        $bytes = max($bytes, 0);
+        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
+        $pow = min($pow, count($units) - 1);
+
+        $bytes /= pow(1024, $pow);
+
+        return round($bytes, $precision) . $units[$pow];
+    }
+}
diff --git a/app/Libraries/TranscriptParser.php b/app/Libraries/TranscriptParser.php
new file mode 100644
index 0000000000000000000000000000000000000000..66c07b6e580c0d02c3d692e2f7857404b9852539
--- /dev/null
+++ b/app/Libraries/TranscriptParser.php
@@ -0,0 +1,95 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * Generates and renders a breadcrumb based on the current url segments
+ *
+ * @copyright  2022 Podlibre
+ * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
+ * @link       https://castopod.org/
+ */
+
+namespace App\Libraries;
+
+use stdClass;
+
+class TranscriptParser
+{
+    protected string $transcriptContent;
+
+    public function loadString(string $content): self
+    {
+        $this->transcriptContent = $content;
+
+        return $this;
+    }
+
+    /**
+     * Adapted from: https://stackoverflow.com/a/11659306
+     */
+    public function parseSrt(): string | false
+    {
+        define('SRT_STATE_SUBNUMBER', 0);
+        define('SRT_STATE_TIME', 1);
+        define('SRT_STATE_TEXT', 2);
+        define('SRT_STATE_BLANK', 3);
+
+        $subs = [];
+        $state = SRT_STATE_SUBNUMBER;
+        $subNum = 0;
+        $subText = '';
+        $subTime = '';
+
+        $lines = explode(PHP_EOL, $this->transcriptContent);
+        foreach ($lines as $line) {
+            // @phpstan-ignore-next-line
+            switch ($state) {
+                case SRT_STATE_SUBNUMBER:
+                    $subNum = trim($line);
+                    $state = SRT_STATE_TIME;
+                    break;
+
+                case SRT_STATE_TIME:
+                    $subTime = trim($line);
+                    $state = SRT_STATE_TEXT;
+                    break;
+
+                case SRT_STATE_TEXT:
+                    if (trim($line) === '') {
+                        $sub = new stdClass();
+                        $sub->number = (int) $subNum;
+                        [$startTime, $endTime] = explode(' --> ', $subTime);
+                        $sub->startTime = $this->getSecondsFromTimeString($startTime);
+                        $sub->endTime = $this->getSecondsFromTimeString($endTime);
+                        $sub->text = trim($subText);
+                        $subText = '';
+                        $state = SRT_STATE_SUBNUMBER;
+
+                        $subs[] = $sub;
+                    } else {
+                        $subText .= $line;
+                    }
+                    break;
+
+            }
+        }
+
+        if ($state === SRT_STATE_TEXT) {
+            // if file was missing the trailing newlines, we'll be in this
+            // state here.  Append the last read text and add the last sub.
+            // @phpstan-ignore-next-line
+            $sub->text = $subText;
+            // @phpstan-ignore-next-line
+            $subs[] = $sub;
+        }
+
+        return json_encode($subs, JSON_PRETTY_PRINT);
+    }
+
+    private function getSecondsFromTimeString(string $timeString): float
+    {
+        $timeString = explode(',', $timeString);
+        return (strtotime($timeString[0]) - strtotime('TODAY')) + (float) "0.{$timeString[1]}";
+    }
+}
diff --git a/app/Resources/icons/file-download.svg b/app/Resources/icons/file-download.svg
new file mode 100644
index 0000000000000000000000000000000000000000..0202c99a7f1d9b640d1beb0c9b96b8c1e59ae442
--- /dev/null
+++ b/app/Resources/icons/file-download.svg
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+    <g>
+        <path fill="none" d="M0 0h24v24H0z"/>
+        <path d="M16 2l5 5v14.008a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992C3 2.444 3.445 2 3.993 2H16zm-3 10V8h-2v4H8l4 4 4-4h-3z"/>
+    </g>
+</svg>
diff --git a/app/Resources/icons/file.svg b/app/Resources/icons/file.svg
deleted file mode 100755
index d10c86cf8168c2a1ec7e1ed6b16c96ada84cdcb4..0000000000000000000000000000000000000000
--- a/app/Resources/icons/file.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
-    <g>
-        <path fill="none" d="M0 0h24v24H0z"/>
-        <path d="M19 22H5a3 3 0 0 1-3-3V3a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v12h4v4a3 3 0 0 1-3 3zm-1-5v2a1 1 0 0 0 2 0v-2h-2zM6 7v2h8V7H6zm0 4v2h8v-2H6zm0 4v2h5v-2H6z"/>
-    </g>
-</svg>
diff --git a/app/Resources/js/admin.ts b/app/Resources/js/admin.ts
index d9ee93cb82b12369e8c7f060e6dde87eff1cf6cb..078e919f88bf160e0b0dca18bec6d66abb5d4089 100644
--- a/app/Resources/js/admin.ts
+++ b/app/Resources/js/admin.ts
@@ -18,6 +18,7 @@ import Slugify from "./modules/Slugify";
 import ThemePicker from "./modules/ThemePicker";
 import Time from "./modules/Time";
 import Tooltip from "./modules/Tooltip";
+import ValidateFileSize from "./modules/ValidateFileSize";
 import "./modules/video-clip-previewer";
 import VideoClipBuilder from "./modules/VideoClipBuilder";
 import "./modules/xml-editor";
@@ -35,4 +36,5 @@ Clipboard();
 ThemePicker();
 PublishMessageWarning();
 HotKeys();
+ValidateFileSize();
 VideoClipBuilder();
diff --git a/app/Resources/js/modules/ValidateFileSize.ts b/app/Resources/js/modules/ValidateFileSize.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b843d5eaa5e74a1dfb75bc9c33cb6e4dab8b1e19
--- /dev/null
+++ b/app/Resources/js/modules/ValidateFileSize.ts
@@ -0,0 +1,22 @@
+const ValidateFileSize = (): void => {
+  const fileInputContainers: NodeListOf<HTMLInputElement> =
+    document.querySelectorAll("[data-max-size]");
+
+  for (let i = 0; i < fileInputContainers.length; i++) {
+    const fileInput = fileInputContainers[i] as HTMLInputElement;
+
+    fileInput.addEventListener("change", () => {
+      if (fileInput.files) {
+        const fileSize = fileInput.files[0].size;
+
+        if (fileSize > parseFloat(fileInput.dataset.maxSize ?? "0")) {
+          alert(fileInput.dataset.maxSizeError);
+          // remove the selected file by resetting input to prevent from uploading it.
+          fileInput.value = "";
+        }
+      }
+    });
+  }
+};
+
+export default ValidateFileSize;
diff --git a/modules/Admin/Controllers/EpisodeController.php b/modules/Admin/Controllers/EpisodeController.php
index 01dbb051a6f2a39f1ef299d5901ec843c09f6c04..2594972ea4fd4ff4ba51338b3da88f4eb854cdcd 100644
--- a/modules/Admin/Controllers/EpisodeController.php
+++ b/modules/Admin/Controllers/EpisodeController.php
@@ -116,7 +116,7 @@ class EpisodeController extends BaseController
             'cover' =>
                 'is_image[cover]|ext_in[cover,jpg,png]|min_dims[cover,1400,1400]|is_image_ratio[cover,1,1]',
             'transcript_file' =>
-                'ext_in[transcript,txt,html,srt,json]|permit_empty',
+                'ext_in[transcript,srt]|permit_empty',
             'chapters_file' => 'ext_in[chapters,json]|permit_empty',
         ];
 
diff --git a/modules/Admin/Language/en/Common.php b/modules/Admin/Language/en/Common.php
index d105e76d0d9371f60ca4f9255fef0493b06527ae..58a0a48667fb90c795f6bf1a31d488e6eb482fdf 100644
--- a/modules/Admin/Language/en/Common.php
+++ b/modules/Admin/Language/en/Common.php
@@ -45,4 +45,5 @@ return [
         'play' => 'Play',
         'playing' => 'Playing',
     ],
+    'size_limit' => 'Size limit: {0}.',
 ];
diff --git a/modules/Admin/Language/en/Episode.php b/modules/Admin/Language/en/Episode.php
index cce9992ff7716f0d7053d877faef5ff449746fa9..7188b60c924df6a57258ee42ec302b14369bb444 100644
--- a/modules/Admin/Language/en/Episode.php
+++ b/modules/Admin/Language/en/Episode.php
@@ -48,8 +48,8 @@ return [
         'editSuccess' => 'Episode has been successfully updated!',
     ],
     'form' => [
-        'warning' =>
-            'In case of fatal error, try increasing the `memory_limit`, `upload_max_filesize` and `post_max_size` values in your php configuration file then restart your web server.<br />These values must be higher than the audio file you wish to upload.',
+        'file_size_error' =>
+            'Your file size is too big! Max size is {0}. Increase the `memory_limit`, `upload_max_filesize` and `post_max_size` values in your php configuration file then restart your web server to upload your file.',
         'audio_file' => 'Audio file',
         'audio_file_hint' => 'Choose an .mp3 or .m4a audio file.',
         'info_section_title' => 'Episode info',
@@ -93,13 +93,15 @@ return [
         'location_section_subtitle' => 'What place is this episode about?',
         'location_name' => 'Location name or address',
         'location_name_hint' => 'This can be a real or fictional location',
-        'transcript' => 'Transcript or closed captions',
-        'transcript_hint' => 'Allowed formats are txt, html, srt or json.',
-        'transcript_file' => 'Transcript file',
+        'transcript' => 'Transcript (subtitles / closed captions)',
+        'transcript_hint' => 'Only .srt are allowed.',
+        'transcript_download' => 'Download transcript',
+        'transcript_file' => 'Transcript file (.srt)',
         'transcript_remote_url' => 'Remote url for transcript',
         'transcript_file_delete' => 'Delete transcript file',
         'chapters' => 'Chapters',
         'chapters_hint' => 'File must be in JSON Chapters format.',
+        'chapters_download' => 'Download chapters',
         'chapters_file' => 'Chapters file',
         'chapters_remote_url' => 'Remote url for chapters file',
         'chapters_file_delete' => 'Delete chapters file',
diff --git a/modules/Admin/Language/fr/Common.php b/modules/Admin/Language/fr/Common.php
index f856cf907362fa5b5565cf524b7d47c47e245457..531a8e5920c87c7996c947f3fc0bb9d007df1fdc 100644
--- a/modules/Admin/Language/fr/Common.php
+++ b/modules/Admin/Language/fr/Common.php
@@ -45,4 +45,5 @@ return [
         'play' => 'Lire',
         'playing' => 'En cours',
     ],
+    'size_limit' => 'Taille maximale : {0}.',
 ];
diff --git a/modules/Admin/Language/fr/Episode.php b/modules/Admin/Language/fr/Episode.php
index 1ff5a800af82dad7b23c58efebc31a2b37e571fd..610bb35f3a360d35412913c2032bf1c7bc16aa54 100644
--- a/modules/Admin/Language/fr/Episode.php
+++ b/modules/Admin/Language/fr/Episode.php
@@ -49,8 +49,8 @@ return [
         'editSuccess' => 'L’épisode a bien été mis à jour !',
     ],
     'form' => [
-        'warning' =>
-            'En cas d’erreur fatale, essayez d’augmenter les valeurs de `memory_limit`, `upload_max_filesize` et `post_max_size` dans votre fichier de configuration php puis redémarrez votre serveur web.<br />Les valeurs doivent être plus grandes que le fichier audio que vous souhaitez téléverser.',
+        'file_size_error' =>
+            'Votre fichier est trop lourd ! La taille maximale est de {0}. Augmentez les valeurs de `memory_limit`, `upload_max_filesize` et `post_max_size` dans votre fichier de configuration php puis redémarrez votre serveur web pour téléverser votre fichier.',
         'audio_file' => 'Fichier audio',
         'audio_file_hint' => 'Sélectionnez un fichier audio .mp3 ou .m4a.',
         'info_section_title' => 'Informations épisode',
@@ -94,15 +94,16 @@ return [
         'location_section_subtitle' => 'De quel lieu cet épisode parle-t-il ?',
         'location_name' => 'Nom ou adresse du lieu',
         'location_name_hint' => 'Ce lieu peut être réel ou fictif',
-        'transcript' => 'Transcription ou sous-titrage',
-        'transcript_hint' =>
-            'Les formats autorisés sont txt, html, srt ou json.',
-        'transcript_file' => 'Fichier de transcription',
+        'transcript' => 'Transcription (sous-titrage)',
+        'transcript_hint' => 'Seulement les .srt sont autorisés',
+        'transcript_download' => 'Télécharger le transcript',
+        'transcript_file' => 'Fichier de transcription (.srt)',
         'transcript_remote_url' =>
             'URL distante pour le fichier de transcription',
         'transcript_file_delete' => 'Supprimer le fichier de transcription',
         'chapters' => 'Chapitrage',
         'chapters_hint' => 'Le fichier doit être en format “JSON Chapters”.',
+        'chapters_download' => 'Télécharger le chapitrage',
         'chapters_file' => 'Fichier de chapitrage',
         'chapters_remote_url' =>
             'URL distante pour le fichier de chapitrage',
diff --git a/themes/cp_admin/episode/create.php b/themes/cp_admin/episode/create.php
index 39a440cf5cfe6d1c0c6b3cb3323fedebe3a44d6c..90eb4b7f84f271918e9e43c6d35a703c9f3875ed 100644
--- a/themes/cp_admin/episode/create.php
+++ b/themes/cp_admin/episode/create.php
@@ -11,8 +11,6 @@
 
 <?= $this->section('content') ?>
 
-<Alert variant="danger" glyph="alert" class="max-w-xl"><?= lang('Episode.form.warning') ?></Alert>
-
 <form action="<?= route_to('episode-create', $podcast->id) ?>" method="POST" enctype="multipart/form-data" class="flex flex-col max-w-xl mt-6 gap-y-8">
 <?= csrf_field() ?>
 
@@ -23,9 +21,12 @@
     name="audio_file"
     label="<?= lang('Episode.form.audio_file') ?>"
     hint="<?= lang('Episode.form.audio_file_hint') ?>"
+    helper="<?= lang('Common.size_limit', [formatBytes(file_upload_max_size())]) ?>"
     type="file"
     accept=".mp3,.m4a"
-    required="true" />
+    required="true"
+    data-max-size="<?= file_upload_max_size() ?>"
+    data-max-size-error="<?= lang('Episode.form.file_size_error', [formatBytes(file_upload_max_size())]) ?>" />
 
 <Forms.Field
     name="cover"
diff --git a/themes/cp_admin/episode/edit.php b/themes/cp_admin/episode/edit.php
index b693cb9a09fabcbb9c482d2a1f53a89b358fb5ad..86a5bc9856db840f1136f44d8ea0306f2b8cc594 100644
--- a/themes/cp_admin/episode/edit.php
+++ b/themes/cp_admin/episode/edit.php
@@ -15,8 +15,6 @@
 
 <?= $this->section('content') ?>
 
-<Alert variant="danger" glyph="alert" class="max-w-xl"><?= lang('Episode.form.warning') ?></Alert>
-
 <form id="episode-edit-form" action="<?= route_to('episode-edit', $podcast->id, $episode->id) ?>" method="POST" enctype="multipart/form-data" class="flex flex-col max-w-xl mt-6 gap-y-8">
 <?= csrf_field() ?>
 
@@ -27,14 +25,17 @@
     name="audio_file"
     label="<?= lang('Episode.form.audio_file') ?>"
     hint="<?= lang('Episode.form.audio_file_hint') ?>"
+    helper="<?= lang('Common.size_limit', [formatBytes(file_upload_max_size())]) ?>"
     type="file"
-    accept=".mp3,.m4a" />
+    accept=".mp3,.m4a"
+    data-max-size="<?= file_upload_max_size() ?>"
+    data-max-size-error="<?= lang('Episode.form.file_size_error', [formatBytes(file_upload_max_size())]) ?>" />
 
 <Forms.Field
     name="cover"
     label="<?= lang('Episode.form.cover') ?>"
     hint="<?= lang('Episode.form.cover_hint') ?>"
-    helper="<?= lang('Episode.form.cover_size_hint', ) ?>"
+    helper="<?= lang('Episode.form.cover_size_hint') ?>"
     type="file"
     accept=".jpg,.jpeg,.png" />
 
@@ -166,12 +167,10 @@
                 <div class="flex items-center mb-1 gap-x-2">
                     <?= anchor(
                 $episode->transcript->file_url,
-                icon('file', 'mr-2 text-skin-muted') .
-                            $episode->transcript->file_name_with_extension,
+                icon('file-download', 'mr-1 text-skin-muted text-xl') . lang('Episode.form.transcript_download'),
                 [
-                    'class' => 'inline-flex items-center text-xs',
-                    'target' => '_blank',
-                    'rel' => 'noreferrer noopener',
+                    'class' => 'flex-1 font-semibold hover:underline inline-flex items-center text-xs',
+                    'download' => '',
                 ],
             ) .
                         anchor(
@@ -223,11 +222,10 @@
                 <div class="flex mb-1 gap-x-2">
                     <?= anchor(
                 $episode->chapters->file_url,
-                icon('file', 'mr-2') . $episode->chapters->file_name_with_extension,
+                icon('file-download', 'mr-1 text-skin-muted text-xl') . lang('Episode.form.chapters_download'),
                 [
-                    'class' => 'inline-flex items-center text-xs',
-                    'target' => '_blank',
-                    'rel' => 'noreferrer noopener',
+                    'class' => 'flex-1 font-semibold hover:underline inline-flex items-center text-xs',
+                    'download' => '',
                 ],
             ) .
                     anchor(