diff --git a/app/controllers/api/v1/accounts/statuses_controller.rb b/app/controllers/api/v1/accounts/statuses_controller.rb
index fe4279302f..6a994ff541 100644
--- a/app/controllers/api/v1/accounts/statuses_controller.rb
+++ b/app/controllers/api/v1/accounts/statuses_controller.rb
@@ -4,7 +4,7 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
   before_action -> { authorize_if_got_token! :read, :'read:statuses' }
   before_action :set_account
 
-  after_action :insert_pagination_headers, unless: -> { truthy_param?(:pinned) }
+  after_action :insert_pagination_headers
 
   def index
     cache_if_unauthenticated!
diff --git a/app/javascript/core/admin.js b/app/javascript/core/admin.js
deleted file mode 100644
index 8e335131a9..0000000000
--- a/app/javascript/core/admin.js
+++ /dev/null
@@ -1,224 +0,0 @@
-//  This file will be loaded on admin pages, regardless of theme.
-
-import 'packs/public-path';
-import Rails from '@rails/ujs';
-
-import ready from '../mastodon/ready';
-
-const setAnnouncementEndsAttributes = (target) => {
-  const valid = target?.value && target?.validity?.valid;
-  const element = document.querySelector('input[type="datetime-local"]#announcement_ends_at');
-  if (valid) {
-    element.classList.remove('optional');
-    element.required = true;
-    element.min = target.value;
-  } else {
-    element.classList.add('optional');
-    element.removeAttribute('required');
-    element.removeAttribute('min');
-  }
-};
-
-Rails.delegate(document, 'input[type="datetime-local"]#announcement_starts_at', 'change', ({ target }) => {
-  setAnnouncementEndsAttributes(target);
-});
-
-const batchCheckboxClassName = '.batch-checkbox input[type="checkbox"]';
-
-const showSelectAll = () => {
-  const selectAllMatchingElement = document.querySelector('.batch-table__select-all');
-  selectAllMatchingElement.classList.add('active');
-};
-
-const hideSelectAll = () => {
-  const selectAllMatchingElement = document.querySelector('.batch-table__select-all');
-  const hiddenField = document.querySelector('#select_all_matching');
-  const selectedMsg = document.querySelector('.batch-table__select-all .selected');
-  const notSelectedMsg = document.querySelector('.batch-table__select-all .not-selected');
-
-  selectAllMatchingElement.classList.remove('active');
-  selectedMsg.classList.remove('active');
-  notSelectedMsg.classList.add('active');
-  hiddenField.value = '0';
-};
-
-Rails.delegate(document, '#batch_checkbox_all', 'change', ({ target }) => {
-  const selectAllMatchingElement = document.querySelector('.batch-table__select-all');
-
-  document.querySelectorAll(batchCheckboxClassName).forEach((content) => {
-    content.checked = target.checked;
-  });
-
-  if (selectAllMatchingElement) {
-    if (target.checked) {
-      showSelectAll();
-    } else {
-      hideSelectAll();
-    }
-  }
-});
-
-Rails.delegate(document, '.batch-table__select-all button', 'click', () => {
-  const hiddenField = document.querySelector('#select_all_matching');
-  const active = hiddenField.value === '1';
-  const selectedMsg = document.querySelector('.batch-table__select-all .selected');
-  const notSelectedMsg = document.querySelector('.batch-table__select-all .not-selected');
-
-  if (active) {
-    hiddenField.value = '0';
-    selectedMsg.classList.remove('active');
-    notSelectedMsg.classList.add('active');
-  } else {
-    hiddenField.value = '1';
-    notSelectedMsg.classList.remove('active');
-    selectedMsg.classList.add('active');
-  }
-});
-
-Rails.delegate(document, batchCheckboxClassName, 'change', () => {
-  const checkAllElement = document.querySelector('#batch_checkbox_all');
-  const selectAllMatchingElement = document.querySelector('.batch-table__select-all');
-
-  if (checkAllElement) {
-    const allCheckboxes = Array.from(
-      document.querySelectorAll(batchCheckboxClassName)
-    );
-    checkAllElement.checked = allCheckboxes.every((content) => content.checked);
-    checkAllElement.indeterminate = !checkAllElement.checked && allCheckboxes.some((content) => content.checked);
-
-    if (selectAllMatchingElement) {
-      if (checkAllElement.checked) {
-        showSelectAll();
-      } else {
-        hideSelectAll();
-      }
-    }
-  }
-});
-
-Rails.delegate(document, '.filter-subset--with-select select', 'change', ({ target }) => {
-  target.form.submit();
-});
-
-const onDomainBlockSeverityChange = (target) => {
-  const rejectMediaDiv   = document.querySelector('.input.with_label.domain_block_reject_media');
-  const rejectReportsDiv = document.querySelector('.input.with_label.domain_block_reject_reports');
-
-  if (rejectMediaDiv) {
-    rejectMediaDiv.style.display = (target.value === 'suspend') ? 'none' : 'block';
-  }
-
-  if (rejectReportsDiv) {
-    rejectReportsDiv.style.display = (target.value === 'suspend') ? 'none' : 'block';
-  }
-};
-
-Rails.delegate(document, '#domain_block_severity', 'change', ({ target }) => onDomainBlockSeverityChange(target));
-
-const onEnableBootstrapTimelineAccountsChange = (target) => {
-  const bootstrapTimelineAccountsField = document.querySelector('#form_admin_settings_bootstrap_timeline_accounts');
-
-  if (bootstrapTimelineAccountsField) {
-    bootstrapTimelineAccountsField.disabled = !target.checked;
-    if (target.checked) {
-      bootstrapTimelineAccountsField.parentElement.classList.remove('disabled');
-      bootstrapTimelineAccountsField.parentElement.parentElement.classList.remove('disabled');
-    } else {
-      bootstrapTimelineAccountsField.parentElement.classList.add('disabled');
-      bootstrapTimelineAccountsField.parentElement.parentElement.classList.add('disabled');
-    }
-  }
-};
-
-Rails.delegate(document, '#form_admin_settings_enable_bootstrap_timeline_accounts', 'change', ({ target }) => onEnableBootstrapTimelineAccountsChange(target));
-
-const onChangeRegistrationMode = (target) => {
-  const enabled = target.value === 'approved';
-
-  document.querySelectorAll('.form_admin_settings_registrations_mode .warning-hint').forEach((warning_hint) => {
-    warning_hint.style.display = target.value === 'open' ? 'inline' : 'none';
-  });
-
-  document.querySelectorAll('#form_admin_settings_require_invite_text').forEach((input) => {
-    input.disabled = !enabled;
-    if (enabled) {
-      let element = input;
-      do {
-        element.classList.remove('disabled');
-        element = element.parentElement;
-      } while (element && !element.classList.contains('fields-group'));
-    } else {
-      let element = input;
-      do {
-        element.classList.add('disabled');
-        element = element.parentElement;
-      } while (element && !element.classList.contains('fields-group'));
-    }
-  });
-};
-
-const convertUTCDateTimeToLocal = (value) => {
-  const date = new Date(value + 'Z');
-  const twoChars = (x) => (x.toString().padStart(2, '0'));
-  return `${date.getFullYear()}-${twoChars(date.getMonth()+1)}-${twoChars(date.getDate())}T${twoChars(date.getHours())}:${twoChars(date.getMinutes())}`;
-};
-
-const convertLocalDatetimeToUTC = (value) => {
-  const re = /^([0-9]{4,})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2})/;
-  const match = re.exec(value);
-  const date = new Date(match[1], match[2] - 1, match[3], match[4], match[5]);
-  const fullISO8601 = date.toISOString();
-  return fullISO8601.slice(0, fullISO8601.indexOf('T') + 6);
-};
-
-Rails.delegate(document, '#form_admin_settings_registrations_mode', 'change', ({ target }) => onChangeRegistrationMode(target));
-
-ready(() => {
-  const domainBlockSeverityInput = document.getElementById('domain_block_severity');
-  if (domainBlockSeverityInput) onDomainBlockSeverityChange(domainBlockSeverityInput);
-
-  const enableBootstrapTimelineAccounts = document.getElementById('form_admin_settings_enable_bootstrap_timeline_accounts');
-  if (enableBootstrapTimelineAccounts) onEnableBootstrapTimelineAccountsChange(enableBootstrapTimelineAccounts);
-
-  const registrationMode = document.getElementById('form_admin_settings_registrations_mode');
-  if (registrationMode) onChangeRegistrationMode(registrationMode);
-
-  const checkAllElement = document.querySelector('#batch_checkbox_all');
-  if (checkAllElement) {
-    const allCheckboxes = Array.from(document.querySelectorAll(batchCheckboxClassName));
-    checkAllElement.checked = allCheckboxes.every( (content) => content.checked);
-    checkAllElement.indeterminate = !checkAllElement.checked && allCheckboxes.some((content) => content.checked);
-  }
-
-  document.querySelector('a#add-instance-button')?.addEventListener('click', (e) => {
-    const domain = document.querySelector('input[type="text"]#by_domain')?.value;
-
-    if (domain) {
-      const url = new URL(event.target.href);
-      url.searchParams.set('_domain', domain);
-      e.target.href = url;
-    }
-  });
-
-  document.querySelectorAll('input[type="datetime-local"]').forEach(element => {
-    if (element.value) {
-      element.value = convertUTCDateTimeToLocal(element.value);
-    }
-    if (element.placeholder) {
-      element.placeholder = convertUTCDateTimeToLocal(element.placeholder);
-    }
-  });
-
-  Rails.delegate(document, 'form', 'submit', ({ target }) => {
-    target.querySelectorAll('input[type="datetime-local"]').forEach(element => {
-      if (element.value && element.validity.valid) {
-        element.value = convertLocalDatetimeToUTC(element.value);
-      }
-    });
-  });
-
-  const announcementStartsAt = document.querySelector('input[type="datetime-local"]#announcement_starts_at');
-  if (announcementStartsAt) {
-    setAnnouncementEndsAttributes(announcementStartsAt);
-  }
-});
diff --git a/app/javascript/core/admin.ts b/app/javascript/core/admin.ts
new file mode 100644
index 0000000000..3b3fe76488
--- /dev/null
+++ b/app/javascript/core/admin.ts
@@ -0,0 +1,340 @@
+//  This file will be loaded on admin pages, regardless of theme.
+
+import 'packs/public-path';
+
+import Rails from '@rails/ujs';
+
+import ready from '../mastodon/ready';
+
+const setAnnouncementEndsAttributes = (target: HTMLInputElement) => {
+  const valid = target.value && target.validity.valid;
+  const element = document.querySelector<HTMLInputElement>(
+    'input[type="datetime-local"]#announcement_ends_at',
+  );
+
+  if (!element) return;
+
+  if (valid) {
+    element.classList.remove('optional');
+    element.required = true;
+    element.min = target.value;
+  } else {
+    element.classList.add('optional');
+    element.removeAttribute('required');
+    element.removeAttribute('min');
+  }
+};
+
+Rails.delegate(
+  document,
+  'input[type="datetime-local"]#announcement_starts_at',
+  'change',
+  ({ target }) => {
+    if (target instanceof HTMLInputElement)
+      setAnnouncementEndsAttributes(target);
+  },
+);
+
+const batchCheckboxClassName = '.batch-checkbox input[type="checkbox"]';
+
+const showSelectAll = () => {
+  const selectAllMatchingElement = document.querySelector(
+    '.batch-table__select-all',
+  );
+  selectAllMatchingElement?.classList.add('active');
+};
+
+const hideSelectAll = () => {
+  const selectAllMatchingElement = document.querySelector(
+    '.batch-table__select-all',
+  );
+  const hiddenField = document.querySelector<HTMLInputElement>(
+    'input#select_all_matching',
+  );
+  const selectedMsg = document.querySelector(
+    '.batch-table__select-all .selected',
+  );
+  const notSelectedMsg = document.querySelector(
+    '.batch-table__select-all .not-selected',
+  );
+
+  selectAllMatchingElement?.classList.remove('active');
+  selectedMsg?.classList.remove('active');
+  notSelectedMsg?.classList.add('active');
+  if (hiddenField) hiddenField.value = '0';
+};
+
+Rails.delegate(document, '#batch_checkbox_all', 'change', ({ target }) => {
+  if (!(target instanceof HTMLInputElement)) return;
+
+  const selectAllMatchingElement = document.querySelector(
+    '.batch-table__select-all',
+  );
+
+  document
+    .querySelectorAll<HTMLInputElement>(batchCheckboxClassName)
+    .forEach((content) => {
+      content.checked = target.checked;
+    });
+
+  if (selectAllMatchingElement) {
+    if (target.checked) {
+      showSelectAll();
+    } else {
+      hideSelectAll();
+    }
+  }
+});
+
+Rails.delegate(document, '.batch-table__select-all button', 'click', () => {
+  const hiddenField = document.querySelector<HTMLInputElement>(
+    '#select_all_matching',
+  );
+
+  if (!hiddenField) return;
+
+  const active = hiddenField.value === '1';
+  const selectedMsg = document.querySelector(
+    '.batch-table__select-all .selected',
+  );
+  const notSelectedMsg = document.querySelector(
+    '.batch-table__select-all .not-selected',
+  );
+
+  if (!selectedMsg || !notSelectedMsg) return;
+
+  if (active) {
+    hiddenField.value = '0';
+    selectedMsg.classList.remove('active');
+    notSelectedMsg.classList.add('active');
+  } else {
+    hiddenField.value = '1';
+    notSelectedMsg.classList.remove('active');
+    selectedMsg.classList.add('active');
+  }
+});
+
+Rails.delegate(document, batchCheckboxClassName, 'change', () => {
+  const checkAllElement = document.querySelector<HTMLInputElement>(
+    'input#batch_checkbox_all',
+  );
+  const selectAllMatchingElement = document.querySelector(
+    '.batch-table__select-all',
+  );
+
+  if (checkAllElement) {
+    const allCheckboxes = Array.from(
+      document.querySelectorAll<HTMLInputElement>(batchCheckboxClassName),
+    );
+    checkAllElement.checked = allCheckboxes.every((content) => content.checked);
+    checkAllElement.indeterminate =
+      !checkAllElement.checked &&
+      allCheckboxes.some((content) => content.checked);
+
+    if (selectAllMatchingElement) {
+      if (checkAllElement.checked) {
+        showSelectAll();
+      } else {
+        hideSelectAll();
+      }
+    }
+  }
+});
+
+Rails.delegate(
+  document,
+  '.filter-subset--with-select select',
+  'change',
+  ({ target }) => {
+    if (target instanceof HTMLSelectElement) target.form?.submit();
+  },
+);
+
+const onDomainBlockSeverityChange = (target: HTMLInputElement) => {
+  const rejectMediaDiv = document.querySelector(
+    '.input.with_label.domain_block_reject_media',
+  );
+  const rejectReportsDiv = document.querySelector(
+    '.input.with_label.domain_block_reject_reports',
+  );
+
+  if (rejectMediaDiv && rejectMediaDiv instanceof HTMLElement) {
+    rejectMediaDiv.style.display =
+      target.value === 'suspend' ? 'none' : 'block';
+  }
+
+  if (rejectReportsDiv && rejectReportsDiv instanceof HTMLElement) {
+    rejectReportsDiv.style.display =
+      target.value === 'suspend' ? 'none' : 'block';
+  }
+};
+
+Rails.delegate(document, '#domain_block_severity', 'change', ({ target }) => {
+  if (target instanceof HTMLInputElement) onDomainBlockSeverityChange(target);
+});
+
+const onEnableBootstrapTimelineAccountsChange = (target: HTMLInputElement) => {
+  const bootstrapTimelineAccountsField =
+    document.querySelector<HTMLInputElement>(
+      '#form_admin_settings_bootstrap_timeline_accounts',
+    );
+
+  if (bootstrapTimelineAccountsField) {
+    bootstrapTimelineAccountsField.disabled = !target.checked;
+    if (target.checked) {
+      bootstrapTimelineAccountsField.parentElement?.classList.remove(
+        'disabled',
+      );
+      bootstrapTimelineAccountsField.parentElement?.parentElement?.classList.remove(
+        'disabled',
+      );
+    } else {
+      bootstrapTimelineAccountsField.parentElement?.classList.add('disabled');
+      bootstrapTimelineAccountsField.parentElement?.parentElement?.classList.add(
+        'disabled',
+      );
+    }
+  }
+};
+
+Rails.delegate(
+  document,
+  '#form_admin_settings_enable_bootstrap_timeline_accounts',
+  'change',
+  ({ target }) => {
+    if (target instanceof HTMLInputElement)
+      onEnableBootstrapTimelineAccountsChange(target);
+  },
+);
+
+const onChangeRegistrationMode = (target: HTMLInputElement) => {
+  const enabled = target.value === 'approved';
+
+  document
+    .querySelectorAll<HTMLElement>(
+      '.form_admin_settings_registrations_mode .warning-hint',
+    )
+    .forEach((warning_hint) => {
+      warning_hint.style.display = target.value === 'open' ? 'inline' : 'none';
+    });
+
+  document
+    .querySelectorAll<HTMLInputElement>(
+      'input#form_admin_settings_require_invite_text',
+    )
+    .forEach((input) => {
+      input.disabled = !enabled;
+      if (enabled) {
+        let element: HTMLElement | null = input;
+        do {
+          element.classList.remove('disabled');
+          element = element.parentElement;
+        } while (element && !element.classList.contains('fields-group'));
+      } else {
+        let element: HTMLElement | null = input;
+        do {
+          element.classList.add('disabled');
+          element = element.parentElement;
+        } while (element && !element.classList.contains('fields-group'));
+      }
+    });
+};
+
+const convertUTCDateTimeToLocal = (value: string) => {
+  const date = new Date(value + 'Z');
+  const twoChars = (x: number) => x.toString().padStart(2, '0');
+  return `${date.getFullYear()}-${twoChars(date.getMonth() + 1)}-${twoChars(date.getDate())}T${twoChars(date.getHours())}:${twoChars(date.getMinutes())}`;
+};
+
+function convertLocalDatetimeToUTC(value: string) {
+  const date = new Date(value);
+  const fullISO8601 = date.toISOString();
+  return fullISO8601.slice(0, fullISO8601.indexOf('T') + 6);
+}
+
+Rails.delegate(
+  document,
+  '#form_admin_settings_registrations_mode',
+  'change',
+  ({ target }) => {
+    if (target instanceof HTMLInputElement) onChangeRegistrationMode(target);
+  },
+);
+
+ready(() => {
+  const domainBlockSeverityInput = document.querySelector<HTMLInputElement>(
+    'input#domain_block_severity',
+  );
+  if (domainBlockSeverityInput)
+    onDomainBlockSeverityChange(domainBlockSeverityInput);
+
+  const enableBootstrapTimelineAccounts =
+    document.querySelector<HTMLInputElement>(
+      'input#form_admin_settings_enable_bootstrap_timeline_accounts',
+    );
+  if (enableBootstrapTimelineAccounts)
+    onEnableBootstrapTimelineAccountsChange(enableBootstrapTimelineAccounts);
+
+  const registrationMode = document.querySelector<HTMLInputElement>(
+    'input#form_admin_settings_registrations_mode',
+  );
+  if (registrationMode) onChangeRegistrationMode(registrationMode);
+
+  const checkAllElement = document.querySelector<HTMLInputElement>(
+    'input#batch_checkbox_all',
+  );
+  if (checkAllElement) {
+    const allCheckboxes = Array.from(
+      document.querySelectorAll<HTMLInputElement>(batchCheckboxClassName),
+    );
+    checkAllElement.checked = allCheckboxes.every((content) => content.checked);
+    checkAllElement.indeterminate =
+      !checkAllElement.checked &&
+      allCheckboxes.some((content) => content.checked);
+  }
+
+  document
+    .querySelector('a#add-instance-button')
+    ?.addEventListener('click', (e) => {
+      const domain = document.querySelector<HTMLInputElement>(
+        'input[type="text"]#by_domain',
+      )?.value;
+
+      if (domain && e.target instanceof HTMLAnchorElement) {
+        const url = new URL(e.target.href);
+        url.searchParams.set('_domain', domain);
+        e.target.href = url.toString();
+      }
+    });
+
+  document
+    .querySelectorAll<HTMLInputElement>('input[type="datetime-local"]')
+    .forEach((element) => {
+      if (element.value) {
+        element.value = convertUTCDateTimeToLocal(element.value);
+      }
+      if (element.placeholder) {
+        element.placeholder = convertUTCDateTimeToLocal(element.placeholder);
+      }
+    });
+
+  Rails.delegate(document, 'form', 'submit', ({ target }) => {
+    if (target instanceof HTMLFormElement)
+      target
+        .querySelectorAll<HTMLInputElement>('input[type="datetime-local"]')
+        .forEach((element) => {
+          if (element.value && element.validity.valid) {
+            element.value = convertLocalDatetimeToUTC(element.value);
+          }
+        });
+  });
+
+  const announcementStartsAt = document.querySelector<HTMLInputElement>(
+    'input[type="datetime-local"]#announcement_starts_at',
+  );
+  if (announcementStartsAt) {
+    setAnnouncementEndsAttributes(announcementStartsAt);
+  }
+}).catch((reason) => {
+  throw reason;
+});
diff --git a/app/javascript/core/theme.yml b/app/javascript/core/theme.yml
index f6f653c0a9..ab8de6afad 100644
--- a/app/javascript/core/theme.yml
+++ b/app/javascript/core/theme.yml
@@ -2,7 +2,7 @@
 #  theme.
 pack:
   about:
