From 26e9df1a69cabdb25bd7505f65cfa19acaaa7f57 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 15 Jun 2026 22:09:15 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8F=85=20Sync=202026-06-15=2022:09:15?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- autocore/Makefile | 2 +- autocore/files/autocore | 5 - cloudreve/Makefile | 5 +- dae/Makefile | 6 +- daed/Makefile | 6 +- luci-app-daede/Makefile | 2 +- .../resources/view/daede/updates.js | 67 +- .../usr/share/luci-app-daede/refresh-index.sh | 20 + .../usr/share/luci-app-daede/update-geo.sh | 24 +- .../usr/share/luci-app-daede/update-pkg.sh | 21 +- .../usr/share/rpcd/acl.d/luci-app-daede.json | 1 + .../root/usr/share/rpcd/ucode/luci.fchomo | 17 +- .../root/usr/share/ucode/fchomo.uc | 2 +- luci-app-passwall2/Makefile | 2 +- .../luasrc/passwall2/util_xray.lua | 5 - luci-app-wechatpush/Makefile | 2 +- .../root/usr/share/wechatpush/wechatpush | 12 +- luci-theme-aurora/.dev/docs/DEVELOPMENT.md | 46 +- luci-theme-aurora/.dev/package.json | 9 +- luci-theme-aurora/.dev/pnpm-lock.yaml | 204 ++++- luci-theme-aurora/.dev/scripts/gen-tokens.js | 80 ++ luci-theme-aurora/.dev/src/media/_base.css | 90 +-- .../.dev/src/media/_elements.css | 88 +++ luci-theme-aurora/.dev/src/media/_layout.css | 97 +-- luci-theme-aurora/.dev/src/media/_patches.css | 10 +- luci-theme-aurora/.dev/src/media/_tokens.css | 287 ++----- .../.dev/src/media/_utilities.css | 4 +- .../.dev/src/media/components/_badge.css | 16 +- .../.dev/src/media/components/_button.css | 10 +- .../.dev/src/media/components/_card.css | 20 +- .../.dev/src/media/components/_dropdown.css | 10 +- .../src/media/components/_float-button.css | 12 +- .../.dev/src/media/components/_form.css | 14 +- .../.dev/src/media/components/_input.css | 4 +- .../.dev/src/media/components/_message.css | 10 +- .../.dev/src/media/components/_modal.css | 28 +- .../.dev/src/media/components/_nav.css | 65 +- .../.dev/src/media/components/_overlay.css | 47 +- .../.dev/src/media/components/_progress.css | 4 +- .../.dev/src/media/components/_segmented.css | 8 +- .../.dev/src/media/components/_select.css | 2 +- .../.dev/src/media/components/_switcher.css | 22 +- .../.dev/src/media/components/_tab.css | 8 +- .../.dev/src/media/components/_table.css | 39 +- .../.dev/src/media/components/_textarea.css | 2 +- .../.dev/src/media/components/_tooltip.css | 10 +- luci-theme-aurora/.dev/src/media/login.css | 39 +- luci-theme-aurora/.dev/src/media/main.css | 1 + .../.dev/src/resource/menu-aurora.js | 480 ++++++------ luci-theme-aurora/.dev/tests/engine.test.js | 41 + .../.dev/tests/navigation-model.test.js | 569 ++++++++++++++ .../.dev/tests/navigation-rendering.test.js | 723 ++++++++++++++++++ .../.dev/tests/navigation-styles.test.js | 159 ++++ luci-theme-aurora/.dev/tests/overlay.test.js | 27 + luci-theme-aurora/.dev/tests/resolve.test.js | 69 ++ luci-theme-aurora/.dev/tests/surfaces.test.js | 84 ++ luci-theme-aurora/.dev/tokens/defaults.js | 27 + luci-theme-aurora/.dev/tokens/engine.js | 32 + luci-theme-aurora/.dev/tokens/resolve.js | 51 ++ luci-theme-aurora/.dev/tokens/spec.js | 62 ++ luci-theme-aurora/.dev/vite.config.ts | 7 + luci-theme-aurora/CLAUDE.md | 14 +- luci-theme-aurora/Makefile | 4 +- .../htdocs/luci-static/aurora/login.css | 2 +- .../htdocs/luci-static/aurora/main.css | 2 +- .../luci-static/resources/menu-aurora.js | 2 +- opera-proxy/Makefile | 18 +- tun2socks/Makefile | 24 +- 68 files changed, 2964 insertions(+), 918 deletions(-) create mode 100755 luci-app-daede/root/usr/share/luci-app-daede/refresh-index.sh create mode 100644 luci-theme-aurora/.dev/scripts/gen-tokens.js create mode 100644 luci-theme-aurora/.dev/src/media/_elements.css create mode 100644 luci-theme-aurora/.dev/tests/engine.test.js create mode 100644 luci-theme-aurora/.dev/tests/navigation-model.test.js create mode 100644 luci-theme-aurora/.dev/tests/navigation-rendering.test.js create mode 100644 luci-theme-aurora/.dev/tests/navigation-styles.test.js create mode 100644 luci-theme-aurora/.dev/tests/overlay.test.js create mode 100644 luci-theme-aurora/.dev/tests/resolve.test.js create mode 100644 luci-theme-aurora/.dev/tests/surfaces.test.js create mode 100644 luci-theme-aurora/.dev/tokens/defaults.js create mode 100644 luci-theme-aurora/.dev/tokens/engine.js create mode 100644 luci-theme-aurora/.dev/tokens/resolve.js create mode 100644 luci-theme-aurora/.dev/tokens/spec.js diff --git a/autocore/Makefile b/autocore/Makefile index d1048ec6..62458fa9 100644 --- a/autocore/Makefile +++ b/autocore/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=autocore PKG_FLAGS:=nonshared -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_CONFIG_DEPENDS:= \ CONFIG_TARGET_bcm27xx \ diff --git a/autocore/files/autocore b/autocore/files/autocore index b0214d6b..b27b42df 100755 --- a/autocore/files/autocore +++ b/autocore/files/autocore @@ -9,11 +9,6 @@ start() { sysctl -w net.core.rps_sock_flow_entries="$(( rfc * threads ))" - for fileRps in /sys/class/net/eth*/queues/rx-*/rps_cpus - do - echo "$threads" > "$fileRps" - done - for fileRfc in /sys/class/net/eth*/queues/rx-*/rps_flow_cnt do echo "$rfc" > "$fileRfc" diff --git a/cloudreve/Makefile b/cloudreve/Makefile index f95edf21..88b833b1 100644 --- a/cloudreve/Makefile +++ b/cloudreve/Makefile @@ -6,11 +6,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=cloudreve PKG_VERSION:=4.16.1 -PKG_RELEASE:=8 +PKG_RELEASE:=9 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/cloudreve/Cloudreve.git -PKG_SOURCE_VERSION:=26b6b1044b0253c5ead7d5a90eaa10ff67ac2582 +PKG_SOURCE_VERSION:=ba2e870bbd17f1918dd2321de861e453f696d6a3 PKG_MIRROR_HASH:=skip PKG_LICENSE:=GPL-3.0-only @@ -23,6 +23,7 @@ PKG_BUILD_PARALLEL:=1 PKG_BUILD_FLAGS:=no-mips16 GO_PKG:=github.com/cloudreve/Cloudreve/v4 +GO_PKG_EXCLUDES:=pkg/request/ssrftest GO_PKG_LDFLAGS_X:= \ $(GO_PKG)/application/constants.BackendVersion=$(PKG_VERSION) \ $(GO_PKG)/application/constants.LastCommit=$(PKG_VERSION) diff --git a/dae/Makefile b/dae/Makefile index d6e4d688..77af759d 100644 --- a/dae/Makefile +++ b/dae/Makefile @@ -3,10 +3,10 @@ include $(TOPDIR)/rules.mk PKG_NAME:=dae -PKG_VERSION:=2026.06.08 -PKG_RELEASE:=5 +PKG_VERSION:=2026.06.14 +PKG_RELEASE:=6 -PKG_SOURCE:=dae-src-$(PKG_VERSION).tar.gz +PKG_SOURCE:=dae-src-2026.06.14-fa89ea7197a5.tar.gz PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/dae-src PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) PKG_HASH:=skip diff --git a/daed/Makefile b/daed/Makefile index 35054777..7ce04c99 100644 --- a/daed/Makefile +++ b/daed/Makefile @@ -3,10 +3,10 @@ include $(TOPDIR)/rules.mk PKG_NAME:=daed -PKG_VERSION:=2026.06.08 -PKG_RELEASE:=7 +PKG_VERSION:=2026.06.14 +PKG_RELEASE:=8 -PKG_SOURCE:=daed-src-$(PKG_VERSION).tar.gz +PKG_SOURCE:=daed-src-2026.06.14-4e215048068a.tar.gz PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/daed-src PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) PKG_HASH:=skip diff --git a/luci-app-daede/Makefile b/luci-app-daede/Makefile index 7f7d63d2..a1c7905f 100644 --- a/luci-app-daede/Makefile +++ b/luci-app-daede/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-daede PKG_VERSION:=1.12.0 -PKG_RELEASE:=8 +PKG_RELEASE:=9 PKG_MAINTAINER:=kenzok8 PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) diff --git a/luci-app-daede/htdocs/luci-static/resources/view/daede/updates.js b/luci-app-daede/htdocs/luci-static/resources/view/daede/updates.js index 73338403..e7a439df 100644 --- a/luci-app-daede/htdocs/luci-static/resources/view/daede/updates.js +++ b/luci-app-daede/htdocs/luci-static/resources/view/daede/updates.js @@ -27,6 +27,7 @@ const CSS = [ '.dd-up-icon{font-size:14px;text-align:center;line-height:1}', '.dd-up-ok{color:#3da66a}', '.dd-up-warn{color:#d39e00}', + '.dd-up-new{color:#4a8cff}', '.dd-up-err{color:#d96d6d}', '.dd-up-name{font-weight:600;opacity:.85}', '.dd-up-meta{opacity:.7;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}', @@ -101,17 +102,10 @@ function probePkg(pkg) { }); } -function tailLog(path, into) { - return L.resolveDefault(fs.read_direct(path, 'text'), '').then(function(content) { - if (content) { - into.textContent = content; - into.classList.add('show'); - } - }); -} - return view.extend({ load: function() { + // background apk update so new versions show on next poll + fs.exec('/usr/share/luci-app-daede/refresh-index.sh', []).catch(function() {}); return Promise.all([ backend.detectBackend(), uci.load('daed').catch(function() {}) @@ -145,35 +139,48 @@ return view.extend({ ]); }; - // === Data updates (GeoIP / GeoSite) === - const updateGeo = function(kind, btn) { - const label = kind === 'geoip' ? 'GeoIP' : 'GeoSite'; + // run a backgrounded script, stream its log, then toast the result. + // Scripts end their log with "done (rc=N)"; poll until that appears. + const runJob = function(script, arg, btn, logPath, label) { + const orig = btn.textContent; btn.disabled = true; btn.textContent = '...'; - return fs.exec('/usr/share/luci-app-daede/update-geo.sh', [kind]).then(function(res) { - if (res.code === 0) { - setTimeout(function() { tailLog('/tmp/luci-app-daede.' + kind + '.log', logPane); }, 2000); - } + let tries = 0; + const poll = function() { + return L.resolveDefault(fs.read_direct(logPath, 'text'), '').then(function(c) { + if (c) { logPane.textContent = c; logPane.classList.add('show'); } + const m = c.match(/done \(rc=(\d+)\)/); + if (m) { + const ok = m[1] === '0'; + ui.addNotification(null, E('p', label + ' · ' + (ok ? _('done') : _('failed'))), ok ? null : 'danger'); + refresh(); + return; + } + if (tries++ > 90) return; + return new Promise(function(r) { setTimeout(r, 2000); }).then(poll); + }); + }; + return fs.exec('/usr/share/luci-app-daede/' + script, [arg]).then(function(res) { + if (res.code !== 0) { ui.addNotification(null, E('p', label + ' · ' + _('failed to start')), 'danger'); return; } + return poll(); }).catch(function() {}).finally(function() { btn.disabled = false; - btn.textContent = _('Update'); + btn.textContent = orig; }); }; + // === Data updates (GeoIP / GeoSite) === + const updateGeo = function(kind, btn) { + return runJob('update-geo.sh', kind, btn, + '/tmp/luci-app-daede.' + kind + '.log', kind === 'geoip' ? 'GeoIP' : 'GeoSite'); + }; + // === Package updates (dae|daed / luci-app-daede) === const upgradePkg = function(pkg, btn) { - if (!confirm(_('Run "apk upgrade %s" now? This may restart the active backend.').format(pkg))) + if (!confirm(_('Upgrade %s now? This may restart the active backend.').format(pkg))) return; - btn.disabled = true; - btn.textContent = '...'; - return fs.exec('/usr/share/luci-app-daede/update-pkg.sh', [pkg]).then(function(res) { - if (res.code === 0) { - setTimeout(function() { tailLog('/tmp/luci-app-daede.pkg-' + pkg + '.log', logPane); }, 3000); - } - }).catch(function() {}).finally(function() { - btn.disabled = false; - btn.textContent = _('Upgrade'); - }); + return runJob('update-pkg.sh', pkg, btn, + '/tmp/luci-app-daede.pkg-' + pkg + '.log', pkg); }; const refresh = function() { @@ -256,8 +263,8 @@ return view.extend({ btn.disabled = true; } pkgBody.appendChild(mkRow( - updatable ? '⚠' : (entry.r.installed ? '✓' : '✗'), - updatable ? 'dd-up-warn' : (entry.r.installed ? 'dd-up-ok' : 'dd-up-err'), + updatable ? '↑' : (entry.r.installed ? '✓' : '✗'), + updatable ? 'dd-up-new' : (entry.r.installed ? 'dd-up-ok' : 'dd-up-err'), entry.name, meta, btn diff --git a/luci-app-daede/root/usr/share/luci-app-daede/refresh-index.sh b/luci-app-daede/root/usr/share/luci-app-daede/refresh-index.sh new file mode 100755 index 00000000..cd322cd8 --- /dev/null +++ b/luci-app-daede/root/usr/share/luci-app-daede/refresh-index.sh @@ -0,0 +1,20 @@ +#!/bin/sh +# Background apk/opkg update for the Updates view. Returns at once; throttled. + +LOCK=/tmp/luci-app-daede.idx.lock + +if [ -f "$LOCK" ]; then + mtime=$(date -r "$LOCK" +%s 2>/dev/null || echo 0) + [ "$(( $(date +%s) - mtime ))" -lt 90 ] && exit 0 +fi +: > "$LOCK" + +( + if command -v apk >/dev/null 2>&1; then + apk update + elif command -v opkg >/dev/null 2>&1; then + opkg update + fi +) >/dev/null 2>&1 "$LOG" 2>&1 trap 'rm -f "$LOCK"' EXIT INT TERM + rc=0 TMP="${DEST}.new" mkdir -p "$(dirname "$DEST")" echo "$(date '+%F %T') begin: $URL" @@ -51,18 +52,19 @@ fi if ! curl -fsSL --connect-timeout 15 --max-time 240 -o "$TMP" "$URL"; then echo "$(date '+%F %T') download failed" rm -f "$TMP" - exit 1 + rc=1 + else + size=$(wc -c < "$TMP" 2>/dev/null || echo 0) + if [ "$size" -lt 102400 ]; then + echo "$(date '+%F %T') file too small ($size bytes)" + rm -f "$TMP" + rc=2 + else + mv "$TMP" "$DEST" + echo "$(date '+%F %T') updated $DEST ($size bytes)" + fi fi - - size=$(wc -c < "$TMP" 2>/dev/null || echo 0) - if [ "$size" -lt 102400 ]; then - echo "$(date '+%F %T') file too small ($size bytes)" - rm -f "$TMP" - exit 2 - fi - - mv "$TMP" "$DEST" - echo "$(date '+%F %T') updated $DEST ($size bytes)" + echo "$(date '+%F %T') done (rc=$rc)" ) /dev/null 2>&1 & echo "started in background, see $LOG" diff --git a/luci-app-daede/root/usr/share/luci-app-daede/update-pkg.sh b/luci-app-daede/root/usr/share/luci-app-daede/update-pkg.sh index 920143ab..47638057 100755 --- a/luci-app-daede/root/usr/share/luci-app-daede/update-pkg.sh +++ b/luci-app-daede/root/usr/share/luci-app-daede/update-pkg.sh @@ -40,10 +40,23 @@ fi if command -v apk >/dev/null 2>&1; then echo "--- apk update ---" apk update 2>&1 - echo "--- apk upgrade $PKG ---" - # --no-self-upgrade so apk itself does not jump versions mid-op - apk upgrade --no-self-upgrade "$PKG" 2>&1 - rc=$? + echo "--- apk add $PKG ---" + # Target only $PKG (not `apk upgrade`, which re-solves the whole world). + apk add "$PKG" 2>&1 + # Don't trust apk's exit code: apk-tools 3 returns non-zero whenever ANY + # unrelated installed package has an unavailable .apk in the configured + # feeds, even when $PKG itself upgraded fine. Judge success by state — + # $PKG must be installed and have no pending upgrade left. + if ! apk list --installed 2>/dev/null | grep -q "^${PKG}-"; then + echo "result: $PKG is not installed" + rc=1 + elif apk list -u 2>/dev/null | grep -q "^${PKG}-"; then + echo "result: $PKG still has a pending upgrade" + rc=1 + else + echo "result: $PKG is at the latest available version" + rc=0 + fi elif command -v opkg >/dev/null 2>&1; then echo "--- opkg update ---" opkg update 2>&1 diff --git a/luci-app-daede/root/usr/share/rpcd/acl.d/luci-app-daede.json b/luci-app-daede/root/usr/share/rpcd/acl.d/luci-app-daede.json index 2d849590..ae4d9df0 100644 --- a/luci-app-daede/root/usr/share/rpcd/acl.d/luci-app-daede.json +++ b/luci-app-daede/root/usr/share/rpcd/acl.d/luci-app-daede.json @@ -27,6 +27,7 @@ "/usr/share/luci-app-daede/pkg-info.sh dae": [ "exec" ], "/usr/share/luci-app-daede/pkg-info.sh daed": [ "exec" ], "/usr/share/luci-app-daede/pkg-info.sh luci-app-daede": [ "exec" ], + "/usr/share/luci-app-daede/refresh-index.sh": [ "exec" ], "/usr/share/luci-app-daede/proxy-check.sh": [ "exec" ] }, "ubus": { diff --git a/luci-app-fchomo/root/usr/share/rpcd/ucode/luci.fchomo b/luci-app-fchomo/root/usr/share/rpcd/ucode/luci.fchomo index 973b0b55..b0564e13 100644 --- a/luci-app-fchomo/root/usr/share/rpcd/ucode/luci.fchomo +++ b/luci-app-fchomo/root/usr/share/rpcd/ucode/luci.fchomo @@ -53,9 +53,9 @@ const methods = { } const type = req.args?.type; - let cmd = `generate ${type}`; let result = {}; + let cmd = `generate ${type}`; if (type === 'age-x25519') { cmd = 'age keygen'; } else if (type === 'age-mlkem768-x25519') { @@ -63,7 +63,8 @@ const methods = { } else if (type === 'age-convert') { cmd = 'age convert'; } - const fd = popen(`/usr/bin/mihomo ${cmd}` + (req.args?.params ? ' ' + shellQuote(req.args.params) : '')); + + const fd = popen(`/usr/bin/mihomo ${cmd} ${shellQuote(req.args.params ?? '')}`); if (fd) { for (let line = fd.read('line'); length(line); line = fd.read('line')) { if (type === 'uuid') @@ -140,7 +141,7 @@ const methods = { infd.write(content); infd.seek(); - const out = executeCommand(infd, '/usr/bin/mihomo age', req.args?.action, req.args?.key, '-', '-'); + const out = executeCommand(infd, '/usr/bin/mihomo age', req.args?.action, shellQuote(req.args?.key), '-', '-'); infd.close(); return out.exitcode === 0 ? { result: out.stdout } : { result: false, error: out.stderr }; @@ -162,7 +163,7 @@ const methods = { if ((!req.args?.output) || match(req.args?.output, /\.\.\//)) return { result: false, error: 'illegal output' }; - const out = executeCommand(null, '/usr/bin/mihomo age', req.args?.action, req.args?.key, req.args?.input, req.args?.output); + const out = executeCommand(null, '/usr/bin/mihomo age', req.args?.action, shellQuote(req.args?.key), shellQuote(req.args?.input), shellQuote(req.args?.output)); return out.exitcode === 0 ? { result: true } : { result: false, error: out.stderr }; } @@ -228,7 +229,7 @@ const methods = { if (!req.args?.url) return { httpcode: null, error: 'illegal url' }; - const httpcode = trim(popen(`wget --spider -t1 -ST3 '${req.args?.url}' 2>&1 | awk '/^\\s*HTTP\\//{print $2}'`).read('all')) || '-1'; + const httpcode = trim(popen(`wget --spider -t1 -ST3 ${shellQuote(req.args?.url)} 2>&1 | awk '/^\\s*HTTP\\//{print $2}'`).read('all')) || '-1'; return { httpcode: httpcode }; } @@ -239,8 +240,10 @@ const methods = { call: function(req) { if (req.args?.type == 'resources') { system(`sed -i "/${replace(EXE_DIR, "/", "\\/")}\\/update_resources.sh/d" /etc/crontabs/root`); - if (req.args?.expr) + if ((req.args?.expr && match(req.args?.expr, /^[0-9 ,\*\/\?-]+$/))) system(`echo -e "` + req.args?.expr + ` ${EXE_DIR}/update_resources.sh ALL" >> /etc/crontabs/root`); + else + return { result: false, error: 'illegal expr' }; } else return { result: false, error: 'illegal type' }; @@ -396,7 +399,7 @@ const methods = { if ((!req.args?.filename) || match(req.args?.filename, /\.\.\//)) return { result: false, error: 'illegal filename' }; - system(`rm -f ${HM_DIR}/${req.args?.type}/${req.args?.filename}`); + system(`rm -f ${HM_DIR}/${req.args?.type}/${shellQuote(req.args?.filename)}`); return { result: true }; } diff --git a/luci-app-fchomo/root/usr/share/ucode/fchomo.uc b/luci-app-fchomo/root/usr/share/ucode/fchomo.uc index d9c6ed60..b39680a7 100644 --- a/luci-app-fchomo/root/usr/share/ucode/fchomo.uc +++ b/luci-app-fchomo/root/usr/share/ucode/fchomo.uc @@ -85,7 +85,7 @@ export function yqRead(flags, command, content) { }; export function yqReadFile(flags, command, filepath) { - const out = executeCommand(null, 'yq', flags, shellQuote(command), filepath); + const out = executeCommand(null, 'yq', flags, shellQuote(command), shellQuote(filepath)); return out.stdout; }; diff --git a/luci-app-passwall2/Makefile b/luci-app-passwall2/Makefile index 043c5d3b..f16aa44a 100644 --- a/luci-app-passwall2/Makefile +++ b/luci-app-passwall2/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall2 PKG_VERSION:=26.6.3 -PKG_RELEASE:=53 +PKG_RELEASE:=54 PKG_PO_VERSION:=$(PKG_VERSION) PKG_CONFIG_DEPENDS:= \ diff --git a/luci-app-passwall2/luasrc/passwall2/util_xray.lua b/luci-app-passwall2/luasrc/passwall2/util_xray.lua index 50638170..00e9aa4f 100644 --- a/luci-app-passwall2/luasrc/passwall2/util_xray.lua +++ b/luci-app-passwall2/luasrc/passwall2/util_xray.lua @@ -1518,11 +1518,6 @@ function gen_config(var) end end) - table.insert(rules, { - outboundTag = "direct", - ip = { "geoip:private" } - }) - if default_outboundTag then local rule = { ruleTag = "default", diff --git a/luci-app-wechatpush/Makefile b/luci-app-wechatpush/Makefile index b0550f9b..e428574f 100755 --- a/luci-app-wechatpush/Makefile +++ b/luci-app-wechatpush/Makefile @@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-wechatpush PKG_VERSION:=3.6.12 -PKG_RELEASE:=4 +PKG_RELEASE:=5 PKG_MAINTAINER:=tty228 PKG_CONFIG_DEPENDS:= \ diff --git a/luci-app-wechatpush/root/usr/share/wechatpush/wechatpush b/luci-app-wechatpush/root/usr/share/wechatpush/wechatpush index 4145b540..1791f944 100755 --- a/luci-app-wechatpush/root/usr/share/wechatpush/wechatpush +++ b/luci-app-wechatpush/root/usr/share/wechatpush/wechatpush @@ -2293,8 +2293,8 @@ monitor_logins() { trap cleanup_child SIGINT SIGTERM ( - # 监听系统日志,-f 表示跟随实时日志,-p 表示日志级别为 notice - run_with_tag logread -f -p notice | while IFS= read -r line; do + # 监听系统日志,-f 表示跟随实时日志 + run_with_tag logread -f | while IFS= read -r line; do [ -n "$web_logged" ] && { web_login_ip=$(echo "$line" | grep -i "accepted login" | awk '{print $NF}') [ -n "$web_login_ip" ] && process_login "$web_login_ip" $(echo "$line" | awk '{print $4}') web_login_counts @@ -2317,7 +2317,7 @@ monitor_logins() { # 如果未能提取到 IP,从日志标识符提取失败用户的 ID,并再次提取 IP if [ -z "$ssh_failed_ip" ]; then ssh_failed_num=$(echo "$line" | sed -n 's/.*authpriv\.warn dropbear\[\([0-9]\+\)\]: Login attempt for nonexistent user/\1/p') - [ -n "$ssh_failed_num" ] && ssh_failed_ip=$(logread notice | grep "authpriv\.info dropbear\[${ssh_failed_num}\].*Child connection from" | awk '{print $NF}' | sed -nr 's#^(.*):[0-9]{1,5}#\1#gp' | sed -e 's/%.*//' | tail -n 1) + [ -n "$ssh_failed_num" ] && ssh_failed_ip=$(logread | grep "authpriv\.info dropbear\[${ssh_failed_num}\].*Child connection from" | awk '{print $NF}' | sed -nr 's#^(.*):[0-9]{1,5}#\1#gp' | sed -e 's/%.*//' | tail -n 1) fi # 如果成功提取到 IP 地址,调用 process_login 处理 @@ -2578,13 +2578,13 @@ login_send() { # 登录方式 if [[ "$log_type" == "web"* ]]; then # Web 登录、非法登录 - local login_mode=$(logread notice | grep -E ".* $login_time.*$login_ip.*" | awk '{print $13}' | tail -n 1) + local login_mode=$(logread | grep -E ".* $login_time.*$login_ip.*" | awk '{print $13}' | tail -n 1) [ "$login_mode" = "/" ] && login_mode="$(translate "/ (Homepage login)")" elif [[ "$log_type" == "ssh_login"* ]]; then # SSH 登录 - local login_mode=$(logread notice | grep -E ".* $login_time.*$login_ip.*" | awk '{print $8}' | tail -n 1) + local login_mode=$(logread | grep -E ".* $login_time.*$login_ip.*" | awk '{print $8}' | tail -n 1) else - local login_mode=$(logread notice | grep -E ".* $login_time.*$login_ip.*" | awk '{for(i=8;i src/media/_tokens.css) +│ │ ├── defaults.js # 10 editable input colors (light/dark) +│ │ ├── spec.js # Derivation rules (DERIVATIONS) + fixed literals +│ │ ├── engine.js # OKLCH/OKLAB color math (mix/shade/set/alpha) +│ │ └── resolve.js # Resolves spec into a flat token map +│ ├── tests/ # All test suites (pnpm test) +│ │ ├── engine.test.js # Color-math operators +│ │ ├── resolve.test.js # Resolved token invariants +│ │ ├── surfaces.test.js # Surface/hue layering invariants +│ │ ├── overlay.test.js # Overlay/layout CSS assertions +│ │ └── navigation-*.test.js # Navigation model/rendering/styles │ ├── .env.example # Environment variables template │ ├── .prettierrc # Prettier configuration │ ├── package.json # Node.js dependencies @@ -270,6 +299,7 @@ luci-theme-aurora/ - **[Vite](https://vitejs.dev/)** - Build tool and development server - **[pnpm](https://pnpm.io/)** - Fast, disk space efficient package manager - **[lightningcss](https://lightningcss.dev/)** - CSS minifier +- **[colorjs.io](https://colorjs.io/)** - OKLCH/OKLAB color math for design token generation (`.dev/tokens/`) - **[Terser](https://terser.org/)** - JavaScript minifier - **[Prettier](https://prettier.io/)** - Code formatter - **[prettier-plugin-tailwindcss](https://github.com/tailwindlabs/prettier-plugin-tailwindcss)** - Tailwind class sorting diff --git a/luci-theme-aurora/.dev/package.json b/luci-theme-aurora/.dev/package.json index 970b5bcd..25b37be8 100644 --- a/luci-theme-aurora/.dev/package.json +++ b/luci-theme-aurora/.dev/package.json @@ -4,12 +4,17 @@ "type": "module", "scripts": { "dev": "vite", - "build": "npm run clean && vite build", - "clean": "node scripts/clean.js" + "build": "npm run clean && npm run gen:tokens && vite build", + "clean": "node scripts/clean.js", + "gen:tokens": "node scripts/gen-tokens.js", + "test": "node --test tests/*.test.js" }, "devDependencies": { "@tailwindcss/vite": "^4.1.11", "@types/node": "^24.0.0", + "browserslist": "^4.28.2", + "colorjs.io": "^0.6.1", + "lightningcss": "^1.32.0", "prettier": "^3.6.2", "prettier-plugin-tailwindcss": "^0.7.0", "tailwind-scrollbar": "^4.0.2", diff --git a/luci-theme-aurora/.dev/pnpm-lock.yaml b/luci-theme-aurora/.dev/pnpm-lock.yaml index 36bcc5e8..69d5eecd 100644 --- a/luci-theme-aurora/.dev/pnpm-lock.yaml +++ b/luci-theme-aurora/.dev/pnpm-lock.yaml @@ -7,13 +7,23 @@ settings: importers: .: + dependencies: + colorjs.io: + specifier: ^0.6.1 + version: 0.6.1 devDependencies: '@tailwindcss/vite': specifier: ^4.1.11 - version: 4.1.18(vite@7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)) + version: 4.1.18(vite@7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.0)) '@types/node': specifier: ^24.0.0 version: 24.10.9 + browserslist: + specifier: ^4.28.2 + version: 4.28.2 + lightningcss: + specifier: ^1.32.0 + version: 1.32.0 prettier: specifier: ^3.6.2 version: 3.8.1 @@ -34,7 +44,7 @@ importers: version: 1.4.0 vite: specifier: ^7.1.1 - version: 7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0) + version: 7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.0) packages: @@ -459,13 +469,29 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + baseline-browser-mapping@2.10.37: + resolution: {integrity: sha512-girxaJ7WZssDOFhzCGZTDKoTa1gk6A1TbflaYTpykLJ4UU9Fz9kx1aREM8JCuoVHbL8X8T/mJg7w2oYSq72Oig==} + engines: {node: '>=6.0.0'} + hasBin: true + + browserslist@4.28.2: + resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + caniuse-lite@1.0.30001799: + resolution: {integrity: sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==} + clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} + colorjs.io@0.6.1: + resolution: {integrity: sha512-8lyR2wHzuIykCpqHKgluGsqQi5iDm3/a2IgP2GBZrasn2sBRkE4NOGsglZxWLs/jZQoNkmA/KM/8NV16rLUdBg==} + commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -473,6 +499,9 @@ packages: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} + electron-to-chromium@1.5.372: + resolution: {integrity: sha512-M3yhbAlilnwqC8D21t28UCDGHyitShTmmLRU/H+b74P6Ski16Nb9HONYEaVpMj/pwC7BEo5B95FpjODLCWbtfA==} + enhanced-resolve@5.18.4: resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==} engines: {node: '>=10.13.0'} @@ -482,6 +511,10 @@ packages: engines: {node: '>=18'} hasBin: true + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} @@ -509,30 +542,60 @@ packages: cpu: [arm64] os: [android] + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + lightningcss-darwin-arm64@1.30.2: resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + lightningcss-darwin-x64@1.30.2: resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + lightningcss-freebsd-x64@1.30.2: resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + lightningcss-linux-arm-gnueabihf@1.30.2: resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + lightningcss-linux-arm64-gnu@1.30.2: resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==} engines: {node: '>= 12.0.0'} @@ -540,6 +603,13 @@ packages: os: [linux] libc: [glibc] + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + lightningcss-linux-arm64-musl@1.30.2: resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} engines: {node: '>= 12.0.0'} @@ -547,6 +617,13 @@ packages: os: [linux] libc: [musl] + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + lightningcss-linux-x64-gnu@1.30.2: resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} engines: {node: '>= 12.0.0'} @@ -554,6 +631,13 @@ packages: os: [linux] libc: [glibc] + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + lightningcss-linux-x64-musl@1.30.2: resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} engines: {node: '>= 12.0.0'} @@ -561,22 +645,45 @@ packages: os: [linux] libc: [musl] + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + lightningcss-win32-arm64-msvc@1.30.2: resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + lightningcss-win32-x64-msvc@1.30.2: resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + lightningcss@1.30.2: resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} engines: {node: '>= 12.0.0'} + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} @@ -585,6 +692,10 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + node-releases@2.0.47: + resolution: {integrity: sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==} + engines: {node: '>=18'} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -709,6 +820,12 @@ packages: undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + vite@7.3.1: resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -989,12 +1106,12 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.18 '@tailwindcss/oxide-win32-x64-msvc': 4.1.18 - '@tailwindcss/vite@4.1.18(vite@7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0))': + '@tailwindcss/vite@4.1.18(vite@7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.0))': dependencies: '@tailwindcss/node': 4.1.18 '@tailwindcss/oxide': 4.1.18 tailwindcss: 4.1.18 - vite: 7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0) + vite: 7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.0) '@types/estree@1.0.8': {} @@ -1006,14 +1123,30 @@ snapshots: acorn@8.15.0: {} + baseline-browser-mapping@2.10.37: {} + + browserslist@4.28.2: + dependencies: + baseline-browser-mapping: 2.10.37 + caniuse-lite: 1.0.30001799 + electron-to-chromium: 1.5.372 + node-releases: 2.0.47 + update-browserslist-db: 1.2.3(browserslist@4.28.2) + buffer-from@1.1.2: {} + caniuse-lite@1.0.30001799: {} + clsx@2.1.1: {} + colorjs.io@0.6.1: {} + commander@2.20.3: {} detect-libc@2.1.2: {} + electron-to-chromium@1.5.372: {} + enhanced-resolve@5.18.4: dependencies: graceful-fs: 4.2.11 @@ -1048,6 +1181,8 @@ snapshots: '@esbuild/win32-ia32': 0.27.2 '@esbuild/win32-x64': 0.27.2 + escalade@3.2.0: {} + fdir@6.5.0(picomatch@4.0.3): optionalDependencies: picomatch: 4.0.3 @@ -1062,36 +1197,69 @@ snapshots: lightningcss-android-arm64@1.30.2: optional: true + lightningcss-android-arm64@1.32.0: + optional: true + lightningcss-darwin-arm64@1.30.2: optional: true + lightningcss-darwin-arm64@1.32.0: + optional: true + lightningcss-darwin-x64@1.30.2: optional: true + lightningcss-darwin-x64@1.32.0: + optional: true + lightningcss-freebsd-x64@1.30.2: optional: true + lightningcss-freebsd-x64@1.32.0: + optional: true + lightningcss-linux-arm-gnueabihf@1.30.2: optional: true + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + lightningcss-linux-arm64-gnu@1.30.2: optional: true + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + lightningcss-linux-arm64-musl@1.30.2: optional: true + lightningcss-linux-arm64-musl@1.32.0: + optional: true + lightningcss-linux-x64-gnu@1.30.2: optional: true + lightningcss-linux-x64-gnu@1.32.0: + optional: true + lightningcss-linux-x64-musl@1.30.2: optional: true + lightningcss-linux-x64-musl@1.32.0: + optional: true + lightningcss-win32-arm64-msvc@1.30.2: optional: true + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + lightningcss-win32-x64-msvc@1.30.2: optional: true + lightningcss-win32-x64-msvc@1.32.0: + optional: true + lightningcss@1.30.2: dependencies: detect-libc: 2.1.2 @@ -1108,12 +1276,30 @@ snapshots: lightningcss-win32-arm64-msvc: 1.30.2 lightningcss-win32-x64-msvc: 1.30.2 + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 nanoid@3.3.11: {} + node-releases@2.0.47: {} + picocolors@1.1.1: {} picomatch@4.0.3: {} @@ -1205,7 +1391,13 @@ snapshots: undici-types@7.16.0: {} - vite@7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0): + update-browserslist-db@1.2.3(browserslist@4.28.2): + dependencies: + browserslist: 4.28.2 + escalade: 3.2.0 + picocolors: 1.1.1 + + vite@7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.0): dependencies: esbuild: 0.27.2 fdir: 6.5.0(picomatch@4.0.3) @@ -1217,5 +1409,5 @@ snapshots: '@types/node': 24.10.9 fsevents: 2.3.3 jiti: 2.6.1 - lightningcss: 1.30.2 + lightningcss: 1.32.0 terser: 5.46.0 diff --git a/luci-theme-aurora/.dev/scripts/gen-tokens.js b/luci-theme-aurora/.dev/scripts/gen-tokens.js new file mode 100644 index 00000000..7d3ad5cb --- /dev/null +++ b/luci-theme-aurora/.dev/scripts/gen-tokens.js @@ -0,0 +1,80 @@ +import { writeFile } from "node:fs/promises"; +import { resolve } from "node:path"; +import { resolveMode } from "../tokens/resolve.js"; +import { FIXED } from "../tokens/spec.js"; + +const kebab = (s) => s.replace(/_/g, "-"); + +function block(selector, colors, fixed) { + const lines = []; + for (const [k, v] of Object.entries(colors)) { + lines.push(` --${kebab(k)}: ${v};`); + } + for (const [k, v] of Object.entries(fixed)) { + lines.push(` --${kebab(k)}: ${v};`); + } + return `${selector} {\n${lines.join("\n")}\n`; +} + +const light = resolveMode("light"); +const dark = resolveMode("dark"); + +const STRUCTURE = ` + --font-sans: "Lato", ui-sans-serif, system-ui, sans-serif; + --font-mono: ui-monospace, "SF Mono", Menlo, Monaco, Consolas, monospace; + --spacing: 0.25rem; + --container-max-width: 80rem; + --radius-base: 0.5rem; +`; + +const THEME = `@theme inline { +${Object.keys(light) + .map((k) => ` --color-${kebab(k)}: var(--${kebab(k)});`) + .join("\n")} + + --shadow-sm: var(--app-shadow-sm); + --shadow-md: var(--app-shadow-md); + --shadow-lg: var(--app-shadow-md); + --shadow-xl: var(--app-shadow-lg); + --shadow-2xl: var(--app-shadow-lg); + + --font-sans: var(--font-sans); + --font-mono: var(--font-mono); + --spacing: var(--spacing); + --container-max-width: var(--container-max-width); + + --radius-sm: calc(var(--radius-base) * 0.25); + --radius: calc(var(--radius-base) * 0.5); + --radius-md: calc(var(--radius-base) * 0.75); + --radius-lg: var(--radius-base); + --radius-xl: calc(var(--radius-base) * 1.5); + --radius-2xl: calc(var(--radius-base) * 2); + --radius-3xl: calc(var(--radius-base) * 3); + --radius-4xl: calc(var(--radius-base) * 4); +} +`; + +const HEADER = `/** + * luci-theme-aurora: design tokens -- GENERATED, DO NOT EDIT. + * Run \`pnpm gen:tokens\`. Source: tokens/spec.js + tokens/defaults.js + * All color values are flat; lightningcss adds legacy fallbacks. + * ORDER MATTERS: [data-darkmode="true"] must stay after :root. + */ +`; + +const css = + HEADER + + "\n" + + block(":root", light, FIXED.light) + + STRUCTURE + + "}\n\n" + + block('[data-darkmode="true"]', dark, FIXED.dark) + + "}\n\n" + + THEME; + +await writeFile( + resolve(import.meta.dirname, "../src/media/_tokens.css"), + css, + "utf-8", +); +console.log("gen-tokens: wrote src/media/_tokens.css"); diff --git a/luci-theme-aurora/.dev/src/media/_base.css b/luci-theme-aurora/.dev/src/media/_base.css index 162dbfa6..285a8153 100644 --- a/luci-theme-aurora/.dev/src/media/_base.css +++ b/luci-theme-aurora/.dev/src/media/_base.css @@ -1,88 +1,12 @@ -*:not(html) { - @apply scrollbar-thumb-rounded-full scrollbar-thin scrollbar-track-transparent scrollbar-thumb-content-muted; -} - +/** + * Document foundation — shared by main.css and login.css. + * Solid bg on html/body — one paint path with header (no body::before; + * fixed pseudo made the same var(--bg) look mismatched). + */ html { - @apply scrollbar-thumb-rounded-full scrollbar-thin scrollbar-track-surface scrollbar-thumb-content-muted; - @apply bg-canvas relative h-full font-sans; + @apply bg-bg min-h-dvh font-sans; body { - @apply text-content relative flex flex-col bg-transparent text-sm leading-relaxed font-normal; - &.modal-overlay-active { - @apply h-screen overflow-hidden; - } + @apply bg-bg min-h-dvh; } } - -h1, -h2, -h3, -h4, -h5, -h6 { - @apply text-content font-sans leading-tight font-semibold tracking-tight; -} - -h1 { - @apply mb-4 pl-6 text-3xl max-md:pl-4 max-md:text-2xl; -} - -h2 { - @apply mb-4 pl-5 text-2xl max-md:mb-2 max-md:pl-4 max-md:text-xl; -} - -h3 { - @apply mb-4 text-xl font-semibold tracking-tight max-md:mb-2 max-md:text-lg; -} - -h4 { - @apply mb-2 text-lg max-md:text-base; -} - -h5 { - @apply mb-2 text-base max-md:text-sm; -} - -h6 { - @apply mb-2 text-sm max-md:text-xs; -} - -hr { - @apply border-0; -} - -strong { - @apply font-semibold tracking-tight; -} - -abbr { - @apply cursor-help; -} - -p { - @apply text-content text-sm leading-relaxed; -} - -pre { - @apply text-content-muted border-border-subtle bg-surface-muted block rounded-xl border px-3 py-2 font-mono text-sm leading-relaxed wrap-break-word whitespace-pre-wrap; -} - -code { - @apply text-content-muted bg-surface-muted rounded px-2 py-1 font-mono text-sm; -} - -a { - @apply text-link no-underline hover:underline; -} - -var { - @apply text-link font-mono; -} - -small { - @apply text-content text-xs font-normal; -} - -em { - @apply text-content-muted font-medium italic; -} diff --git a/luci-theme-aurora/.dev/src/media/_elements.css b/luci-theme-aurora/.dev/src/media/_elements.css new file mode 100644 index 00000000..d6b51b38 --- /dev/null +++ b/luci-theme-aurora/.dev/src/media/_elements.css @@ -0,0 +1,88 @@ +*:not(html) { + @apply scrollbar-thumb-rounded-full scrollbar-thin scrollbar-track-transparent scrollbar-thumb-text-muted; +} + +html { + @apply scrollbar-thumb-rounded-full scrollbar-thin scrollbar-track-surface scrollbar-thumb-text-muted; + + body { + @apply text-text relative flex min-h-dvh flex-col text-sm leading-relaxed font-normal; + + &.modal-overlay-active { + @apply h-screen overflow-hidden; + } + } +} + +h1, +h2, +h3, +h4, +h5, +h6 { + @apply text-text font-sans leading-tight font-semibold tracking-tight; +} + +h1 { + @apply mb-4 pl-6 text-3xl max-md:pl-4 max-md:text-2xl; +} + +h2 { + @apply mb-4 pl-5 text-2xl max-md:mb-2 max-md:pl-4 max-md:text-xl; +} + +h3 { + @apply mb-4 text-xl font-semibold tracking-tight max-md:mb-2 max-md:text-lg; +} + +h4 { + @apply mb-2 text-lg max-md:text-base; +} + +h5 { + @apply mb-2 text-base max-md:text-sm; +} + +h6 { + @apply mb-2 text-sm max-md:text-xs; +} + +hr { + @apply border-0; +} + +strong { + @apply font-semibold tracking-tight; +} + +abbr { + @apply cursor-help; +} + +p { + @apply text-text text-sm leading-relaxed; +} + +pre { + @apply text-text-muted border-hairline bg-surface-sunken block rounded-xl border px-3 py-2 font-mono text-sm leading-relaxed wrap-break-word whitespace-pre-wrap; +} + +code { + @apply text-text-muted bg-surface-sunken rounded px-2 py-1 font-mono text-sm; +} + +a { + @apply text-link no-underline hover:underline; +} + +var { + @apply text-link font-mono; +} + +small { + @apply text-text text-xs font-normal; +} + +em { + @apply text-text-muted font-medium italic; +} diff --git a/luci-theme-aurora/.dev/src/media/_layout.css b/luci-theme-aurora/.dev/src/media/_layout.css index 7ca65820..d6f2a5e0 100644 --- a/luci-theme-aurora/.dev/src/media/_layout.css +++ b/luci-theme-aurora/.dev/src/media/_layout.css @@ -1,5 +1,5 @@ header { - @apply bg-header-bg sticky top-0 z-60 mb-2; + @apply bg-bg sticky top-0 z-60 mb-2; & .header-content { @apply relative flex h-14 items-center justify-between px-6 py-3 max-md:px-4 max-md:py-2; @@ -7,7 +7,7 @@ header { [data-nav-type="mega-menu"] & { & .desktop-menu-container { - @apply bg-header-glass-bg pointer-events-none absolute inset-x-0 top-0 z-30 h-(--mega-menu-height,0) w-full overflow-hidden opacity-0 backdrop-blur-xl transition-[clip-path,opacity] duration-200 ease-out [will-change:clip-path,opacity] [clip-path:inset(0_0_100%_0)] max-md:hidden; + @apply border-hairline bg-mega-menu-bg pointer-events-none absolute inset-x-0 top-0 z-30 h-(--mega-menu-height,0) w-full overflow-hidden border-b opacity-0 shadow-xl backdrop-blur-lg backdrop-saturate-150 transition-[clip-path,opacity] duration-[250ms] ease-out [will-change:clip-path,opacity] [clip-path:inset(0_0_100%_0)] max-md:hidden; &.active { @apply pointer-events-auto opacity-100 [clip-path:inset(0)]; @@ -22,7 +22,7 @@ header { fixed slot left of them. The entering panel floats up 6px — transform + opacity only. */ & .desktop-nav { - @apply pointer-events-none absolute inset-x-0 top-14 min-h-60 translate-y-1.5 pt-7 pb-8 pl-[calc(50%-13rem)] opacity-0 transition-[opacity,transform] duration-200 ease-out; + @apply pointer-events-none absolute inset-x-0 top-14 min-h-60 translate-y-1.5 pt-7 pb-8 pl-[calc(50%-13rem)] opacity-0 transition-[opacity,transform] duration-[250ms] ease-out; &.active { @apply pointer-events-auto translate-y-0 opacity-100; @@ -32,7 +32,7 @@ header { @apply absolute top-7 left-[calc(50%-30rem)] w-56 max-lg:hidden; & .desktop-nav-title { - @apply text-content text-2xl font-semibold tracking-tight; + @apply text-text text-2xl font-semibold tracking-tight; } } @@ -48,7 +48,7 @@ header { @apply m-0 list-none; & > a { - @apply text-content block w-fit py-2.5 text-sm whitespace-nowrap no-underline hover:underline hover:decoration-2 hover:underline-offset-4; + @apply text-text block w-fit py-2.5 text-sm whitespace-nowrap no-underline hover:underline hover:decoration-2 hover:underline-offset-4; } } } @@ -64,7 +64,7 @@ header { @apply absolute top-34 left-[calc(50%-30rem)] flex w-56 flex-col gap-2 max-lg:hidden; & .board-line { - @apply text-content-muted flex max-w-full items-center gap-2.5 text-xs; + @apply text-text-muted flex max-w-full items-center gap-2.5 text-xs; &::before { @apply size-4 shrink-0 bg-current content-['']; @@ -95,7 +95,7 @@ header { } .brand { - @apply hover:text-brand text-content inline-block shrink-0 text-xl font-semibold tracking-tight no-underline transition-[color,transform] duration-200 hover:-translate-y-0.5 max-md:flex-1 max-md:text-lg; + @apply hover:text-brand text-text inline-block shrink-0 text-xl font-semibold tracking-tight no-underline transition-[color,transform] duration-150 hover:-translate-y-0.5 max-md:flex-1 max-md:text-lg; } .nav { @@ -105,15 +105,15 @@ header { @apply relative; .menu { - @apply text-content block rounded-xl px-3.5 py-1.5 font-medium no-underline transition-colors duration-150; + @apply text-text block rounded-xl px-3.5 py-1.5 font-medium no-underline transition-colors duration-150; &.menu-active { - @apply text-content; + @apply text-text; [data-nav-type="mega-menu"] & { @apply underline decoration-2 underline-offset-4; } [data-nav-type="boxed-dropdown"] & { - @apply bg-header-interactive-bg; + @apply bg-brand-subtle text-brand; } } } @@ -131,16 +131,16 @@ header { & .desktop-nav-list { [data-nav-type="boxed-dropdown"] & { - @apply border-border-subtle bg-header-glass-bg flex flex-col gap-y-1 rounded-3xl border py-2 shadow-lg backdrop-blur-md backdrop-saturate-150; + @apply border-hairline bg-surface-overlay flex flex-col gap-y-1 rounded-3xl border py-2 shadow-lg backdrop-blur-md backdrop-saturate-150; } & > li { @apply m-0 list-none; & > a { - @apply text-content block whitespace-nowrap no-underline; + @apply text-text block whitespace-nowrap no-underline; [data-nav-type="boxed-dropdown"] & { - @apply hover:bg-header-interactive-bg mx-2 rounded-xl px-4 py-2; + @apply hover:bg-hover-faint mx-2 rounded-xl px-4 py-2; } } } @@ -157,15 +157,15 @@ header { } & .navigation-toggle { - @apply cursor-pointer rounded-none border-0 bg-transparent p-0 shadow-none transition-transform duration-200 hover:scale-105 active:scale-95; + @apply cursor-pointer rounded-none border-0 bg-transparent p-0 shadow-none transition-transform duration-150 hover:scale-105 active:scale-95; & svg { - @apply text-content size-5; + @apply text-text size-5; } & .navigation-toggle-line { transform-box: fill-box; - @apply origin-center transition-[transform,opacity] duration-300 ease-in-out; + @apply origin-center transition-[transform,opacity] duration-150 ease-in-out; } &.is-expanded { @@ -189,7 +189,7 @@ header { @apply flex shrink-0 flex-row-reverse gap-5 md:gap-8; & span[data-indicator] { - @apply before:text-content size-5 cursor-pointer text-[0px] before:absolute before:size-5 before:bg-current; + @apply before:text-text size-5 cursor-pointer text-[0px] before:absolute before:size-5 before:bg-current; &[data-indicator="media_error"] { @apply before:[mask:url('@assets/icons/error.svg')_center/cover_no-repeat]; @@ -223,14 +223,14 @@ body[data-nav-type="sidebar"] { so collapsing the sidebar never stretches it — lets the sidebar column animate to zero, and lets #maincontent fluidly reclaim the freed space. overflow-x-clip keeps the sliding sidebar out of horizontal overflow. */ - @apply md:grid md:grid-cols-[17rem_minmax(0,1fr)] md:grid-rows-[auto_minmax(0,1fr)] md:overflow-x-clip md:transition-[grid-template-columns] md:duration-300 md:ease-out; + @apply md:grid md:grid-cols-[17rem_minmax(0,1fr)] md:grid-rows-[auto_minmax(0,1fr)] md:overflow-x-clip md:transition-[grid-template-columns] md:duration-[250ms] md:ease-out; &.sidebar-collapsed { @apply md:grid-cols-[0_minmax(0,1fr)]; } & > header { - @apply md:border-border-subtle md:col-span-full md:row-start-1 md:mb-0 md:border-b; + @apply md:border-hairline md:col-span-full md:row-start-1 md:mb-0 md:border-b; } & > .sidebar-panel { @@ -242,7 +242,7 @@ body[data-nav-type="sidebar"] { } & .header-crumb { - @apply text-content-muted my-0 mr-auto ml-6 hidden min-w-0 list-none items-center gap-2 overflow-hidden p-0 text-sm md:flex; + @apply text-text-muted my-0 mr-auto ml-6 hidden min-w-0 list-none items-center gap-2 overflow-hidden p-0 text-sm md:flex; & li { @apply m-0 list-none whitespace-nowrap; @@ -253,12 +253,12 @@ body[data-nav-type="sidebar"] { } & .current { - @apply text-content min-w-0 truncate font-medium; + @apply text-text min-w-0 truncate font-medium; } } & .sidebar-panel { - @apply border-border-subtle sticky top-14 hidden h-[calc(100vh-3.5rem)] w-full overflow-hidden rounded-none border-r transition-[visibility] duration-300 md:block; + @apply border-hairline sticky top-14 hidden h-[calc(100vh-3.5rem)] w-full overflow-hidden rounded-none border-r transition-[visibility] duration-[250ms] md:block; } /* Visibility flips at the end of the slide so collapsed controls leave the @@ -268,7 +268,7 @@ body[data-nav-type="sidebar"] { } & .sidebar-panel-inner { - @apply bg-header-bg flex h-full w-68 flex-col overflow-hidden transition-[translate,opacity] duration-300; + @apply bg-bg flex h-full w-68 flex-col overflow-hidden transition-[translate,opacity] duration-[250ms]; } &.sidebar-collapsed .sidebar-panel-inner { @@ -283,46 +283,25 @@ body[data-nav-type="sidebar"] { } } - & .sidebar-list .nav-link { + & .sidebar-list .navigation-direct { @apply truncate text-lg; } - /* Selected-pill background for top-level leaf links. The shared - .nav-link-active carries only brand text, so the sidebar owns its pill - here (submenu links get theirs below). */ - & .sidebar-list > li > .nav-link-active { - @apply bg-brand-faint hover:bg-brand-faint; - } - - & .sidebar-section { - @apply grid grid-rows-[0fr] opacity-0 transition-[grid-template-rows,opacity] duration-200 ease-out; - } - - & .sidebar-group-open > .sidebar-section { - @apply grid-rows-[1fr] opacity-100; - } - - /* Child links sit indented under their category — hierarchy comes from - spacing alone, no guide line, for a calmer look. */ & .sidebar-submenu { - @apply m-0 min-h-0 list-none space-y-0.5 overflow-hidden p-0 pl-3; + @apply m-0 min-h-0 list-none space-y-0.5 overflow-hidden p-0 pl-4; } - & .sidebar-submenu .nav-link { - @apply text-content-muted hover:text-content rounded-lg px-3 py-1.5 text-sm; - } - - & .sidebar-submenu .nav-link-active { - @apply bg-brand-faint text-brand hover:text-brand; + & .sidebar-submenu .navigation-sublink { + @apply px-3 py-1.5 text-sm; } & .sidebar-footer { - @apply border-border-subtle shrink-0 border-t p-3; + @apply border-hairline shrink-0 border-t p-3; /* Logout: muted at rest; on hover the base .nav-link pill background plus error-colored text is the intended compound state (matches v1). */ & .nav-link { - @apply text-content-muted hover:text-danger-content; + @apply text-text-muted hover:text-danger; } } } @@ -331,7 +310,7 @@ body[data-nav-type="sidebar"] { @apply max-w-max-width mx-auto min-h-[calc(100vh-4rem)] w-23/24 px-4 max-md:w-full max-md:px-3; #view { - @apply animate-in fade-in-0 slide-in-from-top-2 fill-mode-both md:border-border-faint md:bg-surface mx-0 w-full p-0 shadow-none empty:hidden md:rounded-4xl md:border md:p-6 md:shadow-xl; + @apply animate-in fade-in-0 slide-in-from-top-2 fill-mode-both mx-0 w-full bg-transparent p-0 shadow-none empty:hidden md:p-0; .cbi-title-section { @apply mb-6 leading-relaxed max-md:mx-2 max-md:mb-3; @@ -365,7 +344,7 @@ body[data-nav-type="sidebar"] { @apply dark:!bg-surface; & line[style] { - @apply dark:!stroke-content; + @apply dark:!stroke-text; } } } @@ -373,18 +352,18 @@ body[data-nav-type="sidebar"] { .cbi-map-descr, .cbi-section-descr { - @apply text-content-muted mb-6 text-sm leading-relaxed max-md:mx-2 max-md:mb-3 max-md:text-sm; + @apply text-text-muted mb-6 text-sm leading-relaxed max-md:mx-2 max-md:mb-3 max-md:text-sm; } .cbi-page-actions { - @apply border-border-subtle mt-6 flex flex-wrap items-center justify-end gap-3 border-t pt-4 max-md:mx-2 max-md:mt-4 max-md:gap-2 max-md:pt-3; + @apply border-hairline mt-6 flex flex-wrap items-center justify-end gap-3 border-t pt-4 max-md:mx-2 max-md:mt-4 max-md:gap-2 max-md:pt-3; } .zone-forwards { @apply flex items-start gap-3 leading-relaxed; & > span { - @apply text-content-muted mt-1.5; + @apply text-text-muted mt-1.5; } .zone-dest { @@ -398,12 +377,12 @@ body[data-nav-type="sidebar"] { } #syslog { - @apply bg-terminal-bg text-terminal-content rounded-3xl border p-6 shadow-lg max-md:p-3; + @apply bg-surface-sunken text-text rounded-3xl border p-6 shadow-lg max-md:p-3; } } footer { - @apply text-content-muted mt-2 flex min-h-16 flex-wrap items-center justify-between text-xs; + @apply text-text-muted mt-2 flex min-h-16 flex-wrap items-center justify-between text-xs; & a { @apply text-brand; @@ -414,13 +393,13 @@ footer { } & .breadcrumb { - @apply bg-glass-surface hover:bg-surface flex items-center gap-1 rounded-full px-3 py-1.5 text-xs shadow-sm backdrop-blur-sm transition-colors duration-200; + @apply bg-surface-overlay hover:bg-surface flex items-center gap-1 rounded-full px-3 py-1.5 text-xs shadow-sm backdrop-blur-md backdrop-saturate-150 transition-colors duration-150; & li { @apply list-none; &.active a { - @apply text-content; + @apply text-text; } } } diff --git a/luci-theme-aurora/.dev/src/media/_patches.css b/luci-theme-aurora/.dev/src/media/_patches.css index 3380d4e0..5b2e2647 100644 --- a/luci-theme-aurora/.dev/src/media/_patches.css +++ b/luci-theme-aurora/.dev/src/media/_patches.css @@ -52,17 +52,17 @@ &.tr { @apply rounded-none; } - @apply bg-glass-raised not-[.tr]:border-border-faint not-[.tr]:hover:border-border-subtle max-md:bg-glass-raised not-[.tr]:max-md:border-border-faint not-[.tr]:border not-[.tr]:shadow-lg not-[.tr]:hover:shadow-xl not-[.tr]:max-md:border; + @apply bg-surface-overlay not-[.tr]:border-hairline not-[.tr]:hover:border-hairline max-md:bg-surface-overlay not-[.tr]:max-md:border-hairline not-[.tr]:border not-[.tr]:shadow-lg not-[.tr]:hover:shadow-xl not-[.tr]:max-md:border; /* Dark mode: override custom.css hardcoded light-mode colors on all text nodes */ & span { - @apply dark:text-content!; + @apply dark:text-text!; } & td { - @apply dark:text-content!; + @apply dark:text-text!; } & th { - @apply dark:text-content!; + @apply dark:text-text!; } img[src*=".svg"] { @@ -94,7 +94,7 @@ .title { h3 { - @apply text-content border-0 pb-4 max-md:mx-0 max-md:pb-2; + @apply text-text border-0 pb-4 max-md:mx-0 max-md:pb-2; } } diff --git a/luci-theme-aurora/.dev/src/media/_tokens.css b/luci-theme-aurora/.dev/src/media/_tokens.css index 51d553e2..f4a107b1 100644 --- a/luci-theme-aurora/.dev/src/media/_tokens.css +++ b/luci-theme-aurora/.dev/src/media/_tokens.css @@ -1,122 +1,44 @@ /** - * luci-theme-aurora: design tokens - * Copyright 2025 eamonxg - * Licensed to the public under the Apache License 2.0. - * - * Shared between main.css and login.css. - * - * Layer 1 contains broad theme inputs. Layer 2 names semantic and component - * responsibilities. Components consume named roles and never apply numeric - * color opacity modifiers. - * - * ORDER MATTERS: [data-darkmode="true"] ties with :root on specificity, so - * the dark block must remain after :root. + * luci-theme-aurora: design tokens -- GENERATED, DO NOT EDIT. + * Run `pnpm gen:tokens`. Source: tokens/spec.js + tokens/defaults.js + * All color values are flat; lightningcss adds legacy fallbacks. + * ORDER MATTERS: [data-darkmode="true"] must stay after :root. */ :root { - /* Layer 1: theme inputs */ - --canvas: oklch(0.968 0.007 247.896); + --bg: oklch(0.967 0.003 264); --surface: oklch(1 0 0); - --surface-raised: oklch(1 0 0); - --content: oklch(0.208 0.042 265.755); + --text: oklch(0.21 0.02 264); --brand: oklch(0.68 0.11 233); --on-brand: oklch(1 0 0); --link: oklch(0.74 0.238 322.16); - --info: oklch(0.35 0.08 240); + --info: oklch(0.43 0.2 255); --warning: oklch(0.35 0.08 60); --success: oklch(0.32 0.09 165); --danger: oklch(0.35 0.12 25); + --text-muted: oklch(49.77% 0.0135 264); + --text-subtle: oklch(60.36% 0.0112 264); + --surface-sunken: oklch(95.7% 0.003 264); + --surface-overlay: oklch(98.3% 0.003 264); + --hairline: oklch(21% 0.02 264 / 0.08); + --hover-faint: oklch(92.7% 0.003 264); + --brand-hover: oklch(62% 0.11 233); + --brand-subtle: oklch(93.26% 0.0155 238); + --brand-subtle-hover: oklch(89.26% 0.0155 238); + --focus-ring: oklch(68% 0.11 233 / 0.6); + --progress-start: oklch(77.7% 0.0724 233.4); + --progress-end: oklch(0.68 0.11 233); + --info-surface: oklch(94% 0.05 255); + --warning-surface: oklch(95% 0.05 60); + --success-surface: oklch(94% 0.05 165); + --danger-surface: oklch(94% 0.05 25); + --danger-surface-hover: oklch(90% 0.05 25); + --scrim: oklch(0% 0 0 / 0.6); + --mega-menu-bg: oklch(98.3% 0.003 264 / 0.66); + --app-shadow-sm: 0 1px 3px oklch(0 0 0 / 0.06), 0 1px 2px oklch(0 0 0 / 0.04); + --app-shadow-md: 0 4px 16px oklch(0 0 0 / 0.08), 0 1px 3px oklch(0 0 0 / 0.04); + --app-shadow-lg: 0 12px 32px oklch(0 0 0 / 0.12); - /* Layer 2: semantic surface and content roles */ - --surface-subtle: oklch(from var(--surface-raised) calc(l - 0.02) c h); - --surface-muted: oklch(from var(--surface-raised) calc(l - 0.05) c h); - --content-muted: oklch(0.446 0.043 257.281); - --content-subtle: color-mix(in oklab, var(--content) 52%, var(--surface-raised)); - - /* Layer 2: semantic brand roles */ - --brand-faint: color-mix(in oklab, var(--brand) 8%, var(--surface-raised)); - --brand-soft: color-mix(in oklab, var(--brand) 15%, var(--surface-raised)); - --brand-emphasis: color-mix(in oklab, var(--brand) 25%, var(--surface-raised)); - --brand-emphasis-hover: color-mix( - in oklab, - var(--brand) 30%, - var(--surface-raised) - ); - --brand-hover: color-mix(in oklab, var(--brand) 90%, var(--surface-raised)); - --focus-ring: var(--brand-emphasis); - - /* Layer 2: semantic border and material roles */ - --border-faint: color-mix(in oklab, var(--content) 8%, transparent); - --border-subtle: color-mix(in oklab, var(--content) 12%, transparent); - --border-strong: color-mix(in oklab, var(--content) 28%, transparent); - --glass-surface: color-mix(in oklab, var(--surface) 92%, transparent); - --glass-raised: color-mix(in oklab, var(--surface-raised) 96%, transparent); - --scrim: oklch(0 0 0 / 0.5); - - /* Layer 2: semantic status families */ - --info-surface: oklch(from var(--info) 0.94 0.05 h); - --info-content: var(--info); - --info-border: color-mix(in oklab, var(--info) 28%, var(--surface-raised)); - --warning-surface: oklch(from var(--warning) 0.95 0.05 h); - --warning-content: var(--warning); - --warning-border: color-mix(in oklab, var(--warning) 28%, var(--surface-raised)); - --success-surface: oklch(from var(--success) 0.94 0.05 h); - --success-content: var(--success); - --success-border: color-mix(in oklab, var(--success) 28%, var(--surface-raised)); - --danger-surface: oklch(from var(--danger) 0.94 0.05 h); - --danger-content: var(--danger); - --danger-border: color-mix(in oklab, var(--danger) 28%, var(--surface-raised)); - - /* Layer 2: shell and navigation */ - --header-bg: var(--canvas); - --header-interactive-bg: oklch(from var(--header-bg) calc(l - 0.12) c h); - --header-glass-bg: color-mix(in oklab, var(--header-bg) 40%, transparent); - - /* Layer 2: focused component responsibilities */ - --tooltip-bg: oklch(from var(--surface) calc(l - 0.015) c h); - --terminal-bg: oklch(0.24 0.02 260); - --terminal-content: oklch(1 0 0); - --progress-track-bg: oklch(0.929 0.013 255.508); - --progress-start: var(--brand); - --progress-end: oklch(from var(--brand) calc(l + 0.07) c calc(h - 35)); - --input-bg: var(--surface); - --input-checked-content: oklch(1 0 0); - - /* Layer 2: buttons and neutral status */ - --button-secondary-bg: oklch(0.929 0.013 255.508); - --button-secondary-hover-bg: color-mix( - in oklab, - var(--button-secondary-bg) 90%, - var(--surface-raised) - ); - --button-secondary-content: oklch(0.372 0.044 257.287); - --button-secondary-border: var(--button-secondary-bg); - --button-muted-bg: var(--surface-muted); - --button-muted-hover-bg: color-mix( - in oklab, - var(--button-muted-bg) 90%, - var(--surface-raised) - ); - --button-muted-content: var(--content-muted); - --button-muted-border: var(--button-muted-bg); - --neutral-status-surface: oklch(0.97 0 0); - --neutral-status-content: oklch(0.205 0 0); - --neutral-status-border: var(--border-faint); - - /* Layer 2: responsibilities formerly shared by label-surface */ - --card-action-bg: var(--surface-subtle); - --interface-badge-bg: var(--surface-subtle); - --segmented-control-bg: var(--surface-subtle); - --ifacebox-header-bg: var(--surface-subtle); - --table-header-bg: var(--surface-subtle); - --table-row-hover-bg: var(--surface-subtle); - --table-row-alternate-bg: color-mix( - in oklab, - var(--table-row-hover-bg) 50%, - var(--surface-raised) - ); - - /* Structure */ --font-sans: "Lato", ui-sans-serif, system-ui, sans-serif; --font-mono: ui-monospace, "SF Mono", Menlo, Monaco, Consolas, monospace; --spacing: 0.25rem; @@ -125,52 +47,44 @@ } [data-darkmode="true"] { - /* Layer 1: theme inputs */ - --canvas: oklch(0.32 0.059 188.42); - --surface: oklch(0.21 0.034 264.665); - --surface-raised: oklch(0.279 0.041 260.031); - --content: oklch(0.968 0.007 247.896); + --bg: oklch(0.13 0.018 264); + --surface: oklch(0.21 0.02 264); + --text: oklch(0.985 0.002 264); --brand: oklch(0.6 0.13 188.745); --on-brand: oklch(1 0 0); - --link: oklch(0.702 0.183 293.541); - --info: oklch(0.88 0.06 230); - --warning: oklch(0.924 0.12 95.746); - --success: oklch(0.92 0.09 160); - --danger: oklch(0.88 0.14 25); - - /* Mode-sensitive semantic roles */ - --surface-subtle: oklch(from var(--surface-raised) calc(l + 0.04) c h); - --surface-muted: oklch(from var(--surface-raised) calc(l + 0.09) c h); - --content-muted: oklch(0.704 0.04 256.788); - --info-surface: oklch(from var(--info) 0.34 0.07 h); - --warning-surface: oklch(from var(--warning) 0.35 0.08 h); - --success-surface: oklch(from var(--success) 0.33 0.06 h); - --danger-surface: oklch(from var(--danger) 0.34 0.09 h); - - /* Mode-sensitive component roles */ - --header-bg: var(--surface); - --header-interactive-bg: oklch(from var(--header-bg) calc(l + 0.24) c h); - --header-glass-bg: color-mix(in oklab, var(--header-bg) 90%, transparent); - --tooltip-bg: oklch(from var(--surface) calc(l + 0.06) c h); - --terminal-bg: oklch(0.18 0.03 260); - --terminal-content: oklch(1 0 0); - --progress-track-bg: oklch(0.372 0.044 257.287); - --progress-start: oklch(0.4318 0.0865 166.91); - --progress-end: oklch(0.621 0.145 189.632); - --input-checked-content: oklch(1 0 0); - --button-secondary-bg: oklch(0.372 0.044 257.287); - --button-secondary-content: oklch(0.928 0.006 264.531); - --button-muted-content: oklch(0.704 0.04 256.788); - --neutral-status-surface: oklch(0.274 0.006 286.033); - --neutral-status-content: oklch(0.985 0.01 285.805); + --link: oklch(0.77 0.14 168); + --info: oklch(0.8 0.11 255); + --warning: oklch(0.82 0.13 80); + --success: oklch(0.72 0.13 158); + --danger: oklch(0.7 0.16 22); + --text-muted: oklch(66.01% 0.0081 264); + --text-subtle: oklch(48.91% 0.0113 264); + --surface-sunken: oklch(16.5% 0.02 264); + --surface-overlay: oklch(23% 0.02 264); + --hairline: oklch(98.5% 0.002 264 / 0.1); + --hover-faint: oklch(98.5% 0.002 264 / 0.05); + --brand-hover: oklch(55% 0.13 188.7); + --brand-subtle: oklch(20.52% 0.0287 219.4); + --brand-subtle-hover: oklch(24.52% 0.0287 219.4); + --focus-ring: oklch(60% 0.13 188.7 / 0.6); + --progress-start: oklch(43.18% 0.0865 166.9); + --progress-end: oklch(62.1% 0.145 189.6); + --info-surface: oklch(32% 0.05 255); + --warning-surface: oklch(33% 0.06 80); + --success-surface: oklch(30% 0.05 158); + --danger-surface: oklch(32% 0.08 22); + --danger-surface-hover: oklch(36% 0.08 22); + --scrim: oklch(0% 0 0 / 0.6); + --mega-menu-bg: oklch(23% 0.02 264 / 0.62); + --app-shadow-sm: 0 4px 12px oklch(0 0 0 / 0.3); + --app-shadow-md: 0 10px 28px oklch(0 0 0 / 0.42); + --app-shadow-lg: 0 20px 48px oklch(0 0 0 / 0.55); } @theme inline { - /* Layer 1 */ - --color-canvas: var(--canvas); + --color-bg: var(--bg); --color-surface: var(--surface); - --color-surface-raised: var(--surface-raised); - --color-content: var(--content); + --color-text: var(--text); --color-brand: var(--brand); --color-on-brand: var(--on-brand); --color-link: var(--link); @@ -178,72 +92,37 @@ --color-warning: var(--warning); --color-success: var(--success); --color-danger: var(--danger); - - /* Layer 2: semantic */ - --color-surface-subtle: var(--surface-subtle); - --color-surface-muted: var(--surface-muted); - --color-content-muted: var(--content-muted); - --color-content-subtle: var(--content-subtle); - --color-brand-faint: var(--brand-faint); - --color-brand-soft: var(--brand-soft); - --color-brand-emphasis: var(--brand-emphasis); - --color-brand-emphasis-hover: var(--brand-emphasis-hover); + --color-text-muted: var(--text-muted); + --color-text-subtle: var(--text-subtle); + --color-surface-sunken: var(--surface-sunken); + --color-surface-overlay: var(--surface-overlay); + --color-hairline: var(--hairline); + --color-hover-faint: var(--hover-faint); --color-brand-hover: var(--brand-hover); + --color-brand-subtle: var(--brand-subtle); + --color-brand-subtle-hover: var(--brand-subtle-hover); --color-focus-ring: var(--focus-ring); - --color-border-faint: var(--border-faint); - --color-border-subtle: var(--border-subtle); - --color-border-strong: var(--border-strong); - --color-glass-surface: var(--glass-surface); - --color-glass-raised: var(--glass-raised); - --color-scrim: var(--scrim); - --color-info-surface: var(--info-surface); - --color-info-content: var(--info-content); - --color-info-border: var(--info-border); - --color-warning-surface: var(--warning-surface); - --color-warning-content: var(--warning-content); - --color-warning-border: var(--warning-border); - --color-success-surface: var(--success-surface); - --color-success-content: var(--success-content); - --color-success-border: var(--success-border); - --color-danger-surface: var(--danger-surface); - --color-danger-content: var(--danger-content); - --color-danger-border: var(--danger-border); - - /* Layer 2: component */ - --color-header-bg: var(--header-bg); - --color-header-interactive-bg: var(--header-interactive-bg); - --color-header-glass-bg: var(--header-glass-bg); - --color-tooltip-bg: var(--tooltip-bg); - --color-terminal-bg: var(--terminal-bg); - --color-terminal-content: var(--terminal-content); - --color-progress-track-bg: var(--progress-track-bg); --color-progress-start: var(--progress-start); --color-progress-end: var(--progress-end); - --color-input-bg: var(--input-bg); - --color-input-checked-content: var(--input-checked-content); - --color-button-secondary-bg: var(--button-secondary-bg); - --color-button-secondary-hover-bg: var(--button-secondary-hover-bg); - --color-button-secondary-content: var(--button-secondary-content); - --color-button-secondary-border: var(--button-secondary-border); - --color-button-muted-bg: var(--button-muted-bg); - --color-button-muted-hover-bg: var(--button-muted-hover-bg); - --color-button-muted-content: var(--button-muted-content); - --color-button-muted-border: var(--button-muted-border); - --color-neutral-status-surface: var(--neutral-status-surface); - --color-neutral-status-content: var(--neutral-status-content); - --color-neutral-status-border: var(--neutral-status-border); - --color-card-action-bg: var(--card-action-bg); - --color-interface-badge-bg: var(--interface-badge-bg); - --color-segmented-control-bg: var(--segmented-control-bg); - --color-ifacebox-header-bg: var(--ifacebox-header-bg); - --color-table-header-bg: var(--table-header-bg); - --color-table-row-hover-bg: var(--table-row-hover-bg); - --color-table-row-alternate-bg: var(--table-row-alternate-bg); + --color-info-surface: var(--info-surface); + --color-warning-surface: var(--warning-surface); + --color-success-surface: var(--success-surface); + --color-danger-surface: var(--danger-surface); + --color-danger-surface-hover: var(--danger-surface-hover); + --color-scrim: var(--scrim); + --color-mega-menu-bg: var(--mega-menu-bg); + + --shadow-sm: var(--app-shadow-sm); + --shadow-md: var(--app-shadow-md); + --shadow-lg: var(--app-shadow-md); + --shadow-xl: var(--app-shadow-lg); + --shadow-2xl: var(--app-shadow-lg); --font-sans: var(--font-sans); --font-mono: var(--font-mono); --spacing: var(--spacing); --container-max-width: var(--container-max-width); + --radius-sm: calc(var(--radius-base) * 0.25); --radius: calc(var(--radius-base) * 0.5); --radius-md: calc(var(--radius-base) * 0.75); diff --git a/luci-theme-aurora/.dev/src/media/_utilities.css b/luci-theme-aurora/.dev/src/media/_utilities.css index e3103ecc..d55bc5a5 100644 --- a/luci-theme-aurora/.dev/src/media/_utilities.css +++ b/luci-theme-aurora/.dev/src/media/_utilities.css @@ -52,11 +52,11 @@ } .fade-in { - @apply animate-in fade-in-0 fill-mode-backwards duration-400; + @apply animate-in fade-in-0 fill-mode-backwards duration-[250ms]; } .fade-out { - @apply pointer-events-none opacity-0 transition-opacity duration-400; + @apply pointer-events-none opacity-0 transition-opacity duration-[250ms]; } .spinning { diff --git a/luci-theme-aurora/.dev/src/media/components/_badge.css b/luci-theme-aurora/.dev/src/media/components/_badge.css index c8e60ad1..f8f8002d 100644 --- a/luci-theme-aurora/.dev/src/media/components/_badge.css +++ b/luci-theme-aurora/.dev/src/media/components/_badge.css @@ -1,31 +1,31 @@ .label { - @apply bg-neutral-status-surface text-neutral-status-content rounded-full px-3 py-1 text-xs font-bold uppercase; + @apply bg-surface-sunken text-text rounded-full px-3 py-1 text-xs font-bold uppercase; &.important { - @apply bg-info-surface text-info-content; + @apply bg-info-surface text-info; } &.warning { - @apply bg-danger-surface text-danger-content; + @apply bg-danger-surface text-danger; } &.success { - @apply bg-success-surface text-success-content; + @apply bg-success-surface text-success; } &.notice { - @apply bg-warning-surface text-warning-content; + @apply bg-warning-surface text-warning; } } .zonebadge { - @apply border-border-subtle bg-interface-badge-bg text-content inline-flex items-center gap-1.5 overflow-visible rounded-full border px-1 py-1.5 text-sm font-medium shadow-sm transition-[box-shadow] duration-200 hover:shadow-md max-md:gap-1 max-md:text-xs; + @apply border-hairline bg-surface-sunken text-text inline-flex items-center gap-1.5 overflow-visible rounded-full border px-1 py-1.5 text-sm font-medium shadow-sm transition-[box-shadow] duration-150 hover:shadow-md max-md:gap-1 max-md:text-xs; &[style*="--zone-color-rgb"] { @apply bg-[rgb(var(--zone-color-rgb),.7)]!; & em { - @apply text-content; + @apply text-text; } } @@ -35,7 +35,7 @@ } .ifacebadge { - @apply border-border-subtle bg-interface-badge-bg text-content hover:border-border-strong hover:bg-interface-badge-bg inline-flex cursor-default flex-wrap items-center gap-2 rounded-2xl border px-3 py-2 text-sm font-normal shadow-sm transition-[box-shadow,border-color,background-color] duration-200 hover:shadow-md max-md:gap-1.5 max-md:px-2.5 max-md:py-1.5 max-md:text-xs; + @apply border-hairline bg-surface-sunken text-text hover:border-hairline hover:bg-surface-sunken inline-flex cursor-default flex-wrap items-center gap-2 rounded-2xl border px-3 py-2 text-sm font-normal shadow-sm transition-[box-shadow,border-color,background-color] duration-150 hover:shadow-md max-md:gap-1.5 max-md:px-2.5 max-md:py-1.5 max-md:text-xs; .cbi-dropdown &, .cbi-tooltip & { diff --git a/luci-theme-aurora/.dev/src/media/components/_button.css b/luci-theme-aurora/.dev/src/media/components/_button.css index 681b7940..b5a0347b 100644 --- a/luci-theme-aurora/.dev/src/media/components/_button.css +++ b/luci-theme-aurora/.dev/src/media/components/_button.css @@ -6,7 +6,7 @@ input[type="reset"], .cbi-button { /* transform stays in this list for the .cbi-button active:scale-95 variant in _form.css, which relies on this base transition. */ - @apply inline-flex cursor-pointer items-center justify-center gap-1.5 rounded-2xl border px-3 py-1.5 text-sm font-medium antialiased shadow-sm transition-[background-color,border-color,transform] duration-200 max-md:text-base max-md:font-medium; + @apply inline-flex cursor-pointer items-center justify-center gap-1.5 rounded-xl border px-3 py-1.5 text-sm font-medium antialiased transition-[background-color,border-color,transform] duration-150 max-md:text-base max-md:font-medium; &[disabled] { @apply cursor-not-allowed opacity-40 dark:opacity-30; } @@ -23,11 +23,11 @@ input[type="reset"], .cbi-button-link, .cbi-button-up, .cbi-button-down { - @apply border-button-secondary-border bg-button-secondary-bg text-button-secondary-content hover:bg-button-secondary-hover-bg; + @apply border-hairline bg-surface-sunken text-text hover:bg-hover-faint; } .drag-handle { - @apply border-button-muted-border bg-button-muted-bg text-button-muted-content hover:bg-button-muted-hover-bg; + @apply border-hairline bg-surface-sunken text-text-muted hover:bg-hover-faint; } .btn.primary, @@ -42,12 +42,12 @@ input[type="reset"], .cbi-button-positive, .cbi-button-fieldadd, .cbi-button-save { - @apply border-brand-emphasis bg-brand-emphasis text-brand hover:bg-brand-emphasis-hover; + @apply border-transparent bg-brand-subtle text-brand hover:bg-brand-subtle-hover; } .cbi-button-negative, .cbi-section-remove .cbi-button, .cbi-button-reset, .cbi-button-remove { - @apply border-danger-border bg-danger-surface text-danger-content hover:bg-danger-border; + @apply border-transparent bg-danger-surface text-danger hover:bg-danger-surface-hover; } diff --git a/luci-theme-aurora/.dev/src/media/components/_card.css b/luci-theme-aurora/.dev/src/media/components/_card.css index 7b8146a0..13b4919c 100644 --- a/luci-theme-aurora/.dev/src/media/components/_card.css +++ b/luci-theme-aurora/.dev/src/media/components/_card.css @@ -9,7 +9,7 @@ } #maincontent & { - @apply border-border-faint bg-surface-raised hover:border-border-subtle border shadow-lg hover:shadow-xl; + @apply bg-surface border-hairline border shadow-sm; } & > .cbi-title { @@ -19,12 +19,12 @@ @apply flex-1; & .label[data-clickable] { - @apply text-content bg-card-action-bg; - @apply inline-flex size-7 cursor-pointer items-center justify-center p-0 before:size-4 before:bg-current before:transition-transform before:duration-300 hover:shadow-md active:scale-95 max-md:size-6; + @apply text-text bg-surface-sunken; + @apply inline-flex size-7 cursor-pointer items-center justify-center p-0 before:size-4 before:bg-current before:transition-transform before:duration-150 hover:shadow-md active:scale-95 max-md:size-6; } & span[data-indicator="poll-status"] { - @apply relative size-5 cursor-pointer text-[0px] before:absolute before:size-5 before:bg-current before:transition-transform before:duration-300 before:ease-out hover:before:scale-110 active:before:scale-95; + @apply relative size-5 cursor-pointer text-[0px] before:absolute before:size-5 before:bg-current before:transition-transform before:duration-150 before:ease-out hover:before:scale-110 active:before:scale-95; &[data-style="active"] { @apply before:rotate-0 before:[mask:url('@assets/icons/arrow-right.svg')_center/cover_no-repeat]; @@ -42,7 +42,7 @@ } & h3 { - @apply text-content border-border-subtle border-b pb-4 max-md:mx-0 max-md:pb-2; + @apply text-text border-hairline border-b pb-4 max-md:mx-0 max-md:pb-2; } & div[style*="display:grid"] { @@ -63,14 +63,14 @@ } .ifacebox { - @apply border-border-subtle bg-glass-raised hover:border-border-strong max-md:border-border-subtle relative inline-flex min-w-40 flex-col items-stretch overflow-visible rounded-2xl border text-center text-base leading-5 shadow-md hover:shadow-lg max-md:min-w-30 max-md:flex-1 max-md:rounded-3xl max-md:shadow-sm; + @apply border-hairline bg-surface-overlay hover:border-hairline max-md:border-hairline relative inline-flex min-w-40 flex-col items-stretch overflow-visible rounded-2xl border text-center text-base leading-5 shadow-md hover:shadow-xl max-md:min-w-30 max-md:flex-1 max-md:rounded-3xl max-md:shadow-sm; td & { @apply max-md:flex-row; } & .ifacebox-head { - @apply border-border-subtle bg-ifacebox-header-bg text-content w-full rounded-t-2xl border-b px-4 py-3 text-center font-semibold tracking-tight transition-[background-color,border-color,color] duration-200 max-md:rounded-t-3xl max-md:px-3 max-md:py-2.5 max-md:text-sm max-md:leading-5 max-md:font-medium; + @apply border-hairline bg-surface-sunken text-text w-full rounded-t-2xl border-b px-4 py-3 text-center font-semibold tracking-tight transition-[background-color,border-color,color] duration-150 max-md:rounded-t-3xl max-md:px-3 max-md:py-2.5 max-md:text-sm max-md:leading-5 max-md:font-medium; &[style*="--zone-color-rgb"] { @apply bg-[rgb(var(--zone-color-rgb),.75)]!; @@ -93,14 +93,14 @@ } & .ifacebox-body { - @apply text-content flex w-full flex-1 flex-col items-center justify-around gap-2 rounded-b-2xl p-4 text-center max-md:rounded-b-3xl; + @apply text-text flex w-full flex-1 flex-col items-center justify-around gap-2 rounded-b-2xl p-4 text-center max-md:rounded-b-3xl; td & { @apply max-md:flex-row max-md:rounded-r-3xl max-md:rounded-bl-none max-md:py-2 max-md:pr-2 max-md:pl-4; } & > span { - @apply text-content space-y-1.5 max-md:space-y-1 max-md:text-sm max-md:leading-5; + @apply text-text space-y-1.5 max-md:space-y-1 max-md:text-sm max-md:leading-5; .network-status-table & { @apply w-full; @@ -138,7 +138,7 @@ } & .cbi-tooltip-container { - @apply text-content static inline-flex cursor-help items-center justify-center; + @apply text-text static inline-flex cursor-help items-center justify-center; & .cbi-tooltip { @apply bottom-0 md:left-0; diff --git a/luci-theme-aurora/.dev/src/media/components/_dropdown.css b/luci-theme-aurora/.dev/src/media/components/_dropdown.css index 0b7c9b4b..7f486911 100644 --- a/luci-theme-aurora/.dev/src/media/components/_dropdown.css +++ b/luci-theme-aurora/.dev/src/media/components/_dropdown.css @@ -6,7 +6,7 @@ } &:not(.btn):not(.cbi-button) { - @apply border-border-subtle bg-surface rounded-2xl border; + @apply border-hairline bg-surface rounded-2xl border; & > ul > li { &[placeholder] { @apply hidden; @@ -50,10 +50,10 @@ } &.dropdown { - @apply border-border-subtle bg-glass-surface absolute left-0 z-60 w-fit min-w-full overflow-y-auto rounded-lg border shadow-xl backdrop-blur-sm; + @apply border-hairline bg-surface-overlay absolute left-0 z-60 w-fit min-w-full overflow-y-auto rounded-lg border shadow-xl backdrop-blur-md backdrop-saturate-150; & > li { - @apply text-content-muted hover:bg-brand-soft min-h-9 w-full cursor-pointer px-3 py-1.5 font-medium; + @apply text-text-muted hover:bg-brand-subtle min-h-9 w-full cursor-pointer px-3 py-1.5 font-medium; } } @@ -86,7 +86,7 @@ @apply flex; &[selected] { - @apply bg-brand-emphasis text-brand; + @apply bg-brand-subtle text-brand; } &[unselectable] { @@ -127,7 +127,7 @@ } & > .open { - @apply border-border-subtle flex flex-none shrink-0 cursor-pointer items-center justify-center border-l px-2.5 py-0.5 text-sm text-current; + @apply border-hairline flex flex-none shrink-0 cursor-pointer items-center justify-center border-l px-2.5 py-0.5 text-sm text-current; } & > .more { diff --git a/luci-theme-aurora/.dev/src/media/components/_float-button.css b/luci-theme-aurora/.dev/src/media/components/_float-button.css index b242ec7e..2dd3735b 100644 --- a/luci-theme-aurora/.dev/src/media/components/_float-button.css +++ b/luci-theme-aurora/.dev/src/media/components/_float-button.css @@ -2,22 +2,22 @@ @apply fixed right-4 bottom-4 z-40 flex flex-col items-center max-md:right-3 max-md:bottom-3; .toolbar-list { - @apply visible mb-2 grid origin-bottom grid-rows-[1fr] opacity-100 transition-[grid-template-rows,transform,opacity,visibility] duration-300 ease-in-out max-md:mb-1.5; + @apply visible mb-2 grid origin-bottom grid-rows-[1fr] opacity-100 transition-[grid-template-rows,transform,opacity,visibility] duration-[250ms] ease-in-out max-md:mb-1.5; .toolbar-list-inner { - @apply border-border-subtle bg-glass-surface flex min-h-0 flex-col items-center gap-2 overflow-hidden rounded-full border p-1 shadow-sm max-md:gap-1.5 max-md:p-0.5; + @apply border-hairline bg-surface-overlay flex min-h-0 flex-col items-center gap-2 overflow-hidden rounded-full border p-1 shadow-sm max-md:gap-1.5 max-md:p-0.5; } } .toolbar-btn { - @apply flex h-10 w-10 shrink-0 cursor-pointer items-center justify-center rounded-full p-2 transition-[background-color,transform,opacity] duration-200 ease-in-out active:scale-95 max-md:h-9 max-md:w-9 max-md:p-1.5; + @apply flex h-10 w-10 shrink-0 cursor-pointer items-center justify-center rounded-full p-2 transition-[background-color,transform,opacity] duration-150 ease-in-out active:scale-95 max-md:h-9 max-md:w-9 max-md:p-1.5; .icon { - @apply h-5 w-5 shrink-0 transition-transform duration-300 ease-in-out max-md:h-4 max-md:w-4; + @apply h-5 w-5 shrink-0 transition-transform duration-150 ease-in-out max-md:h-4 max-md:w-4; } &:not(.toggle) { - @apply hover:bg-border-faint no-underline hover:scale-110; + @apply hover:bg-hover-faint no-underline hover:scale-110; .icon { @apply object-contain dark:invert; } @@ -26,7 +26,7 @@ &.toggle { @apply bg-surface border-0 shadow-sm; .icon { - @apply transition-transform duration-300 ease-out; + @apply transition-transform duration-150 ease-out; } } } diff --git a/luci-theme-aurora/.dev/src/media/components/_form.css b/luci-theme-aurora/.dev/src/media/components/_form.css index 23e9014f..25e104a3 100644 --- a/luci-theme-aurora/.dev/src/media/components/_form.css +++ b/luci-theme-aurora/.dev/src/media/components/_form.css @@ -1,6 +1,6 @@ .cbi-input-invalid, .cbi-value-error { - @apply !border-danger-border focus:!ring-danger-border; + @apply !border-danger focus:!ring-danger; } .cbi-value { @@ -25,10 +25,10 @@ @apply cursor-not-allowed; } & .cbi-value-description { - @apply text-content-muted relative mt-1 pl-4 leading-none wrap-break-word; + @apply text-text-muted relative mt-1 pl-4 leading-none wrap-break-word; &:not(:empty) { - @apply before:bg-info-content before:absolute before:-left-0.5 before:inline-block before:size-4 before:[mask:url('@assets/icons/info.svg')_center/cover_no-repeat]; + @apply before:bg-info before:absolute before:-left-0.5 before:inline-block before:size-4 before:[mask:url('@assets/icons/info.svg')_center/cover_no-repeat]; } } } @@ -43,15 +43,15 @@ @apply inline-flex w-max max-w-120 flex-col items-start gap-3 max-md:max-w-full!; & .item { - @apply border-border-faint bg-surface-raised pointer-events-auto relative inline-flex cursor-move flex-col items-start gap-2 self-stretch overflow-hidden rounded-2xl border py-3 pr-10 pl-4 break-all shadow-sm transition-[transform,box-shadow,opacity,border-color,background-color] duration-200 select-text max-md:w-full max-md:py-2.5 max-md:pr-8 max-md:pl-3; - @apply after:bg-button-muted-bg after:text-button-muted-content after:absolute after:top-2.5 after:right-2 after:inline-flex after:h-6 after:w-6 after:shrink-0 after:cursor-pointer after:items-center after:justify-center after:rounded-xl after:text-sm after:font-medium after:content-['\00D7']; + @apply border-hairline bg-surface pointer-events-auto relative inline-flex cursor-move flex-col items-start gap-2 self-stretch overflow-hidden rounded-2xl border py-3 pr-10 pl-4 break-all shadow-sm transition-[transform,box-shadow,opacity,border-color,background-color] duration-150 select-text max-md:w-full max-md:py-2.5 max-md:pr-8 max-md:pl-3; + @apply after:bg-surface-sunken after:text-text-muted after:absolute after:top-2.5 after:right-2 after:inline-flex after:h-6 after:w-6 after:shrink-0 after:cursor-pointer after:items-center after:justify-center after:rounded-xl after:text-sm after:font-medium after:content-['\00D7']; &.dragging { @apply scale-95 cursor-grabbing opacity-50 shadow-2xl; } &.drag-over { - @apply border-brand bg-brand-faint ring-brand-emphasis scale-105 shadow-lg ring-2; + @apply border-brand bg-brand-subtle ring-brand-subtle scale-105 shadow-lg ring-2; } & > span, @@ -65,7 +65,7 @@ } & .add-item { - @apply border-border-subtle hover:border-border-strong hover:bg-surface-subtle inline-flex items-center gap-1.5 self-stretch rounded-2xl border border-dashed bg-transparent px-1 py-1 transition-[border-color,background-color] duration-200; + @apply border-hairline hover:border-hairline hover:bg-surface-sunken inline-flex items-center gap-1.5 self-stretch rounded-2xl border border-dashed bg-transparent px-1 py-1 transition-[border-color,background-color] duration-150; & > input { @apply min-w-61 flex-1; diff --git a/luci-theme-aurora/.dev/src/media/components/_input.css b/luci-theme-aurora/.dev/src/media/components/_input.css index eac8eedb..f9b49a18 100644 --- a/luci-theme-aurora/.dev/src/media/components/_input.css +++ b/luci-theme-aurora/.dev/src/media/components/_input.css @@ -6,7 +6,7 @@ input[type="text"], input[type="password"], .cbi-input-text, .cbi-input { - @apply text-content border-border-subtle bg-surface placeholder-content-muted focus:border-brand focus:ring-brand-emphasis relative rounded-2xl border px-3 py-1.5 text-sm font-normal shadow-sm transition-[border-color,box-shadow] duration-200 focus:ring-2 focus:outline-none; + @apply text-text border-hairline bg-surface-sunken placeholder-text-muted focus:border-brand focus:ring-focus-ring relative rounded-2xl border px-3 py-1.5 text-sm font-normal shadow-sm transition-[border-color,box-shadow] duration-150 focus:ring-2 focus:outline-none; .table.cbi-section-table & { @apply w-full; @@ -23,7 +23,7 @@ input[type="password"], input[type="radio"], input[type="checkbox"] { - @apply focus:before:border-brand focus:before:ring-brand-emphasis checked:before:border-brand checked:before:bg-brand before:border-border-subtle before:bg-surface after:bg-input-checked-content hover:before:border-border-strong relative mr-3 inline-block h-4 w-4 cursor-pointer appearance-none before:absolute before:top-0 before:left-0 before:h-4 before:w-4 before:border before:transition-[background-color,border-color,box-shadow] before:duration-200 after:absolute after:top-0.5 after:left-0.5 after:h-3 after:w-3 after:opacity-0 after:transition-opacity after:duration-200 checked:after:opacity-100 focus:before:ring-2 focus:before:outline-none disabled:cursor-not-allowed; + @apply focus:before:border-brand focus:before:ring-focus-ring checked:before:border-brand checked:before:bg-brand before:border-hairline before:bg-surface-sunken after:bg-on-brand hover:before:border-hairline relative mr-3 inline-block h-4 w-4 cursor-pointer appearance-none before:absolute before:top-0 before:left-0 before:h-4 before:w-4 before:border before:transition-[background-color,border-color,box-shadow] before:duration-150 after:absolute after:top-0.5 after:left-0.5 after:h-3 after:w-3 after:opacity-0 after:transition-opacity after:duration-150 checked:after:opacity-100 focus:before:ring-2 focus:before:outline-none disabled:cursor-not-allowed; } input[type="radio"] { diff --git a/luci-theme-aurora/.dev/src/media/components/_message.css b/luci-theme-aurora/.dev/src/media/components/_message.css index 82031c07..e5c41b1f 100644 --- a/luci-theme-aurora/.dev/src/media/components/_message.css +++ b/luci-theme-aurora/.dev/src/media/components/_message.css @@ -1,5 +1,5 @@ .alert-message { - @apply bg-neutral-status-surface text-neutral-status-content border-neutral-status-border sticky top-14 z-40 mb-4 rounded-4xl border p-6 max-md:mx-0 max-md:mb-3 max-md:rounded-3xl max-md:p-4; + @apply bg-surface-sunken text-text border-hairline sticky top-14 z-40 mb-4 rounded-4xl border p-6 max-md:mx-0 max-md:mb-3 max-md:rounded-3xl max-md:p-4; &.modal { @apply static top-auto; @@ -14,21 +14,21 @@ } &.success { - @apply border-success-border bg-success-surface text-success-content; + @apply border-hairline bg-success-surface text-success; } &.info { - @apply border-info-border bg-info-surface text-info-content; + @apply border-hairline bg-info-surface text-info; } &.warning, &.notice { - @apply border-warning-border bg-warning-surface text-warning-content; + @apply border-hairline bg-warning-surface text-warning; } &.error, &.danger { - @apply border-danger-border bg-danger-surface text-danger-content; + @apply border-hairline bg-danger-surface text-danger; } h4, diff --git a/luci-theme-aurora/.dev/src/media/components/_modal.css b/luci-theme-aurora/.dev/src/media/components/_modal.css index d6b0a001..f40166d2 100644 --- a/luci-theme-aurora/.dev/src/media/components/_modal.css +++ b/luci-theme-aurora/.dev/src/media/components/_modal.css @@ -2,11 +2,11 @@ @apply pointer-events-none fixed top-0 bottom-0 hidden overflow-auto bg-transparent; .modal-overlay-active & { - @apply bg-scrim pointer-events-auto inset-0 right-0 left-0 z-100 grid grid-cols-1 place-items-center backdrop-blur-sm; + @apply bg-scrim pointer-events-auto inset-0 right-0 left-0 z-100 grid grid-cols-1 place-items-center backdrop-blur-md backdrop-saturate-150; } & > .modal { - @apply border-border-subtle bg-surface relative flex w-5xl flex-col gap-4 rounded-3xl border p-6 wrap-break-word whitespace-normal shadow-2xl max-md:w-full max-md:gap-3 max-md:p-4; + @apply border-hairline bg-surface-overlay relative flex w-5xl flex-col gap-4 rounded-3xl border p-6 wrap-break-word whitespace-normal shadow-2xl max-md:w-full max-md:gap-3 max-md:p-4; & h4 { @apply mb-0 text-center; @@ -16,26 +16,26 @@ } & h5 { - @apply text-content my-3; + @apply text-text my-3; } & p { - @apply text-content text-sm leading-relaxed; + @apply text-text text-sm leading-relaxed; } & > ul { - @apply border-border-subtle bg-surface-subtle overflow-auto rounded-2xl border p-3; + @apply border-hairline overflow-auto rounded-2xl border p-3; } & label.btn { - @apply border-border-subtle bg-surface-subtle text-content hover:border-border-strong border; + @apply border-hairline bg-surface-sunken text-text hover:border-hairline border; } & pre { @apply overflow-auto; &.errors { - @apply border-danger-border bg-danger-surface text-danger-content; + @apply border-hairline bg-danger-surface text-danger; } } @@ -46,7 +46,7 @@ & .button-row, & div.left, & div.right { - @apply border-border-subtle flex shrink-0 gap-3 border-t p-4 max-md:gap-1.5 max-md:p-2.5; + @apply border-hairline flex shrink-0 gap-3 border-t p-4 max-md:gap-1.5 max-md:p-2.5; } & div.left { @@ -66,22 +66,22 @@ } & ins { - @apply border-success-border bg-success-surface text-success-content border; + @apply border-hairline bg-success-surface text-success border; } & del { - @apply border-danger-border bg-danger-surface text-danger-content border; + @apply border-hairline bg-danger-surface text-danger border; } & var { - @apply border-info-border bg-info-surface text-info-content border; + @apply border-hairline bg-info-surface text-info border; } & .uci-change-legend { - @apply border-border-subtle bg-surface-subtle mt-4 grid grid-cols-2 gap-3 rounded-2xl border p-4 max-md:grid-cols-1 max-md:gap-2 max-md:p-3; + @apply border-hairline bg-surface-sunken mt-4 grid grid-cols-2 gap-3 rounded-2xl border p-4 max-md:grid-cols-1 max-md:gap-2 max-md:p-3; & .uci-change-legend-label { - @apply text-content flex items-center gap-2 text-sm font-medium; + @apply text-text flex items-center gap-2 text-sm font-medium; & ins, & del, @@ -102,7 +102,7 @@ @apply mt-4 space-y-3; & h5 { - @apply bg-neutral-status-surface text-neutral-status-content mt-6 mb-2 rounded-xl px-3 py-2 text-sm font-semibold first:mt-0; + @apply bg-surface-sunken text-text mt-6 mb-2 rounded-xl px-3 py-2 text-sm font-semibold first:mt-0; } & ins, diff --git a/luci-theme-aurora/.dev/src/media/components/_nav.css b/luci-theme-aurora/.dev/src/media/components/_nav.css index fbb1ac74..0545ba03 100644 --- a/luci-theme-aurora/.dev/src/media/components/_nav.css +++ b/luci-theme-aurora/.dev/src/media/components/_nav.css @@ -8,15 +8,17 @@ */ .nav-link { - @apply text-content hover:bg-header-interactive-bg block rounded-xl px-3 py-1.5 no-underline transition-all duration-150; + @apply text-text hover:bg-hover-faint block rounded-xl px-3 py-1.5 no-underline transition-all duration-150; } -/* Mode-agnostic active state: brand text + weight only. The selected-pill - background is a sidebar affordance (set in _layout.css); the mobile drawer - deliberately omits it and uses an accent indicator bar instead (_overlay.css). - Repeats text-brand on hover so the base link's hover color never bleeds through. */ -.nav-link-active { - @apply text-brand hover:text-brand font-medium; +.navigation-direct { + @apply text-text hover:text-text; +} + +/* Direct destinations use the same selected state in both navigation modes: + a filled brand pill, matching the active sublink. */ +.navigation-direct.is-active-page { + @apply text-brand hover:text-brand bg-brand-subtle font-medium; } /* Category rows are group labels, not buttons: no hover surface, just a @@ -24,28 +26,53 @@ appearance-none + border-0 + shadow-none strip the theme's global