diff --git a/app/Helpers/components_helper.php b/app/Helpers/components_helper.php
index 89c5a121a757e95258b653bbe994567e0cca5dae..2d12bc3deebb746935a187cc151ad44e1d477add 100644
--- a/app/Helpers/components_helper.php
+++ b/app/Helpers/components_helper.php
@@ -85,7 +85,13 @@ if (! function_exists('data_table')) {
                 $table->addRow($rowData);
             }
         } else {
-            return lang('Common.no_data');
+            $table->addRow([
+                [
+                    'colspan' => count($tableHeaders),
+                    'class' => 'px-4 py-2 italic font-semibold text-center',
+                    'data' => lang('Common.no_data'),
+                ],
+            ]);
         }
 
         return '<div class="overflow-x-auto rounded-lg bg-elevated border-3 border-subtle ' . $class . '" >' .
diff --git a/app/Libraries/MediaClipper/Config/MediaClipper.php b/app/Libraries/MediaClipper/Config/MediaClipper.php
index e300f24db0e613ecff4a01c59e4b5504d9fbc77a..f4274d6de256761f601f4dfc9e23fa3e43e6d661 100644
--- a/app/Libraries/MediaClipper/Config/MediaClipper.php
+++ b/app/Libraries/MediaClipper/Config/MediaClipper.php
@@ -213,7 +213,7 @@ class MediaClipper extends BaseConfig
                 'rescaleHeight' => 1200,
                 'x' => 0,
                 'y' => 600,