-  admin: admin.js
+  admin: admin.ts
   auth: auth.js
   common:
     filename: common.js
diff --git a/app/javascript/flavours/glitch/components/edited_timestamp/index.jsx b/app/javascript/flavours/glitch/components/edited_timestamp/index.jsx
index 29a418dfb1..2363f132f1 100644
--- a/app/javascript/flavours/glitch/components/edited_timestamp/index.jsx
+++ b/app/javascript/flavours/glitch/components/edited_timestamp/index.jsx
@@ -68,7 +68,7 @@ class EditedTimestamp extends PureComponent {
     return (
       <DropdownMenu statusId={statusId} renderItem={this.renderItem} scrollable renderHeader={this.renderHeader} onItemClick={this.handleItemClick}>
         <button className='dropdown-menu__text-button'>
-          <FormattedMessage id='status.edited' defaultMessage='Edited {date}' values={{ date: intl.formatDate(timestamp, { hour12: false, month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) }} /> <Icon id='caret-down' icon={ArrowDropDownIcon} />
+          <FormattedMessage id='status.edited' defaultMessage='Edited {date}' values={{ date: intl.formatDate(timestamp, { month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) }} /> <Icon id='caret-down' icon={ArrowDropDownIcon} />
         </button>
       </DropdownMenu>
     );
diff --git a/app/javascript/flavours/glitch/components/relative_timestamp.tsx b/app/javascript/flavours/glitch/components/relative_timestamp.tsx
index ac3ab0fb4d..12530c2b17 100644
--- a/app/javascript/flavours/glitch/components/relative_timestamp.tsx
+++ b/app/javascript/flavours/glitch/components/relative_timestamp.tsx
@@ -53,7 +53,6 @@ const messages = defineMessages({
 });
 
 const dateFormatOptions = {
-  hour12: false,
   year: 'numeric',
   month: 'short',
   day: '2-digit',
diff --git a/app/javascript/flavours/glitch/components/status_action_bar.jsx b/app/javascript/flavours/glitch/components/status_action_bar.jsx
index c10122d234..f27719a6b9 100644
--- a/app/javascript/flavours/glitch/components/status_action_bar.jsx
+++ b/app/javascript/flavours/glitch/components/status_action_bar.jsx
@@ -351,7 +351,7 @@ class StatusActionBar extends ImmutablePureComponent {
 
         <div className='status__action-bar-spacer' />
         <a href={status.get('url')} className='status__relative-time' target='_blank' rel='noopener'>
-          <RelativeTimestamp timestamp={status.get('created_at')} />{status.get('edited_at') && <abbr title={intl.formatMessage(messages.edited, { date: intl.formatDate(status.get('edited_at'), { hour12: false, year: 'numeric', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) })}> *</abbr>}
+          <RelativeTimestamp timestamp={status.get('created_at')} />{status.get('edited_at') && <abbr title={intl.formatMessage(messages.edited, { date: intl.formatDate(status.get('edited_at'), { year: 'numeric', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) })}> *</abbr>}
         </a>
       </div>
     );
diff --git a/app/javascript/flavours/glitch/features/account/components/header.jsx b/app/javascript/flavours/glitch/features/account/components/header.jsx
index 29e3aa32f7..b2aee7682a 100644
--- a/app/javascript/flavours/glitch/features/account/components/header.jsx
+++ b/app/javascript/flavours/glitch/features/account/components/header.jsx
@@ -84,7 +84,6 @@ const dateFormatOptions = {
   month: 'short',
   day: 'numeric',
   year: 'numeric',
-  hour12: false,
   hour: '2-digit',
   minute: '2-digit',
 };
diff --git a/app/javascript/flavours/glitch/features/getting_started/components/announcements.jsx b/app/javascript/flavours/glitch/features/getting_started/components/announcements.jsx
index 27470d9938..0ff0a863b3 100644
--- a/app/javascript/flavours/glitch/features/getting_started/components/announcements.jsx
+++ b/app/javascript/flavours/glitch/features/getting_started/components/announcements.jsx
@@ -343,7 +343,7 @@ class Announcement extends ImmutablePureComponent {
       <div className='announcements__item'>
         <strong className='announcements__item__range'>
           <FormattedMessage id='announcement.announcement' defaultMessage='Announcement' />
-          {hasTimeRange && <span> · <FormattedDate value={startsAt} hour12={false} year={(skipYear || startsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'} month='short' day='2-digit' hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} /> - <FormattedDate value={endsAt} hour12={false} year={(skipYear || endsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'} month={skipEndDate ? undefined : 'short'} day={skipEndDate ? undefined : '2-digit'} hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} /></span>}
+          {hasTimeRange && <span> · <FormattedDate value={startsAt} year={(skipYear || startsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'} month='short' day='2-digit' hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} /> - <FormattedDate value={endsAt} year={(skipYear || endsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'} month={skipEndDate ? undefined : 'short'} day={skipEndDate ? undefined : '2-digit'} hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} /></span>}
         </strong>
 
         <Content announcement={announcement} />
diff --git a/app/javascript/flavours/glitch/features/status/components/card.jsx b/app/javascript/flavours/glitch/features/status/components/card.jsx
index c4461f4378..4c535b0a46 100644
--- a/app/javascript/flavours/glitch/features/status/components/card.jsx
+++ b/app/javascript/flavours/glitch/features/status/components/card.jsx
@@ -82,6 +82,10 @@ export default class Card extends PureComponent {
     this.setState({ embedded: true });
   };
 
+  handleExternalLinkClick = (e) => {
+    e.stopPropagation();
+  };
+
   setRef = c => {
     this.node = c;
   };
@@ -191,7 +195,7 @@ export default class Card extends PureComponent {
               <div className='status-card__actions' onClick={this.handleEmbedClick} role='none'>
                 <div>
                   <button type='button' onClick={this.handleEmbedClick}><Icon id='play' icon={PlayArrowIcon} /></button>
-                  <a href={card.get('url')} target='_blank' rel='noopener noreferrer'><Icon id='external-link' icon={OpenInNewIcon} /></a>
+                  <a href={card.get('url')} onClick={this.handleExternalLinkClick} target='_blank' rel='noopener noreferrer'><Icon id='external-link' icon={OpenInNewIcon} /></a>
                 </div>
               </div>
             ) : spoilerButton}
diff --git a/app/javascript/flavours/glitch/features/status/components/detailed_status.jsx b/app/javascript/flavours/glitch/features/status/components/detailed_status.jsx
index 0638d0d646..2a3ab7001b 100644
--- a/app/javascript/flavours/glitch/features/status/components/detailed_status.jsx
+++ b/app/javascript/flavours/glitch/features/status/components/detailed_status.jsx
@@ -331,7 +331,7 @@ class DetailedStatus extends ImmutablePureComponent {
 
           <div className='detailed-status__meta'>
             <a className='detailed-status__datetime' href={status.get('url')} target='_blank' rel='noopener noreferrer'>
-              <FormattedDate value={new Date(status.get('created_at'))} hour12={false} year='numeric' month='short' day='2-digit' hour='2-digit' minute='2-digit' />
+              <FormattedDate value={new Date(status.get('created_at'))} year='numeric' month='short' day='2-digit' hour='2-digit' minute='2-digit' />
             </a>{edited}{visibilityLink}{applicationLink}{reblogLink} · {favouriteLink}
           </div>
         </div>
diff --git a/app/javascript/flavours/glitch/packs/admin.jsx b/app/javascript/flavours/glitch/packs/admin.jsx
deleted file mode 100644
index fdf483301f..0000000000
--- a/app/javascript/flavours/glitch/packs/admin.jsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import 'packs/public-path';
-import { createRoot } from 'react-dom/client';
-
-import ready from 'flavours/glitch/ready';
-
-ready(() => {
-  document.querySelectorAll('[data-admin-component]').forEach(element => {
-    const componentName  = element.getAttribute('data-admin-component');
-    const componentProps = JSON.parse(element.getAttribute('data-props'));
-
-    import('flavours/glitch/containers/admin_component').then(({ default: AdminComponent }) => {
-      return import('flavours/glitch/components/admin/' + componentName).then(({ default: Component }) => {
-        const root = createRoot(element);
-
-        root.render (
-          <AdminComponent>
-            <Component {...componentProps} />
-          </AdminComponent>,
-        );
-      });
-    }).catch(error => {
-      console.error(error);
-    });
-  });
-});
diff --git a/app/javascript/flavours/glitch/packs/admin.tsx b/app/javascript/flavours/glitch/packs/admin.tsx
new file mode 100644
index 0000000000..e20e74b238
--- /dev/null
+++ b/app/javascript/flavours/glitch/packs/admin.tsx
@@ -0,0 +1,37 @@
+import 'packs/public-path';
+import { createRoot } from 'react-dom/client';
+
+import ready from 'flavours/glitch/ready';
+
+async function mountReactComponent(element: Element) {
+  const componentName = element.getAttribute('data-admin-component');
+  const stringProps = element.getAttribute('data-props');
+
+  if (!stringProps) return;
+
+  const componentProps = JSON.parse(stringProps) as object;
+
+  const { default: AdminComponent } = await import(
+    '@/flavours/glitch/containers/admin_component'
+  );
+
+  const { default: Component } = (await import(
+    `@/flavours/glitch/components/admin/${componentName}`
+  )) as { default: React.ComponentType };
+
+  const root = createRoot(element);
+
+  root.render(
+    <AdminComponent>
+      <Component {...componentProps} />
+    </AdminComponent>,
+  );
+}
+
+ready(() => {
+  document.querySelectorAll('[data-admin-component]').forEach((element) => {
+    void mountReactComponent(element);
+  });
+}).catch((reason) => {
+  throw reason;
+});
diff --git a/app/javascript/flavours/glitch/packs/public.jsx b/app/javascript/flavours/glitch/packs/public.jsx
index 5a72f91786..dab33b3904 100644
--- a/app/javascript/flavours/glitch/packs/public.jsx
+++ b/app/javascript/flavours/glitch/packs/public.jsx
@@ -60,7 +60,6 @@ function main() {
 
   const timeFormat = new Intl.DateTimeFormat(locale, {
     timeStyle: 'short',
-    hour12: false,
   });
 
   const formatMessage = ({ id, defaultMessage }, values) => {
diff --git a/app/javascript/flavours/glitch/styles/components.scss b/app/javascript/flavours/glitch/styles/components.scss
index e7a0156a41..a42bfdc712 100644
--- a/app/javascript/flavours/glitch/styles/components.scss
+++ b/app/javascript/flavours/glitch/styles/components.scss
@@ -5735,10 +5735,6 @@ a.status-card {
       pointer-events: auto;
       opacity: 1;
     }
-
-    @media screen and (min-width: $no-gap-breakpoint) {
-      inset-inline-start: 16px - 2px;
-    }
   }
 
   .icon-search {
@@ -8883,7 +8879,7 @@ noscript {
   .search__input {
     border: 1px solid lighten($ui-base-color, 8%);
     padding: 10px;
-    padding-inline-end: 28px;
+    padding-inline-end: 30px;
   }
 
   .search__popout {
diff --git a/app/javascript/flavours/glitch/theme.yml b/app/javascript/flavours/glitch/theme.yml
index 05497f9c2a..49d71e085c 100644
--- a/app/javascript/flavours/glitch/theme.yml
+++ b/app/javascript/flavours/glitch/theme.yml
@@ -1,7 +1,7 @@
 #  (REQUIRED) The location of the pack files.
 pack:
   admin:
-    - packs/admin.jsx
+    - packs/admin.tsx
     - packs/public.jsx
   auth: packs/public.jsx
   common:
diff --git a/app/javascript/flavours/vanilla/theme.yml b/app/javascript/flavours/vanilla/theme.yml
index fa3b3a758a..b7678dc441 100644
--- a/app/javascript/flavours/vanilla/theme.yml
+++ b/app/javascript/flavours/vanilla/theme.yml
@@ -1,7 +1,7 @@
 #  (REQUIRED) The location of the pack files inside `pack_directory`.
 pack:
   admin:
-    - admin.jsx
+    - admin.tsx
     - public.jsx
   auth: public.jsx
   common:
diff --git a/app/javascript/mastodon/components/edited_timestamp/index.jsx b/app/javascript/mastodon/components/edited_timestamp/index.jsx
index 4ca00f8dda..7b70f9d6e1 100644
--- a/app/javascript/mastodon/components/edited_timestamp/index.jsx
+++ b/app/javascript/mastodon/components/edited_timestamp/index.jsx
@@ -67,7 +67,7 @@ class EditedTimestamp extends PureComponent {
     return (
       <DropdownMenu statusId={statusId} renderItem={this.renderItem} scrollable renderHeader={this.renderHeader} onItemClick={this.handleItemClick}>
         <button className='dropdown-menu__text-button'>
-          <FormattedMessage id='status.edited' defaultMessage='Edited {date}' values={{ date: intl.formatDate(timestamp, { hour12: false, month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) }} /> <Icon id='caret-down' icon={ArrowDropDownIcon} />
+          <FormattedMessage id='status.edited' defaultMessage='Edited {date}' values={{ date: intl.formatDate(timestamp, { month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) }} /> <Icon id='caret-down' icon={ArrowDropDownIcon} />
         </button>
       </DropdownMenu>
     );
diff --git a/app/javascript/mastodon/components/relative_timestamp.tsx b/app/javascript/mastodon/components/relative_timestamp.tsx
index ac3ab0fb4d..12530c2b17 100644
--- a/app/javascript/mastodon/components/relative_timestamp.tsx
+++ b/app/javascript/mastodon/components/relative_timestamp.tsx
@@ -53,7 +53,6 @@ const messages = defineMessages({
 });
 
 const dateFormatOptions = {
-  hour12: false,
   year: 'numeric',
   month: 'short',
   day: '2-digit',
diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx
index 1171351c51..be9a1cec65 100644
--- a/app/javascript/mastodon/components/status.jsx
+++ b/app/javascript/mastodon/components/status.jsx
@@ -554,7 +554,7 @@ class Status extends ImmutablePureComponent {
             <div onClick={this.handleClick} className='status__info'>
               <a href={`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`} className='status__relative-time' target='_blank' rel='noopener noreferrer'>
                 <span className='status__visibility-icon'><VisibilityIcon visibility={status.get('visibility')} /></span>
-                <RelativeTimestamp timestamp={status.get('created_at')} />{status.get('edited_at') && <abbr title={intl.formatMessage(messages.edited, { date: intl.formatDate(status.get('edited_at'), { hour12: false, year: 'numeric', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) })}> *</abbr>}
+                <RelativeTimestamp timestamp={status.get('created_at')} />{status.get('edited_at') && <abbr title={intl.formatMessage(messages.edited, { date: intl.formatDate(status.get('edited_at'), { year: 'numeric', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) })}> *</abbr>}
               </a>
 
               <a onClick={this.handleAccountClick} href={`/@${status.getIn(['account', 'acct'])}`} title={status.getIn(['account', 'acct'])} className='status__display-name' target='_blank' rel='noopener noreferrer'>
diff --git a/app/javascript/mastodon/features/account/components/header.jsx b/app/javascript/mastodon/features/account/components/header.jsx
index 233d208c64..07ea227c48 100644
--- a/app/javascript/mastodon/features/account/components/header.jsx
+++ b/app/javascript/mastodon/features/account/components/header.jsx
@@ -101,7 +101,6 @@ const dateFormatOptions = {
   month: 'short',
   day: 'numeric',
   year: 'numeric',
-  hour12: false,
   hour: '2-digit',
   minute: '2-digit',
 };
diff --git a/app/javascript/mastodon/features/getting_started/components/announcements.jsx b/app/javascript/mastodon/features/getting_started/components/announcements.jsx
index ea36cefd7d..3c0b53b9e7 100644
--- a/app/javascript/mastodon/features/getting_started/components/announcements.jsx
+++ b/app/javascript/mastodon/features/getting_started/components/announcements.jsx
@@ -343,7 +343,7 @@ class Announcement extends ImmutablePureComponent {
       <div className='announcements__item'>
         <strong className='announcements__item__range'>
           <FormattedMessage id='announcement.announcement' defaultMessage='Announcement' />
-          {hasTimeRange && <span> · <FormattedDate value={startsAt} hour12={false} year={(skipYear || startsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'} month='short' day='2-digit' hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} /> - <FormattedDate value={endsAt} hour12={false} year={(skipYear || endsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'} month={skipEndDate ? undefined : 'short'} day={skipEndDate ? undefined : '2-digit'} hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} /></span>}
+          {hasTimeRange && <span> · <FormattedDate value={startsAt} year={(skipYear || startsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'} month='short' day='2-digit' hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} /> - <FormattedDate value={endsAt} year={(skipYear || endsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'} month={skipEndDate ? undefined : 'short'} day={skipEndDate ? undefined : '2-digit'} hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} /></span>}
         </strong>
 
         <Content announcement={announcement} />
diff --git a/app/javascript/mastodon/features/status/components/card.jsx b/app/javascript/mastodon/features/status/components/card.jsx
index f37b558c4c..f47861f663 100644
--- a/app/javascript/mastodon/features/status/components/card.jsx
+++ b/app/javascript/mastodon/features/status/components/card.jsx
@@ -92,6 +92,10 @@ export default class Card extends PureComponent {
     this.setState({ embedded: true });
   };
 
+  handleExternalLinkClick = (e) => {
+    e.stopPropagation();
+  };
+
   setRef = c => {
     this.node = c;
   };
@@ -201,7 +205,7 @@ export default class Card extends PureComponent {
               <div className='status-card__actions' onClick={this.handleEmbedClick} role='none'>
                 <div>
                   <button type='button' onClick={this.handleEmbedClick}><Icon id='play' icon={PlayArrowIcon} /></button>
-                  <a href={card.get('url')} target='_blank' rel='noopener noreferrer'><Icon id='external-link' icon={OpenInNewIcon} /></a>
+                  <a href={card.get('url')} onClick={this.handleExternalLinkClick} target='_blank' rel='noopener noreferrer'><Icon id='external-link' icon={OpenInNewIcon} /></a>
                 </div>
               </div>
             ) : spoilerButton}
diff --git a/app/javascript/mastodon/features/status/components/detailed_status.jsx b/app/javascript/mastodon/features/status/components/detailed_status.jsx
index 437e9e86bf..d10c8966e4 100644
--- a/app/javascript/mastodon/features/status/components/detailed_status.jsx
+++ b/app/javascript/mastodon/features/status/components/detailed_status.jsx
@@ -311,7 +311,7 @@ class DetailedStatus extends ImmutablePureComponent {
 
           <div className='detailed-status__meta'>
             <a className='detailed-status__datetime' href={`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`} target='_blank' rel='noopener noreferrer'>
-              <FormattedDate value={new Date(status.get('created_at'))} hour12={false} year='numeric' month='short' day='2-digit' hour='2-digit' minute='2-digit' />
+              <FormattedDate value={new Date(status.get('created_at'))} year='numeric' month='short' day='2-digit' hour='2-digit' minute='2-digit' />
             </a>{edited}{visibilityLink}{applicationLink}{reblogLink} · {favouriteLink}
           </div>
         </div>
diff --git a/app/javascript/mastodon/locales/lt.json b/app/javascript/mastodon/locales/lt.json
index e8c51791ee..35722b0e0d 100644
--- a/app/javascript/mastodon/locales/lt.json
+++ b/app/javascript/mastodon/locales/lt.json
@@ -1,6 +1,6 @@
 {
   "about.blocks": "Prižiūrimi serveriai",
-  "about.contact": "Kontaktuoti:",
+  "about.contact": "Kontaktai:",
   "about.disclaimer": "Mastodon – nemokama atvirojo kodo programa ir Mastodon gGmbH prekės ženklas.",
   "about.domain_blocks.no_reason_available": "Priežastis nepateikta",
   "about.domain_blocks.preamble": "Mastodon paprastai leidžia peržiūrėti turinį ir bendrauti su naudotojais iš bet kurio kito fediverse esančio serverio. Šios yra išimtys, kurios buvo padarytos šiame konkrečiame serveryje.",
@@ -424,7 +424,7 @@
   "notifications.column_settings.mention": "Paminėjimai:",
   "notifications.column_settings.poll": "Balsavimo rezultatai:",
   "notifications.column_settings.push": "\"Push\" pranešimai",
-  "notifications.column_settings.reblog": "\"Boost\" kiekis:",
+  "notifications.column_settings.reblog": "Pakėlimai:",
   "notifications.column_settings.show": "Rodyti stulpelyje",
   "notifications.column_settings.sound": "Paleisti garsą",
   "notifications.column_settings.status": "New toots:",
@@ -636,6 +636,7 @@
   "status.translate": "Versti",
   "status.translated_from_with": "Išversta iš {lang} naudojant {provider}",
   "status.uncached_media_warning": "Peržiūra nepasiekiama",
+  "subscribed_languages.lead": "Po pakeitimo tavo pagrindinėje ir sąrašo laiko juostose bus rodomi tik įrašai pasirinktomis kalbomis. Jei nori gauti įrašus visomis kalbomis, pasirink nė vieno.",
   "tabs_bar.home": "Pradžia",
   "tabs_bar.notifications": "Pranešimai",
   "time_remaining.days": "Liko {number, plural, one {# diena} few {# dienos} many {# dieno} other {# dienų}}",
diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json
index df04ded166..f2367f6463 100644
--- a/app/javascript/mastodon/locales/nl.json
+++ b/app/javascript/mastodon/locales/nl.json
@@ -529,8 +529,8 @@
   "poll_button.add_poll": "Peiling toevoegen",
   "poll_button.remove_poll": "Peiling verwijderen",
   "privacy.change": "Zichtbaarheid van bericht aanpassen",
-  "privacy.direct.long": "Iedereen die in het bericht wordt vermeld",
-  "privacy.direct.short": "Bepaalde mensen",
+  "privacy.direct.long": "Alleen voor mensen die specifiek in het bericht worden vermeld",
+  "privacy.direct.short": "Specifieke mensen",
   "privacy.private.long": "Alleen jouw volgers",
   "privacy.private.short": "Volgers",
   "privacy.public.long": "Iedereen op Mastodon en daarbuiten",
diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json
index 0ecf1378e3..4962aedad5 100644
--- a/app/javascript/mastodon/locales/zh-TW.json
+++ b/app/javascript/mastodon/locales/zh-TW.json
@@ -668,7 +668,7 @@
   "status.mute": "靜音 @{name}",
   "status.mute_conversation": "靜音對話",
   "status.open": "展開此嘟文",
-  "status.pin": "釘選到個人檔案頁面",
+  "status.pin": "釘選至個人檔案頁面",
   "status.pinned": "釘選嘟文",
   "status.read_more": "閱讀更多",
   "status.reblog": "轉嘟",
diff --git a/app/javascript/packs/admin.jsx b/app/javascript/packs/admin.jsx
deleted file mode 100644
index a9e8260f7d..0000000000
--- a/app/javascript/packs/admin.jsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import './public-path';
-import { createRoot } from 'react-dom/client';
-
-import ready from '../mastodon/ready';
-
-ready(() => {
-  document.querySelectorAll('[data-admin-component]').forEach(element => {
-    const componentName  = element.getAttribute('data-admin-component');
-    const componentProps = JSON.parse(element.getAttribute('data-props'));
-
-    import('../mastodon/containers/admin_component').then(({ default: AdminComponent }) => {
-      return import('../mastodon/components/admin/' + componentName).then(({ default: Component }) => {
-        const root = createRoot(element);
-
-        root.render (
-          <AdminComponent>
-            <Component {...componentProps} />
-          </AdminComponent>,
-        );
-      });
-    }).catch(error => {
-      console.error(error);
-    });
-  });
-});
diff --git a/app/javascript/packs/admin.tsx b/app/javascript/packs/admin.tsx
new file mode 100644
index 0000000000..13e740b190
--- /dev/null
+++ b/app/javascript/packs/admin.tsx
@@ -0,0 +1,37 @@
+import './public-path';
+import { createRoot } from 'react-dom/client';
+
+import ready from '../mastodon/ready';
+
+async function mountReactComponent(element: Element) {
+  const componentName = element.getAttribute('data-admin-component');
+  const stringProps = element.getAttribute('data-props');
+
+  if (!stringProps) return;
+
+  const componentProps = JSON.parse(stringProps) as object;
+
+  const { default: AdminComponent } = await import(
+    '@/mastodon/containers/admin_component'
+  );
+
+  const { default: Component } = (await import(
+    `@/mastodon/components/admin/${componentName}`
+  )) as { default: React.ComponentType };
+
+  const root = createRoot(element);
+
+  root.render(
+    <AdminComponent>
+      <Component {...componentProps} />
+    </AdminComponent>,
+  );
+}
+
+ready(() => {
+  document.querySelectorAll('[data-admin-component]').forEach((element) => {
+    void mountReactComponent(element);
+  });
+}).catch((reason) => {
+  throw reason;
+});
diff --git a/app/javascript/packs/public.jsx b/app/javascript/packs/public.jsx
index 6ffc78c1db..be66683986 100644
--- a/app/javascript/packs/public.jsx
+++ b/app/javascript/packs/public.jsx
@@ -49,7 +49,6 @@ function loaded() {
 
   const timeFormat = new Intl.DateTimeFormat(locale, {
     timeStyle: 'short',
-    hour12: false,
   });
 
   const formatMessage = ({ id, defaultMessage }, values) => {
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index 0116a052c5..68a597abe3 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -5210,10 +5210,6 @@ a.status-card {
       pointer-events: auto;
       opacity: 1;
     }
-
-    @media screen and (min-width: $no-gap-breakpoint) {
-      inset-inline-start: 16px - 2px;
-    }
   }
 
   .icon-search {
@@ -8265,7 +8261,7 @@ noscript {
   .search__input {
     border: 1px solid lighten($ui-base-color, 8%);
     padding: 10px;
-    padding-inline-end: 28px;
+    padding-inline-end: 30px;
   }
 
   .search__popout {
diff --git a/app/lib/admin/metrics/measure/tag_servers_measure.rb b/app/lib/admin/metrics/measure/tag_servers_measure.rb
index 6eb46bca45..e0f1bf3440 100644
--- a/app/lib/admin/metrics/measure/tag_servers_measure.rb
+++ b/app/lib/admin/metrics/measure/tag_servers_measure.rb
@@ -28,14 +28,17 @@ class Admin::Metrics::Measure::TagServersMeasure < Admin::Metrics::Measure::Base
   def sql_query_string
     <<~SQL.squish
       SELECT axis.*, (
-        SELECT count(distinct accounts.domain) AS value
-        FROM statuses
-        INNER JOIN statuses_tags ON statuses.id = statuses_tags.status_id
-        INNER JOIN accounts ON statuses.account_id = accounts.id
-        WHERE statuses_tags.tag_id = :tag_id
-          AND statuses.id BETWEEN :earliest_status_id AND :latest_status_id
-          AND date_trunc('day', statuses.created_at)::date = axis.period
-      )
+        WITH tag_servers AS (
+          SELECT DISTINCT accounts.domain
+          FROM statuses
+          INNER JOIN statuses_tags ON statuses.id = statuses_tags.status_id
+          INNER JOIN accounts ON statuses.account_id = accounts.id
+          WHERE statuses_tags.tag_id = :tag_id
+            AND statuses.id BETWEEN :earliest_status_id AND :latest_status_id
+            AND date_trunc('day', statuses.created_at)::date = axis.period
+        )
+        SELECT COUNT(*) FROM tag_servers
+      ) AS value
       FROM (
         SELECT generate_series(date_trunc('day', :start_at::timestamp)::date, date_trunc('day', :end_at::timestamp)::date, interval '1 day') AS period
       ) as axis
diff --git a/config/locales/cy.yml b/config/locales/cy.yml
index 5085942fb7..1fbcbb2255 100644
--- a/config/locales/cy.yml
+++ b/config/locales/cy.yml
@@ -823,6 +823,7 @@ cy:
         disabled: I neb
         users: I ddefnyddwyr lleol wedi'u mewngofnodi
       registrations:
+        moderation_recommandation: Gwnewch yn siŵr bod gennych chi dîm cymedroli digonol ac adweithiol cyn i chi agor cofrestriadau i bawb!
         preamble: Rheoli pwy all greu cyfrif ar eich gweinydd.
         title: Cofrestriadau
       registrations_mode:
@@ -830,6 +831,7 @@ cy:
           approved: Mae angen cymeradwyaeth i gofrestru
           none: Nid oes neb yn gallu cofrestru
           open: Gall unrhyw un cofrestru
+        warning_hint: Rydym yn argymell defnyddio “Mae angen cymeradwyaeth ar gyfer cofrestru” oni bai eich bod yn hyderus y gall eich tîm cymedroli ymdrin â chofrestriadau sbam a rhai maleisus mewn modd amserol.
       security:
         authorized_fetch: Mae angen dilysu gan weinyddion ffederal
         authorized_fetch_hint: Mae gofyn am ddilysiad gan weinyddion ffederal yn galluogi gorfodi llymach ar flociau lefel defnyddiwr a lefel gweinydd. Fodd bynnag, daw hyn ar gost perfformiad arafach, mae'n lleihau cyrhaeddiad eich atebion, a gall gyflwyno materion cydnawsedd gyda rhai gwasanaethau ffederal. Yn ogystal, ni fydd hyn yn atal actorion ymroddedig rhag estyn eich postiadau a'ch cyfrifon cyhoeddus.
@@ -1038,6 +1040,9 @@ cy:
       title: Bachau Gwe
       webhook: Bachyn Gwe
   admin_mailer:
+    auto_close_registrations:
+      body: Oherwydd diffyg gweithgarwch cymedrolwr diweddar, mae cofrestriadau ar %{instance} wedi'u newid yn awtomatig i'r angen i gael adolygiad â llaw, er mwyn atal %{instance} rhag cael ei ddefnyddio fel llwyfan ar gyfer actorion drwg posibl. Gallwch ei newid yn ôl i agor cofrestriadau ar unrhyw adeg.
+      subject: Mae cofrestriadau ar gyfer %{instance} wedi'u newid yn awtomatig i'r angen i gael cymeradwyaeth
     new_appeal:
       actions:
         delete_statuses: i ddileu eu postiadau
diff --git a/config/locales/is.yml b/config/locales/is.yml
index d374c60755..56d71bd9ad 100644
--- a/config/locales/is.yml
+++ b/config/locales/is.yml
@@ -769,6 +769,7 @@ is:
         disabled: Til engra
         users: Til innskráðra staðværra notenda
       registrations:
+        moderation_recommandation: Tryggðu að þú hafir hæft og aðgengilegt umsjónarteymi til taks áður en þú opnar á skráningar fyrir alla!
         preamble: Stýrðu því hverjir geta útbúið notandaaðgang á netþjóninum þínum.
         title: Nýskráningar
       registrations_mode:
@@ -776,6 +777,7 @@ is:
           approved: Krafist er samþykkt nýskráningar
           none: Enginn getur nýskráð sig
           open: Allir geta nýskráð sig
+        warning_hint: Við mælum með því að nota "Krafist er samþykkt nýskráningar" nema ef þú sért viss um að umsjónarteymið þitt geti brugðist tímanlega við ruslpósti og skráningum í misjöfnum tilgangi.
       security:
         authorized_fetch: Krefjast auðkenningar frá netþjónum í skýjasambandi
         authorized_fetch_hint: Að krefjast auðkenningar frá netþjónum í skýjasambandi kallar fram strangari útfærslu á útilokunum, bæði varðandi notendur og netþjóna. Hins vegar kemur þetta niður á afköstum, minnkar útbreiðslu á svörum þínum og gæti valdið samhæfnivandamálum við sumar sambandsþjónustur. Að auki kemur þetta ekki í veg fyrir að aðilar sem ætla sér að ná í opinberar færslur og notendaaðganga frá þér geri það.
@@ -968,6 +970,9 @@ is:
       title: Webhook-vefkrækjur
       webhook: Webhook-vefkrækja
   admin_mailer:
+    auto_close_registrations:
+      body: Vegna skorts á virkni umsjónaraðila að undanförnu, hafa nýskráningar á %{instance} sjálfkrafa verið stilltar á að þarfnast samþykktar umsjónaraðila, til að koma í veg fyrir að %{instance} verði mögulega misnotað af óprúttnum aðilum. Þú getur skipt hvenær sem er aftur yfir í opnar nýskráningar.
+      subject: Nýskráningar á %{instance} hafa sjálfkrafa verið stilltar á að krefjast samþykktar
     new_appeal:
       actions:
         delete_statuses: að eyða færslum viðkomandi
diff --git a/config/locales/lt.yml b/config/locales/lt.yml
index 590062f3d9..6ca6f3b62f 100644
--- a/config/locales/lt.yml
+++ b/config/locales/lt.yml
@@ -319,7 +319,7 @@ lt:
       guide_link_text: Visi gali prisidėti.
   application_mailer:
     notification_preferences: Keisti el pašto parinktis
-    settings: 'Keisti el pašto parinktis: %{link}'
+    settings: 'Keisti el. pašto nuostatas: %{link}'
     view: 'Peržiūra:'
     view_profile: Peržiurėti profilį
     view_status: Peržiūrėti statusą
diff --git a/config/locales/simple_form.cy.yml b/config/locales/simple_form.cy.yml
index 3bba0d71cb..3daedfc860 100644
--- a/config/locales/simple_form.cy.yml
+++ b/config/locales/simple_form.cy.yml
@@ -39,12 +39,14 @@ cy:
         text: Dim ond unwaith y gallwch apelio yn erbyn rhybudd
       defaults:
         autofollow: Bydd pobl sy'n cofrestru drwy'r gwahoddiad yn eich dilyn yn awtomatig
+        avatar: WEBP, PNG, GIF neu JPG. %{size} ar y mwyaf. Bydd yn cael ei leihau i %{dimensions}px
         bot: Mae'r cyfrif hwn yn perfformio gweithredoedd awtomatig yn bennaf ac mae'n bosib nad yw'n cael ei fonitro
         context: Un neu fwy cyd-destun lle dylai'r hidlydd weithio
         current_password: At ddibenion diogelwch, nodwch gyfrinair y cyfrif cyfredol
         current_username: I gadarnhau, nodwch enw defnyddiwr y cyfrif cyfredol
         digest: Ond yn cael eu hanfon ar ôl cyfnod hir o anweithgarwch ac ond os ydych wedi derbyn unrhyw negeseuon personol yn eich absenoldeb
         email: Byddwch yn derbyn e-bost cadarnhau
+        header: WEBP, PNG, GIF neu JPG. %{size} ar y mwyaf. Bydd yn cael ei leihau i %{dimensions}px
         inbox_url: Copïwch yr URL o dudalen flaen y relái yr ydych am ei ddefnyddio
         irreversible: Bydd postiadau wedi'u hidlo'n diflannu'n ddiwrthdro, hyd yn oed os caiff yr hidlydd ei dynnu'n ddiweddarach
         locale: Iaith y rhyngwyneb, e-byst a hysbysiadau gwthiadwy
diff --git a/config/locales/simple_form.is.yml b/config/locales/simple_form.is.yml
index 0e9c50eff6..0859e89897 100644
--- a/config/locales/simple_form.is.yml
+++ b/config/locales/simple_form.is.yml
@@ -39,12 +39,14 @@ is:
         text: Þú getur aðeins áfrýjað refsingu einu sinni
       defaults:
         autofollow: Fólk sem skráir sig í gegnum boðið mun sjálfkrafa fylgjast með þér
+        avatar: WEBP, PNG, GIF eða JPG. Mest %{size}. Verður smækkað í %{dimensions}px
         bot: Þessi aðgangur er aðallega til að framkvæma sjálfvirkar aðgerðir og gæti verið án þess að hann sé vaktaður reglulega
         context: Eitt eða fleiri samhengi þar sem sían ætti að gilda
         current_password: Í öryggisskyni skaltu setja inn lykilorðið fyrir þennan notandaaðgang
         current_username: Til að staðfesta skaltu setja inn notandanafnið fyrir þennan notandaaðgang
         digest: Er aðeins sent eftir lengri tímabil án virkni og þá aðeins ef þú hefur fengið persónuleg skilaboð á meðan þú hefur ekki verið á línunni
         email: Þú munt fá sendan staðfestingarpóst
+        header: WEBP, PNG, GIF eða JPG. Mest %{size}. Verður smækkað í %{dimensions}px
         inbox_url: Afritaðu slóðina af forsíðu endurvarpans sem þú vilt nota
         irreversible: Síaðar færslur munu hverfa óendurkræft, jafnvel þó sían sé seinna fjarlægð
         locale: Tungumál notandaviðmótsins, tölvupósts og ýti-tilkynninga
diff --git a/config/locales/simple_form.nl.yml b/config/locales/simple_form.nl.yml
index 18a469b55e..3f4f339b93 100644
--- a/config/locales/simple_form.nl.yml
+++ b/config/locales/simple_form.nl.yml
@@ -39,14 +39,14 @@ nl:
         text: Je kunt maar eenmalig bezwaar indienen tegen een vastgestelde overtreding
       defaults:
         autofollow: Mensen die zich via de uitnodiging hebben geregistreerd, volgen jou automatisch
-        avatar: WEBP, PNG, GIF of JPG. Hoogstens %{size}. Wordt verkleind naar %{dimensions}px
+        avatar: WEBP, PNG, GIF of JPG. Maximaal %{size}. Wordt verkleind naar %{dimensions}px
         bot: Signaal aan anderen dat het account voornamelijk geautomatiseerde acties uitvoert en mogelijk niet wordt gecontroleerd
         context: Een of meerdere locaties waar de filter actief moet zijn
         current_password: Voer voor veiligheidsredenen het wachtwoord van je huidige account in
         current_username: Voer ter bevestiging de gebruikersnaam van je huidige account in
         digest: Wordt alleen na een lange periode van inactiviteit verzonden en alleen wanneer je tijdens jouw afwezigheid persoonlijke berichten hebt ontvangen
         email: Je krijgt een bevestigingsmail
-        header: WEBP, PNG, GIF of JPG. Hoogstens %{size}. Wordt verkleind naar %{dimensions}px
+        header: WEBP, PNG, GIF of JPG. Maximaal %{size}. Wordt verkleind naar %{dimensions}px
         inbox_url: Kopieer de URL van de voorpagina van de relayserver die je wil gebruiken
         irreversible: Gefilterde berichten verdwijnen onomkeerbaar, zelfs als de filter later wordt verwijderd
         locale: De taal van de gebruikersomgeving, e-mails en pushmeldingen
diff --git a/spec/controllers/activitypub/replies_controller_spec.rb b/spec/controllers/activitypub/replies_controller_spec.rb
index 6b5a69d42a..db7f60d3f8 100644
--- a/spec/controllers/activitypub/replies_controller_spec.rb
+++ b/spec/controllers/activitypub/replies_controller_spec.rb
@@ -90,7 +90,7 @@ RSpec.describe ActivityPub::RepliesController do
         context 'when there are few self-replies' do
           it 'points next to replies from other people' do
             expect(page_json).to be_a Hash
-            expect(Addressable::URI.parse(page_json[:next]).query.split('&')).to include('only_other_accounts=true', 'page=true')
+            expect(parsed_uri_query_values(page_json[:next])).to include('only_other_accounts=true', 'page=true')
           end
         end
 
@@ -101,7 +101,7 @@ RSpec.describe ActivityPub::RepliesController do
 
           it 'points next to other self-replies' do
             expect(page_json).to be_a Hash
-            expect(Addressable::URI.parse(page_json[:next]).query.split('&')).to include('only_other_accounts=false', 'page=true')
+            expect(parsed_uri_query_values(page_json[:next])).to include('only_other_accounts=false', 'page=true')
           end
         end
       end
@@ -140,7 +140,7 @@ RSpec.describe ActivityPub::RepliesController do
 
           it 'points next to other replies' do
             expect(page_json).to be_a Hash
-            expect(Addressable::URI.parse(page_json[:next]).query.split('&')).to include('only_other_accounts=true', 'page=true')
+            expect(parsed_uri_query_values(page_json[:next])).to include('only_other_accounts=true', 'page=true')
           end
         end
       end
@@ -196,6 +196,13 @@ RSpec.describe ActivityPub::RepliesController do
 
   private
 
+  def parsed_uri_query_values(uri)
+    Addressable::URI
+      .parse(uri)
+      .query
+      .split('&')
+  end
+
   def ap_public_collection
     ActivityPub::TagManager::COLLECTIONS[:public]
   end
diff --git a/spec/controllers/api/v1/accounts/statuses_controller_spec.rb b/spec/controllers/api/v1/accounts/statuses_controller_spec.rb
index 9bf385c03d..102e3b8e91 100644
--- a/spec/controllers/api/v1/accounts/statuses_controller_spec.rb
+++ b/spec/controllers/api/v1/accounts/statuses_controller_spec.rb
@@ -18,7 +18,8 @@ describe Api::V1::Accounts::StatusesController do
       get :index, params: { account_id: user.account.id, limit: 1 }
 
       expect(response).to have_http_status(200)
-      expect(response.headers['Link'].links.size).to eq(2)
+      expect(links_from_header.size)
+        .to eq(2)
     end
 
     context 'with only media' do
@@ -55,10 +56,45 @@ describe Api::V1::Accounts::StatusesController do
         Fabricate(:status_pin, account: user.account, status: Fabricate(:status, account: user.account))
       end
 
-      it 'returns http success' do
+      it 'returns http success and includes a header link' do
         get :index, params: { account_id: user.account.id, pinned: true }
 
         expect(response).to have_http_status(200)
+        expect(links_from_header.size)
+          .to eq(1)
+        expect(links_from_header)
+          .to contain_exactly(
+            have_attributes(
+              href: /pinned=true/,
+              attr_pairs: contain_exactly(['rel', 'prev'])
+            )
+          )
+      end
+    end
+
+    context 'with enough pinned statuses to paginate' do
+      before do
+        stub_const 'Api::BaseController::DEFAULT_STATUSES_LIMIT', 1
+        2.times { Fabricate(:status_pin, account: user.account) }
+      end
+
+      it 'returns http success and header pagination links to prev and next' do
+        get :index, params: { account_id: user.account.id, pinned: true }
+
+        expect(response).to have_http_status(200)
+        expect(links_from_header.size)
+          .to eq(2)
+        expect(links_from_header)
+          .to contain_exactly(
+            have_attributes(
+              href: /pinned=true/,
+              attr_pairs: contain_exactly(['rel', 'next'])
+            ),
+            have_attributes(
+              href: /pinned=true/,
+              attr_pairs: contain_exactly(['rel', 'prev'])
+            )
+          )
       end
     end
 
@@ -98,4 +134,12 @@ describe Api::V1::Accounts::StatusesController do
       end
     end
   end
+
+  private
+
+  def links_from_header
+    response
+      .headers['Link']
+      .links
+  end
 end
diff --git a/spec/fabricators/software_update_fabricator.rb b/spec/fabricators/software_update_fabricator.rb
index 622fff66e8..f4b607da0a 100644
--- a/spec/fabricators/software_update_fabricator.rb
+++ b/spec/fabricators/software_update_fabricator.rb
@@ -1,7 +1,7 @@
 # frozen_string_literal: true
 
 Fabricator(:software_update) do
-  version '99.99.99'
+  version { sequence(:version) { |point| "99.99.#{point}" } }
   urgent false
   type 'patch'
 end
diff --git a/yarn.lock b/yarn.lock
index 9baca397ea..110a15888b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -42,7 +42,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5":
+"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.23.5":
   version: 7.23.5
   resolution: "@babel/code-frame@npm:7.23.5"
   dependencies:
@@ -373,15 +373,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@babel/parser@npm:^7.22.15":
-  version: 7.23.6
-  resolution: "@babel/parser@npm:7.23.6"
-  bin:
-    parser: ./bin/babel-parser.js
-  checksum: 10c0/6f76cd5ccae1fa9bcab3525b0865c6222e9c1d22f87abc69f28c5c7b2c8816a13361f5bd06bddbd5faf903f7320a8feba02545c981468acec45d12a03db7755e
-  languageName: node
-  linkType: hard
-
 "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.23.3":
   version: 7.23.3
   resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.23.3"
@@ -1500,18 +1491,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@babel/template@npm:^7.22.15, @babel/template@npm:^7.3.3":
-  version: 7.22.15
-  resolution: "@babel/template@npm:7.22.15"
-  dependencies:
-    "@babel/code-frame": "npm:^7.22.13"
-    "@babel/parser": "npm:^7.22.15"
-    "@babel/types": "npm:^7.22.15"
-  checksum: 10c0/9312edd37cf1311d738907003f2aa321a88a42ba223c69209abe4d7111db019d321805504f606c7fd75f21c6cf9d24d0a8223104cd21ebd207e241b6c551f454
-  languageName: node
-  linkType: hard
-
-"@babel/template@npm:^7.23.9":
+"@babel/template@npm:^7.22.15, @babel/template@npm:^7.23.9, @babel/template@npm:^7.3.3":
   version: 7.23.9
   resolution: "@babel/template@npm:7.23.9"
   dependencies:
@@ -1540,18 +1520,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.6, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3":
-  version: 7.23.6
-  resolution: "@babel/types@npm:7.23.6"
-  dependencies:
-    "@babel/helper-string-parser": "npm:^7.23.4"
-    "@babel/helper-validator-identifier": "npm:^7.22.20"
-    to-fast-properties: "npm:^2.0.0"
-  checksum: 10c0/42cefce8a68bd09bb5828b4764aa5586c53c60128ac2ac012e23858e1c179347a4aac9c66fc577994fbf57595227611c5ec8270bf0cfc94ff033bbfac0550b70
-  languageName: node
-  linkType: hard
-
-"@babel/types@npm:^7.23.9":
+"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.6, @babel/types@npm:^7.23.9, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3":
   version: 7.23.9
   resolution: "@babel/types@npm:7.23.9"
   dependencies:
@@ -5036,12 +5005,12 @@ __metadata:
   languageName: node
   linkType: hard
 
-"body-parser@npm:1.20.1":
-  version: 1.20.1
-  resolution: "body-parser@npm:1.20.1"
+"body-parser@npm:1.20.2":
+  version: 1.20.2
+  resolution: "body-parser@npm:1.20.2"
   dependencies:
     bytes: "npm:3.1.2"
-    content-type: "npm:~1.0.4"
+    content-type: "npm:~1.0.5"
     debug: "npm:2.6.9"
     depd: "npm:2.0.0"
     destroy: "npm:1.2.0"
@@ -5049,10 +5018,10 @@ __metadata:
     iconv-lite: "npm:0.4.24"
     on-finished: "npm:2.4.1"
     qs: "npm:6.11.0"
-    raw-body: "npm:2.5.1"
+    raw-body: "npm:2.5.2"
     type-is: "npm:~1.6.18"
     unpipe: "npm:1.0.0"
-  checksum: 10c0/a202d493e2c10a33fb7413dac7d2f713be579c4b88343cd814b6df7a38e5af1901fc31044e04de176db56b16d9772aa25a7723f64478c20f4d91b1ac223bf3b8
+  checksum: 10c0/06f1438fff388a2e2354c96aa3ea8147b79bfcb1262dfcc2aae68ec13723d01d5781680657b74e9f83c808266d5baf52804032fbde2b7382b89bd8cdb273ace9
   languageName: node
   linkType: hard
 
@@ -5882,7 +5851,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"content-type@npm:~1.0.4":
+"content-type@npm:~1.0.4, content-type@npm:~1.0.5":
   version: 1.0.5
   resolution: "content-type@npm:1.0.5"
   checksum: 10c0/b76ebed15c000aee4678c3707e0860cb6abd4e680a598c0a26e17f0bfae723ec9cc2802f0ff1bc6e4d80603719010431d2231018373d4dde10f9ccff9dadf5af
@@ -7757,12 +7726,12 @@ __metadata:
   linkType: hard
 
 "express@npm:^4.17.1, express@npm:^4.18.2":
-  version: 4.18.2
-  resolution: "express@npm:4.18.2"
+  version: 4.18.3
+  resolution: "express@npm:4.18.3"
   dependencies:
     accepts: "npm:~1.3.8"
     array-flatten: "npm:1.1.1"
-    body-parser: "npm:1.20.1"
+    body-parser: "npm:1.20.2"
     content-disposition: "npm:0.5.4"
     content-type: "npm:~1.0.4"
     cookie: "npm:0.5.0"
@@ -7791,7 +7760,7 @@ __metadata:
     type-is: "npm:~1.6.18"
     utils-merge: "npm:1.0.1"
     vary: "npm:~1.1.2"
-  checksum: 10c0/75af556306b9241bc1d7bdd40c9744b516c38ce50ae3210658efcbf96e3aed4ab83b3432f06215eae5610c123bc4136957dc06e50dfc50b7d4d775af56c4c59c
+  checksum: 10c0/0b9eeafbac549e3c67d92d083bf1773e358359f41ad142b92121935c6348d29079b75054555b3f62de39263fffc8ba06898b09fdd3e213e28e714c03c5d9f44c
   languageName: node
   linkType: hard
 
@@ -13436,15 +13405,15 @@ __metadata:
   languageName: node
   linkType: hard
 
-"raw-body@npm:2.5.1":
-  version: 2.5.1
-  resolution: "raw-body@npm:2.5.1"
+"raw-body@npm:2.5.2":
+  version: 2.5.2
+  resolution: "raw-body@npm:2.5.2"
   dependencies:
     bytes: "npm:3.1.2"
     http-errors: "npm:2.0.0"
     iconv-lite: "npm:0.4.24"
     unpipe: "npm:1.0.0"
-  checksum: 10c0/5dad5a3a64a023b894ad7ab4e5c7c1ce34d3497fc7138d02f8c88a3781e68d8a55aa7d4fd3a458616fa8647cc228be314a1c03fb430a07521de78b32c4dd09d2
+  checksum: 10c0/b201c4b66049369a60e766318caff5cb3cc5a900efd89bdac431463822d976ad0670912c931fdbdcf5543207daf6f6833bca57aa116e1661d2ea91e12ca692c4
   languageName: node
   linkType: hard