From 4ee3788dd492a09a199df4a381842f29a4981366 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 3 Sep 2026 03:25:04 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20Sync=202026-09-03=2003:25:04?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../root/usr/libexec/rpcd/luci.mptcp | 48 +++++++++++++++++- luci-app-passwall2/Makefile | 2 +- .../luasrc/passwall2/util_xray.lua | 2 +- luci-proto-wwand/Makefile | 6 +-- luci-theme-footstrap/Makefile | 2 +- .../luci-static/resources/fs-appearance.js | 10 ++++ luci-theme-footstrap/po/es/footstrap.po | 49 ++++++++++++++++--- luci-theme-footstrap/po/ru/footstrap.po | 48 +++++++++++++++--- .../po/templates/footstrap.pot | 28 ++++++++--- luci-theme-footstrap/styles/03-palettes.css | 36 +++++++++++++- luci-theme-footstrap/styles/04-nocolormix.css | 8 ++- luci-theme-footstrap/styles/base/30-forms.css | 4 +- .../styles/pages/80-appearance.css | 5 ++ .../styles/theme/65-dropdown.css | 15 ++++-- .../styles/theme/75-search.css | 5 +- .../styles/theme/95-a11y-media.css | 12 +++++ wwand/Makefile | 4 +- 17 files changed, 243 insertions(+), 41 deletions(-) diff --git a/luci-app-mptcp/root/usr/libexec/rpcd/luci.mptcp b/luci-app-mptcp/root/usr/libexec/rpcd/luci.mptcp index 619ebd19b..980a47793 100755 --- a/luci-app-mptcp/root/usr/libexec/rpcd/luci.mptcp +++ b/luci-app-mptcp/root/usr/libexec/rpcd/luci.mptcp @@ -289,6 +289,49 @@ function parse_ss_subflows(raw, endpoints) return subflows end +-- Live per-subflow TCP metrics preferring omr-sockdiag -- a raw +-- NETLINK_SOCK_DIAG/INET_DIAG query of the kernel's tcp_info straight off +-- the socket (see the omr-sockdiag package) -- over parsing "ss -tin" text. +-- Same preference order omr-metrics' 040-metrics post-tracking hook already +-- uses for its own per-WAN subflow collection. omr-sockdiag already emits +-- JSON with the field names this table already uses, so there is no text +-- parsing left to do here at all, only the same WAN attribution +-- parse_ss_subflows does above (a connection's local_ip matched against the +-- endpoints list -- omr-sockdiag has no MPTCP awareness of its own, it only +-- knows sockets). +-- +-- Returns nil when the output is not usable, so the caller can fall back to +-- parse_ss_subflows. omr-sockdiag itself prints "[]" both when no sockets +-- match and when the kernel query cannot be opened; if endpoints exist, let +-- the ss fallback disambiguate that case instead of hiding live subflows. +function parse_sockdiag_subflows(raw, endpoints) + local ok, rows = pcall(jsonc.parse, raw or "") + if not ok or type(rows) ~= "table" then return nil end + if #rows == 0 and #endpoints > 0 then return nil end + + local by_addr = {} + for _, ep in ipairs(endpoints) do by_addr[ep.address] = ep end + + local subflows = {} + for _, row in ipairs(rows) do + local ep = by_addr[row.local_ip] + if ep then + subflows[#subflows + 1] = { + dev = ep.dev, endpoint_id = ep.id, backup = ep.backup, + local_ip = row.local_ip, local_port = row.local_port, + remote_ip = row.remote_ip, remote_port = row.remote_port, + cwnd = row.cwnd, ssthresh = row.ssthresh, + rtt = row.rtt, rttvar = row.rttvar, min_rtt = row.min_rtt, + retrans = row.retrans, retrans_total = row.retrans_total, + bytes_sent = row.bytes_sent, bytes_acked = row.bytes_acked, + bytes_retrans = row.bytes_retrans, bytes_received = row.bytes_received, + pacing_rate = row.pacing_rate, delivery_rate = row.delivery_rate, + } + end + end + return subflows +end + -- Per-WAN endpoint cross-check: for every interface the router considers -- multipath-enabled, is its device actually registered as an MPTCP -- endpoint? If not, that WAN can never carry an MPTCP subflow no matter @@ -839,7 +882,10 @@ local methods = { for _, w in ipairs(wans) do if w.device ~= "" then dev_to_name[w.device] = w.name end end - local subflows = parse_ss_subflows(exec_output("ss -tin 2>/dev/null"), endpoints) + local subflows = parse_sockdiag_subflows(exec_output("omr-sockdiag 2>/dev/null"), endpoints) + if not subflows then + subflows = parse_ss_subflows(exec_output("ss -tin 2>/dev/null"), endpoints) + end for _, sf in ipairs(subflows) do sf.wan = dev_to_name[sf.dev] or sf.dev end diff --git a/luci-app-passwall2/Makefile b/luci-app-passwall2/Makefile index f1d9ea8b2..8492201ef 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.9.2 -PKG_RELEASE:=108 +PKG_RELEASE:=109 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 5995737e0..484a69acc 100644 --- a/luci-app-passwall2/luasrc/passwall2/util_xray.lua +++ b/luci-app-passwall2/luasrc/passwall2/util_xray.lua @@ -1838,7 +1838,7 @@ function gen_config(var) end end end - if dns_outboundTag == "blackhole" then + if value.outboundTag == "blackhole" then table.insert(dns_out_rules, { action = "return", rCode = 0, diff --git a/luci-proto-wwand/Makefile b/luci-proto-wwand/Makefile index 975e9cfa1..3819d3876 100644 --- a/luci-proto-wwand/Makefile +++ b/luci-proto-wwand/Makefile @@ -18,12 +18,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-proto-wwand -PKG_RELEASE:=5 +PKG_RELEASE:=6 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/ddimension/luci-proto-wwand.git -PKG_SOURCE_VERSION:=35f0323f5621eb06e69991f5819ff53e4ca8cc7a -PKG_SOURCE_DATE:=2026-08-31 +PKG_SOURCE_VERSION:=cc0bbfe522c7bc941a25f1ad14dfb2874660311b +PKG_SOURCE_DATE:=2026-09-02 PKG_MIRROR_HASH:=skip PKG_LICENSE:=GPL-2.0-only diff --git a/luci-theme-footstrap/Makefile b/luci-theme-footstrap/Makefile index fc8b3403d..5bb217002 100644 --- a/luci-theme-footstrap/Makefile +++ b/luci-theme-footstrap/Makefile @@ -17,7 +17,7 @@ LUCI_NAME:=luci-theme-footstrap FOOTSTRAP_VERSION?= ifneq ($(FOOTSTRAP_VERSION),) PKG_VERSION:=$(FOOTSTRAP_VERSION) -PKG_RELEASE:=53 +PKG_RELEASE:=54 endif LUCI_TITLE:=Footstrap Theme diff --git a/luci-theme-footstrap/htdocs/luci-static/resources/fs-appearance.js b/luci-theme-footstrap/htdocs/luci-static/resources/fs-appearance.js index 0a7b71986..5546e8415 100644 --- a/luci-theme-footstrap/htdocs/luci-static/resources/fs-appearance.js +++ b/luci-theme-footstrap/htdocs/luci-static/resources/fs-appearance.js @@ -763,9 +763,19 @@ function build() { ]); } + /* This tab is mounted in the stock System form, so LuCI's own Save & Apply footer sits under a + * page it does not save — asked on the forum, topic 251930. Above the first section, because + * the misreading happens before anyone scrolls to Defaults. A bare `.alert-message`: + * theme/35-alerts.css keeps the tinted variants for a STATUS and a flat panel for a note. */ + const note = E('div', { 'class': 'alert-message fs-ap-note' }, [ + E('p', {}, [ _('Changes apply at once and live in this browser.', 'footstrap') ]), + E('p', {}, [ _('To keep them on the router, use Save as default under Defaults — not Save & Apply at the foot of the page.', 'footstrap') ]) + ]); + /* Colours and Surfaces are one fold: the same job, split into two headings only because a * figure and the sheet it sits on are read differently */ const page = E('div', { 'class': 'fs-ap' }, [ + note, section(_('Interface', 'footstrap'), shell), foldable(_('Colours', 'footstrap'), colours.concat([ E('div', { 'class': 'fs-ap-head fs-ap-sub' }, [ E('h4', {}, [ _('Surfaces', 'footstrap') ]) ]) ], surfaces), diff --git a/luci-theme-footstrap/po/es/footstrap.po b/luci-theme-footstrap/po/es/footstrap.po index f212e1856..29d6a50f7 100644 --- a/luci-theme-footstrap/po/es/footstrap.po +++ b/luci-theme-footstrap/po/es/footstrap.po @@ -35,7 +35,7 @@ msgctxt "footstrap" msgid "Auto-collapse" msgstr "Colapso automático" -#: htdocs/luci-static/resources/fs-appearance.js:773 +#: htdocs/luci-static/resources/fs-appearance.js:783 msgctxt "footstrap" msgid "Background" msgstr "Fondo" @@ -55,6 +55,11 @@ msgctxt "footstrap" msgid "Cards" msgstr "Tarjetas" +#: htdocs/luci-static/resources/fs-appearance.js:771 +msgctxt "footstrap" +msgid "Changes apply at once and live in this browser." +msgstr "Los cambios se aplican al instante y viven en este navegador." + #: htdocs/luci-static/resources/fs-appearance.js:454 msgctxt "footstrap" msgid "Choose SVG" @@ -70,13 +75,13 @@ msgctxt "footstrap" msgid "Clearly visible %s" msgstr "Bien visible %s" -#: htdocs/luci-static/resources/fs-chrome.js:430 +#: htdocs/luci-static/resources/fs-chrome.js:447 #: ucode/template/themes/footstrap/header.ut:138 msgid "Collapse menu" msgstr "Contraer menú" #: htdocs/luci-static/resources/fs-appearance.js:465 -#: htdocs/luci-static/resources/fs-appearance.js:770 +#: htdocs/luci-static/resources/fs-appearance.js:780 msgctxt "footstrap" msgid "Colours" msgstr "Colores" @@ -123,7 +128,7 @@ msgctxt "footstrap" msgid "Dark" msgstr "Oscuro" -#: htdocs/luci-static/resources/fs-appearance.js:774 +#: htdocs/luci-static/resources/fs-appearance.js:784 msgctxt "footstrap" msgid "Defaults" msgstr "Predeterminados" @@ -143,7 +148,7 @@ msgctxt "footstrap" msgid "Easy to read %s" msgstr "Se lee bien %s" -#: htdocs/luci-static/resources/fs-chrome.js:430 +#: htdocs/luci-static/resources/fs-chrome.js:447 msgid "Expand menu" msgstr "Expandir menú" @@ -179,7 +184,7 @@ msgctxt "footstrap" msgid "Hard to read %s — large text only" msgstr "Se lee mal %s: solo texto grande" -#: htdocs/luci-static/resources/fs-appearance.js:769 +#: htdocs/luci-static/resources/fs-appearance.js:779 msgctxt "footstrap" msgid "Interface" msgstr "Interfaz" @@ -397,7 +402,7 @@ msgctxt "footstrap" msgid "Submenus" msgstr "Submenús" -#: htdocs/luci-static/resources/fs-appearance.js:771 +#: htdocs/luci-static/resources/fs-appearance.js:781 msgctxt "footstrap" msgid "Surfaces" msgstr "Superficies" @@ -410,7 +415,7 @@ msgstr "Sistema" msgid "System running in recovery (initramfs) mode." msgstr "El sistema se está ejecutando en modo de recuperación (initramfs)." -#: htdocs/luci-static/resources/fs-select.js:647 +#: htdocs/luci-static/resources/fs-select.js:662 msgid "Table" msgstr "Tabla" @@ -492,6 +497,15 @@ msgctxt "footstrap" msgid "Tint strength" msgstr "Intensidad del tinte" +#: htdocs/luci-static/resources/fs-appearance.js:772 +msgctxt "footstrap" +msgid "" +"To keep them on the router, use Save as default under Defaults — not Save & " +"Apply at the foot of the page." +msgstr "" +"Para guardarlos en el router, usa «Guardar como predeterminado» en " +"Predeterminados, no «Guardar y aplicar» al pie de la página." + #: htdocs/luci-static/resources/fs-appearance.js:190 msgctxt "footstrap" msgid "Too faint to read %s" @@ -558,6 +572,25 @@ msgid "" "the uploaded file could not be removed either; it is still on the router." msgstr "tampoco se pudo eliminar el archivo subido; sigue en el router." +#~ msgctxt "footstrap" +#~ msgid "" +#~ "Everything here applies the moment you change it and is remembered in " +#~ "this browser only — the Save & Apply button at the foot of the page " +#~ "belongs to the System form and does not store it." +#~ msgstr "" +#~ "Todo lo de aquí se aplica en el momento en que lo cambias y se recuerda " +#~ "solo en este navegador: el botón «Guardar y aplicar» del pie de la página " +#~ "pertenece al formulario del Sistema y no lo guarda." + +#~ msgctxt "footstrap" +#~ msgid "" +#~ "To make the current look the router's default for every browser, use Save " +#~ "as default under Defaults below." +#~ msgstr "" +#~ "Para que el aspecto actual sea el predeterminado del router para todos " +#~ "los navegadores, usa «Guardar como predeterminado» en Predeterminados más " +#~ "abajo." + #~ msgid "Loading view…" #~ msgstr "Cargando vista…" diff --git a/luci-theme-footstrap/po/ru/footstrap.po b/luci-theme-footstrap/po/ru/footstrap.po index ddd91cec1..7f983a712 100644 --- a/luci-theme-footstrap/po/ru/footstrap.po +++ b/luci-theme-footstrap/po/ru/footstrap.po @@ -31,7 +31,7 @@ msgctxt "footstrap" msgid "Auto-collapse" msgstr "Сворачивать" -#: htdocs/luci-static/resources/fs-appearance.js:773 +#: htdocs/luci-static/resources/fs-appearance.js:783 msgctxt "footstrap" msgid "Background" msgstr "Фон" @@ -51,6 +51,11 @@ msgctxt "footstrap" msgid "Cards" msgstr "Карточки" +#: htdocs/luci-static/resources/fs-appearance.js:771 +msgctxt "footstrap" +msgid "Changes apply at once and live in this browser." +msgstr "Изменения применяются сразу и живут в этом браузере." + #: htdocs/luci-static/resources/fs-appearance.js:454 msgctxt "footstrap" msgid "Choose SVG" @@ -66,13 +71,13 @@ msgctxt "footstrap" msgid "Clearly visible %s" msgstr "Хорошо видна %s" -#: htdocs/luci-static/resources/fs-chrome.js:430 +#: htdocs/luci-static/resources/fs-chrome.js:447 #: ucode/template/themes/footstrap/header.ut:138 msgid "Collapse menu" msgstr "Свернуть меню" #: htdocs/luci-static/resources/fs-appearance.js:465 -#: htdocs/luci-static/resources/fs-appearance.js:770 +#: htdocs/luci-static/resources/fs-appearance.js:780 msgctxt "footstrap" msgid "Colours" msgstr "Цвета" @@ -117,7 +122,7 @@ msgctxt "footstrap" msgid "Dark" msgstr "Тёмная" -#: htdocs/luci-static/resources/fs-appearance.js:774 +#: htdocs/luci-static/resources/fs-appearance.js:784 msgctxt "footstrap" msgid "Defaults" msgstr "Умолчания" @@ -137,7 +142,7 @@ msgctxt "footstrap" msgid "Easy to read %s" msgstr "Хорошо читается %s" -#: htdocs/luci-static/resources/fs-chrome.js:430 +#: htdocs/luci-static/resources/fs-chrome.js:447 msgid "Expand menu" msgstr "Развернуть меню" @@ -173,7 +178,7 @@ msgctxt "footstrap" msgid "Hard to read %s — large text only" msgstr "Плохо читается %s — только крупный текст" -#: htdocs/luci-static/resources/fs-appearance.js:769 +#: htdocs/luci-static/resources/fs-appearance.js:779 msgctxt "footstrap" msgid "Interface" msgstr "Интерфейс" @@ -390,7 +395,7 @@ msgctxt "footstrap" msgid "Submenus" msgstr "Подменю" -#: htdocs/luci-static/resources/fs-appearance.js:771 +#: htdocs/luci-static/resources/fs-appearance.js:781 msgctxt "footstrap" msgid "Surfaces" msgstr "Поверхности" @@ -403,7 +408,7 @@ msgstr "Система" msgid "System running in recovery (initramfs) mode." msgstr "Система работает в режиме восстановления (initramfs)." -#: htdocs/luci-static/resources/fs-select.js:647 +#: htdocs/luci-static/resources/fs-select.js:662 msgid "Table" msgstr "Таблица" @@ -485,6 +490,15 @@ msgctxt "footstrap" msgid "Tint strength" msgstr "Насыщенность оттенка" +#: htdocs/luci-static/resources/fs-appearance.js:772 +msgctxt "footstrap" +msgid "" +"To keep them on the router, use Save as default under Defaults — not Save & " +"Apply at the foot of the page." +msgstr "" +"Чтобы сохранить их на роутере, нажмите «Сохранить по умолчанию» в разделе «По " +"умолчанию», а не «Сохранить и применить» внизу страницы." + #: htdocs/luci-static/resources/fs-appearance.js:190 msgctxt "footstrap" msgid "Too faint to read %s" @@ -551,6 +565,24 @@ msgid "" "the uploaded file could not be removed either; it is still on the router." msgstr "загруженный файл тоже не удалось удалить — он остался на роутере." +#~ msgctxt "footstrap" +#~ msgid "" +#~ "Everything here applies the moment you change it and is remembered in " +#~ "this browser only — the Save & Apply button at the foot of the page " +#~ "belongs to the System form and does not store it." +#~ msgstr "" +#~ "Всё на этой странице применяется в момент изменения и запоминается только " +#~ "в этом браузере — кнопка «Сохранить и применить» внизу страницы " +#~ "принадлежит форме «Система» и настройки внешнего вида не сохраняет." + +#~ msgctxt "footstrap" +#~ msgid "" +#~ "To make the current look the router's default for every browser, use Save " +#~ "as default under Defaults below." +#~ msgstr "" +#~ "Чтобы текущий вид стал умолчанием роутера для всех браузеров, нажмите " +#~ "«Сохранить по умолчанию» в разделе «По умолчанию» ниже." + #~ msgid "Loading view…" #~ msgstr "Загрузка представления…" diff --git a/luci-theme-footstrap/po/templates/footstrap.pot b/luci-theme-footstrap/po/templates/footstrap.pot index d93f441b1..faa73eaeb 100644 --- a/luci-theme-footstrap/po/templates/footstrap.pot +++ b/luci-theme-footstrap/po/templates/footstrap.pot @@ -25,7 +25,7 @@ msgctxt "footstrap" msgid "Auto-collapse" msgstr "" -#: htdocs/luci-static/resources/fs-appearance.js:773 +#: htdocs/luci-static/resources/fs-appearance.js:783 msgctxt "footstrap" msgid "Background" msgstr "" @@ -45,6 +45,11 @@ msgctxt "footstrap" msgid "Cards" msgstr "" +#: htdocs/luci-static/resources/fs-appearance.js:771 +msgctxt "footstrap" +msgid "Changes apply at once and live in this browser." +msgstr "" + #: htdocs/luci-static/resources/fs-appearance.js:454 msgctxt "footstrap" msgid "Choose SVG" @@ -60,13 +65,13 @@ msgctxt "footstrap" msgid "Clearly visible %s" msgstr "" -#: htdocs/luci-static/resources/fs-chrome.js:430 +#: htdocs/luci-static/resources/fs-chrome.js:447 #: ucode/template/themes/footstrap/header.ut:138 msgid "Collapse menu" msgstr "" #: htdocs/luci-static/resources/fs-appearance.js:465 -#: htdocs/luci-static/resources/fs-appearance.js:770 +#: htdocs/luci-static/resources/fs-appearance.js:780 msgctxt "footstrap" msgid "Colours" msgstr "" @@ -111,7 +116,7 @@ msgctxt "footstrap" msgid "Dark" msgstr "" -#: htdocs/luci-static/resources/fs-appearance.js:774 +#: htdocs/luci-static/resources/fs-appearance.js:784 msgctxt "footstrap" msgid "Defaults" msgstr "" @@ -131,7 +136,7 @@ msgctxt "footstrap" msgid "Easy to read %s" msgstr "" -#: htdocs/luci-static/resources/fs-chrome.js:430 +#: htdocs/luci-static/resources/fs-chrome.js:447 msgid "Expand menu" msgstr "" @@ -165,7 +170,7 @@ msgctxt "footstrap" msgid "Hard to read %s — large text only" msgstr "" -#: htdocs/luci-static/resources/fs-appearance.js:769 +#: htdocs/luci-static/resources/fs-appearance.js:779 msgctxt "footstrap" msgid "Interface" msgstr "" @@ -380,7 +385,7 @@ msgctxt "footstrap" msgid "Submenus" msgstr "" -#: htdocs/luci-static/resources/fs-appearance.js:771 +#: htdocs/luci-static/resources/fs-appearance.js:781 msgctxt "footstrap" msgid "Surfaces" msgstr "" @@ -393,7 +398,7 @@ msgstr "" msgid "System running in recovery (initramfs) mode." msgstr "" -#: htdocs/luci-static/resources/fs-select.js:647 +#: htdocs/luci-static/resources/fs-select.js:662 msgid "Table" msgstr "" @@ -469,6 +474,13 @@ msgctxt "footstrap" msgid "Tint strength" msgstr "" +#: htdocs/luci-static/resources/fs-appearance.js:772 +msgctxt "footstrap" +msgid "" +"To keep them on the router, use Save as default under Defaults — not Save & " +"Apply at the foot of the page." +msgstr "" + #: htdocs/luci-static/resources/fs-appearance.js:190 msgctxt "footstrap" msgid "Too faint to read %s" diff --git a/luci-theme-footstrap/styles/03-palettes.css b/luci-theme-footstrap/styles/03-palettes.css index eee9f559a..a5fe68bb7 100644 --- a/luci-theme-footstrap/styles/03-palettes.css +++ b/luci-theme-footstrap/styles/03-palettes.css @@ -18,8 +18,8 @@ * pre-paint switch in partials/head.ut (a router default outside the whitelist becomes * '' and the page paints in the default palette), the label map in fs-appearance.js (an * unnamed palette is missing from the picker, not broken), and matrix() in - * tools/lib/gallery.mjs — a palette absent there is one export-tier.mjs and - * a11y-gallery.mjs never measure, so it ships ungated. + * tools/lib/gallery.mjs — a palette absent there is one export-tier.mjs, + * a11y-gallery.mjs and placeholder-ink.mjs never measure, so it ships ungated. * Nothing else: layout, components and the --*-color-* export bridge key off these tokens, and * every tint, shadow and hairline is a color-mix() over them. * @@ -99,6 +99,26 @@ --fs-good: var(--fs-good-base); --fs-warn: var(--fs-warn-base); --fs-danger: var(--fs-danger-base); + /* The ink of a value that is NOT there — the `placeholder` attribute and the dropdown's + * `li[placeholder]` row. LuCI writes an option's DEFAULT there (`form.Value.placeholder`: + * 128 for the log buffer, 514 for the log port), so an ink that reads as body text tells + * the reader a field is set when it is empty — reported against 0.14.8, forum topic 251930 + * posts 82-83. --fs-dim was that ink and is not far enough away: on footstrap light's + * --fs-panel2 it measures 11.12:1 against the text's 14.84:1, which is two blacks. + * + * Derived, not hand-listed per palette, so it follows a palette that has not been written + * yet. The formula is spelt once and the STRENGTH is a token of its own, because it is the + * only part that varies — per mode here, and again under prefers-contrast:more + * (theme/95-a11y-media.css); restating the whole mix in each of those four places cost 79 B + * of shipped sheet and gave three more copies to keep in step. That is also why it lives + * here rather than in 02-tokens.css's ladder — the same reason --fs-accent-soft does. + * + * Light lands at 3.99-4.48:1 across the four palettes, 43-44% of the way from the value's + * ink to the field: under AA on purpose, see the dark half below for the whole argument. + * oklch because the step is a LIGHTNESS one — srgb at the same 55% stops at 3.58:1. Held by + * `npm run placeholder`. */ + --fs-placeholder-mix: 55%; + --fs-placeholder: color-mix(in oklch, var(--fs-text) var(--fs-placeholder-mix), var(--fs-panel2)); /* The hues the user picked, in degrees. Declared here and not only inline by * head.ut/fs-prefs.js, so the stylesheet stands on its own: a var() with no definition * anywhere is invalid at computed-value time and takes the whole declaration down. */ @@ -158,6 +178,18 @@ :root[data-darkmode="true"] { --fs-tint-c: calc((.011 + .016 * max(0, cos((var(--fs-tint-h) - 258) * 1deg)) - .004 * max(0, cos((var(--fs-tint-h) - 55) * 1deg))) * var(--fs-tint-strength)); + /* 64%, against the 55% above, and the difference is what a dark palette can afford: its ink + * starts at 6.45:1 on --fs-panel2 where the light one has 14.84:1, so the same percentage + * would buy a hint nobody can read. It lands at 3.43-6.05:1, 33-35% of the range. + * + * BOTH modes ship below AA, and that is the decision this token exists to record: a hint + * mistaken for a value makes a reader configure the wrong thing, while a hint at 3.43:1 + * makes them look twice. The AA-clearing mixes (62/80%) were measured first and moved only + * 37% and 20% of the range — the same fault, quieter. 3:1 (SC 1.4.11, and SC 1.4.3's + * large-text floor) is the line NOT crossed, worst 3.43:1; prefers-contrast:more buys the + * AA ink back in both modes (theme/95-a11y-media.css); and `placeholder-ink` holds all + * three states, axe-core being excluded from this row for the same reason. */ + --fs-placeholder-mix: 64%; } :root[data-tint="hue"] { --fs-bg: oklch(from var(--fs-bg-base) l var(--fs-tint-c) var(--fs-tint-h)); } diff --git a/luci-theme-footstrap/styles/04-nocolormix.css b/luci-theme-footstrap/styles/04-nocolormix.css index ff5fb26c2..a26617459 100644 --- a/luci-theme-footstrap/styles/04-nocolormix.css +++ b/luci-theme-footstrap/styles/04-nocolormix.css @@ -9,7 +9,7 @@ * — `background: var(--fs-good-soft)` becomes invalid at computed-value time and computes to * `unset`, which is `initial` for a non-inherited property. IACVT does not fall back to an earlier * declaration in the same block, so the two-declaration trick that works for `background: - * color-mix(…)` written literally does nothing for a token. 38 tokens are affected; without this + * color-mix(…)` written literally does nothing for a token. 36 tokens are affected; without this * block a browser below the floor paints borders in currentcolor and loses every soft surface. * * color-mix() lands in Chrome 111, Firefox 113 and Safari 16.2 (all 2022-2023). See docs/css.md @@ -62,6 +62,12 @@ * take the fixed dialog scrim. Losing it entirely would leave login text over a photo. */ --fs-photo-scrim: var(--fs-scrim); + /* placeholder ink: the quietest ink the palette states outright. Below the floor the + * hint is back to reading like a value, which is the pre-0.14.9 look and still the + * safer degradation — an unresolvable token takes `color` down to `unset`, and an + * inherited near-black placeholder over a light field beats an unstyled one. */ + --fs-placeholder: var(--fs-faint); + /* export tier — third-party apps read these, so they must resolve to something. * -medium keeps the hue, -low degrades to the dim text colour it was mixed toward. */ --border-color-high: var(--fs-border); diff --git a/luci-theme-footstrap/styles/base/30-forms.css b/luci-theme-footstrap/styles/base/30-forms.css index 574535548..dd169c397 100644 --- a/luci-theme-footstrap/styles/base/30-forms.css +++ b/luci-theme-footstrap/styles/base/30-forms.css @@ -173,8 +173,10 @@ /* Checkbox/radio drawing: theme/60-inputs.css — absorbed whole (it undoes the generic input * box, which lives there now). */ + /* --fs-placeholder, not --fs-dim: a placeholder carries the option's DEFAULT and must not read + * as a value the reader typed (03-palettes.css has the numbers). */ ::placeholder { - color: var(--fs-dim); + color: var(--fs-placeholder); } /* Transitions and the focus/hover ring are the theme's one ring token (--fs-focus-ring / diff --git a/luci-theme-footstrap/styles/pages/80-appearance.css b/luci-theme-footstrap/styles/pages/80-appearance.css index e7e85a486..ed7db1c50 100644 --- a/luci-theme-footstrap/styles/pages/80-appearance.css +++ b/luci-theme-footstrap/styles/pages/80-appearance.css @@ -12,6 +12,11 @@ * the only page that draws it: an axis control is not chrome. */ .fs-ap { display: flex; flex-direction: column; gap: var(--fs-space-5); } + /* The page note (fs-appearance.js). Only the outer margins: `.alert-message p` carries + * --fs-space-1 top and bottom, which at the box's own edges adds to the panel's padding and + * makes a two-sentence note look loose against every other alert on the theme. */ + .fs-ap-note p:first-child { margin-top: 0; } + .fs-ap-note p:last-child { margin-bottom: 0; } /* Grouping headings INSIDE the tab pane, not cards: the pane is already inside the stock * .cbi-section card, and a second border around each group is a box in a box. A hairline above * each group does the same job — except for the first, which sits under the tab strip. */ diff --git a/luci-theme-footstrap/styles/theme/65-dropdown.css b/luci-theme-footstrap/styles/theme/65-dropdown.css index 8e2f829df..f01afd431 100644 --- a/luci-theme-footstrap/styles/theme/65-dropdown.css +++ b/luci-theme-footstrap/styles/theme/65-dropdown.css @@ -98,8 +98,8 @@ .cbi-dropdown.cbi-button > .open { margin-inline-start: .5em; } - /* display only: the placeholder's ink is the theme's own `li[placeholder]` --fs-faint below - * (base's --fs-dim had already lost to it by layer — moving it would recolour the row) */ + /* display only: the placeholder's ink is the theme's own `li[placeholder]` --fs-placeholder + * below — the same token base/30-forms.css gives the attribute */ .cbi-dropdown:not(.btn):not(.cbi-button) > ul > li[placeholder] { display: none; } @@ -246,7 +246,16 @@ .cbi-dropdown > ul > li > form, .cbi-dropdown > ul > li label { font-family: inherit; } .cbi-dropdown:not(.btn):not(.cbi-button) > ul > li[display]:not([display="0"]) { border-inline-start: 0; } - .cbi-dropdown > ul > li[placeholder] { color: var(--fs-faint); } + /* The same ink the `placeholder` attribute takes in base/30-forms.css — "-- Please choose --" is + * the absence of a value, not one. + * + * It repeats the row rule's two selectors instead of writing `> ul > li[placeholder]` once, + * because that shorter form (0,2,2) LOSES to the row's own `color: var(--fs-text)` (0,3,2) and + * the placeholder row rendered in the value's ink on every form dropdown — dead from the day it + * was written, and only visible once `placeholder-ink` measured the row. Each selector here + * out-specifies its counterpart above: (0,4,2) over (0,3,2), (0,3,2) over (0,2,2). */ + .cbi-dropdown:not(.btn):not(.cbi-button) > ul > li[placeholder], + .cbi-dropdown > ul.dropdown > li[placeholder] { color: var(--fs-placeholder); } /* the multiselect's inline filter/create inputs — moved from base with the generic `input` * box in theme/60-inputs.css: in base these beat it in-layer, left behind they would lose * to it by layer and render as free-standing 210px fields inside the open list */ diff --git a/luci-theme-footstrap/styles/theme/75-search.css b/luci-theme-footstrap/styles/theme/75-search.css index 311ff7597..7946fb02a 100644 --- a/luci-theme-footstrap/styles/theme/75-search.css +++ b/luci-theme-footstrap/styles/theme/75-search.css @@ -55,7 +55,10 @@ font-family: inherit; font-size: var(--fs-type-lg); font-weight: var(--fs-weight); line-height: 1.4; } .fs-search-row .fs-search-input:focus { outline: none; box-shadow: none; } - .fs-search-row .fs-search-input::placeholder { color: var(--fs-faint); font-weight: var(--fs-weight); } + /* one placeholder ink for the whole theme (03-palettes.css) — this row is not measured by + * `placeholder-ink`, the gallery having no search dialog, and must not drift from the fields + * that are */ + .fs-search-row .fs-search-input::placeholder { color: var(--fs-placeholder); font-weight: var(--fs-weight); } .fs-search-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: var(--fs-space-1-5); } diff --git a/luci-theme-footstrap/styles/theme/95-a11y-media.css b/luci-theme-footstrap/styles/theme/95-a11y-media.css index 8a3e2d165..98a31ce1a 100644 --- a/luci-theme-footstrap/styles/theme/95-a11y-media.css +++ b/luci-theme-footstrap/styles/theme/95-a11y-media.css @@ -52,6 +52,13 @@ * measures rather than takes on trust: below 80 the fainter ink drops under AA on footstrap * dark's --fs-panel2 (4.51:1 at 80), above 82 the high-to-low ramp falls under the 0.10 * spread the tier promises (0.098 at 84); 82 clears both, at 4.68:1 and 0.110. + * - --fs-placeholder, in BOTH modes. It is the one token the theme ships deliberately under AA + * (3.99-4.48:1 light, 3.43-6.05:1 dark): a hint has to move far enough not to read as a + * typed value, and a dark palette has only 6.45:1 of ink to spend. A reader who asked the OS + * for more contrast has said which of the two they want, so the mixes go back to the + * AA-clearing 62% and 80% — 4.98:1 and 4.61:1, at 37% and 20% of the ink-to-field range + * instead of 44% and 34%. Only --fs-placeholder-mix moves: the mix itself is spelt once, in + * 03-palettes.css. `placeholder-ink` measures this pass as well. * - the focus ring: --fs-focus-ring is a tint of the accent (--fs-accent-soft, 10% light and * 15% dark), so at "more contrast" it carries the accent at 60% instead. Its sibling * --fs-focus-ring-solo is already the solid accent and needs no restatement here. */ @@ -65,7 +72,12 @@ --fs-good-line: var(--fs-good); --fs-good-line-hi: var(--fs-good); --fs-warn-line: var(--fs-warn); --fs-warn-line-hi: var(--fs-warn); --fs-danger-line: var(--fs-danger); --fs-danger-line-hi: var(--fs-danger); + /* the placeholder is the one token shipped under AA (see the note above); this reader + * asked for contrast, so both modes buy the AA ink back, at the percentages that clear + * it. Light here, dark in the block below — per mode exactly as in 03-palettes.css. */ + --fs-placeholder-mix: 62%; } + :root[data-darkmode="true"] { --fs-placeholder-mix: 80%; } } /* forced-colors (Windows High Contrast) — the OS replaces every colour the theme picked, and diff --git a/wwand/Makefile b/wwand/Makefile index 9cabd4a45..86deed4a1 100644 --- a/wwand/Makefile +++ b/wwand/Makefile @@ -43,12 +43,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=wwand -PKG_RELEASE:=18 +PKG_RELEASE:=19 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/ddimension/wwand.git PKG_SOURCE_VERSION:=fb4a8ff34967a5ae1d6e882dcd78b8339f5f99d1 -PKG_SOURCE_DATE:=2026-08-31 +PKG_SOURCE_DATE:=2026-09-02 PKG_MIRROR_HASH:=skip PKG_LICENSE:=GPL-2.0-only