diff --git a/Gemfile.lock b/Gemfile.lock
index 02437eab6b..42cc0e1986 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -100,8 +100,8 @@ GEM
     attr_required (1.0.2)
     awrence (1.2.1)
     aws-eventstream (1.3.0)
-    aws-partitions (1.947.0)
-    aws-sdk-core (3.199.0)
+    aws-partitions (1.949.0)
+    aws-sdk-core (3.200.0)
       aws-eventstream (~> 1, >= 1.3.0)
       aws-partitions (~> 1, >= 1.651.0)
       aws-sigv4 (~> 1.8)
@@ -109,7 +109,7 @@ GEM
     aws-sdk-kms (1.87.0)
       aws-sdk-core (~> 3, >= 3.199.0)
       aws-sigv4 (~> 1.1)
-    aws-sdk-s3 (1.154.0)
+    aws-sdk-s3 (1.155.0)
       aws-sdk-core (~> 3, >= 3.199.0)
       aws-sdk-kms (~> 1)
       aws-sigv4 (~> 1.8)
@@ -696,7 +696,7 @@ GEM
     responders (3.1.1)
       actionpack (>= 5.2)
       railties (>= 5.2)
-    rexml (3.3.0)
+    rexml (3.3.1)
       strscan
     rotp (6.3.0)
     rouge (4.2.1)
@@ -751,7 +751,7 @@ GEM
     rubocop-performance (1.21.1)
       rubocop (>= 1.48.1, < 2.0)
       rubocop-ast (>= 1.31.1, < 2.0)
-    rubocop-rails (2.25.0)
+    rubocop-rails (2.25.1)
       activesupport (>= 4.2.0)
       rack (>= 1.1)
       rubocop (>= 1.33.0, < 2.0)
@@ -833,7 +833,7 @@ GEM
       unicode-display_width (>= 1.1.1, < 3)
     terrapin (1.0.1)
       climate_control
-    test-prof (1.3.3)
+    test-prof (1.3.3.1)
     thor (1.3.1)
     tilt (2.3.0)
     timeout (0.4.1)
diff --git a/app/javascript/flavours/glitch/actions/timelines.js b/app/javascript/flavours/glitch/actions/timelines.js
index d3ce4c575c..eb5050f152 100644
--- a/app/javascript/flavours/glitch/actions/timelines.js
+++ b/app/javascript/flavours/glitch/actions/timelines.js
@@ -170,6 +170,7 @@ export const expandAccountTimeline         = (accountId, { maxId, withReplies, t
 export const expandAccountFeaturedTimeline = (accountId, { tagged } = {}) => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true, tagged });
 export const expandAccountMediaTimeline    = (accountId, { maxId } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true, limit: 40 });
 export const expandListTimeline            = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done);