-                'mask' => APPPATH . 'Libraries/MediaClipper/soundwaves-mask-square.png',
+                'mask' => APPPATH . 'Libraries/MediaClipper/soundwaves-mask-squared.png',
             ],
             'subtitles' => [
                 'fontsize' => 20,
diff --git a/app/Resources/js/admin.ts b/app/Resources/js/admin.ts
index a626874e5c7cd4583f7d38961f2f1d4793aa706a..310cc336b8e987d9ab3d51a8977a493993282797 100644
--- a/app/Resources/js/admin.ts
+++ b/app/Resources/js/admin.ts
@@ -19,6 +19,7 @@ import ThemePicker from "./modules/ThemePicker";
 import Time from "./modules/Time";
 import Tooltip from "./modules/Tooltip";
 import "./modules/video-clip-previewer";
+import VideoClipBuilder from "./modules/VideoClipBuilder";
 import "./modules/xml-editor";
 
 Dropdown();
@@ -35,3 +36,4 @@ Clipboard();
 ThemePicker();
 PublishMessageWarning();
 HotKeys();
+VideoClipBuilder();
diff --git a/app/Resources/js/modules/VideoClipBuilder.ts b/app/Resources/js/modules/VideoClipBuilder.ts
new file mode 100644
index 0000000000000000000000000000000000000000..11c1a637fbb376b4fd3c8bdaca69a05817cee0a5
--- /dev/null
+++ b/app/Resources/js/modules/VideoClipBuilder.ts
@@ -0,0 +1,70 @@
+const VideoClipBuilder = (): void => {
+  const form = document.querySelector("form[id=new-video-clip-form]");
+
+  if (form) {
+    const videoClipPreviewer = form?.querySelector("video-clip-previewer");
+
+    if (videoClipPreviewer) {
+      const themeOptions: NodeListOf<HTMLInputElement> = form.querySelectorAll(
+        'input[name="theme"]'
+      ) as NodeListOf<HTMLInputElement>;
+      const formatOptions: NodeListOf<HTMLInputElement> = form.querySelectorAll(
+        'input[name="format"]'
+      ) as NodeListOf<HTMLInputElement>;
+
+      const titleInput = form.querySelector(
+        'input[name="label"]'
+      ) as HTMLInputElement;
+      if (titleInput) {
+        videoClipPreviewer.setAttribute("title", titleInput.value || "");
+        titleInput.addEventListener("input", () => {
+          videoClipPreviewer.setAttribute("title", titleInput.value || "");
+        });
+      }
+
+      let format = (
+        form.querySelector('input[name="format"]:checked') as HTMLInputElement
+      )?.value;
+      videoClipPreviewer.setAttribute("format", format);
+      const watchFormatChange = (event: Event) => {
+        format = (event.target as HTMLInputElement).value;
+        videoClipPreviewer.setAttribute("format", format);
+      };
+      for (let i = 0; i < formatOptions.length; i++) {
+        formatOptions[i].addEventListener("change", watchFormatChange);
+      }
+
+      let theme = form
+        .querySelector('input[name="theme"]:checked')
+        ?.parentElement?.style.getPropertyValue("--color-accent-base");
+      videoClipPreviewer.setAttribute("theme", theme || "");
+
+      const watchThemeChange = (event: Event) => {
+        theme =
+          (
+            event.target as HTMLInputElement
+          ).parentElement?.style.getPropertyValue("--color-accent-base") ??
+          theme;
+        videoClipPreviewer.setAttribute("theme", theme || "");
+      };
+      for (let i = 0; i < themeOptions.length; i++) {
+        themeOptions[i].addEventListener("change", watchThemeChange);
+      }
+
+      const durationInput = form.querySelector(
+        'input[name="duration"]'
+      ) as HTMLInputElement;
+      if (durationInput) {
+        videoClipPreviewer.setAttribute("duration", durationInput.value || "0");
+        durationInput.addEventListener("change", () => {
+          videoClipPreviewer.setAttribute(
+            "duration",
+            durationInput.value || "0"
+          );
+        });
+      }
+    }
+  }
+};
+
+export default VideoClipBuilder;
diff --git a/app/Resources/js/modules/audio-clipper.ts b/app/Resources/js/modules/audio-clipper.ts
index 97549f7e21911b21fa4928031f9048646ff4aca2..e77b4d2e5cefe8a83187f9ee521916098663c774 100644
--- a/app/Resources/js/modules/audio-clipper.ts
+++ b/app/Resources/js/modules/audio-clipper.ts
@@ -3,17 +3,23 @@ import {
   customElement,
   property,
   query,
+  queryAll,
   queryAssignedNodes,
   state,
 } from "lit/decorators.js";
 import WaveSurfer from "wavesurfer.js";
 
-enum ACTIONS {
+enum ActionType {
   StretchLeft,
   StretchRight,
   Seek,
 }
 
+interface Action {
+  type: ActionType;
+  payload?: any;
+}
+
 interface EventElement {
   events: string[];
   onEvent: EventListener;
@@ -51,6 +57,9 @@ export class AudioClipper extends LitElement {
   @query(".buffering-bar")
   _bufferingBarNode!: HTMLCanvasElement;
 
+  @queryAll(".slider__segment-handle")
+  _segmentHandleNodes!: NodeListOf<HTMLButtonElement>;
+
   @property({ type: Number, attribute: "start-time" })
   initStartTime = 0;
 
@@ -76,7 +85,7 @@ export class AudioClipper extends LitElement {
   };
 
   @state()
-  _action: ACTIONS | null = null;
+  _action: Action | null = null;
 
   @state()
   _audioDuration = 0;
@@ -115,7 +124,7 @@ export class AudioClipper extends LitElement {
       onEvent: () => {
         if (this._action !== null) {
           document.body.style.cursor = "";
-          if (this._action === ACTIONS.Seek && this._seekingTime) {
+          if (this._action.type === ActionType.Seek && this._seekingTime) {
             this._audio[0].currentTime = this._seekingTime;
             this._seekingTime = 0;
           }
@@ -193,6 +202,31 @@ export class AudioClipper extends LitElement {
     },
   ];
 
+  _segmentHandleEvents: EventElement[] = [
+    {
+      events: ["mouseenter", "focus"],
+      onEvent: (event: Event) => {
+        const timeInfoElement = (
+          event.target as HTMLButtonElement
+        ).querySelector("span");
+        if (timeInfoElement) {
+          timeInfoElement.style.opacity = "1";
+        }
+      },
+    },
+    {
+      events: ["mouseleave", "blur"],
+      onEvent: (event: Event) => {
+        const timeInfoElement = (
+          event.target as HTMLButtonElement
+        ).querySelector("span");
+        if (timeInfoElement) {
+          timeInfoElement.style.opacity = "0";
+        }
+      },
+    },
+  ];
+
   connectedCallback(): void {
     super.connectedCallback();
 
@@ -249,6 +283,14 @@ export class AudioClipper extends LitElement {
         this._audio[0].addEventListener(name, event.onEvent);
       });
     }
+
+    for (const event of this._segmentHandleEvents) {
+      event.events.forEach((name) => {
+        for (let i = 0; i < this._segmentHandleNodes.length; i++) {
+          this._segmentHandleNodes[i].addEventListener(name, event.onEvent);
+        }
+      });
+    }
   }
 
   removeEventListeners(): void {
@@ -269,6 +311,14 @@ export class AudioClipper extends LitElement {
         this._audio[0].removeEventListener(name, event.onEvent);
       });
     }
+
+    for (const event of this._segmentHandleEvents) {
+      event.events.forEach((name) => {
+        for (let i = 0; i < this._segmentHandleNodes.length; i++) {
+          this._segmentHandleNodes[i].addEventListener(name, event.onEvent);
+        }
+      });
+    }
   }
 
   setSegmentPosition(): void {
@@ -300,6 +350,7 @@ export class AudioClipper extends LitElement {
       this._durationInput[0].value = (
         this._clip.endTime - this._clip.startTime
       ).toFixed(3);
+      this._durationInput[0].dispatchEvent(new Event("change"));
       this._audio[0].currentTime = this._clip.startTime;
     }
     if (_changedProperties.has("_seekingTime")) {
@@ -318,15 +369,20 @@ export class AudioClipper extends LitElement {
   }
 
   private updatePosition(event: MouseEvent): void {
+    if (this._action === null) {
+      return;
+    }
+
     const cursorPosition =
-      event.clientX -
+      event.clientX +
+      (this._action.payload?.offset || 0) -
       (this._sliderNode.getBoundingClientRect().left +
         document.documentElement.scrollLeft);
 
     const seconds = this.getSecondsFromPosition(cursorPosition);
 
-    switch (this._action) {
-      case ACTIONS.StretchLeft: {
+    switch (this._action.type) {
+      case ActionType.StretchLeft: {
         let startTime = 0;
         if (seconds > 0) {
           if (seconds > this._clip.endTime - this.minDuration) {
@@ -341,7 +397,7 @@ export class AudioClipper extends LitElement {
         };
         break;
       }
-      case ACTIONS.StretchRight: {
+      case ActionType.StretchRight: {
         let endTime;
         if (seconds < this._audioDuration) {
           if (seconds < this._clip.startTime + this.minDuration) {
@@ -359,7 +415,7 @@ export class AudioClipper extends LitElement {
         };
         break;
       }
-      case ACTIONS.Seek: {
+      case ActionType.Seek: {
         if (seconds < this._clip.startTime) {
           this._seekingTime = this._clip.startTime;
         } else if (seconds > this._clip.endTime) {
@@ -401,14 +457,23 @@ export class AudioClipper extends LitElement {
     this._seekingNode.style.transform = `scaleX(${seekingTimePercentage})`;
   }
 
-  setAction(action: ACTIONS): void {
-    switch (action) {
-      case ACTIONS.StretchLeft:
-      case ACTIONS.StretchRight:
-        document.body.style.cursor = "grabbing";
+  setAction(event: MouseEvent, action: Action): void {
+    switch (action.type) {
+      case ActionType.StretchLeft:
+        action.payload = {
+          offset:
+            this._segmentHandleNodes[0].getBoundingClientRect().right -
+            event.clientX,
+        };
+        break;
+      case ActionType.StretchRight:
+        action.payload = {
+          offset:
+            this._segmentHandleNodes[1].getBoundingClientRect().left -
+            event.clientX,
+        };
         break;
       default:
-        document.body.style.cursor = "default";
         break;
     }
     this._action = action;
@@ -421,7 +486,7 @@ export class AudioClipper extends LitElement {
   trim(side: "start" | "end") {
     if (side === "start") {
       this._clip = {
-        startTime: this._audio[0].currentTime,
+        startTime: parseFloat(this._audio[0].currentTime.toFixed(3)),
         endTime: this._clip.endTime,
       };
     } else {
@@ -498,6 +563,7 @@ export class AudioClipper extends LitElement {
       margin-top: -2px;
       background-color: #3b82f6;
       border-radius: 50%;
+      box-shadow: 0 0 0 2px #ffffff;
     }
 
     .slider__segment-progress-handle::after {
@@ -543,6 +609,17 @@ export class AudioClipper extends LitElement {
       border-radius: 0.2rem 0 0 0.2rem;
     }
 
+    .slider__segment .slider__segment-handle span {
+      opacity: 0;
+      pointer-events: none;
+      position: absolute;
+      left: -100%;
+      top: -30%;
+      background-color: #0f172a;
+      color: #ffffff;
+      padding: 0 0.25rem;
+    }
+
     .slider__segment .clipper__handle-right {
       right: -1rem;
       border-radius: 0 0.2rem 0.2rem 0;
@@ -555,7 +632,7 @@ export class AudioClipper extends LitElement {
       justify-content: space-between;
       background-color: hsl(var(--color-background-elevated));
       box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
-      border-radius: 0 0 0.25rem 0.25rem;
+      border-radius: 0 0 0.75rem 0.75rem;
       flex-wrap: wrap;
       gap: 0.5rem;
     }
@@ -587,6 +664,39 @@ export class AudioClipper extends LitElement {
       border-radius: 9999px;
       border: none;
       padding: 0.25rem 0.5rem;
+      box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
+    }
+
+    .toolbar button:hover {
+      background-color: hsl(var(--color-accent-hover));
+    }
+
+    .toolbar button:focus {
+      outline: 2px solid transparent;
+      outline-offset: 2px;
+      --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0
+        var(--tw-ring-offset-width) var(--tw-ring-offset-color);
+      --tw-ring-shadow: var(--tw-ring-inset) 0 0 0
+        calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
+      box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow),
+        0 0 rgba(0, 0, 0, 0);
+      box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow),
+        0 0 rgba(0, 0, 0, 0);
+      box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow),
+        var(--tw-shadow, 0 0 rgba(0, 0, 0, 0));
+      --tw-ring-offset-width: 2px;
+      --tw-ring-opacity: 1;
+      --tw-ring-color: hsl(var(--color-accent-base) / var(--tw-ring-opacity));
+      --tw-ring-offset-color: hsl(var(--color-background-base));
+    }
+
+    .toolbar__trim-controls button {
+      font-weight: 600;
+      font-family: Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI,
+        Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, BlinkMacSystemFont,
+        "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,
+        "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
+        "Noto Color Emoji";
     }
 
     .animate-spin {
@@ -614,6 +724,11 @@ export class AudioClipper extends LitElement {
       accent-color: hsl(var(--color-accent-base));
       width: 100px;
     }
+
+    time {
+      font-size: 0.875rem;
+      font-family: "Mono";
+    }
   `;
 
   render(): TemplateResult<1> {
@@ -627,25 +742,33 @@ export class AudioClipper extends LitElement {
           <div class="slider__segment--wrapper">
             <div
               class="slider__segment-progress-handle"
-              @mousedown="${() => this.setAction(ACTIONS.Seek)}"
+              @mousedown="${(event: MouseEvent) =>
+                this.setAction(event, { type: ActionType.Seek })}"
             ></div>
             <div class="slider__segment">
               <button
                 class="slider__segment-handle clipper__handle-left"
-                title="${this.secondsToHHMMSS(this._clip.startTime)}"
-                @mousedown="${() => this.setAction(ACTIONS.StretchLeft)}"
-              ></button>
+                @mousedown="${(event: MouseEvent) =>
+                  this.setAction(event, {
+                    type: ActionType.StretchLeft,
+                  })}"
+              >
+                <span>${this.secondsToHHMMSS(this._clip.startTime)}</span>
+              </button>
               <div class="slider__seeking-placeholder"></div>
               <div
                 class="slider__segment-content"
-                @mousedown="${() => this.setAction(ACTIONS.Seek)}"
+                @mousedown="${(event: MouseEvent) =>
+                  this.setAction(event, { type: ActionType.Seek })}"
                 @click="${(event: MouseEvent) => this.goTo(event)}"
               ></div>
               <button
                 class="slider__segment-handle clipper__handle-right"
-                title="${this.secondsToHHMMSS(this._clip.endTime)}"
-                @mousedown="${() => this.setAction(ACTIONS.StretchRight)}"
-              ></button>
+                @mousedown="${(event: MouseEvent) =>
+                  this.setAction(event, { type: ActionType.StretchRight })}"
+              >
+                <span>${this.secondsToHHMMSS(this._clip.endTime)}</span>
+              </button>
             </div>
           </div>
         </div>
@@ -727,6 +850,7 @@ export class AudioClipper extends LitElement {
               @change="${this.setVolume}"
             />
           </div>
+          <time>${this.secondsToHHMMSS(this._currentTime)}</time>
         </div>
         <div class="toolbar__trim-controls">
           <button @click="${() => this.trim("start")}">Trim start</button>
diff --git a/app/Resources/js/modules/video-clip-previewer.ts b/app/Resources/js/modules/video-clip-previewer.ts
index 1b9b3dc8058eaef3fef6a46ea0c83630bd63fd50..faa138af87553bb82d39c32ea7bb2c14cbc008ad 100644
--- a/app/Resources/js/modules/video-clip-previewer.ts
+++ b/app/Resources/js/modules/video-clip-previewer.ts
@@ -1,5 +1,10 @@
 import { css, html, LitElement, TemplateResult } from "lit";
-import { customElement, property, queryAssignedNodes } from "lit/decorators.js";
+import {
+  customElement,
+  property,
+  queryAssignedNodes,
+  state,
+} from "lit/decorators.js";
 import { styleMap } from "lit/directives/style-map.js";
 
 enum VideoFormats {
@@ -17,40 +22,115 @@ const formatMap = {
 @customElement("video-clip-previewer")
 export class VideoClipPreviewer extends LitElement {
   @queryAssignedNodes("preview_image", true)
-  _previewImage!: NodeListOf<HTMLImageElement>;
+  _image!: NodeListOf<HTMLImageElement>;
 
   @property()
-  format: VideoFormats = VideoFormats.Landscape;
+  title = "";
 
   @property()
-  theme = "#009486";
+  format: VideoFormats = VideoFormats.Portrait;
+
+  @property()
+  theme = "173 44% 96%";
+
+  @property({ type: Number })
+  duration!: number;
+
+  @state()
+  _previewImage!: HTMLImageElement;
+
+  protected firstUpdated(): void {
+    this._previewImage = this._image[0].cloneNode(true) as HTMLImageElement;
+    this._previewImage.classList.add("preview-bg");
+  }
+
+  private secondsToHHMMSS(seconds: number) {
+    // Adapted from https://stackoverflow.com/a/34841026
+    const h = Math.floor(seconds / 3600);
+    const min = Math.floor(seconds / 60) % 60;
+    const s = seconds % 60;
+
+    return [h, min, s]
+      .map((v) => (v < 10 ? "0" + v : v))
+      .filter((v, i) => v !== "00" || i > 0)
+      .join(":");
+  }
 
   static styles = css`
+    .metadata {
+      position: absolute;
+      top: 1rem;
+      left: 1.5rem;
+      color: #ffffff;
+      display: flex;
+      flex-direction: column;
+    }
+
+    .title {
+      font-family: "Kumbh Sans";
+      font-weight: 900;
+      font-size: 1.5rem;
+      text-shadow: 2px 3px 5px rgba(0, 0, 0, 0.5);
+    }
+
+    .duration {
+      font-family: "Inter";
+      font-weight: 600;
+    }
+
+    .preview-bg {
+      position: absolute;
+      background-color: red;
+      width: 100%;
+      object-fit: cover;
+      filter: blur(30px);
+      opacity: 0.5;
+    }
+
     .video-background {
+      position: relative;
       display: grid;
       justify-items: center;
       align-items: center;
       background-color: black;
       width: 100%;
       aspect-ratio: 16 / 9;
+      border-radius: 0.75rem 0.75rem 0 0;
+      overflow: hidden;
     }
 
     .video-format {
+      z-index: 10;
       display: grid;
       align-items: center;
       justify-items: center;
       height: 100%;
+      border: 4px solid hsl(0 0% 100% / 0.5);
+      transition: 300ms ease-in-out aspect-ratio;
+    }
+
+    ::slotted(img) {
+      border-radius: 0.5rem;
+      box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1),
+        0 2px 4px -2px rgb(0 0 0 / 0.1);
     }
   `;
 
   render(): TemplateResult<1> {
     const styles = {
       aspectRatio: formatMap[this.format],
-      backgroundColor: this.theme,
+      backgroundColor: `hsl(${this.theme})`,
     };
 
     return html`<div class="video-background">
+      ${this._previewImage}
       <div class="video-format" style=${styleMap(styles)}>
+        <div class="metadata">
+          <span class="title">${this.title}</span>
+          <time datetime="PT${this.duration}S" class="duration"
+            >${this.secondsToHHMMSS(Math.floor(this.duration))}</time
+          >
+        </div>
         <slot name="preview_image"></slot>
       </div>
     </div>`;
diff --git a/app/Views/Components/Forms/ColorRadioButton.php b/app/Views/Components/Forms/ColorRadioButton.php
index a3454f54ba474cd2f0faf556d8b30dfc85224647..470200efb9d4544ee3de94e5665931cb54bd5eaf 100644
--- a/app/Views/Components/Forms/ColorRadioButton.php
+++ b/app/Views/Components/Forms/ColorRadioButton.php
@@ -17,12 +17,18 @@ class ColorRadioButton extends FormComponent
 
     public function render(): string
     {
+        $data = [
+            'id' => $this->value,
+            'name' => $this->name,
+            'class' => 'color-radio-btn',
+        ];
+
+        if ($this->required) {
+            $data['required'] = 'required';
+        }
+
         $radioInput = form_radio(
-            [
-                'id' => $this->value,
-                'name' => $this->name,
-                'class' => 'color-radio-btn',
-            ],
+            $data,
             $this->value,
             old($this->name) ? old($this->name) === $this->value : $this->isChecked,
         );
diff --git a/app/Views/Components/Forms/RadioButton.php b/app/Views/Components/Forms/RadioButton.php
index f7d7015a111004f34766b5809afaa5ed282301a4..1772c3d4b0c7f95abd3598f68765539d53f8f642 100644
--- a/app/Views/Components/Forms/RadioButton.php
+++ b/app/Views/Components/Forms/RadioButton.php
@@ -17,12 +17,18 @@ class RadioButton extends FormComponent
 
     public function render(): string
     {
+        $data = [
+            'id' => $this->value,
+            'name' => $this->name,
+            'class' => 'form-radio-btn bg-elevated',
+        ];
+
+        if ($this->required) {
+            $data['required'] = 'required';
+        }
+
         $radioInput = form_radio(
-            [
-                'id' => $this->value,
-                'name' => $this->name,
-                'class' => 'form-radio-btn bg-elevated',
-            ],
+            $data,
             $this->value,
             old($this->name) ? old($this->name) === $this->value : $this->isChecked,
         );
@@ -30,7 +36,7 @@ class RadioButton extends FormComponent
         $hint = $this->hint ? hint_tooltip($this->hint, 'ml-1 text-base') : '';
 
         return <<<HTML
-            <div>
+            <div class="{$this->class}">
                 {$radioInput}
                 <label for="{$this->value}">{$this->slot}{$hint}</label>
             </div>
diff --git a/app/Views/Components/Forms/Section.php b/app/Views/Components/Forms/Section.php
index 60279a257af54af2d72235da3bf6e6b641a8bd39..cf7367448e6445fecb7b386cd184dca879895eb3 100644
--- a/app/Views/Components/Forms/Section.php
+++ b/app/Views/Components/Forms/Section.php
@@ -19,7 +19,7 @@ class Section extends Component
         $subtitle = $this->subtitle === null ? '' : '<p class="text-sm clear-left text-skin-muted ' . $this->subtitleClass . '">' . $this->subtitle . '</p>';
 
         return <<<HTML
-            <fieldset class="w-full max-w-xl p-8 bg-elevated border-3 border-subtle rounded-xl {$this->class}">
+            <fieldset class="w-full p-8 bg-elevated border-3 border-subtle rounded-xl {$this->class}">
                 <Heading tagName="legend" class="float-left">{$this->title}</Heading>
                 {$subtitle}
                 <div class="flex flex-col gap-4 py-4 clear-left">{$this->slot}</div>
diff --git a/modules/Admin/Config/Routes.php b/modules/Admin/Config/Routes.php
index a41bdb5d0a4c2c4e0880f0ab78164e045d063ada..dcaf460e1258b7e5b4929609852951af1100ecb5 100644
--- a/modules/Admin/Config/Routes.php
+++ b/modules/Admin/Config/Routes.php
@@ -387,6 +387,14 @@ $routes->group(
                                 'filter' => 'permission:podcast_episodes-edit',
                             ],
                         );
+                        $routes->get(
+                            'video-clips/(:num)/retry',
+                            'VideoClipsController::retry/$1/$2/$3',
+                            [
+                                'as' => 'video-clip-retry',
+                                'filter' => 'permission:podcast_episodes-edit',
+                            ],
+                        );
                         $routes->get(
                             'video-clips/(:num)/delete',
                             'VideoClipsController::delete/$1/$2/$3',
diff --git a/modules/Admin/Controllers/VideoClipsController.php b/modules/Admin/Controllers/VideoClipsController.php
index d24b1cccb9a743f46c0b13c34c2f638a80e993a6..712377e8b2b453844b898630b574287f23b660e7 100644
--- a/modules/Admin/Controllers/VideoClipsController.php
+++ b/modules/Admin/Controllers/VideoClipsController.php
@@ -108,8 +108,6 @@ class VideoClipsController extends BaseController
 
     public function create(): string
     {
-        helper('form');
-
         $data = [
             'podcast' => $this->podcast,
             'episode' => $this->episode,
@@ -120,7 +118,22 @@ class VideoClipsController extends BaseController
             1 => $this->episode->title,
         ]);
 
-        $this->response->setHeader('Accept-Ranges', 'bytes');
+        // First, check that requirements to create a video clip are met
+        $ffmpeg = trim(shell_exec('type -P ffmpeg'));
+        $checks = [
+            'ffmpeg' => ! empty($ffmpeg),
+            'gd' => extension_loaded('gd'),
+            'freetype' => extension_loaded('gd') && gd_info()['FreeType Support'],
+            'transcript' => $this->episode->transcript !== null,
+        ];
+
+        if (in_array(false, $checks, true)) {
+            $data['checks'] = $checks;
+
+            return view('episode/video_clips_requirements', $data);
+        }
+
+        helper('form');
         return view('episode/video_clips_new', $data);
     }
 
@@ -171,6 +184,23 @@ class VideoClipsController extends BaseController
         );
     }
 
+    public function retry(string $videoClipId): RedirectResponse
+    {
+        $videoClip = (new ClipModel())->getVideoClipById((int) $videoClipId);
+
+        if ($videoClip === null) {
+            throw PageNotFoundException::forPageNotFound();
+        }
+
+        (new ClipModel())->update($videoClip->id, [
+            'status' => 'queued',
+            'job_started_at' => null,
+            'job_ended_at' => null,
+        ]);
+
+        return redirect()->back();
+    }
+
     public function delete(string $videoClipId): RedirectResponse
     {
         $videoClip = (new ClipModel())->getVideoClipById((int) $videoClipId);
@@ -181,7 +211,7 @@ class VideoClipsController extends BaseController
 
         if ($videoClip->media === null) {
             // delete Clip directly
-            (new ClipModel())->delete($videoClipId);
+            (new ClipModel())->delete($videoClip->id);
         } else {
             $mediaModel = new MediaModel();
             if (! $mediaModel->deleteMedia($videoClip->media)) {
diff --git a/modules/Admin/Language/en/VideoClip.php b/modules/Admin/Language/en/VideoClip.php
index 49689c673ecec5f5682c1ef735ea53012ffc8150..ef936401a4768d7b4e96000fe5207ba586bcad24 100644
--- a/modules/Admin/Language/en/VideoClip.php
+++ b/modules/Admin/Language/en/VideoClip.php
@@ -31,6 +31,7 @@ return [
     'download_clip' => 'Download clip',
     'create' => 'New video clip',
     'go_to_page' => 'Go to clip page',
+    'retry' => 'Retry clip generation',
     'delete' => 'Delete clip',
     'logs' => 'Job logs',
     'form' => [
@@ -51,4 +52,12 @@ return [
         'duration' => 'Duration',
         'submit' => 'Create video clip',
     ],
+    'requirements' => [
+        'title' => 'Missing requirements',
+        'missing' => 'You have missing requirements. Make sure to add all the required items to be allowed creating a video for this episode!',
+        'ffmpeg' => 'FFmpeg',
+        'gd' => 'Graphics Draw (GD)',
+        'freetype' => 'Freetype library for GD',
+        'transcript' => 'Transcript file (.srt)',
+    ],
 ];
diff --git a/modules/Admin/Language/fr/VideoClip.php b/modules/Admin/Language/fr/VideoClip.php
index 6f4bc60e9a42118efd2e8d07c1246880aca86cb7..c467714f834f7209c251beb0387ebc25261064e5 100644
--- a/modules/Admin/Language/fr/VideoClip.php
+++ b/modules/Admin/Language/fr/VideoClip.php
@@ -31,6 +31,7 @@ return [
     'download_clip' => 'Télécharger l’extrait',
     'create' => 'Nouvel extrait vidéo',
     'go_to_page' => 'Aller à la page de l’extrait',
+    'retry' => 'Relancer la génération de l’extrait',
     'delete' => 'Supprimer l’extrait',
     'logs' => 'Historique d’exécution',
     'form' => [
@@ -51,4 +52,12 @@ return [
         'duration' => 'Durée',
         'submit' => 'Créer un extrait vidéo',
     ],
+    'requirements' => [
+        'title' => 'Outils manquants',
+        'missing' => 'Il vous manque des outils. Assurez vous d’avoir ajouté tous les outils nécessaires pour accéder au fomulaire de génération d’extrait vidéo !',
+        'ffmpeg' => 'FFmpeg',
+        'gd' => 'Graphics Draw (GD)',
+        'freetype' => 'Librairie Freetype pour GD',
+        'transcript' => 'Fichier de transcription (.srt)',
+    ],
 ];
diff --git a/themes/cp_admin/_partials/_nav_header.php b/themes/cp_admin/_partials/_nav_header.php
index 107e87234eb72a099e6389e0815e98162ec42606..0631b61a387fc697051d1c98128e8ca95e5ca1e0 100644
--- a/themes/cp_admin/_partials/_nav_header.php
+++ b/themes/cp_admin/_partials/_nav_header.php
@@ -36,7 +36,7 @@
 
             $interactButtons .= <<<CODE_SAMPLE
                 <button class="inline-flex items-center w-full px-4 py-1 hover:bg-highlight" id="interact-as-actor-{$userPodcast->id}" name="actor_id" value="{$userPodcast->actor_id}">
-                    <span class="inline-flex items-center flex-1 text-sm"><img src="{$userPodcast->cover->tiny_url}" class="w-6 h-6 mr-2 rounded-full" />{$userPodcast->title}{$checkMark}</span>
+                    <div class="inline-flex items-center flex-1 text-sm"><img src="{$userPodcast->cover->tiny_url}" class="w-6 h-6 mr-2 rounded-full" /><span class="truncate">{$userPodcast->title}</span>{$checkMark}</div>
                 </button>
             CODE_SAMPLE;
         }
diff --git a/themes/cp_admin/episode/create.php b/themes/cp_admin/episode/create.php
index 617a2158f0cfc49293d5fae7285acac4da75de35..fdc20326958bf14b0d6c58a26f92d178fc6ab4dc 100644
--- a/themes/cp_admin/episode/create.php
+++ b/themes/cp_admin/episode/create.php
@@ -13,7 +13,7 @@
 
 <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 mt-6 gap-y-8">
+<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() ?>
 
 
diff --git a/themes/cp_admin/episode/edit.php b/themes/cp_admin/episode/edit.php
index 1c0add5d4a08644b038a0bac3136bc9eff1c0fd2..acc4eb423679cf361efa2276ebc2b9057d4696c6 100644
--- a/themes/cp_admin/episode/edit.php
+++ b/themes/cp_admin/episode/edit.php
@@ -17,7 +17,7 @@
 
 <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 mt-6 gap-y-8">
+<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() ?>
 
 
diff --git a/themes/cp_admin/episode/persons.php b/themes/cp_admin/episode/persons.php
index 516f7ca0dbccb126b8c55571bb10ae860bc3e0b2..534d0af9dc5baf780ec942ddfcb8c6fb5d39b499 100644
--- a/themes/cp_admin/episode/persons.php
+++ b/themes/cp_admin/episode/persons.php
@@ -14,7 +14,7 @@
 
 <?= $this->section('content') ?>
 
-<form action="<?= route_to('episode-persons-manage', $podcast->id, $episode->id) ?>" method="POST">
+<form action="<?= route_to('episode-persons-manage', $podcast->id, $episode->id) ?>" method="POST" class="max-w-xl">
     <?= csrf_field() ?>
 
     <Forms.Section
diff --git a/themes/cp_admin/episode/soundbites.php b/themes/cp_admin/episode/soundbites.php
index ec42a99f3c9dd5a9488de18e0194968ff81f525f..111483e371e3fbb2b5647fbfd7d7e7a05e3cd66e 100644
--- a/themes/cp_admin/episode/soundbites.php
+++ b/themes/cp_admin/episode/soundbites.php
@@ -15,7 +15,7 @@
 
 <?= $this->section('content') ?>
 
-<form id="soundbites-form" action="<?= route_to('episode-soundbites-edit', $podcast->id, $episode->id) ?>" method="POST" class="flex flex-col">
+<form id="soundbites-form" action="<?= route_to('episode-soundbites-edit', $podcast->id, $episode->id) ?>" method="POST" class="flex flex-col max-w-xl">
 <?= csrf_field() ?>
 
 <Forms.Section
diff --git a/themes/cp_admin/episode/video_clips_list.php b/themes/cp_admin/episode/video_clips_list.php
index 3a0b065e632abc0738affa079ca617f3a3e99972..f79a3b7cf3ab1f95afc8982c6be1df80a5615403 100644
--- a/themes/cp_admin/episode/video_clips_list.php
+++ b/themes/cp_admin/episode/video_clips_list.php
@@ -103,6 +103,11 @@ use CodeIgniter\I18n\Time;
                                 'title' => lang('VideoClip.go_to_page'),
                                 'uri' => route_to('video-clip', $videoClip->podcast_id, $videoClip->episode_id, $videoClip->id),
                             ],
+                            [
+                                'type' => 'link',
+                                'title' => lang('VideoClip.retry'),
+                                'uri' => route_to('video-clip-retry', $videoClip->podcast_id, $videoClip->episode_id, $videoClip->id),
+                            ],
                             [
                                 'type' => 'separator',
                             ],
diff --git a/themes/cp_admin/episode/video_clips_new.php b/themes/cp_admin/episode/video_clips_new.php
index 97a5547613da68802985e0beaf292a4df2d8bc7c..dbfcd9fce26bd6d1ca3f6147f83e0eadde59cb8f 100644
--- a/themes/cp_admin/episode/video_clips_new.php
+++ b/themes/cp_admin/episode/video_clips_new.php
@@ -10,13 +10,13 @@
 
 <?= $this->section('content') ?>
 
-<form action="<?= route_to('video-clips-create', $podcast->id, $episode->id) ?>" method="POST" class="flex flex-col items-center gap-4 xl:items-start xl:flex-row">
+<form id="new-video-clip-form" action="<?= route_to('video-clips-create', $podcast->id, $episode->id) ?>" method="POST" class="flex flex-col items-center gap-4 xl:items-start xl:flex-row">
 
-<div class="flex-1 w-full">
-    <video-clip-previewer format="portrait">
+<div class="flex-1 w-full rounded-xl border-3 border-subtle">
+    <video-clip-previewer duration="<?= old('duration', 30) ?>">
         <img slot="preview_image" src="<?= $episode->cover->thumbnail_url ?>" alt="<?= $episode->cover->description ?>" />
     </video-clip-previewer>
-    <audio-clipper start-time="15" duration="10" min-duration="10" volume=".25" height="50">
+    <audio-clipper start-time="<?= old('start_time', 0) ?>" duration="<?= old('duration', 30) ?>" min-duration="10" volume=".5" height="50">
         <audio slot="audio" src="<?= $episode->audio->file_url ?>" class="w-full" preload="auto">
             Your browser does not support the <code>audio</code> element.
         </audio>
@@ -25,47 +25,49 @@
     </audio-clipper>
 </div>
 
-<Forms.Section title="<?= lang('VideoClip.form.params_section_title') ?>" >
-
-<Forms.Field
-    name="label"
-    label="<?= lang('VideoClip.form.clip_title') ?>"
-    required="true"
-/>
-
-<fieldset class="flex gap-1">
-<legend><?= lang('VideoClip.form.format.label') ?></legend>
-<Forms.RadioButton
-    value="landscape"
-    name="format"
-    hint="<?= lang('VideoClip.form.format.landscape_hint') ?>"><?= lang('VideoClip.form.format.landscape') ?></Forms.RadioButton>
-<Forms.RadioButton
-    value="portrait"
-    name="format"
-    hint="<?= lang('VideoClip.form.format.portrait_hint') ?>"><?= lang('VideoClip.form.format.portrait') ?></Forms.RadioButton>
-<Forms.RadioButton
-    value="squared"
-    name="format"
-    hint="<?= lang('VideoClip.form.format.squared_hint') ?>"><?= lang('VideoClip.form.format.squared') ?></Forms.RadioButton>
-</fieldset>
-
-<fieldset>
-<legend><?= lang('VideoClip.form.theme') ?></legend>
-<div class="grid gap-4 grid-cols-colorButtons">
-    <?php foreach (config('MediaClipper')->themes as $themeName => $colors): ?>
-        <Forms.ColorRadioButton
-        class="mx-auto"
-        value="<?= $themeName ?>"
-        name="theme"
-        style="--color-accent-base: <?= $colors['preview']?>"><?= lang('Settings.theme.' . $themeName) ?></Forms.ColorRadioButton>
-    <?php endforeach; ?>
+<div class="flex flex-col items-end w-full max-w-xl xl:max-w-sm 2xl:max-w-xl gap-y-4">
+    <Forms.Section title="<?= lang('VideoClip.form.params_section_title') ?>" >
+        <Forms.Field
+            name="label"
+            label="<?= lang('VideoClip.form.clip_title') ?>"
+            required="true"
+        />
+        <fieldset class="flex flex-wrap gap-x-1 gap-y-2">
+            <legend><?= lang('VideoClip.form.format.label') ?></legend>
+            <Forms.RadioButton
+                value="landscape"
+                name="format"
+                isChecked="true"
+                required="true"
+                hint="<?= lang('VideoClip.form.format.landscape_hint') ?>"><?= lang('VideoClip.form.format.landscape') ?></Forms.RadioButton>
+            <Forms.RadioButton
+                value="portrait"
+                name="format"
+                required="true"
+                hint="<?= lang('VideoClip.form.format.portrait_hint') ?>"><?= lang('VideoClip.form.format.portrait') ?></Forms.RadioButton>
+            <Forms.RadioButton
+                value="squared"
+                name="format"
+                required="true"
+                hint="<?= lang('VideoClip.form.format.squared_hint') ?>"><?= lang('VideoClip.form.format.squared') ?></Forms.RadioButton>
+        </fieldset>
+        <fieldset>
+            <legend><?= lang('VideoClip.form.theme') ?></legend>
+            <div class="grid gap-x-4 gap-y-2 grid-cols-colorButtons">
+                <?php foreach (config('MediaClipper')->themes as $themeName => $colors): ?>
+                    <Forms.ColorRadioButton
+                    class="mx-auto"
+                    value="<?= $themeName ?>"
+                    name="theme"
+                    required="true"
+                    isChecked="<?= $themeName === 'pine' ? 'true' : 'false' ?>"
+                    style="--color-accent-base: <?= $colors['preview']?>"><?= lang('Settings.theme.' . $themeName) ?></Forms.ColorRadioButton>
+                <?php endforeach; ?>
+            </div>
+        </fieldset>
+    </Forms.Section>
+    <Button variant="primary" type="submit" iconRight="arrow-right" class="self-end"><?= lang('VideoClip.form.submit') ?></Button>
 </div>
-</fieldset>
-
-<Button variant="primary" type="submit" iconRight="arrow-right" class="self-end"><?= lang('VideoClip.form.submit') ?></Button>
-
-</Forms.Section>
-
 </form>
 
 <?= $this->endSection() ?>
diff --git a/themes/cp_admin/episode/video_clips_requirements.php b/themes/cp_admin/episode/video_clips_requirements.php
new file mode 100644
index 0000000000000000000000000000000000000000..f9c714aaf0ac54a586bef01992d025a9bd525f81
--- /dev/null
+++ b/themes/cp_admin/episode/video_clips_requirements.php
@@ -0,0 +1,29 @@
+<?= $this->extend('_layout') ?>
+
+<?= $this->section('title') ?>
+<?= lang('VideoClip.form.title') ?>
+<?= $this->endSection() ?>
+
+<?= $this->section('pageTitle') ?>
+<?= lang('VideoClip.form.title') ?>
+<?= $this->endSection() ?>
+
+<?= $this->section('content') ?>
+
+<div class="flex flex-col gap-6">
+<div class="flex flex-col items-start">
+    <Heading class="flex items-center gap-x-2"><Icon glyph="alert" class="flex-shrink-0 text-xl text-orange-600" /><?= lang('VideoClip.requirements.title') ?></Heading>
+    <p class="max-w-sm font-semibold text-gray-500"><?= lang('VideoClip.requirements.missing') ?></p>
+    <div class="flex flex-col mt-4">
+    <?php foreach ($checks as $requirement => $value): ?>
+        <?php if ($value): ?>
+            <div class="inline-flex items-center"><Icon glyph="check" class="mr-1 text-white rounded-full bg-pine-500"/><?= lang('VideoClip.requirements.' . $requirement) ?></div>
+        <?php else: ?>
+            <div class="inline-flex items-center"><Icon glyph="close" class="mr-1 text-white bg-red-500 rounded-full"/><?= lang('VideoClip.requirements.' . $requirement) ?></div>
+        <?php endif; ?>
+    <?php endforeach; ?>
+    </div>
+
+</div>
+
+<?= $this->endSection() ?>
diff --git a/themes/cp_admin/fediverse/blocked_actors.php b/themes/cp_admin/fediverse/blocked_actors.php
index 2d4bf514c6dd889d1a19c03ae138e74b30bd51b8..3446545a90b167b96f9f98e970c708053a8c61d6 100644
--- a/themes/cp_admin/fediverse/blocked_actors.php
+++ b/themes/cp_admin/fediverse/blocked_actors.php
@@ -40,6 +40,7 @@
         ],
     ],
     $blockedActors,
+    'mt-8'
 ) ?>
 
 
diff --git a/themes/cp_admin/podcast/create.php b/themes/cp_admin/podcast/create.php
index 452ff8d57ef0acdf1b0cc437d099a03c36ba7753..938121c10b01b5c58f87f058774cb33479aeb9f2 100644
--- a/themes/cp_admin/podcast/create.php
+++ b/themes/cp_admin/podcast/create.php
@@ -14,7 +14,7 @@
 
 <?= $this->section('content') ?>
 
-<form action="<?= route_to('podcast-create') ?>" method="POST" enctype='multipart/form-data' class="flex flex-col gap-y-6">
+<form action="<?= route_to('podcast-create') ?>" method="POST" enctype='multipart/form-data' class="flex flex-col max-w-xl gap-y-6">
 <?= csrf_field() ?>
 
 <Forms.Section
diff --git a/themes/cp_admin/podcast/edit.php b/themes/cp_admin/podcast/edit.php
index a6fcec9f5d93e3d0dc59c345ade590b503190bc8..682febfa453cf2a3ba5650ccbab40ae4f16e8ed2 100644
--- a/themes/cp_admin/podcast/edit.php
+++ b/themes/cp_admin/podcast/edit.php
@@ -36,7 +36,7 @@
     </div>
 </div>
 
-<div class="flex flex-col gap-y-6">
+<div class="flex flex-col max-w-xl gap-y-6">
 
 <Forms.Section
     title="<?= lang('Podcast.form.identity_section_title') ?>"
diff --git a/themes/cp_admin/podcast/import.php b/themes/cp_admin/podcast/import.php
index c2f71a18beda621b00ad3e7e4b57fd9faa83ddf0..e7abcf463b58b149e9de3a9dfb7967c9376b297c 100644
--- a/themes/cp_admin/podcast/import.php
+++ b/themes/cp_admin/podcast/import.php
@@ -12,7 +12,7 @@
 
 <Alert glyph="alert" variant="danger" class="max-w-xl"><?= lang('PodcastImport.warning') ?></Alert>
 
-<form action="<?= route_to('podcast-import') ?>" method="POST" enctype='multipart/form-data' class="flex flex-col mt-6 gap-y-8">
+<form action="<?= route_to('podcast-import') ?>" method="POST" enctype='multipart/form-data' class="flex flex-col max-w-xl mt-6 gap-y-8">
 <?= csrf_field() ?>
 
 <Forms.Section
diff --git a/themes/cp_admin/podcast/persons.php b/themes/cp_admin/podcast/persons.php
index 77cc2992b77873ebf9246ea6ad25282e0a2c52f8..fda00612ebc45dcb84b67466337a459b29b53e0e 100644
--- a/themes/cp_admin/podcast/persons.php
+++ b/themes/cp_admin/podcast/persons.php
@@ -14,7 +14,7 @@
 
 <?= $this->section('content') ?>
 
-<form action="<?= route_to('podcast-persons-manage', $podcast->id) ?>" method="POST">
+<form action="<?= route_to('podcast-persons-manage', $podcast->id) ?>" method="POST" class="max-w-xl">
     <?= csrf_field() ?>
 
     <Forms.Section
diff --git a/themes/cp_admin/settings/general.php b/themes/cp_admin/settings/general.php
index 46787aa74d49ebeb304b78eef47ef786b5e6a55b..26c8e86d9bf7df3480d179679a8e4ba1ec67cdfe 100644
--- a/themes/cp_admin/settings/general.php
+++ b/themes/cp_admin/settings/general.php
@@ -11,7 +11,7 @@
 <?= $this->section('content') ?>
 <div class="flex flex-col gap-y-4">
 
-<form action="<?= route_to('settings-instance') ?>" method="POST" enctype="multipart/form-data">
+<form action="<?= route_to('settings-instance') ?>" method="POST" enctype="multipart/form-data" class="max-w-xl">
 <?= csrf_field() ?>
 
 <Forms.Section
@@ -57,7 +57,7 @@
 
 </form>
 
-<form action="<?= route_to('settings-images-regenerate') ?>" method="POST" class="flex flex-col gap-y-4">
+<form action="<?= route_to('settings-images-regenerate') ?>" method="POST" class="flex flex-col max-w-xl gap-y-4">
 <?= csrf_field() ?>
 
 <Forms.Section
diff --git a/themes/cp_admin/settings/theme.php b/themes/cp_admin/settings/theme.php
index 1bcb240c1b28d25942ced3823edb36032388cd75..6c43b91842a012347705ed9b2b07a25a92456019 100644
--- a/themes/cp_admin/settings/theme.php
+++ b/themes/cp_admin/settings/theme.php
@@ -10,7 +10,7 @@
 
 <?= $this->section('content') ?>
 
-<form action="<?= route_to('settings-theme') ?>" method="POST" class="flex flex-col gap-y-4" enctype="multipart/form-data">
+<form action="<?= route_to('settings-theme') ?>" method="POST" class="flex flex-col max-w-xl gap-y-4" enctype="multipart/form-data">
 <?= csrf_field() ?>
 <Forms.Section
     title="<?= lang('Settings.theme.accent_section_title') ?>"
diff --git a/themes/cp_app/_admin_navbar.php b/themes/cp_app/_admin_navbar.php
index 2984c28fa67039239318b1a2b65790050bb477bd..0cea27a6fa4808f3c4fbde0d7856a4dac9e605bd 100644
--- a/themes/cp_app/_admin_navbar.php
+++ b/themes/cp_app/_admin_navbar.php
@@ -31,7 +31,7 @@
 
                 $interactButtons .= <<<CODE_SAMPLE
                     <button class="inline-flex items-center w-full px-4 py-1 hover:bg-highlight" id="interact-as-actor-{$userPodcast->id}" name="actor_id" value="{$userPodcast->actor_id}">
-                        <span class="inline-flex items-center flex-1 text-sm"><img src="{$userPodcast->cover->tiny_url}" class="w-6 h-6 mr-2 rounded-full" />{$userPodcast->title}{$checkMark}</span>
+                        <div class="inline-flex items-center flex-1 text-sm"><img src="{$userPodcast->cover->tiny_url}" class="w-6 h-6 mr-2 rounded-full" /><span class="truncate">{$userPodcast->title}</span>{$checkMark}</div>
                     </button>
                 CODE_SAMPLE;
             }