diff --git a/DESIGN.html b/DESIGN.html
new file mode 100644
index 000000000..15e9a47ba
--- /dev/null
+++ b/DESIGN.html
@@ -0,0 +1,182 @@
+
+
+
+
+ Invidious UI refinement
+ Approved dark-theme reference for shared navigation, channel identity, contained video cards, and compact authentication. The source of truth for behaviour is DESIGN.md.
+
+ Dark theme tokens
+
+
+
Light-theme pairings
+
+
+
+ Spacing: --redesign-space-1 8 px, --redesign-space-2 12 px, --redesign-space-3 16 px, --redesign-space-4 24 px. Card surfaces use an 8 px radius and the shared 1 px / 2 px edge shadow.
+
+ Wide search results
+
+ INVIDIOUS Search
Preferences Log in
+
+
+
+ Theo - t3.gg✓ @t3dotgg · 564K subscribers
Software development, AI, and TypeScript videos. Select the channel to browse its videos.
+
Theo Von @TheoVon · 4.7M subscribers
Search results
+
+
28:36
Stop Pretending You Understand Your Codebase
Theo - t3.gg
163K views
3 days ago Quick actions
+
49:22
You’re using AI agents wrong
Theo - t3.gg
163K views
3 days ago Quick actions
+
1:16:52
Fable Vs Astra Debate Is Over
Theo - t3.gg
163K views
3 days ago Quick actions
+
+
+
+
+ Account disclosure
+ ♧ N nr
Preferences
Light mode
Dark mode
Log out
+ Local initial avatar or generic person icon when the nickname is hidden. Native disclosure works without scripts. Actual notification and menu actions use the existing icon family.
+ Quiet login, CAPTCHA, and focus
+
+ Focus is a 3 px blue outline with a 3 px offset. Controls retain native semantics in the app; this page is visual evidence only.
+
+ Narrow composition
+
+
+
Theo - t3.gg✓ @t3dotgg 564K subscribers
Search results
28:36
Stop Pretending You Understand Your Codebase
Theo - t3.gg
163K views
3 days ago Quick actions
+
+ Search relationships and navigation
+ Channel matches appear together in a scrollable top row; the continuous media grid follows below. A channel never labels unrelated videos. Channel pages use horizontal content tabs and a compact sort row; account controls reserve space and search uses an icon disclosure below 600px.
+ Search results Next page ›
Stop Pretending You Understand Your Codebase
Theo - t3.gg
Bishop Robert Barron
Theo Von
+ Watch composition and player behavior
+
+
+
▶
You're using AI agents wrong ▶ 12:35 / 49:21 1× ▭ ⛶
Theo - t3.gg ✓ Subscribe | 564K
163K views Audio mode ▶ Share Invidious URL · YouTube URL
↓ Download Existing formats and native download form.
More Genre, license and remaining metadata.
+
Fable Vs Astra Debate Is Over
Theo - t3.gg · 41K views
+
+
+ Theater mode is the default and expands the same video above the related rail. Below 900 px, related videos follow the main content. The visible seek track has its own row at every width, with theater beside fullscreen. Clip start/end markers remain functional but are visually hidden so the blue progress rail is the only position signal.
+ Player actions use existing Video.js icons and accessible names; time and speed remain text. With focus inside the player or on Play, J/L seek ten seconds, K and Space tap toggle playback, and Space or mouse holds temporarily play at 2× before restoring the prior rate and paused state. Enhancements remain optional.
+
+
+
diff --git a/DESIGN.md b/DESIGN.md
new file mode 100644
index 000000000..16e0bd077
--- /dev/null
+++ b/DESIGN.md
@@ -0,0 +1,195 @@
+# Invidious UI refinement
+
+## Purpose
+
+The primary user is someone who wants to search and browse YouTube privately,
+then sign in only when saved preferences or subscriptions need an account. The
+interface is used in wide desktop browsing sessions and narrow touch sessions.
+It remains server-rendered and usable with JavaScript disabled.
+
+The approved direction is the refined proposal: B's distinct channel treatment
+and contained video cards, paired with a compact account form. Search results
+should scan as media destinations, while a channel remains visibly different
+from a video result. Existing search filters, saved home/feed preferences,
+localization, thin mode, theme choice, authentication, CAPTCHA, and all
+existing links/forms retain their behavior.
+
+## Tokens
+
+The implementation exposes the following values in `assets/css/redesign.css`.
+They are semantic roles, not a new user preference. `.light-theme`,
+`.dark-theme`, and the system-controlled `.no-theme` each assign the same
+roles. Client-side theme changes must retain the structural `redesign-ui` body
+class while replacing only the theme class.
+
+| Role | Light | Dark | Use |
+| --- | --- | --- | --- |
+| `--redesign-canvas` | `#f7f8fa` | `#0b0c0e` | Page background |
+| `--redesign-surface` | `#ffffff` | `#15161a` | Media cards |
+| `--redesign-control` | `#fbfcfd` | `#111216` | Search and text inputs |
+| `--redesign-text` | `#17181b` | `#f4f4f5` | Primary text and titles |
+| `--redesign-muted` | `#656a73` | `#a9abb1` | Metadata and quiet navigation |
+| `--redesign-line` | `#d9dce2` | `#303239` | Stable boundaries |
+| `--redesign-accent` | `#255fbe` | `#83b5fc` | Links and primary submit action |
+| `--redesign-accent-hover` | `#174a9f` | `#b2d0ff` | Link and submit hover/focus state |
+| `--redesign-on-accent` | `#ffffff` | `#121315` | Submit-action foreground |
+| `--redesign-focus` | `#0b6ece` | `#83b5fc` | 3 px keyboard focus outline |
+| `--redesign-radius` | `8px` | `8px` | Results and form surfaces |
+| `--redesign-control-radius` | `6px` | `6px` | Inputs and compact controls |
+| `--redesign-shadow` | `0 1px 2px rgb(15 23 42 / 0.08)` | `0 1px 2px rgb(0 0 0 / 0.38)` | Card edge separation only |
+
+The typeface remains the project’s existing system stack. Results use 16 px,
+650-weight titles at a 1.32 line-height; channel names use 22 px at 1.3;
+metadata uses 13–14 px and stays readable in both themes. The spacing scale is
+`--redesign-space-1` = 8 px, `--redesign-space-2` = 12 px,
+`--redesign-space-3` = 16 px, and `--redesign-space-4` = 24 px.
+
+## Layout and components
+
+- The navigation bar has a 64 px minimum height, a border separating it from
+ content, and a single clear search field. Search stays in the header row; below 600px a native icon disclosure opens the field.
+- Search channel matches occupy their own horizontally scrollable row above
+ the continuous media grid. Each match keeps its avatar, linked identity,
+ metadata and description. Channels never act as headings for unrelated
+ video results; selecting a channel follows its existing channel link.
+- Videos and playlists are contained cards with a 16:9 thumbnail, then title,
+ author and metadata. They use two columns from 768 px and three from 1100 px;
+ under 768 px each card is full width. The thumbnail’s duration and existing
+ action controls remain in their established positions.
+- The login form is at most 352 px wide, sits directly on the canvas without an outer card, has persistent labels, native inputs, and
+ one full-width submit action. Existing server validation and CAPTCHA
+ rendering remain in the same form flow. The heading-to-field gap is 24 px; the page fills the viewport and its footer follows the flexible main area near the bottom.
+
+There are only two raised surface types: media cards and the expanded
+filter panel. Each has a one-pixel boundary plus the same restrained shadow;
+the page, navigation, and footer remain on the base plane.
+
+The watch-layout layer consumes the same theme through `--watch-border`,
+`--watch-panel`, `--watch-muted`, and `--watch-focus` aliases. It owns the
+watch composition and player controls; the shared stylesheet only supplies the
+common color roles.
+
+## Access and adaptation
+
+All existing links, buttons, checkbox/radio controls, labels, forms, and
+server-side errors retain their native semantics. A skip link targets the main
+content. Keyboard focus uses the `--redesign-focus` outline with a 3 px offset;
+focus is never indicated by color alone. Controls remain at least 36–44 px in
+their compact contexts, and the account submit/input controls are 44 px high.
+
+Long translated titles and channel names wrap; no title or metadata is clamped.
+The dark, light, and system theme roles are explicit. Reduced-motion users do
+not receive new animated effects. Thin mode retains its placeholders and does
+not request thumbnails.
+
+## Evidence and open questions
+
+`DESIGN.html` renders the token values, wide/narrow card compositions, focus,
+the channel distinction, and login/CAPTCHA state using the same rules. The
+application build and browser checks are recorded by the coordinating agent.
+There are no unresolved visual decisions in this approved scope.
+
+## Watch page and optional player enhancements
+
+The accepted A watch composition places the player beside a compact related
+rail, with the title, channel, compact action row, description and comments
+beneath the player. The native theater checkbox expands the same video across
+the grid; it preserves playback and also works without scripts. Below 900 px,
+related videos follow the main content. All stream/source and download links
+retain their existing behavior.
+
+Player actions retain Video.js's familiar icons and accessible names. Time and
+speed remain text. All players put a visible 4px seek track on its own row above icon controls; the duplicate remaining-time display is hidden to conserve space.
+Only while focus is inside the player, J/L seek exactly ten seconds; K and a Space tap toggle playback. Holding Space
+or the left mouse button on the video for 350 ms temporarily plays at exactly
+2×, then restores the prior speed and paused state. Editable fields, menus,
+controls and modified shortcuts are excluded. Holds never save a temporary
+speed preference. Blur/cancel restores state. The post-hold mouseup and click
+are consumed because Video.js toggles playback on mouseup.
+
+## Runtime verification criterion
+
+The actual application must retain the design after scripts initialize and
+when themes change. Verify rendered desktop and narrow login/search/watch
+pages, real media playback, hold release, theater continuity, and the native
+no-JavaScript flow. Static screenshots and mocked gesture tests alone cannot
+prove these behaviors. This is project guidance proposed by the user's runtime
+correction; it does not modify shared Fleet guidance.
+
+## Channel and feed navigation refinement
+
+Channel content tabs and sort links form a horizontal toolbar; utility links
+remain separate and quiet. Subscribe and RSS retain their existing actions.
+The signed-in header reserves intrinsic width for account controls, uses native
+logout button semantics. Search stays in the header and becomes an icon below 600px.
+Subscription feeds have a clear title, management/history/RSS actions and an
+empty state linking to subscription management. Saved feed choices remain
+unchanged. On narrow screens controls wrap rather than collide.
+
+The search results heading and top pagination share one row, with equal vertical
+centers and outer edges aligned to the media cards. Pagination wraps within its
+available space on narrow screens; card and channel geometry remain unchanged.
+
+## Account disclosure and card metadata
+
+Signed-in navigation shows the existing notification bell and a circular local
+avatar. An initial is displayed only when show_nick is enabled; otherwise a
+generic person icon preserves that privacy preference. A native details/summary
+disclosure exposes the name, Preferences and CSRF-protected POST
+logout. It works without JavaScript; optional script adds Escape, outside-click
+and focus-out dismissal. No remote profile image or avatar service is used.
+
+Video cards place title first, channel and views on the second row, date and
+existing quick actions on the third. Existing verified badges use bright #3ea6ff in dark mode and #0878d1 in light mode, a .2em inline gap and -.08em baseline adjustment; no verification statuses are added or inferred.
+
+Header avatars are 32px within 40px hit areas; the bell is approximately 22px.
+Filter disclosure has horizontal padding, and card action links center their
+glyphs alongside the date text. Theme choices set the requested mode explicitly
+on both client and server; repeated selection never reverses the mode.
+
+Theater mode sits beside fullscreen in the enhanced player and has an explicit
+text label in the no-JavaScript fallback. Storyboard URLs preserve root-relative
+paths; previews show one timestamp and clamp to player edges. The timeline has
+a neutral track, lighter buffered range and bright blue progress.
+
+Watch actions share a compact row: view/like counts on the left; Share, Download and More on the right. More holds audio-only mode, source/embed/instance links, annotations and metadata. Native disclosures retain download
+formats, playlist forms and technical metadata, wrapping on narrow screens.
+Subscribe is red (#d92332) with white text; subscribed state stays neutral. Channel verification marks stay bright blue; only comment verification is white. All keyboard handlers require focus
+inside the player; search, page actions and outside clicks release shortcuts.
+
+Player follow-up: the large play control is centered. Play-button focus accepts
+shortcuts; external inputs remain excluded. Fullscreen clears fluid aspect-ratio
+padding, captions reserve 68px above visible controls, and caption menus use
+readable padded rows. Share is only below the video, with Invidious/YouTube URL
+choices and optional clipboard buttons; native links work without JavaScript.
+Action menus dismiss on outside click or Escape, and only one sibling stays
+open. Header bottom padding is 4px with no divider. Related titles use primary
+text, with muted channel/views and consistent thumbnail geometry.
+
+Theater is the default watch layout, including without JavaScript; the player
+button returns to the split layout. Light and Dark icon controls remain visible beside the avatar; Preferences stays inside its menu.
+
+Final refinement: Audio mode and Watch on YouTube are quick actions alongside
+Share, Download and More. Instance/embed/annotation links are hidden; More holds
+remaining metadata. Menus have bounded scrollable height. Comment avatars are
+36px with consistent author/body/metadata/reply spacing. Cards align metadata
+rows and avoid inherited paragraph margins. Player corners are 12px, with a
+12px gap below navigation. Light mode strengthens muted text and surface borders.
+
+Embedded-fullscreen recovery: when the browser leaves native fullscreen pending
+for 700ms, reuse Video.js full-window mode; F/button and Escape exit preserve
+the same player and video. Regular browsers continue using native fullscreen.
+
+The watch title tops out at 25px to retain hierarchy without competing with the
+player. Watch on YouTube is a 36px icon action with a localized accessible name
+and native tooltip. Start/end clip markers continue controlling playback but are
+visually hidden because the blue progress rail already communicates position.
+The unused Video.js share plugin is excluded; sharing remains in the watch action
+row through native links and the optional copy enhancement.
+
+The watch title tops out at 25px to retain hierarchy without competing with the
+player. Watch on YouTube is a 36px icon action with a localized accessible name
+and native tooltip. Start/end clip markers continue controlling playback but are
+visually hidden because the blue progress rail already communicates position.
+The unused Video.js share plugin is excluded; sharing remains in the watch action
+row through native links and the optional copy enhancement.
diff --git a/assets/css/player.css b/assets/css/player.css
index d95549ac7..828372c83 100644
--- a/assets/css/player.css
+++ b/assets/css/player.css
@@ -116,10 +116,6 @@ ul.vjs-menu-content::-webkit-scrollbar {
order: 5;
}
-.vjs-share-control {
- order: 6;
-}
-
.vjs-fullscreen-control {
order: 7;
}
@@ -253,14 +249,139 @@ video.video-js {
top: 1.5em;
}
-@media screen and (max-width: 700px) {
- .video-js .vjs-share {
- justify-content: unset;
- }
-}
-
@media screen and (max-width: 650px) {
.vjs-modal-dialog-content {
overflow-x: hidden;
}
}
+
+/* Familiar icon controls, with readable time/speed and native accessible labels. */
+.video-js .vjs-control-bar {
+ background: #101114;
+ min-height: 3.6em;
+}
+.video-js .vjs-control:focus-visible,
+.video-js .vjs-menu-item:focus-visible {
+ outline: 2px solid #9ac2fc;
+ outline-offset: -2px;
+}
+.video-js .vjs-play-progress,
+.video-js.player-style-invidious .vjs-play-progress {
+ background: #9ac2fc;
+}
+.video-js .vjs-big-play-button {
+ background: rgba(8, 9, 11, .9);
+ border: 0;
+ border-radius: 8px;
+}
+.video-js .vjs-poster {
+ background-size: contain;
+ object-fit: contain;
+}
+.video-js .speed-hold-indicator {
+ display: none;
+ position: absolute;
+ top: 20px;
+ left: 50%;
+ transform: translateX(-50%);
+ padding: 6px 14px;
+ border-radius: 5px;
+ background: rgba(8, 9, 11, .9);
+ color: #fff;
+ font: 600 16px/1.4 system-ui, sans-serif;
+ pointer-events: none;
+}
+.video-js.vjs-speed-hold .speed-hold-indicator { display: block; }
+
+/* One visible timeline above a consistent icon row in both player styles. */
+.video-js .vjs-control-bar,
+.video-js.player-style-youtube .vjs-control-bar {
+ height: 5.8em; min-height: 5.8em; padding: 0 8px;
+ flex-wrap: wrap; align-items: center; background: rgba(12, 13, 16, .96);
+}
+.video-js .vjs-progress-control,
+.video-js.player-style-youtube .vjs-progress-control {
+ position: relative; inset: auto; flex: 1 0 100%; order: -1;
+ width: 100%; height: 1.8em; min-height: 1.8em; margin: 0; font-size: 10px;
+}
+.video-js .vjs-progress-control .vjs-progress-holder,
+.video-js.player-style-youtube .vjs-progress-control .vjs-progress-holder {
+ position: relative; inset: auto; width: auto; margin: 0 4px; height: 4px;
+ font-size: 10px; background: #62646a; border-radius: 2px;
+}
+.video-js .vjs-load-progress, .video-js .vjs-load-progress div { background: #a2a4aa; }
+.video-js .vjs-play-progress, .video-js.player-style-youtube .vjs-play-progress { background: #3ea6ff; }
+.video-js .vjs-play-progress::before, .video-js.player-style-youtube .vjs-play-progress::before {
+ content: ''; display: block; position: absolute; right: -5px; top: -3px;
+ width: 10px; height: 10px; background: #fff; border-radius: 50%;
+}
+.video-js .vjs-marker { display: none !important; }
+.video-js .vjs-play-progress .vjs-time-tooltip { display: none; }
+.video-js .vjs-vtt-thumbnail-display {
+ bottom: calc(100% + 24px); left: 0; border-radius: 4px;
+ background-color: #17181c; transition: none;
+}
+.video-js .vjs-vtt-thumbnail-display::after {
+ content: attr(data-time); position: absolute; top: 100%; left: 0; right: 0;
+ padding: 4px; color: white; background: #17181c; text-align: center;
+ font: 12px/16px system-ui, sans-serif; border-radius: 0 0 4px 4px;
+}
+.video-js .vjs-control-bar > .vjs-control:not(.vjs-progress-control) { height: 4em; }
+.video-js .vjs-control-bar > .vjs-button, .video-js .vjs-control-bar > .vjs-menu-button { width: 3.6em; flex-shrink: 0; }
+.video-js .vjs-button > .vjs-icon-placeholder::before { line-height: 2.22; }
+.video-js .vjs-time-control { line-height: 4em; padding-inline: .35em; }
+.video-js .vjs-playback-rate-value { font-size: 1.3em; line-height: 3.08; }
+.video-js .vjs-remaining-time { display: none; }
+.video-js .vjs-control-bar > .vjs-spacer { display: block; flex: 1; order: 1; }
+.video-js .vjs-theater-control { order: 6; }
+.video-js .vjs-theater-control .vjs-icon-placeholder {
+ display: block; width: 18px; height: 12px; border: 2px solid currentColor;
+ border-radius: 2px; margin: auto; box-sizing: border-box;
+}
+.video-js .vjs-theater-control[aria-pressed="true"] .vjs-icon-placeholder { border-bottom-width: 4px; }
+@media screen and (max-width: 600px) {
+ .video-js .vjs-control-bar > .vjs-button, .video-js .vjs-control-bar > .vjs-menu-button { width: 2.8em; }
+ .video-js .vjs-control-bar { padding-inline: 4px; }
+ .video-js .vjs-volume-panel { width: 2.8em; }
+ .video-js .vjs-volume-panel .vjs-volume-control { display: none; }
+}
+
+@media screen and (max-width: 600px) {
+ .video-js .vjs-time-control { font-size: 10px; min-width: 0; }
+}
+
+.video-js .vjs-big-play-button, .video-js.player-style-youtube .vjs-big-play-button {
+ top: 50%; left: 50%; margin: 0; transform: translate(-50%, -50%);
+ width: 2.4em; height: 1.6em; line-height: 1.6em;
+}
+
+/* Captions reserve space for the visible two-row control bar. */
+.video-js.vjs-user-active .vjs-text-track-display,
+.video-js.vjs-paused .vjs-text-track-display { bottom: 68px; }
+.video-js .vjs-text-track-display > div > div > div {
+ padding: 2px 5px !important; border-radius: 3px !important; line-height: 1.3 !important;
+}
+.video-js .vjs-menu-button-popup .vjs-menu,
+.video-js.player-style-youtube .vjs-menu-button-popup .vjs-menu {
+ width: min(240px, 72vw); left: auto; right: 0; bottom: 4em; margin: 0; padding: 0;
+}
+.video-js .vjs-menu-button-popup .vjs-menu .vjs-menu-content {
+ box-sizing: border-box; padding: 6px; max-height: min(240px, 35vh);
+ background: #17191e; color: #f4f4f5; border: 1px solid #3d414b;
+ border-radius: 6px; box-shadow: 0 6px 18px #0005;
+}
+.video-js .vjs-menu li { font-size: 13px; line-height: 1.4; padding: 8px 10px; text-align: left; text-transform: none; border-radius: 3px; }
+.video-js .vjs-menu li.vjs-menu-item:hover, .video-js .vjs-menu li.vjs-menu-item:focus { background: #2b303a; color: #fff; text-shadow: none; }
+.video-js .vjs-menu li.vjs-selected { background: #263a54; color: #a8d1ff; }
+.video-js .vjs-text-track-settings { color: #f4f4f5; background: #17191e; }
+.video-js .vjs-text-track-settings .vjs-modal-dialog-content { padding: 20px; overflow: auto; }
+.video-js .vjs-text-track-settings fieldset { margin-bottom: 12px; }
+.video-js .vjs-text-track-settings select { color: white; background: #22262e; border: 1px solid #535965; border-radius: 4px; padding: 5px; }
+.video-js .vjs-text-track-settings button { border-radius: 4px; padding: 6px 12px; }
+.watch-page .video-js.vjs-fullscreen, .watch-page .player-dimensions.vjs-fluid.vjs-fullscreen {
+ padding-top: 0 !important; height: 100% !important; width: 100% !important; max-height: none;
+}
+
+@media screen and (max-width: 600px) {
+ .video-js .vjs-captions-button .vjs-menu { width: min(220px, 52vw); }
+}
diff --git a/assets/css/redesign.css b/assets/css/redesign.css
new file mode 100644
index 000000000..96081418c
--- /dev/null
+++ b/assets/css/redesign.css
@@ -0,0 +1,912 @@
+/*
+ * Approved UI refinement
+ *
+ * The variables below describe the shared media-browser treatment. They are
+ * deliberately scoped to `.redesign-ui` so the established theme preference
+ * continues to control the appearance rather than being replaced by a new
+ * theme setting.
+ */
+
+body.redesign-ui {
+ --redesign-canvas: #f7f8fa;
+ --redesign-surface: #ffffff;
+ --redesign-control: #fbfcfd;
+ --redesign-text: #17181b;
+ --redesign-muted: #656a73;
+ --redesign-line: #d9dce2;
+ --redesign-accent: #255fbe;
+ --redesign-accent-hover: #174a9f;
+ --redesign-on-accent: #ffffff;
+ --redesign-focus: #0b6ece;
+ --redesign-radius: 8px;
+ --redesign-control-radius: 6px;
+ --redesign-space-1: 0.5rem;
+ --redesign-space-2: 0.75rem;
+ --redesign-space-3: 1rem;
+ --redesign-space-4: 1.5rem;
+ --redesign-shadow: 0 1px 2px rgb(15 23 42 / 0.08);
+
+ background: var(--redesign-canvas);
+ color: var(--redesign-text);
+}
+
+.redesign-ui.dark-theme {
+ --redesign-canvas: #0b0c0e;
+ --redesign-surface: #15161a;
+ --redesign-control: #111216;
+ --redesign-text: #f4f4f5;
+ --redesign-muted: #a9abb1;
+ --redesign-line: #303239;
+ --redesign-accent: #83b5fc;
+ --redesign-accent-hover: #b2d0ff;
+ --redesign-on-accent: #121315;
+ --redesign-focus: #83b5fc;
+ --redesign-shadow: 0 1px 2px rgb(0 0 0 / 0.38);
+}
+
+@media (prefers-color-scheme: dark) {
+ .redesign-ui.no-theme {
+ --redesign-canvas: #0b0c0e;
+ --redesign-surface: #15161a;
+ --redesign-control: #111216;
+ --redesign-text: #f4f4f5;
+ --redesign-muted: #a9abb1;
+ --redesign-line: #303239;
+ --redesign-accent: #83b5fc;
+ --redesign-accent-hover: #b2d0ff;
+ --redesign-on-accent: #121315;
+ --redesign-focus: #83b5fc;
+ --redesign-shadow: 0 1px 2px rgb(0 0 0 / 0.38);
+ }
+}
+
+.redesign-ui a,
+.redesign-ui .simulated_a {
+ color: var(--redesign-accent);
+}
+
+.redesign-ui a:hover,
+.redesign-ui a:active,
+.redesign-ui .simulated_a:hover,
+.redesign-ui .simulated_a:active {
+ color: var(--redesign-accent-hover) !important;
+}
+
+.redesign-ui :focus-visible {
+ outline: 3px solid var(--redesign-focus);
+ outline-offset: 3px;
+}
+
+.redesign-skip-link {
+ background: var(--redesign-surface);
+ border: 1px solid var(--redesign-line);
+ border-radius: var(--redesign-control-radius);
+ color: var(--redesign-accent);
+ left: var(--redesign-space-3);
+ padding: var(--redesign-space-2) var(--redesign-space-3);
+ position: fixed;
+ top: var(--redesign-space-3);
+ transform: translateY(-200%);
+ z-index: 1000;
+}
+
+.redesign-skip-link:focus {
+ transform: translateY(0);
+}
+
+.redesign-main {
+ min-width: 0;
+}
+
+/* `watch-layout.css` owns the watch composition. These aliases let that
+ * layout consume the shared theme roles without introducing a competing
+ * player palette. */
+.redesign-ui .watch-page {
+ --watch-border: var(--redesign-line);
+ --watch-panel: var(--redesign-surface);
+ --watch-muted: var(--redesign-muted);
+ --watch-focus: var(--redesign-focus);
+}
+
+.redesign-ui .redesign-navbar {
+ align-items: center;
+ border-bottom: 1px solid var(--redesign-line);
+ margin: 0;
+ min-height: 4rem;
+ padding-bottom: var(--redesign-space-2);
+ padding-top: var(--redesign-space-2);
+}
+
+.redesign-ui .redesign-navbar .index-link {
+ color: var(--redesign-text);
+ font-size: 1rem;
+ font-weight: 700;
+ letter-spacing: -0.025em;
+}
+
+.redesign-ui .redesign-navbar .searchbar .pure-form {
+ align-items: center;
+ background: var(--redesign-control);
+ border: 1px solid var(--redesign-line);
+ border-radius: var(--redesign-control-radius);
+ min-height: 2.625rem;
+ padding: 0 0.25rem 0 0.625rem;
+}
+
+.redesign-ui .redesign-navbar .searchbar input[type="search"] {
+ background: transparent;
+ border: 0;
+ border-radius: 0;
+ color: var(--redesign-text);
+ font: inherit;
+ margin: 0;
+ min-height: 2.375rem;
+ padding: 0.5rem 0;
+}
+
+.redesign-ui .redesign-navbar .searchbar input[type="search"]:focus {
+ border: 0;
+ margin: 0;
+}
+
+.redesign-ui .redesign-navbar #searchbutton {
+ border-radius: var(--redesign-control-radius);
+ color: var(--redesign-muted);
+ min-height: 2.25rem;
+ min-width: 2.25rem;
+}
+
+.redesign-ui .redesign-navbar #searchbutton:hover,
+.redesign-ui .redesign-navbar #searchbutton:focus-visible {
+ color: var(--redesign-accent) !important;
+}
+
+.redesign-ui .redesign-navbar .user-field {
+ color: var(--redesign-muted);
+ gap: var(--redesign-space-3);
+}
+
+.redesign-ui .redesign-navbar .user-field div:not(:last-child) {
+ margin-right: 0;
+}
+
+.redesign-ui .redesign-navbar .user-field a,
+.redesign-ui .redesign-navbar .user-field input[type="submit"] {
+ color: var(--redesign-muted);
+ font-size: 0.9375rem;
+}
+
+.redesign-ui .redesign-banner h3 {
+ border-bottom: 1px solid var(--redesign-line);
+ font-size: 1rem;
+ margin: var(--redesign-space-3) 0 0;
+ padding-bottom: var(--redesign-space-3);
+}
+
+/* Search filters retain their form and native controls while using the shared
+ * page rhythm and theme roles. */
+.redesign-search-page {
+ padding: var(--redesign-space-3) 0 var(--redesign-space-4);
+}
+
+.redesign-search-page > hr {
+ border: 0;
+ border-top: 1px solid var(--redesign-line);
+ margin: 0 var(--redesign-space-3) var(--redesign-space-4);
+}
+
+.redesign-search-page #filters-collapse summary {
+ color: var(--redesign-text);
+ font-size: 1rem;
+ font-weight: 600;
+ margin: 0 var(--redesign-space-3) var(--redesign-space-2);
+ padding: var(--redesign-space-2) 0;
+}
+
+.redesign-search-page #filters-collapse summary::before {
+ background: var(--redesign-surface);
+ border: 1px solid var(--redesign-line);
+ border-radius: var(--redesign-control-radius);
+ color: var(--redesign-muted);
+ font-weight: 400;
+}
+
+.redesign-search-page #filters-box {
+ background: var(--redesign-surface);
+ border: 1px solid var(--redesign-line);
+ border-radius: var(--redesign-radius);
+ box-shadow: var(--redesign-shadow);
+ margin: var(--redesign-space-2) var(--redesign-space-3) var(--redesign-space-4);
+ padding: var(--redesign-space-2) var(--redesign-space-3) var(--redesign-space-3);
+}
+
+.redesign-search-page .filter-name {
+ border-bottom-color: var(--redesign-line);
+ color: var(--redesign-text);
+}
+
+.redesign-search-page .filter-options,
+.redesign-search-page .filter-options label {
+ color: var(--redesign-muted);
+}
+
+.redesign-search-page .no-results-error {
+ background: var(--redesign-surface);
+ border: 1px solid var(--redesign-line);
+ border-radius: var(--redesign-radius);
+ box-shadow: var(--redesign-shadow);
+ margin: var(--redesign-space-4) auto;
+ max-width: 42rem;
+ padding-bottom: 4rem;
+}
+
+/* Result cards */
+.redesign-item {
+ box-sizing: border-box;
+ padding: var(--redesign-space-2);
+}
+
+.redesign-item-card {
+ background: var(--redesign-surface);
+ border: 1px solid var(--redesign-line);
+ border-radius: var(--redesign-radius);
+ box-shadow: var(--redesign-shadow);
+ box-sizing: border-box;
+ color: var(--redesign-text);
+}
+
+.redesign-video-result .redesign-item-card,
+.redesign-collection-result .redesign-item-card {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ overflow: hidden;
+}
+
+.redesign-video-result .thumbnail,
+.redesign-collection-result .thumbnail {
+ background: var(--redesign-control);
+ border-radius: 0;
+ flex: 0 0 auto;
+}
+
+.redesign-video-result .thumbnail-placeholder,
+.redesign-collection-result .thumbnail-placeholder {
+ background: var(--redesign-control);
+ min-height: 8rem;
+}
+
+.redesign-ui .redesign-video-result .length,
+.redesign-ui .redesign-collection-result .length {
+ background: rgb(8 8 8 / 0.9) !important;
+ color: #ffffff;
+ font-size: 0.8125rem;
+ font-weight: 600;
+ padding: 0.125rem 0.3125rem;
+}
+
+.redesign-video-result .video-card-row,
+.redesign-collection-result .video-card-row {
+ margin: 0;
+ padding-left: var(--redesign-space-3);
+ padding-right: var(--redesign-space-3);
+}
+
+.redesign-video-result .redesign-item-title,
+.redesign-collection-result .redesign-item-title {
+ padding-top: var(--redesign-space-3);
+}
+
+.redesign-item-title p {
+ color: var(--redesign-text);
+ font-size: 1rem;
+ font-weight: 650;
+ line-height: 1.32;
+ margin: 0;
+}
+
+.redesign-item-title a {
+ color: var(--redesign-text);
+ text-decoration: none;
+}
+
+.redesign-item-title a:hover,
+.redesign-item-title a:focus-visible {
+ color: var(--redesign-accent) !important;
+ text-decoration: underline;
+}
+
+.redesign-video-result .redesign-item-author,
+.redesign-collection-result .redesign-item-author {
+ margin-top: var(--redesign-space-1);
+}
+
+.redesign-video-result .channel-name,
+.redesign-collection-result .channel-name {
+ color: var(--redesign-muted);
+ font-size: 0.875rem;
+}
+
+.redesign-video-result .redesign-item-meta,
+.redesign-collection-result .redesign-item-meta {
+ color: var(--redesign-muted);
+ margin-top: var(--redesign-space-1);
+ padding-bottom: var(--redesign-space-3);
+}
+
+.redesign-video-result .video-data,
+.redesign-collection-result .video-data {
+ color: var(--redesign-muted);
+ font-size: 0.8125rem;
+ font-weight: 400;
+}
+
+.redesign-video-result .icon-buttons,
+.redesign-collection-result .icon-buttons {
+ display: flex;
+ gap: var(--redesign-space-2);
+}
+
+.redesign-video-result .icon-buttons a,
+.redesign-collection-result .icon-buttons a {
+ color: var(--redesign-muted);
+ min-height: 2rem;
+ min-width: 2rem;
+ text-align: center;
+}
+
+/* A channel carries a different relationship from a video. It spans the
+ * results grid and uses its own compact identity block instead of another
+ * media card. */
+.redesign-channel-result {
+ width: 100%;
+}
+
+.redesign-channel-result .redesign-item-card {
+ padding: var(--redesign-space-4);
+}
+
+.redesign-channel-result__identity {
+ align-items: center;
+ display: flex;
+ gap: 1.25rem;
+}
+
+.redesign-channel-result__avatar-link {
+ display: block;
+ flex: 0 0 auto;
+}
+
+.redesign-channel-result__avatar {
+ background: var(--redesign-control);
+ border-radius: 50%;
+ display: block;
+ height: 4.5rem;
+ object-fit: cover;
+ width: 4.5rem;
+}
+
+.redesign-channel-result__body {
+ min-width: 0;
+}
+
+.redesign-channel-result__name {
+ color: var(--redesign-text);
+ font-size: 1.375rem;
+ font-weight: 650;
+ line-height: 1.3;
+ margin: 0;
+}
+
+.redesign-channel-result__metadata {
+ color: var(--redesign-muted);
+ display: flex;
+ flex-wrap: wrap;
+ font-size: 0.875rem;
+ gap: 0.25rem 0.5rem;
+ margin-top: 0.25rem;
+}
+
+.redesign-channel-result__metadata > span:not(:first-child)::before {
+ content: "·";
+ margin-right: 0.5rem;
+}
+
+.redesign-channel-result__description {
+ color: var(--redesign-muted);
+ font-size: 0.9375rem;
+ line-height: 1.45;
+ margin-top: var(--redesign-space-2);
+ max-width: 46rem;
+}
+
+.redesign-channel-result__description > :first-child {
+ margin-top: 0;
+}
+
+.redesign-channel-result__description > :last-child {
+ margin-bottom: 0;
+}
+
+.redesign-special-result .redesign-item-card {
+ padding: var(--redesign-space-3);
+}
+
+/* Categories have no rendered card content in the existing item template. */
+.redesign-category-result {
+ display: none;
+}
+
+/* Compact authentication form. Server-side validation and CAPTCHA fields use
+ * the same native form controls as the ordinary sign-in path. */
+.redesign-ui #contents:has(.redesign-login) {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ min-height: 100svh;
+}
+
+.redesign-main:has(.redesign-login) {
+ display: grid;
+ align-items: center;
+ flex: 1;
+}
+
+.redesign-login {
+ justify-content: center;
+ padding: 3rem 1.5rem;
+}
+
+.redesign-login__content {
+ padding: 0;
+}
+
+.redesign-login-form {
+ box-sizing: border-box;
+ margin: 0 auto;
+ max-width: 22rem;
+ padding: 0;
+}
+
+.redesign-login-form h1 {
+ color: var(--redesign-text);
+ font-size: 2rem;
+ letter-spacing: -0.025em;
+ line-height: 1.25;
+ margin: 0 0 1.5rem;
+}
+
+.redesign-login-form fieldset { padding: 0; }
+.redesign-login-form fieldset > label:first-child { margin-top: 0; }
+
+.redesign-login-form label {
+ color: var(--redesign-text);
+ font-size: 0.875rem;
+ font-weight: 500;
+ margin: 1rem 0 0.375rem;
+}
+
+.redesign-login-form input[type="text"],
+.redesign-login-form input[type="password"] {
+ background: var(--redesign-control);
+ border: 1px solid var(--redesign-line);
+ border-radius: var(--redesign-control-radius);
+ box-shadow: none;
+ color: var(--redesign-text);
+ min-height: 2.75rem;
+ padding: 0.625rem 0.75rem;
+}
+
+.redesign-login-form input[type="text"]:focus,
+.redesign-login-form input[type="password"]:focus {
+ border-color: var(--redesign-focus);
+ box-shadow: 0 0 0 1px var(--redesign-focus);
+}
+
+.redesign-login-form__captcha {
+ background: var(--redesign-control);
+ border: 1px solid var(--redesign-line);
+ border-radius: var(--redesign-control-radius);
+ display: block;
+ margin: 1.25rem 0 0.5rem;
+ max-width: 100%;
+ width: 50%;
+}
+
+.redesign-ui .redesign-login-form .pure-button-primary {
+ background: var(--redesign-accent);
+ border: 1px solid var(--redesign-accent);
+ border-radius: var(--redesign-control-radius);
+ color: var(--redesign-on-accent);
+ display: block;
+ font-weight: 650;
+ margin: 1.5rem 0 0;
+ min-height: 2.75rem;
+ padding: 0.625rem 0.75rem;
+ width: 100%;
+}
+
+.redesign-ui .redesign-login-form .pure-button-primary:hover,
+.redesign-ui .redesign-login-form .pure-button-primary:focus-visible {
+ background: var(--redesign-accent-hover) !important;
+ border-color: var(--redesign-accent-hover) !important;
+ color: var(--redesign-on-accent) !important;
+}
+
+.redesign-footer {
+ border-top: 1px solid var(--redesign-line);
+ color: var(--redesign-muted) !important;
+ font-size: 0.8125rem;
+ margin-top: 2rem;
+}
+
+.redesign-footer a {
+ color: var(--redesign-muted) !important;
+}
+
+@media screen and (min-width: 768px) {
+ .redesign-video-result,
+ .redesign-collection-result {
+ width: 50%;
+ }
+}
+
+@media screen and (min-width: 1100px) {
+ .redesign-video-result,
+ .redesign-collection-result {
+ width: 33.3333%;
+ }
+}
+
+@media screen and (max-width: 767px) {
+ .redesign-ui .redesign-navbar {
+ align-items: stretch;
+ gap: var(--redesign-space-2);
+ padding-bottom: var(--redesign-space-3);
+ padding-top: var(--redesign-space-3);
+ }
+
+ .redesign-ui .redesign-navbar > div {
+ margin-bottom: 0;
+ }
+
+ .redesign-ui .redesign-navbar > .searchbar {
+ order: 3;
+ }
+
+ .redesign-ui .redesign-navbar > .searchbar > form {
+ width: 100%;
+ }
+
+ .redesign-ui .redesign-navbar .user-field {
+ font-size: 1rem;
+ justify-content: flex-end;
+ }
+
+ .redesign-item {
+ padding: var(--redesign-space-2) var(--redesign-space-3);
+ }
+
+ .redesign-channel-result .redesign-item-card {
+ padding: var(--redesign-space-3);
+ }
+
+ .redesign-channel-result__identity {
+ align-items: flex-start;
+ gap: var(--redesign-space-3);
+ }
+
+ .redesign-channel-result__avatar {
+ height: 3.5rem;
+ width: 3.5rem;
+ }
+
+ .redesign-channel-result__name {
+ font-size: 1.1875rem;
+ }
+
+ .redesign-channel-result__metadata > span::before {
+ display: none;
+ }
+
+ .redesign-channel-result__metadata > span {
+ flex-basis: 100%;
+ }
+
+ .redesign-login {
+ padding: 2rem var(--redesign-space-3);
+ }
+
+ .redesign-login-form {
+ padding: 0;
+ }
+}
+
+@media (prefers-reduced-motion: reduce) {
+ .redesign-ui *,
+ .redesign-ui *::before,
+ .redesign-ui *::after {
+ scroll-behavior: auto !important;
+ }
+}
+
+/* Search matches are separate destinations, never headings for unrelated videos. */
+.redesign-channel-matches,
+.redesign-media-matches { margin: 0 0 1.5rem; }
+.redesign-channel-matches h2,
+.redesign-media-matches h2 { font-size: 1.125rem; margin: 1rem 1rem .5rem; }
+.redesign-channel-rail {
+ display: flex;
+ overflow-x: auto;
+ gap: .75rem;
+ padding: .5rem 1rem 1rem;
+}
+.redesign-channel-rail .redesign-channel-result {
+ flex: 0 0 19rem;
+ padding: 0;
+ width: 19rem;
+}
+.redesign-channel-rail .redesign-item-card { padding: 1rem; height: 100%; }
+.redesign-channel-rail .redesign-channel-result__identity { gap: .75rem; align-items: flex-start; }
+.redesign-channel-rail .redesign-channel-result__avatar { width: 3rem; height: 3rem; }
+.redesign-channel-rail .redesign-channel-result__name { font-size: 1rem; }
+.redesign-channel-rail .redesign-channel-result__metadata { font-size: .75rem; }
+.redesign-channel-rail .redesign-channel-result__metadata > span { flex-basis: 100%; }
+.redesign-channel-rail .redesign-channel-result__metadata > span::before { display: none; }
+.redesign-channel-rail .redesign-channel-result__description { font-size: .75rem; line-height: 1.4; margin-top: .5rem; }
+.redesign-media-matches:has(> h2) {
+ display: grid;
+ grid-template-columns: auto minmax(0, 1fr);
+ align-items: center;
+}
+.redesign-media-matches > h2 {
+ grid-area: 1 / 1;
+ margin: 0 0 .5rem .75rem;
+}
+.redesign-media-matches > div { grid-column: 1 / -1; }
+.redesign-media-matches:has(> h2) > .h-box:first-of-type {
+ grid-area: 1 / 2;
+ padding-inline: 1rem .75rem;
+ margin-bottom: .5rem;
+}
+.redesign-ui .redesign-media-matches:has(> h2) > .h-box:first-of-type .page-nav-container {
+ justify-content: flex-end;
+ flex-wrap: wrap;
+ gap: .5rem;
+ margin: 0;
+ padding: 0;
+}
+.redesign-media-matches:has(> h2) > .h-box:first-of-type .page-prev-container:empty { display: none; }
+.redesign-media-matches:has(> h2) > .h-box:first-of-type .pure-button { margin: 0; }
+@media screen and (max-width: 767px) {
+ .redesign-media-matches > h2 { margin-inline-start: 1rem; }
+ .redesign-media-matches:has(> h2) > .h-box:first-of-type { padding-inline-end: 1rem; }
+}
+.redesign-ui .page-nav-container { padding: 0 1rem; margin: .5rem 0 1rem; }
+.redesign-ui .redesign-video-result .redesign-item-card,
+.redesign-ui .redesign-collection-result .redesign-item-card { padding-inline: 0; }
+
+/* The header must reserve space for the signed-in actions before sizing search. */
+.redesign-ui .redesign-navbar { display: grid; grid-template-columns: minmax(7rem,1fr) minmax(14rem,30rem) auto; gap: 1.25rem; }
+.redesign-ui .redesign-navbar > div { width: auto; margin: 0; min-width: 0; }
+.redesign-ui .redesign-navbar .searchbar { flex: none; }
+.redesign-ui .redesign-navbar .searchbar > form { width: 100%; box-sizing: border-box; }
+.redesign-ui .redesign-navbar .user-field { gap: .25rem; flex: none; flex-wrap: wrap; }
+.redesign-ui .redesign-navbar .user-field > div { width: auto; flex: none; }
+.redesign-ui .redesign-navbar .user-field a,
+.redesign-ui .redesign-navbar .redesign-signout {
+ box-sizing: border-box;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 2.5rem;
+ min-height: 2.5rem;
+ padding: .5rem;
+ text-transform: none;
+ line-height: 1.25;
+}
+.redesign-ui .redesign-navbar .user-field .icon { font-size: 1.2rem; }
+.redesign-ui .redesign-signout { background: transparent; border: 0; color: var(--redesign-muted); font: inherit; cursor: pointer; }
+.redesign-ui .redesign-navbar #user_name { display: block; max-width: 7rem; overflow: hidden; text-overflow: ellipsis; padding: 0 .5rem; font-size: .875rem; }
+
+.redesign-channel-page-header { padding-block: 1.5rem 1rem; }
+.redesign-channel-page-header .title { margin: 0; gap: 1rem; }
+.redesign-channel-page-header .title > .flex-left { flex: 1; min-width: 0; width: auto; }
+.redesign-channel-page-header .title > .flex-right { flex: none; width: auto; }
+.redesign-channel-page-header .channel-profile { display: flex; align-items: center; gap: .875rem; }
+.redesign-channel-page-header .channel-profile img { width: 4rem; height: 4rem; }
+.redesign-channel-page-header .channel-name { font-size: 1.5rem; line-height: 1.25; }
+.redesign-channel-page-header .button-container { gap: .5rem; }
+.redesign-channel-page-header #descriptionWrapper { max-width: 72ch; font-size: .9375rem; line-height: 1.5; color: var(--redesign-muted); }
+.redesign-channel-links { display: flex; flex-wrap: wrap; gap: .5rem 1.5rem; font-size: .8125rem; }
+.redesign-channel-links a { color: var(--redesign-muted); }
+.redesign-channel-toolbar { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: .5rem 1.5rem; border-bottom: 1px solid var(--redesign-line); margin-bottom: .75rem; }
+.redesign-channel-tabs { display: flex; flex-wrap: wrap; gap: 1rem; }
+.redesign-channel-tabs > div { width: auto; }
+.redesign-channel-tabs a,
+.redesign-channel-tabs b { display: block; padding: .875rem 0; font-size: .9375rem; }
+.redesign-channel-tabs b { border-bottom: 2px solid var(--redesign-text); }
+.redesign-channel-tabs a { color: var(--redesign-muted); }
+.redesign-channel-sort { display: flex; gap: 1rem; font-size: .8125rem; padding: .75rem 0; }
+.redesign-channel-sort a { color: var(--redesign-muted); }
+.redesign-channel-page-header .pure-button { min-height: 2.5rem; padding: .6rem .9rem; border: 1px solid var(--redesign-line); border-radius: 6px; background: var(--redesign-surface); color: var(--redesign-text); font-size: .875rem; }
+
+.redesign-ui #contents:has(.redesign-subscriptions) { display:flex; flex-direction:column; min-height:100svh; }
+.redesign-main:has(.redesign-subscriptions) { flex: 1; }
+.redesign-ui .feed-menu { display:flex; flex-wrap:wrap; justify-content:flex-start; gap:1.5rem; padding:.5rem 1rem 0; margin:0; border-bottom:1px solid var(--redesign-line); }
+.redesign-ui .feed-menu-item { color:var(--redesign-muted); padding:.875rem 0; font-size:.9375rem; text-transform:none; }
+.redesign-ui .feed-menu-item[aria-current="page"] { color:var(--redesign-text); border-bottom:2px solid var(--redesign-text); }
+.redesign-feed-heading { display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:.75rem; padding-block:1.5rem .75rem; }
+.redesign-feed-heading h1 { font-size:1.5rem; margin:0; }
+.redesign-feed-actions { display:flex; align-items:center; flex-wrap:wrap; gap:1rem; font-size:.875rem; }
+.redesign-feed-actions a { color:var(--redesign-muted); }
+.redesign-feed-empty { margin:2rem 1rem; padding:2rem 0; border-block:1px solid var(--redesign-line); }
+.redesign-feed-empty p { font-size:1.125rem; margin:0 0 .75rem; }
+.redesign-feed-status { font-size:.8125rem; color:var(--redesign-muted); }
+.redesign-subscriptions > .h-box:has(hr) { display:none; }
+
+@media screen and (max-width: 1000px) {
+ .redesign-ui .redesign-navbar { grid-template-columns: 1fr auto; gap: .5rem 1rem; }
+ .redesign-ui .redesign-navbar .searchbar { grid-column:1 / -1; grid-row:2; order:initial; }
+ .redesign-ui .redesign-navbar .user-field { grid-column:2; grid-row:1; }
+ .redesign-ui .redesign-navbar .index-link { text-align:start; padding-left:0; }
+}
+@media screen and (max-width: 520px) {
+ .redesign-ui .redesign-navbar { gap:.5rem; }
+ .redesign-ui .redesign-navbar .user-field { gap:0; }
+ .redesign-ui .redesign-navbar .user-field a,
+ .redesign-ui .redesign-navbar .redesign-signout { min-width:2rem; padding:.375rem; font-size:.8125rem; }
+ .redesign-ui .redesign-navbar #user_name { max-width:3.5rem; padding:0 .25rem; }
+ .redesign-channel-page-header .title { flex-wrap:wrap; }
+ .redesign-channel-page-header .title > div { width:100%; justify-content:flex-start; }
+ .redesign-channel-page-header .title > .flex-left { flex-basis:100%; }
+ .redesign-channel-page-header .channel-name { font-size:1.25rem; }
+ .redesign-channel-page-header .channel-profile img { width:3rem; height:3rem; }
+}
+
+/* Native account disclosure: a local avatar, with no remote profile request. */
+.redesign-ui .redesign-navbar .user-field:has(.redesign-account-menu) { gap: .75rem; flex-wrap: nowrap; }
+.redesign-account-menu { position: relative; }
+.redesign-account-trigger {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 2.75rem;
+ height: 2.75rem;
+ list-style: none;
+ cursor: pointer;
+ border-radius: 50%;
+}
+.redesign-account-trigger::-webkit-details-marker { display: none; }
+.redesign-account-trigger::before { content: none; }
+.redesign-account-avatar {
+ display: grid;
+ place-items: center;
+ width: 2.5rem;
+ height: 2.5rem;
+ border-radius: 50%;
+ background: var(--redesign-control);
+ border: 1px solid var(--redesign-line);
+ color: var(--redesign-text);
+ font-size: 1rem;
+ font-weight: 650;
+}
+.redesign-account-menu[open] .redesign-account-avatar { border-color: var(--redesign-focus); }
+.redesign-ui .redesign-account-panel {
+ position: absolute;
+ inset-inline-end: 0;
+ top: calc(100% + .5rem);
+ z-index: 100;
+ width: min(15rem, calc(100vw - 2rem));
+ box-sizing: border-box;
+ padding: .375rem;
+ background: var(--redesign-surface);
+ border: 1px solid var(--redesign-line);
+ border-radius: .5rem;
+ box-shadow: 0 8px 24px rgb(0 0 0 / .2);
+}
+.redesign-ui .redesign-navbar .redesign-account-panel > a,
+.redesign-ui .redesign-navbar .redesign-account-panel .redesign-signout {
+ display: flex;
+ justify-content: flex-start;
+ gap: .75rem;
+ width: 100%;
+ min-height: 2.75rem;
+ padding: .625rem .75rem;
+ font-size: .875rem;
+ color: var(--redesign-text);
+ border-radius: .25rem;
+}
+.redesign-ui .redesign-account-panel > a:hover,
+.redesign-ui .redesign-account-panel .redesign-signout:hover { background: var(--redesign-control); }
+.redesign-account-identity { padding: .75rem; border-bottom: 1px solid var(--redesign-line); margin-bottom: .375rem; }
+.redesign-ui .redesign-navbar .redesign-account-panel #user_name { max-width: none; padding: 0; overflow-wrap: anywhere; white-space: normal; color: var(--redesign-text); }
+.redesign-account-panel form { border-top: 1px solid var(--redesign-line); margin-top: .375rem; padding-top: .375rem; }
+.redesign-ui .redesign-navbar #notification_ticker { position: relative; }
+.redesign-ui .redesign-navbar #notification_ticker > .icon { font-size: 1.65rem; }
+#notification_ticker #notification_count {
+ position: absolute;
+ inset-inline-end: -.25rem;
+ top: -.15rem;
+ min-width: 1.15rem;
+ padding: .125rem .25rem;
+ border-radius: 1rem;
+ background: #bd1641;
+ border: 2px solid var(--redesign-canvas);
+ color: #fff;
+ font-size: .6875rem;
+ font-weight: 700;
+ line-height: 1.2;
+ text-align: center;
+}
+
+.redesign-ui .ion-md-checkmark-circle {
+ color: #3ea6ff;
+ margin-inline-start: .2em;
+ vertical-align: -.08em;
+ line-height: 1;
+}
+.redesign-ui.light-theme .ion-md-checkmark-circle { color: #0878d1; }
+@media (prefers-color-scheme: light) {
+ .redesign-ui.no-theme .ion-md-checkmark-circle { color: #0878d1; }
+}
+.redesign-video-result .redesign-item-author,
+.redesign-video-result .redesign-item-meta { gap: .75rem; }
+.redesign-video-result .redesign-item-author > .flex-left,
+.redesign-video-result .redesign-item-meta > .flex-left { min-width: 0; }
+.redesign-video-result .redesign-item-author > .flex-right,
+.redesign-video-result .redesign-item-meta > .flex-right { flex: 0 0 auto; }
+
+/* Compact glyphs retain comfortable hit areas. */
+.redesign-account-avatar { width: 2rem; height: 2rem; font-size: .875rem; }
+.redesign-account-trigger { width: 2.5rem; height: 2.5rem; }
+.redesign-ui .redesign-navbar #notification_ticker > .icon { font-size: 1.35rem; }
+.redesign-ui .redesign-navbar .redesign-account-panel .icon { font-size: 1rem; }
+.redesign-account-panel [data-theme][aria-current="true"] { background: var(--redesign-control); }
+.redesign-account-panel [data-theme][aria-current="true"]::after { content: '✓'; margin-inline-start: auto; color: var(--redesign-accent); }
+.redesign-search-page #filters-collapse summary {
+ display: inline-flex;
+ align-items: center;
+ padding: .625rem .875rem;
+ border: 1px solid var(--redesign-line);
+ border-radius: .375rem;
+ min-height: 2.5rem;
+ box-sizing: border-box;
+}
+.redesign-search-page #filters-collapse summary::before { margin: 0 .625rem 0 0; border: 0; padding: 0; background: transparent; }
+.redesign-video-result .redesign-item-meta { align-items: center; }
+.redesign-video-result .redesign-item-meta .icon-buttons { align-items: center; gap: .5rem; }
+.redesign-video-result .redesign-item-meta .icon-buttons a { display: inline-flex; align-items: center; justify-content: center; margin: 0; line-height: 1; font-size: 1rem; }
+
+/* Search stays in the header; only compact viewports disclose the field. */
+.redesign-search-toggle, .redesign-search-trigger { display: none; }
+.redesign-ui .redesign-navbar { position: relative; grid-template-columns: minmax(7rem,1fr) minmax(12rem,30rem) auto; }
+.redesign-ui .redesign-navbar .searchbar { grid-column: 2; grid-row: 1; }
+.redesign-ui .redesign-navbar .user-field { grid-column: 3; grid-row: 1; }
+.redesign-ui .redesign-account-avatar { box-sizing: border-box; }
+@media screen and (max-width: 600px) {
+ .redesign-ui .redesign-navbar { grid-template-columns: minmax(0,1fr) 40px auto; gap: 4px; }
+ .redesign-ui .redesign-search-toggle { display: block; position: absolute; width: 1px; height: 1px; clip-path: inset(50%); overflow: hidden; }
+ .redesign-search-trigger { display: flex; grid-column: 2; grid-row: 1; align-items: center; justify-content: center; width: 40px; height: 40px; font-size: 22px; cursor: pointer; border-radius: 5px; }
+ .redesign-search-toggle:focus-visible + .redesign-search-trigger { outline: 3px solid var(--redesign-focus); }
+ .redesign-ui .redesign-navbar .searchbar { display: none; position: absolute; top: 100%; inset-inline: 0; z-index: 8; padding: 8px; background: var(--redesign-canvas); border-bottom: 1px solid var(--redesign-line); }
+ .redesign-ui .redesign-search-toggle:checked ~ .searchbar { display: block; }
+ .redesign-search-toggle:checked + .redesign-search-trigger { background: var(--redesign-surface); }
+}
+
+.redesign-ui .redesign-navbar { box-sizing: border-box; min-height: 60px; padding-block: 8px 4px; align-content: center; border-bottom: 0; }
+
+.redesign-ui .redesign-navbar .user-field:has(.redesign-account-menu) { gap: 4px; }
+
+/* Stable metadata rows without inherited paragraph spacing or empty card tails. */
+.redesign-ui .redesign-video-result .redesign-item-card { display: grid; grid-template-rows: auto 1fr auto auto; }
+.redesign-ui .redesign-video-result .video-card-row p { margin: 0; }
+.redesign-ui .redesign-video-result .redesign-item-title { padding-top: 12px; }
+.redesign-ui .redesign-video-result .redesign-item-author { margin-top: 10px; align-items: center; }
+.redesign-ui .redesign-video-result .redesign-item-meta { margin-top: 6px; padding-bottom: 12px; min-height: 28px; align-items: center; }
+.redesign-ui .redesign-video-result .redesign-item-meta .icon-buttons a { width: 28px; height: 28px; }
+.redesign-ui .redesign-video-result .redesign-item-author .video-data { white-space: nowrap; }
+
+.redesign-ui .redesign-navbar .user-field .redesign-theme-choice { display: inline-flex; align-items: center; justify-content: center; min-width: 32px; height: 36px; box-sizing: border-box; padding: 6px; color: var(--redesign-muted); border: 1px solid transparent; border-radius: 5px; }
+.redesign-ui .redesign-navbar .redesign-theme-choice .icon { font-size: 18px; }
+.redesign-ui .redesign-navbar .redesign-theme-choice[aria-current="true"] { color: var(--redesign-text); border-color: var(--redesign-line); background: var(--redesign-surface); }
diff --git a/assets/css/watch-layout.css b/assets/css/watch-layout.css
new file mode 100644
index 000000000..050fafdf8
--- /dev/null
+++ b/assets/css/watch-layout.css
@@ -0,0 +1,488 @@
+.watch-page {
+ --watch-border: #3a3c42;
+ --watch-panel: #191a1e;
+ --watch-muted: #b4b6bc;
+ --watch-focus: #79b7ff;
+ box-sizing: border-box;
+ display: grid;
+ grid-template-columns: minmax(0, 1fr) minmax(16rem, 20rem);
+ column-gap: clamp(1.25rem, 2.5vw, 2rem);
+ width: 100%;
+ padding-inline: 1rem;
+}
+
+.watch-page-wide {
+ grid-template-columns: minmax(0, 1fr);
+}
+
+.watch-visually-hidden {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border: 0;
+}
+
+.watch-page .watch-theater-toggle {
+ grid-column: 1 / -1;
+ grid-row: 1;
+ justify-self: end;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ box-sizing: border-box;
+ min-width: 2.75rem;
+ min-height: 2.5rem;
+ margin-block-end: 0.65rem;
+ border: 1px solid var(--watch-border);
+ border-radius: 0.35rem;
+ color: inherit;
+ cursor: pointer;
+}
+
+.watch-page .watch-theater-toggle:hover {
+ border-color: var(--watch-muted);
+}
+
+.watch-page #theater-mode-toggle:focus-visible + .watch-theater-toggle {
+ outline: 2px solid var(--watch-focus);
+ outline-offset: 3px;
+}
+
+.watch-theater-icon {
+ position: relative;
+ display: block;
+ box-sizing: border-box;
+ width: 1.35rem;
+ height: 0.9rem;
+ border: 2px solid currentColor;
+ border-radius: 0.12rem;
+}
+
+.watch-theater-icon::after {
+ position: absolute;
+ inset-inline: 0.16rem;
+ bottom: 0.12rem;
+ height: 0.16rem;
+ background: currentColor;
+ content: "";
+}
+
+#theater-mode-toggle:checked + .watch-theater-toggle .watch-theater-icon::after {
+ inset: 0.14rem;
+ height: auto;
+ border: 1px solid currentColor;
+ background: transparent;
+}
+
+.watch-page > #player-container {
+ grid-column: 1;
+ grid-row: 2;
+ width: 100%;
+ margin-inline: 0;
+ padding-bottom: 56.25% !important;
+}
+
+.watch-page .player-dimensions.vjs-fluid {
+ padding-top: 56.25% !important;
+}
+
+.watch-page .watch-title {
+ grid-column: 1;
+ grid-row: 3;
+ padding-inline: 0;
+}
+
+.watch-title h1 {
+ margin-block: 1rem 0.5rem;
+ font-size: clamp(1.35rem, 2vw, 1.5625rem);
+ line-height: 1.28;
+ letter-spacing: -0.015em;
+}
+
+.watch-title h3 {
+ margin-block: 0.35rem;
+ font-size: 1rem;
+}
+
+.watch-title #link-iv-listen {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 2.5rem;
+ min-height: 2.5rem;
+ margin-inline-start: 0.25rem;
+ vertical-align: middle;
+}
+
+.watch-page .watch-content,
+.watch-page .watch-primary-content {
+ display: contents;
+}
+
+.watch-content > .watch-channel {
+ grid-column: 1;
+ grid-row: 4;
+ min-width: 0;
+ margin-block: 0.25rem 0.75rem;
+ padding: 0;
+}
+
+.watch-content > .watch-channel .channel-profile {
+ display: flex;
+ align-items: center;
+ gap: 0.7rem;
+}
+
+.watch-content > .watch-channel .channel-profile > img {
+ width: 2.75rem;
+ height: 2.75rem;
+ flex: none;
+ object-fit: cover;
+}
+
+.watch-content > .watch-channel .button-container {
+ min-width: max-content;
+}
+
+.watch-utilities {
+ grid-column: 1;
+ grid-row: 5;
+ min-width: 0;
+ margin-block-end: 1rem;
+}
+
+.watch-utility-disclosure {
+ border-block: 1px solid var(--watch-border);
+}
+
+.watch-utility-disclosure > summary {
+ box-sizing: border-box;
+ width: max-content;
+ min-height: 2.75rem;
+ padding: 0.7rem 0;
+ font-weight: 600;
+ cursor: pointer;
+}
+
+.watch-utility-disclosure > summary:focus-visible {
+ outline: 2px solid var(--watch-focus);
+ outline-offset: 3px;
+}
+
+.watch-utility-content {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: 0.8rem 1.25rem;
+ padding: 0.5rem 0 1rem;
+}
+
+.watch-utility-content > p,
+.watch-utility-content > span,
+.watch-utility-content > form {
+ margin: 0;
+}
+
+.watch-utility-content > form,
+.watch-utility-content > #allowed_regions {
+ grid-column: 1 / -1;
+}
+
+.watch-utility-content .pure-button {
+ min-height: 2.5rem;
+}
+
+.watch-primary-content > .h-box {
+ grid-column: 1;
+ grid-row: 6;
+ min-width: 0;
+ padding: 0;
+}
+
+.watch-primary-content #published-date {
+ color: var(--watch-muted);
+}
+
+.watch-primary-content #description-box {
+ box-sizing: border-box;
+ margin-block: 1rem;
+ padding: 1rem;
+ border-radius: 0.4rem;
+ background: var(--watch-panel);
+}
+
+.watch-primary-content #descriptionWrapper {
+ max-width: 70ch;
+}
+
+.watch-primary-content #comments {
+ max-width: none;
+ margin: 0;
+}
+
+.watch-related {
+ grid-column: 2;
+ grid-row: 2 / span 5;
+ min-width: 0;
+}
+
+.watch-related > .h-box {
+ padding: 0;
+}
+
+.watch-related .pure-u-1 {
+ display: grid;
+ grid-template-columns: 7rem minmax(0, 1fr);
+ grid-template-rows: min-content min-content;
+ gap: 0.15rem 0.7rem;
+ width: 100%;
+ margin-block-end: 1rem;
+}
+
+.watch-related .pure-u-1 > .thumbnail {
+ grid-column: 1;
+ grid-row: 1 / span 2;
+}
+
+.watch-related .video-card-row {
+ grid-column: 2;
+ grid-row: 1;
+ min-width: 0;
+ margin: 0;
+}
+
+.watch-related .video-card-row p {
+ display: -webkit-box;
+ margin: 0;
+ overflow: hidden;
+ font-size: 0.9rem;
+ font-weight: 600;
+ line-height: 1.3;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 2;
+}
+
+.watch-related .pure-u-1 > h5 {
+ grid-column: 2;
+ grid-row: 2;
+ min-width: 0;
+ margin: 0;
+ color: var(--watch-muted);
+ font-size: 0.75rem;
+ font-weight: 400;
+ line-height: 1.35;
+}
+
+.watch-related .pure-u-1 > h5 > div {
+ width: 100%;
+ text-align: start !important;
+}
+
+.watch-related .pure-u-1 > h5 b {
+ font-weight: 400;
+}
+
+#theater-mode-toggle:checked ~ #player-container {
+ grid-column: 1 / -1;
+}
+
+#theater-mode-toggle:checked ~ .watch-content .watch-related {
+ grid-column: 2;
+ grid-row: 3 / span 4;
+}
+
+.light-theme .watch-page {
+ --watch-border: #d2d5da;
+ --watch-panel: #f0f1f3;
+ --watch-muted: #5c6068;
+ --watch-focus: #075a9e;
+}
+
+@media (prefers-color-scheme: light) {
+ .no-theme .watch-page {
+ --watch-border: #d2d5da;
+ --watch-panel: #f0f1f3;
+ --watch-muted: #5c6068;
+ --watch-focus: #075a9e;
+ }
+}
+
+@media screen and (max-width: 900px) {
+ .watch-page,
+ .watch-page-wide {
+ grid-template-columns: minmax(0, 1fr);
+ }
+
+ .watch-related,
+ #theater-mode-toggle:checked ~ .watch-content .watch-related {
+ grid-column: 1;
+ grid-row: 7;
+ margin-block-start: 1.25rem;
+ }
+
+ .watch-related .pure-u-1 {
+ grid-template-columns: minmax(7rem, 11rem) minmax(0, 1fr);
+ }
+}
+
+@media screen and (max-width: 520px) {
+ .watch-page {
+ padding-inline: 0.75rem;
+ }
+
+ .watch-theater-toggle {
+ min-width: 2.75rem;
+ }
+
+ .watch-title h1 {
+ font-size: 1.25rem;
+ }
+
+ .watch-page .watch-content > .watch-channel {
+ display: flex;
+ align-items: flex-start;
+ gap: 0.75rem;
+ }
+
+ .watch-page .watch-content > .watch-channel > div {
+ width: auto;
+ }
+
+ .watch-page .watch-content > .watch-channel .flex-left {
+ min-width: 0;
+ }
+
+ .watch-page .watch-content > .watch-channel .flex-right {
+ justify-content: flex-start;
+ margin: 0;
+ }
+
+ .watch-utility-content {
+ grid-template-columns: minmax(0, 1fr);
+ }
+
+ .watch-utility-content > form,
+ .watch-utility-content > #allowed_regions {
+ grid-column: 1;
+ }
+
+ .watch-related .pure-u-1 {
+ grid-template-columns: minmax(6.5rem, 38vw) minmax(0, 1fr);
+ }
+}
+
+@media (forced-colors: active) {
+ .watch-theater-toggle,
+ .watch-utility-disclosure {
+ border-color: CanvasText;
+ }
+}
+
+/* Keep watch actions on one compact row; native disclosures hold form details. */
+.watch-page.has-player-theater-control .watch-theater-toggle,
+.watch-page.has-player-theater-control #theater-mode-toggle { display: none; }
+.watch-page .watch-theater-toggle { gap: .6rem; padding-inline: .75rem; }
+.watch-page .watch-action-row { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; position: relative; padding-block: .35rem; }
+.watch-action-row > p, .watch-action-row > span { margin: 0; }
+.watch-action-row #watch-on-youtube { display: inline-flex; gap: 4px; }
+.watch-action-row .watch-stat { display: inline-flex; align-items: center; gap: 6px; margin-inline-end: 12px; font-size: .85rem; color: var(--watch-muted); }
+.watch-action-row .watch-action { display: inline-flex; align-items: center; justify-content: center; gap: 7px; box-sizing: border-box; min-width: 36px; min-height: 36px; padding: 6px 9px; border: 0; border-radius: 5px; color: var(--redesign-text); font-size: .85rem; line-height: 1.3; cursor: pointer; }
+.watch-action-row .watch-action-icon { width: 36px; padding: 0; }
+.watch-action-row .watch-action .icon { font-size: 18px; line-height: 1; }
+.watch-action-row .watch-action:hover, .watch-action-menu[open] > summary { background: var(--watch-panel); }
+.watch-action-menu > summary { list-style: none; }
+.watch-action-menu > summary::-webkit-details-marker { display: none; }
+.watch-action-row .watch-action-panel { position: absolute; z-index: 5; inset-inline-end: 0; top: 100%; width: min(320px, 100%); box-sizing: border-box; padding: 16px; background: var(--redesign-surface); color: var(--redesign-text); border: 1px solid var(--watch-border); border-radius: 6px; box-shadow: 0 6px 18px #0003; }
+.watch-action-panel p { margin: 0 0 10px; font-size: .85rem; }
+.watch-action-panel select { width: 100%; max-width: 100%; color: var(--redesign-text); background: var(--redesign-control); }
+.watch-action-panel form { margin: 0; }
+.redesign-ui #subscribe:not([data-type="unsubscribe"]) { background: #d92332; border-color: #d92332; color: #fff; }
+.redesign-ui #subscribe:not([data-type="unsubscribe"]):hover { background: #bc1826; border-color: #bc1826; }
+.redesign-ui .watch-channel .ion-md-checkmark-circle { color: #3ea6ff; }
+.redesign-ui .channel-owner .ion-md-checkmark-circle { color: #fff; }
+
+.watch-page .watch-action-row { justify-content: space-between; gap: 8px 16px; padding-block: 8px; border-block: 1px solid var(--watch-border); }
+.watch-action-stats, .watch-action-buttons { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
+.watch-action-buttons { margin-inline-start: auto; }
+.watch-action-row .watch-action { min-height: 36px; gap: 7px; padding: 8px 10px; font-weight: 500; }
+.watch-action-row .watch-action-panel { top: calc(100% + 6px); }
+.watch-info-menu .watch-action-panel .watch-action { justify-content: flex-start; width: 100%; }
+.watch-info-menu .watch-visually-hidden { position: static; clip: auto; margin: 0; padding: 0; width: auto; height: auto; overflow: visible; white-space: normal; }
+.watch-info-menu #watch-on-youtube { display: block; }
+.watch-info-menu .watch-action-panel hr { border: 0; border-top: 1px solid var(--watch-border); margin-block: 12px; }
+.redesign-ui .watch-action-panel select, .redesign-ui .watch-action-panel input:not([type=hidden]) { box-sizing: border-box; color: var(--redesign-text); background-color: var(--redesign-control); border: 1px solid var(--watch-border); border-radius: 4px; min-height: 38px; padding: 8px; width: 100%; margin-block: 8px; }
+.redesign-ui .watch-action-panel button { background: var(--redesign-accent); color: var(--redesign-on-accent); border: 0; border-radius: 4px; padding: 9px 12px; cursor: pointer; margin: 0; }
+.watch-share-choice { display: grid; grid-template-columns: 1fr auto; gap: 6px; margin-bottom: 16px; }
+.watch-share-choice:last-child { margin-bottom: 0; }
+.watch-share-choice .watch-share-link { grid-column: 1 / -1; }
+.watch-share-choice input { min-width: 0; font-size: 12px; }
+.watch-share-panel > .watch-share-link { display: block; padding: 10px 0; }
+.watch-share-choice button { font-size: 12px; align-self: center; }
+.watch-related { padding-top: 2px; }
+#theater-mode-toggle:checked ~ .watch-content .watch-related { padding-top: 16px; }
+.redesign-ui .watch-related .video-card-row a { color: var(--redesign-text); }
+.redesign-ui .watch-related h5 a { color: var(--watch-muted); }
+.watch-related .pure-u-1 { grid-template-columns: 8rem minmax(0,1fr); gap: 4px 12px; margin-bottom: 16px; }
+.watch-related .thumbnail { border-radius: 5px; overflow: hidden; align-self: start; }
+.watch-related .video-card-row p { font-size: .875rem; line-height: 1.4; }
+.watch-related .pure-control-group { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 36px; font-size: .8125rem; color: var(--watch-muted); }
+.watch-related .pure-control-group input { margin: 0; accent-color: var(--redesign-accent); }
+.watch-related hr { border: 0; border-top: 1px solid var(--watch-border); margin: 8px 0 16px; }
+.watch-related .length { font-size: .75rem; padding: 2px 4px; }
+@media screen and (max-width: 520px) {
+ .watch-action-buttons { margin-inline-start: 0; }
+ .watch-action-stats { width: 100%; }
+ .watch-page .watch-channel { flex-wrap: nowrap; align-items: center; }
+ .watch-channel #subscribe { font-size: .8125rem; padding: 8px 10px; white-space: nowrap; }
+ .watch-channel #channel-name { font-size: 1rem; }
+}
+
+.redesign-ui .watch-page a:hover, .redesign-ui .watch-page a:active { color: var(--redesign-text) !important; }
+.redesign-ui .watch-page .channel-profile a:hover, .redesign-ui .watch-page .channel-profile:hover { color: var(--redesign-text); }
+.redesign-ui .watch-related h5 a:hover { color: var(--watch-muted) !important; }
+.redesign-ui .watch-channel a, .redesign-ui #comments h3 a { color: var(--redesign-text); }
+.redesign-ui .watch-channel a:hover .ion-md-checkmark-circle { color: #3ea6ff; }
+
+.redesign-ui #subscribe:not([data-type="unsubscribe"]):hover,
+.redesign-ui #subscribe:not([data-type="unsubscribe"]):focus,
+.redesign-ui #subscribe:not([data-type="unsubscribe"]):active { background: #bc1826 !important; border-color: #bc1826 !important; color: #fff !important; }
+.watch-action-panel [hidden] { display: none !important; }
+.watch-action-row .watch-action-panel { max-height: min(420px, 65vh); overflow-y: auto; }
+.watch-action-panel p { line-height: 1.5; }
+.redesign-ui #comments > div:first-child { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin: 20px 0; }
+.redesign-ui #comments h3 { margin: 0; font-size: 1.125rem; }
+.redesign-ui #comments > div:first-child > b { font-size: .8125rem; font-weight: 400; }
+.redesign-ui #comments .pure-g:has(> .channel-profile) { display: grid; grid-template-columns: 36px minmax(0,1fr); gap: 12px; padding: 0; margin-bottom: 24px; letter-spacing: normal; }
+.redesign-ui #comments .pure-g > .channel-profile { width: 36px; }
+.redesign-ui #comments .channel-profile img { width: 36px !important; height: 36px; object-fit: cover; margin: 0 !important; border-radius: 50%; }
+.redesign-ui #comments .channel-profile + div { width: auto; min-width: 0; }
+.redesign-ui #comments .channel-profile + div > p { margin: 0 0 8px; font-size: .875rem; line-height: 1.5; }
+.redesign-ui #comments .channel-profile + div > p:first-child { font-size: .8125rem; line-height: 1.3; }
+.redesign-ui #comments .channel-profile + div > p:has(> span[title]) { color: var(--watch-muted); font-size: .75rem; }
+.redesign-ui #comments .channel-owner { background: #3a3d45; color: #fff; border-radius: 4px; padding: 3px 6px; display: inline-block; }
+.redesign-ui #comments .channel-owner:hover { background: #3a3d45; color: #fff !important; }
+.redesign-ui #comments .ion-md-checkmark-circle { color: #fff; }
+.redesign-ui #comments [id="replies"] { margin-top: 8px; padding-left: 0; }
+.redesign-ui #comments [id="replies"] > .pure-u-1-24 { display: none; }
+.redesign-ui #comments [id="replies"] > .pure-u-23-24 { width: 100%; }
+.redesign-ui #comments [id="replies"] p { margin: 4px 0 12px; font-size: .8125rem; }
+.redesign-ui .watch-primary-content hr { border: 0; border-top: 1px solid var(--watch-border); }
+@media screen and (max-width: 600px) {
+ .watch-action-buttons { gap: 2px; }
+ .watch-action-row .watch-action { font-size: .75rem; padding-inline: 7px; gap: 5px; }
+}
+
+.watch-page { padding-top: 12px; }
+.watch-page .video-js { border-radius: 12px; overflow: hidden; }
+.watch-page video, .watch-page .vjs-poster { border-radius: 12px; }
+.watch-page .video-js.vjs-fullscreen, .watch-page .vjs-fullscreen video { border-radius: 0; }
+.light-theme .watch-page { --watch-muted: #555c68; --watch-border: #d5d9e0; }
+.light-theme .watch-primary-content #description-box { border: 1px solid #e0e3e9; }
+.light-theme .watch-action-row .watch-action:hover, .light-theme .watch-action-menu[open] > summary { background: #e8edf4; color: #17181b; }
+.light-theme .watch-action-row .watch-action-panel { border-color: #c9ced8; box-shadow: 0 6px 18px #1720331a; }
+.light-theme .watch-channel .ion-md-checkmark-circle { color: #0878d1; }
+.light-theme .watch-page #comments .channel-owner { background: #4d5562; }
diff --git a/assets/js/account-menu.js b/assets/js/account-menu.js
new file mode 100644
index 000000000..f72d7de8a
--- /dev/null
+++ b/assets/js/account-menu.js
@@ -0,0 +1,20 @@
+'use strict';
+
+// Native details handles disclosure without scripts. These only add dismissal.
+(function () {
+ var menu = document.querySelector('.redesign-account-menu');
+ if (!menu) return;
+ var trigger = menu.querySelector('summary');
+ document.addEventListener('keydown', function (event) {
+ if (event.key === 'Escape' && menu.open) {
+ menu.open = false;
+ trigger.focus();
+ }
+ });
+ document.addEventListener('click', function (event) {
+ if (menu.open && !menu.contains(event.target)) menu.open = false;
+ });
+ document.addEventListener('focusin', function (event) {
+ if (menu.open && !menu.contains(event.target)) menu.open = false;
+ });
+})();
diff --git a/assets/js/player-gestures.js b/assets/js/player-gestures.js
new file mode 100644
index 000000000..b678250b3
--- /dev/null
+++ b/assets/js/player-gestures.js
@@ -0,0 +1,152 @@
+'use strict';
+
+// Optional enhancements: native media controls remain available without this script.
+(function (root, factory) {
+ if (typeof module === 'object' && module.exports) module.exports = factory;
+ else root.installPlayerGestures = factory;
+})(typeof window === 'undefined' ? globalThis : window, function (player, environment) {
+ var env = environment || {};
+ var win = env.window || window;
+ var doc = env.document || document;
+ var later = env.setTimeout || win.setTimeout.bind(win);
+ var cancelTimer = env.clearTimeout || win.clearTimeout.bind(win);
+ var el = player.el();
+ var session = null;
+ var suppressClick = false;
+ var listeners = [];
+
+ function blocked(event) {
+ return event.altKey || event.ctrlKey || event.metaKey || event.shiftKey ||
+ !player.controls() || (event.target && event.target.closest &&
+ event.target.closest('input, textarea, select, button, a, summary, [role="button"], [role="slider"], [role="textbox"], [contenteditable]:not([contenteditable="false"]), .vjs-control-bar, .vjs-menu'));
+ }
+
+ function consume(event) {
+ event.preventDefault();
+ event.stopImmediatePropagation();
+ }
+
+ function play() {
+ var result = player.play();
+ if (result && result.catch) result.catch(function () { finish(false); });
+ }
+
+ function toggle() {
+ if (player.paused()) play();
+ else player.pause();
+ }
+
+ function showHold(active) {
+ if (env.onHold) env.onHold(active);
+ else el.classList.toggle('vjs-speed-hold', active);
+ }
+
+ function begin(kind, event) {
+ if (session) return;
+ session = { kind: kind, pointerId: event.pointerId, x: event.clientX, y: event.clientY,
+ active: false, speed: player.playbackRate(), paused: player.paused() };
+ session.timer = later(function () {
+ if (!session) return;
+ session.active = true;
+ showHold(true);
+ player.playbackRate(2);
+ play();
+ }, 350);
+ }
+
+ function finish(tap) {
+ if (!session) return false;
+ var current = session;
+ cancelTimer(current.timer);
+ // Keep the hold marked active while ratechange handlers restore preferences.
+ if (current.active) {
+ player.playbackRate(current.speed);
+ if (current.paused) player.pause();
+ showHold(false);
+ }
+ session = null;
+ if (tap && !current.active && current.kind === 'keyboard') toggle();
+ return current.active;
+ }
+
+ function listen(target, type, handler) {
+ target.addEventListener(type, handler, true);
+ listeners.push([target, type, handler]);
+ }
+
+ listen(win, 'keydown', function (event) {
+ var playButton = event.target && event.target.closest &&
+ event.target.closest('.vjs-play-control, .vjs-big-play-button');
+ var playerControl = event.key !== ' ' && event.target && event.target.closest &&
+ event.target.closest('.vjs-control-bar') &&
+ !event.target.closest('.vjs-menu, input, select, [role="slider"]');
+ if (!el.contains(doc.activeElement) || (!playButton && !playerControl && blocked(event)) ||
+ event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;
+ if (event.key === ' ') {
+ consume(event);
+ if (!event.repeat) begin('keyboard', event);
+ } else if (event.key === 'k') {
+ consume(event);
+ if (!event.repeat && !session) toggle();
+ } else if (event.key === 'j' || event.key === 'l') {
+ consume(event);
+ var time = Math.max(0, player.currentTime() + (event.key === 'j' ? -10 : 10));
+ var duration = player.duration();
+ player.currentTime(Number.isFinite(duration) ? Math.min(duration, time) : time);
+ }
+ });
+
+ listen(win, 'keyup', function (event) {
+ if (event.key === ' ' && session && session.kind === 'keyboard') {
+ consume(event);
+ finish(el.contains(doc.activeElement));
+ }
+ });
+
+ listen(el, 'pointerdown', function (event) {
+ suppressClick = false;
+ if (event.button !== 0 || event.pointerType !== 'mouse' || blocked(event)) return;
+ el.focus({ preventScroll: true });
+ begin('pointer', event);
+ });
+
+ listen(win, 'pointermove', function (event) {
+ if (!session || session.kind !== 'pointer' || session.active || event.pointerId !== session.pointerId) return;
+ if (Math.abs(event.clientX - session.x) + Math.abs(event.clientY - session.y) > 12) finish(false);
+ });
+
+ listen(win, 'pointerup', function (event) {
+ if (!session || session.kind !== 'pointer' || event.pointerId !== session.pointerId) return;
+ if (finish(false)) {
+ // Browsers may deliver click in a later task. A new pointerdown clears
+ // this flag, so releasing outside cannot consume the next deliberate click.
+ suppressClick = true;
+ }
+ });
+
+ // Video.js toggles on mouseup; the subsequent browser click must also be
+ // consumed so other click handlers cannot turn a completed hold into a tap.
+ listen(el, 'mouseup', function (event) {
+ if (suppressClick && !blocked(event)) consume(event);
+ });
+
+ listen(el, 'click', function (event) {
+ if (suppressClick && event.detail !== 0 && !blocked(event)) {
+ consume(event);
+ suppressClick = false;
+ }
+ });
+
+ listen(win, 'pointercancel', function () { finish(false); });
+ listen(win, 'blur', function () { finish(false); });
+ listen(doc, 'visibilitychange', function () { if (doc.hidden) finish(false); });
+ listen(doc, 'focusin', function (event) { if (!el.contains(event.target) || blocked(event)) finish(false); });
+
+ return {
+ isHolding: function () { return !!(session && session.active); },
+ dispose: function () {
+ finish(false);
+ listeners.forEach(function (entry) { entry[0].removeEventListener(entry[1], entry[2], true); });
+ }
+ };
+});
diff --git a/assets/js/player.js b/assets/js/player.js
index 24f3379af..a1502b045 100644
--- a/assets/js/player.js
+++ b/assets/js/player.js
@@ -39,11 +39,6 @@ if (player_data.aspect_ratio) {
options.aspectRatio = player_data.aspect_ratio;
}
-var embed_url = new URL(location);
-embed_url.searchParams.delete('v');
-var short_url = location.origin + '/' + video_data.id + embed_url.search;
-embed_url = location.origin + '/embed/' + video_data.id + embed_url.search;
-
var save_player_pos_key = 'save_player_pos';
videojs.Vhs.xhr.beforeRequest = function(options) {
@@ -64,6 +59,13 @@ if (CONFIG.videojs.max_goal_buffer_length) {
}
var player = videojs('player', options);
+var playerGestures = installPlayerGestures(player);
+player.on('dispose', function () { playerGestures.dispose(); });
+var speedHoldIndicator = document.createElement('span');
+speedHoldIndicator.className = 'speed-hold-indicator';
+speedHoldIndicator.textContent = '2×';
+speedHoldIndicator.setAttribute('aria-hidden', 'true');
+player.el().appendChild(speedHoldIndicator);
player.on('error', function () {
if (video_data.params.quality === 'dash') return;
@@ -185,22 +187,6 @@ player.on('timeupdate', function () {
});
-var shareOptions = {
- socials: ['fbFeed', 'tw', 'reddit', 'email'],
-
- get url() {
- return addCurrentTimeToURL(short_url);
- },
- title: player_data.title,
- description: player_data.description,
- image: player_data.thumbnail,
- get embedCode() {
- // Single quotes inside here required. HTML inserted as is into value attribute of input
- return "