🎨 Sync 2026-10-09 01:04:17

This commit is contained in:
github-actions[bot] committed 2026-10-09 01:04:17 +08:00
1 parent eb76e89012
commit 812da7f08b
154 files changed
+10613 -3987

No files matched your search

+2 -2
View File
@@ -8,8 +8,8 @@ include $(TOPDIR)/rules.mk
LUCI_TITLE:=Argon Theme
LUCI_DEPENDS:=+USE_APK:wget-any +!USE_APK:wget +jsonfilter
PKG_VERSION:=2.4.7
PKG_RELEASE:=25
PKG_VERSION:=2.4.8
PKG_RELEASE:=26
CONFIG_LUCI_CSSTIDY:=
+40 -7
View File
@@ -67,6 +67,8 @@ It also supports automatic and manual switching between light and dark modes.
- The login page supports local images, videos, and online wallpapers as backgrounds.
- Works with [luci-app-argon-config][config-link] for a more complete theme configuration experience.
Choose **Classic sidebar** (default) or **Centered card** under **System → Argon Config → Login page style**. Both layouts use the same wallpaper, color and authentication settings. Update both the theme and configuration plugin to use the selector; missing or unsupported `login_style` values fall back to `classic`.
Unsplash wallpapers require an Unsplash API access key. The current `luci-app-argon-config` UI does not expose this setting; after choosing Unsplash, set it through UCI:
```sh
@@ -83,7 +85,7 @@ Support is focused on modern LuCI environments based on [Official OpenWrt][offic
## Version History
The latest version is v2.4.7 [Click here][en-us-release-log] to view the full version history record.
The latest version is v2.4.8 [Click here][en-us-release-log] to view the full version history record.
## Getting started
@@ -96,22 +98,53 @@ make menuconfig #choose LUCI->Theme->Luci-theme-argon
make -j1 V=s
```
### Choose the package format
Choose the format used by the firmware's native package manager. The presence of an `apk` command alone does not identify it:
| Firmware package manager | Release assets | Install command |
| --- | --- | --- |
| `opkg` (including OpenWrt 23.05, 24.10, and GL.iNet firmware based on these versions) | `.ipk` | `opkg install` |
| OpenWrt / ImmortalWrt using APK v3 natively (`apk-tools 3.x`) | `.apk` | `apk add --allow-untrusted` |
The APK assets use **APK v3 format**, which `apk-tools 2.x` (including `2.14.0`) cannot read. `--allow-untrusted` only bypasses signature trust checks; it does not add format support. `apk` cannot install IPK files either.
For the GL.iNet / OpenWrt 23.05 environment in [#705](https://github.com/jerrykuku/luci-theme-argon/issues/705), download IPK files and install them with the firmware's existing `opkg`. There is no need to replace the system package manager.
Download `luci-theme-argon`, `luci-app-argon-config`, and any required `luci-i18n-argon-config-<language>` packages from [Releases][release]. Select the same format for all packages and use the actual asset filenames; do not construct version suffixes or rename file extensions.
Put the downloaded files in one empty directory, keeping only one version of each package, then run the appropriate commands from that directory.
### Install release packages (`ipk`)
```bash
wget https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.4.7/luci-theme-argon_2.4.7-1_all.ipk
wget https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.4.7/luci-app-argon-config_2.4.7-1_all.ipk
opkg install ./luci-theme-argon_2.4.7-1_all.ipk ./luci-app-argon-config_2.4.7-1_all.ipk
opkg update
opkg install ./luci-theme-argon_*.ipk ./luci-app-argon-config_*.ipk
```
If you also downloaded language packages in the same format, install them with:
```bash
opkg install ./luci-i18n-argon-config-*.ipk
```
### Install release packages (`apk`)
Use this only on firmware that natively uses `apk-tools 3.x`. Check the version with `apk --version`.
```bash
wget https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.4.7/luci-theme-argon-2.4.7-r1.apk
wget https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.4.7/luci-app-argon-config-2.4.7-r1.apk
apk add --allow-untrusted ./luci-theme-argon-2.4.7-r1.apk ./luci-app-argon-config-2.4.7-r1.apk
apk update
apk add --allow-untrusted ./luci-theme-argon-*.apk ./luci-app-argon-config-*.apk
```
If you also downloaded language packages in the same format, install them with:
```bash
apk add --allow-untrusted ./luci-i18n-argon-config-*.apk
```
If you encounter `IO ERROR`, first use `ls -l ./*.apk` to check that the files exist, their names are correct, and the downloads are complete, then check `apk --version`. Do not force installation to bypass format or dependency errors.
## Screenshots
+40 -7
View File
@@ -67,6 +67,8 @@ Argon 是**一款干净整洁的 OpenWrt LuCI 主题**,
- 登录页支持本地图片、视频和在线壁纸背景。
- 可搭配 [luci-app-argon-config][config-link] 实现更完整的主题设置体验。
在 **系统 → Argon 主题设置 → 登录页样式** 中,可选择默认的**经典侧栏**或**居中卡片**。两种布局共用壁纸、配色和认证设置。请同时更新主题和配置插件以使用此选项;未配置或不支持的 `login_style` 值会回退到 `classic`。
Unsplash 在线壁纸需要 Unsplash API Access Key。当前 `luci-app-argon-config` 界面尚未提供此设置;选择 Unsplash 后,可通过 UCI 配置:
```sh
@@ -83,7 +85,7 @@ uci commit argon
## 版本历史
当前最新的版本为 v2.4.7 [点击这里][zh-cn-release-log]查看完整的版本历史日志.
当前最新的版本为 v2.4.8 [点击这里][zh-cn-release-log]查看完整的版本历史日志.
## 快速开始
@@ -96,22 +98,53 @@ make menuconfig #choose LUCI->Theme->Luci-theme-argon
make -j1 V=s
```
### 选择安装包
请按固件原生使用的包管理器选择格式,不能仅根据系统中是否有 `apk` 命令判断:
| 固件的包管理器 | Release 附件 | 安装命令 |
| --- | --- | --- |
| `opkg`(如 OpenWrt 23.05、24.10,以及基于这些版本的 GL.iNet 固件) | `.ipk` | `opkg install` |
| 原生使用 APK v3 的 OpenWrt / ImmortalWrt(`apk-tools 3.x`) | `.apk` | `apk add --allow-untrusted` |
本项目的 APK 使用 **APK v3 格式**,`apk-tools 2.x`(包括 `2.14.0`)无法读取。`--allow-untrusted` 只跳过签名信任检查,不能解决格式不兼容;`apk` 也不能安装 IPK。
对于 [#705](https://github.com/jerrykuku/luci-theme-argon/issues/705) 中的 GL.iNet / OpenWrt 23.05 环境,应下载 IPK 并使用固件原有的 `opkg` 安装,无需替换系统包管理器。
从 [Release][release] 下载主题包 `luci-theme-argon`、配置插件包 `luci-app-argon-config`,以及需要的 `luci-i18n-argon-config-<语言>` 语言包。所有包必须选择相同格式,以附件的实际文件名为准,不要自行拼接版本号或修改扩展名。
将文件放在同一个空目录中,每个包只保留一个版本,然后在该目录执行下面对应的命令。
### 安装 release 包 (`ipk`)
```bash
wget https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.4.7/luci-theme-argon_2.4.7-1_all.ipk
wget https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.4.7/luci-app-argon-config_2.4.7-1_all.ipk
opkg install ./luci-theme-argon_2.4.7-1_all.ipk ./luci-app-argon-config_2.4.7-1_all.ipk
opkg update
opkg install ./luci-theme-argon_*.ipk ./luci-app-argon-config_*.ipk
```
如已下载相同格式的语言包,再执行:
```bash
opkg install ./luci-i18n-argon-config-*.ipk
```
### 安装 release 包 (`apk`)
仅适用于固件原生使用 `apk-tools 3.x` 的环境,可用 `apk --version` 查看版本。
```bash
wget https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.4.7/luci-theme-argon-2.4.7-r1.apk
wget https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.4.7/luci-app-argon-config-2.4.7-r1.apk
apk add --allow-untrusted ./luci-theme-argon-2.4.7-r1.apk ./luci-app-argon-config-2.4.7-r1.apk
apk update
apk add --allow-untrusted ./luci-theme-argon-*.apk ./luci-app-argon-config-*.apk
```
如已下载相同格式的语言包,再执行:
```bash
apk add --allow-untrusted ./luci-i18n-argon-config-*.apk
```
遇到 `IO ERROR` 时,先用 `ls -l ./*.apk` 核对文件确实存在、名称正确且下载完整,再检查 `apk --version`;不要通过强制安装绕过包格式或依赖问题。
## 屏幕截图
+28
View File
@@ -1,5 +1,33 @@
# Update log for master branch
## v2.4.8 [ 2026.10.08 ]
### Installation / 安装说明
| Firmware / 固件 | Package / 安装包 |
| --- | --- |
| Native `opkg`, including OpenWrt 23.05 / 24.10 and GL.iNet firmware based on them / 原生使用 `opkg` 的固件 | `.ipk` → `opkg install` |
| Native APK v3 with `apk-tools 3.x` / 原生使用 APK v3 的固件 | `.apk` → `apk add --allow-untrusted` |
APK assets use **APK v3** and cannot be read by `apk-tools 2.x`, including `2.14.0`. Having an `apk` command installed on an opkg-based firmware does not make it APK v3 compatible. `--allow-untrusted` does not change format compatibility, and `apk` cannot install IPK files.
APK 附件采用 **APK v3 格式**,`apk-tools 2.x`(包括 `2.14.0`)无法读取。在原生使用 opkg 的固件上额外安装 `apk`,并不会让固件兼容 APK v3;`--allow-untrusted` 不能解决格式不兼容,`apk` 也不能安装 IPK。
Download the theme, configuration plugin, and required language packages in the **same format**. Use the exact asset filenames below. For GL.iNet / OpenWrt 23.05, use IPK files with the firmware's existing `opkg`.
主题、配置插件和需要的语言包应选择**相同格式**,以本页附件实际文件名为准。GL.iNet / OpenWrt 23.05 请下载 IPK 并使用固件原有的 `opkg` 安装。
### What's Changed
* fix(cascade): add bottom spacing for argon config form by @TuringTrail in https://github.com/jerrykuku/luci-theme-argon/pull/709
* feat(sysauth): render Authentication Login plugins on the login page by @FuSan21 in https://github.com/jerrykuku/luci-theme-argon/pull/710
* fix(sysauth): avoid blue outline on focused login inputs by @TuringTrail in https://github.com/jerrykuku/luci-theme-argon/pull/712
### New Contributors
* @TuringTrail made their first contribution in https://github.com/jerrykuku/luci-theme-argon/pull/709
**Full Changelog**: https://github.com/jerrykuku/luci-theme-argon/compare/v2.4.7...v2.4.8
## v2.4.7 [ 2026.08.24 ]
### What's Changed
+5
View File
@@ -1,5 +1,10 @@
# Master 分支的更新日志
## v2.4.8 [ 2026.10.08 ]
- GitHub Release: https://github.com/jerrykuku/luci-theme-argon/releases/tag/v2.4.8
- 详细更新内容请以 Release 页面为准。
## v2.4.7 [ 2026.08.24 ]
- GitHub Release: https://github.com/jerrykuku/luci-theme-argon/releases/tag/v2.4.7
@@ -37,6 +37,7 @@
--gray: #8898aa;
--gray-dark: #32325d;
--lighter: #e9ecef;
--table-border: thin solid #ddd;
--success: #2dce89;
--info: #11cdef;
--warning: #fb6340;
@@ -929,6 +930,102 @@ select[multiple="multiple"] {
.login-page .login-container footer .luci-link {
display: block;
}
.login-page[data-login-style="centered"] {
height: auto;
min-height: 100vh;
min-height: 100dvh;
padding: 2rem 1rem;
box-sizing: border-box;
align-items: center;
}
.login-page[data-login-style="centered"] .main-bg,
.login-page[data-login-style="centered"] .video {
position: fixed;
height: 100%;
width: 100%;
}
.login-page[data-login-style="centered"] .login-container {
flex: 0 0 auto;
width: 26rem;
max-width: 100%;
height: auto;
margin: auto 0;
border-radius: 0.75rem;
}
.login-page[data-login-style="centered"] .login-container .login-form {
min-height: 0;
}
.login-page[data-login-style="centered"] .login-container .login-form .brand {
max-width: 100%;
margin: 0;
padding: 2rem 1.5rem 1.5rem;
box-sizing: border-box;
gap: 1rem;
}
.login-page[data-login-style="centered"] .login-container .login-form .brand .icon {
width: 2.5rem;
margin: 0;
flex-shrink: 0;
}
.login-page[data-login-style="centered"] .login-container .login-form .brand .brand-text {
min-width: 0;
margin: 0;
overflow-wrap: anywhere;
}
.login-page[data-login-style="centered"] .login-container .login-form .form-login {
padding: 0 2rem;
}
.login-page[data-login-style="centered"] .login-container .login-form .form-login .input-group input {
margin: 0;
}
.login-page[data-login-style="centered"] .login-container .login-form .form-login .errorbox {
padding-bottom: 1.25rem;
overflow-wrap: anywhere;
}
.login-page[data-login-style="centered"] .login-container .login-form .form-login .auth-plugin {
max-width: 100%;
overflow-wrap: anywhere;
overflow-x: auto;
}
.login-page[data-login-style="centered"] .login-container .login-form .cbi-button-apply {
margin: 0.5rem 0 0;
padding: 0.75rem 1rem;
height: auto;
letter-spacing: 0.1rem;
white-space: normal;
}
.login-page[data-login-style="centered"] .login-container footer {
position: static;
display: block;
width: auto;
margin: 0;
padding: 1.5rem 2rem;
}
.login-page[data-login-style="centered"] .login-container footer > div {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.login-page[data-login-style="centered"] .login-container footer .luci-link {
display: inline;
}
.login-page[data-login-style="centered"] .login-container footer .login-footer-detail {
display: none;
}
.login-page[data-login-style="centered"] .login-container footer a + a::before {
content: " · ";
}
@media screen and (max-width: 480px) {
.login-page[data-login-style="centered"] {
padding: 1rem;
}
.login-page[data-login-style="centered"] .login-container .login-form .form-login {
padding: 0 1.25rem;
}
.login-page[data-login-style="centered"] .login-container footer {
padding: 1.25rem;
}
}
.main {
position: relative;
width: 100%;
@@ -1501,8 +1598,38 @@ footer > a {
}
}
#maincontent > .alert-message {
position: fixed;
transform: translate(-50%, -50%);
position: static;
width: auto;
left: auto;
top: auto;
transform: none;
z-index: auto;
margin: 0 1.25rem 1rem;
flex-wrap: wrap;
gap: 1rem;
line-height: 1.5;
}
#maincontent > .alert-message > div {
min-width: 0;
margin: 0;
}
#maincontent > .alert-message > div:first-child > * {
margin: 0;
}
#maincontent > .alert-message > div:first-child > * + * {
margin-top: 0.75rem;
}
#maincontent > .alert-message h4 {
padding: 0.5rem 0.75rem;
}
#maincontent > .alert-message .btn {
max-width: 100%;
white-space: normal;
}
@media screen and (max-width: 600px) {
#maincontent > .alert-message {
flex-direction: column;
}
}
.container .alert,
.container .alert-message {
@@ -1514,10 +1641,6 @@ footer > a {
transform: translate(-50%, 0);
width: 100%;
}
#mwan3-service-status > .alert-message {
left: 0.5rem;
transform: none;
}
.lg {
margin: 0;
padding: 0 !important;
@@ -1678,17 +1801,9 @@ body:not([data-page="admin-dashboard"]) .tr > .td,
body:not([data-page="admin-dashboard"]) .tr > .th,
body:not([data-page="admin-dashboard"]) .cbi-section-table-row::before,
body:not([data-page="admin-dashboard"]) #cbi-wireless > #wifi_assoclist_table > .tr:nth-child(2) {
border-top: thin solid #ddd;
border-top: var(--table-border);
padding: 1.1em 1.25rem;
}
@media (prefers-color-scheme: dark) {
body:not([data-page="admin-dashboard"]) tr > td,
body:not([data-page="admin-dashboard"]) tr > th,
body:not([data-page="admin-dashboard"]) .tr > .td,
body:not([data-page="admin-dashboard"]) .tr > .th {
border-top: thin solid #444 !important;
}
}
#cbi-wireless .td,
.table[width="100%"] > .tr:first-child > .td,
[data-page="admin-network-diagnostics"] .tr > .td,
@@ -2564,7 +2679,6 @@ body:not(.Interfaces) .cbi-rowstyle-2:first-child {
align-items: center;
flex-grow: 1;
}
.cbi-dropdown[empty] > ul > li,
.cbi-dropdown[optional][open] > ul.dropdown > li[placeholder],
.cbi-dropdown[multiple][open] > ul.dropdown > li > form {
display: block;
@@ -3457,6 +3571,12 @@ pre.command-output {
[data-page="admin-system-attendedsysupgrade-configuration"] .cbi-map .cbi-map-descr {
padding-bottom: 0;
}
[data-page="admin-system-flash"] .modal .btn {
height: auto;
min-height: 2.5rem;
max-width: 100%;
white-space: normal;
}
[data-page="admin-system-flash"] .cbi-value {
padding: 0 1rem;
}
@@ -3640,6 +3760,72 @@ pre.command-output {
border: 1px solid #dee2e6 !important;
border-radius: 4px;
}
[data-page="admin-network-switch-vlan"] #switch-vlan-view {
--background-color-medium: #f4f5f7;
--background-color-high: #fff;
--text-color-high: var(--gray-dark);
--text-color-low: #626b7a;
--border-color-low: #dee2e6;
--border-color-medium: #cbd5e1;
--border-color-high: #8898aa;
--primary-color-high: var(--primary);
--svc-row-bg: var(--background-color-medium);
--svc-row-hover-bg: var(--background-color-high);
--svc-row-add-bg: var(--background-color-medium);
--svc-port-selected-bg: #e8ecff;
--svc-port-selected-hover-bg: #dfe4ff;
--svc-port-selected-border: var(--primary);
--svc-port-selected-ring: rgba(94, 114, 228, 0.28);
--svc-vlan-tagged: #8c4800;
--svc-vlan-untagged: #06685f;
--svc-vlan-checked-text: #fff;
color: var(--text-color-high);
}
[data-page="admin-network-switch-vlan"] #switch-vlan-view input[type="text"],
[data-page="admin-network-switch-vlan"] #switch-vlan-view input[type="number"] {
background-color: var(--background-color-high) !important;
}
[data-page="admin-network-switch-vlan"] #switch-vlan-view input[type="text"]::placeholder,
[data-page="admin-network-switch-vlan"] #switch-vlan-view input[type="number"]::placeholder {
color: var(--text-color-low);
opacity: 1;
}
[data-page="admin-network-switch-vlan"] #switch-vlan-view input[type="text"]:focus,
[data-page="admin-network-switch-vlan"] #switch-vlan-view input[type="number"]:focus {
border-color: var(--primary-color-high) !important;
}
[data-page="admin-network-switch-vlan"] #switch-vlan-view .svc-port-tile.selected:hover {
background: var(--svc-port-selected-hover-bg);
border-color: var(--svc-port-selected-border);
}
[data-page="admin-network-switch-vlan"] #switch-vlan-view .svc-vlan-btn-tagged,
[data-page="admin-network-switch-vlan"] #switch-vlan-view .svc-vlan-btn-assign-tagged {
--svc-role-color: var(--svc-vlan-tagged);
--svc-role-bg: var(--svc-vlan-tagged-bg);
--svc-role-stripe: var(--svc-vlan-tagged-stripe);
}
[data-page="admin-network-switch-vlan"] #switch-vlan-view .svc-vlan-btn-untagged,
[data-page="admin-network-switch-vlan"] #switch-vlan-view .svc-vlan-btn-assign-untagged {
--svc-role-color: var(--svc-vlan-untagged);
--svc-role-bg: var(--svc-vlan-untagged-bg);
--svc-role-stripe: var(--svc-vlan-untagged-stripe);
}
[data-page="admin-network-switch-vlan"] #switch-vlan-view .svc-vlan-btn-tagged:not(:disabled),
[data-page="admin-network-switch-vlan"] #switch-vlan-view .svc-vlan-btn-untagged:not(:disabled),
[data-page="admin-network-switch-vlan"] #switch-vlan-view .svc-vlan-assign-btn:not(.svc-vlan-assign-disabled) {
color: var(--svc-role-color) !important;
border-color: var(--svc-role-color) !important;
}
[data-page="admin-network-switch-vlan"] #switch-vlan-view .svc-vlan-assign-btn.svc-vlan-assign-checked {
background: var(--svc-role-color);
color: var(--svc-vlan-checked-text) !important;
}
[data-page="admin-network-switch-vlan"] #switch-vlan-view .svc-vlan-assign-btn.svc-vlan-assign-mixed {
background: repeating-linear-gradient(135deg, var(--svc-role-stripe) 0 0.5rem, var(--svc-role-bg) 0.5rem 1rem);
}
[data-page="admin-network-switch-vlan"] #switch-vlan-view .svc-vlan-assign-btn.svc-vlan-assign-checked .svc-vlan-btn-prefix {
color: inherit;
}
[data-page="admin-network-dhcp"] .cbi-value {
padding: 0;
}
@@ -3747,6 +3933,11 @@ pre.command-output {
[data-page="admin-status-overview"] #view > div:first-child {
gap: 0 !important;
}
[data-page="admin-status-channel_analysis"] [data-tab-title]:not([data-tab-active="true"]) {
display: block !important;
visibility: hidden;
padding: 0;
}
[data-page="admin-status-iptables"] .right {
margin-bottom: 0 !important;
}
@@ -3779,6 +3970,20 @@ pre.command-output {
[data-page="admin-services-ttyd"] #view iframe {
height: 100%;
}
[data-page="admin-docker-overview"] .cbi-section-table {
table-layout: fixed;
}
[data-page="admin-docker-overview"] .cbi-section-table .th,
[data-page="admin-docker-overview"] .cbi-section-table .td {
min-width: 0;
white-space: normal;
overflow-wrap: anywhere;
text-align: left !important;
vertical-align: top;
}
[data-page="admin-docker-overview"] .cbi-section-table .th:first-child {
width: 30% !important;
}
#cbi-dockerd .cbi-section {
box-sizing: border-box;
padding: 16px;
@@ -4421,13 +4626,18 @@ div[style*="display:grid;grid-template-columns:repeat"] .ifacebox .ifacebox-body
}
#mwan3-service-status {
display: flex;
justify-content: center;
align-items: center;
justify-content: flex-start;
align-items: stretch;
flex-wrap: wrap;
}
#mwan3-service-status > .alert-message {
#mwan3-service-status > div.alert-message {
position: static;
transform: none;
z-index: auto;
height: auto;
min-height: 6rem;
max-width: calc(100% - 2rem);
overflow-wrap: anywhere;
}
/* responsive */
@media all and (-ms-high-contrast: none) {
@@ -1,4 +1,4 @@
body{background:#1e1e1e;color:#ccc}.spinning::before{filter:invert(1)}.login-page .login-container{background-color:rgba(0,0,0,var(--blur-opacity-dark));-webkit-backdrop-filter:blur(var(--blur-radius-dark));backdrop-filter:blur(var(--blur-radius-dark))}.login-page .login-container .login-form{background-color:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}.login-page .login-container .login-form .brand{color:#adb5bd}.login-page .login-container .login-form .form-login .input-group::before{color:#adb5bd}.login-page .login-container .login-form .form-login .input-group input{background-color:transparent!important;color:#adb5bd;border-bottom:#adb5bd 1px solid!important;border-radius:0!important;border-top:none!important;border-left:none!important;border-right:none!important;box-shadow:none}.login-page .login-container .login-form .form-login .cbi-button-apply{background-color:#483d8b!important;background-color:var(--dark-primary)!important}.login-page .login-container .login-form .form-login .cbi-button-apply:focus,.login-page .login-container .login-form .form-login .cbi-button-apply:hover{opacity:.9}header::after{background-color:#1e1e1e!important}.main .main-left{background-color:#333!important;box-shadow:0 0 .5rem 0 rgba(0,0,0,.15)}.main .main-left .sidenav-header .brand{color:#ccc}.main .main-left .nav .slide .slide-menu .active a{color:#ccc}.main .main-left .nav .slide .slide-menu .active a::after{background-color:#ccc!important}.main .main-left .nav .slide .slide-menu .active::after{background-color:var(--dark-primary)!important}.main .main-left .nav .slide .slide-menu li a{color:#ccc}.main .main-left .nav .slide .slide-menu li a:hover{background:0 0!important}.main .main-left .nav .slide .slide-menu li::after{background-color:var(--dark-primary)!important}.main .main-left .nav .slide .menu.active{background-color:#483d8b!important;background-color:var(--dark-primary)!important;color:#fff!important}.main .main-left .nav .slide .menu.active a::after{background-color:#fff!important}.main .main-left .nav li a{color:#ccc!important}.main .main-left .nav li a:hover{background-color:#483d8b!important;background-color:var(--dark-primary)!important;color:#fff!important}.main .main-left::-webkit-scrollbar-thumb{background-color:#252526!important}.main .main-left::-webkit-scrollbar-track{background-color:#333}.main .main-right{background-color:#1e1e1e}h2{color:#ccc;background:#333}h3{color:#ccc;border-bottom:0;background:#333}h4{color:#8c6900}abbr{color:var(--dark-primary)!important}a:active,a:link,a:visited{color:#a5b2ff}input:-webkit-autofill{background-color:#3c3c3c!important}#channel_graph{background-color:transparent!important}.cbi-button-apply,.cbi-button-edit,.cbi-value-field .cbi-input-apply{color:#fff!important;background-color:#483d8b!important;background-color:var(--dark-primary)!important;border-color:#483d8b!important;border-color:var(--dark-primary)!important}.cbi-section em{color:#ccc}header.bg-primary{background-color:#1e1e1e!important}.cbi-map-descr{color:#ccc}.cbi-section{background:0 0;box-shadow:0 0 .5rem 0 rgba(0,0,0,.35)}.panel-title{color:#ccc;background-color:#333}div>.table>.tr:nth-of-type(2n),div>table>tbody>tr:nth-of-type(2n){background-color:#252526}table>tbody>tr>td,table>tfoot>tr>td,table>thead>tr>td{color:#ccc}fieldset>table>tbody>tr:nth-of-type(2n){background-color:#252526}table>tbody>tr>td,table>tfoot>tr>td,table>thead>tr>td{border-top:1px solid #252526}#conns>div>div,#membuff>div>div,#memfree>div>div,#memtotal>div>div,#swapfree>div>div,#swaptotal>div>div{background-color:var(--dark-primary)!important}#conns>div>div>div>small,#membuff>div>div>div>small,#memfree>div>div>div>small,#memtotal>div>div>div>small,#swapfree>div>div>div>small,#swaptotal>div>div>div>small{color:#ccc!important}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last{line-height:1.8em}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"]{border:1px solid #999!important;background-color:transparent!important}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"] div{background-color:#ba8b00!important}table>tbody>tr>th,table>tfoot>tr>th,table>thead>tr>th{background-color:#252526;border-bottom:#000 1px solid!important}.tr.cbi-section-table-titles.named::before,.tr[data-title]::before{background-color:#252526}#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2),.cbi-section-table-row::before,.tr>.td,.tr>.th,tr>td,tr>th{border-top:0}.cbi-rowstyle-2{background-color:#1e1e1e}.cbi-rowstyle-1{background-color:#252526}.cbi-rowstyle-2 .cbi-button-down,.cbi-rowstyle-2 .cbi-button-up,body:not(.Interfaces) .cbi-rowstyle-2:first-child{background-color:#666!important}.cbi-section>h3:first-child,.panel-title,h3{color:#ccc}h4{background-color:#1e1e1f}.cLine truncated
:root{--table-border:0}body{background:#1e1e1e;color:#ccc}.spinning::before{filter:invert(1)}.login-page .login-container{background-color:rgba(0,0,0,var(--blur-opacity-dark));-webkit-backdrop-filter:blur(var(--blur-radius-dark));backdrop-filter:blur(var(--blur-radius-dark))}.login-page .login-container .login-form{background-color:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}.login-page .login-container .login-form .brand{color:#adb5bd}.login-page .login-container .login-form .form-login .input-group::before{color:#adb5bd}.login-page .login-container .login-form .form-login .input-group input{background-color:transparent!important;color:#adb5bd;border-bottom:#adb5bd 1px solid!important;border-radius:0!important;border-top:none!important;border-left:none!important;border-right:none!important;box-shadow:none}.login-page .login-container .login-form .form-login .cbi-button-apply{background-color:#483d8b!important;background-color:var(--dark-primary)!important}.login-page .login-container .login-form .form-login .cbi-button-apply:focus,.login-page .login-container .login-form .form-login .cbi-button-apply:hover{opacity:.9}header::after{background-color:#1e1e1e!important}.main .main-left{background-color:#333!important;box-shadow:0 0 .5rem 0 rgba(0,0,0,.15)}.main .main-left .sidenav-header .brand{color:#ccc}.main .main-left .nav .slide .slide-menu .active a{color:#ccc}.main .main-left .nav .slide .slide-menu .active a::after{background-color:#ccc!important}.main .main-left .nav .slide .slide-menu .active::after{background-color:var(--dark-primary)!important}.main .main-left .nav .slide .slide-menu li a{color:#ccc}.main .main-left .nav .slide .slide-menu li a:hover{background:0 0!important}.main .main-left .nav .slide .slide-menu li::after{background-color:var(--dark-primary)!important}.main .main-left .nav .slide .menu.active{background-color:#483d8b!important;background-color:var(--dark-primary)!important;color:#fff!important}.main .main-left .nav .slide .menu.active a::after{background-color:#fff!important}.main .main-left .nav li a{color:#ccc!important}.main .main-left .nav li a:hover{background-color:#483d8b!important;background-color:var(--dark-primary)!important;color:#fff!important}.main .main-left::-webkit-scrollbar-thumb{background-color:#252526!important}.main .main-left::-webkit-scrollbar-track{background-color:#333}.main .main-right{background-color:#1e1e1e}h2{color:#ccc;background:#333}h3{color:#ccc;border-bottom:0;background:#333}h4{color:#8c6900}abbr{color:var(--dark-primary)!important}a:active,a:link,a:visited{color:#a5b2ff}input:-webkit-autofill{background-color:#3c3c3c!important}#channel_graph{background-color:transparent!important}.cbi-button-apply,.cbi-button-edit,.cbi-value-field .cbi-input-apply{color:#fff!important;background-color:#483d8b!important;background-color:var(--dark-primary)!important;border-color:#483d8b!important;border-color:var(--dark-primary)!important}.cbi-section em{color:#ccc}header.bg-primary{background-color:#1e1e1e!important}.cbi-map-descr{color:#ccc}.cbi-section{background:0 0;box-shadow:0 0 .5rem 0 rgba(0,0,0,.35)}.panel-title{color:#ccc;background-color:#333}div>.table>.tr:nth-of-type(2n),div>table>tbody>tr:nth-of-type(2n){background-color:#252526}table>tbody>tr>td,table>tfoot>tr>td,table>thead>tr>td{color:#ccc}fieldset>table>tbody>tr:nth-of-type(2n){background-color:#252526}table>tbody>tr>td,table>tfoot>tr>td,table>thead>tr>td{border-top:1px solid #252526}#conns>div>div,#membuff>div>div,#memfree>div>div,#memtotal>div>div,#swapfree>div>div,#swaptotal>div>div{background-color:var(--dark-primary)!important}#conns>div>div>div>small,#membuff>div>div>div>small,#memfree>div>div>div>small,#memtotal>div>div>div>small,#swapfree>div>div>div>small,#swaptotal>div>div>div>small{color:#ccc!important}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last{line-height:1.8em}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"]{border:1px solid #999!important;background-color:transparent!important}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"] div{background-color:#ba8b00!important}table>tbody>tr>th,table>tfoot>tr>th,table>thead>tr>th{background-color:#252526;border-bottom:#000 1px solid!important}.tr.cbi-section-table-titles.named::before,.tr[data-title]::before{background-color:#252526}#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2),.cbi-section-table-row::before,.tr>.td,.tr>.th,tr>td,tr>th{border-top:0}.cbi-rowstyle-2{background-color:#1e1e1e}.cbi-rowstyle-1{background-color:#252526}.cbi-rowstyle-2 .cbi-button-down,.cbi-rowstyle-2 .cbi-button-up,body:not(.Interfaces) .cbi-rowstyle-2:first-child{background-color:#666!important}.cbi-section>h3:first-child,.panel-title,h3{color:#ccc}h4{backLine truncated
.modal>pre,.modal>textarea{color: #ccc}
.login-page.defwallpaper .login-container{background-color: rgb(136 136 136 / 14%);backdrop-filter: blur(0);margin:0 auto;}
.defwallpaper.defwallpaper .main-bg img{object-position: -99999px -99999px;opacity: 0;}
+40 -20
View File
@@ -39,6 +39,7 @@
--gray: #8898aa;
--gray-dark: #32325d;
--lighter: #e9ecef;
--table-border: thin solid #ddd;
--success: #2dce89;
--info: #11cdef;
--warning: #fb6340;
@@ -323,8 +324,43 @@ select[multiple="multiple"] {
}
#maincontent > .alert-message {
position: fixed;
transform: translate(-50%, -50%);
// LuCI inserts notification banners before the view container.
position: static;
width: auto;
left: auto;
top: auto;
transform: none;
z-index: auto;
margin: 0 1.25rem 1rem;
flex-wrap: wrap;
gap: 1rem;
line-height: 1.5;
> div {
min-width: 0;
margin: 0;
}
> div:first-child > * {
margin: 0;
+ * {
margin-top: .75rem;
}
}
h4 {
padding: .5rem .75rem;
}
.btn {
max-width: 100%;
white-space: normal;
}
@media screen and (max-width: 600px) {
flex-direction: column;
}
}
.container .alert,
@@ -338,11 +374,6 @@ select[multiple="multiple"] {
width: 100%;
}
#mwan3-service-status > .alert-message {
left: 0.5rem;
transform: none;
}
.lg {
margin: 0;
padding: 0 !important;
@@ -528,22 +559,11 @@ body:not([data-page="admin-dashboard"]) {
.tr>.th,
.cbi-section-table-row::before,
#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2) {
border-top: thin solid #ddd;
border-top: var(--table-border);
padding: 1.1em 1.25rem;
}
}
@media (prefers-color-scheme: dark) {
body:not([data-page="admin-dashboard"]) {
tr>td,
tr>th,
.tr>.td,
.tr>.th {
border-top: thin solid #444 !important;
}
}
}
#cbi-wireless .td,
.table[width="100%"]>.tr:first-child>.td,
[data-page="admin-network-diagnostics"] .tr>.td,
@@ -1549,6 +1569,7 @@ body:not(.Interfaces) .cbi-rowstyle-2:first-child {
border-left: thin solid #ccc;
}
// Empty selections use .more; list items stay hidden until the menu opens.
.cbi-dropdown[empty]>ul {
max-width: 1px;
}
@@ -1612,7 +1633,6 @@ body:not(.Interfaces) .cbi-rowstyle-2:first-child {
}
.cbi-dropdown[empty]>ul>li,
.cbi-dropdown[optional][open]>ul.dropdown>li[placeholder],
.cbi-dropdown[multiple][open]>ul.dropdown>li>form {
display: block;
+31 -6
View File
@@ -29,6 +29,11 @@
*/
// Follow the active theme stylesheet, including forced dark mode.
:root {
--table-border: 0;
}
body {
background: #1e1e1e;
color: #cccccc;
@@ -833,18 +838,14 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] {
border-color: #fff !important;
}
.btn {
white-space: normal !important;
background-color: darkseagreen;
}
.alert-message {
background-color: transparent !important;
}
.danger {
border: thin solid darkorange !important;
background-color: darkorange !important;
background-color: #784f00 !important;
color: #fff;
}
}
}
@@ -1081,6 +1082,30 @@ input,
}
}
// The switch-vlan page uses Bootstrap variables and its own dark-mode marker.
// Map its palette here so forced and system-following Argon modes both work.
[data-page="admin-network-switch-vlan"] #switch-vlan-view {
--background-color-medium: #252526;
--background-color-high: #333;
--text-color-high: #ccc;
--text-color-low: #adb5bd;
--border-color-low: #3c3c3c;
--border-color-medium: #515151;
--border-color-high: #8898aa;
--primary-color-high: var(--dark-primary);
--svc-port-selected-bg: #34314b;
--svc-port-selected-hover-bg: #413c60;
--svc-port-selected-border: #a5b2ff;
--svc-port-selected-ring: rgba(165, 178, 255, 0.28);
--svc-vlan-untagged: #2dd4bf;
--svc-vlan-tagged: #fbbf24;
--svc-vlan-untagged-bg: rgba(45, 212, 191, 0.08);
--svc-vlan-tagged-bg: rgba(251, 191, 36, 0.1);
--svc-vlan-untagged-stripe: rgba(45, 212, 191, 0.16);
--svc-vlan-tagged-stripe: rgba(251, 191, 36, 0.18);
--svc-vlan-checked-text: #1e1e1e;
}
[data-page="admin-network-diagnostics"] {
.cbi-section {
background: #252526 !important;
+128 -7
View File
@@ -156,6 +156,14 @@
// System - Flash Firmware
[data-page="admin-system-flash"] {
// Upgrade options use button-styled labels with multiline text.
.modal .btn {
height: auto;
min-height: 2.5rem;
max-width: 100%;
white-space: normal;
}
.cbi-value {
padding: 0 1rem;
}
@@ -445,6 +453,86 @@
}
}
// Network - Switch / VLAN (LuCI's page stylesheet loads after the theme)
[data-page="admin-network-switch-vlan"] #switch-vlan-view {
--background-color-medium: #f4f5f7;
--background-color-high: #fff;
--text-color-high: var(--gray-dark);
--text-color-low: #626b7a;
--border-color-low: #dee2e6;
--border-color-medium: #cbd5e1;
--border-color-high: #8898aa;
--primary-color-high: var(--primary);
--svc-row-bg: var(--background-color-medium);
--svc-row-hover-bg: var(--background-color-high);
--svc-row-add-bg: var(--background-color-medium);
--svc-port-selected-bg: #e8ecff;
--svc-port-selected-hover-bg: #dfe4ff;
--svc-port-selected-border: var(--primary);
--svc-port-selected-ring: rgba(94, 114, 228, 0.28);
--svc-vlan-tagged: #8c4800;
--svc-vlan-untagged: #06685f;
--svc-vlan-checked-text: #fff;
color: var(--text-color-high);
input[type="text"],
input[type="number"] {
background-color: var(--background-color-high) !important;
&::placeholder {
color: var(--text-color-low);
opacity: 1;
}
&:focus {
border-color: var(--primary-color-high) !important;
}
}
.svc-port-tile.selected:hover {
background: var(--svc-port-selected-hover-bg);
border-color: var(--svc-port-selected-border);
}
.svc-vlan-btn-tagged,
.svc-vlan-btn-assign-tagged {
--svc-role-color: var(--svc-vlan-tagged);
--svc-role-bg: var(--svc-vlan-tagged-bg);
--svc-role-stripe: var(--svc-vlan-tagged-stripe);
}
.svc-vlan-btn-untagged,
.svc-vlan-btn-assign-untagged {
--svc-role-color: var(--svc-vlan-untagged);
--svc-role-bg: var(--svc-vlan-untagged-bg);
--svc-role-stripe: var(--svc-vlan-untagged-stripe);
}
// Preserve T/U colors against Argon's generic button color and border rules.
.svc-vlan-btn-tagged:not(:disabled),
.svc-vlan-btn-untagged:not(:disabled),
.svc-vlan-assign-btn:not(.svc-vlan-assign-disabled) {
color: var(--svc-role-color) !important;
border-color: var(--svc-role-color) !important;
}
.svc-vlan-assign-btn.svc-vlan-assign-checked {
background: var(--svc-role-color);
color: var(--svc-vlan-checked-text) !important;
}
.svc-vlan-assign-btn.svc-vlan-assign-mixed {
background: repeating-linear-gradient(135deg,
var(--svc-role-stripe) 0 0.5rem,
var(--svc-role-bg) 0.5rem 1rem);
}
.svc-vlan-assign-btn.svc-vlan-assign-checked .svc-vlan-btn-prefix {
color: inherit;
}
}
// Network - DHCP and DNS
[data-page="admin-network-dhcp"] {
.cbi-value {
@@ -592,6 +680,15 @@
}
}
// Status - Channel Analysis
[data-page="admin-status-channel_analysis"] [data-tab-title]:not([data-tab-active="true"]) {
// LuCI measures every band's graph before its tab is activated. Preserve
// the width of inactive panes while the shared tab rules collapse height.
display: block !important;
visibility: hidden;
padding: 0;
}
// Status - IPTables
[data-page="admin-status-iptables"] {
.right {
@@ -652,6 +749,24 @@
}
// Services - Dockerman
[data-page="admin-docker-overview"] .cbi-section-table {
// Keep long JSON values inside the Version and Environment tables.
table-layout: fixed;
.th,
.td {
min-width: 0;
white-space: normal;
overflow-wrap: anywhere;
text-align: left !important;
vertical-align: top;
}
.th:first-child {
width: 30% !important;
}
}
#cbi-dockerd {
.cbi-section {
box-sizing: border-box;
@@ -1475,15 +1590,21 @@ div[style*="display:grid;grid-template-columns:repeat"] {
display: none;
}
// overview & mwan3
// MultiWAN cards in the system overview and the mwan3 overview.
#mwan3-service-status {
display: flex;
justify-content: center;
align-items: center;
justify-content: flex-start;
align-items: stretch;
flex-wrap: wrap;
}
#mwan3-service-status > .alert-message {
position: static;
transform: none;
// Override mwan3.css even when the view loads it after the theme.
>div.alert-message {
position: static;
transform: none;
z-index: auto;
height: auto;
min-height: 6rem;
max-width: calc(100% - 2rem);
overflow-wrap: anywhere;
}
}
+117
View File
@@ -278,3 +278,120 @@
}
}
}
// Keep all authentication markup shared; only the centered layout differs.
.login-page[data-login-style="centered"] {
height: auto;
min-height: 100vh;
min-height: 100dvh;
padding: 2rem 1rem;
box-sizing: border-box;
align-items: center;
.main-bg,
.video {
position: fixed;
height: 100%;
width: 100%;
}
.login-container {
flex: 0 0 auto;
width: 26rem;
max-width: 100%;
height: auto;
margin: auto 0;
border-radius: .75rem;
.login-form {
min-height: 0;
.brand {
max-width: 100%;
margin: 0;
padding: 2rem 1.5rem 1.5rem;
box-sizing: border-box;
gap: 1rem;
.icon {
width: 2.5rem;
margin: 0;
flex-shrink: 0;
}
.brand-text {
min-width: 0;
margin: 0;
overflow-wrap: anywhere;
}
}
.form-login {
padding: 0 2rem;
.input-group input {
margin: 0;
}
.errorbox {
padding-bottom: 1.25rem;
overflow-wrap: anywhere;
}
.auth-plugin {
max-width: 100%;
overflow-wrap: anywhere;
overflow-x: auto;
}
}
.cbi-button-apply {
margin: .5rem 0 0;
padding: .75rem 1rem;
height: auto;
letter-spacing: .1rem;
white-space: normal;
}
}
footer {
position: static;
display: block;
width: auto;
margin: 0;
padding: 1.5rem 2rem;
> div {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.luci-link {
display: inline;
}
.login-footer-detail {
display: none;
}
a + a::before {
content: " · ";
}
}
}
@media screen and (max-width: 480px) {
padding: 1rem;
.login-container {
.login-form .form-login {
padding: 0 1.25rem;
}
footer {
padding: 1.25rem;
}
}
}
}
@@ -118,6 +118,19 @@ for (const template of ['header.ut', 'header_login.ut']) {
});
}
test('login layouts allow supported styles and fall back for old or invalid configs', () => {
const selected = (value, hasConfig = true) => runUcodeSnippet(
'ucode/template/themes/argon/sysauth.ut',
"let login_style = 'classic';", '\n\t// Per-request',
configSetup + '\nlet fs = { access };', 'login_style', { login_style: value }, hasConfig
);
assert.equal(selected('classic'), 'classic');
assert.equal(selected('centered'), 'centered');
assert.equal(selected('centered', false), 'classic');
for (const value of [undefined, null, '', 'unknown', 'CENTERED', '" onclick="alert(1)', '../centered', 1, ['centered'], {}])
assert.equal(selected(value), 'classic');
});
test('local backgrounds accept dotted names and encode spaces', () => {
const setup = `
let fs = { lsdir: path => ['photo.jpg', 'my.photo.jpg', 'space name.webp', 'hash#name.jpg', 'what?.png', 'VIDEO.MP4', 'notes.txt'] };
@@ -17,10 +17,13 @@
-#}
</div>
<!-- added style="text-wrap: auto" but on this page it is still not the best solution. I will take it to consideration next time :) -->
<footer style="text-wrap: auto">
<div>
<a class="luci-link" href="{{ version.disturl }}" target="_blank">{{ version.distname }} {{ version.distversion }}-{{ version.distrevision }}</a>
{%
const luci_info = 'Powered by ' + version.luciname + ' (' + version.luciversion + ')';
const firmware_info = version.distname + ' ' + version.distversion + '-' + version.distrevision;
%}
<footer>
<div title="{{ entityencode(luci_info + ' · ArgonTheme · ' + firmware_info, true) }}">
<a class="luci-link" href="{{ version.disturl }}" target="_blank" title="{{ entityencode(firmware_info, true) }}">{{ version.distname }} {{ version.distversion }}<span class="login-footer-detail">-{{ version.distrevision }}</span></a>
</div>
</footer>
</div>
@@ -28,12 +31,6 @@
<script>
// thanks for Jo-Philipp Wich <jow@openwrt.org>
var luciLocation = {{ ctx.path }};
const loginContainer = document.querySelector(
'div[class="login-container"][style*="backdrop-filter: blur(0px)"]'
);
if (loginContainer) {
loginContainer.style.margin = '0 auto';
}
</script>
</body>
</html>
@@ -27,6 +27,14 @@
import { cursor } from 'uci';
let cfg = cursor();
// Only known layouts may select login page styles; old configs stay classic.
let login_style = 'classic';
if (fs.access('/etc/config/argon')) {
let configured_style = cfg.get_first('argon', 'global', 'login_style');
if (configured_style == 'classic' || configured_style == 'centered')
login_style = configured_style;
}
// Per-request pseudo-random state for selecting local backgrounds.
let lcgState = (+time()) % 2147483648;
@@ -63,7 +71,7 @@
let mimeType = "";
if (fs.access("/etc/config/argon")) {
online_wallpaper = cfg.get_first('argon', 'global', 'online_wallpaper') ?? (cfg.get_first('argon', 'global', 'bing_background') == '1' ? 'bing' : null);
let online_wallpaper = cfg.get_first('argon', 'global', 'online_wallpaper') ?? (cfg.get_first('argon', 'global', 'bing_background') == '1' ? 'bing' : null);
if (online_wallpaper && online_wallpaper != "none") {
const picurl = ubus.call("luci.argon_wallpaper", "get_url") ?? {};
if (type(picurl?.url) == 'string' && match(picurl.url, /^https:\/\/[^[:space:]"'<>]+$/)) {
@@ -93,7 +101,7 @@
%}
<!-- Login Page Start -->
<div class="login-page {{ online_wallpaper == 'default' ? ' defwallpaper' : '' }}">
<div class="login-page" data-login-style="{{ login_style }}">
{% if ( bgArry.backgroundType == "Video" ): %}
<!-- Video Player Start -->
<div class="video">