about summary refs log tree commit diff
path: root/app/javascript
diff options
context:
space:
mode:
Diffstat (limited to 'app/javascript')
-rw-r--r--app/javascript/mastodon/components/error_boundary.js7
-rw-r--r--app/javascript/mastodon/components/missing_indicator.js5
-rw-r--r--app/javascript/mastodon/containers/mastodon.js2
-rw-r--r--app/javascript/mastodon/features/about/index.js6
-rw-r--r--app/javascript/mastodon/features/account/components/header.js5
-rw-r--r--app/javascript/mastodon/features/account_timeline/index.js12
-rw-r--r--app/javascript/mastodon/features/bookmarked_statuses/index.js1
-rw-r--r--app/javascript/mastodon/features/community_timeline/index.js1
-rw-r--r--app/javascript/mastodon/features/compose/index.js5
-rw-r--r--app/javascript/mastodon/features/direct_timeline/index.js1
-rw-r--r--app/javascript/mastodon/features/directory/index.js1
-rw-r--r--app/javascript/mastodon/features/domain_blocks/index.js6
-rw-r--r--app/javascript/mastodon/features/explore/index.js1
-rw-r--r--app/javascript/mastodon/features/favourited_statuses/index.js1
-rw-r--r--app/javascript/mastodon/features/favourites/index.js5
-rw-r--r--app/javascript/mastodon/features/follow_recommendations/index.js5
-rw-r--r--app/javascript/mastodon/features/follow_requests/index.js5
-rw-r--r--app/javascript/mastodon/features/getting_started/index.js1
-rw-r--r--app/javascript/mastodon/features/hashtag_timeline/index.js1
-rw-r--r--app/javascript/mastodon/features/home_timeline/index.js3
-rw-r--r--app/javascript/mastodon/features/keyboard_shortcuts/index.js5
-rw-r--r--app/javascript/mastodon/features/list_timeline/index.js1
-rw-r--r--app/javascript/mastodon/features/lists/index.js1
-rw-r--r--app/javascript/mastodon/features/mutes/index.js5
-rw-r--r--app/javascript/mastodon/features/notifications/index.js1
-rw-r--r--app/javascript/mastodon/features/pinned_statuses/index.js4
-rw-r--r--app/javascript/mastodon/features/privacy_policy/index.js6
-rw-r--r--app/javascript/mastodon/features/public_timeline/index.js1
-rw-r--r--app/javascript/mastodon/features/reblogs/index.js5
-rw-r--r--app/javascript/mastodon/features/status/index.js17
-rw-r--r--app/javascript/mastodon/features/ui/components/bundle_column_error.js27
-rw-r--r--app/javascript/mastodon/features/ui/components/column_loading.js6
-rw-r--r--app/javascript/mastodon/features/ui/components/columns_area.js4
-rw-r--r--app/javascript/mastodon/features/ui/components/modal_root.js21
-rw-r--r--app/javascript/mastodon/features/ui/index.js4
-rw-r--r--app/javascript/mastodon/features/ui/util/async-components.js8
-rw-r--r--app/javascript/mastodon/features/ui/util/react_router_helpers.js4
-rw-r--r--app/javascript/mastodon/main.js8
-rw-r--r--app/javascript/mastodon/reducers/statuses.js6
-rw-r--r--app/javascript/mastodon/selectors/index.js2
-rw-r--r--app/javascript/mastodon/service_worker/web_push_notifications.js26
-rw-r--r--app/javascript/packs/public.js29
-rw-r--r--app/javascript/styles/application.scss1
-rw-r--r--app/javascript/styles/contrast/diff.scss4
-rw-r--r--app/javascript/styles/mastodon-light/diff.scss89
-rw-r--r--app/javascript/styles/mastodon/containers.scss782
-rw-r--r--app/javascript/styles/mastodon/footer.scss152
-rw-r--r--app/javascript/styles/mastodon/rtl.scss74
-rw-r--r--app/javascript/styles/mastodon/statuses.scss3
49 files changed, 170 insertions, 1200 deletions
diff --git a/app/javascript/mastodon/components/error_boundary.js b/app/javascript/mastodon/components/error_boundary.js
index ca4a2cfe1..02d5616d6 100644
--- a/app/javascript/mastodon/components/error_boundary.js
+++ b/app/javascript/mastodon/components/error_boundary.js
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
 import { FormattedMessage } from 'react-intl';
 import { version, source_url } from 'mastodon/initial_state';
 import StackTrace from 'stacktrace-js';
+import { Helmet } from 'react-helmet';
 
 export default class ErrorBoundary extends React.PureComponent {
 
@@ -84,6 +85,7 @@ export default class ErrorBoundary extends React.PureComponent {
               <FormattedMessage id='error.unexpected_crash.explanation' defaultMessage='Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.' />
             )}
           </p>
+
           <p>
             { likelyBrowserAddonIssue ? (
               <FormattedMessage id='error.unexpected_crash.next_steps_addons' defaultMessage='Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.' />
@@ -91,8 +93,13 @@ export default class ErrorBoundary extends React.PureComponent {
               <FormattedMessage id='error.unexpected_crash.next_steps' defaultMessage='Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.' />
             )}
           </p>
+
           <p className='error-boundary__footer'>Mastodon v{version} · <a href={source_url} rel='noopener noreferrer' target='_blank'><FormattedMessage id='errors.unexpected_crash.report_issue' defaultMessage='Report issue' /></a> · <button onClick={this.handleCopyStackTrace} className={copied ? 'copied' : ''}><FormattedMessage id='errors.unexpected_crash.copy_stacktrace' defaultMessage='Copy stacktrace to clipboard' /></button></p>
         </div>
+
+        <Helmet>
+          <meta name='robots' content='noindex' />
+        </Helmet>
       </div>
     );
   }
diff --git a/app/javascript/mastodon/components/missing_indicator.js b/app/javascript/mastodon/components/missing_indicator.js
index 7b0101bab..05e0d653d 100644
--- a/app/javascript/mastodon/components/missing_indicator.js
+++ b/app/javascript/mastodon/components/missing_indicator.js
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
 import { FormattedMessage } from 'react-intl';
 import illustration from 'mastodon/../images/elephant_ui_disappointed.svg';
 import classNames from 'classnames';
+import { Helmet } from 'react-helmet';
 
 const MissingIndicator = ({ fullPage }) => (
   <div className={classNames('regeneration-indicator', { 'regeneration-indicator--without-header': fullPage })}>
@@ -14,6 +15,10 @@ const MissingIndicator = ({ fullPage }) => (
       <FormattedMessage id='missing_indicator.label' tagName='strong' defaultMessage='Not found' />
       <FormattedMessage id='missing_indicator.sublabel' defaultMessage='This resource could not be found' />
     </div>
+
+    <Helmet>
+      <meta name='robots' content='noindex' />
+    </Helmet>
   </div>
 );
 
diff --git a/app/javascript/mastodon/containers/mastodon.js b/app/javascript/mastodon/containers/mastodon.js
index 8e5a1fa3a..730695c49 100644
--- a/app/javascript/mastodon/containers/mastodon.js
+++ b/app/javascript/mastodon/containers/mastodon.js
@@ -78,7 +78,7 @@ export default class Mastodon extends React.PureComponent {
       <IntlProvider locale={locale} messages={messages}>
         <ReduxProvider store={store}>
           <ErrorBoundary>
-            <BrowserRouter basename='/web'>
+            <BrowserRouter>
               <ScrollContext shouldUpdateScroll={this.shouldUpdateScroll}>
                 <Route path='/' component={UI} />
               </ScrollContext>
diff --git a/app/javascript/mastodon/features/about/index.js b/app/javascript/mastodon/features/about/index.js
index e9212565a..75fed9b95 100644
--- a/app/javascript/mastodon/features/about/index.js
+++ b/app/javascript/mastodon/features/about/index.js
@@ -94,6 +94,7 @@ class About extends React.PureComponent {
     }),
     dispatch: PropTypes.func.isRequired,
     intl: PropTypes.object.isRequired,
+    multiColumn: PropTypes.bool,
   };
 
   componentDidMount () {
@@ -108,11 +109,11 @@ class About extends React.PureComponent {
   }
 
   render () {
-    const { intl, server, extendedDescription, domainBlocks } = this.props;
+    const { multiColumn, intl, server, extendedDescription, domainBlocks } = this.props;
     const isLoading = server.get('isLoading');
 
     return (
-      <Column>
+      <Column bindToDocument={!multiColumn} label={intl.formatMessage(messages.title)}>
         <div className='scrollable about'>
           <div className='about__header'>
             <Image blurhash={server.getIn(['thumbnail', 'blurhash'])} src={server.getIn(['thumbnail', 'url'])} srcSet={server.getIn(['thumbnail', 'versions'])?.map((value, key) => `${value} ${key.replace('@', '')}`).join(', ')} className='about__header__hero' />
@@ -212,6 +213,7 @@ class About extends React.PureComponent {
 
         <Helmet>
           <title>{intl.formatMessage(messages.title)}</title>
+          <meta name='robots' content='all' />
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/mastodon/features/account/components/header.js b/app/javascript/mastodon/features/account/components/header.js
index 44c53f9ce..954cb0ee7 100644
--- a/app/javascript/mastodon/features/account/components/header.js
+++ b/app/javascript/mastodon/features/account/components/header.js
@@ -270,7 +270,9 @@ class Header extends ImmutablePureComponent {
     const content         = { __html: account.get('note_emojified') };
     const displayNameHtml = { __html: account.get('display_name_html') };
     const fields          = account.get('fields');
-    const acct            = account.get('acct').indexOf('@') === -1 && domain ? `${account.get('acct')}@${domain}` : account.get('acct');
+    const isLocal         = account.get('acct').indexOf('@') === -1;
+    const acct            = isLocal && domain ? `${account.get('acct')}@${domain}` : account.get('acct');
+    const isIndexable     = !account.get('noindex');
 
     let badge;
 
@@ -373,6 +375,7 @@ class Header extends ImmutablePureComponent {
 
         <Helmet>
           <title>{titleFromAccount(account)}</title>
+          <meta name='robots' content={(isLocal && isIndexable) ? 'all' : 'noindex'} />
         </Helmet>
       </div>
     );
diff --git a/app/javascript/mastodon/features/account_timeline/index.js b/app/javascript/mastodon/features/account_timeline/index.js
index 51fb76f1f..437cee95c 100644
--- a/app/javascript/mastodon/features/account_timeline/index.js
+++ b/app/javascript/mastodon/features/account_timeline/index.js
@@ -142,19 +142,17 @@ class AccountTimeline extends ImmutablePureComponent {
   render () {
     const { accountId, statusIds, featuredStatusIds, isLoading, hasMore, blockedBy, suspended, isAccount, hidden, multiColumn, remote, remoteUrl } = this.props;
 
-    if (!isAccount) {
+    if (isLoading && statusIds.isEmpty()) {
       return (
         <Column>
-          <ColumnBackButton multiColumn={multiColumn} />
-          <MissingIndicator />
+          <LoadingIndicator />
         </Column>
       );
-    }
-
-    if (!statusIds && isLoading) {
+    } else if (!isLoading && !isAccount) {
       return (
         <Column>
-          <LoadingIndicator />
+          <ColumnBackButton multiColumn={multiColumn} />
+          <MissingIndicator />
         </Column>
       );
     }
diff --git a/app/javascript/mastodon/features/bookmarked_statuses/index.js b/app/javascript/mastodon/features/bookmarked_statuses/index.js
index 0e466e5ed..097be17c9 100644
--- a/app/javascript/mastodon/features/bookmarked_statuses/index.js
+++ b/app/javascript/mastodon/features/bookmarked_statuses/index.js
@@ -99,6 +99,7 @@ class Bookmarks extends ImmutablePureComponent {
 
         <Helmet>
           <title>{intl.formatMessage(messages.heading)}</title>
+          <meta name='robots' content='noindex' />
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/mastodon/features/community_timeline/index.js b/app/javascript/mastodon/features/community_timeline/index.js
index 757521802..7b3f8845f 100644
--- a/app/javascript/mastodon/features/community_timeline/index.js
+++ b/app/javascript/mastodon/features/community_timeline/index.js
@@ -151,6 +151,7 @@ class CommunityTimeline extends React.PureComponent {
 
         <Helmet>
           <title>{intl.formatMessage(messages.title)}</title>
+          <meta name='robots' content='noindex' />
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/mastodon/features/compose/index.js b/app/javascript/mastodon/features/compose/index.js
index c27556a0e..763c715de 100644
--- a/app/javascript/mastodon/features/compose/index.js
+++ b/app/javascript/mastodon/features/compose/index.js
@@ -18,6 +18,7 @@ import { mascot } from '../../initial_state';
 import Icon from 'mastodon/components/icon';
 import { logOut } from 'mastodon/utils/log_out';
 import Column from 'mastodon/components/column';
+import { Helmet } from 'react-helmet';
 
 const messages = defineMessages({
   start: { id: 'getting_started.heading', defaultMessage: 'Getting started' },
@@ -145,6 +146,10 @@ class Compose extends React.PureComponent {
       <Column onFocus={this.onFocus}>
         <NavigationContainer onClose={this.onBlur} />
         <ComposeFormContainer />
+
+        <Helmet>
+          <meta name='robots' content='noindex' />
+        </Helmet>
       </Column>
     );
   }
diff --git a/app/javascript/mastodon/features/direct_timeline/index.js b/app/javascript/mastodon/features/direct_timeline/index.js
index cfaa9c4c5..8dcc43e28 100644
--- a/app/javascript/mastodon/features/direct_timeline/index.js
+++ b/app/javascript/mastodon/features/direct_timeline/index.js
@@ -98,6 +98,7 @@ class DirectTimeline extends React.PureComponent {
 
         <Helmet>
           <title>{intl.formatMessage(messages.title)}</title>
+          <meta name='robots' content='noindex' />
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/mastodon/features/directory/index.js b/app/javascript/mastodon/features/directory/index.js
index 0ce7919b6..b45faa049 100644
--- a/app/javascript/mastodon/features/directory/index.js
+++ b/app/javascript/mastodon/features/directory/index.js
@@ -169,6 +169,7 @@ class Directory extends React.PureComponent {
 
         <Helmet>
           <title>{intl.formatMessage(messages.title)}</title>
+          <meta name='robots' content='noindex' />
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/mastodon/features/domain_blocks/index.js b/app/javascript/mastodon/features/domain_blocks/index.js
index edb80aef4..43b275c2d 100644
--- a/app/javascript/mastodon/features/domain_blocks/index.js
+++ b/app/javascript/mastodon/features/domain_blocks/index.js
@@ -11,6 +11,7 @@ import ColumnBackButtonSlim from '../../components/column_back_button_slim';
 import DomainContainer from '../../containers/domain_container';
 import { fetchDomainBlocks, expandDomainBlocks } from '../../actions/domain_blocks';
 import ScrollableList from '../../components/scrollable_list';
+import { Helmet } from 'react-helmet';
 
 const messages = defineMessages({
   heading: { id: 'column.domain_blocks', defaultMessage: 'Blocked domains' },
@@ -59,6 +60,7 @@ class Blocks extends ImmutablePureComponent {
     return (
       <Column bindToDocument={!multiColumn} icon='minus-circle' heading={intl.formatMessage(messages.heading)}>
         <ColumnBackButtonSlim />
+
         <ScrollableList
           scrollKey='domain_blocks'
           onLoadMore={this.handleLoadMore}
@@ -70,6 +72,10 @@ class Blocks extends ImmutablePureComponent {
             <DomainContainer key={domain} domain={domain} />,
           )}
         </ScrollableList>
+
+        <Helmet>
+          <meta name='robots' content='noindex' />
+        </Helmet>
       </Column>
     );
   }
diff --git a/app/javascript/mastodon/features/explore/index.js b/app/javascript/mastodon/features/explore/index.js
index 566be631e..1c7049e97 100644
--- a/app/javascript/mastodon/features/explore/index.js
+++ b/app/javascript/mastodon/features/explore/index.js
@@ -84,6 +84,7 @@ class Explore extends React.PureComponent {
 
               <Helmet>
                 <title>{intl.formatMessage(messages.title)}</title>
+                <meta name='robots' content={isSearching ? 'noindex' : 'all'} />
               </Helmet>
             </React.Fragment>
           )}
diff --git a/app/javascript/mastodon/features/favourited_statuses/index.js b/app/javascript/mastodon/features/favourited_statuses/index.js
index f1d32eff1..3741f68f6 100644
--- a/app/javascript/mastodon/features/favourited_statuses/index.js
+++ b/app/javascript/mastodon/features/favourited_statuses/index.js
@@ -99,6 +99,7 @@ class Favourites extends ImmutablePureComponent {
 
         <Helmet>
           <title>{intl.formatMessage(messages.heading)}</title>
+          <meta name='robots' content='noindex' />
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/mastodon/features/favourites/index.js b/app/javascript/mastodon/features/favourites/index.js
index 673317f04..ad10744da 100644
--- a/app/javascript/mastodon/features/favourites/index.js
+++ b/app/javascript/mastodon/features/favourites/index.js
@@ -11,6 +11,7 @@ import LoadingIndicator from 'mastodon/components/loading_indicator';
 import ScrollableList from 'mastodon/components/scrollable_list';
 import AccountContainer from 'mastodon/containers/account_container';
 import Column from 'mastodon/features/ui/components/column';
+import { Helmet } from 'react-helmet';
 
 const messages = defineMessages({
   refresh: { id: 'refresh', defaultMessage: 'Refresh' },
@@ -80,6 +81,10 @@ class Favourites extends ImmutablePureComponent {
             <AccountContainer key={id} id={id} withNote={false} />,
           )}
         </ScrollableList>
+
+        <Helmet>
+          <meta name='robots' content='noindex' />
+        </Helmet>
       </Column>
     );
   }
diff --git a/app/javascript/mastodon/features/follow_recommendations/index.js b/app/javascript/mastodon/features/follow_recommendations/index.js
index 32b55eeb3..5f7baa64c 100644
--- a/app/javascript/mastodon/features/follow_recommendations/index.js
+++ b/app/javascript/mastodon/features/follow_recommendations/index.js
@@ -12,6 +12,7 @@ import Column from 'mastodon/features/ui/components/column';
 import Account from './components/account';
 import imageGreeting from 'mastodon/../images/elephant_ui_greeting.svg';
 import Button from 'mastodon/components/button';
+import { Helmet } from 'react-helmet';
 
 const mapStateToProps = state => ({
   suggestions: state.getIn(['suggestions', 'items']),
@@ -104,6 +105,10 @@ class FollowRecommendations extends ImmutablePureComponent {
             </React.Fragment>
           )}
         </div>
+
+        <Helmet>
+          <meta name='robots' content='noindex' />
+        </Helmet>
       </Column>
     );
   }
diff --git a/app/javascript/mastodon/features/follow_requests/index.js b/app/javascript/mastodon/features/follow_requests/index.js
index 1f9b635bb..d16aa7737 100644
--- a/app/javascript/mastodon/features/follow_requests/index.js
+++ b/app/javascript/mastodon/features/follow_requests/index.js
@@ -12,6 +12,7 @@ import AccountAuthorizeContainer from './containers/account_authorize_container'
 import { fetchFollowRequests, expandFollowRequests } from '../../actions/accounts';
 import ScrollableList from '../../components/scrollable_list';
 import { me } from '../../initial_state';
+import { Helmet } from 'react-helmet';
 
 const messages = defineMessages({
   heading: { id: 'column.follow_requests', defaultMessage: 'Follow requests' },
@@ -87,6 +88,10 @@ class FollowRequests extends ImmutablePureComponent {
             <AccountAuthorizeContainer key={id} id={id} />,
           )}
         </ScrollableList>
+
+        <Helmet>
+          <meta name='robots' content='noindex' />
+        </Helmet>
       </Column>
     );
   }
diff --git a/app/javascript/mastodon/features/getting_started/index.js b/app/javascript/mastodon/features/getting_started/index.js
index 42a5b581f..f002ffc77 100644
--- a/app/javascript/mastodon/features/getting_started/index.js
+++ b/app/javascript/mastodon/features/getting_started/index.js
@@ -138,6 +138,7 @@ class GettingStarted extends ImmutablePureComponent {
 
         <Helmet>
           <title>{intl.formatMessage(messages.menu)}</title>
+          <meta name='robots' content='noindex' />
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/mastodon/features/hashtag_timeline/index.js b/app/javascript/mastodon/features/hashtag_timeline/index.js
index 0f7df5036..ec524be8f 100644
--- a/app/javascript/mastodon/features/hashtag_timeline/index.js
+++ b/app/javascript/mastodon/features/hashtag_timeline/index.js
@@ -228,6 +228,7 @@ class HashtagTimeline extends React.PureComponent {
 
         <Helmet>
           <title>#{id}</title>
+          <meta name='robots' content='noindex' />
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/mastodon/features/home_timeline/index.js b/app/javascript/mastodon/features/home_timeline/index.js
index 68770b739..838ed7dd8 100644
--- a/app/javascript/mastodon/features/home_timeline/index.js
+++ b/app/javascript/mastodon/features/home_timeline/index.js
@@ -20,7 +20,7 @@ const messages = defineMessages({
   title: { id: 'column.home', defaultMessage: 'Home' },
   show_announcements: { id: 'home.show_announcements', defaultMessage: 'Show announcements' },
   hide_announcements: { id: 'home.hide_announcements', defaultMessage: 'Hide announcements' },
-});  
+});
 
 const mapStateToProps = state => ({
   hasUnread: state.getIn(['timelines', 'home', 'unread']) > 0,
@@ -167,6 +167,7 @@ class HomeTimeline extends React.PureComponent {
 
         <Helmet>
           <title>{intl.formatMessage(messages.title)}</title>
+          <meta name='robots' content='noindex' />
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/mastodon/features/keyboard_shortcuts/index.js b/app/javascript/mastodon/features/keyboard_shortcuts/index.js
index 2a32577ba..9a870478d 100644
--- a/app/javascript/mastodon/features/keyboard_shortcuts/index.js
+++ b/app/javascript/mastodon/features/keyboard_shortcuts/index.js
@@ -4,6 +4,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import PropTypes from 'prop-types';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import ColumnHeader from 'mastodon/components/column_header';
+import { Helmet } from 'react-helmet';
 
 const messages = defineMessages({
   heading: { id: 'keyboard_shortcuts.heading', defaultMessage: 'Keyboard Shortcuts' },
@@ -164,6 +165,10 @@ class KeyboardShortcuts extends ImmutablePureComponent {
             </tbody>
           </table>
         </div>
+
+        <Helmet>
+          <meta name='robots' content='noindex' />
+        </Helmet>
       </Column>
     );
   }
diff --git a/app/javascript/mastodon/features/list_timeline/index.js b/app/javascript/mastodon/features/list_timeline/index.js
index f0a7a0c7f..fd9d33df7 100644
--- a/app/javascript/mastodon/features/list_timeline/index.js
+++ b/app/javascript/mastodon/features/list_timeline/index.js
@@ -212,6 +212,7 @@ class ListTimeline extends React.PureComponent {
 
         <Helmet>
           <title>{title}</title>
+          <meta name='robots' content='noindex' />
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/mastodon/features/lists/index.js b/app/javascript/mastodon/features/lists/index.js
index 389a0c5c8..017595ba0 100644
--- a/app/javascript/mastodon/features/lists/index.js
+++ b/app/javascript/mastodon/features/lists/index.js
@@ -80,6 +80,7 @@ class Lists extends ImmutablePureComponent {
 
         <Helmet>
           <title>{intl.formatMessage(messages.heading)}</title>
+          <meta name='robots' content='noindex' />
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/mastodon/features/mutes/index.js b/app/javascript/mastodon/features/mutes/index.js
index c21433cc4..65df6149f 100644
--- a/app/javascript/mastodon/features/mutes/index.js
+++ b/app/javascript/mastodon/features/mutes/index.js
@@ -11,6 +11,7 @@ import ColumnBackButtonSlim from '../../components/column_back_button_slim';
 import AccountContainer from '../../containers/account_container';
 import { fetchMutes, expandMutes } from '../../actions/mutes';
 import ScrollableList from '../../components/scrollable_list';
+import { Helmet } from 'react-helmet';
 
 const messages = defineMessages({
   heading: { id: 'column.mutes', defaultMessage: 'Muted users' },
@@ -72,6 +73,10 @@ class Mutes extends ImmutablePureComponent {
             <AccountContainer key={id} id={id} defaultAction='mute' />,
           )}
         </ScrollableList>
+
+        <Helmet>
+          <meta name='robots' content='noindex' />
+        </Helmet>
       </Column>
     );
   }
diff --git a/app/javascript/mastodon/features/notifications/index.js b/app/javascript/mastodon/features/notifications/index.js
index 4577bcb2d..f1bc5f160 100644
--- a/app/javascript/mastodon/features/notifications/index.js
+++ b/app/javascript/mastodon/features/notifications/index.js
@@ -281,6 +281,7 @@ class Notifications extends React.PureComponent {
 
         <Helmet>
           <title>{intl.formatMessage(messages.title)}</title>
+          <meta name='robots' content='noindex' />
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/mastodon/features/pinned_statuses/index.js b/app/javascript/mastodon/features/pinned_statuses/index.js
index 67b13f10a..c6790ea06 100644
--- a/app/javascript/mastodon/features/pinned_statuses/index.js
+++ b/app/javascript/mastodon/features/pinned_statuses/index.js
@@ -8,6 +8,7 @@ import ColumnBackButtonSlim from '../../components/column_back_button_slim';
 import StatusList from '../../components/status_list';
 import { defineMessages, injectIntl } from 'react-intl';
 import ImmutablePureComponent from 'react-immutable-pure-component';
+import { Helmet } from 'react-helmet';
 
 const messages = defineMessages({
   heading: { id: 'column.pins', defaultMessage: 'Pinned post' },
@@ -54,6 +55,9 @@ class PinnedStatuses extends ImmutablePureComponent {
           hasMore={hasMore}
           bindToDocument={!multiColumn}
         />
+        <Helmet>
+          <meta name='robots' content='noindex' />
+        </Helmet>
       </Column>
     );
   }
diff --git a/app/javascript/mastodon/features/privacy_policy/index.js b/app/javascript/mastodon/features/privacy_policy/index.js
index eee4255f4..3df487e8f 100644
--- a/app/javascript/mastodon/features/privacy_policy/index.js
+++ b/app/javascript/mastodon/features/privacy_policy/index.js
@@ -15,6 +15,7 @@ class PrivacyPolicy extends React.PureComponent {
 
   static propTypes = {
     intl: PropTypes.object,
+    multiColumn: PropTypes.bool,
   };
 
   state = {
@@ -32,11 +33,11 @@ class PrivacyPolicy extends React.PureComponent {
   }
 
   render () {
-    const { intl } = this.props;
+    const { intl, multiColumn } = this.props;
     const { isLoading, content, lastUpdated } = this.state;
 
     return (
-      <Column>
+      <Column bindToDocument={!multiColumn} label={intl.formatMessage(messages.title)}>
         <div className='scrollable privacy-policy'>
           <div className='column-title'>
             <h3><FormattedMessage id='privacy_policy.title' defaultMessage='Privacy Policy' /></h3>
@@ -51,6 +52,7 @@ class PrivacyPolicy extends React.PureComponent {
 
         <Helmet>
           <title>{intl.formatMessage(messages.title)}</title>
+          <meta name='robots' content='all' />
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/mastodon/features/public_timeline/index.js b/app/javascript/mastodon/features/public_timeline/index.js
index 8dbef98c0..a41be07e1 100644
--- a/app/javascript/mastodon/features/public_timeline/index.js
+++ b/app/javascript/mastodon/features/public_timeline/index.js
@@ -153,6 +153,7 @@ class PublicTimeline extends React.PureComponent {
 
         <Helmet>
           <title>{intl.formatMessage(messages.title)}</title>
+          <meta name='robots' content='noindex' />
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/mastodon/features/reblogs/index.js b/app/javascript/mastodon/features/reblogs/index.js
index 7704a049f..70d338ef1 100644
--- a/app/javascript/mastodon/features/reblogs/index.js
+++ b/app/javascript/mastodon/features/reblogs/index.js
@@ -11,6 +11,7 @@ import Column from '../ui/components/column';
 import ScrollableList from '../../components/scrollable_list';
 import Icon from 'mastodon/components/icon';
 import ColumnHeader from '../../components/column_header';
+import { Helmet } from 'react-helmet';
 
 const messages = defineMessages({
   refresh: { id: 'refresh', defaultMessage: 'Refresh' },
@@ -80,6 +81,10 @@ class Reblogs extends ImmutablePureComponent {
             <AccountContainer key={id} id={id} withNote={false} />,
           )}
         </ScrollableList>
+
+        <Helmet>
+          <meta name='robots' content='noindex' />
+        </Helmet>
       </Column>
     );
   }
diff --git a/app/javascript/mastodon/features/status/index.js b/app/javascript/mastodon/features/status/index.js
index f9a97c9b5..02f390c6a 100644
--- a/app/javascript/mastodon/features/status/index.js
+++ b/app/javascript/mastodon/features/status/index.js
@@ -7,6 +7,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
 import { createSelector } from 'reselect';
 import { fetchStatus } from '../../actions/statuses';
 import MissingIndicator from '../../components/missing_indicator';
+import LoadingIndicator from 'mastodon/components/loading_indicator';
 import DetailedStatus from './components/detailed_status';
 import ActionBar from './components/action_bar';
 import Column from '../ui/components/column';
@@ -145,6 +146,7 @@ const makeMapStateToProps = () => {
     }
 
     return {
+      isLoading: state.getIn(['statuses', props.params.statusId, 'isLoading']),
       status,
       ancestorsIds,
       descendantsIds,
@@ -187,6 +189,7 @@ class Status extends ImmutablePureComponent {
     params: PropTypes.object.isRequired,
     dispatch: PropTypes.func.isRequired,
     status: ImmutablePropTypes.map,
+    isLoading: PropTypes.bool,
     ancestorsIds: ImmutablePropTypes.list,
     descendantsIds: ImmutablePropTypes.list,
     intl: PropTypes.object.isRequired,
@@ -566,9 +569,17 @@ class Status extends ImmutablePureComponent {
 
   render () {
     let ancestors, descendants;
-    const { status, ancestorsIds, descendantsIds, intl, domain, multiColumn, pictureInPicture } = this.props;
+    const { isLoading, status, ancestorsIds, descendantsIds, intl, domain, multiColumn, pictureInPicture } = this.props;
     const { fullscreen } = this.state;
 
+    if (isLoading) {
+      return (
+        <Column>
+          <LoadingIndicator />
+        </Column>
+      );
+    }
+
     if (status === null) {
       return (
         <Column>
@@ -586,6 +597,9 @@ class Status extends ImmutablePureComponent {
       descendants = <div>{this.renderChildren(descendantsIds)}</div>;
     }
 
+    const isLocal = status.getIn(['account', 'acct'], '').indexOf('@') === -1;
+    const isIndexable = !status.getIn(['account', 'noindex']);
+
     const handlers = {
       moveUp: this.handleHotkeyMoveUp,
       moveDown: this.handleHotkeyMoveDown,
@@ -659,6 +673,7 @@ class Status extends ImmutablePureComponent {
 
         <Helmet>
           <title>{titleFromStatus(status)}</title>
+          <meta name='robots' content={(isLocal && isIndexable) ? 'all' : 'noindex'} />
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/mastodon/features/ui/components/bundle_column_error.js b/app/javascript/mastodon/features/ui/components/bundle_column_error.js
index f39ebd900..ab6d4aa44 100644
--- a/app/javascript/mastodon/features/ui/components/bundle_column_error.js
+++ b/app/javascript/mastodon/features/ui/components/bundle_column_error.js
@@ -1,11 +1,10 @@
 import React from 'react';
 import PropTypes from 'prop-types';
 import { defineMessages, injectIntl } from 'react-intl';
-
-import Column from './column';
-import ColumnHeader from './column_header';
-import ColumnBackButtonSlim from '../../../components/column_back_button_slim';
-import IconButton from '../../../components/icon_button';
+import Column from 'mastodon/components/column';
+import ColumnHeader from 'mastodon/components/column_header';
+import IconButton from 'mastodon/components/icon_button';
+import { Helmet } from 'react-helmet';
 
 const messages = defineMessages({
   title: { id: 'bundle_column_error.title', defaultMessage: 'Network error' },
@@ -18,6 +17,7 @@ class BundleColumnError extends React.PureComponent {
   static propTypes = {
     onRetry: PropTypes.func.isRequired,
     intl: PropTypes.object.isRequired,
+    multiColumn: PropTypes.bool,
   }
 
   handleRetry = () => {
@@ -25,16 +25,25 @@ class BundleColumnError extends React.PureComponent {
   }
 
   render () {
-    const { intl: { formatMessage } } = this.props;
+    const { multiColumn, intl: { formatMessage } } = this.props;
 
     return (
-      <Column>
-        <ColumnHeader icon='exclamation-circle' type={formatMessage(messages.title)} />
-        <ColumnBackButtonSlim />
+      <Column bindToDocument={!multiColumn} label={formatMessage(messages.title)}>
+        <ColumnHeader
+          icon='exclamation-circle'
+          title={formatMessage(messages.title)}
+          showBackButton
+          multiColumn={multiColumn}
+        />
+
         <div className='error-column'>
           <IconButton title={formatMessage(messages.retry)} icon='refresh' onClick={this.handleRetry} size={64} />
           {formatMessage(messages.body)}
         </div>
+
+        <Helmet>
+          <meta name='robots' content='noindex' />
+        </Helmet>
       </Column>
     );
   }
diff --git a/app/javascript/mastodon/features/ui/components/column_loading.js b/app/javascript/mastodon/features/ui/components/column_loading.js
index 0cdfd05d8..e5ed22584 100644
--- a/app/javascript/mastodon/features/ui/components/column_loading.js
+++ b/app/javascript/mastodon/features/ui/components/column_loading.js
@@ -10,6 +10,7 @@ export default class ColumnLoading extends ImmutablePureComponent {
   static propTypes = {
     title: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
     icon: PropTypes.string,
+    multiColumn: PropTypes.bool,
   };
 
   static defaultProps = {
@@ -18,10 +19,11 @@ export default class ColumnLoading extends ImmutablePureComponent {
   };
 
   render() {
-    let { title, icon } = this.props;
+    let { title, icon, multiColumn } = this.props;
+
     return (
       <Column>
-        <ColumnHeader icon={icon} title={title} multiColumn={false} focusable={false} placeholder />
+        <ColumnHeader icon={icon} title={title} multiColumn={multiColumn} focusable={false} placeholder />
         <div className='scrollable' />
       </Column>
     );
diff --git a/app/javascript/mastodon/features/ui/components/columns_area.js b/app/javascript/mastodon/features/ui/components/columns_area.js
index cc1bc83e0..9ee6fca43 100644
--- a/app/javascript/mastodon/features/ui/components/columns_area.js
+++ b/app/javascript/mastodon/features/ui/components/columns_area.js
@@ -139,11 +139,11 @@ class ColumnsArea extends ImmutablePureComponent {
   }
 
   renderLoading = columnId => () => {
-    return columnId === 'COMPOSE' ? <DrawerLoading /> : <ColumnLoading />;
+    return columnId === 'COMPOSE' ? <DrawerLoading /> : <ColumnLoading multiColumn />;
   }
 
   renderError = (props) => {
-    return <BundleColumnError {...props} />;
+    return <BundleColumnError multiColumn {...props} />;
   }
 
   render () {
diff --git a/app/javascript/mastodon/features/ui/components/modal_root.js b/app/javascript/mastodon/features/ui/components/modal_root.js
index 5c273ffa4..2224a8207 100644
--- a/app/javascript/mastodon/features/ui/components/modal_root.js
+++ b/app/javascript/mastodon/features/ui/components/modal_root.js
@@ -11,9 +11,7 @@ import VideoModal from './video_modal';
 import BoostModal from './boost_modal';
 import AudioModal from './audio_modal';
 import ConfirmationModal from './confirmation_modal';
-import SubscribedLanguagesModal from 'mastodon/features/subscribed_languages_modal';
 import FocalPointModal from './focal_point_modal';
-import InteractionModal from 'mastodon/features/interaction_modal';
 import {
   MuteModal,
   BlockModal,
@@ -23,7 +21,10 @@ import {
   ListAdder,
   CompareHistoryModal,
   FilterModal,
+  InteractionModal,
+  SubscribedLanguagesModal,
 } from 'mastodon/features/ui/util/async-components';
+import { Helmet } from 'react-helmet';
 
 const MODAL_COMPONENTS = {
   'MEDIA': () => Promise.resolve({ default: MediaModal }),
@@ -41,8 +42,8 @@ const MODAL_COMPONENTS = {
   'LIST_ADDER': ListAdder,
   'COMPARE_HISTORY': CompareHistoryModal,
   'FILTER': FilterModal,
-  'SUBSCRIBED_LANGUAGES': () => Promise.resolve({ default: SubscribedLanguagesModal }),
-  'INTERACTION': () => Promise.resolve({ default: InteractionModal }),
+  'SUBSCRIBED_LANGUAGES': SubscribedLanguagesModal,
+  'INTERACTION': InteractionModal,
 };
 
 export default class ModalRoot extends React.PureComponent {
@@ -111,9 +112,15 @@ export default class ModalRoot extends React.PureComponent {
     return (
       <Base backgroundColor={backgroundColor} onClose={this.handleClose} ignoreFocus={ignoreFocus}>
         {visible && (
-          <BundleContainer fetchComponent={MODAL_COMPONENTS[type]} loading={this.renderLoading(type)} error={this.renderError} renderDelay={200}>
-            {(SpecificComponent) => <SpecificComponent {...props} onChangeBackgroundColor={this.setBackgroundColor} onClose={this.handleClose} ref={this.setModalRef} />}
-          </BundleContainer>
+          <>
+            <BundleContainer fetchComponent={MODAL_COMPONENTS[type]} loading={this.renderLoading(type)} error={this.renderError} renderDelay={200}>
+              {(SpecificComponent) => <SpecificComponent {...props} onChangeBackgroundColor={this.setBackgroundColor} onClose={this.handleClose} ref={this.setModalRef} />}
+            </BundleContainer>
+
+            <Helmet>
+              <meta name='robots' content='noindex' />
+            </Helmet>
+          </>
         )}
       </Base>
     );
diff --git a/app/javascript/mastodon/features/ui/index.js b/app/javascript/mastodon/features/ui/index.js
index 8f9f38036..003991857 100644
--- a/app/javascript/mastodon/features/ui/index.js
+++ b/app/javascript/mastodon/features/ui/index.js
@@ -197,8 +197,8 @@ class SwitchingColumnsArea extends React.PureComponent {
           <WrappedRoute path={['/@:acct', '/accounts/:id']} exact component={AccountTimeline} content={children} />
           <WrappedRoute path='/@:acct/tagged/:tagged?' exact component={AccountTimeline} content={children} />
           <WrappedRoute path={['/@:acct/with_replies', '/accounts/:id/with_replies']} component={AccountTimeline} content={children} componentParams={{ withReplies: true }} />
-          <WrappedRoute path={['/@:acct/followers', '/accounts/:id/followers']} component={Followers} content={children} />
-          <WrappedRoute path={['/@:acct/following', '/accounts/:id/following']} component={Following} content={children} />
+          <WrappedRoute path={['/accounts/:id/followers', '/users/:acct/followers', '/@:acct/followers']} component={Followers} content={children} />
+          <WrappedRoute path={['/accounts/:id/following', '/users/:acct/following', '/@:acct/following']} component={Following} content={children} />
           <WrappedRoute path={['/@:acct/media', '/accounts/:id/media']} component={AccountGallery} content={children} />
           <WrappedRoute path='/@:acct/:statusId' exact component={Status} content={children} />
           <WrappedRoute path='/@:acct/:statusId/reblogs' component={Reblogs} content={children} />
diff --git a/app/javascript/mastodon/features/ui/util/async-components.js b/app/javascript/mastodon/features/ui/util/async-components.js
index c79dc014c..7686a69ea 100644
--- a/app/javascript/mastodon/features/ui/util/async-components.js
+++ b/app/javascript/mastodon/features/ui/util/async-components.js
@@ -166,6 +166,14 @@ export function FilterModal () {
   return import(/*webpackChunkName: "modals/filter_modal" */'../components/filter_modal');
 }
 
+export function InteractionModal () {
+  return import(/*webpackChunkName: "modals/interaction_modal" */'../../interaction_modal');
+}
+
+export function SubscribedLanguagesModal () {
+  return import(/*webpackChunkName: "modals/subscribed_languages_modal" */'../../subscribed_languages_modal');
+}
+
 export function About () {
   return import(/*webpackChunkName: "features/about" */'../../about');
 }
diff --git a/app/javascript/mastodon/features/ui/util/react_router_helpers.js b/app/javascript/mastodon/features/ui/util/react_router_helpers.js
index d452b871f..a65d79def 100644
--- a/app/javascript/mastodon/features/ui/util/react_router_helpers.js
+++ b/app/javascript/mastodon/features/ui/util/react_router_helpers.js
@@ -53,7 +53,9 @@ export class WrappedRoute extends React.Component {
   }
 
   renderLoading = () => {
-    return <ColumnLoading />;
+    const { multiColumn } = this.props;
+
+    return <ColumnLoading multiColumn={multiColumn} />;
   }
 
   renderError = (props) => {
diff --git a/app/javascript/mastodon/main.js b/app/javascript/mastodon/main.js
index f33375b50..d0337ce0c 100644
--- a/app/javascript/mastodon/main.js
+++ b/app/javascript/mastodon/main.js
@@ -12,14 +12,6 @@ const perf = require('mastodon/performance');
 function main() {
   perf.start('main()');
 
-  if (window.history && history.replaceState) {
-    const { pathname, search, hash } = window.location;
-    const path = pathname + search + hash;
-    if (!(/^\/web($|\/)/).test(path)) {
-      history.replaceState(null, document.title, `/web${path}`);
-    }
-  }
-
   return ready(async () => {
     const mountNode = document.getElementById('mastodon');
     const props = JSON.parse(mountNode.getAttribute('data-props'));
diff --git a/app/javascript/mastodon/reducers/statuses.js b/app/javascript/mastodon/reducers/statuses.js
index 7efb49d85..c30c1e2cc 100644
--- a/app/javascript/mastodon/reducers/statuses.js
+++ b/app/javascript/mastodon/reducers/statuses.js
@@ -15,6 +15,8 @@ import {
   STATUS_COLLAPSE,
   STATUS_TRANSLATE_SUCCESS,
   STATUS_TRANSLATE_UNDO,
+  STATUS_FETCH_REQUEST,
+  STATUS_FETCH_FAIL,
 } from '../actions/statuses';
 import { TIMELINE_DELETE } from '../actions/timelines';
 import { STATUS_IMPORT, STATUSES_IMPORT } from '../actions/importer';
@@ -37,6 +39,10 @@ const initialState = ImmutableMap();
 
 export default function statuses(state = initialState, action) {
   switch(action.type) {
+  case STATUS_FETCH_REQUEST:
+    return state.setIn([action.id, 'isLoading'], true);
+  case STATUS_FETCH_FAIL:
+    return state.delete(action.id);
   case STATUS_IMPORT:
     return importStatus(state, action.status);
   case STATUSES_IMPORT:
diff --git a/app/javascript/mastodon/selectors/index.js b/app/javascript/mastodon/selectors/index.js
index 3dd7f4897..bf46c810e 100644
--- a/app/javascript/mastodon/selectors/index.js
+++ b/app/javascript/mastodon/selectors/index.js
@@ -41,7 +41,7 @@ export const makeGetStatus = () => {
     ],
 
     (statusBase, statusReblog, accountBase, accountReblog, filters) => {
-      if (!statusBase) {
+      if (!statusBase || statusBase.get('isLoading')) {
         return null;
       }
 
diff --git a/app/javascript/mastodon/service_worker/web_push_notifications.js b/app/javascript/mastodon/service_worker/web_push_notifications.js
index 9b75e9b9d..f12595777 100644
--- a/app/javascript/mastodon/service_worker/web_push_notifications.js
+++ b/app/javascript/mastodon/service_worker/web_push_notifications.js
@@ -15,7 +15,7 @@ const notify = options =>
         icon: '/android-chrome-192x192.png',
         tag: GROUP_TAG,
         data: {
-          url: (new URL('/web/notifications', self.location)).href,
+          url: (new URL('/notifications', self.location)).href,
           count: notifications.length + 1,
           preferred_locale: options.data.preferred_locale,
         },
@@ -90,7 +90,7 @@ export const handlePush = (event) => {
       options.tag       = notification.id;
       options.badge     = '/badge.png';
       options.image     = notification.status && notification.status.media_attachments.length > 0 && notification.status.media_attachments[0].preview_url || undefined;
-      options.data      = { access_token, preferred_locale, id: notification.status ? notification.status.id : notification.account.id, url: notification.status ? `/web/@${notification.account.acct}/${notification.status.id}` : `/web/@${notification.account.acct}` };
+      options.data      = { access_token, preferred_locale, id: notification.status ? notification.status.id : notification.account.id, url: notification.status ? `/@${notification.account.acct}/${notification.status.id}` : `/@${notification.account.acct}` };
 
       if (notification.status && notification.status.spoiler_text || notification.status.sensitive) {
         options.data.hiddenBody  = htmlToPlainText(notification.status.content);
@@ -115,7 +115,7 @@ export const handlePush = (event) => {
         tag: notification_id,
         timestamp: new Date(),
         badge: '/badge.png',
-        data: { access_token, preferred_locale, url: '/web/notifications' },
+        data: { access_token, preferred_locale, url: '/notifications' },
       });
     }),
   );
@@ -166,24 +166,10 @@ const removeActionFromNotification = (notification, action) => {
 
 const openUrl = url =>
   self.clients.matchAll({ type: 'window' }).then(clientList => {
-    if (clientList.length !== 0) {
-      const webClients = clientList.filter(client => /\/web\//.test(client.url));
-
-      if (webClients.length !== 0) {
-        const client       = findBestClient(webClients);
-        const { pathname } = new URL(url, self.location);
-
-        if (pathname.startsWith('/web/')) {
-          return client.focus().then(client => client.postMessage({
-            type: 'navigate',
-            path: pathname.slice('/web/'.length - 1),
-          }));
-        }
-      } else if ('navigate' in clientList[0]) { // Chrome 42-48 does not support navigate
-        const client = findBestClient(clientList);
+    if (clientList.length !== 0 && 'navigate' in clientList[0]) { // Chrome 42-48 does not support navigate
+      const client = findBestClient(clientList);
 
-        return client.navigate(url).then(client => client.focus());
-      }
+      return client.navigate(url).then(client => client.focus());
     }
 
     return self.clients.openWindow(url);
diff --git a/app/javascript/packs/public.js b/app/javascript/packs/public.js
index e42468e0c..5ff45fa55 100644
--- a/app/javascript/packs/public.js
+++ b/app/javascript/packs/public.js
@@ -33,7 +33,6 @@ function main() {
   const { messages } = getLocale();
   const React = require('react');
   const ReactDOM = require('react-dom');
-  const Rellax = require('rellax');
   const { createBrowserHistory } = require('history');
 
   const scrollToDetailedStatus = () => {
@@ -112,12 +111,6 @@ function main() {
       scrollToDetailedStatus();
     }
 
-    const parallaxComponents = document.querySelectorAll('.parallax');
-
-    if (parallaxComponents.length > 0 ) {
-      new Rellax('.parallax', { speed: -1 });
-    }
-
     delegate(document, '#registration_user_password_confirmation,#registration_user_password', 'input', () => {
       const password = document.getElementById('registration_user_password');
       const confirmation = document.getElementById('registration_user_password_confirmation');
@@ -168,28 +161,6 @@ function main() {
     });
   });
 
-  delegate(document, '.webapp-btn', 'click', ({ target, button }) => {
-    if (button !== 0) {
-      return true;
-    }
-    window.location.href = target.href;
-    return false;
-  });
-
-  delegate(document, '.modal-button', 'click', e => {
-    e.preventDefault();
-
-    let href;
-
-    if (e.target.nodeName !== 'A') {
-      href = e.target.parentNode.href;
-    } else {
-      href = e.target.href;
-    }
-
-    window.open(href, 'mastodon-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes');
-  });
-
   delegate(document, '#account_display_name', 'input', ({ target }) => {
     const name = document.querySelector('.card .display-name strong');
     if (name) {
diff --git a/app/javascript/styles/application.scss b/app/javascript/styles/application.scss
index e9f596e2f..81a040108 100644
--- a/app/javascript/styles/application.scss
+++ b/app/javascript/styles/application.scss
@@ -8,7 +8,6 @@
 @import 'mastodon/branding';
 @import 'mastodon/containers';
 @import 'mastodon/lists';
-@import 'mastodon/footer';
 @import 'mastodon/widgets';
 @import 'mastodon/forms';
 @import 'mastodon/accounts';
diff --git a/app/javascript/styles/contrast/diff.scss b/app/javascript/styles/contrast/diff.scss
index 22f5bcc94..27eb837df 100644
--- a/app/javascript/styles/contrast/diff.scss
+++ b/app/javascript/styles/contrast/diff.scss
@@ -68,10 +68,6 @@
   color: $darker-text-color;
 }
 
-.public-layout .public-account-header__tabs__tabs .counter.active::after {
-  border-bottom: 4px solid $ui-highlight-color;
-}
-
 .compose-form .autosuggest-textarea__textarea::placeholder,
 .compose-form .spoiler-input__input::placeholder {
   color: $inverted-text-color;
diff --git a/app/javascript/styles/mastodon-light/diff.scss b/app/javascript/styles/mastodon-light/diff.scss
index 4b27e6b4f..20e973b8b 100644
--- a/app/javascript/styles/mastodon-light/diff.scss
+++ b/app/javascript/styles/mastodon-light/diff.scss
@@ -655,95 +655,6 @@ html {
   }
 }
 
-.public-layout {
-  .account__section-headline {
-    border: 1px solid lighten($ui-base-color, 8%);
-
-    @media screen and (max-width: $no-gap-breakpoint) {
-      border-top: 0;
-    }
-  }
-
-  .header,
-  .public-account-header,
-  .public-account-bio {
-    box-shadow: none;
-  }
-
-  .public-account-bio,
-  .hero-widget__text {
-    background: $account-background-color;
-  }
-
-  .header {
-    background: $ui-base-color;
-    border: 1px solid lighten($ui-base-color, 8%);
-
-    @media screen and (max-width: $no-gap-breakpoint) {
-      border: 0;
-    }
-
-    .brand {
-      &:hover,
-      &:focus,
-      &:active {
-        background: lighten($ui-base-color, 4%);
-      }
-    }
-  }
-
-  .public-account-header {
-    &__image {
-      background: lighten($ui-base-color, 12%);
-
-      &::after {
-        box-shadow: none;
-      }
-    }
-
-    &__bar {
-      &::before {
-        background: $account-background-color;
-        border: 1px solid lighten($ui-base-color, 8%);
-        border-top: 0;
-      }
-
-      .avatar img {
-        border-color: $account-background-color;
-      }
-
-      @media screen and (max-width: $no-columns-breakpoint) {
-        background: $account-background-color;
-        border: 1px solid lighten($ui-base-color, 8%);
-        border-top: 0;
-      }
-    }
-
-    &__tabs {
-      &__name {
-        h1,
-        h1 small {
-          color: $white;
-
-          @media screen and (max-width: $no-columns-breakpoint) {
-            color: $primary-text-color;
-          }
-        }
-      }
-    }
-
-    &__extra {
-      .public-account-bio {
-        border: 0;
-      }
-
-      .public-account-bio .account__header__fields {
-        border-color: lighten($ui-base-color, 8%);
-      }
-    }
-  }
-}
-
 .notification__filter-bar button.active::after,
 .account__section-headline a.active::after {
   border-color: transparent transparent $white;
diff --git a/app/javascript/styles/mastodon/containers.scss b/app/javascript/styles/mastodon/containers.scss
index 8e5ed03f0..b49b93984 100644
--- a/app/javascript/styles/mastodon/containers.scss
+++ b/app/javascript/styles/mastodon/containers.scss
@@ -104,785 +104,3 @@
     margin-left: 10px;
   }
 }
-
-.grid-3 {
-  display: grid;
-  grid-gap: 10px;
-  grid-template-columns: 3fr 1fr;
-  grid-auto-columns: 25%;
-  grid-auto-rows: max-content;
-
-  .column-0 {
-    grid-column: 1 / 3;
-    grid-row: 1;
-  }
-
-  .column-1 {
-    grid-column: 1;
-    grid-row: 2;
-  }
-
-  .column-2 {
-    grid-column: 2;
-    grid-row: 2;
-  }
-
-  .column-3 {
-    grid-column: 1 / 3;
-    grid-row: 3;
-  }
-
-  @media screen and (max-width: $no-gap-breakpoint) {
-    grid-gap: 0;
-    grid-template-columns: minmax(0, 100%);
-
-    .column-0 {
-      grid-column: 1;
-    }
-
-    .column-1 {
-      grid-column: 1;
-      grid-row: 3;
-    }
-
-    .column-2 {
-      grid-column: 1;
-      grid-row: 2;
-    }
-
-    .column-3 {
-      grid-column: 1;
-      grid-row: 4;
-    }
-  }
-}
-
-.grid-4 {
-  display: grid;
-  grid-gap: 10px;
-  grid-template-columns: repeat(4, minmax(0, 1fr));
-  grid-auto-columns: 25%;
-  grid-auto-rows: max-content;
-
-  .column-0 {
-    grid-column: 1 / 5;
-    grid-row: 1;
-  }
-
-  .column-1 {
-    grid-column: 1 / 4;
-    grid-row: 2;
-  }
-
-  .column-2 {
-    grid-column: 4;
-    grid-row: 2;
-  }
-
-  .column-3 {
-    grid-column: 2 / 5;
-    grid-row: 3;
-  }
-
-  .column-4 {
-    grid-column: 1;
-    grid-row: 3;
-  }
-
-  .landing-page__call-to-action {
-    min-height: 100%;
-  }
-
-  .flash-message {
-    margin-bottom: 10px;
-  }
-
-  @media screen and (max-width: 738px) {
-    grid-template-columns: minmax(0, 50%) minmax(0, 50%);
-
-    .landing-page__call-to-action {
-      padding: 20px;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-    }
-
-    .row__information-board {
-      width: 100%;
-      justify-content: center;
-      align-items: center;
-    }
-
-    .row__mascot {
-      display: none;
-    }
-  }
-
-  @media screen and (max-width: $no-gap-breakpoint) {
-    grid-gap: 0;
-    grid-template-columns: minmax(0, 100%);
-
-    .column-0 {
-      grid-column: 1;
-    }
-
-    .column-1 {
-      grid-column: 1;
-      grid-row: 3;
-    }
-
-    .column-2 {
-      grid-column: 1;
-      grid-row: 2;
-    }
-
-    .column-3 {
-      grid-column: 1;
-      grid-row: 5;
-    }
-
-    .column-4 {
-      grid-column: 1;
-      grid-row: 4;
-    }
-  }
-}
-
-.public-layout {
-  @media screen and (max-width: $no-gap-breakpoint) {
-    padding-top: 48px;
-  }
-
-  .container {
-    max-width: 960px;
-
-    @media screen and (max-width: $no-gap-breakpoint) {
-      padding: 0;
-    }
-  }
-
-  .header {
-    background: lighten($ui-base-color, 8%);
-    box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
-    border-radius: 4px;
-    height: 48px;
-    margin: 10px 0;
-    display: flex;
-    align-items: stretch;
-    justify-content: center;
-    flex-wrap: nowrap;
-    overflow: hidden;
-
-    @media screen and (max-width: $no-gap-breakpoint) {
-      position: fixed;
-      width: 100%;
-      top: 0;
-      left: 0;
-      margin: 0;
-      border-radius: 0;
-      box-shadow: none;
-      z-index: 110;
-    }
-
-    & > div {
-      flex: 1 1 33.3%;
-      min-height: 1px;
-    }
-
-    .nav-left {
-      display: flex;
-      align-items: stretch;
-      justify-content: flex-start;
-      flex-wrap: nowrap;
-    }
-
-    .nav-center {
-      display: flex;
-      align-items: stretch;
-      justify-content: center;
-      flex-wrap: nowrap;
-    }
-
-    .nav-right {
-      display: flex;
-      align-items: stretch;
-      justify-content: flex-end;
-      flex-wrap: nowrap;
-    }
-
-    .brand {
-      display: block;
-      padding: 15px;
-
-      .logo {
-        display: block;
-        height: 18px;
-        width: auto;
-        position: relative;
-        bottom: -2px;
-        fill: $primary-text-color;
-
-        @media screen and (max-width: $no-gap-breakpoint) {
-          height: 20px;
-        }
-      }
-
-      &:hover,
-      &:focus,
-      &:active {
-        background: lighten($ui-base-color, 12%);
-      }
-    }
-
-    .nav-link {
-      display: flex;
-      align-items: center;
-      padding: 0 1rem;
-      font-size: 12px;
-      font-weight: 500;
-      text-decoration: none;
-      color: $darker-text-color;
-      white-space: nowrap;
-      text-align: center;
-
-      &:hover,
-      &:focus,
-      &:active {
-        text-decoration: underline;
-        color: $primary-text-color;
-      }
-
-      @media screen and (max-width: 550px) {
-        &.optional {
-          display: none;
-        }
-      }
-    }
-
-    .nav-button {
-      background: lighten($ui-base-color, 16%);
-      margin: 8px;
-      margin-left: 0;
-      border-radius: 4px;
-
-      &:hover,
-      &:focus,
-      &:active {
-        text-decoration: none;
-        background: lighten($ui-base-color, 20%);
-      }
-    }
-  }
-
-  $no-columns-breakpoint: 600px;
-
-  .grid {
-    display: grid;
-    grid-gap: 10px;
-    grid-template-columns: minmax(300px, 3fr) minmax(298px, 1fr);
-    grid-auto-columns: 25%;
-    grid-auto-rows: max-content;
-
-    .column-0 {
-      grid-row: 1;
-      grid-column: 1;
-    }
-
-    .column-1 {
-      grid-row: 1;
-      grid-column: 2;
-    }
-
-    @media screen and (max-width: $no-columns-breakpoint) {
-      grid-template-columns: 100%;
-      grid-gap: 0;
-
-      .column-1 {
-        display: none;
-      }
-    }
-  }
-
-  .page-header {
-    @media screen and (max-width: $no-gap-breakpoint) {
-      border-bottom: 0;
-    }
-  }
-
-  .public-account-header {
-    overflow: hidden;
-    margin-bottom: 10px;
-    box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
-
-    &.inactive {
-      opacity: 0.5;
-
-      .public-account-header__image,
-      .avatar {
-        filter: grayscale(100%);
-      }
-
-      .logo-button {
-        background-color: $secondary-text-color;
-      }
-    }
-
-    .logo-button {
-      padding: 3px 15px;
-    }
-
-    &__image {
-      border-radius: 4px 4px 0 0;
-      overflow: hidden;
-      height: 300px;
-      position: relative;
-      background: darken($ui-base-color, 12%);
-
-      &::after {
-        content: "";
-        display: block;
-        position: absolute;
-        width: 100%;
-        height: 100%;
-        box-shadow: inset 0 -1px 1px 1px rgba($base-shadow-color, 0.15);
-        top: 0;
-        left: 0;
-      }
-
-      img {
-        object-fit: cover;
-        display: block;
-        width: 100%;
-        height: 100%;
-        margin: 0;
-        border-radius: 4px 4px 0 0;
-      }
-
-      @media screen and (max-width: 600px) {
-        height: 200px;
-      }
-    }
-
-    &--no-bar {
-      margin-bottom: 0;
-
-      .public-account-header__image,
-      .public-account-header__image img {
-        border-radius: 4px;
-
-        @media screen and (max-width: $no-gap-breakpoint) {
-          border-radius: 0;
-        }
-      }
-    }
-
-    @media screen and (max-width: $no-gap-breakpoint) {
-      margin-bottom: 0;
-      box-shadow: none;
-
-      &__image::after {
-        display: none;
-      }
-
-      &__image,
-      &__image img {
-        border-radius: 0;
-      }
-    }
-
-    &__bar {
-      position: relative;
-      margin-top: -80px;
-      display: flex;
-      justify-content: flex-start;
-
-      &::before {
-        content: "";
-        display: block;
-        background: lighten($ui-base-color, 4%);
-        position: absolute;
-        bottom: 0;
-        left: 0;
-        right: 0;
-        height: 60px;
-        border-radius: 0 0 4px 4px;
-        z-index: -1;
-      }
-
-      .avatar {
-        display: block;
-        width: 120px;
-        height: 120px;
-        padding-left: 20px - 4px;
-        flex: 0 0 auto;
-
-        img {
-          display: block;
-          width: 100%;
-          height: 100%;
-          margin: 0;
-          border-radius: 50%;
-          border: 4px solid lighten($ui-base-color, 4%);
-          background: darken($ui-base-color, 8%);
-        }
-      }
-
-      @media screen and (max-width: 600px) {
-        margin-top: 0;
-        background: lighten($ui-base-color, 4%);
-        border-radius: 0 0 4px 4px;
-        padding: 5px;
-
-        &::before {
-          display: none;
-        }
-
-        .avatar {
-          width: 48px;
-          height: 48px;
-          padding: 7px 0;
-          padding-left: 10px;
-
-          img {
-            border: 0;
-            border-radius: 4px;
-          }
-
-          @media screen and (max-width: 360px) {
-            display: none;
-          }
-        }
-      }
-
-      @media screen and (max-width: $no-gap-breakpoint) {
-        border-radius: 0;
-      }
-
-      @media screen and (max-width: $no-columns-breakpoint) {
-        flex-wrap: wrap;
-      }
-    }
-
-    &__tabs {
-      flex: 1 1 auto;
-      margin-left: 20px;
-
-      &__name {
-        padding-top: 20px;
-        padding-bottom: 8px;
-
-        h1 {
-          font-size: 20px;
-          line-height: 18px * 1.5;
-          color: $primary-text-color;
-          font-weight: 500;
-          overflow: hidden;
-          white-space: nowrap;
-          text-overflow: ellipsis;
-          text-shadow: 1px 1px 1px $base-shadow-color;
-
-          small {
-            display: block;
-            font-size: 14px;
-            color: $primary-text-color;
-            font-weight: 400;
-            overflow: hidden;
-            text-overflow: ellipsis;
-          }
-        }
-      }
-
-      @media screen and (max-width: 600px) {
-        margin-left: 15px;
-        display: flex;
-        justify-content: space-between;
-        align-items: center;
-
-        &__name {
-          padding-top: 0;
-          padding-bottom: 0;
-
-          h1 {
-            font-size: 16px;
-            line-height: 24px;
-            text-shadow: none;
-
-            small {
-              color: $darker-text-color;
-            }
-          }
-        }
-      }
-
-      &__tabs {
-        display: flex;
-        justify-content: flex-start;
-        align-items: stretch;
-        height: 58px;
-
-        .details-counters {
-          display: flex;
-          flex-direction: row;
-          min-width: 300px;
-        }
-
-        @media screen and (max-width: $no-columns-breakpoint) {
-          .details-counters {
-            display: none;
-          }
-        }
-
-        .counter {
-          min-width: 33.3%;
-          box-sizing: border-box;
-          flex: 0 0 auto;
-          color: $darker-text-color;
-          padding: 10px;
-          border-right: 1px solid lighten($ui-base-color, 4%);
-          cursor: default;
-          text-align: center;
-          position: relative;
-
-          a {
-            display: block;
-          }
-
-          &:last-child {
-            border-right: 0;
-          }
-
-          &::after {
-            display: block;
-            content: "";
-            position: absolute;
-            bottom: 0;
-            left: 0;
-            width: 100%;
-            border-bottom: 4px solid $ui-primary-color;
-            opacity: 0.5;
-            transition: all 400ms ease;
-          }
-
-          &.active {
-            &::after {
-              border-bottom: 4px solid $highlight-text-color;
-              opacity: 1;
-            }
-
-            &.inactive::after {
-              border-bottom-color: $secondary-text-color;
-            }
-          }
-
-          &:hover {
-            &::after {
-              opacity: 1;
-              transition-duration: 100ms;
-            }
-          }
-
-          a {
-            text-decoration: none;
-            color: inherit;
-          }
-
-          .counter-label {
-            font-size: 12px;
-            display: block;
-          }
-
-          .counter-number {
-            font-weight: 500;
-            font-size: 18px;
-            margin-bottom: 5px;
-            color: $primary-text-color;
-            font-family: $font-display, sans-serif;
-          }
-        }
-
-        .spacer {
-          flex: 1 1 auto;
-          height: 1px;
-        }
-
-        &__buttons {
-          padding: 7px 8px;
-        }
-      }
-    }
-
-    &__extra {
-      display: none;
-      margin-top: 4px;
-
-      .public-account-bio {
-        border-radius: 0;
-        box-shadow: none;
-        background: transparent;
-        margin: 0 -5px;
-
-        .account__header__fields {
-          border-top: 1px solid lighten($ui-base-color, 12%);
-        }
-
-        .roles {
-          display: none;
-        }
-      }
-
-      &__links {
-        margin-top: -15px;
-        font-size: 14px;
-        color: $darker-text-color;
-
-        a {
-          display: inline-block;
-          color: $darker-text-color;
-          text-decoration: none;
-          padding: 15px;
-          font-weight: 500;
-
-          strong {
-            font-weight: 700;
-            color: $primary-text-color;
-          }
-        }
-      }
-
-      @media screen and (max-width: $no-columns-breakpoint) {
-        display: block;
-        flex: 100%;
-      }
-    }
-  }
-
-  .account__section-headline {
-    border-radius: 4px 4px 0 0;
-
-    @media screen and (max-width: $no-gap-breakpoint) {
-      border-radius: 0;
-    }
-  }
-
-  .detailed-status__meta {
-    margin-top: 25px;
-  }
-
-  .public-account-bio {
-    background: lighten($ui-base-color, 8%);
-    box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
-    border-radius: 4px;
-    overflow: hidden;
-    margin-bottom: 10px;
-
-    @media screen and (max-width: $no-gap-breakpoint) {
-      box-shadow: none;
-      margin-bottom: 0;
-      border-radius: 0;
-    }
-
-    .account__header__fields {
-      margin: 0;
-      border-top: 0;
-
-      a {
-        color: $highlight-text-color;
-      }
-
-      dl:first-child .verified {
-        border-radius: 0 4px 0 0;
-      }
-
-      .verified a {
-        color: $valid-value-color;
-      }
-    }
-
-    .account__header__content {
-      padding: 20px;
-      padding-bottom: 0;
-      color: $primary-text-color;
-    }
-
-    &__extra,
-    .roles {
-      padding: 20px;
-      font-size: 14px;
-      color: $darker-text-color;
-    }
-
-    .roles {
-      padding-bottom: 0;
-    }
-  }
-
-  .directory__list {
-    display: grid;
-    grid-gap: 10px;
-    grid-template-columns: minmax(0, 50%) minmax(0, 50%);
-
-    .account-card {
-      display: flex;
-      flex-direction: column;
-    }
-
-    @media screen and (max-width: $no-gap-breakpoint) {
-      display: block;
-
-      .account-card {
-        margin-bottom: 10px;
-        display: block;
-      }
-    }
-  }
-
-  .card-grid {
-    display: flex;
-    flex-wrap: wrap;
-    min-width: 100%;
-    margin: 0 -5px;
-
-    & > div {
-      box-sizing: border-box;
-      flex: 1 0 auto;
-      width: 300px;
-      padding: 0 5px;
-      margin-bottom: 10px;
-      max-width: 33.333%;
-
-      @media screen and (max-width: 900px) {
-        max-width: 50%;
-      }
-
-      @media screen and (max-width: 600px) {
-        max-width: 100%;
-      }
-    }
-
-    @media screen and (max-width: $no-gap-breakpoint) {
-      margin: 0;
-      border-top: 1px solid lighten($ui-base-color, 8%);
-
-      & > div {
-        width: 100%;
-        padding: 0;
-        margin-bottom: 0;
-        border-bottom: 1px solid lighten($ui-base-color, 8%);
-
-        &:last-child {
-          border-bottom: 0;
-        }
-
-        .card__bar {
-          background: $ui-base-color;
-
-          &:hover,
-          &:active,
-          &:focus {
-            background: lighten($ui-base-color, 4%);
-          }
-        }
-      }
-    }
-  }
-}
diff --git a/app/javascript/styles/mastodon/footer.scss b/app/javascript/styles/mastodon/footer.scss
deleted file mode 100644
index 0c3e42033..000000000
--- a/app/javascript/styles/mastodon/footer.scss
+++ /dev/null
@@ -1,152 +0,0 @@
-.public-layout {
-  .footer {
-    text-align: left;
-    padding-top: 20px;
-    padding-bottom: 60px;
-    font-size: 12px;
-    color: lighten($ui-base-color, 34%);
-
-    @media screen and (max-width: $no-gap-breakpoint) {
-      padding-left: 20px;
-      padding-right: 20px;
-    }
-
-    .grid {
-      display: grid;
-      grid-gap: 10px;
-      grid-template-columns: 1fr 1fr 2fr 1fr 1fr;
-
-      .column-0 {
-        grid-column: 1;
-        grid-row: 1;
-        min-width: 0;
-      }
-
-      .column-1 {
-        grid-column: 2;
-        grid-row: 1;
-        min-width: 0;
-      }
-
-      .column-2 {
-        grid-column: 3;
-        grid-row: 1;
-        min-width: 0;
-        text-align: center;
-
-        h4 a {
-          color: lighten($ui-base-color, 34%);
-        }
-      }
-
-      .column-3 {
-        grid-column: 4;
-        grid-row: 1;
-        min-width: 0;
-      }
-
-      .column-4 {
-        grid-column: 5;
-        grid-row: 1;
-        min-width: 0;
-      }
-
-      @media screen and (max-width: 690px) {
-        grid-template-columns: 1fr 2fr 1fr;
-
-        .column-0,
-        .column-1 {
-          grid-column: 1;
-        }
-
-        .column-1 {
-          grid-row: 2;
-        }
-
-        .column-2 {
-          grid-column: 2;
-        }
-
-        .column-3,
-        .column-4 {
-          grid-column: 3;
-        }
-
-        .column-4 {
-          grid-row: 2;
-        }
-      }
-
-      @media screen and (max-width: 600px) {
-        .column-1 {
-          display: block;
-        }
-      }
-
-      @media screen and (max-width: $no-gap-breakpoint) {
-        .column-0,
-        .column-1,
-        .column-3,
-        .column-4 {
-          display: none;
-        }
-
-        .column-2 h4 {
-          display: none;
-        }
-      }
-    }
-
-    .legal-xs {
-      display: none;
-      text-align: center;
-      padding-top: 20px;
-
-      @media screen and (max-width: $no-gap-breakpoint) {
-        display: block;
-      }
-    }
-
-    h4 {
-      text-transform: uppercase;
-      font-weight: 700;
-      margin-bottom: 8px;
-      color: $darker-text-color;
-
-      a {
-        color: inherit;
-        text-decoration: none;
-      }
-    }
-
-    ul a,
-    .legal-xs a {
-      text-decoration: none;
-      color: lighten($ui-base-color, 34%);
-
-      &:hover,
-      &:active,
-      &:focus {
-        text-decoration: underline;
-      }
-    }
-
-    .brand {
-      .logo {
-        display: block;
-        height: 36px;
-        width: auto;
-        margin: 0 auto;
-        color: lighten($ui-base-color, 34%);
-      }
-
-      &:hover,
-      &:focus,
-      &:active {
-        .logo {
-          color: lighten($ui-base-color, 38%);
-        }
-      }
-    }
-  }
-}
diff --git a/app/javascript/styles/mastodon/rtl.scss b/app/javascript/styles/mastodon/rtl.scss
index 98eb1511c..ccec8e95e 100644
--- a/app/javascript/styles/mastodon/rtl.scss
+++ b/app/javascript/styles/mastodon/rtl.scss
@@ -53,16 +53,6 @@ body.rtl {
     right: -26px;
   }
 
-  .landing-page__logo {
-    margin-right: 0;
-    margin-left: 20px;
-  }
-
-  .landing-page .features-list .features-list__row .visual {
-    margin-left: 0;
-    margin-right: 15px;
-  }
-
   .column-link__icon,
   .column-header__icon {
     margin-right: 0;
@@ -350,44 +340,6 @@ body.rtl {
     margin-left: 45px;
   }
 
-  .landing-page .header-wrapper .mascot {
-    right: 60px;
-    left: auto;
-  }
-
-  .landing-page__call-to-action .row__information-board {
-    direction: rtl;
-  }
-
-  .landing-page .header .hero .floats .float-1 {
-    left: -120px;
-    right: auto;
-  }
-
-  .landing-page .header .hero .floats .float-2 {
-    left: 210px;
-    right: auto;
-  }
-
-  .landing-page .header .hero .floats .float-3 {
-    left: 110px;
-    right: auto;
-  }
-
-  .landing-page .header .links .brand img {
-    left: 0;
-  }
-
-  .landing-page .fa-external-link {
-    padding-right: 5px;
-    padding-left: 0 !important;
-  }
-
-  .landing-page .features #mastodon-timeline {
-    margin-right: 0;
-    margin-left: 30px;
-  }
-
   @media screen and (min-width: 631px) {
     .column,
     .drawer {
@@ -415,32 +367,6 @@ body.rtl {
     padding-right: 0;
   }
 
-  .public-layout {
-    .header {
-      .nav-button {
-        margin-left: 8px;
-        margin-right: 0;
-      }
-    }
-
-    .public-account-header__tabs {
-      margin-left: 0;
-      margin-right: 20px;
-    }
-  }
-
-  .landing-page__information {
-    .account__display-name {
-      margin-right: 0;
-      margin-left: 5px;
-    }
-
-    .account__avatar-wrapper {
-      margin-left: 12px;
-      margin-right: 0;
-    }
-  }
-
   .card__bar .display-name {
     margin-left: 0;
     margin-right: 15px;
diff --git a/app/javascript/styles/mastodon/statuses.scss b/app/javascript/styles/mastodon/statuses.scss
index a3237a630..ce71d11e4 100644
--- a/app/javascript/styles/mastodon/statuses.scss
+++ b/app/javascript/styles/mastodon/statuses.scss
@@ -137,8 +137,7 @@ a.button.logo-button {
   justify-content: center;
 }
 
-.embed,
-.public-layout {
+.embed {
   .status__content[data-spoiler="folded"] {
     .e-content {
       display: none;