+export const expandLinkTimeline            = (url, { maxId } = {}, done = noOp) => expandTimeline(`link:${url}`, `/api/v1/timelines/link`, { url, max_id: maxId }, done);
 export const expandHashtagTimeline         = (hashtag, { maxId, tags, local } = {}, done = noOp) => {
   return expandTimeline(`hashtag:${hashtag}${local ? ':local' : ''}`, `/api/v1/timelines/tag/${hashtag}`, {
     max_id: maxId,
diff --git a/app/javascript/flavours/glitch/api_types/statuses.ts b/app/javascript/flavours/glitch/api_types/statuses.ts
index 261d600305..9de86e7fa6 100644
--- a/app/javascript/flavours/glitch/api_types/statuses.ts
+++ b/app/javascript/flavours/glitch/api_types/statuses.ts
@@ -44,6 +44,7 @@ export interface ApiPreviewCardJSON {
   type: string;
   author_name: string;
   author_url: string;
+  author_account?: ApiAccountJSON;
   provider_name: string;
   provider_url: string;
   html: string;
diff --git a/app/javascript/flavours/glitch/components/follow_button.tsx b/app/javascript/flavours/glitch/components/follow_button.tsx
index 5c9cd2c067..a6b2064703 100644
--- a/app/javascript/flavours/glitch/components/follow_button.tsx
+++ b/app/javascript/flavours/glitch/components/follow_button.tsx
@@ -1,6 +1,6 @@
 import { useCallback, useEffect } from 'react';
 
-import { useIntl, defineMessages } from 'react-intl';
+import { useIntl, defineMessages, FormattedMessage } from 'react-intl';
 
 import { useIdentity } from '@/flavours/glitch/identity_context';
 import {
@@ -18,15 +18,11 @@ const messages = defineMessages({
   unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
   follow: { id: 'account.follow', defaultMessage: 'Follow' },
   followBack: { id: 'account.follow_back', defaultMessage: 'Follow back' },
-  cancel_follow_request: {
-    id: 'account.cancel_follow_request',
-    defaultMessage: 'Withdraw follow request',
-  },
   edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' },
 });
 
 export const FollowButton: React.FC<{
-  accountId: string;
+  accountId?: string;
 }> = ({ accountId }) => {
   const intl = useIntl();
   const dispatch = useAppDispatch();
@@ -35,7 +31,7 @@ export const FollowButton: React.FC<{
     accountId ? state.accounts.get(accountId) : undefined,
   );
   const relationship = useAppSelector((state) =>
-    state.relationships.get(accountId),
+    accountId ? state.relationships.get(accountId) : undefined,
   );
   const following = relationship?.following || relationship?.requested;
 
@@ -64,11 +60,28 @@ export const FollowButton: React.FC<{
     if (accountId === me) {
       return;
     } else if (relationship.following || relationship.requested) {
-      dispatch(unfollowAccount(accountId));
+      dispatch(
+        openModal({
+          modalType: 'CONFIRM',
+          modalProps: {
+            message: (
+              <FormattedMessage
+                id='confirmations.unfollow.message'
+                defaultMessage='Are you sure you want to unfollow {name}?'
+                values={{ name: <strong>@{account?.acct}</strong> }}
+              />
+            ),
+            confirm: intl.formatMessage(messages.unfollow),
+            onConfirm: () => {
+              dispatch(unfollowAccount(accountId));
+            },
+          },
+        }),
+      );
     } else {
       dispatch(followAccount(accountId));
     }
-  }, [dispatch, accountId, relationship, account, signedIn]);
+  }, [dispatch, intl, accountId, relationship, account, signedIn]);
 
   let label;
 
@@ -78,11 +91,9 @@ export const FollowButton: React.FC<{
     label = intl.formatMessage(messages.edit_profile);
   } else if (!relationship) {
     label = <LoadingIndicator />;
-  } else if (relationship.requested) {
-    label = intl.formatMessage(messages.cancel_follow_request);
   } else if (!relationship.following && relationship.followed_by) {
     label = intl.formatMessage(messages.followBack);
-  } else if (relationship.following) {
+  } else if (relationship.following || relationship.requested) {
     label = intl.formatMessage(messages.unfollow);
   } else {
     label = intl.formatMessage(messages.follow);
diff --git a/app/javascript/flavours/glitch/components/hover_card_account.tsx b/app/javascript/flavours/glitch/components/hover_card_account.tsx
index a62128e17b..56f431a786 100644
--- a/app/javascript/flavours/glitch/components/hover_card_account.tsx
+++ b/app/javascript/flavours/glitch/components/hover_card_account.tsx
@@ -17,7 +17,7 @@ import { useAppSelector, useAppDispatch } from 'flavours/glitch/store';
 
 export const HoverCardAccount = forwardRef<
   HTMLDivElement,
-  { accountId: string }
+  { accountId?: string }
 >(({ accountId }, ref) => {
   const dispatch = useAppDispatch();
 
diff --git a/app/javascript/flavours/glitch/components/hover_card_controller.tsx b/app/javascript/flavours/glitch/components/hover_card_controller.tsx
index 6e11d28381..347dcd4f2f 100644
--- a/app/javascript/flavours/glitch/components/hover_card_controller.tsx
+++ b/app/javascript/flavours/glitch/components/hover_card_controller.tsx
@@ -12,8 +12,8 @@ import { HoverCardAccount } from 'flavours/glitch/components/hover_card_account'
 import { useTimeout } from 'flavours/glitch/hooks/useTimeout';
 
 const offset = [-12, 4] as OffsetValue;
-const enterDelay = 650;
-const leaveDelay = 250;
+const enterDelay = 750;
+const leaveDelay = 150;
 const popperConfig = { strategy: 'fixed' } as UsePopperOptions;
 
 const isHoverCardAnchor = (element: HTMLElement) =>
@@ -23,50 +23,12 @@ export const HoverCardController: React.FC = () => {
   const [open, setOpen] = useState(false);
   const [accountId, setAccountId] = useState<string | undefined>();
   const [anchor, setAnchor] = useState<HTMLElement | null>(null);
-  const cardRef = useRef<HTMLDivElement>(null);
+  const cardRef = useRef<HTMLDivElement | null>(null);
   const [setLeaveTimeout, cancelLeaveTimeout] = useTimeout();
-  const [setEnterTimeout, cancelEnterTimeout] = useTimeout();
+  const [setEnterTimeout, cancelEnterTimeout, delayEnterTimeout] = useTimeout();
+  const [setScrollTimeout] = useTimeout();
   const location = useLocation();
 
-  const handleAnchorMouseEnter = useCallback(
-    (e: MouseEvent) => {
-      const { target } = e;
-
-      if (target instanceof HTMLElement && isHoverCardAnchor(target)) {
-        cancelLeaveTimeout();
-
-        setEnterTimeout(() => {
-          target.setAttribute('aria-describedby', 'hover-card');
-          setAnchor(target);
-          setOpen(true);
-          setAccountId(
-            target.getAttribute('data-hover-card-account') ?? undefined,
-          );
-        }, enterDelay);
-      }
-
-      if (target === cardRef.current?.parentNode) {
-        cancelLeaveTimeout();
-      }
-    },
-    [cancelLeaveTimeout, setEnterTimeout, setOpen, setAccountId, setAnchor],
-  );
-
-  const handleAnchorMouseLeave = useCallback(
-    (e: MouseEvent) => {
-      if (e.target === anchor || e.target === cardRef.current?.parentNode) {
-        cancelEnterTimeout();
-
-        setLeaveTimeout(() => {
-          anchor?.removeAttribute('aria-describedby');
-          setOpen(false);
-          setAnchor(null);
-        }, leaveDelay);
-      }
-    },
-    [cancelEnterTimeout, setLeaveTimeout, setOpen, setAnchor, anchor],
-  );
-
   const handleClose = useCallback(() => {
     cancelEnterTimeout();
     cancelLeaveTimeout();
@@ -79,22 +41,119 @@ export const HoverCardController: React.FC = () => {
   }, [handleClose, location]);
 
   useEffect(() => {
-    document.body.addEventListener('mouseenter', handleAnchorMouseEnter, {
+    let isScrolling = false;
+    let currentAnchor: HTMLElement | null = null;
+
+    const open = (target: HTMLElement) => {
+      target.setAttribute('aria-describedby', 'hover-card');
+      setOpen(true);
+      setAnchor(target);
+      setAccountId(target.getAttribute('data-hover-card-account') ?? undefined);
+    };
+
+    const close = () => {
+      currentAnchor?.removeAttribute('aria-describedby');
+      currentAnchor = null;
+      setOpen(false);
+      setAnchor(null);
+      setAccountId(undefined);
+    };
+
+    const handleMouseEnter = (e: MouseEvent) => {
+      const { target } = e;
+
+      // We've exited the window
+      if (!(target instanceof HTMLElement)) {
+        close();
+        return;
+      }
+
+      // We've entered an anchor
+      if (!isScrolling && isHoverCardAnchor(target)) {
+        cancelLeaveTimeout();
+
+        currentAnchor?.removeAttribute('aria-describedby');
+        currentAnchor = target;
+
+        setEnterTimeout(() => {
+          open(target);
+        }, enterDelay);
+      }
+
+      // We've entered the hover card
+      if (
+        !isScrolling &&
+        (target === currentAnchor || target === cardRef.current)
+      ) {
+        cancelLeaveTimeout();
+      }
+    };
+
+    const handleMouseLeave = (e: MouseEvent) => {
+      if (!currentAnchor) {
+        return;
+      }
+
+      if (e.target === currentAnchor || e.target === cardRef.current) {
+        cancelEnterTimeout();
+
+        setLeaveTimeout(() => {
+          close();
+        }, leaveDelay);
+      }
+    };
+
+    const handleScrollEnd = () => {
+      isScrolling = false;
+    };
+
+    const handleScroll = () => {
+      isScrolling = true;
+      cancelEnterTimeout();
+      setScrollTimeout(handleScrollEnd, 100);
+    };
+
+    const handleMouseMove = () => {
+      delayEnterTimeout(enterDelay);
+    };
+
+    document.body.addEventListener('mouseenter', handleMouseEnter, {
       passive: true,
       capture: true,
     });
-    document.body.addEventListener('mouseleave', handleAnchorMouseLeave, {
+
+    document.body.addEventListener('mousemove', handleMouseMove, {
+      passive: true,
+      capture: false,
+    });
+
+    document.body.addEventListener('mouseleave', handleMouseLeave, {
+      passive: true,
+      capture: true,
+    });
+
+    document.addEventListener('scroll', handleScroll, {
       passive: true,
       capture: true,
     });
 
     return () => {
-      document.body.removeEventListener('mouseenter', handleAnchorMouseEnter);
-      document.body.removeEventListener('mouseleave', handleAnchorMouseLeave);
+      document.body.removeEventListener('mouseenter', handleMouseEnter);
+      document.body.removeEventListener('mousemove', handleMouseMove);
+      document.body.removeEventListener('mouseleave', handleMouseLeave);
+      document.removeEventListener('scroll', handleScroll);
     };
-  }, [handleAnchorMouseEnter, handleAnchorMouseLeave]);
-
-  if (!accountId) return null;
+  }, [
+    setEnterTimeout,
+    setLeaveTimeout,
+    setScrollTimeout,
+    cancelEnterTimeout,
+    cancelLeaveTimeout,
+    delayEnterTimeout,
+    setOpen,
+    setAccountId,
+    setAnchor,
+  ]);
 
   return (
     <Overlay
diff --git a/app/javascript/flavours/glitch/components/status_list.jsx b/app/javascript/flavours/glitch/components/status_list.jsx
index dde8bd9663..374d14a56a 100644
--- a/app/javascript/flavours/glitch/components/status_list.jsx
+++ b/app/javascript/flavours/glitch/components/status_list.jsx
@@ -33,6 +33,7 @@ export default class StatusList extends ImmutablePureComponent {
     withCounters: PropTypes.bool,
     timelineId: PropTypes.string.isRequired,
     lastId: PropTypes.string,
+    bindToDocument: PropTypes.bool,
     regex: PropTypes.string,
   };
 
diff --git a/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.jsx b/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.jsx
index a87c7fd3e4..1e85a08cd9 100644
--- a/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.jsx
+++ b/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.jsx
@@ -23,7 +23,6 @@ import { makeGetAccount, getAccountHidden } from '../../../selectors';
 import Header from '../components/header';
 
 const messages = defineMessages({
-  cancelFollowRequestConfirm: { id: 'confirmations.cancel_follow_request.confirm', defaultMessage: 'Withdraw request' },
   unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' },
   blockDomainConfirm: { id: 'confirmations.domain_block.confirm', defaultMessage: 'Block entire domain' },
 });
@@ -43,7 +42,7 @@ const makeMapStateToProps = () => {
 const mapDispatchToProps = (dispatch, { intl }) => ({
 
   onFollow (account) {
-    if (account.getIn(['relationship', 'following'])) {
+    if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) {
       dispatch(openModal({
         modalType: 'CONFIRM',
         modalProps: {
@@ -52,15 +51,6 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
           onConfirm: () => dispatch(unfollowAccount(account.get('id'))),
         },
       }));
-    } else if (account.getIn(['relationship', 'requested'])) {
-      dispatch(openModal({
-        modalType: 'CONFIRM',
-        modalProps: {
-          message: <FormattedMessage id='confirmations.cancel_follow_request.message' defaultMessage='Are you sure you want to withdraw your request to follow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
-          confirm: intl.formatMessage(messages.cancelFollowRequestConfirm),
-          onConfirm: () => dispatch(unfollowAccount(account.get('id'))),
-        },
-      }));
     } else {
       dispatch(followAccount(account.get('id')));
     }
diff --git a/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.jsx b/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.jsx
index 458a547d02..7071c8719d 100644
--- a/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.jsx
+++ b/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.jsx
@@ -185,7 +185,7 @@ export const Conversation = ({ conversation, scrollKey, onMoveUp, onMoveDown })
   menu.push({ text: intl.formatMessage(messages.delete), action: handleDelete });
 
   const names = accounts.map(a => (
-    <Permalink to={`/@${a.get('acct')}`} href={a.get('url')} key={a.get('id')} title={a.get('acct')}>
+    <Permalink to={`/@${a.get('acct')}`} href={a.get('url')} key={a.get('id')} data-hover-card-account={a.get('id')}>
       <bdi>
         <strong
           className='display-name__html'
diff --git a/app/javascript/flavours/glitch/features/explore/components/story.jsx b/app/javascript/flavours/glitch/features/explore/components/story.jsx
index 28a1d69f8a..b07425b277 100644
--- a/app/javascript/flavours/glitch/features/explore/components/story.jsx
+++ b/app/javascript/flavours/glitch/features/explore/components/story.jsx
@@ -4,6 +4,8 @@ import { useState, useCallback } from 'react';
 import { FormattedMessage } from 'react-intl';
 
 import classNames from 'classnames';
+import { Link } from 'react-router-dom';
+
 
 
 import { Blurhash } from 'flavours/glitch/components/blurhash';
@@ -57,7 +59,7 @@ export const Story = ({
 
         <div className='story__details__shared'>
           {author ? <FormattedMessage id='link_preview.author' className='story__details__shared__author' defaultMessage='By {name}' values={{ name: authorAccount ? <AuthorLink accountId={authorAccount} /> : <strong>{author}</strong> }} /> : <span />}
-          {typeof sharedTimes === 'number' ? <span className='story__details__shared__pill'><ShortNumber value={sharedTimes} renderer={sharesCountRenderer} /></span> : <Skeleton width='10ch' />}
+          {typeof sharedTimes === 'number' ? <Link className='story__details__shared__pill' to={`/links/${encodeURIComponent(url)}`}><ShortNumber value={sharedTimes} renderer={sharesCountRenderer} /></Link> : <Skeleton width='10ch' />}
         </div>
       </div>
 
diff --git a/app/javascript/flavours/glitch/features/link_timeline/index.tsx b/app/javascript/flavours/glitch/features/link_timeline/index.tsx
new file mode 100644
index 0000000000..bbe295d474
--- /dev/null
+++ b/app/javascript/flavours/glitch/features/link_timeline/index.tsx
@@ -0,0 +1,77 @@
+import { useRef, useEffect, useCallback } from 'react';
+
+import { Helmet } from 'react-helmet';
+import { useParams } from 'react-router-dom';
+
+import ExploreIcon from '@/material-icons/400-24px/explore.svg?react';
+import { expandLinkTimeline } from 'flavours/glitch/actions/timelines';
+import Column from 'flavours/glitch/components/column';
+import { ColumnHeader } from 'flavours/glitch/components/column_header';
+import StatusListContainer from 'flavours/glitch/features/ui/containers/status_list_container';
+import type { Card } from 'flavours/glitch/models/status';
+import { useAppDispatch, useAppSelector } from 'flavours/glitch/store';
+
+export const LinkTimeline: React.FC<{
+  multiColumn: boolean;
+}> = ({ multiColumn }) => {
+  const { url } = useParams<{ url: string }>();
+  const decodedUrl = url ? decodeURIComponent(url) : undefined;
+  const dispatch = useAppDispatch();
+  const columnRef = useRef<Column>(null);
+  const firstStatusId = useAppSelector((state) =>
+    decodedUrl
+      ? // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
+        (state.timelines.getIn([`link:${decodedUrl}`, 'items', 0]) as string)
+      : undefined,
+  );
+  const story = useAppSelector((state) =>
+    firstStatusId
+      ? (state.statuses.getIn([firstStatusId, 'card']) as Card)
+      : undefined,
+  );
+
+  const handleHeaderClick = useCallback(() => {
+    columnRef.current?.scrollTop();
+  }, []);
+
+  const handleLoadMore = useCallback(
+    (maxId: string) => {
+      dispatch(expandLinkTimeline(decodedUrl, { maxId }));
+    },
+    [dispatch, decodedUrl],
+  );
+
+  useEffect(() => {
+    dispatch(expandLinkTimeline(decodedUrl));
+  }, [dispatch, decodedUrl]);
+
+  return (
+    <Column bindToDocument={!multiColumn} ref={columnRef} label={story?.title}>
+      <ColumnHeader
+        icon='explore'
+        iconComponent={ExploreIcon}
+        title={story?.title}
+        onClick={handleHeaderClick}
+        multiColumn={multiColumn}
+        showBackButton
+      />
+
+      <StatusListContainer
+        timelineId={`link:${decodedUrl}`}
+        onLoadMore={handleLoadMore}
+        trackScroll
+        scrollKey={`link_timeline-${decodedUrl}`}
+        bindToDocument={!multiColumn}
+        regex={undefined}
+      />
+
+      <Helmet>
+        <title>{story?.title}</title>
+        <meta name='robots' content='noindex' />
+      </Helmet>
+    </Column>
+  );
+};
+
+// eslint-disable-next-line import/no-default-export
+export default LinkTimeline;
diff --git a/app/javascript/flavours/glitch/features/ui/index.jsx b/app/javascript/flavours/glitch/features/ui/index.jsx
index 9fb4a784b3..747922f23e 100644
--- a/app/javascript/flavours/glitch/features/ui/index.jsx
+++ b/app/javascript/flavours/glitch/features/ui/index.jsx
@@ -58,6 +58,7 @@ import {
   FavouritedStatuses,
   BookmarkedStatuses,
   FollowedTags,
+  LinkTimeline,
   ListTimeline,
   Blocks,
   DomainBlocks,
@@ -211,6 +212,7 @@ class SwitchingColumnsArea extends PureComponent {
             <WrappedRoute path='/public/remote' exact component={Firehose} componentParams={{ feedType: 'public:remote' }} content={children} />
             <WrappedRoute path={['/conversations', '/timelines/direct']} component={DirectTimeline} content={children} />
             <WrappedRoute path='/tags/:id' component={HashtagTimeline} content={children} />
+            <WrappedRoute path='/links/:url' component={LinkTimeline} content={children} />
             <WrappedRoute path='/lists/:id' component={ListTimeline} content={children} />
             <WrappedRoute path='/notifications' component={Notifications} content={children} exact />
             <WrappedRoute path='/notifications/requests' component={NotificationRequests} content={children} exact />
@@ -649,7 +651,7 @@ class UI extends PureComponent {
 
           {layout !== 'mobile' && <PictureInPicture />}
           <NotificationsContainer />
-          {/* Temporarily disabled while upstream improves the issue */ null && <HoverCardController />}
+          <HoverCardController />
           <LoadingBarContainer className='loading-bar' />
           <ModalContainer />
           <UploadArea active={draggingOver} onClose={this.closeUploadModal} />
diff --git a/app/javascript/flavours/glitch/features/ui/util/async-components.js b/app/javascript/flavours/glitch/features/ui/util/async-components.js
index 6a140e3fd7..a312cefff7 100644
--- a/app/javascript/flavours/glitch/features/ui/util/async-components.js
+++ b/app/javascript/flavours/glitch/features/ui/util/async-components.js
@@ -213,3 +213,7 @@ export function NotificationRequests () {
 export function NotificationRequest () {
   return import(/*webpackChunkName: "features/glitch/notifications/request" */'../../notifications/request');
 }
+
+export function LinkTimeline () {
+  return import(/*webpackChunkName: "features/glitch/link_timeline" */'../../link_timeline');
+}
diff --git a/app/javascript/flavours/glitch/hooks/useTimeout.ts b/app/javascript/flavours/glitch/hooks/useTimeout.ts
index f1814ae8e3..bb1e8848dd 100644
--- a/app/javascript/flavours/glitch/hooks/useTimeout.ts
+++ b/app/javascript/flavours/glitch/hooks/useTimeout.ts
@@ -2,19 +2,34 @@ import { useRef, useCallback, useEffect } from 'react';
 
 export const useTimeout = () => {
   const timeoutRef = useRef<ReturnType<typeof setTimeout>>();
+  const callbackRef = useRef<() => void>();
 
   const set = useCallback((callback: () => void, delay: number) => {
     if (timeoutRef.current) {
       clearTimeout(timeoutRef.current);
     }
 
+    callbackRef.current = callback;
     timeoutRef.current = setTimeout(callback, delay);
   }, []);
 
+  const delay = useCallback((delay: number) => {
+    if (timeoutRef.current) {
+      clearTimeout(timeoutRef.current);
+    }
+
+    if (!callbackRef.current) {
+      return;
+    }
+
+    timeoutRef.current = setTimeout(callbackRef.current, delay);
+  }, []);
+
   const cancel = useCallback(() => {
     if (timeoutRef.current) {
       clearTimeout(timeoutRef.current);
       timeoutRef.current = undefined;
+      callbackRef.current = undefined;
     }
   }, []);
 
@@ -25,5 +40,5 @@ export const useTimeout = () => {
     [cancel],
   );
 
-  return [set, cancel] as const;
+  return [set, cancel, delay] as const;
 };
diff --git a/app/javascript/flavours/glitch/models/status.ts b/app/javascript/flavours/glitch/models/status.ts
index d9566daf39..bf1784bc61 100644
--- a/app/javascript/flavours/glitch/models/status.ts
+++ b/app/javascript/flavours/glitch/models/status.ts
@@ -1,4 +1,12 @@
+import type { RecordOf } from 'immutable';
+
+import type { ApiPreviewCardJSON } from 'flavours/glitch/api_types/statuses';
+
 export type { StatusVisibility } from 'flavours/glitch/api_types/statuses';
 
 // Temporary until we type it correctly
 export type Status = Immutable.Map<string, unknown>;
+
+type CardShape = Required<ApiPreviewCardJSON>;
+
+export type Card = RecordOf<CardShape>;
diff --git a/app/javascript/flavours/glitch/styles/components.scss b/app/javascript/flavours/glitch/styles/components.scss
index 2760259346..5c2a130cb9 100644
--- a/app/javascript/flavours/glitch/styles/components.scss
+++ b/app/javascript/flavours/glitch/styles/components.scss
@@ -11022,12 +11022,14 @@ noscript {
         overflow: hidden;
         white-space: nowrap;
         text-overflow: ellipsis;
+        text-align: end;
       }
 
       &.verified {
         dd {
           display: flex;
           align-items: center;
+          justify-content: flex-end;
           gap: 4px;
           overflow: hidden;
           white-space: nowrap;
diff --git a/app/javascript/hooks/useTimeout.ts b/app/javascript/hooks/useTimeout.ts
index f1814ae8e3..bb1e8848dd 100644
--- a/app/javascript/hooks/useTimeout.ts
+++ b/app/javascript/hooks/useTimeout.ts
@@ -2,19 +2,34 @@ import { useRef, useCallback, useEffect } from 'react';
 
 export const useTimeout = () => {
   const timeoutRef = useRef<ReturnType<typeof setTimeout>>();
+  const callbackRef = useRef<() => void>();
 
   const set = useCallback((callback: () => void, delay: number) => {
     if (timeoutRef.current) {
       clearTimeout(timeoutRef.current);
     }
 
+    callbackRef.current = callback;
     timeoutRef.current = setTimeout(callback, delay);
   }, []);
 
+  const delay = useCallback((delay: number) => {
+    if (timeoutRef.current) {
+      clearTimeout(timeoutRef.current);
+    }
+
+    if (!callbackRef.current) {
+      return;
+    }
+
+    timeoutRef.current = setTimeout(callbackRef.current, delay);
+  }, []);
+
   const cancel = useCallback(() => {
     if (timeoutRef.current) {
       clearTimeout(timeoutRef.current);
       timeoutRef.current = undefined;
+      callbackRef.current = undefined;
     }
   }, []);
 
@@ -25,5 +40,5 @@ export const useTimeout = () => {
     [cancel],
   );
 
-  return [set, cancel] as const;
+  return [set, cancel, delay] as const;
 };
diff --git a/app/javascript/mastodon/actions/timelines.js b/app/javascript/mastodon/actions/timelines.js
index 4ca3c3a151..f0ea46118e 100644
--- a/app/javascript/mastodon/actions/timelines.js
+++ b/app/javascript/mastodon/actions/timelines.js
@@ -158,6 +158,7 @@ export const expandAccountTimeline         = (accountId, { maxId, withReplies, t
 export const expandAccountFeaturedTimeline = (accountId, { tagged } = {}) => expandTimeline(`account:${accountId}:pinned${tagged ? `:${tagged}` : ''}`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true, tagged });
 export const expandAccountMediaTimeline    = (accountId, { maxId } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true, limit: 40 });
 export const expandListTimeline            = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done);
+export const expandLinkTimeline            = (url, { maxId } = {}, done = noOp) => expandTimeline(`link:${url}`, `/api/v1/timelines/link`, { url, max_id: maxId }, done);
 export const expandHashtagTimeline         = (hashtag, { maxId, tags, local } = {}, done = noOp) => {
   return expandTimeline(`hashtag:${hashtag}${local ? ':local' : ''}`, `/api/v1/timelines/tag/${hashtag}`, {
     max_id: maxId,
diff --git a/app/javascript/mastodon/api_types/statuses.ts b/app/javascript/mastodon/api_types/statuses.ts
index db4e20506f..a934faeb7a 100644
--- a/app/javascript/mastodon/api_types/statuses.ts
+++ b/app/javascript/mastodon/api_types/statuses.ts
@@ -44,6 +44,7 @@ export interface ApiPreviewCardJSON {
   type: string;
   author_name: string;
   author_url: string;
+  author_account?: ApiAccountJSON;
   provider_name: string;
   provider_url: string;
   html: string;
diff --git a/app/javascript/mastodon/components/follow_button.tsx b/app/javascript/mastodon/components/follow_button.tsx
index db59942882..ecc4e1ee17 100644
--- a/app/javascript/mastodon/components/follow_button.tsx
+++ b/app/javascript/mastodon/components/follow_button.tsx
@@ -1,6 +1,6 @@
 import { useCallback, useEffect } from 'react';
 
-import { useIntl, defineMessages } from 'react-intl';
+import { useIntl, defineMessages, FormattedMessage } from 'react-intl';
 
 import { useIdentity } from '@/mastodon/identity_context';
 import {
@@ -19,15 +19,11 @@ const messages = defineMessages({
   follow: { id: 'account.follow', defaultMessage: 'Follow' },
   followBack: { id: 'account.follow_back', defaultMessage: 'Follow back' },
   mutual: { id: 'account.mutual', defaultMessage: 'Mutual' },
-  cancel_follow_request: {
-    id: 'account.cancel_follow_request',
-    defaultMessage: 'Withdraw follow request',
-  },
   edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' },
 });
 
 export const FollowButton: React.FC<{
-  accountId: string;
+  accountId?: string;
 }> = ({ accountId }) => {
   const intl = useIntl();
   const dispatch = useAppDispatch();
@@ -36,7 +32,7 @@ export const FollowButton: React.FC<{
     accountId ? state.accounts.get(accountId) : undefined,
   );
   const relationship = useAppSelector((state) =>
-    state.relationships.get(accountId),
+    accountId ? state.relationships.get(accountId) : undefined,
   );
   const following = relationship?.following || relationship?.requested;
 
@@ -65,11 +61,28 @@ export const FollowButton: React.FC<{
     if (accountId === me) {
       return;
     } else if (relationship.following || relationship.requested) {
-      dispatch(unfollowAccount(accountId));
+      dispatch(
+        openModal({
+          modalType: 'CONFIRM',
+          modalProps: {
+            message: (
+              <FormattedMessage
+                id='confirmations.unfollow.message'
+                defaultMessage='Are you sure you want to unfollow {name}?'
+                values={{ name: <strong>@{account?.acct}</strong> }}
+              />
+            ),
+            confirm: intl.formatMessage(messages.unfollow),
+            onConfirm: () => {
+              dispatch(unfollowAccount(accountId));
+            },
+          },
+        }),
+      );
     } else {
       dispatch(followAccount(accountId));
     }
-  }, [dispatch, accountId, relationship, account, signedIn]);
+  }, [dispatch, intl, accountId, relationship, account, signedIn]);
 
   let label;
 
@@ -79,13 +92,11 @@ export const FollowButton: React.FC<{
     label = intl.formatMessage(messages.edit_profile);
   } else if (!relationship) {
     label = <LoadingIndicator />;
-  } else if (relationship.requested) {
-    label = intl.formatMessage(messages.cancel_follow_request);
   } else if (relationship.following && relationship.followed_by) {
     label = intl.formatMessage(messages.mutual);
   } else if (!relationship.following && relationship.followed_by) {
     label = intl.formatMessage(messages.followBack);
-  } else if (relationship.following) {
+  } else if (relationship.following || relationship.requested) {
     label = intl.formatMessage(messages.unfollow);
   } else {
     label = intl.formatMessage(messages.follow);
diff --git a/app/javascript/mastodon/components/hover_card_account.tsx b/app/javascript/mastodon/components/hover_card_account.tsx
index 59f9577838..8933e14a98 100644
--- a/app/javascript/mastodon/components/hover_card_account.tsx
+++ b/app/javascript/mastodon/components/hover_card_account.tsx
@@ -17,7 +17,7 @@ import { useAppSelector, useAppDispatch } from 'mastodon/store';
 
 export const HoverCardAccount = forwardRef<
   HTMLDivElement,
-  { accountId: string }
+  { accountId?: string }
 >(({ accountId }, ref) => {
   const dispatch = useAppDispatch();
 
diff --git a/app/javascript/mastodon/components/hover_card_controller.tsx b/app/javascript/mastodon/components/hover_card_controller.tsx
index 0130390ef8..5ca55ebde9 100644
--- a/app/javascript/mastodon/components/hover_card_controller.tsx
+++ b/app/javascript/mastodon/components/hover_card_controller.tsx
@@ -12,8 +12,8 @@ import { useTimeout } from 'mastodon/../hooks/useTimeout';
 import { HoverCardAccount } from 'mastodon/components/hover_card_account';
 
 const offset = [-12, 4] as OffsetValue;
-const enterDelay = 650;
-const leaveDelay = 250;
+const enterDelay = 750;
+const leaveDelay = 150;
 const popperConfig = { strategy: 'fixed' } as UsePopperOptions;
 
 const isHoverCardAnchor = (element: HTMLElement) =>
@@ -23,50 +23,12 @@ export const HoverCardController: React.FC = () => {
   const [open, setOpen] = useState(false);
   const [accountId, setAccountId] = useState<string | undefined>();
   const [anchor, setAnchor] = useState<HTMLElement | null>(null);
-  const cardRef = useRef<HTMLDivElement>(null);
+  const cardRef = useRef<HTMLDivElement | null>(null);
   const [setLeaveTimeout, cancelLeaveTimeout] = useTimeout();
-  const [setEnterTimeout, cancelEnterTimeout] = useTimeout();
+  const [setEnterTimeout, cancelEnterTimeout, delayEnterTimeout] = useTimeout();
+  const [setScrollTimeout] = useTimeout();
   const location = useLocation();
 
-  const handleAnchorMouseEnter = useCallback(
-    (e: MouseEvent) => {
-      const { target } = e;
-
-      if (target instanceof HTMLElement && isHoverCardAnchor(target)) {
-        cancelLeaveTimeout();
-
-        setEnterTimeout(() => {
-          target.setAttribute('aria-describedby', 'hover-card');
-          setAnchor(target);
-          setOpen(true);
-          setAccountId(
-            target.getAttribute('data-hover-card-account') ?? undefined,
-          );
-        }, enterDelay);
-      }
-
-      if (target === cardRef.current?.parentNode) {
-        cancelLeaveTimeout();
-      }
-    },
-    [cancelLeaveTimeout, setEnterTimeout, setOpen, setAccountId, setAnchor],
-  );
-
-  const handleAnchorMouseLeave = useCallback(
-    (e: MouseEvent) => {
-      if (e.target === anchor || e.target === cardRef.current?.parentNode) {
-        cancelEnterTimeout();
-
-        setLeaveTimeout(() => {
-          anchor?.removeAttribute('aria-describedby');
-          setOpen(false);
-          setAnchor(null);
-        }, leaveDelay);
-      }
-    },
-    [cancelEnterTimeout, setLeaveTimeout, setOpen, setAnchor, anchor],
-  );
-
   const handleClose = useCallback(() => {
     cancelEnterTimeout();
     cancelLeaveTimeout();
@@ -79,22 +41,119 @@ export const HoverCardController: React.FC = () => {
   }, [handleClose, location]);
 
   useEffect(() => {
-    document.body.addEventListener('mouseenter', handleAnchorMouseEnter, {
+    let isScrolling = false;
+    let currentAnchor: HTMLElement | null = null;
+
+    const open = (target: HTMLElement) => {
+      target.setAttribute('aria-describedby', 'hover-card');
+      setOpen(true);
+      setAnchor(target);
+      setAccountId(target.getAttribute('data-hover-card-account') ?? undefined);
+    };
+
+    const close = () => {
+      currentAnchor?.removeAttribute('aria-describedby');
+      currentAnchor = null;
+      setOpen(false);
+      setAnchor(null);
+      setAccountId(undefined);
+    };
+
+    const handleMouseEnter = (e: MouseEvent) => {
+      const { target } = e;
+
+      // We've exited the window
+      if (!(target instanceof HTMLElement)) {
+        close();
+        return;
+      }
+
+      // We've entered an anchor
+      if (!isScrolling && isHoverCardAnchor(target)) {
+        cancelLeaveTimeout();
+
+        currentAnchor?.removeAttribute('aria-describedby');
+        currentAnchor = target;
+
+        setEnterTimeout(() => {
+          open(target);
+        }, enterDelay);
+      }
+
+      // We've entered the hover card
+      if (
+        !isScrolling &&
+        (target === currentAnchor || target === cardRef.current)
+      ) {
+        cancelLeaveTimeout();
+      }
+    };
+
+    const handleMouseLeave = (e: MouseEvent) => {
+      if (!currentAnchor) {
+        return;
+      }
+
+      if (e.target === currentAnchor || e.target === cardRef.current) {
+        cancelEnterTimeout();
+
+        setLeaveTimeout(() => {
+          close();
+        }, leaveDelay);
+      }
+    };
+
+    const handleScrollEnd = () => {
+      isScrolling = false;
+    };
+
+    const handleScroll = () => {
+      isScrolling = true;
+      cancelEnterTimeout();
+      setScrollTimeout(handleScrollEnd, 100);
+    };
+
+    const handleMouseMove = () => {
+      delayEnterTimeout(enterDelay);
+    };
+
+    document.body.addEventListener('mouseenter', handleMouseEnter, {
       passive: true,
       capture: true,
     });
-    document.body.addEventListener('mouseleave', handleAnchorMouseLeave, {
+
+    document.body.addEventListener('mousemove', handleMouseMove, {
+      passive: true,
+      capture: false,
+    });
+
+    document.body.addEventListener('mouseleave', handleMouseLeave, {
+      passive: true,
+      capture: true,
+    });
+
+    document.addEventListener('scroll', handleScroll, {
       passive: true,
       capture: true,
     });
 
     return () => {
-      document.body.removeEventListener('mouseenter', handleAnchorMouseEnter);
-      document.body.removeEventListener('mouseleave', handleAnchorMouseLeave);
+      document.body.removeEventListener('mouseenter', handleMouseEnter);
+      document.body.removeEventListener('mousemove', handleMouseMove);
+      document.body.removeEventListener('mouseleave', handleMouseLeave);
+      document.removeEventListener('scroll', handleScroll);
     };
-  }, [handleAnchorMouseEnter, handleAnchorMouseLeave]);
-
-  if (!accountId) return null;
+  }, [
+    setEnterTimeout,
+    setLeaveTimeout,
+    setScrollTimeout,
+    cancelEnterTimeout,
+    cancelLeaveTimeout,
+    delayEnterTimeout,
+    setOpen,
+    setAccountId,
+    setAnchor,
+  ]);
 
   return (
     <Overlay
diff --git a/app/javascript/mastodon/components/status_list.jsx b/app/javascript/mastodon/components/status_list.jsx
index 3ed20f65eb..fee6675faa 100644
--- a/app/javascript/mastodon/components/status_list.jsx
+++ b/app/javascript/mastodon/components/status_list.jsx
@@ -33,6 +33,7 @@ export default class StatusList extends ImmutablePureComponent {
     withCounters: PropTypes.bool,
     timelineId: PropTypes.string,
     lastId: PropTypes.string,
+    bindToDocument: PropTypes.bool,
   };
 
   static defaultProps = {
diff --git a/app/javascript/mastodon/features/account/components/header.jsx b/app/javascript/mastodon/features/account/components/header.jsx
index b10ef6ef76..1326874e50 100644
--- a/app/javascript/mastodon/features/account/components/header.jsx
+++ b/app/javascript/mastodon/features/account/components/header.jsx
@@ -94,7 +94,7 @@ const messageForFollowButton = relationship => {
     return messages.mutual;
   } else if (!relationship.get('following') && relationship.get('followed_by')) {
     return messages.followBack;
-  } else if (relationship.get('following')) {
+  } else if (relationship.get('following') || relationship.get('requested')) {
     return messages.unfollow;
   } else {
     return messages.follow;
@@ -291,10 +291,8 @@ class Header extends ImmutablePureComponent {
     if (me !== account.get('id')) {
       if (signedIn && !account.get('relationship')) { // Wait until the relationship is loaded
         actionBtn = <Button disabled><LoadingIndicator /></Button>;
-      } else if (account.getIn(['relationship', 'requested'])) {
-        actionBtn = <Button text={intl.formatMessage(messages.cancel_follow_request)} title={intl.formatMessage(messages.requested)} onClick={this.props.onFollow} />;
       } else if (!account.getIn(['relationship', 'blocking'])) {
-        actionBtn = <Button disabled={account.getIn(['relationship', 'blocked_by'])} className={classNames({ 'button--destructive': account.getIn(['relationship', 'following']) })} text={intl.formatMessage(messageForFollowButton(account.get('relationship')))} onClick={signedIn ? this.props.onFollow : this.props.onInteractionModal} />;
+        actionBtn = <Button disabled={account.getIn(['relationship', 'blocked_by'])} className={classNames({ 'button--destructive': (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) })} text={intl.formatMessage(messageForFollowButton(account.get('relationship')))} onClick={signedIn ? this.props.onFollow : this.props.onInteractionModal} />;
       } else if (account.getIn(['relationship', 'blocking'])) {
         actionBtn = <Button text={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.props.onBlock} />;
       }
diff --git a/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx b/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx
index 73fd62841b..d55d8c58e4 100644
--- a/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx
+++ b/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx
@@ -25,7 +25,6 @@ import { makeGetAccount, getAccountHidden } from '../../../selectors';
 import Header from '../components/header';
 
 const messages = defineMessages({
-  cancelFollowRequestConfirm: { id: 'confirmations.cancel_follow_request.confirm', defaultMessage: 'Withdraw request' },
   unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' },
   blockDomainConfirm: { id: 'confirmations.domain_block.confirm', defaultMessage: 'Block entire domain' },
 });
@@ -45,7 +44,7 @@ const makeMapStateToProps = () => {
 const mapDispatchToProps = (dispatch, { intl }) => ({
 
   onFollow (account) {
-    if (account.getIn(['relationship', 'following'])) {
+    if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) {
       dispatch(openModal({
         modalType: 'CONFIRM',
         modalProps: {
@@ -54,15 +53,6 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
           onConfirm: () => dispatch(unfollowAccount(account.get('id'))),
         },
       }));
-    } else if (account.getIn(['relationship', 'requested'])) {
-      dispatch(openModal({
-        modalType: 'CONFIRM',
-        modalProps: {
-          message: <FormattedMessage id='confirmations.cancel_follow_request.message' defaultMessage='Are you sure you want to withdraw your request to follow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
-          confirm: intl.formatMessage(messages.cancelFollowRequestConfirm),
-          onConfirm: () => dispatch(unfollowAccount(account.get('id'))),
-        },
-      }));
     } else {
       dispatch(followAccount(account.get('id')));
     }
diff --git a/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx b/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx
index 3af89f9974..a2b72f7162 100644
--- a/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx
+++ b/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx
@@ -163,7 +163,7 @@ export const Conversation = ({ conversation, scrollKey, onMoveUp, onMoveDown })
   menu.push({ text: intl.formatMessage(messages.delete), action: handleDelete });
 
   const names = accounts.map(a => (
-    <Link to={`/@${a.get('acct')}`} key={a.get('id')} title={a.get('acct')}>
+    <Link to={`/@${a.get('acct')}`} key={a.get('id')} data-hover-card-account={a.get('id')}>
       <bdi>
         <strong
           className='display-name__html'
diff --git a/app/javascript/mastodon/features/explore/components/story.jsx b/app/javascript/mastodon/features/explore/components/story.jsx
index a2cae942d4..125df412a1 100644
--- a/app/javascript/mastodon/features/explore/components/story.jsx
+++ b/app/javascript/mastodon/features/explore/components/story.jsx
@@ -4,6 +4,8 @@ import { useState, useCallback } from 'react';
 import { FormattedMessage } from 'react-intl';
 
 import classNames from 'classnames';
+import { Link } from 'react-router-dom';
+
 
 
 import { Blurhash } from 'mastodon/components/blurhash';
@@ -57,7 +59,7 @@ export const Story = ({
 
         <div className='story__details__shared'>
           {author ? <FormattedMessage id='link_preview.author' className='story__details__shared__author' defaultMessage='By {name}' values={{ name: authorAccount ? <AuthorLink accountId={authorAccount} /> : <strong>{author}</strong> }} /> : <span />}
-          {typeof sharedTimes === 'number' ? <span className='story__details__shared__pill'><ShortNumber value={sharedTimes} renderer={sharesCountRenderer} /></span> : <Skeleton width='10ch' />}
+          {typeof sharedTimes === 'number' ? <Link className='story__details__shared__pill' to={`/links/${encodeURIComponent(url)}`}><ShortNumber value={sharedTimes} renderer={sharesCountRenderer} /></Link> : <Skeleton width='10ch' />}
         </div>
       </div>
 
diff --git a/app/javascript/mastodon/features/link_timeline/index.tsx b/app/javascript/mastodon/features/link_timeline/index.tsx
new file mode 100644
index 0000000000..dd726dac1a
--- /dev/null
+++ b/app/javascript/mastodon/features/link_timeline/index.tsx
@@ -0,0 +1,76 @@
+import { useRef, useEffect, useCallback } from 'react';
+
+import { Helmet } from 'react-helmet';
+import { useParams } from 'react-router-dom';
+
+import ExploreIcon from '@/material-icons/400-24px/explore.svg?react';
+import { expandLinkTimeline } from 'mastodon/actions/timelines';
+import Column from 'mastodon/components/column';
+import { ColumnHeader } from 'mastodon/components/column_header';
+import StatusListContainer from 'mastodon/features/ui/containers/status_list_container';
+import type { Card } from 'mastodon/models/status';
+import { useAppDispatch, useAppSelector } from 'mastodon/store';
+
+export const LinkTimeline: React.FC<{
+  multiColumn: boolean;
+}> = ({ multiColumn }) => {
+  const { url } = useParams<{ url: string }>();
+  const decodedUrl = url ? decodeURIComponent(url) : undefined;
+  const dispatch = useAppDispatch();
+  const columnRef = useRef<Column>(null);
+  const firstStatusId = useAppSelector((state) =>
+    decodedUrl
+      ? // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
+        (state.timelines.getIn([`link:${decodedUrl}`, 'items', 0]) as string)
+      : undefined,
+  );
+  const story = useAppSelector((state) =>
+    firstStatusId
+      ? (state.statuses.getIn([firstStatusId, 'card']) as Card)
+      : undefined,
+  );
+
+  const handleHeaderClick = useCallback(() => {
+    columnRef.current?.scrollTop();
+  }, []);
+
+  const handleLoadMore = useCallback(
+    (maxId: string) => {
+      dispatch(expandLinkTimeline(decodedUrl, { maxId }));
+    },
+    [dispatch, decodedUrl],
+  );
+
+  useEffect(() => {
+    dispatch(expandLinkTimeline(decodedUrl));
+  }, [dispatch, decodedUrl]);
+
+  return (
+    <Column bindToDocument={!multiColumn} ref={columnRef} label={story?.title}>
+      <ColumnHeader
+        icon='explore'
+        iconComponent={ExploreIcon}
+        title={story?.title}
+        onClick={handleHeaderClick}
+        multiColumn={multiColumn}
+        showBackButton
+      />
+
+      <StatusListContainer
+        timelineId={`link:${decodedUrl}`}
+        onLoadMore={handleLoadMore}
+        trackScroll
+        scrollKey={`link_timeline-${decodedUrl}`}
+        bindToDocument={!multiColumn}
+      />
+
+      <Helmet>
+        <title>{story?.title}</title>
+        <meta name='robots' content='noindex' />
+      </Helmet>
+    </Column>
+  );
+};
+
+// eslint-disable-next-line import/no-default-export
+export default LinkTimeline;
diff --git a/app/javascript/mastodon/features/ui/index.jsx b/app/javascript/mastodon/features/ui/index.jsx
index b58e191ed8..d41132f9ca 100644
--- a/app/javascript/mastodon/features/ui/index.jsx
+++ b/app/javascript/mastodon/features/ui/index.jsx
@@ -56,6 +56,7 @@ import {
   FavouritedStatuses,
   BookmarkedStatuses,
   FollowedTags,
+  LinkTimeline,
   ListTimeline,
   Blocks,
   DomainBlocks,
@@ -202,6 +203,7 @@ class SwitchingColumnsArea extends PureComponent {
             <WrappedRoute path='/public/remote' exact component={Firehose} componentParams={{ feedType: 'public:remote' }} content={children} />
             <WrappedRoute path={['/conversations', '/timelines/direct']} component={DirectTimeline} content={children} />
             <WrappedRoute path='/tags/:id' component={HashtagTimeline} content={children} />
+            <WrappedRoute path='/links/:url' component={LinkTimeline} content={children} />
             <WrappedRoute path='/lists/:id' component={ListTimeline} content={children} />
             <WrappedRoute path='/notifications' component={Notifications} content={children} exact />
             <WrappedRoute path='/notifications/requests' component={NotificationRequests} content={children} exact />
diff --git a/app/javascript/mastodon/features/ui/util/async-components.js b/app/javascript/mastodon/features/ui/util/async-components.js
index e1f5bfdaf6..b8a2359d92 100644
--- a/app/javascript/mastodon/features/ui/util/async-components.js
+++ b/app/javascript/mastodon/features/ui/util/async-components.js
@@ -201,3 +201,7 @@ export function NotificationRequests () {
 export function NotificationRequest () {
   return import(/*webpackChunkName: "features/notifications/request" */'../../notifications/request');
 }
+
+export function LinkTimeline () {
+  return import(/*webpackChunkName: "features/link_timeline" */'../../link_timeline');
+}
diff --git a/app/javascript/mastodon/locales/br.json b/app/javascript/mastodon/locales/br.json
index c919d2e9de..a150fb4902 100644
--- a/app/javascript/mastodon/locales/br.json
+++ b/app/javascript/mastodon/locales/br.json
@@ -35,6 +35,7 @@
   "account.follow_back": "Heuliañ d'ho tro",
   "account.followers": "Tud koumanantet",
   "account.followers.empty": "Den na heul an implijer·ez-mañ c'hoazh.",
+  "account.followers_counter": "{count, plural, one {{counter} heulier} two {{counter} heulier} few {{counter} heulier} many {{counter} heulier} other {{counter} heulier}}",
   "account.following": "Koumanantoù",
   "account.follows.empty": "An implijer·ez-mañ na heul den ebet.",
   "account.go_to_profile": "Gwelet ar profil",
@@ -60,6 +61,7 @@
   "account.requested_follow": "Gant {name} eo bet goulennet ho heuliañ",
   "account.share": "Skignañ profil @{name}",
   "account.show_reblogs": "Diskouez skignadennoù @{name}",
+  "account.statuses_counter": "{count, plural, one {{counter} embannadur} two {{counter} embannadur} few {{counter} embannadur} many {{counter} embannadur} other {{counter} embannadur}}",
   "account.unblock": "Diverzañ @{name}",
   "account.unblock_domain": "Diverzañ an domani {domain}",
   "account.unblock_short": "Distankañ",
diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json
index 66aa1fe0a9..e96e283970 100644
--- a/app/javascript/mastodon/locales/cs.json
+++ b/app/javascript/mastodon/locales/cs.json
@@ -20,7 +20,7 @@
   "account.block_short": "Zablokovat",
   "account.blocked": "Blokovaný",
   "account.browse_more_on_origin_server": "Více na původním profilu",
-  "account.cancel_follow_request": "Zrušit žádost o sledování",
+  "account.cancel_follow_request": "Zrušit sledování",
   "account.copy": "Kopírovat odkaz na profil",
   "account.direct": "Soukromě zmínit @{name}",
   "account.disable_notifications": "Přestat mě upozorňovat, když @{name} zveřejní příspěvek",
@@ -35,7 +35,9 @@
   "account.follow_back": "Také sledovat",
   "account.followers": "Sledující",
   "account.followers.empty": "Tohoto uživatele zatím nikdo nesleduje.",
+  "account.followers_counter": "{count, plural, one {{counter} sledující} few {{counter} sledující} many {{counter} sledujících} other {{counter} sledujících}}",
   "account.following": "Sledujete",
+  "account.following_counter": "{count, plural, one {{counter} sledovaný} few {{counter} sledovaní} many {{counter} sledovaných} other {{counter} sledovaných}}",
   "account.follows.empty": "Tento uživatel zatím nikoho nesleduje.",
   "account.go_to_profile": "Přejít na profil",
   "account.hide_reblogs": "Skrýt boosty od @{name}",
@@ -61,6 +63,7 @@
   "account.requested_follow": "{name} tě požádal o sledování",
   "account.share": "Sdílet profil @{name}",
   "account.show_reblogs": "Zobrazit boosty od @{name}",
+  "account.statuses_counter": "{count, plural, one {{counter} příspěvek} few {{counter} příspěvky} many {{counter} příspěvků} other {{counter} příspěvků}}",
   "account.unblock": "Odblokovat @{name}",
   "account.unblock_domain": "Odblokovat doménu {domain}",
   "account.unblock_short": "Odblokovat",
@@ -75,9 +78,9 @@
   "admin.dashboard.retention.average": "Průměr",
   "admin.dashboard.retention.cohort": "Měsíc registrace",
   "admin.dashboard.retention.cohort_size": "Noví uživatelé",
-  "admin.impact_report.instance_accounts": "Profily účtů, které by odstranily",
-  "admin.impact_report.instance_followers": "Sledovatelé, o které by naši uživatelé přišli",
-  "admin.impact_report.instance_follows": "Následovníci jejich uživatelé by ztratili",
+  "admin.impact_report.instance_accounts": "Profily účtů, které by byli odstaněny",
+  "admin.impact_report.instance_followers": "Sledující, o které by naši uživatelé přišli",
+  "admin.impact_report.instance_follows": "Sledující, o které by naši uživatelé přišli",
   "admin.impact_report.title": "Shrnutí dopadu",
   "alert.rate_limited.message": "Zkuste to prosím znovu po {retry_time, time, medium}.",
   "alert.rate_limited.title": "Spojení omezena",
@@ -86,7 +89,7 @@
   "announcement.announcement": "Oznámení",
   "attachments_list.unprocessed": "(nezpracováno)",
   "audio.hide": "Skrýt zvuk",
-  "block_modal.remote_users_caveat": "Požádáme server {domain}, aby respektoval vaše rozhodnutí. Úplné dodržování nastavení však není zaručeno, protože některé servery mohou řešit blokování různě. Veřejné příspěvky mohou být stále viditelné pro nepřihlášené uživatele.",
+  "block_modal.remote_users_caveat": "Požádáme server {domain}, aby respektoval vaše rozhodnutí. Úplné dodržování nastavení však není zaručeno, protože některé servery mohou řešit blokování různě. Veřejné příspěvky mohou stále být viditelné pro nepřihlášené uživatele.",
   "block_modal.show_less": "Zobrazit méně",
   "block_modal.show_more": "Zobrazit více",
   "block_modal.they_cant_mention": "Nemůže vás zmiňovat ani sledovat.",
@@ -411,6 +414,8 @@
   "limited_account_hint.action": "Přesto profil zobrazit",
   "limited_account_hint.title": "Tento profil byl skryt moderátory {domain}.",
   "link_preview.author": "Podle {name}",
+  "link_preview.more_from_author": "Více od {name}",
+  "link_preview.shares": "{count, plural, one {{counter} příspěvek} few {{counter} příspěvky} many {{counter} příspěvků} other {{counter} příspěvků}}",
   "lists.account.add": "Přidat do seznamu",
   "lists.account.remove": "Odebrat ze seznamu",
   "lists.delete": "Smazat seznam",
@@ -691,8 +696,11 @@
   "server_banner.about_active_users": "Lidé používající tento server během posledních 30 dní (měsíční aktivní uživatelé)",
   "server_banner.active_users": "aktivní uživatelé",
   "server_banner.administered_by": "Spravováno:",
+  "server_banner.is_one_of_many": "{domain} je jedním z mnoha Mastodon serverů, které můžete použít k účasti na fediversu.",
   "server_banner.server_stats": "Statistiky serveru:",
   "sign_in_banner.create_account": "Vytvořit účet",
+  "sign_in_banner.follow_anyone": "Sledujte kohokoli napříč fediversem a uvidíte vše v chronologickém pořadí. Bez algoritmů, reklam a clickbaitu.",
+  "sign_in_banner.mastodon_is": "Mastodon je ten nejlepší způsob, jak udržet krok s tím, co se právě děje.",
   "sign_in_banner.sign_in": "Přihlásit se",
   "sign_in_banner.sso_redirect": "Přihlášení nebo Registrace",
   "status.admin_account": "Otevřít moderátorské rozhraní pro @{name}",
diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json
index 4a5b666d3e..86438757a3 100644
--- a/app/javascript/mastodon/locales/de.json
+++ b/app/javascript/mastodon/locales/de.json
@@ -37,7 +37,7 @@
   "account.followers.empty": "Diesem Profil folgt noch niemand.",
   "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Follower}}",
   "account.following": "Folge ich",
-  "account.following_counter": "{count, plural, one {{counter} folge ich} other {{counter} folge ich}}",
+  "account.following_counter": "{count, plural, one {{counter} Folge ich} other {{counter} Folge ich}}",
   "account.follows.empty": "Dieses Profil folgt noch niemandem.",
   "account.go_to_profile": "Profil aufrufen",
   "account.hide_reblogs": "Geteilte Beiträge von @{name} ausblenden",
diff --git a/app/javascript/mastodon/locales/fo.json b/app/javascript/mastodon/locales/fo.json
index e7786f388d..c27ffe0aa7 100644
--- a/app/javascript/mastodon/locales/fo.json
+++ b/app/javascript/mastodon/locales/fo.json
@@ -35,7 +35,9 @@
   "account.follow_back": "Fylg aftur",
   "account.followers": "Fylgjarar",
   "account.followers.empty": "Ongar fylgjarar enn.",
+  "account.followers_counter": "{count, plural, one {{counter} fylgjari} other {{counter} fylgjarar}}",
   "account.following": "Fylgir",
+  "account.following_counter": "{count, plural, one {{counter} fylgir} other {{counter} fylgja}}",
   "account.follows.empty": "Hesin brúkari fylgir ongum enn.",
   "account.go_to_profile": "Far til vanga",
   "account.hide_reblogs": "Fjal lyft frá @{name}",
@@ -61,6 +63,7 @@
   "account.requested_follow": "{name} hevur biðið um at fylgja tær",
   "account.share": "Deil vanga @{name}'s",
   "account.show_reblogs": "Vís lyft frá @{name}",
+  "account.statuses_counter": "{count, plural, one {{counter} postur} other {{counter} postar}}",
   "account.unblock": "Banna ikki @{name}",
   "account.unblock_domain": "Banna ikki økisnavnið {domain}",
   "account.unblock_short": "Banna ikki",
diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json
index 90755666bb..fe3582c1d8 100644
--- a/app/javascript/mastodon/locales/ko.json
+++ b/app/javascript/mastodon/locales/ko.json
@@ -35,7 +35,9 @@
   "account.follow_back": "맞팔로우 하기",
   "account.followers": "팔로워",
   "account.followers.empty": "아직 아무도 이 사용자를 팔로우하고 있지 않습니다.",
+  "account.followers_counter": "{count, plural, other {{counter} 팔로워}}",
   "account.following": "팔로잉",
+  "account.following_counter": "{count, plural, other {{counter} 팔로잉}}",
   "account.follows.empty": "이 사용자는 아직 아무도 팔로우하고 있지 않습니다.",
   "account.go_to_profile": "프로필로 이동",
   "account.hide_reblogs": "@{name}의 부스트를 숨기기",
@@ -61,6 +63,7 @@
   "account.requested_follow": "{name} 님이 팔로우 요청을 보냈습니다",
   "account.share": "@{name}의 프로필 공유",
   "account.show_reblogs": "@{name}의 부스트 보기",
+  "account.statuses_counter": "{count, plural, other {{counter} 게시물}}",
   "account.unblock": "차단 해제",
   "account.unblock_domain": "도메인 {domain} 차단 해제",
   "account.unblock_short": "차단 해제",
diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json
index e1d556ebf0..64abb394bf 100644
--- a/app/javascript/mastodon/locales/th.json
+++ b/app/javascript/mastodon/locales/th.json
@@ -35,7 +35,9 @@
   "account.follow_back": "ติดตามกลับ",
   "account.followers": "ผู้ติดตาม",
   "account.followers.empty": "ยังไม่มีใครติดตามผู้ใช้นี้",
+  "account.followers_counter": "{count, plural, other {{counter} ผู้ติดตาม}}",
   "account.following": "กำลังติดตาม",
+  "account.following_counter": "{count, plural, other {{counter} กำลังติดตาม}}",
   "account.follows.empty": "ผู้ใช้นี้ยังไม่ได้ติดตามใคร",
   "account.go_to_profile": "ไปยังโปรไฟล์",
   "account.hide_reblogs": "ซ่อนการดันจาก @{name}",
@@ -61,6 +63,7 @@
   "account.requested_follow": "{name} ได้ขอติดตามคุณ",
   "account.share": "แชร์โปรไฟล์ของ @{name}",
   "account.show_reblogs": "แสดงการดันจาก @{name}",
+  "account.statuses_counter": "{count, plural, other {{counter} โพสต์}}",
   "account.unblock": "เลิกปิดกั้น @{name}",
   "account.unblock_domain": "เลิกปิดกั้นโดเมน {domain}",
   "account.unblock_short": "เลิกปิดกั้น",
diff --git a/app/javascript/mastodon/locales/vi.json b/app/javascript/mastodon/locales/vi.json
index bbfecf2c8a..70932d10be 100644
--- a/app/javascript/mastodon/locales/vi.json
+++ b/app/javascript/mastodon/locales/vi.json
@@ -35,7 +35,9 @@
   "account.follow_back": "Theo dõi lại",
   "account.followers": "Người theo dõi",
   "account.followers.empty": "Chưa có người theo dõi nào.",
+  "account.followers_counter": "{count, plural, other {{counter} người theo dõi}}",
   "account.following": "Đang theo dõi",
+  "account.following_counter": "{count, plural, other {{counter} đang theo dõi}}",
   "account.follows.empty": "Người này chưa theo dõi ai.",
   "account.go_to_profile": "Xem hồ sơ",
   "account.hide_reblogs": "Ẩn tút @{name} đăng lại",
@@ -61,6 +63,7 @@
   "account.requested_follow": "{name} yêu cầu theo dõi bạn",
   "account.share": "Chia sẻ @{name}",
   "account.show_reblogs": "Hiện tút do @{name} đăng lại",
+  "account.statuses_counter": "{count, plural, other {{counter} tút}}",
   "account.unblock": "Bỏ chặn @{name}",
   "account.unblock_domain": "Bỏ ẩn {domain}",
   "account.unblock_short": "Bỏ chặn",
diff --git a/app/javascript/mastodon/models/status.ts b/app/javascript/mastodon/models/status.ts
index 7907fc34f8..3900df4e38 100644
--- a/app/javascript/mastodon/models/status.ts
+++ b/app/javascript/mastodon/models/status.ts
@@ -1,4 +1,12 @@
+import type { RecordOf } from 'immutable';
+
+import type { ApiPreviewCardJSON } from 'mastodon/api_types/statuses';
+
 export type { StatusVisibility } from 'mastodon/api_types/statuses';
 
 // Temporary until we type it correctly
 export type Status = Immutable.Map<string, unknown>;
+
+type CardShape = Required<ApiPreviewCardJSON>;
+
+export type Card = RecordOf<CardShape>;
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index 61ff2a65ed..ed99ec9773 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -10468,12 +10468,14 @@ noscript {
         overflow: hidden;
         white-space: nowrap;
         text-overflow: ellipsis;
+        text-align: end;
       }
 
       &.verified {
         dd {
           display: flex;
           align-items: center;
+          justify-content: flex-end;
           gap: 4px;
           overflow: hidden;
           white-space: nowrap;
diff --git a/config/locales/cs.yml b/config/locales/cs.yml
index 17c743f1de..f3b8f27d80 100644
--- a/config/locales/cs.yml
+++ b/config/locales/cs.yml
@@ -291,6 +291,7 @@ cs:
         update_custom_emoji_html: Uživatel %{name} aktualizoval emoji %{target}
         update_domain_block_html: "%{name} aktualizoval blokaci domény %{target}"
         update_ip_block_html: "%{name} změnil pravidlo pro IP %{target}"
+        update_report_html: "%{name} aktualizoval hlášení %{target}"
         update_status_html: Uživatel %{name} aktualizoval příspěvek uživatele %{target}
         update_user_role_html: "%{name} změnil %{target} roli"
       deleted_account: smazaný účet
@@ -298,6 +299,7 @@ cs:
       filter_by_action: Filtrovat podle akce
       filter_by_user: Filtrovat podle uživatele
       title: Protokol auditu
+      unavailable_instance: "(doména není k dispozici)"
     announcements:
       destroyed_msg: Oznámení bylo úspěšně odstraněno!
       edit:
@@ -984,6 +986,7 @@ cs:
       delete: Smazat
       edit_preset: Upravit předlohu pro varování
       empty: Zatím jste nedefinovali žádné předlohy varování.
+      title: Předvolby varování
     webhooks:
       add_new: Přidat koncový bod
       delete: Smazat
diff --git a/config/locales/doorkeeper.cs.yml b/config/locales/doorkeeper.cs.yml
index 3323834685..3101779edf 100644
--- a/config/locales/doorkeeper.cs.yml
+++ b/config/locales/doorkeeper.cs.yml
@@ -166,6 +166,7 @@ cs:
       admin:write:reports: provádět moderátorské akce s hlášeními
       crypto: používat end-to-end šifrování
       follow: upravovat vztahy mezi profily
+      profile: číst pouze základní informace o vašem účtu
       push: přijímat vaše push oznámení
       read: vidět všechna data vašeho účtu
       read:accounts: vidět informace o účtech
diff --git a/config/routes.rb b/config/routes.rb
index 25f8a4949e..51e09ca622 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -28,6 +28,7 @@ Rails.application.routes.draw do
     /public/remote
     /conversations
     /lists/(*any)
+    /links/(*any)
     /notifications/(*any)
     /favourites
     /bookmarks
diff --git a/package.json b/package.json
index 9fffa2b9da..c114c3201a 100644
--- a/package.json
+++ b/package.json
@@ -181,8 +181,8 @@
     "eslint-plugin-formatjs": "^4.10.1",
     "eslint-plugin-import": "~2.29.0",
     "eslint-plugin-jsdoc": "^48.0.0",
-    "eslint-plugin-jsx-a11y": "~6.8.0",
-    "eslint-plugin-promise": "~6.2.0",
+    "eslint-plugin-jsx-a11y": "~6.9.0",
+    "eslint-plugin-promise": "~6.4.0",
     "eslint-plugin-react": "^7.33.2",
     "eslint-plugin-react-hooks": "^4.6.0",
     "husky": "^9.0.11",
diff --git a/yarn.lock b/yarn.lock
index 8fd8f583a9..764617e032 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1502,7 +1502,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.22.3, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2":
+"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.22.3, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2":
   version: 7.24.7
   resolution: "@babel/runtime@npm:7.24.7"
   dependencies:
@@ -1558,69 +1558,69 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@csstools/cascade-layer-name-parser@npm:^1.0.11":
-  version: 1.0.11
-  resolution: "@csstools/cascade-layer-name-parser@npm:1.0.11"
+"@csstools/cascade-layer-name-parser@npm:^1.0.12":
+  version: 1.0.12
+  resolution: "@csstools/cascade-layer-name-parser@npm:1.0.12"
   peerDependencies:
-    "@csstools/css-parser-algorithms": ^2.6.3
-    "@csstools/css-tokenizer": ^2.3.1
-  checksum: 10c0/52ac8369877c8072ff5c111f656bd87e9a2a4b9e44e48fe005c26faeb6cffd83bfe2f463f4f385a2ae5cfe1f82bbf95d26ddaabca18b66c6b657c4fe1520fb43
+    "@csstools/css-parser-algorithms": ^2.7.0
+    "@csstools/css-tokenizer": ^2.3.2
+  checksum: 10c0/5f92aefcbb3f4b660cf7b0db54f6a4ba21a32fa1b64ea4f050a6370233152d4f561ecf5c8e98ca231e73c16e0d9f75b20b0a65153e18b14957658c81e0f68213
   languageName: node
   linkType: hard
 
-"@csstools/color-helpers@npm:^4.2.0":
-  version: 4.2.0
-  resolution: "@csstools/color-helpers@npm:4.2.0"
-  checksum: 10c0/3f1feac43c2ef35f38b3b06fe74e0acc130283d7efb6874f6624e45e178c1a7b3c7e39816c7421cddbffc2666430906aa6f0d3dd7c7209db1369c0afd4a29b1b
+"@csstools/color-helpers@npm:^4.2.1":
+  version: 4.2.1
+  resolution: "@csstools/color-helpers@npm:4.2.1"
+  checksum: 10c0/72e11b186ad0f6019a9b4b3752e620fa798c2a40cf47e8cad565dff46e572c9342eb8cf804542d7886344a1e540555d77f20119ace6b2d8a45b6e5ef8a41685c
   languageName: node
   linkType: hard
 
-"@csstools/css-calc@npm:^1.2.2":
-  version: 1.2.2
-  resolution: "@csstools/css-calc@npm:1.2.2"
+"@csstools/css-calc@npm:^1.2.3":
+  version: 1.2.3
+  resolution: "@csstools/css-calc@npm:1.2.3"
   peerDependencies:
-    "@csstools/css-parser-algorithms": ^2.6.3
-    "@csstools/css-tokenizer": ^2.3.1
-  checksum: 10c0/6032b482764a11c1b882d7502928950ab11760044fa7a2c23ecee802002902f6ea8fca045ee2919302af5a5c399e7baa9f68dff001ac6246ac7fef48fb3f6df7
+    "@csstools/css-parser-algorithms": ^2.7.0
+    "@csstools/css-tokenizer": ^2.3.2
+  checksum: 10c0/fb34767ea9638b837167bcecaf945bcc0c5e8f0d811067c4e8c7a57bc8f0955f61107b1ed5e017b95c54acacc8088473e5497a9986bee95b37ec92999e792871
   languageName: node
   linkType: hard
 
-"@csstools/css-color-parser@npm:^2.0.2":
-  version: 2.0.2
-  resolution: "@csstools/css-color-parser@npm:2.0.2"
+"@csstools/css-color-parser@npm:^2.0.3":
+  version: 2.0.3
+  resolution: "@csstools/css-color-parser@npm:2.0.3"
   dependencies:
-    "@csstools/color-helpers": "npm:^4.2.0"
-    "@csstools/css-calc": "npm:^1.2.2"
+    "@csstools/color-helpers": "npm:^4.2.1"
+    "@csstools/css-calc": "npm:^1.2.3"
   peerDependencies:
-    "@csstools/css-parser-algorithms": ^2.6.3
-    "@csstools/css-tokenizer": ^2.3.1
-  checksum: 10c0/c5ae4ad78745e425dce56da9f1ab053fb4f7963399735df3303305b32123bed0b2237689c2e7e99da2c62387e3226c12ea85e70e275c4027c7507e4ac929bffa
+    "@csstools/css-parser-algorithms": ^2.7.0
+    "@csstools/css-tokenizer": ^2.3.2
+  checksum: 10c0/d8860e6b9c65de4f90d4c21e4d66471fd858434cf63af80f812a900371343b753b86a256627e8bd024cb8903a6a0181d2d9c0c65ab5d78cf29d084a761e2adba
   languageName: node
   linkType: hard
 
-"@csstools/css-parser-algorithms@npm:^2.6.3":
-  version: 2.6.3
-  resolution: "@csstools/css-parser-algorithms@npm:2.6.3"
+"@csstools/css-parser-algorithms@npm:^2.6.3, @csstools/css-parser-algorithms@npm:^2.7.0":
+  version: 2.7.0
+  resolution: "@csstools/css-parser-algorithms@npm:2.7.0"
   peerDependencies:
-    "@csstools/css-tokenizer": ^2.3.1
-  checksum: 10c0/6648fda75a1c08096320fb5c04fd13656a0168de13584d2795547fecfb26c2c7d8b3b1fb79ba7aa758714851e98bfbec20d89e28697f999f41f91133eafe4207
+    "@csstools/css-tokenizer": ^2.3.2
+  checksum: 10c0/fb84fefdf37c41d170f81b687bf1ee1847a970e51cc1fe3a320e3eaf225383ae9a3c4eb6208b83357dfe18c5114353d780e0c65f05d86d6435e5a9ad9334c834
   languageName: node
   linkType: hard
 
-"@csstools/css-tokenizer@npm:^2.3.1":
-  version: 2.3.1
-  resolution: "@csstools/css-tokenizer@npm:2.3.1"
-  checksum: 10c0/fed6619fb5108e109d4dd10b0e967035a92793bae8fb84544e1342058b6df4e306d9d075623e2201fe88831b1ada797aea3546a8d12229d2d81cd7a5dfee4444
+"@csstools/css-tokenizer@npm:^2.3.1, @csstools/css-tokenizer@npm:^2.3.2":
+  version: 2.3.2
+  resolution: "@csstools/css-tokenizer@npm:2.3.2"
+  checksum: 10c0/f7d0d8b3e9e2dcdc6547a387253a09dbbacaaffb5c8718bcd7f15dddeefdd441b73fc5f9fad3f03fabef3b37ec4b62be7ff79caab366427fa90eaf54cd8fc452
   languageName: node
   linkType: hard
 
-"@csstools/media-query-list-parser@npm:^2.1.11":
-  version: 2.1.11
-  resolution: "@csstools/media-query-list-parser@npm:2.1.11"
+"@csstools/media-query-list-parser@npm:^2.1.11, @csstools/media-query-list-parser@npm:^2.1.12":
+  version: 2.1.12
+  resolution: "@csstools/media-query-list-parser@npm:2.1.12"
   peerDependencies:
-    "@csstools/css-parser-algorithms": ^2.6.3
-    "@csstools/css-tokenizer": ^2.3.1
-  checksum: 10c0/9bcd99f7d28ae3cdaba73fbbfef571b0393dd4e841f522cc796fe5161744f17e327ba1713dad3c481626fade1357c55890e3d365177abed50e857b69130a9be5
+    "@csstools/css-parser-algorithms": ^2.7.0
+    "@csstools/css-tokenizer": ^2.3.2
+  checksum: 10c0/7395cc710d8f54670c1e7a418a88dcf1ae726316272294ec645f6d79a8e931f5d390ba7ed5d0141d29ad7280cd447b8773143dc7676659413de79228130e1a65
   languageName: node
   linkType: hard
 
@@ -1636,46 +1636,46 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@csstools/postcss-color-function@npm:^3.0.16":
-  version: 3.0.16
-  resolution: "@csstools/postcss-color-function@npm:3.0.16"
+"@csstools/postcss-color-function@npm:^3.0.17":
+  version: 3.0.17
+  resolution: "@csstools/postcss-color-function@npm:3.0.17"
   dependencies:
-    "@csstools/css-color-parser": "npm:^2.0.2"
-    "@csstools/css-parser-algorithms": "npm:^2.6.3"
-    "@csstools/css-tokenizer": "npm:^2.3.1"
+    "@csstools/css-color-parser": "npm:^2.0.3"
+    "@csstools/css-parser-algorithms": "npm:^2.7.0"
+    "@csstools/css-tokenizer": "npm:^2.3.2"
     "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0"
     "@csstools/utilities": "npm:^1.0.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/41756a4601a3f1086290dab6ca92b54e201bd94637b54b439c66a04fd628a14e2a0bd1452ad294d2981e2f4bb306758fa5f44639b1c4332320435050749aa487
+  checksum: 10c0/6d347fc9fe65cb897c275c129103576e551b74a7c47a1a4dc8160da2fad7752bf51e3cfbff339f86b39c723efac33643168d2dfaac4d3624d072875d18a65a4b
   languageName: node
   linkType: hard
 
-"@csstools/postcss-color-mix-function@npm:^2.0.16":
-  version: 2.0.16
-  resolution: "@csstools/postcss-color-mix-function@npm:2.0.16"
+"@csstools/postcss-color-mix-function@npm:^2.0.17":
+  version: 2.0.17
+  resolution: "@csstools/postcss-color-mix-function@npm:2.0.17"
   dependencies:
-    "@csstools/css-color-parser": "npm:^2.0.2"
-    "@csstools/css-parser-algorithms": "npm:^2.6.3"
-    "@csstools/css-tokenizer": "npm:^2.3.1"
+    "@csstools/css-color-parser": "npm:^2.0.3"
+    "@csstools/css-parser-algorithms": "npm:^2.7.0"
+    "@csstools/css-tokenizer": "npm:^2.3.2"
     "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0"
     "@csstools/utilities": "npm:^1.0.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/70cd5b291dd615e20e4475517bf0027c90c433241397a66866f89acedb12cb91f45552a162bdd1000636ec56f7d6a099b65e44fe100fd03228fc65f17cfae285
+  checksum: 10c0/ba9a406ebe4caba6709878ee26debb06780be5cbf4e6ab7e902d79ca6e21ec6a8409b9dc0a5ef36fc4bf54bf2bd8f9642b72da8d7939145f99dc40fedd2be9d2
   languageName: node
   linkType: hard
 
-"@csstools/postcss-exponential-functions@npm:^1.0.7":
-  version: 1.0.7
-  resolution: "@csstools/postcss-exponential-functions@npm:1.0.7"
+"@csstools/postcss-exponential-functions@npm:^1.0.8":
+  version: 1.0.8
+  resolution: "@csstools/postcss-exponential-functions@npm:1.0.8"
   dependencies:
-    "@csstools/css-calc": "npm:^1.2.2"
-    "@csstools/css-parser-algorithms": "npm:^2.6.3"
-    "@csstools/css-tokenizer": "npm:^2.3.1"
+    "@csstools/css-calc": "npm:^1.2.3"
+    "@csstools/css-parser-algorithms": "npm:^2.7.0"
+    "@csstools/css-tokenizer": "npm:^2.3.2"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/2079c81c3437686ef432d88502fa3a13bf8a27b7af105b4c6c2eb8e779f14adc8967a5a3ed03271ab919eeaf999fc4489fe4b37d32a8f61ab3212439517bddcc
+  checksum: 10c0/6b049801fc1275b34f43ffbb915f447a54cbff7bf48ab0705c3ad1ffde055cb876c4dc24e7a9162cd65e219457328e298a673f6176446493db17cf7af6f90dc0
   languageName: node
   linkType: hard
 
@@ -1691,46 +1691,46 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@csstools/postcss-gamut-mapping@npm:^1.0.9":
-  version: 1.0.9
-  resolution: "@csstools/postcss-gamut-mapping@npm:1.0.9"
+"@csstools/postcss-gamut-mapping@npm:^1.0.10":
+  version: 1.0.10
+  resolution: "@csstools/postcss-gamut-mapping@npm:1.0.10"
   dependencies:
-    "@csstools/css-color-parser": "npm:^2.0.2"
-    "@csstools/css-parser-algorithms": "npm:^2.6.3"
-    "@csstools/css-tokenizer": "npm:^2.3.1"
+    "@csstools/css-color-parser": "npm:^2.0.3"
+    "@csstools/css-parser-algorithms": "npm:^2.7.0"
+    "@csstools/css-tokenizer": "npm:^2.3.2"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/412ae1410f3fce240401576441637c2c4e71d1a54153ac9b7a991b3de7519c253d03e10db78b09872eb10b0776d7f960b442779efabc11332b5be6672163c836
+  checksum: 10c0/6c2dab6a84f81904bed89cb584bd9bc6a904b49a4fa315b17be65c7d68baefe592561ee439660d5602b7481bac3be9a93189dc45404764524495400f34c6b6e6
   languageName: node
   linkType: hard
 
-"@csstools/postcss-gradients-interpolation-method@npm:^4.0.17":
-  version: 4.0.17
-  resolution: "@csstools/postcss-gradients-interpolation-method@npm:4.0.17"
+"@csstools/postcss-gradients-interpolation-method@npm:^4.0.18":
+  version: 4.0.18
+  resolution: "@csstools/postcss-gradients-interpolation-method@npm:4.0.18"
   dependencies:
-    "@csstools/css-color-parser": "npm:^2.0.2"
-    "@csstools/css-parser-algorithms": "npm:^2.6.3"
-    "@csstools/css-tokenizer": "npm:^2.3.1"
+    "@csstools/css-color-parser": "npm:^2.0.3"
+    "@csstools/css-parser-algorithms": "npm:^2.7.0"
+    "@csstools/css-tokenizer": "npm:^2.3.2"
     "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0"
     "@csstools/utilities": "npm:^1.0.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/465ac42856ca1a57aa2b9ea41ede31d9e2bcf2fe84345dbc182ae41f463069a0cfd41041b834b5133108c702cd85ecb8636b51b0b88fff8a221628639b59f386
+  checksum: 10c0/23c431068ac205392b4953dbce411e208e79e221ba8030c5e23c0b82e8fd53bc3bc4f2cdc47050f5d91a4ac69cb80f4f1853b213aa8072fa60a6cb6ff0621e04
   languageName: node
   linkType: hard
 
-"@csstools/postcss-hwb-function@npm:^3.0.15":
-  version: 3.0.15
-  resolution: "@csstools/postcss-hwb-function@npm:3.0.15"
+"@csstools/postcss-hwb-function@npm:^3.0.16":
+  version: 3.0.16
+  resolution: "@csstools/postcss-hwb-function@npm:3.0.16"
   dependencies:
-    "@csstools/css-color-parser": "npm:^2.0.2"
-    "@csstools/css-parser-algorithms": "npm:^2.6.3"
-    "@csstools/css-tokenizer": "npm:^2.3.1"
+    "@csstools/css-color-parser": "npm:^2.0.3"
+    "@csstools/css-parser-algorithms": "npm:^2.7.0"
+    "@csstools/css-tokenizer": "npm:^2.3.2"
     "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0"
     "@csstools/utilities": "npm:^1.0.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/fdfaeefbab1008ab1e4a98a2b45cc3db002b2724c404fa0600954b411a68b1fa4028286250bf9898eed10fa80c44e4d6b4e55f1aca073c3dfce8198a0aaedf3f
+  checksum: 10c0/4deca8831a69038aff719a77df92c53578bb28e23cc61dc4ea7b1d912b1b685683a9c6232396c2616948ac2e8488ad1e2009c9c8ed30c493d97ba8ad37b6418d
   languageName: node
   linkType: hard
 
@@ -1768,17 +1768,17 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@csstools/postcss-light-dark-function@npm:^1.0.5":
-  version: 1.0.5
-  resolution: "@csstools/postcss-light-dark-function@npm:1.0.5"
+"@csstools/postcss-light-dark-function@npm:^1.0.6":
+  version: 1.0.6
+  resolution: "@csstools/postcss-light-dark-function@npm:1.0.6"
   dependencies:
-    "@csstools/css-parser-algorithms": "npm:^2.6.3"
-    "@csstools/css-tokenizer": "npm:^2.3.1"
+    "@csstools/css-parser-algorithms": "npm:^2.7.0"
+    "@csstools/css-tokenizer": "npm:^2.3.2"
     "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0"
     "@csstools/utilities": "npm:^1.0.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/4fbeda98372d0da25d3ed87da09903c9a0a5d0b8c13cc9de82a98acce4a8f8367e5ba33bfc25c2534d10f2b1db9d5b4278df4ebab755e27ef2b03a95e0ebe264
+  checksum: 10c0/6b2c64860d789cd3e3ce875c01259333911f6e32a751a7475604de8022c13abcb578e5cb941b51bd3a2022bee883df3f6b64800c6e3559b06da283d968aeb615
   languageName: node
   linkType: hard
 
@@ -1820,42 +1820,42 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@csstools/postcss-logical-viewport-units@npm:^2.0.9":
-  version: 2.0.9
-  resolution: "@csstools/postcss-logical-viewport-units@npm:2.0.9"
+"@csstools/postcss-logical-viewport-units@npm:^2.0.10":
+  version: 2.0.10
+  resolution: "@csstools/postcss-logical-viewport-units@npm:2.0.10"
   dependencies:
-    "@csstools/css-tokenizer": "npm:^2.3.1"
+    "@csstools/css-tokenizer": "npm:^2.3.2"
     "@csstools/utilities": "npm:^1.0.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/25b01e36b08c571806d09046be63582dbebf97a4612df59be405fa8a92e6eebcd4e768ad7fbe53b0b8739d6ab04d56957964fb04d6a3ea129fc5f72e6d0adf95
+  checksum: 10c0/fe142b11e0e8ccab4667cc5db90b45e67b7d11eaf5c038e91d867e1b18a315ef0859114185aeb48fdc1ce05986be8b644d6157fe9e19da7281f7023c99eb8877
   languageName: node
   linkType: hard
 
-"@csstools/postcss-media-minmax@npm:^1.1.6":
-  version: 1.1.6
-  resolution: "@csstools/postcss-media-minmax@npm:1.1.6"
+"@csstools/postcss-media-minmax@npm:^1.1.7":
+  version: 1.1.7
+  resolution: "@csstools/postcss-media-minmax@npm:1.1.7"
   dependencies:
-    "@csstools/css-calc": "npm:^1.2.2"
-    "@csstools/css-parser-algorithms": "npm:^2.6.3"
-    "@csstools/css-tokenizer": "npm:^2.3.1"
-    "@csstools/media-query-list-parser": "npm:^2.1.11"
+    "@csstools/css-calc": "npm:^1.2.3"
+    "@csstools/css-parser-algorithms": "npm:^2.7.0"
+    "@csstools/css-tokenizer": "npm:^2.3.2"
+    "@csstools/media-query-list-parser": "npm:^2.1.12"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/2cbfb3728a232c655d82f63d5ac7da36876d14e5fee5d62a0738efed40c58f20ef11f600395ade24d5063d750e8e093251dd93cc361f782b5a6c0e0f80288f51
+  checksum: 10c0/a02943a17b540cbd909b55bbb1f8c9331badc51b613279bbdb7127c9921a5d0675bb41675a3b4d0f15e9586120e5a96d9b9786b63b2c594fbb3a238e860c6ad8
   languageName: node
   linkType: hard
 
-"@csstools/postcss-media-queries-aspect-ratio-number-values@npm:^2.0.9":
-  version: 2.0.9
-  resolution: "@csstools/postcss-media-queries-aspect-ratio-number-values@npm:2.0.9"
+"@csstools/postcss-media-queries-aspect-ratio-number-values@npm:^2.0.10":
+  version: 2.0.10
+  resolution: "@csstools/postcss-media-queries-aspect-ratio-number-values@npm:2.0.10"
   dependencies:
-    "@csstools/css-parser-algorithms": "npm:^2.6.3"
-    "@csstools/css-tokenizer": "npm:^2.3.1"
-    "@csstools/media-query-list-parser": "npm:^2.1.11"
+    "@csstools/css-parser-algorithms": "npm:^2.7.0"
+    "@csstools/css-tokenizer": "npm:^2.3.2"
+    "@csstools/media-query-list-parser": "npm:^2.1.12"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/d431d2900a7177c938d9dc2d5bdf3c1930758adc214cc72f94b34e6bbd02fd917c200dc81482db515519c97d4f1e766ba3200f3ec9b55081887f2f8111f68e20
+  checksum: 10c0/d7879e72df98d9fe2e5d85a64837e7a73c2df1aea8659d65516f0acb070317edd353531882f0bdfd81510703d1da30d6da861052a0bda85fde1f9eab94b1e467
   languageName: node
   linkType: hard
 
@@ -1882,18 +1882,18 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@csstools/postcss-oklab-function@npm:^3.0.16":
-  version: 3.0.16
-  resolution: "@csstools/postcss-oklab-function@npm:3.0.16"
+"@csstools/postcss-oklab-function@npm:^3.0.17":
+  version: 3.0.17
+  resolution: "@csstools/postcss-oklab-function@npm:3.0.17"
   dependencies:
-    "@csstools/css-color-parser": "npm:^2.0.2"
-    "@csstools/css-parser-algorithms": "npm:^2.6.3"
-    "@csstools/css-tokenizer": "npm:^2.3.1"
+    "@csstools/css-color-parser": "npm:^2.0.3"
+    "@csstools/css-parser-algorithms": "npm:^2.7.0"
+    "@csstools/css-tokenizer": "npm:^2.3.2"
     "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0"
     "@csstools/utilities": "npm:^1.0.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/9c67ee5f51116df16ab6baffa1b3c6c7aa93d53b836f421125ae8824075bd3cfaa1a93594466de0ac935c89c4fc8171e80974e1a15bafa23ea864e4cf1f1c1f2
+  checksum: 10c0/ff27a4b6fd8490439aa0f3c91ffa2a42a8cf539d7306d9329cef7ca59f28317cee40253f402d19a18c196471fd39a05842d2974d92f1b131dc748074d91ac4ee
   languageName: node
   linkType: hard
 
@@ -1908,18 +1908,18 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@csstools/postcss-relative-color-syntax@npm:^2.0.16":
-  version: 2.0.16
-  resolution: "@csstools/postcss-relative-color-syntax@npm:2.0.16"
+"@csstools/postcss-relative-color-syntax@npm:^2.0.17":
+  version: 2.0.17
+  resolution: "@csstools/postcss-relative-color-syntax@npm:2.0.17"
   dependencies:
-    "@csstools/css-color-parser": "npm:^2.0.2"
-    "@csstools/css-parser-algorithms": "npm:^2.6.3"
-    "@csstools/css-tokenizer": "npm:^2.3.1"
+    "@csstools/css-color-parser": "npm:^2.0.3"
+    "@csstools/css-parser-algorithms": "npm:^2.7.0"
+    "@csstools/css-tokenizer": "npm:^2.3.2"
     "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0"
     "@csstools/utilities": "npm:^1.0.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/cdc965706212dcbc03394f55c79a0ad043d1e0174059c4d0d90e4267fe8e6fd9eef7cfed4f5bbc1f8e89c225c1c042ae792e115bba198eb2daae763d65f44679
+  checksum: 10c0/46226351b3825323e3496dcee44ff354cd3ccc9241d837659e1311f428f0b4dc878d9bb762cbb8f63243b7af346728ab7a46c311f9dc38bb609147523c698eab
   languageName: node
   linkType: hard
 
@@ -1934,41 +1934,41 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@csstools/postcss-stepped-value-functions@npm:^3.0.8":
-  version: 3.0.8
-  resolution: "@csstools/postcss-stepped-value-functions@npm:3.0.8"
+"@csstools/postcss-stepped-value-functions@npm:^3.0.9":
+  version: 3.0.9
+  resolution: "@csstools/postcss-stepped-value-functions@npm:3.0.9"
   dependencies:
-    "@csstools/css-calc": "npm:^1.2.2"
-    "@csstools/css-parser-algorithms": "npm:^2.6.3"
-    "@csstools/css-tokenizer": "npm:^2.3.1"
+    "@csstools/css-calc": "npm:^1.2.3"
+    "@csstools/css-parser-algorithms": "npm:^2.7.0"
+    "@csstools/css-tokenizer": "npm:^2.3.2"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/2be66aa769808245137be8ff14308aa17c3a0d75433f6fd6789114966a78c365dbf173d087e7ff5bc80118c75be2ff740baab83ed39fc0671980f6217779956b
+  checksum: 10c0/bafe80947abc8613903f1f3f1939ece9780696774f15960aef229733e40e483dc2830145426d49c4f6d0b1dabb35f812c8a2dda0d0dcddc930321e36b5c6ca0b
   languageName: node
   linkType: hard
 
-"@csstools/postcss-text-decoration-shorthand@npm:^3.0.6":
-  version: 3.0.6
-  resolution: "@csstools/postcss-text-decoration-shorthand@npm:3.0.6"
+"@csstools/postcss-text-decoration-shorthand@npm:^3.0.7":
+  version: 3.0.7
+  resolution: "@csstools/postcss-text-decoration-shorthand@npm:3.0.7"
   dependencies:
-    "@csstools/color-helpers": "npm:^4.2.0"
+    "@csstools/color-helpers": "npm:^4.2.1"
     postcss-value-parser: "npm:^4.2.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/5abdc4fad1c3f15e9d47c7af3995dec9cdf4e6f87c5857eb2e149764779b8389f4f4b21d11e6f2509c57c554a0dc5c11f68f212acd04bbc47defa15911ac3eb9
+  checksum: 10c0/072b9893ca2409aa16e53e84747d7b7e13071ce19738a0800a139bf71b535e439958d9093df2b85f83eee2e0c44bc22a14bf3a39b5a7508bca9e747a12273d02
   languageName: node
   linkType: hard
 
-"@csstools/postcss-trigonometric-functions@npm:^3.0.8":
-  version: 3.0.8
-  resolution: "@csstools/postcss-trigonometric-functions@npm:3.0.8"
+"@csstools/postcss-trigonometric-functions@npm:^3.0.9":
+  version: 3.0.9
+  resolution: "@csstools/postcss-trigonometric-functions@npm:3.0.9"
   dependencies:
-    "@csstools/css-calc": "npm:^1.2.2"
-    "@csstools/css-parser-algorithms": "npm:^2.6.3"
-    "@csstools/css-tokenizer": "npm:^2.3.1"
+    "@csstools/css-calc": "npm:^1.2.3"
+    "@csstools/css-parser-algorithms": "npm:^2.7.0"
+    "@csstools/css-tokenizer": "npm:^2.3.2"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/aeed8d1026f4a5cb7afafbadd739af84291d5bfcbcdef2f79b77174f003d0cd0c7f9deb3fe0b9377efab37ce9bb17a2499efd4af8211f5ff9eb01b878b0b62b3
+  checksum: 10c0/7a439d31a63d35986dab634d9e415f7ce7c32a2d3d382052b5b730a259a12e44c5f1b14e318d79086253e3d5d4f7d942d0e7317d92eb3421dd08824eebec45fb
   languageName: node
   linkType: hard
 
@@ -2831,8 +2831,8 @@ __metadata:
     eslint-plugin-formatjs: "npm:^4.10.1"
     eslint-plugin-import: "npm:~2.29.0"
     eslint-plugin-jsdoc: "npm:^48.0.0"
-    eslint-plugin-jsx-a11y: "npm:~6.8.0"
-    eslint-plugin-promise: "npm:~6.2.0"
+    eslint-plugin-jsx-a11y: "npm:~6.9.0"
+    eslint-plugin-promise: "npm:~6.4.0"
     eslint-plugin-react: "npm:^7.33.2"
     eslint-plugin-react-hooks: "npm:^4.6.0"
     exif-js: "npm:^2.3.0"
@@ -3039,6 +3039,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@pkgr/core@npm:^0.1.0":
+  version: 0.1.1
+  resolution: "@pkgr/core@npm:0.1.1"
+  checksum: 10c0/3f7536bc7f57320ab2cf96f8973664bef624710c403357429fbf680a5c3b4843c1dbd389bb43daa6b1f6f1f007bb082f5abcb76bb2b5dc9f421647743b71d3d8
+  languageName: node
+  linkType: hard
+
 "@polka/url@npm:^1.0.0-next.20":
   version: 1.0.0-next.21
   resolution: "@polka/url@npm:1.0.0-next.21"
@@ -3061,8 +3068,8 @@ __metadata:
   linkType: hard
 
 "@reduxjs/toolkit@npm:^2.0.1":
-  version: 2.2.5
-  resolution: "@reduxjs/toolkit@npm:2.2.5"
+  version: 2.2.6
+  resolution: "@reduxjs/toolkit@npm:2.2.6"
   dependencies:
     immer: "npm:^10.0.3"
     redux: "npm:^5.0.1"
@@ -3076,7 +3083,7 @@ __metadata:
       optional: true
     react-redux:
       optional: true
-  checksum: 10c0/be0593bf26852482fb8716b9248531466c6e8782a3114b823ae680fce90267d8c5512a3231cfecc30b17eff81a4604112772b49ad7ca6a3366ddd4f2a838e53c
+  checksum: 10c0/60af753e6d02c8acd3c5bc843c846d60b19821d93ff9f4415fa7011ebf17a85301ed42132fabc1aaee8523d8f61418b5ba164a11c31ab29937e485842d3744a0
   languageName: node
   linkType: hard
 
@@ -3628,11 +3635,11 @@ __metadata:
   linkType: hard
 
 "@types/http-link-header@npm:^1.0.3":
-  version: 1.0.6
-  resolution: "@types/http-link-header@npm:1.0.6"
+  version: 1.0.7
+  resolution: "@types/http-link-header@npm:1.0.7"
   dependencies:
     "@types/node": "npm:*"
-  checksum: 10c0/63f3f7ab5ff6312280727ba8cf836abf5d1b76f9dc5eefc8cd4389db29d57a72fb0e028db99735ada5ccfd3c2cc6607e096b5cc142fc53c2bb5688b6295f61af
+  checksum: 10c0/ffde4514a286ee62fab86bd5164958f5c9ad9d8012eaeb4f5536efa6157e6cf9f93121d5a39bf160c3712554d945300a223a9f8b1f3fb08cc70b73f539767338
   languageName: node
   linkType: hard
 
@@ -3718,9 +3725,9 @@ __metadata:
   linkType: hard
 
 "@types/lodash@npm:^4.14.195":
-  version: 4.17.5
-  resolution: "@types/lodash@npm:4.17.5"
-  checksum: 10c0/55924803ed853e72261512bd3eaf2c5b16558c3817feb0a3125ef757afe46e54b86f33d1960e40b7606c0ddab91a96f47966bf5e6006b7abfd8994c13b04b19b
+  version: 4.17.6
+  resolution: "@types/lodash@npm:4.17.6"
+  checksum: 10c0/3b197ac47af9443fee8c4719c5ffde527d7febc018b827d44a6bc2523c728c7adfdd25196fdcfe3eed827993e0c41a917d0da6e78938b18b2be94164789f1117
   languageName: node
   linkType: hard
 
@@ -4123,14 +4130,14 @@ __metadata:
   linkType: hard
 
 "@typescript-eslint/eslint-plugin@npm:^7.0.0":
-  version: 7.11.0
-  resolution: "@typescript-eslint/eslint-plugin@npm:7.11.0"
+  version: 7.14.1
+  resolution: "@typescript-eslint/eslint-plugin@npm:7.14.1"
   dependencies:
     "@eslint-community/regexpp": "npm:^4.10.0"
-    "@typescript-eslint/scope-manager": "npm:7.11.0"
-    "@typescript-eslint/type-utils": "npm:7.11.0"
-    "@typescript-eslint/utils": "npm:7.11.0"
-    "@typescript-eslint/visitor-keys": "npm:7.11.0"
+    "@typescript-eslint/scope-manager": "npm:7.14.1"
+    "@typescript-eslint/type-utils": "npm:7.14.1"
+    "@typescript-eslint/utils": "npm:7.14.1"
+    "@typescript-eslint/visitor-keys": "npm:7.14.1"
     graphemer: "npm:^1.4.0"
     ignore: "npm:^5.3.1"
     natural-compare: "npm:^1.4.0"
@@ -4141,25 +4148,25 @@ __metadata:
   peerDependenciesMeta:
     typescript:
       optional: true
-  checksum: 10c0/50fedf832e4de9546569106eab1d10716204ceebc5cc7d62299112c881212270d0f7857e3d6452c07db031d40b58cf27c4d1b1a36043e8e700fc3496e377b54a
+  checksum: 10c0/7c2b9b98a38d78326b0ff7348fe001203eda10817ca7834a7a01f492ae7c2508469bbafaa933208d6459f8ff6685277685983cf6f6843e556a6ab2aa5c05080c
   languageName: node
   linkType: hard
 
 "@typescript-eslint/parser@npm:^7.0.0":
-  version: 7.11.0
-  resolution: "@typescript-eslint/parser@npm:7.11.0"
+  version: 7.14.1
+  resolution: "@typescript-eslint/parser@npm:7.14.1"
   dependencies:
-    "@typescript-eslint/scope-manager": "npm:7.11.0"
-    "@typescript-eslint/types": "npm:7.11.0"
-    "@typescript-eslint/typescript-estree": "npm:7.11.0"
-    "@typescript-eslint/visitor-keys": "npm:7.11.0"
+    "@typescript-eslint/scope-manager": "npm:7.14.1"
+    "@typescript-eslint/types": "npm:7.14.1"
+    "@typescript-eslint/typescript-estree": "npm:7.14.1"
+    "@typescript-eslint/visitor-keys": "npm:7.14.1"
     debug: "npm:^4.3.4"
   peerDependencies:
     eslint: ^8.56.0
   peerDependenciesMeta:
     typescript:
       optional: true
-  checksum: 10c0/f5d1343fae90ccd91aea8adf194e22ed3eb4b2ea79d03d8a9ca6e7b669a6db306e93138ec64f7020c5b3128619d50304dea1f06043eaff6b015071822cad4972
+  checksum: 10c0/db3169d4852685cfb27db741c557f58a3e52104bfacc7621beb7c94ec36ac2a08d4e410ac86745db52f482fbfc87e99fa0a26c1d7a10d37a215cce85e1661f0e
   languageName: node
   linkType: hard
 
@@ -4173,22 +4180,22 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@typescript-eslint/scope-manager@npm:7.11.0":
-  version: 7.11.0
-  resolution: "@typescript-eslint/scope-manager@npm:7.11.0"
+"@typescript-eslint/scope-manager@npm:7.14.1":
+  version: 7.14.1
+  resolution: "@typescript-eslint/scope-manager@npm:7.14.1"
   dependencies:
-    "@typescript-eslint/types": "npm:7.11.0"
-    "@typescript-eslint/visitor-keys": "npm:7.11.0"
-  checksum: 10c0/35f9d88f38f2366017b15c9ee752f2605afa8009fa1eaf81c8b2b71fc22ddd2a33fff794a02015c8991a5fa99f315c3d6d76a5957d3fad1ccbb4cd46735c98b5
+    "@typescript-eslint/types": "npm:7.14.1"
+    "@typescript-eslint/visitor-keys": "npm:7.14.1"
+  checksum: 10c0/f8c05a0d6f8de4cc19b90a4da308817c66e53f36f7ec48f6cc23e93c7399bc418643d8135933aaf5fc013199cbef0e1ea4223f5147db5ca401b239eaf087011e
   languageName: node
   linkType: hard
 
-"@typescript-eslint/type-utils@npm:7.11.0":
-  version: 7.11.0
-  resolution: "@typescript-eslint/type-utils@npm:7.11.0"
+"@typescript-eslint/type-utils@npm:7.14.1":
+  version: 7.14.1
+  resolution: "@typescript-eslint/type-utils@npm:7.14.1"
   dependencies:
-    "@typescript-eslint/typescript-estree": "npm:7.11.0"
-    "@typescript-eslint/utils": "npm:7.11.0"
+    "@typescript-eslint/typescript-estree": "npm:7.14.1"
+    "@typescript-eslint/utils": "npm:7.14.1"
     debug: "npm:^4.3.4"
     ts-api-utils: "npm:^1.3.0"
   peerDependencies:
@@ -4196,7 +4203,7 @@ __metadata:
   peerDependenciesMeta:
     typescript:
       optional: true
-  checksum: 10c0/637395cb0f4c424c610e751906a31dcfedcdbd8c479012da6e81f9be6b930f32317bfe170ccb758d93a411b2bd9c4e7e5d18892094466099c6f9c3dceda81a72
+  checksum: 10c0/bd1c4a8db6273e24156fb10da2cbeb52b4eb03f819da193d4b6bd5a95db3b5524c6fe00d088308d8855b9ae60a3b82afa3a06e89982a09a8573561da960758fd
   languageName: node
   linkType: hard
 
@@ -4207,10 +4214,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@typescript-eslint/types@npm:7.11.0, @typescript-eslint/types@npm:^7.2.0":
-  version: 7.11.0
-  resolution: "@typescript-eslint/types@npm:7.11.0"
-  checksum: 10c0/c5d6c517124017eb44aa180c8ea1fad26ec8e47502f92fd12245ba3141560e69d7f7e35b8aa160ddd5df63a2952af407e2f62cc58b663c86e1f778ffb5b01789
+"@typescript-eslint/types@npm:7.14.1, @typescript-eslint/types@npm:^7.2.0":
+  version: 7.14.1
+  resolution: "@typescript-eslint/types@npm:7.14.1"
+  checksum: 10c0/5b7bda83c47a9b386482e63447c6b0ed7bd4e82eb43f11a180c6e2f3d2e7a2828f57bcbed82196ad761c49e363cccf4c81a89f1fc976e9f5f0a79dcc928fa2d2
   languageName: node
   linkType: hard
 
@@ -4233,12 +4240,12 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@typescript-eslint/typescript-estree@npm:7.11.0":
-  version: 7.11.0
-  resolution: "@typescript-eslint/typescript-estree@npm:7.11.0"
+"@typescript-eslint/typescript-estree@npm:7.14.1":
+  version: 7.14.1
+  resolution: "@typescript-eslint/typescript-estree@npm:7.14.1"
   dependencies:
-    "@typescript-eslint/types": "npm:7.11.0"
-    "@typescript-eslint/visitor-keys": "npm:7.11.0"
+    "@typescript-eslint/types": "npm:7.14.1"
+    "@typescript-eslint/visitor-keys": "npm:7.14.1"
     debug: "npm:^4.3.4"
     globby: "npm:^11.1.0"
     is-glob: "npm:^4.0.3"
@@ -4248,21 +4255,21 @@ __metadata:
   peerDependenciesMeta:
     typescript:
       optional: true
-  checksum: 10c0/a4eda43f352d20edebae0c1c221c4fd9de0673a94988cf1ae3f5e4917ef9cdb9ead8d3673ea8dd6e80d9cf3523a47c295be1326a3fae017b277233f4c4b4026b
+  checksum: 10c0/a8da9bcc4de3334a225424946abd99374de05c42098455419224bc0f46bb1b66115f8bd6ae268461294b90943ed4a407bcd255c0fa60eb76ba4cdc5fc7c20855
   languageName: node
   linkType: hard
 
-"@typescript-eslint/utils@npm:7.11.0":
-  version: 7.11.0
-  resolution: "@typescript-eslint/utils@npm:7.11.0"
+"@typescript-eslint/utils@npm:7.14.1":
+  version: 7.14.1
+  resolution: "@typescript-eslint/utils@npm:7.14.1"
   dependencies:
     "@eslint-community/eslint-utils": "npm:^4.4.0"
-    "@typescript-eslint/scope-manager": "npm:7.11.0"
-    "@typescript-eslint/types": "npm:7.11.0"
-    "@typescript-eslint/typescript-estree": "npm:7.11.0"
+    "@typescript-eslint/scope-manager": "npm:7.14.1"
+    "@typescript-eslint/types": "npm:7.14.1"
+    "@typescript-eslint/typescript-estree": "npm:7.14.1"
   peerDependencies:
     eslint: ^8.56.0
-  checksum: 10c0/539a7ff8b825ad810fc59a80269094748df1a397a42cdbb212c493fc2486711c7d8fd6d75d4cd8a067822b8e6a11f42c50441977d51c183eec47992506d1cdf8
+  checksum: 10c0/c7f635a3c2c6c085e1d51a52088e55cad9d7e1257b1f60378e5eeb6eb0871db027d42747e9ef60a2f557cf9dd68b2ce014d488d795db8f771506290b164b0e5a
   languageName: node
   linkType: hard
 
@@ -4293,13 +4300,13 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@typescript-eslint/visitor-keys@npm:7.11.0":
-  version: 7.11.0
-  resolution: "@typescript-eslint/visitor-keys@npm:7.11.0"
+"@typescript-eslint/visitor-keys@npm:7.14.1":
+  version: 7.14.1
+  resolution: "@typescript-eslint/visitor-keys@npm:7.14.1"
   dependencies:
-    "@typescript-eslint/types": "npm:7.11.0"
+    "@typescript-eslint/types": "npm:7.14.1"
     eslint-visitor-keys: "npm:^3.4.3"
-  checksum: 10c0/664e558d9645896484b7ffc9381837f0d52443bf8d121a5586d02d42ca4d17dc35faf526768c4b1beb52c57c43fae555898eb087651eb1c7a3d60f1085effea1
+  checksum: 10c0/39ac489990fcfdcee442f27658431a0eb44ccf694f701a45df2a108c47cea9582e0955bff0d449047549149385f72895a5d7e6c1622ece1fe32594b7cecb85f3
   languageName: node
   linkType: hard
 
@@ -4789,7 +4796,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"aria-query@npm:5.3.0, aria-query@npm:^5.0.0, aria-query@npm:^5.3.0":
+"aria-query@npm:5.3.0, aria-query@npm:^5.0.0":
   version: 5.3.0
   resolution: "aria-query@npm:5.3.0"
   dependencies:
@@ -4798,6 +4805,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"aria-query@npm:~5.1.3":
+  version: 5.1.3
+  resolution: "aria-query@npm:5.1.3"
+  dependencies:
+    deep-equal: "npm:^2.0.5"
+  checksum: 10c0/edcbc8044c4663d6f88f785e983e6784f98cb62b4ba1e9dd8d61b725d0203e4cfca38d676aee984c31f354103461102a3d583aa4fbe4fd0a89b679744f4e5faf
+  languageName: node
+  linkType: hard
+
 "arr-diff@npm:^4.0.0":
   version: 4.0.0
   resolution: "arr-diff@npm:4.0.0"
@@ -4819,7 +4835,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"array-buffer-byte-length@npm:^1.0.1":
+"array-buffer-byte-length@npm:^1.0.0, array-buffer-byte-length@npm:^1.0.1":
   version: 1.0.1
   resolution: "array-buffer-byte-length@npm:1.0.1"
   dependencies:
@@ -4963,16 +4979,16 @@ __metadata:
   languageName: node
   linkType: hard
 
-"array.prototype.tosorted@npm:^1.1.3":
-  version: 1.1.3
-  resolution: "array.prototype.tosorted@npm:1.1.3"
+"array.prototype.tosorted@npm:^1.1.4":
+  version: 1.1.4
+  resolution: "array.prototype.tosorted@npm:1.1.4"
   dependencies:
-    call-bind: "npm:^1.0.5"
+    call-bind: "npm:^1.0.7"
     define-properties: "npm:^1.2.1"
-    es-abstract: "npm:^1.22.3"
-    es-errors: "npm:^1.1.0"
+    es-abstract: "npm:^1.23.3"
+    es-errors: "npm:^1.3.0"
     es-shim-unscopables: "npm:^1.0.2"
-  checksum: 10c0/a27e1ca51168ecacf6042901f5ef021e43c8fa04b6c6b6f2a30bac3645cd2b519cecbe0bc45db1b85b843f64dc3207f0268f700b4b9fbdec076d12d432cf0865
+  checksum: 10c0/eb3c4c4fc0381b0bf6dba2ea4d48d367c2827a0d4236a5718d97caaccc6b78f11f4cadf090736e86301d295a6aa4967ed45568f92ced51be8cbbacd9ca410943
   languageName: node
   linkType: hard
 
@@ -5145,10 +5161,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"axe-core@npm:=4.7.0":
-  version: 4.7.0
-  resolution: "axe-core@npm:4.7.0"
-  checksum: 10c0/89ac5712b5932ac7d23398b4cb5ba081c394a086e343acc68ba49c83472706e18e0799804e8388c779dcdacc465377deb29f2714241d3fbb389cf3a6b275c9ba
+"axe-core@npm:^4.9.1":
+  version: 4.9.1
+  resolution: "axe-core@npm:4.9.1"
+  checksum: 10c0/ac9e5a0c6fa115a43ebffc32a1d2189e1ca6431b5a78e88cdcf94a72a25c5964185682edd94fe6bdb1cb4266c0d06301b022866e0e50dcdf6e3cefe556470110
   languageName: node
   linkType: hard
 
@@ -5163,12 +5179,12 @@ __metadata:
   languageName: node
   linkType: hard
 
-"axobject-query@npm:^3.2.1":
-  version: 3.2.1
-  resolution: "axobject-query@npm:3.2.1"
+"axobject-query@npm:~3.1.1":
+  version: 3.1.1
+  resolution: "axobject-query@npm:3.1.1"
   dependencies:
-    dequal: "npm:^2.0.3"
-  checksum: 10c0/f7debc2012e456139b57d888c223f6d3cb4b61eb104164a85e3d346273dd6ef0bc9a04b6660ca9407704a14a8e05fa6b6eb9d55f44f348c7210de7ffb350c3a7
+    deep-equal: "npm:^2.0.5"
+  checksum: 10c0/fff3175a22fd1f41fceb7ae0cd25f6594a0d7fba28c2335dd904538b80eb4e1040432564a3c643025cd2bb748f68d35aaabffb780b794da97ecfc748810b25ad
   languageName: node
   linkType: hard
 
@@ -5656,7 +5672,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"browserslist@npm:^4.0.0, browserslist@npm:^4.22.2, browserslist@npm:^4.22.3, browserslist@npm:^4.23.0, browserslist@npm:^4.23.1":
+"browserslist@npm:^4.0.0, browserslist@npm:^4.22.2, browserslist@npm:^4.23.0, browserslist@npm:^4.23.1":
   version: 4.23.1
   resolution: "browserslist@npm:4.23.1"
   dependencies:
@@ -7006,6 +7022,32 @@ __metadata:
   languageName: node
   linkType: hard
 
+"deep-equal@npm:^2.0.5":
+  version: 2.2.3
+  resolution: "deep-equal@npm:2.2.3"
+  dependencies:
+    array-buffer-byte-length: "npm:^1.0.0"
+    call-bind: "npm:^1.0.5"
+    es-get-iterator: "npm:^1.1.3"
+    get-intrinsic: "npm:^1.2.2"
+    is-arguments: "npm:^1.1.1"
+    is-array-buffer: "npm:^3.0.2"
+    is-date-object: "npm:^1.0.5"
+    is-regex: "npm:^1.1.4"
+    is-shared-array-buffer: "npm:^1.0.2"
+    isarray: "npm:^2.0.5"
+    object-is: "npm:^1.1.5"
+    object-keys: "npm:^1.1.1"
+    object.assign: "npm:^4.1.4"
+    regexp.prototype.flags: "npm:^1.5.1"
+    side-channel: "npm:^1.0.4"
+    which-boxed-primitive: "npm:^1.0.2"
+    which-collection: "npm:^1.0.1"
+    which-typed-array: "npm:^1.1.13"
+  checksum: 10c0/a48244f90fa989f63ff5ef0cc6de1e4916b48ea0220a9c89a378561960814794a5800c600254482a2c8fd2e49d6c2e196131dc983976adb024c94a42dfe4949f
+  languageName: node
+  linkType: hard
+
 "deep-is@npm:^0.1.3":
   version: 0.1.4
   resolution: "deep-is@npm:0.1.4"
@@ -7588,7 +7630,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"es-abstract@npm:^1.17.2, es-abstract@npm:^1.20.4, es-abstract@npm:^1.21.2, es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3":
+"es-abstract@npm:^1.17.2, es-abstract@npm:^1.17.5, es-abstract@npm:^1.20.4, es-abstract@npm:^1.21.2, es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3":
   version: 1.23.3
   resolution: "es-abstract@npm:1.23.3"
   dependencies:
@@ -7658,14 +7700,31 @@ __metadata:
   languageName: node
   linkType: hard
 
-"es-errors@npm:^1.1.0, es-errors@npm:^1.2.1, es-errors@npm:^1.3.0":
+"es-errors@npm:^1.2.1, es-errors@npm:^1.3.0":
   version: 1.3.0
   resolution: "es-errors@npm:1.3.0"
   checksum: 10c0/0a61325670072f98d8ae3b914edab3559b6caa980f08054a3b872052640d91da01d38df55df797fcc916389d77fc92b8d5906cf028f4db46d7e3003abecbca85
   languageName: node
   linkType: hard
 
-"es-iterator-helpers@npm:^1.0.15, es-iterator-helpers@npm:^1.0.19":
+"es-get-iterator@npm:^1.1.3":
+  version: 1.1.3
+  resolution: "es-get-iterator@npm:1.1.3"
+  dependencies:
+    call-bind: "npm:^1.0.2"
+    get-intrinsic: "npm:^1.1.3"
+    has-symbols: "npm:^1.0.3"
+    is-arguments: "npm:^1.1.1"
+    is-map: "npm:^2.0.2"
+    is-set: "npm:^2.0.2"
+    is-string: "npm:^1.0.7"
+    isarray: "npm:^2.0.5"
+    stop-iteration-iterator: "npm:^1.0.0"
+  checksum: 10c0/ebd11effa79851ea75d7f079405f9d0dc185559fd65d986c6afea59a0ff2d46c2ed8675f19f03dce7429d7f6c14ff9aede8d121fbab78d75cfda6a263030bac0
+  languageName: node
+  linkType: hard
+
+"es-iterator-helpers@npm:^1.0.19":
   version: 1.0.19
   resolution: "es-iterator-helpers@npm:1.0.19"
   dependencies:
@@ -7687,6 +7746,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"es-module-lexer@npm:^1.5.3":
+  version: 1.5.4
+  resolution: "es-module-lexer@npm:1.5.4"
+  checksum: 10c0/300a469488c2f22081df1e4c8398c78db92358496e639b0df7f89ac6455462aaf5d8893939087c1a1cbcbf20eed4610c70e0bcb8f3e4b0d80a5d2611c539408c
+  languageName: node
+  linkType: hard
+
 "es-object-atoms@npm:^1.0.0":
   version: 1.0.0
   resolution: "es-object-atoms@npm:1.0.0"
@@ -7877,8 +7943,8 @@ __metadata:
   linkType: hard
 
 "eslint-plugin-jsdoc@npm:^48.0.0":
-  version: 48.2.7
-  resolution: "eslint-plugin-jsdoc@npm:48.2.7"
+  version: 48.5.0
+  resolution: "eslint-plugin-jsdoc@npm:48.5.0"
   dependencies:
     "@es-joy/jsdoccomment": "npm:~0.43.1"
     are-docs-informative: "npm:^0.0.2"
@@ -7886,46 +7952,48 @@ __metadata:
     debug: "npm:^4.3.4"
     escape-string-regexp: "npm:^4.0.0"
     esquery: "npm:^1.5.0"
+    parse-imports: "npm:^2.1.0"
     semver: "npm:^7.6.2"
     spdx-expression-parse: "npm:^4.0.0"
+    synckit: "npm:^0.9.0"
   peerDependencies:
     eslint: ^7.0.0 || ^8.0.0 || ^9.0.0
-  checksum: 10c0/74d0f95b3d880dd4221dbc0b9341266a6cce3b8ca8d3e30032223af3552364643d6b82ad733d9bc06a20f0d640f21e4d8f5a4b00901d1771572625178b8c40c3
+  checksum: 10c0/1c5eb83df06cb228e44ad2c9da5b31987347a45b99d9e7a68957d178487a81603ad3c4c7db1ecba7e8a62d7ae20d9de1aec18a8cf2aa0e9169731cec54f78ab7
   languageName: node
   linkType: hard
 
-"eslint-plugin-jsx-a11y@npm:~6.8.0":
-  version: 6.8.0
-  resolution: "eslint-plugin-jsx-a11y@npm:6.8.0"
+"eslint-plugin-jsx-a11y@npm:~6.9.0":
+  version: 6.9.0
+  resolution: "eslint-plugin-jsx-a11y@npm:6.9.0"
   dependencies:
-    "@babel/runtime": "npm:^7.23.2"
-    aria-query: "npm:^5.3.0"
-    array-includes: "npm:^3.1.7"
+    aria-query: "npm:~5.1.3"
+    array-includes: "npm:^3.1.8"
     array.prototype.flatmap: "npm:^1.3.2"
     ast-types-flow: "npm:^0.0.8"
-    axe-core: "npm:=4.7.0"
-    axobject-query: "npm:^3.2.1"
+    axe-core: "npm:^4.9.1"
+    axobject-query: "npm:~3.1.1"
     damerau-levenshtein: "npm:^1.0.8"
     emoji-regex: "npm:^9.2.2"
-    es-iterator-helpers: "npm:^1.0.15"
-    hasown: "npm:^2.0.0"
+    es-iterator-helpers: "npm:^1.0.19"
+    hasown: "npm:^2.0.2"
     jsx-ast-utils: "npm:^3.3.5"
     language-tags: "npm:^1.0.9"
     minimatch: "npm:^3.1.2"
-    object.entries: "npm:^1.1.7"
-    object.fromentries: "npm:^2.0.7"
+    object.fromentries: "npm:^2.0.8"
+    safe-regex-test: "npm:^1.0.3"
+    string.prototype.includes: "npm:^2.0.0"
   peerDependencies:
     eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8
-  checksum: 10c0/199b883e526e6f9d7c54cb3f094abc54f11a1ec816db5fb6cae3b938eb0e503acc10ccba91ca7451633a9d0b9abc0ea03601844a8aba5fe88c5e8897c9ac8f49
+  checksum: 10c0/72ac719ca90b6149c8f3c708ac5b1177f6757668b6e174d72a78512d4ac10329331b9c666c21e9561237a96a45d7f147f6a5d270dadbb99eb4ee093f127792c3
   languageName: node
   linkType: hard
 
-"eslint-plugin-promise@npm:~6.2.0":
-  version: 6.2.0
-  resolution: "eslint-plugin-promise@npm:6.2.0"
+"eslint-plugin-promise@npm:~6.4.0":
+  version: 6.4.0
+  resolution: "eslint-plugin-promise@npm:6.4.0"
   peerDependencies:
     eslint: ^7.0.0 || ^8.0.0 || ^9.0.0
-  checksum: 10c0/5f42ee774023c089453ecb792076c64c6d0739ea6e9d6cdc9d6a63da5ba928c776e349d01cc110548f2c67045ec55343136aa7eb8b486e4ab145ac016c06a492
+  checksum: 10c0/5d07be976504f92d1d91756b0b0588a4c65e379af2520dd77c8655203085c0ab43e24d4698d1ac4b50926430cd8eb81cd1cc4c3653aae8386c805577bdf57b6c
   languageName: node
   linkType: hard
 
@@ -7939,14 +8007,14 @@ __metadata:
   linkType: hard
 
 "eslint-plugin-react@npm:^7.33.2":
-  version: 7.34.2
-  resolution: "eslint-plugin-react@npm:7.34.2"
+  version: 7.34.3
+  resolution: "eslint-plugin-react@npm:7.34.3"
   dependencies:
     array-includes: "npm:^3.1.8"
     array.prototype.findlast: "npm:^1.2.5"
     array.prototype.flatmap: "npm:^1.3.2"
     array.prototype.toreversed: "npm:^1.1.2"
-    array.prototype.tosorted: "npm:^1.1.3"
+    array.prototype.tosorted: "npm:^1.1.4"
     doctrine: "npm:^2.1.0"
     es-iterator-helpers: "npm:^1.0.19"
     estraverse: "npm:^5.3.0"
@@ -7962,7 +8030,7 @@ __metadata:
     string.prototype.matchall: "npm:^4.0.11"
   peerDependencies:
     eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8
-  checksum: 10c0/37dc04424da8626f20a071466e7238d53ed111c53e5e5398d813ac2cf76a2078f00d91f7833fe5b2f0fc98f2688a75b36e78e9ada9f1068705d23c7031094316
+  checksum: 10c0/60717e32c9948e2b4ddc53dac7c4b62c68fc7129c3249079191c941c08ebe7d1f4793d65182922d19427c2a6634e05231a7b74ceee34169afdfd0e43d4a43d26
   languageName: node
   linkType: hard
 
@@ -8845,7 +8913,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4":
+"get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4":
   version: 1.2.4
   resolution: "get-intrinsic@npm:1.2.4"
   dependencies:
@@ -9685,7 +9753,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"internal-slot@npm:^1.0.7":
+"internal-slot@npm:^1.0.4, internal-slot@npm:^1.0.7":
   version: 1.0.7
   resolution: "internal-slot@npm:1.0.7"
   dependencies:
@@ -9801,7 +9869,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"is-arguments@npm:^1.0.4":
+"is-arguments@npm:^1.0.4, is-arguments@npm:^1.1.1":
   version: 1.1.1
   resolution: "is-arguments@npm:1.1.1"
   dependencies:
@@ -9811,7 +9879,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"is-array-buffer@npm:^3.0.4":
+"is-array-buffer@npm:^3.0.2, is-array-buffer@npm:^3.0.4":
   version: 3.0.4
   resolution: "is-array-buffer@npm:3.0.4"
   dependencies:
@@ -10067,10 +10135,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"is-map@npm:^2.0.1":
-  version: 2.0.2
-  resolution: "is-map@npm:2.0.2"
-  checksum: 10c0/119ff9137a37fd131a72fab3f4ab8c9d6a24b0a1ee26b4eff14dc625900d8675a97785eea5f4174265e2006ed076cc24e89f6e57ebd080a48338d914ec9168a5
+"is-map@npm:^2.0.1, is-map@npm:^2.0.2":
+  version: 2.0.3
+  resolution: "is-map@npm:2.0.3"
+  checksum: 10c0/2c4d431b74e00fdda7162cd8e4b763d6f6f217edf97d4f8538b94b8702b150610e2c64961340015fe8df5b1fcee33ccd2e9b62619c4a8a3a155f8de6d6d355fc
   languageName: node
   linkType: hard
 
@@ -10192,10 +10260,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"is-set@npm:^2.0.1":
-  version: 2.0.2
-  resolution: "is-set@npm:2.0.2"
-  checksum: 10c0/5f8bd1880df8c0004ce694e315e6e1e47a3452014be792880bb274a3b2cdb952fdb60789636ca6e084c7947ca8b7ae03ccaf54c93a7fcfed228af810559e5432
+"is-set@npm:^2.0.1, is-set@npm:^2.0.2":
+  version: 2.0.3
+  resolution: "is-set@npm:2.0.3"
+  checksum: 10c0/f73732e13f099b2dc879c2a12341cfc22ccaca8dd504e6edae26484bd5707a35d503fba5b4daad530a9b088ced1ae6c9d8200fd92e09b428fe14ea79ce8080b7
   languageName: node
   linkType: hard
 
@@ -12390,13 +12458,13 @@ __metadata:
   languageName: node
   linkType: hard
 
-"object-is@npm:^1.0.1":
-  version: 1.1.5
-  resolution: "object-is@npm:1.1.5"
+"object-is@npm:^1.0.1, object-is@npm:^1.1.5":
+  version: 1.1.6
+  resolution: "object-is@npm:1.1.6"
   dependencies:
-    call-bind: "npm:^1.0.2"
-    define-properties: "npm:^1.1.3"
-  checksum: 10c0/8c263fb03fc28f1ffb54b44b9147235c5e233dc1ca23768e7d2569740b5d860154d7cc29a30220fe28ed6d8008e2422aefdebfe987c103e1c5d190cf02d9d886
+    call-bind: "npm:^1.0.7"
+    define-properties: "npm:^1.2.1"
+  checksum: 10c0/506af444c4dce7f8e31f34fc549e2fb8152d6b9c4a30c6e62852badd7f520b579c679af433e7a072f9d78eb7808d230dc12e1cf58da9154dfbf8813099ea0fe0
   languageName: node
   linkType: hard
 
@@ -12428,7 +12496,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"object.entries@npm:^1.1.7, object.entries@npm:^1.1.8":
+"object.entries@npm:^1.1.8":
   version: 1.1.8
   resolution: "object.entries@npm:1.1.8"
   dependencies:
@@ -12732,6 +12800,16 @@ __metadata:
   languageName: node
   linkType: hard
 
+"parse-imports@npm:^2.1.0":
+  version: 2.1.0
+  resolution: "parse-imports@npm:2.1.0"
+  dependencies:
+    es-module-lexer: "npm:^1.5.3"
+    slashes: "npm:^3.0.12"
+  checksum: 10c0/18ef58008868d2d09e472bb540d63efc7cc27f2c33607e5d09c256ece7a30062cac292bda96d820438e94f3dbf558c85e4b084c10d238baa858796794e6cf628
+  languageName: node
+  linkType: hard
+
 "parse-json@npm:^5.0.0, parse-json@npm:^5.2.0":
   version: 5.2.0
   resolution: "parse-json@npm:5.2.0"
@@ -13232,18 +13310,18 @@ __metadata:
   languageName: node
   linkType: hard
 
-"postcss-color-functional-notation@npm:^6.0.11":
-  version: 6.0.11
-  resolution: "postcss-color-functional-notation@npm:6.0.11"
+"postcss-color-functional-notation@npm:^6.0.12":
+  version: 6.0.12
+  resolution: "postcss-color-functional-notation@npm:6.0.12"
   dependencies:
-    "@csstools/css-color-parser": "npm:^2.0.2"
-    "@csstools/css-parser-algorithms": "npm:^2.6.3"
-    "@csstools/css-tokenizer": "npm:^2.3.1"
+    "@csstools/css-color-parser": "npm:^2.0.3"
+    "@csstools/css-parser-algorithms": "npm:^2.7.0"
+    "@csstools/css-tokenizer": "npm:^2.3.2"
     "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0"
     "@csstools/utilities": "npm:^1.0.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/7fd75e6881cf62f536f79dfc0ae1b709ea0b8b84833cce1671372711f6019ab4360c6a17089b654b2d376b87e7f9455b94f0d13b45ab0ab767e547b604709b3d
+  checksum: 10c0/2e8faecd2609e1b4eb8c1cab21ecca5e746916795df20e6997d66eb61c29fbb01d3e75fef3e0b3e1c181918a2186570441b81779b1fc429d6d8823fbfa164231
   languageName: node
   linkType: hard
 
@@ -13297,46 +13375,46 @@ __metadata:
   languageName: node
   linkType: hard
 
-"postcss-custom-media@npm:^10.0.6":
-  version: 10.0.6
-  resolution: "postcss-custom-media@npm:10.0.6"
+"postcss-custom-media@npm:^10.0.7":
+  version: 10.0.7
+  resolution: "postcss-custom-media@npm:10.0.7"
   dependencies:
-    "@csstools/cascade-layer-name-parser": "npm:^1.0.11"
-    "@csstools/css-parser-algorithms": "npm:^2.6.3"
-    "@csstools/css-tokenizer": "npm:^2.3.1"
-    "@csstools/media-query-list-parser": "npm:^2.1.11"
+    "@csstools/cascade-layer-name-parser": "npm:^1.0.12"
+    "@csstools/css-parser-algorithms": "npm:^2.7.0"
+    "@csstools/css-tokenizer": "npm:^2.3.2"
+    "@csstools/media-query-list-parser": "npm:^2.1.12"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/98a524bc46b780a86094bbe8007f1e577137da5490823631a683d4b3df4a13e40c5e1ab52380275a54f7011abfd98bb597c6293d964c14f9f22ec6cf9d75c550
+  checksum: 10c0/4171385ab9370806861dcf7597e53fd6aa1862e77b475c9c565c95bfcc2b950f920f8da26a6dbec42e257388bca97c274635662b5e81fe3905b5e37babe06569
   languageName: node
   linkType: hard
 
-"postcss-custom-properties@npm:^13.3.10":
-  version: 13.3.10
-  resolution: "postcss-custom-properties@npm:13.3.10"
+"postcss-custom-properties@npm:^13.3.11":
+  version: 13.3.11
+  resolution: "postcss-custom-properties@npm:13.3.11"
   dependencies:
-    "@csstools/cascade-layer-name-parser": "npm:^1.0.11"
-    "@csstools/css-parser-algorithms": "npm:^2.6.3"
-    "@csstools/css-tokenizer": "npm:^2.3.1"
+    "@csstools/cascade-layer-name-parser": "npm:^1.0.12"
+    "@csstools/css-parser-algorithms": "npm:^2.7.0"
+    "@csstools/css-tokenizer": "npm:^2.3.2"
     "@csstools/utilities": "npm:^1.0.0"
     postcss-value-parser: "npm:^4.2.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/52688fd0aaadccfdf4a3d86d3a2ab988163e8108088c5e33fc9145d261f75b92b8321c044a8161345abda10df5715d674330309dcc0c17f2980db5515f6a76d6
+  checksum: 10c0/4aa95628aa5d5b6df4dfeedbc3891b9666db88d75930cadc14d2fbba0a1b72f4e3cc3d83b5a0c0b8ce44f85b4fda6ebd7fe7792a1abc0a14d7d63b9f170d299c
   languageName: node
   linkType: hard
 
-"postcss-custom-selectors@npm:^7.1.10":
-  version: 7.1.10
-  resolution: "postcss-custom-selectors@npm:7.1.10"
+"postcss-custom-selectors@npm:^7.1.11":
+  version: 7.1.11
+  resolution: "postcss-custom-selectors@npm:7.1.11"
   dependencies:
-    "@csstools/cascade-layer-name-parser": "npm:^1.0.11"
-    "@csstools/css-parser-algorithms": "npm:^2.6.3"
-    "@csstools/css-tokenizer": "npm:^2.3.1"
-    postcss-selector-parser: "npm:^6.0.13"
+    "@csstools/cascade-layer-name-parser": "npm:^1.0.12"
+    "@csstools/css-parser-algorithms": "npm:^2.7.0"
+    "@csstools/css-tokenizer": "npm:^2.3.2"
+    postcss-selector-parser: "npm:^6.1.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/11311ae6f306420223c6bf926fb1798738f3aa525a267de204de8e8ee9de467bf63b580d9ad5dbb0fff4bd9266770a3fa7e27a24af08a2e0a4115d0727d1d043
+  checksum: 10c0/f37d2e34239e868b35b7970ec97a7a8f657a9f92ed2b221af44f19949f7c3aedcecd0abb5fa1acb120c5ceffdf7a20869338956a37d7bfc37a83d8088f5d3dd2
   languageName: node
   linkType: hard
 
@@ -13454,18 +13532,18 @@ __metadata:
   languageName: node
   linkType: hard
 
-"postcss-lab-function@npm:^6.0.16":
-  version: 6.0.16
-  resolution: "postcss-lab-function@npm:6.0.16"
+"postcss-lab-function@npm:^6.0.17":
+  version: 6.0.17
+  resolution: "postcss-lab-function@npm:6.0.17"
   dependencies:
-    "@csstools/css-color-parser": "npm:^2.0.2"
-    "@csstools/css-parser-algorithms": "npm:^2.6.3"
-    "@csstools/css-tokenizer": "npm:^2.3.1"
+    "@csstools/css-color-parser": "npm:^2.0.3"
+    "@csstools/css-parser-algorithms": "npm:^2.7.0"
+    "@csstools/css-tokenizer": "npm:^2.3.2"
     "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0"
     "@csstools/utilities": "npm:^1.0.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/ba8717cd8a197ec17acaac1b61631cd4403f07bd406b0c92f2e430a55e3f786cd6c338b626c3326e9178a0f3e58ff838ebaded19f480f39197a9cb17349ecdcd
+  checksum: 10c0/a331f188b02cc8beb315150232b6b58bc5793e8d61585973d352a9b4d370b908ff354ccf9ea1ba20a956fd37ea4ada918ea975c8d4f69e850d26edf0106436e8
   languageName: node
   linkType: hard
 
@@ -13786,52 +13864,52 @@ __metadata:
   linkType: hard
 
 "postcss-preset-env@npm:^9.5.2":
-  version: 9.5.14
-  resolution: "postcss-preset-env@npm:9.5.14"
+  version: 9.5.15
+  resolution: "postcss-preset-env@npm:9.5.15"
   dependencies:
     "@csstools/postcss-cascade-layers": "npm:^4.0.6"
-    "@csstools/postcss-color-function": "npm:^3.0.16"
-    "@csstools/postcss-color-mix-function": "npm:^2.0.16"
-    "@csstools/postcss-exponential-functions": "npm:^1.0.7"
+    "@csstools/postcss-color-function": "npm:^3.0.17"
+    "@csstools/postcss-color-mix-function": "npm:^2.0.17"
+    "@csstools/postcss-exponential-functions": "npm:^1.0.8"
     "@csstools/postcss-font-format-keywords": "npm:^3.0.2"
-    "@csstools/postcss-gamut-mapping": "npm:^1.0.9"
-    "@csstools/postcss-gradients-interpolation-method": "npm:^4.0.17"
-    "@csstools/postcss-hwb-function": "npm:^3.0.15"
+    "@csstools/postcss-gamut-mapping": "npm:^1.0.10"
+    "@csstools/postcss-gradients-interpolation-method": "npm:^4.0.18"
+    "@csstools/postcss-hwb-function": "npm:^3.0.16"
     "@csstools/postcss-ic-unit": "npm:^3.0.6"
     "@csstools/postcss-initial": "npm:^1.0.1"
     "@csstools/postcss-is-pseudo-class": "npm:^4.0.8"
-    "@csstools/postcss-light-dark-function": "npm:^1.0.5"
+    "@csstools/postcss-light-dark-function": "npm:^1.0.6"
     "@csstools/postcss-logical-float-and-clear": "npm:^2.0.1"
     "@csstools/postcss-logical-overflow": "npm:^1.0.1"
     "@csstools/postcss-logical-overscroll-behavior": "npm:^1.0.1"
     "@csstools/postcss-logical-resize": "npm:^2.0.1"
-    "@csstools/postcss-logical-viewport-units": "npm:^2.0.9"
-    "@csstools/postcss-media-minmax": "npm:^1.1.6"
-    "@csstools/postcss-media-queries-aspect-ratio-number-values": "npm:^2.0.9"
+    "@csstools/postcss-logical-viewport-units": "npm:^2.0.10"
+    "@csstools/postcss-media-minmax": "npm:^1.1.7"
+    "@csstools/postcss-media-queries-aspect-ratio-number-values": "npm:^2.0.10"
     "@csstools/postcss-nested-calc": "npm:^3.0.2"
     "@csstools/postcss-normalize-display-values": "npm:^3.0.2"
-    "@csstools/postcss-oklab-function": "npm:^3.0.16"
+    "@csstools/postcss-oklab-function": "npm:^3.0.17"
     "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0"
-    "@csstools/postcss-relative-color-syntax": "npm:^2.0.16"
+    "@csstools/postcss-relative-color-syntax": "npm:^2.0.17"
     "@csstools/postcss-scope-pseudo-class": "npm:^3.0.1"
-    "@csstools/postcss-stepped-value-functions": "npm:^3.0.8"
-    "@csstools/postcss-text-decoration-shorthand": "npm:^3.0.6"
-    "@csstools/postcss-trigonometric-functions": "npm:^3.0.8"
+    "@csstools/postcss-stepped-value-functions": "npm:^3.0.9"
+    "@csstools/postcss-text-decoration-shorthand": "npm:^3.0.7"
+    "@csstools/postcss-trigonometric-functions": "npm:^3.0.9"
     "@csstools/postcss-unset-value": "npm:^3.0.1"
     autoprefixer: "npm:^10.4.19"
-    browserslist: "npm:^4.22.3"
+    browserslist: "npm:^4.23.1"
     css-blank-pseudo: "npm:^6.0.2"
     css-has-pseudo: "npm:^6.0.5"
     css-prefers-color-scheme: "npm:^9.0.1"
     cssdb: "npm:^8.0.0"
     postcss-attribute-case-insensitive: "npm:^6.0.3"
     postcss-clamp: "npm:^4.1.0"
-    postcss-color-functional-notation: "npm:^6.0.11"
+    postcss-color-functional-notation: "npm:^6.0.12"
     postcss-color-hex-alpha: "npm:^9.0.4"
     postcss-color-rebeccapurple: "npm:^9.0.3"
-    postcss-custom-media: "npm:^10.0.6"
-    postcss-custom-properties: "npm:^13.3.10"
-    postcss-custom-selectors: "npm:^7.1.10"
+    postcss-custom-media: "npm:^10.0.7"
+    postcss-custom-properties: "npm:^13.3.11"
+    postcss-custom-selectors: "npm:^7.1.11"
     postcss-dir-pseudo-class: "npm:^8.0.1"
     postcss-double-position-gradients: "npm:^5.0.6"
     postcss-focus-visible: "npm:^9.0.1"
@@ -13839,7 +13917,7 @@ __metadata:
     postcss-font-variant: "npm:^5.0.0"
     postcss-gap-properties: "npm:^5.0.1"
     postcss-image-set-function: "npm:^6.0.3"
-    postcss-lab-function: "npm:^6.0.16"
+    postcss-lab-function: "npm:^6.0.17"
     postcss-logical: "npm:^7.0.1"
     postcss-nesting: "npm:^12.1.5"
     postcss-opacity-percentage: "npm:^2.0.0"
@@ -13851,7 +13929,7 @@ __metadata:
     postcss-selector-not: "npm:^7.0.2"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/8e0c8f5c2e7b8385a770c13185986dc50d7a73b10b98c65c2f86bb4cd2860de722caef8172b1676962dafbbc044d6be1955f2a092e951976a30d4ee33b0d7571
+  checksum: 10c0/e2ee0b5d7dbaddb82ff6d51b5882120862d6be184973ae3d55642923183ab441d421d5f9810fe02e680a70dbc85b20b1c2eb02c68f167dcaf3ef80a71dd40e78
   languageName: node
   linkType: hard
 
@@ -13975,13 +14053,13 @@ __metadata:
   linkType: hard
 
 "postcss@npm:^8.2.15, postcss@npm:^8.4.24, postcss@npm:^8.4.38":
-  version: 8.4.38
-  resolution: "postcss@npm:8.4.38"
+  version: 8.4.39
+  resolution: "postcss@npm:8.4.39"
   dependencies:
     nanoid: "npm:^3.3.7"
-    picocolors: "npm:^1.0.0"
+    picocolors: "npm:^1.0.1"
     source-map-js: "npm:^1.2.0"
-  checksum: 10c0/955407b8f70cf0c14acf35dab3615899a2a60a26718a63c848cf3c29f2467b0533991b985a2b994430d890bd7ec2b1963e36352b0774a19143b5f591540f7c06
+  checksum: 10c0/16f5ac3c4e32ee76d1582b3c0dcf1a1fdb91334a45ad755eeb881ccc50318fb8d64047de4f1601ac96e30061df203f0f2e2edbdc0bfc49b9c57bc9fb9bedaea3
   languageName: node
   linkType: hard
 
@@ -14964,7 +15042,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"regexp.prototype.flags@npm:^1.2.0, regexp.prototype.flags@npm:^1.5.2":
+"regexp.prototype.flags@npm:^1.2.0, regexp.prototype.flags@npm:^1.5.1, regexp.prototype.flags@npm:^1.5.2":
   version: 1.5.2
   resolution: "regexp.prototype.flags@npm:1.5.2"
   dependencies:
@@ -15766,6 +15844,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"slashes@npm:^3.0.12":
+  version: 3.0.12
+  resolution: "slashes@npm:3.0.12"
+  checksum: 10c0/71ca2a1fcd1ab6814b0fdb8cf9c33a3d54321deec2aa8d173510f0086880201446021a9b9e6a18561f7c472b69a2145977c6a8fb9c53a8ff7be31778f203d175
+  languageName: node
+  linkType: hard
+
 "slice-ansi@npm:^4.0.0":
   version: 4.0.0
   resolution: "slice-ansi@npm:4.0.0"
@@ -16175,6 +16260,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"stop-iteration-iterator@npm:^1.0.0":
+  version: 1.0.0
+  resolution: "stop-iteration-iterator@npm:1.0.0"
+  dependencies:
+    internal-slot: "npm:^1.0.4"
+  checksum: 10c0/c4158d6188aac510d9e92925b58709207bd94699e9c31186a040c80932a687f84a51356b5895e6dc72710aad83addb9411c22171832c9ae0e6e11b7d61b0dfb9
+  languageName: node
+  linkType: hard
+
 "stream-browserify@npm:^2.0.1":
   version: 2.0.2
   resolution: "stream-browserify@npm:2.0.2"
@@ -16259,6 +16353,16 @@ __metadata:
   languageName: node
   linkType: hard
 
+"string.prototype.includes@npm:^2.0.0":
+  version: 2.0.0
+  resolution: "string.prototype.includes@npm:2.0.0"
+  dependencies:
+    define-properties: "npm:^1.1.3"
+    es-abstract: "npm:^1.17.5"
+  checksum: 10c0/32dff118c9e9dcc87e240b05462fa8ee7248d9e335c0015c1442fe18152261508a2146d9bb87ddae56abab69148a83c61dfaea33f53853812a6a2db737689ed2
+  languageName: node
+  linkType: hard
+
 "string.prototype.matchall@npm:^4.0.11, string.prototype.matchall@npm:^4.0.6":
   version: 4.0.11
   resolution: "string.prototype.matchall@npm:4.0.11"
@@ -16702,6 +16806,16 @@ __metadata:
   languageName: node
   linkType: hard
 
+"synckit@npm:^0.9.0":
+  version: 0.9.0
+  resolution: "synckit@npm:0.9.0"
+  dependencies:
+    "@pkgr/core": "npm:^0.1.0"
+    tslib: "npm:^2.6.2"
+  checksum: 10c0/b5c1e7c03fefe3d36a9ab4e71dd21859cb32be4138712c31a893382a568fd00efc59ede8f521dd7e53d43a2fea92bdf717e987ea9ed6ad94f97ef28d71d0ba2f
+  languageName: node
+  linkType: hard
+
 "table@npm:^6.8.2":
   version: 6.8.2
   resolution: "table@npm:6.8.2"
@@ -17038,13 +17152,20 @@ __metadata:
   languageName: node
   linkType: hard
 
-"tslib@npm:2.6.2, tslib@npm:^2.4.0":
+"tslib@npm:2.6.2":
   version: 2.6.2
   resolution: "tslib@npm:2.6.2"
   checksum: 10c0/e03a8a4271152c8b26604ed45535954c0a45296e32445b4b87f8a5abdb2421f40b59b4ca437c4346af0f28179780d604094eb64546bee2019d903d01c6c19bdb
   languageName: node
   linkType: hard
 
+"tslib@npm:^2.4.0, tslib@npm:^2.6.2":
+  version: 2.6.3
+  resolution: "tslib@npm:2.6.3"
+  checksum: 10c0/2598aef53d9dbe711af75522464b2104724d6467b26a60f2bdac8297d2b5f1f6b86a71f61717384aa8fd897240467aaa7bcc36a0700a0faf751293d1331db39a
+  languageName: node
+  linkType: hard
+
 "tty-browserify@npm:0.0.0":
   version: 0.0.0
   resolution: "tty-browserify@npm:0.0.0"
@@ -18033,7 +18154,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.15, which-typed-array@npm:^1.1.9":
+"which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.15, which-typed-array@npm:^1.1.9":
   version: 1.1.15
   resolution: "which-typed-array@npm:1.1.15"
   dependencies: