🎉 Sync 2026-10-01 14:45:51

This commit is contained in:
github-actions[bot] committed 2026-10-01 14:45:51 +08:00
1 parent 50a5f3fd55
commit 93fb610fbd
124 files changed
+21594 -1

No files matched your search

+1 -1
View File
@@ -1 +1 @@
snapshot
both
@@ -0,0 +1 @@
26.273.20498~1fcad1e
+24
View File
@@ -0,0 +1,24 @@
# Internal use
docs/
/resources/
# Hidden dotfiles/folders
.*
!.gitignore
!.gitkeep
# Editor files
*.swp
*.swo
*~
# Signing keys (secret key is in GitHub Secrets, NEVER commit)
/keys/
# Build output
dist/
# Node modules (for LESS compilation)
node_modules/
package-lock.json
+674
View File
@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
+19
View File
@@ -0,0 +1,19 @@
#
# Copyright (C) 2024-2026 luci-theme-glass contributors
#
# This is free software, licensed under the GNU General Public License v3.0.
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Glass - Apple-inspired glassmorphism theme for LuCI
LUCI_DEPENDS:=
PKG_VERSION:=$(shell cat $(CURDIR)/ucode/template/themes/glass/version | tr -d '[:space:]')
PKG_RELEASE:=1
# Disable CSS minification (backdrop-filter can break with csstidy)
CONFIG_LUCI_CSSTIDY:=
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature
+236
View File
@@ -0,0 +1,236 @@
# luci-theme-glass
A glassmorphism theme for OpenWrt LuCI, inspired by Apple's visionOS and macOS. Frosted-glass panels, backdrop blur, translucent buttons, and inset highlights across the entire UI.
**[Live Demo](https://rchen14b.github.io/luci-theme-glass/)** | **[Download](https://github.com/rchen14b/luci-theme-glass/releases/latest)**
![License](https://img.shields.io/badge/license-GPL--3.0%20%2F%20Commercial-blue.svg)
![OpenWrt](https://img.shields.io/badge/OpenWrt-23.05%2B-brightgreen.svg)
![Version](https://img.shields.io/badge/version-1.1.6-orange.svg)
[![Buy Me A Coffee](https://img.shields.io/badge/Buy%20Me%20A%20Coffee-support-yellow?style=flat&logo=buy-me-a-coffee)](https://buymeacoffee.com/rchen14b)
## Screenshots
### Login
![Login](screenshots/Login_page_light.png)
### Overview (Light)
![Overview Light](screenshots/Overview_page_light.png)
### Overview (Dark)
![Overview Dark](screenshots/Overview_page_dark.png)
### Software
![Software](screenshots/Software_page_light.png)
### Traffic Graph
![Traffic](screenshots/Traffic_graph_light.png)
## Features
### Design
- **Glassmorphism everywhere** — `backdrop-filter: blur() saturate()` with multi-stop gradients, translucent backgrounds, 0.5px glass borders, and inset glow highlights on all panels
- **Glass buttons** — Neutral buttons are translucent glass, primary buttons are blue-tinted, danger buttons are red-tinted. No solid-color buttons
- **Frosted sidebar** — Fixed sidebar with 30px blur and inset light diffusion
- **Glass header** — Top nav bar with glass pill badges for page title and status indicators
- **Live status indicators** — CPU load, RAM %, uptime, and WAN throughput in the header bar. Auto-detects WAN interface, resolves bridges, handles DSA hardware offloading. MikroTik-style speed formatting. Color-coded levels and detailed tooltips
- **Glass login card** — Frosted login page with translucent inputs
### Theming
- **Auto / Light / Dark mode** — Toggle in the header bar cycles through Auto (follows OS `prefers-color-scheme`), Light, and Dark. Works on every page including login. Saved to `localStorage` so it persists across sessions
- **Dark mode glass** — Lower-opacity gradients (`rgba(255,255,255,0.05-0.08)`) with adjusted shadows
- **Server-side default** — Set default mode via UCI config (`option mode 'dark'`, `'light'`, or `'normal'` for auto). The client-side toggle overrides this per browser
- **Accent color config** — Primary color, blur radius, and glass transparency are adjustable via UCI
- **Custom wallpapers** — Drop an image or video into the background folder. It shows through all glass panels
### Layout
- **Responsive** — Sidebar collapses to a slide-out drawer on mobile with hamburger toggle
- **Sub-navigation bar** — CBI tab menus get moved into a secondary glass bar below the header
- **Sticky header** — Fixed header with smooth transitions
### Compatibility
- **Full LuCI coverage** — Styles all CBI components: sections, tables, forms, dropdowns, checkboxes, textareas, progress bars, tooltips, modals, tab menus
- **Page-specific fixes** — Overrides inline CSS from LuCI view JS (package manager layout, port status grid, network status cards)
- **OpenWrt 23.05+** — Uses ucode `.ut` templates
- **No dependencies** — Pure CSS, no JS frameworks
## Installation
### From package repository (auto-update, signed)
Add the repository to get updates via the package manager. Both opkg and apk feeds are signed.
**OpenWrt 24.10 and earlier (opkg):**
```sh
# First install: fetch signing public key (one-time)
wget -O /etc/opkg/keys/ef97c468af77cea1 \
https://raw.githubusercontent.com/rchen14b/luci-theme-glass/main/root/etc/opkg/keys/ef97c468af77cea1
# Add feed and install
echo "src/gz glass https://rchen14b.github.io/luci-theme-glass/packages" >> /etc/opkg/customfeeds.conf
opkg update
opkg install luci-theme-glass
```
**OpenWrt 25.12+ (apk):**
```sh
# First install: fetch signing public key (one-time)
wget -O /etc/apk/keys/glass-apk.rsa.pub \
https://raw.githubusercontent.com/rchen14b/luci-theme-glass/main/root/etc/apk/keys/glass-apk.rsa.pub
# Add feed and install
echo "https://rchen14b.github.io/luci-theme-glass/apk/packages.adb" >> /etc/apk/repositories.d/customfeeds.list
apk update
apk add luci-theme-glass
```
After the first install, the public key persists on the router — future updates via `opkg upgrade` / `apk upgrade` just work. The LuCI web-gui "Update lists" button also works without warnings.
### From release (manual)
Download the latest package from [Releases](../../releases):
- **OpenWrt 25.12+** (apk): `apk add --allow-untrusted luci-theme-glass-*.apk`
- **OpenWrt 24.10 and earlier** (opkg): `opkg install luci-theme-glass_*.ipk`
### From source
```sh
# Add to your OpenWrt build tree
cd /path/to/openwrt
git clone https://github.com/rchen14b/luci-theme-glass.git package/luci-theme-glass
# Build
make package/luci-theme-glass/compile V=s
```
### Manual install (dev)
```sh
# Copy theme files to router
scp -r htdocs/luci-static/glass/ root@router:/www/luci-static/glass/
scp htdocs/luci-static/resources/menu-glass.js root@router:/www/luci-static/resources/
scp -r ucode/template/themes/glass/ root@router:/usr/share/ucode/luci/template/themes/glass/
# Register and activate
ssh root@router "uci set luci.themes.Glass=/luci-static/glass && \
uci set luci.main.mediaurlbase=/luci-static/glass && \
uci commit luci"
```
## Configuration
After installation, select **Glass** in **System > System > Language and Style**.
### Theme config
Create `/etc/config/glass` on the router:
```
config global
option mode 'normal'
option primary '#007AFF'
option dark_primary '#0A84FF'
option blur '20'
option transparency '0.72'
option blur_dark '25'
option transparency_dark '0.30'
```
| Option | Default | Description |
|--------|---------|-------------|
| `mode` | `normal` | `normal` (auto), `dark`, or `light` |
| `primary` | `#007AFF` | Accent color (light mode) |
| `dark_primary` | `#0A84FF` | Accent color (dark mode) |
| `blur` | `20` | Backdrop blur in px (light mode) |
| `transparency` | `0.72` | Glass panel opacity 0-1 (light mode) |
| `blur_dark` | `25` | Backdrop blur in px (dark mode) |
| `transparency_dark` | `0.30` | Glass panel opacity 0-1 (dark mode) |
### Custom wallpapers
Place a file named `bg.*` in `/www/luci-static/glass/background/` on the router.
Supported: `.jpg`, `.jpeg`, `.png`, `.gif`, `.webp`, `.mp4`, `.webm`
The background shows through all glass panels.
## Development
### Prerequisites
- Node.js with `lessc`: `npm install -g less`
### Building CSS
```sh
lessc less/cascade.less htdocs/luci-static/glass/css/cascade.css
lessc less/dark.less htdocs/luci-static/glass/css/dark.css
```
### Project structure
```
luci-theme-glass/
├── Makefile # OpenWrt package build
├── htdocs/luci-static/
│ ├── glass/
│ │ ├── css/ # Compiled CSS
│ │ ├── img/ # Logo and icons
│ │ └── background/ # User wallpapers (bg.jpg, etc.)
│ └── resources/
│ ├── menu-glass.js # Client-side menu renderer
│ └── status-glass.js # Header status indicators (CPU, RAM, net, uptime)
├── less/ # LESS source
│ ├── cascade.less # Master import file
│ ├── variables.less # Design tokens (CSS custom properties)
│ ├── normalize.less # CSS reset
│ ├── glass.less # Glassmorphism mixins
│ ├── layout.less # Sidebar, header, footer, content
│ ├── components.less # CBI forms, tables, buttons, alerts
│ ├── sysauth.less # Login page
│ ├── page-fix.less # LuCI page-specific overrides
│ ├── dark.less # Dark mode overrides
│ └── responsive.less # Mobile breakpoints
├── ucode/template/themes/glass/ # Server-side ucode templates
│ ├── header.ut # HTML head + sidebar + header
│ ├── header_login.ut # Login page variant
│ ├── footer.ut # Footer + scripts
│ ├── footer_login.ut # Login footer variant
│ └── sysauth.ut # Login page
├── root/ # Files installed to device root
│ ├── etc/uci-defaults/ # First-boot theme registration
│ └── usr/share/rpcd/acl.d/ # ACL permissions
└── screenshots/
```
### Design system
Design tokens live in `variables.less`. Glass effects use three LESS mixins:
| Mixin | Use | Blur | Opacity |
|-------|-----|------|---------|
| `.glass-effect()` | Panels, cards | `var(--glass-blur)` | `var(--glass-bg)` |
| `.glass-frosted()` | Sidebar, login card | 30px | Higher |
| `.glass-subtle()` | Secondary elements | Lower | Minimal |
### Version bump checklist
1. `Makefile` — `PKG_VERSION`
2. `README.md` — version badge
3. `ucode/template/themes/glass/sysauth.ut` — login version text
4. `ucode/template/themes/glass/header.ut` — sidebar version text
5. `ucode/template/themes/glass/footer.ut` — footer version text
## Credits
- Architecture based on [luci-theme-argon](https://github.com/jerrykuku/luci-theme-argon)
- Glass effects from [glass-ui](https://github.com/crenspire/glass-ui)
- Design language from Apple visionOS / macOS
## License
Dual-licensed:
- **Open Source**: [GPL-3.0](LICENSE) — free for personal, educational, and open-source use. Derivatives must also be GPL-3.0.
- **Commercial**: Proprietary/closed-source use requires a separate license. Contact the author.
+151
View File
@@ -0,0 +1,151 @@
#!/bin/bash
set -e
PKG_NAME="luci-theme-glass"
PKG_VERSION="$(tr -d '[:space:]' < "$(dirname "$0")/ucode/template/themes/glass/version")"
PKG_RELEASE="1"
MAINTAINER="Ryan Chen <rchen14b@gmail.com>"
DESCRIPTION="Glass - Apple-inspired glassmorphism theme for LuCI"
HOMEPAGE="https://github.com/rchen14b/luci-theme-glass"
LICENSE="GPL-3.0"
DIST_DIR="dist"
WORK_DIR=$(mktemp -d)
# Use GNU tar (gtar) on macOS, fall back to tar
TAR=$(command -v gtar 2>/dev/null || echo tar)
trap "rm -rf $WORK_DIR" EXIT
echo "==> Preparing file tree..."
DATA_DIR="$WORK_DIR/data"
mkdir -p "$DATA_DIR/www/luci-static/glass"
mkdir -p "$DATA_DIR/www/luci-static/resources"
mkdir -p "$DATA_DIR/www/luci-static/resources/view/system"
mkdir -p "$DATA_DIR/usr/share/ucode/luci/template/themes/glass"
mkdir -p "$DATA_DIR/usr/share/rpcd/acl.d"
mkdir -p "$DATA_DIR/usr/share/luci/menu.d"
mkdir -p "$DATA_DIR/etc/uci-defaults"
mkdir -p "$DATA_DIR/etc/config"
mkdir -p "$DATA_DIR/etc/opkg/keys"
mkdir -p "$DATA_DIR/etc/apk/keys"
cp -r htdocs/luci-static/glass/css "$DATA_DIR/www/luci-static/glass/"
cp -r htdocs/luci-static/glass/img "$DATA_DIR/www/luci-static/glass/"
mkdir -p "$DATA_DIR/www/luci-static/glass/background"
cp htdocs/luci-static/resources/menu-glass.js "$DATA_DIR/www/luci-static/resources/"
cp htdocs/luci-static/resources/status-glass.js "$DATA_DIR/www/luci-static/resources/"
cp htdocs/luci-static/resources/view/system/glass.js "$DATA_DIR/www/luci-static/resources/view/system/"
cp ucode/template/themes/glass/*.ut "$DATA_DIR/usr/share/ucode/luci/template/themes/glass/"
cp ucode/template/themes/glass/version "$DATA_DIR/usr/share/ucode/luci/template/themes/glass/"
cp root/usr/share/rpcd/acl.d/luci-theme-glass.json "$DATA_DIR/usr/share/rpcd/acl.d/"
cp root/usr/share/luci/menu.d/luci-theme-glass.json "$DATA_DIR/usr/share/luci/menu.d/"
cp root/etc/uci-defaults/30_luci-theme-glass "$DATA_DIR/etc/uci-defaults/"
cp root/etc/config/glass "$DATA_DIR/etc/config/"
cp root/etc/opkg/keys/* "$DATA_DIR/etc/opkg/keys/" 2>/dev/null || true
cp root/etc/apk/keys/* "$DATA_DIR/etc/apk/keys/" 2>/dev/null || true
INSTALLED_SIZE=$(du -sk "$DATA_DIR" | cut -f1)
INSTALLED_BYTES=$((INSTALLED_SIZE * 1024))
BUILD_DATE=$(date +%s)
mkdir -p "$DIST_DIR"
# ============================================================
# Build IPK (opkg — OpenWrt 24.10 and earlier)
# ============================================================
echo "==> Building IPK..."
IPK_DIR="$WORK_DIR/ipk"
mkdir -p "$IPK_DIR/control"
cat > "$IPK_DIR/control/control" <<EOF
Package: $PKG_NAME
Version: ${PKG_VERSION}-${PKG_RELEASE}
Architecture: all
Maintainer: $MAINTAINER
Section: luci
Priority: optional
Installed-Size: $INSTALLED_SIZE
Description: $DESCRIPTION
Homepage: $HOMEPAGE
License: $LICENSE
EOF
cat > "$IPK_DIR/control/postinst" <<'SCRIPT'
#!/bin/sh
if [ "$PKG_UPGRADE" != 1 ]; then
uci get luci.themes.Glass >/dev/null 2>&1 || \
uci batch <<-EOF
set luci.themes.Glass=/luci-static/glass
set luci.main.mediaurlbase=/luci-static/glass
commit luci
EOF
fi
exit 0
SCRIPT
chmod 755 "$IPK_DIR/control/postinst"
echo "2.0" > "$IPK_DIR/debian-binary"
(cd "$DATA_DIR" && $TAR --format=gnu --numeric-owner --owner=0 --group=0 -cf - . | gzip -n > "$IPK_DIR/data.tar.gz")
(cd "$IPK_DIR/control" && $TAR --format=gnu --numeric-owner --owner=0 --group=0 -cf - . | gzip -n > "$IPK_DIR/control.tar.gz")
(cd "$IPK_DIR" && $TAR --format=gnu --numeric-owner --owner=0 --group=0 -cf - ./debian-binary ./data.tar.gz ./control.tar.gz | gzip -n > "$OLDPWD/$DIST_DIR/${PKG_NAME}_${PKG_VERSION}-${PKG_RELEASE}_all.ipk")
echo " -> $DIST_DIR/${PKG_NAME}_${PKG_VERSION}-${PKG_RELEASE}_all.ipk"
# ============================================================
# Build APK (apk-tools v3 ADB format — OpenWrt 25.12+)
# Requires Docker (uses Alpine container with apk mkpkg)
# ============================================================
echo "==> Building APK..."
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
APK_FILENAME="${PKG_NAME}-${PKG_VERSION}-r${PKG_RELEASE}.apk"
if ! command -v docker &>/dev/null; then
echo " [SKIP] Docker not found — APK build requires Docker with Alpine"
echo " IPK package was built successfully."
else
# Prepare post-install script for APK
APK_SCRIPT="$WORK_DIR/post-install.sh"
cat > "$APK_SCRIPT" <<'SCRIPT'
#!/bin/sh
uci get luci.themes.Glass >/dev/null 2>&1 || \
uci batch <<-EOF
set luci.themes.Glass=/luci-static/glass
set luci.main.mediaurlbase=/luci-static/glass
commit luci
EOF
exit 0
SCRIPT
chmod 755 "$APK_SCRIPT"
# Build using Alpine container with apk mkpkg
docker run --rm \
-v "$DATA_DIR:/pkg/files:ro" \
-v "$APK_SCRIPT:/pkg/post-install.sh:ro" \
-v "$SCRIPT_DIR/$DIST_DIR:/pkg/out" \
alpine:latest sh -c "
apk add --no-cache apk-tools-mkpkg >/dev/null 2>&1 || true
apk mkpkg \
--info 'name:$PKG_NAME' \
--info 'version:${PKG_VERSION}-r${PKG_RELEASE}' \
--info 'description:$DESCRIPTION' \
--info 'arch:noarch' \
--info 'license:$LICENSE' \
--info 'origin:$PKG_NAME' \
--info 'url:$HOMEPAGE' \
--info 'maintainer:$MAINTAINER' \
--script 'post-install:/pkg/post-install.sh' \
--files /pkg/files \
--output /pkg/out/$APK_FILENAME
" 2>&1
echo " -> $DIST_DIR/$APK_FILENAME"
fi
echo ""
echo "==> Done! Packages in $DIST_DIR/"
ls -lh "$DIST_DIR/"
Whitespace-only changes.
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,339 @@
/* ==========================================================================
Dark Mode — luci-theme-glass
Compiled separately and injected by header.ut when dark mode is active.
========================================================================== */
:root {
/* ---- Colors — Dark mode ---- */
--color-primary: #0A84FF;
--color-primary-hover: #409cff;
--color-primary-active: #0066d6;
--color-primary-rgb: 10, 132, 255;
--color-success: #30D158;
--color-warning: #FFD60A;
--color-danger: #FF453A;
--color-info: #64D2FF;
--color-text: #f5f5f7;
--color-text-secondary: #98989d;
--color-text-tertiary: #636366;
--color-text-inverse: #1d1d1f;
--color-bg: #1c1c1e;
--color-bg-elevated: #2c2c2e;
--color-bg-secondary: #3a3a3c;
--color-border: rgba(255, 255, 255, 0.08);
--color-border-strong: rgba(255, 255, 255, 0.16);
--color-separator: rgba(84, 84, 88, 0.36);
/* ---- Dark glassmorphism ---- */
--glass-blur: 25px;
--glass-saturate: 180%;
--glass-bg: rgba(38, 38, 42, 0.55);
--glass-bg-hover: rgba(52, 52, 56, 0.65);
--glass-bg-strong: rgba(38, 38, 42, 0.72);
--glass-border: rgba(255, 255, 255, 0.12);
--glass-shadow: 0 2px 16px rgba(0, 0, 0, 0.2), 0 0 1px rgba(0, 0, 0, 0.25);
--glass-shadow-lg: 0 8px 40px rgba(0, 0, 0, 0.3), 0 0 1px rgba(0, 0, 0, 0.15);
/* ---- Dark background ---- */
--bg-gradient: linear-gradient(135deg, #2c2e3a 0%, #353848 50%, #2a2d38 100%);
}
/* ---- Dark-mode-specific overrides ---- */
/* Inputs need darker backgrounds */
.cbi-input-text,
.cbi-input-password,
input[type="text"],
input[type="password"],
input[type="number"],
textarea,
select {
background: rgba(44, 44, 46, 0.55);
}
/* Login card */
.login-card {
background-image: linear-gradient(160deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.07) 25%, rgba(240, 248, 255, 0.08) 50%, rgba(255, 255, 255, 0.06) 75%, rgba(230, 240, 255, 0.07) 100%);
background-color: rgba(38, 38, 42, 0.55);
border-color: rgba(255, 255, 255, 0.14);
box-shadow: 0 8px 40px rgba(0, 0, 0, 0.25), 0 2px 8px rgba(0, 0, 0, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.1), inset 0 0 16px rgba(255, 255, 255, 0.06);
}
.login-form .login-field input {
background: rgba(255, 255, 255, 0.06);
border-color: rgba(255, 255, 255, 0.15);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), inset 0 0 4px rgba(255, 255, 255, 0.04);
}
.login-btn {
background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0.06) 25%, rgba(240, 248, 255, 0.07) 50%, rgba(255, 255, 255, 0.05) 75%, rgba(230, 240, 255, 0.06) 100%);
border-color: rgba(255, 255, 255, 0.15);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3), 0 1px 4px rgba(0, 0, 0, 0.15), inset 0 0 0.5px rgba(255, 255, 255, 0.12), inset 0 0 12px rgba(255, 255, 255, 0.15);
color: var(--color-text);
}
/* Buttons — glass-ui dark pattern */
.btn,
.cbi-button {
background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0.06) 25%, rgba(240, 248, 255, 0.07) 50%, rgba(255, 255, 255, 0.05) 75%, rgba(230, 240, 255, 0.06) 100%);
background-color: transparent;
border-color: rgba(255, 255, 255, 0.15);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3), 0 1px 4px rgba(0, 0, 0, 0.15), inset 0 0 0.5px rgba(255, 255, 255, 0.12), inset 0 0 12px rgba(255, 255, 255, 0.15);
}
.btn:hover,
.cbi-button:hover {
opacity: 0.9;
background-color: transparent;
}
.btn:active,
.cbi-button:active {
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3), inset 0 1px 2px rgba(0, 0, 0, 0.2);
}
.cbi-button-negative,
.cbi-button-remove,
.cbi-button-reset {
background-image: linear-gradient(135deg, rgba(255, 69, 58, 0.12) 0%, rgba(255, 69, 58, 0.08) 50%, rgba(255, 69, 58, 0.1) 100%);
background-color: transparent;
color: var(--color-danger);
border-color: rgba(255, 69, 58, 0.25);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3), 0 1px 4px rgba(0, 0, 0, 0.15), inset 0 0 0.5px rgba(255, 255, 255, 0.08), inset 0 0 8px rgba(255, 255, 255, 0.06);
}
.cbi-button-negative:hover,
.cbi-button-remove:hover,
.cbi-button-reset:hover {
opacity: 0.9;
background-color: transparent;
}
.cbi-button-negative:active,
.cbi-button-remove:active,
.cbi-button-reset:active {
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3), inset 0 1px 2px rgba(0, 0, 0, 0.2);
}
/* Sidebar */
#sidebar {
background-image: linear-gradient(160deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.07) 20%, rgba(240, 248, 255, 0.08) 45%, rgba(255, 255, 255, 0.06) 70%, rgba(230, 240, 255, 0.07) 100%);
background-color: rgba(38, 38, 42, 0.55);
border-color: rgba(255, 255, 255, 0.14);
box-shadow: 0 8px 40px rgba(0, 0, 0, 0.25), 0 2px 8px rgba(0, 0, 0, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.1), inset 0 0 12px rgba(255, 255, 255, 0.06);
}
/* Header bar */
#header {
background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.07) 25%, rgba(240, 248, 255, 0.08) 50%, rgba(255, 255, 255, 0.06) 75%, rgba(230, 240, 255, 0.07) 100%);
border-color: rgba(255, 255, 255, 0.15);
box-shadow: 0 2px 16px rgba(0, 0, 0, 0.2), 0 1px 4px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.1), inset 0 0 8px rgba(255, 255, 255, 0.06);
}
/* Page actions bar */
.cbi-page-actions {
background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.07) 25%, rgba(240, 248, 255, 0.08) 50%, rgba(255, 255, 255, 0.06) 75%, rgba(230, 240, 255, 0.07) 100%);
border-color: rgba(255, 255, 255, 0.15);
box-shadow: 0 2px 16px rgba(0, 0, 0, 0.2), 0 1px 4px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.1), inset 0 0 8px rgba(255, 255, 255, 0.06);
}
/* Nav hover & active */
.nav-item:hover {
background: rgba(255, 255, 255, 0.06);
}
.nav-item.active {
background: rgba(255, 255, 255, 0.15);
color: var(--color-text);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3), inset 0 1px 2px rgba(255, 255, 255, 0.12), inset 0 0 8px rgba(255, 255, 255, 0.08);
}
/* Sub-item active — slider handles highlight */
.nav-sub .nav-item.active {
background: transparent;
box-shadow: none;
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
/* Sliding selector — dark glass */
.nav-sub .nav-slider {
background: rgba(255, 255, 255, 0.08);
border: 0.5px solid rgba(255, 255, 255, 0.12);
backdrop-filter: blur(12px) saturate(150%);
-webkit-backdrop-filter: blur(12px) saturate(150%);
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2), inset 0 1px 1px rgba(255, 255, 255, 0.08), inset 0 0 4px rgba(255, 255, 255, 0.03);
}
/* Header tabs */
.header-tab:hover {
background: rgba(255, 255, 255, 0.06);
color: var(--color-text);
}
.header-tab.active {
background: transparent;
box-shadow: none;
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
/* Tab slider — dark glass */
.tab-slider {
background: rgba(255, 255, 255, 0.1);
border: 0.5px solid rgba(255, 255, 255, 0.12);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3), inset 0 1px 2px rgba(255, 255, 255, 0.1), inset 0 0 8px rgba(255, 255, 255, 0.06);
}
/* Sub-nav bar */
#header-sub {
background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.07) 25%, rgba(240, 248, 255, 0.08) 50%, rgba(255, 255, 255, 0.06) 75%, rgba(230, 240, 255, 0.07) 100%);
border-color: rgba(255, 255, 255, 0.15);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2), 0 1px 4px rgba(0, 0, 0, 0.1), 0 0 0 0.5px rgba(255, 255, 255, 0.12) inset, 0 0 12px rgba(255, 255, 255, 0.15) inset;
}
.sub-tab:hover {
background: rgba(255, 255, 255, 0.06);
}
.sub-tab.active {
background: transparent;
box-shadow: none;
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
/* Header glass pills */
.header-title,
#status-indicators,
.header-actions {
background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.04) 0%, rgba(255, 255, 255, 0.02) 50%, rgba(255, 255, 255, 0.03) 100%);
border-color: rgba(255, 255, 255, 0.1);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.12), inset 0 0.5px 0 rgba(255, 255, 255, 0.06);
}
/* Theme toggle */
.theme-toggle:hover {
background: rgba(255, 255, 255, 0.08);
}
.theme-toggle-float {
background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.07) 25%, rgba(240, 248, 255, 0.08) 50%, rgba(255, 255, 255, 0.06) 75%, rgba(230, 240, 255, 0.07) 100%);
border-color: rgba(255, 255, 255, 0.15);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18), 0 1px 2px rgba(0, 0, 0, 0.08), inset 0 0 0.5px rgba(255, 255, 255, 0.12), inset 0 1px 6px rgba(255, 255, 255, 0.12);
}
/* Tabs */
.cbi-tabmenu {
background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.07) 25%, rgba(240, 248, 255, 0.08) 50%, rgba(255, 255, 255, 0.06) 75%, rgba(230, 240, 255, 0.07) 100%);
border-color: rgba(255, 255, 255, 0.15);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2), 0 1px 4px rgba(0, 0, 0, 0.1), inset 0 0 0.5px rgba(255, 255, 255, 0.12), inset 0 0 12px rgba(255, 255, 255, 0.15);
}
.cbi-tabmenu li a:hover {
background: rgba(255, 255, 255, 0.06);
}
.cbi-tabmenu li.cbi-tab a {
background: rgba(255, 255, 255, 0.15);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3), inset 0 1px 2px rgba(255, 255, 255, 0.12), inset 0 0 8px rgba(255, 255, 255, 0.08);
}
/* Section fold button */
.cbi-section.fade-in .cbi-title > div:last-child span:hover {
background: rgba(255, 255, 255, 0.08);
}
/* Table row hover */
table tbody tr:hover td,
.table .tr:hover .td {
background: rgba(255, 255, 255, 0.03);
}
/* Pre / code */
pre,
#syslog {
background: rgba(255, 255, 255, 0.04);
}
/* Alert colors adjusted for dark */
.alert-message,
.cbi-section-error {
background: rgba(100, 210, 255, 0.08);
border-color: rgba(100, 210, 255, 0.18);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.08), inset 0 0 6px rgba(255, 255, 255, 0.04);
}
.alert-message.notice,
.alert-message.info {
background: rgba(100, 210, 255, 0.1);
border-color: rgba(100, 210, 255, 0.25);
}
.alert-message.warning {
background: rgba(255, 214, 10, 0.1);
border-color: rgba(255, 214, 10, 0.25);
}
.alert-message.error,
.cbi-section-error {
background: rgba(255, 69, 58, 0.1);
border-color: rgba(255, 69, 58, 0.25);
}
.alert-message.success {
background: rgba(48, 209, 88, 0.1);
border-color: rgba(48, 209, 88, 0.25);
}
/* Diagnostics & file browser in dark */
#diag-rc-output,
.cbi-filebrowser {
background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.07) 25%, rgba(240, 248, 255, 0.08) 50%, rgba(255, 255, 255, 0.06) 75%, rgba(230, 240, 255, 0.07) 100%);
border-color: rgba(255, 255, 255, 0.15);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18), 0 1px 2px rgba(0, 0, 0, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.08), inset 0 0 6px rgba(255, 255, 255, 0.04);
}
/* Ifacebox zone header in dark — slightly brighter tint */
.ifacebox-head[style*="background-color"] {
background-color: rgba(var(--zone-color-rgb), 0.2) !important;
border-bottom-color: rgba(var(--zone-color-rgb), 0.25) !important;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
}
/* Zone badges in dark — tint zone color instead of opaque background */
.zonebadge[style*="background-color"] {
background-color: rgba(var(--zone-color-rgb), 0.25) !important;
border-color: rgba(var(--zone-color-rgb), 0.3);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), inset 0 0 4px rgba(255, 255, 255, 0.03);
}
.zonebadge {
border-color: rgba(255, 255, 255, 0.08);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), inset 0 0 4px rgba(255, 255, 255, 0.03);
}
/* Ifacebox in dark */
.ifacebadge {
background: rgba(255, 255, 255, 0.08);
border-color: rgba(255, 255, 255, 0.1);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), inset 0 0 4px rgba(255, 255, 255, 0.03);
}
/* Port grid boxes in dark — glass-ui dark card */
div[style*="display:grid;grid-template-columns:repeat"] > .ifacebox {
background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.07) 25%, rgba(240, 248, 255, 0.08) 50%, rgba(255, 255, 255, 0.06) 75%, rgba(230, 240, 255, 0.07) 100%) !important;
border-color: rgba(255, 255, 255, 0.15) !important;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2), 0 1px 4px rgba(0, 0, 0, 0.1), 0 0 0 0.5px rgba(255, 255, 255, 0.12) inset, 0 0 12px rgba(255, 255, 255, 0.15) inset !important;
}
/* Network status table badges in dark */
.network-status-table .ifacebox-body .ifacebadge {
background: rgba(255, 255, 255, 0.06);
}
/* Dropdown open items hover */
.cbi-dropdown[open] > ul.dropdown > li:hover {
background: rgba(255, 255, 255, 0.06);
}
/* Progressbar */
.cbi-progressbar {
background: rgba(255, 255, 255, 0.06);
border-color: rgba(255, 255, 255, 0.06);
}
.cbi-progressbar > div {
background: linear-gradient(135deg, rgba(var(--color-primary-rgb), 0.65) 0%, rgba(var(--color-primary-rgb), 0.5) 50%, rgba(var(--color-primary-rgb), 0.6) 100%);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 0 6px rgba(255, 255, 255, 0.06);
}
.cbi-progressbar::after {
color: var(--color-text);
text-shadow: 0 0 4px rgba(0, 0, 0, 0.4);
}
/* Ifacebox-body itemlist labels */
.ifacebox-body > span > .nowrap > strong {
color: var(--color-text-tertiary);
}
/* UCI Changes dialog in dark */
.uci-change-legend-label > ins {
background-color: rgba(48, 209, 88, 0.3);
border-color: rgba(48, 209, 88, 0.5);
}
.uci-change-legend-label > del {
background-color: rgba(255, 69, 58, 0.3);
border-color: rgba(255, 69, 58, 0.5);
}
.uci-change-legend-label > var {
background-color: rgba(100, 210, 255, 0.25);
border-color: rgba(100, 210, 255, 0.4);
}
.uci-change-list ins {
background-color: rgba(48, 209, 88, 0.12);
border-color: rgba(48, 209, 88, 0.25);
}
.uci-change-list del {
background-color: rgba(255, 69, 58, 0.12);
border-color: rgba(255, 69, 58, 0.25);
}
.uci-change-list var {
background-color: rgba(100, 210, 255, 0.1);
border-color: rgba(100, 210, 255, 0.18);
}
/* Selection */
::selection {
background: rgba(var(--color-primary-rgb), 0.35);
}
@@ -0,0 +1,90 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="64" y2="64" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F5F5F7"/>
<stop offset="100%" stop-color="#E8E8ED"/>
</linearGradient>
<linearGradient id="glass" x1="4" y1="4" x2="60" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="white" stop-opacity="0.9"/>
<stop offset="40%" stop-color="white" stop-opacity="0.4"/>
<stop offset="100%" stop-color="white" stop-opacity="0.6"/>
</linearGradient>
<linearGradient id="edge" x1="4" y1="4" x2="60" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="white" stop-opacity="0.95"/>
<stop offset="50%" stop-color="#D1D1D6" stop-opacity="0.4"/>
<stop offset="100%" stop-color="white" stop-opacity="0.7"/>
</linearGradient>
<radialGradient id="refract" cx="18" cy="16" r="36" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="white" stop-opacity="0.55"/>
<stop offset="100%" stop-color="white" stop-opacity="0"/>
</radialGradient>
<!-- 3D shadow filter for WiFi arcs -->
<filter id="arc-shadow" x="-20%" y="-20%" width="140%" height="140%">
<feDropShadow dx="0" dy="1.5" stdDeviation="1.5" flood-color="#002266" flood-opacity="0.3"/>
</filter>
<!-- Arc stroke gradients — darker Apple blue with depth -->
<linearGradient id="arc1" x1="14" y1="26" x2="50" y2="30" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#3A8EF6" stop-opacity="0.3"/>
<stop offset="20%" stop-color="#0040DD" stop-opacity="0.9"/>
<stop offset="50%" stop-color="#0033BB" stop-opacity="1"/>
<stop offset="80%" stop-color="#0040DD" stop-opacity="0.9"/>
<stop offset="100%" stop-color="#3A8EF6" stop-opacity="0.3"/>
</linearGradient>
<linearGradient id="arc2" x1="20" y1="32" x2="44" y2="36" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#3A8EF6" stop-opacity="0.25"/>
<stop offset="25%" stop-color="#0040DD" stop-opacity="0.8"/>
<stop offset="50%" stop-color="#0033BB" stop-opacity="0.95"/>
<stop offset="75%" stop-color="#0040DD" stop-opacity="0.8"/>
<stop offset="100%" stop-color="#3A8EF6" stop-opacity="0.25"/>
</linearGradient>
<linearGradient id="arc3" x1="26" y1="38" x2="38" y2="42" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#4D9BF7" stop-opacity="0.2"/>
<stop offset="30%" stop-color="#0040DD" stop-opacity="0.7"/>
<stop offset="50%" stop-color="#0033BB" stop-opacity="0.9"/>
<stop offset="70%" stop-color="#0040DD" stop-opacity="0.7"/>
<stop offset="100%" stop-color="#4D9BF7" stop-opacity="0.2"/>
</linearGradient>
<radialGradient id="dot-grad" cx="32" cy="46" r="3.5" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#0033BB"/>
<stop offset="60%" stop-color="#0040DD"/>
<stop offset="100%" stop-color="#3A8EF6" stop-opacity="0.4"/>
</radialGradient>
</defs>
<!-- Outer shadow for 3D depth -->
<rect width="64" height="64" rx="14" fill="none" filter="url(#arc-shadow)"/>
<!-- Light background -->
<rect width="64" height="64" rx="14" fill="url(#bg)"/>
<!-- Clean glass pane -->
<rect x="4" y="4" width="56" height="56" rx="12" fill="url(#glass)" stroke="url(#edge)" stroke-width="0.75"/>
<!-- Light refraction highlight -->
<rect x="4" y="4" width="56" height="28" rx="12" fill="url(#refract)"/>
<!-- Inner glow edge -->
<rect x="5" y="5" width="54" height="54" rx="11" fill="none" stroke="white" stroke-opacity="0.35" stroke-width="0.5"/>
<!-- WiFi shadow layer (dark offset below — 3D depth) -->
<path d="M14 30a25.5 25.5 0 0 1 36 0" fill="none" stroke="#002266" stroke-opacity="0.18" stroke-width="3" stroke-linecap="round"/>
<path d="M20 36a16 16 0 0 1 24 0" fill="none" stroke="#002266" stroke-opacity="0.15" stroke-width="3" stroke-linecap="round"/>
<path d="M26 42a7.5 7.5 0 0 1 12 0" fill="none" stroke="#002266" stroke-opacity="0.12" stroke-width="3" stroke-linecap="round"/>
<!-- WiFi highlight layer (white offset above — raised/embossed) -->
<path d="M14 27a25.5 25.5 0 0 1 36 0" fill="none" stroke="white" stroke-opacity="0.65" stroke-width="2" stroke-linecap="round"/>
<path d="M20 33a16 16 0 0 1 24 0" fill="none" stroke="white" stroke-opacity="0.6" stroke-width="2" stroke-linecap="round"/>
<path d="M26 39a7.5 7.5 0 0 1 12 0" fill="none" stroke="white" stroke-opacity="0.55" stroke-width="2" stroke-linecap="round"/>
<!-- WiFi main arcs — darker blue gradient -->
<path d="M14 28a25.5 25.5 0 0 1 36 0" fill="none" stroke="url(#arc1)" stroke-width="2.5" stroke-linecap="round"/>
<path d="M20 34a16 16 0 0 1 24 0" fill="none" stroke="url(#arc2)" stroke-width="2.5" stroke-linecap="round"/>
<path d="M26 40a7.5 7.5 0 0 1 12 0" fill="none" stroke="url(#arc3)" stroke-width="2.5" stroke-linecap="round"/>
<!-- Center dot with 3D -->
<circle cx="32" cy="48" r="2.5" fill="#002266" fill-opacity="0.15"/>
<circle cx="32" cy="46" r="2.5" fill="url(#dot-grad)"/>
<circle cx="31.2" cy="45.2" r="0.9" fill="white" fill-opacity="0.4"/>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

@@ -0,0 +1,327 @@
'use strict';
'require baseclass';
'require ui';
return baseclass.extend({
__init__: function() {
ui.menu.load().then(L.bind(this.render, this));
},
/* Icon SVG paths for top-level sidebar categories (stroke-based, 24x24 viewBox) */
icons: {
'status': '<line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/>',
'system': '<circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 01-2.83 2.83l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09a1.65 1.65 0 00-1-1.51 1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09a1.65 1.65 0 001.51-1 1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06a1.65 1.65 0 001.82.33h.09a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06a1.65 1.65 0 00-.33 1.82v.09a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z"/>',
'network': '<circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 014 10 15.3 15.3 0 01-4 10 15.3 15.3 0 01-4-10 15.3 15.3 0 014-10z"/>',
'services': '<polygon points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/>',
'nas': '<line x1="22" y1="12" x2="2" y2="12"/><path d="M5.45 5.11L2 12v6a2 2 0 002 2h16a2 2 0 002-2v-6l-3.45-6.89A2 2 0 0016.76 4H7.24a2 2 0 00-1.79 1.11z"/><line x1="6" y1="16" x2="6.01" y2="16"/><line x1="10" y1="16" x2="10.01" y2="16"/>',
'vpn': '<rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0110 0v4"/>',
'docker': '<path d="M21 16V8a2 2 0 00-1-1.73l-7-4a2 2 0 00-2 0l-7 4A2 2 0 003 8v8a2 2 0 001 1.73l7 4a2 2 0 002 0l7-4A2 2 0 0021 16z"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/>',
'logout': '<path d="M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/>',
'_default': '<circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/>'
},
getIcon: function(name) {
var pathData = this.icons[name] || this.icons['_default'];
var markup = '<svg xmlns="http://www.w3.org/2000/svg" class="nav-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">' + pathData + '</svg>';
var doc = new DOMParser().parseFromString(markup, 'image/svg+xml');
return document.importNode(doc.documentElement, true);
},
render: function(tree) {
var container = document.getElementById('sidebar-nav');
if (!container) return;
/* Clear existing menu elements to prevent duplicates on re-render (e.g. Save & Apply) */
container.innerHTML = '';
var headerNav = document.getElementById('header-nav');
if (headerNav) {
/* Remove only tabs and sliders, preserve header-title */
var old = headerNav.querySelectorAll('.header-tab, .tab-slider');
for (var k = 0; k < old.length; k++) old[k].remove();
}
var headerTabs = document.getElementById('header-tabs');
if (headerTabs) headerTabs.innerHTML = '';
var topChildren = ui.menu.getChildren(tree);
for (var i = 0; i < topChildren.length; i++) {
var topNode = topChildren[i];
var isTopActive = L.env.requestpath.length
? topNode.name == L.env.requestpath[0]
: i == 0;
if (isTopActive) {
this.renderSidebarMenu(container, topNode, topNode.name);
}
}
/* Render mode menu (top-level tabs) if more than one category */
if (topChildren.length > 1) {
this.renderModeMenu(topChildren);
}
/* Set header title from the deepest active menu node */
var titleEl = document.getElementById('header-title');
if (titleEl) {
var node = tree;
var title = '';
for (var i = 0; i < L.env.dispatchpath.length && node; i++) {
node = node.children[L.env.dispatchpath[i]];
if (node && node.title)
title = node.title;
}
titleEl.textContent = title ? _(title) : '';
}
/* Render tab menu for sub-sub pages */
if (L.env.dispatchpath.length >= 3) {
var node = tree;
var url = '';
for (var i = 0; i < 3 && node; i++) {
node = node.children[L.env.dispatchpath[i]];
url = url + (url ? '/' : '') + L.env.dispatchpath[i];
}
if (node)
this.renderTabMenu(node, url);
}
},
/* Shared: position a slider behind the active tab element */
positionTabSlider: function(container, slider, activeEl, animate) {
if (!activeEl) return;
if (!animate) slider.style.transition = 'none';
slider.style.left = activeEl.offsetLeft + 'px';
slider.style.width = activeEl.offsetWidth + 'px';
slider.style.opacity = '1';
if (!animate) {
requestAnimationFrame(function() {
slider.style.transition = '';
});
}
},
/* Shared: add slider to a horizontal tab container */
addTabSlider: function(container, navigateOnClick) {
var slider = E('div', { 'class': 'tab-slider' });
container.insertBefore(slider, container.firstChild);
var self = this;
/* Attach click handlers to all tabs */
var tabs = container.querySelectorAll('.header-tab, .sub-tab');
for (var i = 0; i < tabs.length; i++) {
(function(tab, sl) {
tab.addEventListener('click', function(ev) {
if (navigateOnClick) {
/* Slide first, then navigate */
ev.preventDefault();
var prev = container.querySelector('.header-tab.active, .sub-tab.active');
if (prev) prev.classList.remove('active');
tab.classList.add('active');
self.positionTabSlider(container, sl, tab, true);
document.body.classList.add('page-leaving');
var href = tab.href;
setTimeout(function() {
window.location.href = href;
}, 180);
} else {
/* In-page tab switch — just move slider */
self.positionTabSlider(container, sl, tab, true);
}
});
})(tabs[i], slider);
}
/* Position on active tab */
requestAnimationFrame(function() {
var active = container.querySelector('.header-tab.active, .sub-tab.active');
self.positionTabSlider(container, slider, active, false);
});
return slider;
},
renderModeMenu: function(topChildren) {
var container = document.getElementById('header-nav');
if (!container) return;
for (var i = 0; i < topChildren.length; i++) {
var child = topChildren[i];
var isActive = L.env.requestpath.length
? child.name == L.env.requestpath[0]
: i == 0;
var item = E('a', {
'class': 'header-tab' + (isActive ? ' active' : ''),
'href': L.url(child.name),
'data-name': child.name
}, [ _(child.title) ]);
container.appendChild(item);
}
/* Add sliding selector */
this.addTabSlider(container, true);
},
renderSidebarMenu: function(container, tree, url) {
var children = ui.menu.getChildren(tree);
if (children.length == 0) return;
var group = E('div', { 'class': 'nav-group' });
for (var i = 0; i < children.length; i++) {
var child = children[i];
var subChildren = ui.menu.getChildren(child);
var hasChildren = subChildren.length > 0;
var isActive = L.env.dispatchpath[1] == child.name;
/* For items with children, link to first child */
var linkUrl = hasChildren
? L.url(url, child.name, subChildren[0].name)
: L.url(url, child.name);
var item = E('a', {
'class': 'nav-item' + (isActive ? ' open' : ''),
'href': linkUrl,
'data-name': child.name
}, [
E('span', { 'class': 'nav-label' }, [ _(child.title) ])
]);
/* Add icon before the label */
item.insertBefore(this.getIcon(child.name), item.firstChild);
if (hasChildren) {
item.appendChild(E('svg', {
'class': 'nav-arrow',
'viewBox': '0 0 24 24',
'fill': 'none',
'stroke': 'currentColor',
'stroke-width': '2'
}, [
E('polyline', { 'points': '9 18 15 12 9 6' })
]));
}
group.appendChild(item);
if (hasChildren) {
var subMenu = E('div', {
'class': 'nav-sub' + (isActive ? ' open' : '')
});
/* Sliding highlight indicator */
var slider = E('div', { 'class': 'nav-slider' });
subMenu.appendChild(slider);
for (var j = 0; j < subChildren.length; j++) {
var sub = subChildren[j];
var isSubActive = isActive && L.env.dispatchpath[2] == sub.name;
var subItem = E('a', {
'class': 'nav-item' + (isSubActive ? ' active' : ''),
'href': L.url(url, child.name, sub.name)
}, [
E('span', { 'class': 'nav-label' }, [ _(sub.title) ])
]);
/* Slide highlight to clicked item before navigating */
(function(el, sl) {
el.addEventListener('click', function(ev) {
ev.preventDefault();
var prev = el.parentNode.querySelector('.nav-item.active');
if (prev) prev.classList.remove('active');
el.classList.add('active');
sl.style.top = el.offsetTop + 'px';
sl.style.height = el.offsetHeight + 'px';
sl.style.opacity = '1';
document.body.classList.add('page-leaving');
setTimeout(function() {
window.location.href = el.href;
}, 180);
});
})(subItem, slider);
subMenu.appendChild(subItem);
}
/* Position slider on the active item after render */
(function(sm, sl) {
requestAnimationFrame(function() {
var active = sm.querySelector('.nav-item.active');
if (active) {
sl.style.transition = 'none';
sl.style.top = active.offsetTop + 'px';
sl.style.height = active.offsetHeight + 'px';
sl.style.opacity = '1';
/* Re-enable transition after initial position */
requestAnimationFrame(function() {
sl.style.transition = '';
});
}
});
})(subMenu, slider);
group.appendChild(subMenu);
/* Bind click handler to toggle submenu */
(function(navItem, subEl) {
navItem.addEventListener('click', function(ev) {
ev.preventDefault();
var isOpen = subEl.classList.contains('open');
if (isOpen) {
subEl.classList.remove('open');
navItem.classList.remove('open');
} else {
subEl.classList.add('open');
navItem.classList.add('open');
}
});
})(item, subMenu);
}
}
container.appendChild(group);
},
renderTabMenu: function(tree, url, level) {
var container = document.getElementById('header-sub');
if (!container) return E([]);
var children = ui.menu.getChildren(tree);
var activeNode = null;
if (children.length == 0)
return E([]);
/* Clear any CBI tabs that footer.ut added before menu loaded */
container.innerHTML = '';
container.classList.remove('active');
document.body.classList.remove('has-sub-nav');
for (var i = 0; i < children.length; i++) {
var child = children[i];
var isActive = L.env.dispatchpath[3 + (level || 0)] == child.name;
container.appendChild(E('a', {
'class': 'sub-tab' + (isActive ? ' active' : ''),
'href': L.url(url, child.name)
}, [ _(child.title) ]));
if (isActive)
activeNode = child;
}
container.classList.add('active');
document.body.classList.add('has-sub-nav');
/* Add sliding selector */
this.addTabSlider(container, true);
/* Do NOT recurse — deeper menu-tree levels stay in-content as CBI tabmenus */
}
});
@@ -0,0 +1,286 @@
'use strict';
'require baseclass';
'require rpc';
'require fs';
var callSystemInfo = rpc.declare({
object: 'system',
method: 'info'
});
var callInterfaceDump = rpc.declare({
object: 'network.interface',
method: 'dump',
expect: { 'interface': [] }
});
var callDeviceStatus = rpc.declare({
object: 'network.device',
method: 'status',
params: ['name']
});
return baseclass.extend({
prevStats: null,
prevTime: null,
netDevice: null,
netLabel: null,
netChecked: false,
linkSpeed: null,
numCores: 1,
__init__: function() {
var self = this;
/* Detect core count once so load average can be converted to %. */
L.resolveDefault(fs.read('/proc/cpuinfo'), '').then(function(text) {
var m = text.match(/^processor\s*:/gm);
self.numCores = (m && m.length) || 1;
});
this.setupIndicators();
},
icons: {
cpu: '<svg xmlns="http://www.w3.org/2000/svg" class="indicator-icon" width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="1 9 4 4 7 11 10 2 13 9"/></svg>',
ram: '<svg xmlns="http://www.w3.org/2000/svg" class="indicator-icon" width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"><path d="M1 3 H13 V10 H8 V9 H6 V10 H1 Z"/><rect x="2.2" y="4.5" width="2" height="3"/><rect x="6" y="4.5" width="2" height="3"/><rect x="9.8" y="4.5" width="2" height="3"/><line x1="2" y1="10" x2="2" y2="11.5"/><line x1="4" y1="10" x2="4" y2="11.5"/><line x1="10" y1="10" x2="10" y2="11.5"/><line x1="12" y1="10" x2="12" y2="11.5"/></svg>',
net: '<svg xmlns="http://www.w3.org/2000/svg" class="indicator-icon" width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><line x1="7" y1="1" x2="7" y2="13"/><polyline points="3 4 7 1 11 4"/><polyline points="3 10 7 13 11 10"/></svg>',
uptime: '<svg xmlns="http://www.w3.org/2000/svg" class="indicator-icon" width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="7" cy="7" r="6"/><polyline points="7 3 7 7 10 9"/></svg>'
},
makeIcon: function(name) {
var markup = this.icons[name];
if (!markup) return document.createTextNode('');
var doc = new DOMParser().parseFromString(markup, 'image/svg+xml');
return document.importNode(doc.documentElement, true);
},
createIndicator: function(name, title) {
var el = document.createElement('span');
el.setAttribute('data-indicator', name);
el.title = title;
el.appendChild(this.makeIcon(name));
var val = document.createElement('span');
val.className = 'indicator-value';
/* Restore last known value from session to avoid flash of "--" on page nav */
var cached = null;
try { cached = sessionStorage.getItem('glass-status-' + name); } catch(e) {}
val.textContent = cached || '--';
el.appendChild(val);
return el;
},
setLevel: function(el, level) {
el.setAttribute('data-level', level);
},
setupIndicators: function() {
this.container = document.getElementById('status-indicators');
if (!this.container) return;
this.cpuEl = this.createIndicator('cpu', 'CPU Load');
this.ramEl = this.createIndicator('ram', 'Memory Usage');
this.uptimeEl = this.createIndicator('uptime', 'Uptime');
this.container.appendChild(this.cpuEl);
this.container.appendChild(this.ramEl);
this.container.appendChild(this.uptimeEl);
this.fetchAndUpdate();
setInterval(L.bind(this.fetchAndUpdate, this), 5000);
},
fetchAndUpdate: function() {
var self = this;
L.resolveDefault(callSystemInfo(), {}).then(function(info) {
self.updateSystem(info);
});
if (!this.netChecked) {
this.netChecked = true;
L.resolveDefault(callInterfaceDump(), []).then(function(ifaces) {
/* Find WAN device — prefer 'wan' over 'wan6' */
var wanDev = null;
for (var i = 0; i < ifaces.length; i++) {
var iface = ifaces[i];
if (iface.interface === 'wan') {
wanDev = iface.l3_device || iface.device || null;
break;
}
}
if (!wanDev) {
for (var i = 0; i < ifaces.length; i++) {
if (ifaces[i].interface === 'wan6') {
wanDev = ifaces[i].l3_device || ifaces[i].device || null;
break;
}
}
}
self.resolvePhysicalDevice(wanDev || 'wan');
});
} else if (this.netDevice) {
this.pollNetwork();
}
},
resolvePhysicalDevice: function(devName) {
var self = this;
L.resolveDefault(callDeviceStatus(devName), {}).then(function(dev) {
if (!dev) return;
var members = dev['bridge-members'];
if (dev.type === 'bridge' && members && members.length > 0) {
/* Bridge stats only count management traffic;
use first physical port for real forwarded stats */
self.netDevice = members[0];
} else if (dev.statistics) {
self.netDevice = devName;
}
if (!self.netDevice) return;
/* Query physical port for link speed and DSA info */
L.resolveDefault(callDeviceStatus(self.netDevice), {}).then(function(phys) {
if (phys && phys.speed) {
var m = String(phys.speed).match(/^(\d+)/);
if (m) self.linkSpeed = parseInt(m[1], 10);
}
/* DSA port with hardware offload: per-port counters miss
offloaded flows; use the conduit (switch master) instead */
if (phys && phys.devtype === 'dsa' && phys['hw-tc-offload'] && phys.conduit) {
self.netLabel = self.netDevice;
self.netDevice = phys.conduit;
}
self.netEl = self.createIndicator('net', 'Throughput');
self.container.insertBefore(self.netEl, self.uptimeEl);
self.pollNetwork();
});
});
},
pollNetwork: function() {
var self = this;
L.resolveDefault(callDeviceStatus(this.netDevice), {}).then(function(dev) {
self.updateNetwork(dev);
});
},
updateSystem: function(info) {
if (!info) return;
if (info.load) {
var load1 = info.load[0] / 65536;
var load5 = (info.load[1] / 65536).toFixed(2);
var load15 = (info.load[2] / 65536).toFixed(2);
var pct = Math.min(load1 / this.numCores, 1) * 100;
var pctStr = pct.toFixed(0) + '%';
this.cpuEl.querySelector('.indicator-value').textContent = pctStr;
try { sessionStorage.setItem('glass-status-cpu', pctStr); } catch(e) {}
this.cpuEl.title = 'CPU: ' + pctStr + ' (load ' + load1.toFixed(2) +
' / ' + load5 + ' / ' + load15 + ' on ' + this.numCores +
(this.numCores === 1 ? ' core)' : ' cores)');
var level = pct < 60 ? 'ok' : pct < 85 ? 'warn' : 'crit';
this.setLevel(this.cpuEl, level);
}
if (info.memory) {
var total = info.memory.total;
var avail = info.memory.available || info.memory.free;
var used = total - avail;
var pct = (used / total * 100).toFixed(0);
this.ramEl.querySelector('.indicator-value').textContent = pct + '%';
try { sessionStorage.setItem('glass-status-ram', pct + '%'); } catch(e) {}
this.ramEl.title = 'RAM: ' + this.formatBytes(used) + ' / ' + this.formatBytes(total) + ' (' + pct + '% used)';
var level = pct < 60 ? 'ok' : pct < 85 ? 'warn' : 'crit';
this.setLevel(this.ramEl, level);
}
if (info.uptime) {
this.uptimeEl.querySelector('.indicator-value').textContent = this.formatUptime(info.uptime);
try { sessionStorage.setItem('glass-status-uptime', this.formatUptime(info.uptime)); } catch(e) {}
this.uptimeEl.title = 'Uptime: ' + this.formatUptimeFull(info.uptime);
}
},
updateNetwork: function(dev) {
if (!dev || !dev.statistics || !this.netEl) return;
var now = Date.now() / 1000;
var rx = dev.statistics.rx_bytes || 0;
var tx = dev.statistics.tx_bytes || 0;
if (this.prevStats && this.prevTime) {
var dt = now - this.prevTime;
if (dt > 0) {
var rxSpeed = (rx - this.prevStats.rx) / dt;
var txSpeed = (tx - this.prevStats.tx) / dt;
if (rxSpeed < 0) rxSpeed = 0;
if (txSpeed < 0) txSpeed = 0;
var netText = '\u2193' + this.formatSpeed(rxSpeed) + ' \u2191' + this.formatSpeed(txSpeed);
this.netEl.querySelector('.indicator-value').textContent = netText;
try { sessionStorage.setItem('glass-status-net', netText); } catch(e) {}
var tip = (this.netLabel || this.netDevice) + ': \u2193 ' + this.formatSpeedFull(rxSpeed) + ' / \u2191 ' + this.formatSpeedFull(txSpeed);
if (this.linkSpeed)
tip += ' (Link: ' + (this.linkSpeed >= 1000 ? (this.linkSpeed / 1000) + ' Gbps' : this.linkSpeed + ' Mbps') + ')';
this.netEl.title = tip;
var peak = Math.max(rxSpeed, txSpeed);
var level = peak < 1048576 ? 'ok' : peak < 52428800 ? 'active' : 'busy';
this.setLevel(this.netEl, level);
}
}
this.prevStats = { rx: rx, tx: tx };
this.prevTime = now;
},
formatUptime: function(s) {
var d = Math.floor(s / 86400);
var h = Math.floor((s % 86400) / 3600);
var m = Math.floor((s % 3600) / 60);
if (d > 0) return d + 'd ' + h + 'h';
return h + 'h ' + m + 'm';
},
formatUptimeFull: function(s) {
var d = Math.floor(s / 86400);
var h = Math.floor((s % 86400) / 3600);
var m = Math.floor((s % 3600) / 60);
var parts = [];
if (d > 0) parts.push(d + (d === 1 ? ' day' : ' days'));
if (h > 0) parts.push(h + (h === 1 ? ' hour' : ' hours'));
if (m > 0) parts.push(m + (m === 1 ? ' min' : ' mins'));
return parts.join(', ') || '< 1 min';
},
formatBytes: function(bytes) {
if (bytes >= 1073741824)
return (bytes / 1073741824).toFixed(1) + ' GB';
if (bytes >= 1048576)
return (bytes / 1048576).toFixed(0) + ' MB';
return (bytes / 1024).toFixed(0) + ' KB';
},
formatSpeed: function(bytesPerSec) {
var bits = bytesPerSec * 8;
if (bits >= 1000000000)
return (bits / 1000000000).toFixed(1) + 'G';
if (bits >= 1000000)
return (bits / 1000000).toFixed(1) + 'M';
if (bits >= 1000)
return (bits / 1000).toFixed(1) + 'K';
return Math.round(bits) + 'b';
},
formatSpeedFull: function(bytesPerSec) {
var bits = bytesPerSec * 8;
if (bits >= 1000000000)
return (bits / 1000000000).toFixed(1) + ' Gbps';
if (bits >= 1000000)
return (bits / 1000000).toFixed(1) + ' Mbps';
if (bits >= 1000)
return (bits / 1000).toFixed(1) + ' kbps';
return Math.round(bits) + ' bps';
}
});
@@ -0,0 +1,137 @@
'use strict';
'require view';
'require form';
'require uci';
'require fs';
return view.extend({
load: function () {
return Promise.all([
uci.load('glass'),
L.resolveDefault(fs.list('/www/luci-static/glass/background'), [])
]);
},
render: function (data) {
var bgFiles = (data[1] || []).filter(function(f) {
return f.name && !f.name.startsWith('.') && /\.(jpe?g|png|gif|webp|mp4|webm)$/i.test(f.name);
});
var hasBg = bgFiles.length > 0;
var bgName = hasBg ? bgFiles[0].name : null;
var m, s, o;
m = new form.Map('glass', _('Glass Theme'),
_('Configure the appearance of the Glass theme. Changes take effect after saving and refreshing the page.'));
/* ── General ── */
s = m.section(form.NamedSection, 'global', 'global', _('General'));
s.anonymous = true;
o = s.option(form.ListValue, 'mode', _('Theme mode'),
_('Controls the overall appearance. "Normal" follows the system preference.'));
o.value('normal', _('Auto (follow system)'));
o.value('light', _('Light'));
o.value('dark', _('Dark'));
o.default = 'normal';
o = s.option(form.Flag, 'status_bar', _('Header status bar'),
_('Show live system stats (CPU, RAM, network, uptime) in the header. Disable to reduce resource usage on low-end devices.'));
o.default = '1';
o.rmempty = false;
o = s.option(form.ListValue, 'font_size', _('Base font size'),
_('Scales all text in the theme. Larger values improve readability on high-DPI displays.'));
o.value('13', _('Small (13px)'));
o.value('14', _('Normal (14px)'));
o.value('16', _('Large (16px)'));
o.value('18', _('Extra Large (18px)'));
o.default = '14';
/* ── Colors ── */
s = m.section(form.NamedSection, 'global', 'global', _('Accent Colors'));
s.anonymous = true;
o = s.option(form.Value, 'primary', _('Primary color (light mode)'),
_('Accent color used for active elements, links, and buttons in light mode.'));
o.default = '#007AFF';
o.placeholder = '#007AFF';
o.datatype = 'string';
o.renderWidget = function(section_id, option_index, cfgvalue) {
var el = form.Value.prototype.renderWidget.apply(this, arguments);
var input = el.querySelector('input');
if (input) {
input.type = 'color';
input.style.height = '2.5rem';
input.style.cursor = 'pointer';
}
return el;
};
o = s.option(form.Value, 'dark_primary', _('Primary color (dark mode)'),
_('Accent color used for active elements, links, and buttons in dark mode.'));
o.default = '#0A84FF';
o.placeholder = '#0A84FF';
o.datatype = 'string';
o.renderWidget = function(section_id, option_index, cfgvalue) {
var el = form.Value.prototype.renderWidget.apply(this, arguments);
var input = el.querySelector('input');
if (input) {
input.type = 'color';
input.style.height = '2.5rem';
input.style.cursor = 'pointer';
}
return el;
};
/* ── Glass Effects (Light Mode) ── */
s = m.section(form.NamedSection, 'global', 'global', _('Glass Effects — Light Mode'));
s.anonymous = true;
o = s.option(form.Value, 'blur', _('Blur intensity (px)'),
_('Backdrop blur radius for glass panels. Higher values create a more frosted appearance.'));
o.default = '20';
o.placeholder = '20';
o.datatype = 'range(0,50)';
o = s.option(form.Value, 'transparency', _('Panel transparency'),
_('Background opacity of glass panels (0 = fully transparent, 1 = fully opaque).'));
o.default = '0.72';
o.placeholder = '0.72';
o.datatype = 'string';
/* ── Glass Effects (Dark Mode) ── */
s = m.section(form.NamedSection, 'global', 'global', _('Glass Effects — Dark Mode'));
s.anonymous = true;
o = s.option(form.Value, 'blur_dark', _('Blur intensity (px)'),
_('Backdrop blur radius for glass panels in dark mode.'));
o.default = '25';
o.placeholder = '25';
o.datatype = 'range(0,50)';
o = s.option(form.Value, 'transparency_dark', _('Panel transparency'),
_('Background opacity of glass panels in dark mode (0 = fully transparent, 1 = fully opaque).'));
o.default = '0.30';
o.placeholder = '0.30';
o.datatype = 'string';
/* ── Background ── */
s = m.section(form.NamedSection, 'global', 'global', _('Background'));
s.anonymous = true;
o = s.option(form.DummyValue, '_bg_info', _('Current background'));
o.rawhtml = true;
o.cfgvalue = function () {
if (hasBg) {
return '<span style="color:var(--color-success)">' +
_('Active') + ': ' + bgName + '</span>';
}
return '<span style="color:var(--color-text-secondary)">' +
_('No background set. Upload an image or video named "bg" (e.g. bg.jpg, bg.png, bg.mp4) to /www/luci-static/glass/background/ via SCP.') +
'</span>';
};
return m.render();
}
});
+13
View File
@@ -0,0 +1,13 @@
/* ==========================================================================
luci-theme-glass — Master Stylesheet
Import order matters: tokens → reset → mixins → layout → components → fixes
========================================================================== */
@import "variables";
@import "normalize";
@import "glass";
@import "layout";
@import "components";
@import "sysauth";
@import "responsive";
@import "page-fix";
File diff suppressed because it is too large. Load diff
+576
View File
@@ -0,0 +1,576 @@
/* ==========================================================================
Dark Mode — luci-theme-glass
Compiled separately and injected by header.ut when dark mode is active.
========================================================================== */
:root {
/* ---- Colors — Dark mode ---- */
--color-primary: #0A84FF;
--color-primary-hover: #409cff;
--color-primary-active: #0066d6;
--color-primary-rgb: 10, 132, 255;
--color-success: #30D158;
--color-warning: #FFD60A;
--color-danger: #FF453A;
--color-info: #64D2FF;
--color-text: #f5f5f7;
--color-text-secondary: #98989d;
--color-text-tertiary: #636366;
--color-text-inverse: #1d1d1f;
--color-bg: #1c1c1e;
--color-bg-elevated: #2c2c2e;
--color-bg-secondary: #3a3a3c;
--color-border: rgba(255, 255, 255, 0.08);
--color-border-strong: rgba(255, 255, 255, 0.16);
--color-separator: rgba(84, 84, 88, 0.36);
/* ---- Dark glassmorphism ---- */
--glass-blur: 25px;
--glass-saturate: 180%;
--glass-bg: rgba(38, 38, 42, 0.55);
--glass-bg-hover: rgba(52, 52, 56, 0.65);
--glass-bg-strong: rgba(38, 38, 42, 0.72);
--glass-border: rgba(255, 255, 255, 0.12);
--glass-shadow: 0 2px 16px rgba(0, 0, 0, 0.20),
0 0 1px rgba(0, 0, 0, 0.25);
--glass-shadow-lg: 0 8px 40px rgba(0, 0, 0, 0.30),
0 0 1px rgba(0, 0, 0, 0.15);
/* ---- Dark background ---- */
--bg-gradient: linear-gradient(135deg, #2c2e3a 0%, #353848 50%, #2a2d38 100%);
}
/* ---- Dark-mode-specific overrides ---- */
/* Inputs need darker backgrounds */
.cbi-input-text,
.cbi-input-password,
input[type="text"],
input[type="password"],
input[type="number"],
textarea,
select {
background: rgba(44, 44, 46, 0.55);
}
/* Login card */
.login-card {
background-image: linear-gradient(
160deg,
rgba(255, 255, 255, 0.10) 0%,
rgba(255, 255, 255, 0.07) 25%,
rgba(240, 248, 255, 0.08) 50%,
rgba(255, 255, 255, 0.06) 75%,
rgba(230, 240, 255, 0.07) 100%
);
background-color: rgba(38, 38, 42, 0.55);
border-color: rgba(255, 255, 255, 0.14);
box-shadow:
0 8px 40px rgba(0, 0, 0, 0.25),
0 2px 8px rgba(0, 0, 0, 0.12),
inset 0 1px 0 rgba(255, 255, 255, 0.10),
inset 0 0 16px rgba(255, 255, 255, 0.06);
}
.login-form .login-field input {
background: rgba(255, 255, 255, 0.06);
border-color: rgba(255, 255, 255, 0.15);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.08),
inset 0 0 4px rgba(255, 255, 255, 0.04);
}
.login-btn {
background-image: linear-gradient(
135deg,
rgba(255, 255, 255, 0.08) 0%,
rgba(255, 255, 255, 0.06) 25%,
rgba(240, 248, 255, 0.07) 50%,
rgba(255, 255, 255, 0.05) 75%,
rgba(230, 240, 255, 0.06) 100%
);
border-color: rgba(255, 255, 255, 0.15);
box-shadow:
0 4px 16px rgba(0, 0, 0, 0.30),
0 1px 4px rgba(0, 0, 0, 0.15),
inset 0 0 0.5px rgba(255, 255, 255, 0.12),
inset 0 0 12px rgba(255, 255, 255, 0.15);
color: var(--color-text);
}
/* Buttons — glass-ui dark pattern */
.btn,
.cbi-button {
background-image: linear-gradient(
135deg,
rgba(255, 255, 255, 0.08) 0%,
rgba(255, 255, 255, 0.06) 25%,
rgba(240, 248, 255, 0.07) 50%,
rgba(255, 255, 255, 0.05) 75%,
rgba(230, 240, 255, 0.06) 100%
);
background-color: transparent;
border-color: rgba(255, 255, 255, 0.15);
box-shadow:
0 4px 16px rgba(0, 0, 0, 0.30),
0 1px 4px rgba(0, 0, 0, 0.15),
inset 0 0 0.5px rgba(255, 255, 255, 0.12),
inset 0 0 12px rgba(255, 255, 255, 0.15);
&:hover {
opacity: 0.90;
background-color: transparent;
}
&:active {
box-shadow:
inset 0 2px 4px rgba(0, 0, 0, 0.30),
inset 0 1px 2px rgba(0, 0, 0, 0.20);
}
}
.cbi-button-negative,
.cbi-button-remove,
.cbi-button-reset {
background-image: linear-gradient(
135deg,
rgba(255, 69, 58, 0.12) 0%,
rgba(255, 69, 58, 0.08) 50%,
rgba(255, 69, 58, 0.10) 100%
);
background-color: transparent;
color: var(--color-danger);
border-color: rgba(255, 69, 58, 0.25);
box-shadow:
0 4px 16px rgba(0, 0, 0, 0.30),
0 1px 4px rgba(0, 0, 0, 0.15),
inset 0 0 0.5px rgba(255, 255, 255, 0.08),
inset 0 0 8px rgba(255, 255, 255, 0.06);
&:hover {
opacity: 0.90;
background-color: transparent;
}
&:active {
box-shadow:
inset 0 2px 4px rgba(0, 0, 0, 0.30),
inset 0 1px 2px rgba(0, 0, 0, 0.20);
}
}
/* Sidebar */
#sidebar {
background-image: linear-gradient(
160deg,
rgba(255, 255, 255, 0.10) 0%,
rgba(255, 255, 255, 0.07) 20%,
rgba(240, 248, 255, 0.08) 45%,
rgba(255, 255, 255, 0.06) 70%,
rgba(230, 240, 255, 0.07) 100%
);
background-color: rgba(38, 38, 42, 0.55);
border-color: rgba(255, 255, 255, 0.14);
box-shadow:
0 8px 40px rgba(0, 0, 0, 0.25),
0 2px 8px rgba(0, 0, 0, 0.12),
inset 0 1px 0 rgba(255, 255, 255, 0.10),
inset 0 0 12px rgba(255, 255, 255, 0.06);
}
/* Header bar */
#header {
background-image: linear-gradient(
135deg,
rgba(255, 255, 255, 0.10) 0%,
rgba(255, 255, 255, 0.07) 25%,
rgba(240, 248, 255, 0.08) 50%,
rgba(255, 255, 255, 0.06) 75%,
rgba(230, 240, 255, 0.07) 100%
);
border-color: rgba(255, 255, 255, 0.15);
box-shadow:
0 2px 16px rgba(0, 0, 0, 0.20),
0 1px 4px rgba(0, 0, 0, 0.10),
inset 0 1px 0 rgba(255, 255, 255, 0.10),
inset 0 0 8px rgba(255, 255, 255, 0.06);
}
/* Page actions bar */
.cbi-page-actions {
background-image: linear-gradient(
135deg,
rgba(255, 255, 255, 0.10) 0%,
rgba(255, 255, 255, 0.07) 25%,
rgba(240, 248, 255, 0.08) 50%,
rgba(255, 255, 255, 0.06) 75%,
rgba(230, 240, 255, 0.07) 100%
);
border-color: rgba(255, 255, 255, 0.15);
box-shadow:
0 2px 16px rgba(0, 0, 0, 0.20),
0 1px 4px rgba(0, 0, 0, 0.10),
inset 0 1px 0 rgba(255, 255, 255, 0.10),
inset 0 0 8px rgba(255, 255, 255, 0.06);
}
/* Nav hover & active */
.nav-item:hover {
background: rgba(255, 255, 255, 0.06);
}
.nav-item.active {
background: rgba(255, 255, 255, 0.15);
color: var(--color-text);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
box-shadow:
0 2px 6px rgba(0, 0, 0, 0.30),
inset 0 1px 2px rgba(255, 255, 255, 0.12),
inset 0 0 8px rgba(255, 255, 255, 0.08);
}
/* Sub-item active — slider handles highlight */
.nav-sub .nav-item.active {
background: transparent;
box-shadow: none;
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
/* Sliding selector — dark glass */
.nav-sub .nav-slider {
background: rgba(255, 255, 255, 0.08);
border: 0.5px solid rgba(255, 255, 255, 0.12);
backdrop-filter: blur(12px) saturate(150%);
-webkit-backdrop-filter: blur(12px) saturate(150%);
box-shadow:
0 1px 4px rgba(0, 0, 0, 0.20),
inset 0 1px 1px rgba(255, 255, 255, 0.08),
inset 0 0 4px rgba(255, 255, 255, 0.03);
}
/* Header tabs */
.header-tab {
&:hover {
background: rgba(255, 255, 255, 0.06);
color: var(--color-text);
}
&.active {
background: transparent;
box-shadow: none;
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
}
/* Tab slider — dark glass */
.tab-slider {
background: rgba(255, 255, 255, 0.10);
border: 0.5px solid rgba(255, 255, 255, 0.12);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
box-shadow:
0 2px 6px rgba(0, 0, 0, 0.30),
inset 0 1px 2px rgba(255, 255, 255, 0.10),
inset 0 0 8px rgba(255, 255, 255, 0.06);
}
/* Sub-nav bar */
#header-sub {
background-image: linear-gradient(
135deg,
rgba(255, 255, 255, 0.10) 0%,
rgba(255, 255, 255, 0.07) 25%,
rgba(240, 248, 255, 0.08) 50%,
rgba(255, 255, 255, 0.06) 75%,
rgba(230, 240, 255, 0.07) 100%
);
border-color: rgba(255, 255, 255, 0.15);
box-shadow:
0 4px 16px rgba(0, 0, 0, 0.20),
0 1px 4px rgba(0, 0, 0, 0.10),
0 0 0 0.5px rgba(255, 255, 255, 0.12) inset,
0 0 12px rgba(255, 255, 255, 0.15) inset;
}
.sub-tab {
&:hover {
background: rgba(255, 255, 255, 0.06);
}
&.active {
background: transparent;
box-shadow: none;
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
}
/* Header glass pills */
.header-title,
#status-indicators,
.header-actions {
background-image: linear-gradient(
135deg,
rgba(255, 255, 255, 0.04) 0%,
rgba(255, 255, 255, 0.02) 50%,
rgba(255, 255, 255, 0.03) 100%
);
border-color: rgba(255, 255, 255, 0.10);
box-shadow:
0 2px 8px rgba(0, 0, 0, 0.25),
0 1px 2px rgba(0, 0, 0, 0.12),
inset 0 0.5px 0 rgba(255, 255, 255, 0.06);
}
/* Theme toggle */
.theme-toggle:hover {
background: rgba(255, 255, 255, 0.08);
}
.theme-toggle-float {
background-image: linear-gradient(
135deg,
rgba(255, 255, 255, 0.10) 0%,
rgba(255, 255, 255, 0.07) 25%,
rgba(240, 248, 255, 0.08) 50%,
rgba(255, 255, 255, 0.06) 75%,
rgba(230, 240, 255, 0.07) 100%
);
border-color: rgba(255, 255, 255, 0.15);
box-shadow:
0 2px 8px rgba(0, 0, 0, 0.18),
0 1px 2px rgba(0, 0, 0, 0.08),
inset 0 0 0.5px rgba(255, 255, 255, 0.12),
inset 0 1px 6px rgba(255, 255, 255, 0.12);
}
/* Tabs */
.cbi-tabmenu {
background-image: linear-gradient(
135deg,
rgba(255, 255, 255, 0.10) 0%,
rgba(255, 255, 255, 0.07) 25%,
rgba(240, 248, 255, 0.08) 50%,
rgba(255, 255, 255, 0.06) 75%,
rgba(230, 240, 255, 0.07) 100%
);
border-color: rgba(255, 255, 255, 0.15);
box-shadow:
0 4px 16px rgba(0, 0, 0, 0.20),
0 1px 4px rgba(0, 0, 0, 0.10),
inset 0 0 0.5px rgba(255, 255, 255, 0.12),
inset 0 0 12px rgba(255, 255, 255, 0.15);
li {
a:hover {
background: rgba(255, 255, 255, 0.06);
}
&.cbi-tab a {
background: rgba(255, 255, 255, 0.15);
box-shadow:
0 2px 6px rgba(0, 0, 0, 0.30),
inset 0 1px 2px rgba(255, 255, 255, 0.12),
inset 0 0 8px rgba(255, 255, 255, 0.08);
}
}
}
/* Section fold button */
.cbi-section.fade-in .cbi-title > div:last-child span:hover {
background: rgba(255, 255, 255, 0.08);
}
/* Table row hover */
table tbody tr:hover td,
.table .tr:hover .td {
background: rgba(255, 255, 255, 0.03);
}
/* Pre / code */
pre,
#syslog {
background: rgba(255, 255, 255, 0.04);
}
/* Alert colors adjusted for dark */
.alert-message,
.cbi-section-error {
background: rgba(100, 210, 255, 0.08);
border-color: rgba(100, 210, 255, 0.18);
box-shadow:
0 2px 8px rgba(0, 0, 0, 0.20),
inset 0 1px 0 rgba(255, 255, 255, 0.08),
inset 0 0 6px rgba(255, 255, 255, 0.04);
}
.alert-message.notice,
.alert-message.info {
background: rgba(100, 210, 255, 0.10);
border-color: rgba(100, 210, 255, 0.25);
}
.alert-message.warning {
background: rgba(255, 214, 10, 0.10);
border-color: rgba(255, 214, 10, 0.25);
}
.alert-message.error,
.cbi-section-error {
background: rgba(255, 69, 58, 0.10);
border-color: rgba(255, 69, 58, 0.25);
}
.alert-message.success {
background: rgba(48, 209, 88, 0.10);
border-color: rgba(48, 209, 88, 0.25);
}
/* Diagnostics & file browser in dark */
#diag-rc-output,
.cbi-filebrowser {
background-image: linear-gradient(
135deg,
rgba(255, 255, 255, 0.10) 0%,
rgba(255, 255, 255, 0.07) 25%,
rgba(240, 248, 255, 0.08) 50%,
rgba(255, 255, 255, 0.06) 75%,
rgba(230, 240, 255, 0.07) 100%
);
border-color: rgba(255, 255, 255, 0.15);
box-shadow:
0 2px 8px rgba(0, 0, 0, 0.18),
0 1px 2px rgba(0, 0, 0, 0.08),
inset 0 1px 0 rgba(255, 255, 255, 0.08),
inset 0 0 6px rgba(255, 255, 255, 0.04);
}
/* Ifacebox zone header in dark — slightly brighter tint */
.ifacebox-head[style*="background-color"] {
background-color: rgba(var(--zone-color-rgb), 0.20) !important;
border-bottom-color: rgba(var(--zone-color-rgb), 0.25) !important;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
}
/* Zone badges in dark — tint zone color instead of opaque background */
.zonebadge[style*="background-color"] {
background-color: rgba(var(--zone-color-rgb), 0.25) !important;
border-color: rgba(var(--zone-color-rgb), 0.30);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.06),
inset 0 0 4px rgba(255, 255, 255, 0.03);
}
.zonebadge {
border-color: rgba(255, 255, 255, 0.08);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.06),
inset 0 0 4px rgba(255, 255, 255, 0.03);
}
/* Ifacebox in dark */
.ifacebadge {
background: rgba(255, 255, 255, 0.08);
border-color: rgba(255, 255, 255, 0.10);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.06),
inset 0 0 4px rgba(255, 255, 255, 0.03);
}
/* Port grid boxes in dark — glass-ui dark card */
div[style*="display:grid;grid-template-columns:repeat"] > .ifacebox {
background-image: linear-gradient(
135deg,
rgba(255, 255, 255, 0.10) 0%,
rgba(255, 255, 255, 0.07) 25%,
rgba(240, 248, 255, 0.08) 50%,
rgba(255, 255, 255, 0.06) 75%,
rgba(230, 240, 255, 0.07) 100%
) !important;
border-color: rgba(255, 255, 255, 0.15) !important;
box-shadow:
0 4px 16px rgba(0, 0, 0, 0.20),
0 1px 4px rgba(0, 0, 0, 0.10),
0 0 0 0.5px rgba(255, 255, 255, 0.12) inset,
0 0 12px rgba(255, 255, 255, 0.15) inset !important;
}
/* Network status table badges in dark */
.network-status-table .ifacebox-body .ifacebadge {
background: rgba(255, 255, 255, 0.06);
}
/* Dropdown open items hover */
.cbi-dropdown[open] > ul.dropdown > li:hover {
background: rgba(255, 255, 255, 0.06);
}
/* Progressbar */
.cbi-progressbar {
background: rgba(255, 255, 255, 0.06);
border-color: rgba(255, 255, 255, 0.06);
> div {
background: linear-gradient(
135deg,
rgba(var(--color-primary-rgb), 0.65) 0%,
rgba(var(--color-primary-rgb), 0.50) 50%,
rgba(var(--color-primary-rgb), 0.60) 100%
);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.15),
inset 0 0 6px rgba(255, 255, 255, 0.06);
}
&::after {
color: var(--color-text);
text-shadow: 0 0 4px rgba(0, 0, 0, 0.40);
}
}
/* Ifacebox-body itemlist labels */
.ifacebox-body > span > .nowrap > strong {
color: var(--color-text-tertiary);
}
/* UCI Changes dialog in dark */
.uci-change-legend-label {
> ins {
background-color: rgba(48, 209, 88, 0.30);
border-color: rgba(48, 209, 88, 0.50);
}
> del {
background-color: rgba(255, 69, 58, 0.30);
border-color: rgba(255, 69, 58, 0.50);
}
> var {
background-color: rgba(100, 210, 255, 0.25);
border-color: rgba(100, 210, 255, 0.40);
}
}
.uci-change-list {
ins {
background-color: rgba(48, 209, 88, 0.12);
border-color: rgba(48, 209, 88, 0.25);
}
del {
background-color: rgba(255, 69, 58, 0.12);
border-color: rgba(255, 69, 58, 0.25);
}
var {
background-color: rgba(100, 210, 255, 0.10);
border-color: rgba(100, 210, 255, 0.18);
}
}
/* Selection */
::selection {
background: rgba(var(--color-primary-rgb), 0.35);
}
+55
View File
@@ -0,0 +1,55 @@
/* ==========================================================================
Glassmorphism Mixins — luci-theme-glass
========================================================================== */
/* Standard glass panel — default for cards, sections, dropdowns */
.glass-effect() {
background: var(--glass-bg);
backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
-webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
border: 0.5px solid var(--glass-border);
box-shadow: var(--glass-shadow);
}
/* Frosted glass — stronger blur, higher opacity (sidebar, login card) */
.glass-frosted() {
background: var(--glass-bg-strong);
backdrop-filter: blur(30px) saturate(var(--glass-saturate));
-webkit-backdrop-filter: blur(30px) saturate(var(--glass-saturate));
border: 0.5px solid var(--glass-border);
box-shadow: var(--glass-shadow-lg);
}
/* Subtle glass — minimal effect for secondary/nested elements */
.glass-subtle() {
background: rgba(255, 255, 255, 0.40);
backdrop-filter: blur(10px) saturate(120%);
-webkit-backdrop-filter: blur(10px) saturate(120%);
border: 0.5px solid rgba(255, 255, 255, 0.25);
}
/* Glass hover state */
.glass-hover() {
background: var(--glass-bg-hover);
box-shadow: var(--glass-shadow-lg);
}
/* Inner glow — top highlight for glass panels */
.glass-inner-glow() {
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 1px;
background: linear-gradient(
90deg,
transparent,
rgba(255, 255, 255, 0.6),
transparent
);
border-radius: inherit;
pointer-events: none;
}
}
+798
View File
@@ -0,0 +1,798 @@
/* ==========================================================================
Layout — Sidebar, Header, Content
========================================================================== */
/* ---- Background layer ---- */
#bg-wrap {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
background: var(--bg-gradient);
background-size: cover;
background-position: center;
img, video {
width: 100%;
height: 100%;
object-fit: cover;
}
}
/* ---- Sidebar ---- */
#sidebar {
position: fixed;
top: var(--sidebar-gap);
left: var(--sidebar-gap);
width: var(--sidebar-width);
height: calc(100vh - var(--sidebar-gap) * 2);
z-index: var(--z-sidebar);
/* True glassmorphism — multi-stop gradient, stronger for readability */
background-image: linear-gradient(
160deg,
rgba(255, 255, 255, 0.22) 0%,
rgba(255, 255, 255, 0.18) 20%,
rgba(245, 250, 255, 0.20) 45%,
rgba(255, 255, 255, 0.16) 70%,
rgba(240, 245, 255, 0.19) 100%
);
background-color: rgba(255, 255, 255, 0.62);
backdrop-filter: blur(30px) saturate(var(--glass-saturate));
-webkit-backdrop-filter: blur(30px) saturate(var(--glass-saturate));
border: 0.5px solid rgba(255, 255, 255, 0.40);
box-shadow:
0 8px 40px rgba(0, 0, 0, 0.08),
0 2px 8px rgba(0, 0, 0, 0.04),
inset 0 1px 0 rgba(255, 255, 255, 0.50),
inset 0 0 12px rgba(255, 255, 255, 0.15);
border-radius: var(--radius-xl);
display: flex;
flex-direction: column;
transition: transform var(--transition-slow);
overflow: hidden;
}
.sidebar-header {
display: flex;
align-items: center;
padding: var(--space-lg) var(--space-xl);
height: var(--header-height);
border-bottom: 0.5px solid var(--color-separator);
.logo {
width: 32px;
height: 32px;
flex-shrink: 0;
}
.brand {
margin-left: var(--space-md);
font-size: var(--font-size-lg);
font-weight: var(--font-weight-semibold);
color: var(--color-text);
white-space: nowrap;
overflow: hidden;
}
}
.sidebar-footer {
padding: var(--space-md) var(--space-xl);
border-top: 0.5px solid var(--color-separator);
text-align: center;
.sidebar-version {
font-size: 0.75rem;
color: var(--color-text-tertiary);
}
}
/* ---- Sidebar navigation ---- */
.sidebar-nav {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
padding: var(--space-sm) 0;
&::-webkit-scrollbar {
width: 4px;
}
&::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, 0.15);
border-radius: var(--radius-full);
}
}
.nav-group {
margin-bottom: var(--space-xs);
.nav-group-title {
padding: var(--space-sm) var(--space-xl);
font-size: var(--font-size-sm);
font-weight: var(--font-weight-semibold);
color: var(--color-text-tertiary);
text-transform: uppercase;
letter-spacing: 0.05em;
}
}
.nav-item {
display: flex;
align-items: center;
padding: 0.55rem var(--space-xl);
margin: 1px var(--space-sm);
border-radius: var(--radius-md);
font-size: var(--font-size-lg);
color: var(--color-text);
cursor: pointer;
transition: background var(--transition-fast), color var(--transition-fast);
text-decoration: none;
&:hover {
background: rgba(0, 0, 0, 0.04);
color: var(--color-text);
}
&.active {
background: rgba(255, 255, 255, 0.45);
color: var(--color-text);
font-weight: var(--font-weight-medium);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
box-shadow:
0 1px 3px rgba(0, 0, 0, 0.08),
inset 0 1px 1px rgba(255, 255, 255, 0.60),
inset 0 0 6px rgba(255, 255, 255, 0.15);
}
.nav-icon {
width: 20px;
height: 20px;
margin-right: var(--space-md);
flex-shrink: 0;
opacity: 0.65;
}
&.active .nav-icon {
opacity: 1;
}
.nav-label {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.nav-arrow {
margin-left: auto;
width: 16px;
height: 16px;
opacity: 0.4;
transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1), opacity var(--transition-fast);
}
&.open .nav-arrow {
transform: rotate(90deg);
opacity: 0.6;
}
}
.nav-sub {
position: relative;
overflow: hidden;
max-height: 0;
opacity: 0;
transition: max-height 0.35s cubic-bezier(0.16, 1, 0.3, 1),
opacity 0.25s ease;
&.open {
/* Upper bound for the expand animation. Must exceed the tallest submenu
encountered in the wild (System commonly reaches ~14 items once third-
party apps like theme-config, scheduled-tasks, etc. are installed). */
max-height: 2000px;
opacity: 1;
}
.nav-item {
padding-left: calc(var(--space-xl) + 32px);
font-size: var(--font-size-base);
transform: translateX(-8px);
opacity: 0;
transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1),
opacity 0.2s ease,
color var(--transition-fast);
/* Sub-item active state — no background, slider handles it */
&.active {
background: transparent;
box-shadow: none;
backdrop-filter: none;
-webkit-backdrop-filter: none;
font-weight: var(--font-weight-medium);
}
}
&.open .nav-item {
transform: translateX(0);
opacity: 1;
}
// Stagger sub-items (nth-of-type since slider is first child)
&.open .nav-item:nth-of-type(1) { transition-delay: 0.03s; }
&.open .nav-item:nth-of-type(2) { transition-delay: 0.06s; }
&.open .nav-item:nth-of-type(3) { transition-delay: 0.09s; }
&.open .nav-item:nth-of-type(4) { transition-delay: 0.12s; }
&.open .nav-item:nth-of-type(5) { transition-delay: 0.15s; }
&.open .nav-item:nth-of-type(6) { transition-delay: 0.18s; }
&.open .nav-item:nth-of-type(7) { transition-delay: 0.21s; }
&.open .nav-item:nth-of-type(8) { transition-delay: 0.24s; }
&.open .nav-item:nth-of-type(n+9) { transition-delay: 0.27s; }
.nav-slider {
position: absolute;
left: var(--space-sm);
right: var(--space-sm);
top: 0;
height: 0;
opacity: 0;
border-radius: var(--radius-md);
background: rgba(255, 255, 255, 0.35);
backdrop-filter: blur(12px) saturate(150%);
-webkit-backdrop-filter: blur(12px) saturate(150%);
border: 0.5px solid rgba(255, 255, 255, 0.45);
box-shadow:
0 1px 3px rgba(0, 0, 0, 0.04),
inset 0 1px 1px rgba(255, 255, 255, 0.35),
inset 0 0 4px rgba(255, 255, 255, 0.10);
transition: top 0.3s cubic-bezier(0.16, 1, 0.3, 1),
height 0.2s cubic-bezier(0.16, 1, 0.3, 1),
opacity 0.2s ease;
z-index: 0;
pointer-events: none;
}
.nav-item {
position: relative;
z-index: 1;
}
}
/* ---- Sidebar user area ---- */
.sidebar-user {
padding: var(--space-lg) var(--space-xl);
border-top: 0.5px solid var(--color-separator);
display: flex;
align-items: center;
.user-avatar {
width: 32px;
height: 32px;
border-radius: var(--radius-full);
background: var(--color-bg-secondary);
display: flex;
align-items: center;
justify-content: center;
font-weight: var(--font-weight-semibold);
font-size: var(--font-size-sm);
color: var(--color-text-secondary);
flex-shrink: 0;
}
.user-info {
margin-left: var(--space-md);
overflow: hidden;
.user-name {
font-weight: var(--font-weight-medium);
font-size: var(--font-size-sm);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.user-host {
font-size: var(--font-size-sm);
color: var(--color-text-tertiary);
}
}
}
/* ---- Top header nav bar ---- */
#header {
position: fixed;
top: var(--sidebar-gap);
left: calc(var(--sidebar-width) + var(--sidebar-gap) * 2);
right: var(--sidebar-gap);
height: 44px;
z-index: var(--z-header);
border-radius: var(--radius-lg);
display: flex;
align-items: center;
padding: 4px 4px 4px 6px;
gap: var(--space-xs);
transition: left var(--transition-slow);
/* True glassmorphism — multi-stop gradient like sub-nav */
background-image: linear-gradient(
135deg,
rgba(255, 255, 255, 0.15) 0%,
rgba(255, 255, 255, 0.12) 25%,
rgba(240, 248, 255, 0.13) 50%,
rgba(255, 255, 255, 0.11) 75%,
rgba(230, 240, 255, 0.12) 100%
);
background-color: transparent;
backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
-webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
border: 0.5px solid rgba(255, 255, 255, 0.35);
box-shadow:
0 2px 16px rgba(0, 0, 0, 0.06),
0 1px 4px rgba(0, 0, 0, 0.03),
inset 0 1px 0 rgba(255, 255, 255, 0.40),
inset 0 0 8px rgba(255, 255, 255, 0.12);
}
/* ---- Header top-level tabs ---- */
#header-nav,
#header-tabs {
display: flex;
align-items: center;
position: relative;
}
.header-sep {
width: 1px;
height: 18px;
background: var(--color-separator);
margin: 0 var(--space-xs);
flex-shrink: 0;
}
.header-tab {
padding: 6px var(--space-lg);
border-radius: var(--radius-md);
font-size: var(--font-size-sm);
font-weight: var(--font-weight-medium);
color: var(--color-text-secondary);
text-decoration: none;
transition: background var(--transition-fast), color var(--transition-fast), box-shadow var(--transition-fast);
white-space: nowrap;
&:hover {
background: rgba(0, 0, 0, 0.04);
color: var(--color-text);
}
&.active {
color: var(--color-text);
background: transparent;
box-shadow: none;
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
}
/* Horizontal sliding selector for header tabs */
.tab-slider {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 0;
opacity: 0;
border-radius: var(--radius-md);
background: rgba(255, 255, 255, 0.45);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
box-shadow:
0 1px 3px rgba(0, 0, 0, 0.08),
inset 0 1px 1px rgba(255, 255, 255, 0.60),
inset 0 0 6px rgba(255, 255, 255, 0.15);
transition: left 0.3s cubic-bezier(0.16, 1, 0.3, 1),
width 0.2s cubic-bezier(0.16, 1, 0.3, 1),
opacity 0.2s ease;
z-index: 0;
pointer-events: none;
}
.header-tab,
.sub-tab {
position: relative;
z-index: 1;
}
/* ---- Status indicators (center of header) ---- */
#status-indicators {
margin: 0 auto;
display: flex;
align-items: center;
gap: var(--space-sm);
padding: 4px var(--space-md);
.header-glass-pill();
&:empty {
display: none;
}
[data-indicator] {
display: flex;
align-items: center;
gap: 4px;
font-size: var(--font-size-sm);
font-weight: var(--font-weight-medium);
color: var(--color-text-secondary);
white-space: nowrap;
cursor: default;
transition: color 0.3s ease;
.indicator-icon {
width: 14px;
height: 14px;
flex-shrink: 0;
opacity: 0.6;
transition: color 0.3s ease, opacity 0.3s ease;
}
/* Level colors — neutral by default, color only when noteworthy */
&[data-level="warn"] {
color: #FF9500;
.indicator-icon { opacity: 0.85; }
}
&[data-level="crit"] {
color: #FF3B30;
.indicator-icon { opacity: 0.9; }
}
&[data-level="active"] {
color: #007AFF;
.indicator-icon { opacity: 0.8; }
}
&[data-level="busy"] {
color: #AF52DE;
.indicator-icon { opacity: 0.85; }
}
}
[data-indicator] + [data-indicator] {
border-left: 0.5px solid rgba(128, 128, 128, 0.25);
padding-left: var(--space-sm);
}
}
/* ---- Glass pill badges (title + indicators) ---- */
.header-glass-pill() {
height: 2.25rem;
display: flex;
align-items: center;
border-radius: var(--radius-md);
background-image: linear-gradient(
135deg,
rgba(255, 255, 255, 0.15) 0%,
rgba(255, 255, 255, 0.10) 25%,
rgba(240, 248, 255, 0.12) 50%,
rgba(255, 255, 255, 0.08) 75%,
rgba(230, 240, 255, 0.10) 100%
);
background-color: transparent;
border: 0.5px solid rgba(255, 255, 255, 0.18);
box-shadow:
0 2px 8px rgba(0, 0, 0, 0.06),
0 1px 2px rgba(0, 0, 0, 0.03),
0 0 0 0.5px rgba(255, 255, 255, 0.08) inset,
0 1px 6px rgba(255, 255, 255, 0.10) inset;
backdrop-filter: blur(12px) saturate(180%);
-webkit-backdrop-filter: blur(12px) saturate(180%);
}
.header-title {
font-size: var(--font-size-sm);
font-weight: var(--font-weight-semibold);
color: var(--color-text);
white-space: nowrap;
cursor: default;
padding: 4px var(--space-md);
.header-glass-pill();
}
.header-actions {
margin-left: auto;
flex-shrink: 0;
display: flex;
align-items: center;
gap: var(--space-sm);
padding: 4px var(--space-md);
.header-glass-pill();
&:empty {
display: none;
}
[data-indicator] {
display: flex;
align-items: center;
gap: 4px;
font-size: var(--font-size-sm);
font-weight: var(--font-weight-medium);
color: var(--color-text-secondary);
white-space: nowrap;
cursor: default;
&[data-style="active"] {
color: var(--color-primary);
}
}
}
/* ---- Theme toggle button ---- */
.theme-toggle {
display: flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
padding: 0;
border: none;
border-radius: var(--radius-sm);
background: none;
color: var(--color-text-secondary);
cursor: pointer;
transition: color var(--transition-fast);
flex-shrink: 0;
&:hover {
color: var(--color-text);
}
&:active {
transform: scale(0.92);
}
.theme-icon {
width: 15px;
height: 15px;
display: none;
}
}
/* Show only the icon matching current theme */
html[data-theme="auto"] .theme-icon-auto,
html:not([data-theme]) .theme-icon-auto {
display: block;
}
html[data-theme="light"] .theme-icon-light {
display: block;
}
html[data-theme="dark"] .theme-icon-dark {
display: block;
}
/* Floating variant for login page */
.theme-toggle-float {
position: fixed;
top: var(--space-lg);
right: var(--space-lg);
z-index: var(--z-dropdown);
width: 36px;
height: 36px;
border-radius: var(--radius-md);
.header-glass-pill();
.theme-icon {
width: 18px;
height: 18px;
}
}
/* Mobile hamburger */
.menu-toggle {
display: none;
background: none;
border: none;
cursor: pointer;
padding: var(--space-sm);
margin-right: var(--space-md);
color: var(--color-text);
svg {
width: 22px;
height: 22px;
}
}
/* ---- Sub-navigation bar (CBI tabs) ---- */
#header-sub {
position: fixed;
top: calc(var(--sidebar-gap) + 44px + 4px);
left: calc(var(--sidebar-width) + var(--sidebar-gap) * 2);
width: fit-content;
max-width: calc(100vw - var(--sidebar-width) - var(--sidebar-gap) * 3);
height: 2.25rem;
z-index: var(--z-header);
border-radius: var(--radius-md);
display: none;
align-items: center;
padding: 3px 4px;
gap: 2px;
overflow-x: auto;
transition: left var(--transition-slow);
/* Glass tab-list background — from glass-ui */
background-image: linear-gradient(
135deg,
rgba(255, 255, 255, 0.15) 0%,
rgba(255, 255, 255, 0.12) 25%,
rgba(240, 248, 255, 0.13) 50%,
rgba(255, 255, 255, 0.11) 75%,
rgba(230, 240, 255, 0.12) 100%
);
background-color: transparent;
backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
-webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
border: 0.5px solid rgba(255, 255, 255, 0.12);
box-shadow:
0 4px 16px rgba(0, 0, 0, 0.08),
0 1px 4px rgba(0, 0, 0, 0.04),
0 0 0 0.5px rgba(255, 255, 255, 0.08) inset,
0 0 12px rgba(255, 255, 255, 0.10) inset;
/* Hide scrollbar */
&::-webkit-scrollbar {
display: none;
}
scrollbar-width: none;
&.active {
display: inline-flex;
}
}
/* Sub-nav tab items — glass-ui TabsTrigger pattern */
.sub-tab {
padding: 4px var(--space-md);
border-radius: var(--radius-sm);
font-size: var(--font-size-sm);
font-weight: var(--font-weight-medium);
color: var(--color-text-secondary);
text-decoration: none;
white-space: nowrap;
cursor: pointer;
transition: background var(--transition-fast), color var(--transition-fast),
box-shadow var(--transition-fast), backdrop-filter var(--transition-fast);
&:hover {
background: rgba(0, 0, 0, 0.04);
color: var(--color-text);
}
&.active {
color: var(--color-text);
background: transparent;
box-shadow: none;
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
}
/* Sub-tab slider — inset to match sub-tab content area */
#header-sub > .tab-slider {
border-radius: var(--radius-sm);
top: 3px;
bottom: 3px;
height: auto;
}
/* ---- Page transition ---- */
@keyframes page-enter {
from {
opacity: 0;
transform: translateY(12px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* ---- Main content area ---- */
#content-wrap {
margin-left: calc(var(--sidebar-width) + var(--sidebar-gap) * 2);
margin-top: calc(44px + var(--sidebar-gap) * 2);
min-height: calc(100vh - 44px - var(--sidebar-gap) * 2);
padding: var(--content-padding);
transition: margin-left var(--transition-slow);
animation: page-enter 0.3s cubic-bezier(0.16, 1, 0.3, 1) both;
}
/* JS view content — fade in when LuCI replaces the spinner */
#view > :not(.spinning) {
animation: page-enter 0.25s cubic-bezier(0.16, 1, 0.3, 1) both;
}
/* Style LuCI's "Loading view..." spinner as a centered glass card */
#view > .spinning {
position: fixed;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
padding: var(--space-lg) var(--space-xl);
border-radius: var(--radius-lg);
.glass-effect();
z-index: 100;
}
/* Fade-out before navigation */
body.page-leaving #content-wrap {
opacity: 0;
transform: translateY(-8px);
transition: opacity 0.15s ease, transform 0.15s ease;
}
/* Push content down when sub-nav is visible */
body.has-sub-nav #content-wrap {
margin-top: calc(44px + 36px + var(--sidebar-gap) * 2 + 4px);
}
#content {
max-width: var(--content-max-width);
margin: 0 auto;
}
/* Mobile overlay */
.sidebar-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.3);
z-index: calc(var(--z-sidebar) - 1);
opacity: 0;
transition: opacity var(--transition-normal);
&.active {
display: block;
opacity: 1;
}
}
/* ---- Page title ---- */
.page-title {
margin-bottom: var(--space-xl);
h2 {
font-size: var(--font-size-xl);
font-weight: var(--font-weight-bold);
}
.page-description {
margin-top: var(--space-xs);
color: var(--color-text-secondary);
font-size: var(--font-size-sm);
}
}
/* ---- Footer ---- */
.glass-footer {
margin-left: calc(var(--sidebar-width) + var(--sidebar-gap) * 2);
padding: var(--space-lg) var(--content-padding);
text-align: right;
font-size: var(--font-size-sm);
color: var(--color-text-tertiary);
transition: margin-left var(--transition-slow);
a {
color: var(--color-text-tertiary);
text-decoration: none;
&:hover {
color: var(--color-text-secondary);
}
}
.footer-sep {
margin: 0 var(--space-sm);
opacity: 0.4;
}
}
+129
View File
@@ -0,0 +1,129 @@
/* ==========================================================================
Normalize / Reset — luci-theme-glass
Minimal reset for LuCI pages.
========================================================================== */
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-size: var(--font-size-base);
line-height: var(--line-height);
-webkit-text-size-adjust: 100%;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
/* Glass scrollbar */
scrollbar-width: thin;
scrollbar-color: rgba(128, 128, 128, 0.35) transparent;
}
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: rgba(128, 128, 128, 0.35);
border-radius: 3px;
&:hover {
background: rgba(128, 128, 128, 0.55);
}
}
body {
font-family: var(--font-sans);
font-size: var(--font-size-base);
color: var(--color-text);
background: var(--color-bg);
min-height: 100vh;
overflow-x: hidden;
}
a {
color: var(--color-primary);
text-decoration: none;
transition: color var(--transition-fast);
&:hover {
color: var(--color-primary-hover);
}
}
img {
max-width: 100%;
height: auto;
}
table {
border-collapse: collapse;
border-spacing: 0;
width: 100%;
}
input,
select,
textarea,
button {
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
code,
pre {
font-family: var(--font-mono);
font-size: var(--font-size-sm);
}
hr {
border: none;
border-top: 0.5px solid var(--color-border);
margin: var(--space-md) 0;
}
p {
margin-bottom: var(--space-sm);
}
ul, ol {
padding-left: 1.5em;
margin: var(--space-sm) 0;
}
li {
margin-bottom: 2px;
}
h1, h2, h3, h4, h5, h6 {
font-weight: var(--font-weight-semibold);
line-height: 1.25;
color: var(--color-text);
}
h1 { font-size: var(--font-size-2xl); }
h2 { font-size: var(--font-size-xl); }
h3 { font-size: 1.125rem; }
h4 { font-size: 1rem; }
::selection {
background: rgba(var(--color-primary-rgb), 0.25);
}
/* LuCI injects <input type="submit" class="hidden"> at the top of every
CBI form. Without this rule the input renders as an unstyled browser
button (seen in PassWall, OpenAppFilter, etc). Both bootstrap and argon
themes ship this utility rule. */
.hidden {
display: none;
}
+553
View File
@@ -0,0 +1,553 @@
/* ==========================================================================
Page Fixes — LuCI-specific overrides and quirks
========================================================================== */
/* LuCI wraps everything in #maincontent */
#maincontent {
padding: 0;
}
/* ---- Interface boxes (general) ---- */
.ifacebox {
.glass-effect();
display: inline-flex;
flex-direction: column;
border-radius: var(--radius-md);
padding: 0;
margin-bottom: var(--space-md);
line-height: 1.25;
overflow: visible;
min-width: 100px;
}
.ifacebox-head {
font-weight: var(--font-weight-semibold);
padding: var(--space-sm) var(--space-lg);
margin: 0;
border-bottom: 0.5px solid var(--color-separator);
/* Zone-colored header — tinted glass instead of opaque */
&[style*="background-color"] {
background-color: rgba(var(--zone-color-rgb), 0.50) !important;
border-radius: var(--radius-md) var(--radius-md) 0 0;
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
border-bottom: 0.5px solid rgba(var(--zone-color-rgb), 0.20);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.20);
}
&.active {
background: linear-gradient(
135deg,
rgba(var(--color-primary-rgb), 0.75) 0%,
rgba(var(--color-primary-rgb), 0.60) 50%,
rgba(var(--color-primary-rgb), 0.70) 100%
);
color: var(--color-text-inverse);
padding: var(--space-sm) var(--space-lg);
border-bottom: none;
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.20),
inset 0 0 6px rgba(255, 255, 255, 0.08);
}
}
.ifacebox-body {
line-height: 1.5;
font-size: var(--font-size-sm);
padding: var(--space-sm) var(--space-lg) var(--space-lg);
/* L.itemlist output — key-value pairs */
> span {
display: block;
padding: var(--space-xs) 0;
> .nowrap {
display: inline-block;
margin-right: var(--space-md);
margin-bottom: 2px;
> strong {
color: var(--color-text-secondary);
font-weight: var(--font-weight-medium);
}
}
}
/* Device badge row */
> div {
margin-top: var(--space-sm);
}
}
/* ---- Port status grid (29_ports.js) ---- */
div[style*="display:grid;grid-template-columns:repeat"] {
gap: var(--space-md) !important;
margin-bottom: var(--space-lg) !important;
> .ifacebox {
margin: 0 !important;
padding: 0 !important;
text-align: center;
border-radius: var(--radius-md) !important;
/* Glass-ui card pattern */
background-image: linear-gradient(
135deg,
rgba(255, 255, 255, 0.15) 0%,
rgba(255, 255, 255, 0.12) 25%,
rgba(240, 248, 255, 0.13) 50%,
rgba(255, 255, 255, 0.11) 75%,
rgba(230, 240, 255, 0.12) 100%
) !important;
background-color: transparent !important;
backdrop-filter: blur(10px) saturate(180%) !important;
-webkit-backdrop-filter: blur(10px) saturate(180%) !important;
border: 0.5px solid rgba(255, 255, 255, 0.12) !important;
box-shadow:
0 4px 16px rgba(0, 0, 0, 0.08),
0 1px 4px rgba(0, 0, 0, 0.04),
0 0 0 0.5px rgba(255, 255, 255, 0.08) inset,
0 0 12px rgba(255, 255, 255, 0.10) inset !important;
> .ifacebox-head {
padding: var(--space-xs) var(--space-sm);
font-size: var(--font-size-sm);
font-weight: var(--font-weight-semibold);
margin-bottom: 0;
}
> .ifacebox-body {
padding: var(--space-xs) var(--space-sm);
font-size: var(--font-size-sm);
line-height: 1.3;
img {
width: 28px;
height: 28px;
margin: 2px auto;
}
}
/* Zone color bar */
> .ifacebox-head.cbi-tooltip-container {
padding: 0;
border-bottom: none;
.zonebadge {
border-radius: 0;
padding: 0;
}
}
}
}
/* ---- Network status table (30_network.js) ---- */
.network-status-table {
display: flex;
flex-wrap: wrap;
gap: var(--space-md);
.ifacebox {
flex: 1 1 300px;
margin: 0;
}
.ifacebox-body {
display: flex;
flex-direction: column;
gap: var(--space-xs);
> div {
display: flex;
flex-wrap: wrap;
gap: var(--space-sm);
}
.ifacebadge {
flex: 1 1 auto;
min-width: 200px;
> span {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
}
/* ---- Interface badges ---- */
.ifacebadge {
display: inline-flex;
align-items: center;
gap: var(--space-xs);
padding: 2px var(--space-sm);
margin-right: 0.4em;
min-width: max-content;
background: rgba(255, 255, 255, 0.40);
backdrop-filter: blur(8px) saturate(180%);
-webkit-backdrop-filter: blur(8px) saturate(180%);
border: 0.5px solid rgba(255, 255, 255, 0.20);
border-radius: var(--radius-sm);
font-size: var(--font-size-sm);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.30),
inset 0 0 4px rgba(255, 255, 255, 0.08);
img {
width: 16px;
height: 16px;
}
}
/* Zone badges */
.zonebadge {
display: inline-block;
padding: 2px var(--space-sm);
border-radius: var(--radius-sm);
font-size: var(--font-size-sm);
font-weight: var(--font-weight-medium);
border: 0.5px solid rgba(255, 255, 255, 0.15);
backdrop-filter: blur(6px) saturate(160%);
-webkit-backdrop-filter: blur(6px) saturate(160%);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.20),
inset 0 0 4px rgba(255, 255, 255, 0.06);
}
.zonebadge .ifacebadge {
margin: 1px 2px;
padding: 2px 4px;
}
/* ---- Tooltips ---- */
.cbi-tooltip-container {
position: relative;
}
.cbi-tooltip {
display: none;
position: absolute;
z-index: var(--z-toast);
left: 0;
bottom: 100%;
margin-bottom: var(--space-xs);
.glass-effect();
border-radius: var(--radius-sm);
padding: var(--space-sm) var(--space-md);
font-size: var(--font-size-sm);
max-width: 300px;
white-space: normal;
line-height: 1.5;
&.left {
left: auto;
right: 0;
}
}
.cbi-tooltip-container:hover > .cbi-tooltip {
display: block;
}
/* System log */
#syslog {
font-family: var(--font-mono);
font-size: var(--font-size-sm);
background: rgba(0, 0, 0, 0.04);
border-radius: var(--radius-md);
padding: var(--space-lg);
overflow-y: hidden;
width: 100%;
white-space: pre-wrap;
word-break: break-all;
}
/* Terminal / command output */
pre {
background: rgba(0, 0, 0, 0.04);
border-radius: var(--radius-md);
padding: var(--space-lg);
overflow-x: auto;
font-family: var(--font-mono);
font-size: var(--font-size-sm);
}
/* Flatten pre inside modals — avoid box-in-box */
.modal pre {
background: none;
border: none;
box-shadow: none;
border-radius: 0;
padding: var(--space-sm) 0;
}
/* Native progress element (package manager, etc.) */
progress {
-webkit-appearance: none;
appearance: none;
width: 100%;
height: 8px;
border: none;
border-radius: var(--radius-full);
overflow: hidden;
background: rgba(0, 0, 0, 0.06);
&::-webkit-progress-bar {
background: rgba(0, 0, 0, 0.06);
border-radius: var(--radius-full);
}
&::-webkit-progress-value {
background: linear-gradient(
135deg,
rgba(var(--color-primary-rgb), 0.75) 0%,
rgba(var(--color-primary-rgb), 0.60) 50%,
rgba(var(--color-primary-rgb), 0.70) 100%
);
border-radius: var(--radius-full);
}
&::-moz-progress-bar {
background: linear-gradient(
135deg,
rgba(var(--color-primary-rgb), 0.75) 0%,
rgba(var(--color-primary-rgb), 0.60) 50%,
rgba(var(--color-primary-rgb), 0.70) 100%
);
border-radius: var(--radius-full);
}
}
/* ACL/UBUS error page styling */
#error-message {
text-align: center;
padding: var(--space-3xl);
color: var(--color-text-secondary);
}
/* LuCI diagnostics ping/traceroute output */
#diag-rc-output {
border-radius: var(--radius-md);
padding: var(--space-lg);
background-image: linear-gradient(
135deg,
rgba(255, 255, 255, 0.15) 0%,
rgba(255, 255, 255, 0.12) 25%,
rgba(240, 248, 255, 0.13) 50%,
rgba(255, 255, 255, 0.11) 75%,
rgba(230, 240, 255, 0.12) 100%
);
background-color: transparent;
backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
-webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
border: 0.5px solid rgba(255, 255, 255, 0.12);
box-shadow:
0 2px 8px rgba(0, 0, 0, 0.06),
0 1px 2px rgba(0, 0, 0, 0.03),
inset 0 1px 0 rgba(255, 255, 255, 0.30),
inset 0 0 6px rgba(255, 255, 255, 0.08);
}
/* File upload */
.cbi-filebrowser {
border-radius: var(--radius-md);
padding: var(--space-lg);
background-image: linear-gradient(
135deg,
rgba(255, 255, 255, 0.15) 0%,
rgba(255, 255, 255, 0.12) 25%,
rgba(240, 248, 255, 0.13) 50%,
rgba(255, 255, 255, 0.11) 75%,
rgba(230, 240, 255, 0.12) 100%
);
background-color: transparent;
backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
-webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
border: 0.5px solid rgba(255, 255, 255, 0.12);
box-shadow:
0 2px 8px rgba(0, 0, 0, 0.06),
0 1px 2px rgba(0, 0, 0, 0.03),
inset 0 1px 0 rgba(255, 255, 255, 0.30),
inset 0 0 6px rgba(255, 255, 255, 0.08);
}
/* Apply config spinner */
#cbi_apply_overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.25);
z-index: var(--z-overlay);
display: flex;
align-items: center;
justify-content: center;
}
#cbi_apply_overlay .spinning {
width: 40px;
height: 40px;
padding-left: 0 !important;
border: 3px solid var(--color-bg-secondary);
border-top-color: var(--color-primary);
border-radius: 50%;
animation: spin 1s linear infinite;
&::before {
display: none;
}
}
/* ---- Utility classes ---- */
.nowrap {
white-space: nowrap;
}
.left {
text-align: left;
}
.center {
text-align: center;
}
.right {
text-align: right;
}
.hide-xs {
@media (max-width: 640px) {
display: none !important;
}
}
/* ---- Standalone section headings (DHCP, WiFi assoclist) ---- */
#maincontent h3,
#view h3 {
font-size: var(--font-size-lg);
font-weight: var(--font-weight-semibold);
margin: var(--space-xl) 0 var(--space-md);
}
/* ---- Table sort indicators ---- */
.th[data-sort-direction] {
cursor: pointer;
user-select: none;
&::after {
content: '';
display: inline-block;
width: 0;
height: 0;
margin-left: var(--space-xs);
vertical-align: middle;
border-left: 4px solid transparent;
border-right: 4px solid transparent;
}
&[data-sort-direction="asc"]::after {
border-bottom: 5px solid var(--color-text-secondary);
}
&[data-sort-direction="desc"]::after {
border-top: 5px solid var(--color-text-secondary);
}
}
.th[data-sortable-row] {
cursor: pointer;
}
/* ---- Table placeholder (empty state) ---- */
.tr.placeholder .td {
text-align: center;
padding: var(--space-2xl) var(--space-lg);
color: var(--color-text-tertiary);
font-style: italic;
}
/* ---- Software / Package Manager page ---- */
[data-page="admin-system-opkg"],
[data-page="admin-system-package-manager"] {
/* Action buttons — glass pill style */
div.btn {
display: inline-flex;
padding: var(--space-sm) var(--space-lg);
}
/* Override opkg.js inline CSS for controls layout */
.controls {
display: flex !important;
flex-wrap: wrap !important;
justify-content: flex-start !important;
gap: var(--space-md) var(--space-lg) !important;
margin: 0 0 var(--space-lg) 0 !important;
}
/* All control sections — override inline flex: 1 1 33% */
.controls > div {
padding: 0 !important;
white-space: normal !important;
display: flex !important;
flex-wrap: wrap !important;
align-items: flex-end !important;
}
/* Disk space — full width row */
.controls > div:first-child {
flex: 1 1 100% !important;
}
/* Filter — share row, grow equally */
.controls > div:nth-child(2) {
flex: 1 1 200px !important;
}
/* Download / install — share row, grow equally */
.controls > div:nth-child(3) {
flex: 1 1 280px !important;
}
/* Actions — own row */
.controls > div:nth-child(4) {
flex: 1 1 100% !important;
}
/* Translation filter — own row */
.controls > div:nth-child(5) {
flex: 1 1 100% !important;
}
/* Labels — block above their control group */
.controls > div > label {
flex-basis: 100% !important;
min-width: 0 !important;
margin-bottom: var(--space-xs) !important;
font-weight: var(--font-weight-medium) !important;
font-size: var(--font-size-sm) !important;
color: var(--color-text-secondary) !important;
}
/* Control groups — input + button inline */
.controls .control-group {
display: flex !important;
gap: var(--space-sm) !important;
flex: 1 1 auto !important;
align-items: center !important;
}
.controls .control-group input[type="text"] {
flex: 1 1 auto !important;
min-width: 120px !important;
width: auto !important;
}
/* Action buttons — inline row with gap */
.controls > div:nth-child(4) > .control-group {
gap: var(--space-sm) !important;
}
}
+91
View File
@@ -0,0 +1,91 @@
/* ==========================================================================
Responsive — Media queries for tablet & mobile
========================================================================== */
/* Tablet: sidebar overlay */
@media (max-width: 1024px) {
#sidebar {
transform: translateX(calc(-100% - var(--sidebar-gap)));
&.open {
transform: translateX(0);
}
}
#header {
left: 0;
}
#header-sub {
left: 0;
max-width: calc(100vw - var(--sidebar-gap));
}
#content-wrap {
margin-left: 0;
}
.glass-footer {
margin-left: 0;
}
.menu-toggle {
display: block;
}
.sidebar-overlay.active {
display: block;
}
}
/* Hide status indicators on small screens */
@media (max-width: 768px) {
#status-indicators {
display: none !important;
}
}
/* Mobile: tighter spacing */
@media (max-width: 640px) {
:root {
--content-padding: 16px;
--sidebar-width: 280px;
}
.cbi-value {
flex-direction: column;
}
.cbi-value-title {
flex: none;
padding-right: 0;
padding-bottom: var(--space-xs);
}
.cbi-page-actions {
flex-direction: column;
.cbi-button {
width: 100%;
}
}
.login-card {
padding: var(--space-2xl) var(--space-xl);
}
.cbi-tabmenu {
overflow-x: auto;
flex-wrap: nowrap;
li a {
white-space: nowrap;
}
}
table.cbi-section-table,
.table {
display: block;
overflow-x: auto;
}
}
+160
View File
@@ -0,0 +1,160 @@
/* ==========================================================================
Login Page (sysauth) — luci-theme-glass
========================================================================== */
.login-wrap {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
padding: var(--space-xl);
}
.login-card {
/* True frosted glass — translucent, not white box */
background-image: linear-gradient(
160deg,
rgba(255, 255, 255, 0.25) 0%,
rgba(255, 255, 255, 0.20) 25%,
rgba(245, 250, 255, 0.22) 50%,
rgba(255, 255, 255, 0.18) 75%,
rgba(240, 248, 255, 0.21) 100%
);
background-color: rgba(255, 255, 255, 0.55);
backdrop-filter: blur(30px) saturate(var(--glass-saturate));
-webkit-backdrop-filter: blur(30px) saturate(var(--glass-saturate));
border: 0.5px solid rgba(255, 255, 255, 0.35);
box-shadow:
0 8px 40px rgba(0, 0, 0, 0.10),
0 2px 8px rgba(0, 0, 0, 0.05),
inset 0 1px 0 rgba(255, 255, 255, 0.50),
inset 0 0 16px rgba(255, 255, 255, 0.15);
border-radius: var(--radius-xl);
padding: var(--space-3xl) var(--space-2xl);
width: 100%;
max-width: 380px;
position: relative;
text-align: center;
}
.login-logo {
width: 64px;
height: 64px;
margin: 0 auto var(--space-lg);
}
.login-title {
font-size: var(--font-size-xl);
font-weight: var(--font-weight-bold);
margin-bottom: var(--space-xs);
color: var(--color-text);
}
.login-subtitle {
font-size: var(--font-size-sm);
color: var(--color-text-secondary);
margin-bottom: var(--space-sm);
}
.login-version {
font-size: var(--font-size-sm);
color: var(--color-text-tertiary);
margin-bottom: var(--space-2xl);
}
.login-form {
text-align: left;
.login-field {
margin-bottom: var(--space-lg);
label {
display: block;
font-size: var(--font-size-sm);
font-weight: var(--font-weight-medium);
color: var(--color-text-secondary);
margin-bottom: var(--space-xs);
}
input {
width: 100%;
max-width: none;
padding: var(--space-md) var(--space-lg);
background: rgba(255, 255, 255, 0.30);
border: 0.5px solid rgba(255, 255, 255, 0.35);
border-radius: var(--radius-md);
font-size: var(--font-size-base);
color: var(--color-text);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.25),
inset 0 0 4px rgba(255, 255, 255, 0.08);
transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
&:focus {
outline: none;
border-color: var(--color-primary);
box-shadow:
0 0 0 3px rgba(var(--color-primary-rgb), 0.15),
inset 0 1px 0 rgba(255, 255, 255, 0.25);
}
&::placeholder {
color: var(--color-text-tertiary);
}
}
}
}
.login-btn {
width: 100%;
padding: var(--space-md) var(--space-lg);
/* Glass button — glass-ui .glass-bg pattern */
background-image: linear-gradient(
135deg,
rgba(255, 255, 255, 0.15) 0%,
rgba(255, 255, 255, 0.12) 25%,
rgba(240, 248, 255, 0.13) 50%,
rgba(255, 255, 255, 0.11) 75%,
rgba(230, 240, 255, 0.12) 100%
);
background-color: transparent;
backdrop-filter: blur(var(--glass-blur)) saturate(180%);
-webkit-backdrop-filter: blur(var(--glass-blur)) saturate(180%);
border: 0.5px solid rgba(255, 255, 255, 0.12);
box-shadow:
0 4px 16px rgba(0, 0, 0, 0.08),
0 1px 4px rgba(0, 0, 0, 0.04),
inset 0 0 0.5px rgba(255, 255, 255, 0.08),
inset 0 0 12px rgba(255, 255, 255, 0.10);
color: var(--color-text);
border-radius: var(--radius-md);
font-size: var(--font-size-base);
font-weight: var(--font-weight-semibold);
cursor: pointer;
transition: all var(--transition-fast);
&:hover {
opacity: 0.90;
}
&:active {
transform: scale(0.98);
opacity: 0.80;
box-shadow:
inset 0 2px 4px rgba(0, 0, 0, 0.15),
inset 0 1px 2px rgba(0, 0, 0, 0.10);
}
}
.login-error {
background: rgba(255, 59, 48, 0.10);
border: 1px solid rgba(255, 59, 48, 0.30);
color: var(--color-danger);
padding: var(--space-md) var(--space-lg);
border-radius: var(--radius-md);
font-size: var(--font-size-sm);
margin-bottom: var(--space-lg);
text-align: center;
}
+99
View File
@@ -0,0 +1,99 @@
/* ==========================================================================
Design Tokens — luci-theme-glass
All CSS custom properties live here for easy theming.
========================================================================== */
:root {
/* ---- Typography ---- */
--font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue",
"Segoe UI", Roboto, "Noto Sans", sans-serif;
--font-mono: "SF Mono", SFMono-Regular, ui-monospace, Menlo, Consolas,
"Liberation Mono", monospace;
--font-size-base: 0.875rem;
--font-size-sm: 0.8125rem;
--font-size-lg: 1rem;
--font-size-xl: 1.25rem;
--font-size-2xl: 1.75rem;
--line-height: 1.5;
--font-weight-normal: 400;
--font-weight-medium: 500;
--font-weight-semibold: 600;
--font-weight-bold: 700;
/* ---- Colors — Light mode ---- */
--color-primary: #007AFF;
--color-primary-hover: #0066d6;
--color-primary-active: #004fad;
--color-primary-rgb: 0, 122, 255;
--color-success: #34C759;
--color-warning: #FF9500;
--color-danger: #FF3B30;
--color-info: #5AC8FA;
--color-text: #1d1d1f;
--color-text-secondary: #6e6e73;
--color-text-tertiary: #aeaeb2;
--color-text-inverse: #ffffff;
--color-bg: #f5f5f7;
--color-bg-elevated: #ffffff;
--color-bg-secondary: #e8e8ed;
--color-border: rgba(0, 0, 0, 0.08);
--color-border-strong: rgba(0, 0, 0, 0.16);
--color-separator: rgba(60, 60, 67, 0.12);
/* ---- Glassmorphism ---- */
--glass-blur: 20px;
--glass-saturate: 180%;
--glass-bg: rgba(255, 255, 255, 0.72);
--glass-bg-hover: rgba(255, 255, 255, 0.82);
--glass-bg-strong: rgba(255, 255, 255, 0.85);
--glass-border: rgba(255, 255, 255, 0.45);
--glass-shadow: 0 2px 16px rgba(0, 0, 0, 0.06),
0 0 1px rgba(0, 0, 0, 0.08);
--glass-shadow-lg: 0 8px 40px rgba(0, 0, 0, 0.10),
0 0 1px rgba(0, 0, 0, 0.06);
/* ---- Layout ---- */
--sidebar-width: 260px;
--sidebar-collapsed-width: 64px;
--sidebar-gap: 10px;
--header-height: 56px;
--content-max-width: none;
--content-padding: 24px;
/* ---- Radius ---- */
--radius-sm: 6px;
--radius-md: 10px;
--radius-lg: 14px;
--radius-xl: 20px;
--radius-full: 9999px;
/* ---- Spacing ---- */
--space-xs: 4px;
--space-sm: 8px;
--space-md: 12px;
--space-lg: 16px;
--space-xl: 24px;
--space-2xl: 32px;
--space-3xl: 48px;
/* ---- Transitions ---- */
--transition-fast: 0.15s ease;
--transition-normal: 0.25s ease;
--transition-slow: 0.4s cubic-bezier(0.16, 1, 0.3, 1);
/* ---- Z-index ---- */
--z-dropdown: 100;
--z-sticky: 200;
--z-sidebar: 300;
--z-header: 400;
--z-overlay: 500;
--z-modal: 600;
--z-toast: 700;
/* ---- Background ---- */
--bg-gradient: linear-gradient(135deg, #b8c4d0 0%, #d5dce5 50%, #ddd5cc 100%);
}
+209
View File
@@ -0,0 +1,209 @@
msgid ""
msgstr ""
"Language: de\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
#: htdocs/luci-static/resources/view/system/glass.js:52
msgid "Accent Colors"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:72
msgid "Accent color used for active elements, links, and buttons in dark mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:56
msgid ""
"Accent color used for active elements, links, and buttons in light mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:128
msgid "Active"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:33
msgid "Auto (follow system)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:108
msgid "Backdrop blur radius for glass panels in dark mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:92
msgid ""
"Backdrop blur radius for glass panels. Higher values create a more frosted "
"appearance."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:120
msgid "Background"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:98
msgid ""
"Background opacity of glass panels (0 = fully transparent, 1 = fully opaque)."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:114
msgid ""
"Background opacity of glass panels in dark mode (0 = fully transparent, 1 = "
"fully opaque)."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:43
msgid "Base font size"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:91
#: htdocs/luci-static/resources/view/system/glass.js:107
msgid "Blur intensity (px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:25
msgid ""
"Configure the appearance of the Glass theme. Changes take effect after "
"saving and refreshing the page."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:32
msgid ""
"Controls the overall appearance. \"Normal\" follows the system preference."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:123
msgid "Current background"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:35
msgid "Dark"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:48
msgid "Extra Large (18px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:28
msgid "General"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:104
msgid "Glass Effects — Dark Mode"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:88
msgid "Glass Effects — Light Mode"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:24
msgid "Glass Theme"
msgstr ""
#: root/usr/share/luci/menu.d/luci-theme-glass.json:3
msgid "Glass Theme Config"
msgstr ""
#: ucode/template/themes/glass/header.ut:204
msgid "Go to password configuration..."
msgstr ""
#: root/usr/share/rpcd/acl.d/luci-theme-glass.json:3
msgid "Grant access for luci-theme-glass"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:38
msgid "Header status bar"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:111
msgid "Invalid username and/or password! Please try again."
msgstr ""
#: ucode/template/themes/glass/header.ut:211
msgid "JavaScript required!"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:47
msgid "Large (16px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:34
msgid "Light"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:129
msgid "Log in"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:51
msgid "Login"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:131
msgid ""
"No background set. Upload an image or video named \"bg\" (e.g. bg.jpg, "
"bg.png, bg.mp4) to /www/luci-static/glass/background/ via SCP."
msgstr ""
#: ucode/template/themes/glass/header.ut:201
msgid "No password set!"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:46
msgid "Normal (14px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:97
#: htdocs/luci-static/resources/view/system/glass.js:113
msgid "Panel transparency"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:124
msgid "Password"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:71
msgid "Primary color (dark mode)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:55
msgid "Primary color (light mode)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:44
msgid ""
"Scales all text in the theme. Larger values improve readability on high-DPI "
"displays."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:39
msgid ""
"Show live system stats (CPU, RAM, network, uptime) in the header. Disable to "
"reduce resource usage on low-end devices."
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:106
msgid "Sign in to continue"
msgstr "Zum Fortfahren anmelden"
#: htdocs/luci-static/resources/view/system/glass.js:45
msgid "Small (13px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:31
msgid "Theme mode"
msgstr ""
#: ucode/template/themes/glass/header.ut:202
msgid ""
"There is no password set on this router. Please configure a root password to "
"protect the web interface."
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:117
msgid "Username"
msgstr ""
#: ucode/template/themes/glass/header.ut:212
msgid ""
"You must enable JavaScript in your browser or LuCI will not work properly."
msgstr ""
+242
View File
@@ -0,0 +1,242 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Poedit 3.8\n"
#: htdocs/luci-static/resources/view/system/glass.js:52
msgid "Accent Colors"
msgstr "Colores de acento"
#: htdocs/luci-static/resources/view/system/glass.js:72
msgid "Accent color used for active elements, links, and buttons in dark mode."
msgstr ""
"Color de acento utilizado para elementos activos, enlaces y botones en el "
"modo oscuro."
#: htdocs/luci-static/resources/view/system/glass.js:56
msgid ""
"Accent color used for active elements, links, and buttons in light mode."
msgstr ""
"Color de acento utilizado para elementos activos, enlaces y botones en el "
"modo claro."
#: htdocs/luci-static/resources/view/system/glass.js:128
msgid "Active"
msgstr "Activo"
#: htdocs/luci-static/resources/view/system/glass.js:33
msgid "Auto (follow system)"
msgstr "Automático (seguir el del sistema)"
#: htdocs/luci-static/resources/view/system/glass.js:108
msgid "Backdrop blur radius for glass panels in dark mode."
msgstr "Radio de desenfoque del fondo para paneles de cristal en modo oscuro."
#: htdocs/luci-static/resources/view/system/glass.js:92
msgid ""
"Backdrop blur radius for glass panels. Higher values create a more frosted "
"appearance."
msgstr ""
"Radio de desenfoque del fondo para paneles de cristal. Los valores más altos "
"crean una apariencia más esmerilada."
#: htdocs/luci-static/resources/view/system/glass.js:120
msgid "Background"
msgstr "Fondo"
#: htdocs/luci-static/resources/view/system/glass.js:98
msgid ""
"Background opacity of glass panels (0 = fully transparent, 1 = fully opaque)."
msgstr ""
"Opacidad de fondo de los paneles de cristal (0 = totalmente transparente, 1 "
"= totalmente opaco)."
#: htdocs/luci-static/resources/view/system/glass.js:114
msgid ""
"Background opacity of glass panels in dark mode (0 = fully transparent, 1 = "
"fully opaque)."
msgstr ""
"Opacidad de fondo de los paneles de cristal en modo oscuro (0 = totalmente "
"transparente, 1 = totalmente opaco)."
#: htdocs/luci-static/resources/view/system/glass.js:43
msgid "Base font size"
msgstr "Tamaño de fuente base"
#: htdocs/luci-static/resources/view/system/glass.js:91
#: htdocs/luci-static/resources/view/system/glass.js:107
msgid "Blur intensity (px)"
msgstr "Intensidad del desenfoque (px)"
#: htdocs/luci-static/resources/view/system/glass.js:25
msgid ""
"Configure the appearance of the Glass theme. Changes take effect after "
"saving and refreshing the page."
msgstr ""
"Configure la apariencia del tema Glass. Los cambios surtirán efecto después "
"de guardar y actualizar la página."
#: htdocs/luci-static/resources/view/system/glass.js:32
msgid ""
"Controls the overall appearance. \"Normal\" follows the system preference."
msgstr ""
"Controla la apariencia general. La opción «Normal» respeta la preferencia "
"del sistema."
#: htdocs/luci-static/resources/view/system/glass.js:123
msgid "Current background"
msgstr "Fondo actual"
#: htdocs/luci-static/resources/view/system/glass.js:35
msgid "Dark"
msgstr "Oscuro"
#: htdocs/luci-static/resources/view/system/glass.js:48
msgid "Extra Large (18px)"
msgstr "Extra grande (18px)"
#: htdocs/luci-static/resources/view/system/glass.js:28
msgid "General"
msgstr "General"
#: htdocs/luci-static/resources/view/system/glass.js:104
msgid "Glass Effects — Dark Mode"
msgstr "Efectos de vidrio - Modo oscuro"
#: htdocs/luci-static/resources/view/system/glass.js:88
msgid "Glass Effects — Light Mode"
msgstr "Efectos de vidrio - Modo claro"
#: htdocs/luci-static/resources/view/system/glass.js:24
msgid "Glass Theme"
msgstr "Tema Glass"
#: root/usr/share/luci/menu.d/luci-theme-glass.json:3
msgid "Glass Theme Config"
msgstr "Configuración de Glass"
#: ucode/template/themes/glass/header.ut:204
msgid "Go to password configuration..."
msgstr "Ir a la configuración de contraseñas..."
#: root/usr/share/rpcd/acl.d/luci-theme-glass.json:3
msgid "Grant access for luci-theme-glass"
msgstr "Conceder acceso para luci-theme-glass"
#: htdocs/luci-static/resources/view/system/glass.js:38
msgid "Header status bar"
msgstr "Barra de estado del encabezado"
#: ucode/template/themes/glass/sysauth.ut:111
msgid "Invalid username and/or password! Please try again."
msgstr "Nombre de usuario y/o contraseña incorrectos. Inténtelo de nuevo."
#: ucode/template/themes/glass/header.ut:211
msgid "JavaScript required!"
msgstr "¡Se requiere JavaScript!"
#: htdocs/luci-static/resources/view/system/glass.js:47
msgid "Large (16px)"
msgstr "Grande (16px)"
#: htdocs/luci-static/resources/view/system/glass.js:34
msgid "Light"
msgstr "Claro"
#: ucode/template/themes/glass/sysauth.ut:129
msgid "Log in"
msgstr "Iniciar sesión"
#: ucode/template/themes/glass/sysauth.ut:51
msgid "Login"
msgstr "Acceso"
#: htdocs/luci-static/resources/view/system/glass.js:131
msgid ""
"No background set. Upload an image or video named \"bg\" (e.g. bg.jpg, "
"bg.png, bg.mp4) to /www/luci-static/glass/background/ via SCP."
msgstr ""
"No se ha configurado ningún fondo. Cargue una imagen o video llamado \"bg\" "
"(por ejemplo, bg.jpg, bg.png, bg.mp4) a /www/luci-static/glass/background/ a "
"través de SCP."
#: ucode/template/themes/glass/header.ut:201
msgid "No password set!"
msgstr "¡No se ha establecido ninguna contraseña!"
#: htdocs/luci-static/resources/view/system/glass.js:46
msgid "Normal (14px)"
msgstr "Normal (14px)"
#: htdocs/luci-static/resources/view/system/glass.js:97
#: htdocs/luci-static/resources/view/system/glass.js:113
msgid "Panel transparency"
msgstr "Transparencia del panel"
#: ucode/template/themes/glass/sysauth.ut:124
msgid "Password"
msgstr "Contraseña"
#: htdocs/luci-static/resources/view/system/glass.js:71
msgid "Primary color (dark mode)"
msgstr "Color principal (modo oscuro)"
#: htdocs/luci-static/resources/view/system/glass.js:55
msgid "Primary color (light mode)"
msgstr "Color principal (modo claro)"
#: htdocs/luci-static/resources/view/system/glass.js:44
msgid ""
"Scales all text in the theme. Larger values improve readability on high-DPI "
"displays."
msgstr ""
"Ajusta el tamaño de todo el texto del tema. Los valores mayores mejoran la "
"legibilidad en pantallas de alta resolución."
#: htdocs/luci-static/resources/view/system/glass.js:39
msgid ""
"Show live system stats (CPU, RAM, network, uptime) in the header. Disable to "
"reduce resource usage on low-end devices."
msgstr ""
"Muestra estadísticas del sistema en tiempo real (CPU, RAM, red, tiempo de "
"actividad) en el encabezado. Desactive para reducir el consumo de recursos "
"en dispositivos de gama baja."
#: ucode/template/themes/glass/sysauth.ut:106
msgid "Sign in to continue"
msgstr "Inicia sesión para continuar"
#: htdocs/luci-static/resources/view/system/glass.js:45
msgid "Small (13px)"
msgstr "Pequeño (13px)"
#: htdocs/luci-static/resources/view/system/glass.js:31
msgid "Theme mode"
msgstr "Modo del tema"
#: ucode/template/themes/glass/header.ut:202
msgid ""
"There is no password set on this router. Please configure a root password to "
"protect the web interface."
msgstr ""
"Este enrutador no tiene contraseña. Configure una contraseña de "
"administrador para proteger la interfaz web."
#: ucode/template/themes/glass/sysauth.ut:117
msgid "Username"
msgstr "Nombre de usuario"
#: ucode/template/themes/glass/header.ut:212
msgid ""
"You must enable JavaScript in your browser or LuCI will not work properly."
msgstr ""
"Debe activar JavaScript en su navegador o LuCI no funcionará correctamente."
+209
View File
@@ -0,0 +1,209 @@
msgid ""
msgstr ""
"Language: fr\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
#: htdocs/luci-static/resources/view/system/glass.js:52
msgid "Accent Colors"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:72
msgid "Accent color used for active elements, links, and buttons in dark mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:56
msgid ""
"Accent color used for active elements, links, and buttons in light mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:128
msgid "Active"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:33
msgid "Auto (follow system)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:108
msgid "Backdrop blur radius for glass panels in dark mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:92
msgid ""
"Backdrop blur radius for glass panels. Higher values create a more frosted "
"appearance."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:120
msgid "Background"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:98
msgid ""
"Background opacity of glass panels (0 = fully transparent, 1 = fully opaque)."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:114
msgid ""
"Background opacity of glass panels in dark mode (0 = fully transparent, 1 = "
"fully opaque)."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:43
msgid "Base font size"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:91
#: htdocs/luci-static/resources/view/system/glass.js:107
msgid "Blur intensity (px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:25
msgid ""
"Configure the appearance of the Glass theme. Changes take effect after "
"saving and refreshing the page."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:32
msgid ""
"Controls the overall appearance. \"Normal\" follows the system preference."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:123
msgid "Current background"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:35
msgid "Dark"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:48
msgid "Extra Large (18px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:28
msgid "General"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:104
msgid "Glass Effects — Dark Mode"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:88
msgid "Glass Effects — Light Mode"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:24
msgid "Glass Theme"
msgstr ""
#: root/usr/share/luci/menu.d/luci-theme-glass.json:3
msgid "Glass Theme Config"
msgstr ""
#: ucode/template/themes/glass/header.ut:204
msgid "Go to password configuration..."
msgstr ""
#: root/usr/share/rpcd/acl.d/luci-theme-glass.json:3
msgid "Grant access for luci-theme-glass"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:38
msgid "Header status bar"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:111
msgid "Invalid username and/or password! Please try again."
msgstr ""
#: ucode/template/themes/glass/header.ut:211
msgid "JavaScript required!"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:47
msgid "Large (16px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:34
msgid "Light"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:129
msgid "Log in"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:51
msgid "Login"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:131
msgid ""
"No background set. Upload an image or video named \"bg\" (e.g. bg.jpg, "
"bg.png, bg.mp4) to /www/luci-static/glass/background/ via SCP."
msgstr ""
#: ucode/template/themes/glass/header.ut:201
msgid "No password set!"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:46
msgid "Normal (14px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:97
#: htdocs/luci-static/resources/view/system/glass.js:113
msgid "Panel transparency"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:124
msgid "Password"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:71
msgid "Primary color (dark mode)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:55
msgid "Primary color (light mode)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:44
msgid ""
"Scales all text in the theme. Larger values improve readability on high-DPI "
"displays."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:39
msgid ""
"Show live system stats (CPU, RAM, network, uptime) in the header. Disable to "
"reduce resource usage on low-end devices."
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:106
msgid "Sign in to continue"
msgstr "Connectez-vous pour continuer"
#: htdocs/luci-static/resources/view/system/glass.js:45
msgid "Small (13px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:31
msgid "Theme mode"
msgstr ""
#: ucode/template/themes/glass/header.ut:202
msgid ""
"There is no password set on this router. Please configure a root password to "
"protect the web interface."
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:117
msgid "Username"
msgstr ""
#: ucode/template/themes/glass/header.ut:212
msgid ""
"You must enable JavaScript in your browser or LuCI will not work properly."
msgstr ""
+209
View File
@@ -0,0 +1,209 @@
msgid ""
msgstr ""
"Language: ja\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: htdocs/luci-static/resources/view/system/glass.js:52
msgid "Accent Colors"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:72
msgid "Accent color used for active elements, links, and buttons in dark mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:56
msgid ""
"Accent color used for active elements, links, and buttons in light mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:128
msgid "Active"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:33
msgid "Auto (follow system)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:108
msgid "Backdrop blur radius for glass panels in dark mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:92
msgid ""
"Backdrop blur radius for glass panels. Higher values create a more frosted "
"appearance."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:120
msgid "Background"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:98
msgid ""
"Background opacity of glass panels (0 = fully transparent, 1 = fully opaque)."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:114
msgid ""
"Background opacity of glass panels in dark mode (0 = fully transparent, 1 = "
"fully opaque)."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:43
msgid "Base font size"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:91
#: htdocs/luci-static/resources/view/system/glass.js:107
msgid "Blur intensity (px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:25
msgid ""
"Configure the appearance of the Glass theme. Changes take effect after "
"saving and refreshing the page."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:32
msgid ""
"Controls the overall appearance. \"Normal\" follows the system preference."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:123
msgid "Current background"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:35
msgid "Dark"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:48
msgid "Extra Large (18px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:28
msgid "General"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:104
msgid "Glass Effects — Dark Mode"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:88
msgid "Glass Effects — Light Mode"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:24
msgid "Glass Theme"
msgstr ""
#: root/usr/share/luci/menu.d/luci-theme-glass.json:3
msgid "Glass Theme Config"
msgstr ""
#: ucode/template/themes/glass/header.ut:204
msgid "Go to password configuration..."
msgstr ""
#: root/usr/share/rpcd/acl.d/luci-theme-glass.json:3
msgid "Grant access for luci-theme-glass"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:38
msgid "Header status bar"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:111
msgid "Invalid username and/or password! Please try again."
msgstr ""
#: ucode/template/themes/glass/header.ut:211
msgid "JavaScript required!"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:47
msgid "Large (16px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:34
msgid "Light"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:129
msgid "Log in"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:51
msgid "Login"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:131
msgid ""
"No background set. Upload an image or video named \"bg\" (e.g. bg.jpg, "
"bg.png, bg.mp4) to /www/luci-static/glass/background/ via SCP."
msgstr ""
#: ucode/template/themes/glass/header.ut:201
msgid "No password set!"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:46
msgid "Normal (14px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:97
#: htdocs/luci-static/resources/view/system/glass.js:113
msgid "Panel transparency"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:124
msgid "Password"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:71
msgid "Primary color (dark mode)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:55
msgid "Primary color (light mode)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:44
msgid ""
"Scales all text in the theme. Larger values improve readability on high-DPI "
"displays."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:39
msgid ""
"Show live system stats (CPU, RAM, network, uptime) in the header. Disable to "
"reduce resource usage on low-end devices."
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:106
msgid "Sign in to continue"
msgstr "続行するにはサインインしてください"
#: htdocs/luci-static/resources/view/system/glass.js:45
msgid "Small (13px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:31
msgid "Theme mode"
msgstr ""
#: ucode/template/themes/glass/header.ut:202
msgid ""
"There is no password set on this router. Please configure a root password to "
"protect the web interface."
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:117
msgid "Username"
msgstr ""
#: ucode/template/themes/glass/header.ut:212
msgid ""
"You must enable JavaScript in your browser or LuCI will not work properly."
msgstr ""
+209
View File
@@ -0,0 +1,209 @@
msgid ""
msgstr ""
"Language: ko\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: htdocs/luci-static/resources/view/system/glass.js:52
msgid "Accent Colors"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:72
msgid "Accent color used for active elements, links, and buttons in dark mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:56
msgid ""
"Accent color used for active elements, links, and buttons in light mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:128
msgid "Active"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:33
msgid "Auto (follow system)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:108
msgid "Backdrop blur radius for glass panels in dark mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:92
msgid ""
"Backdrop blur radius for glass panels. Higher values create a more frosted "
"appearance."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:120
msgid "Background"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:98
msgid ""
"Background opacity of glass panels (0 = fully transparent, 1 = fully opaque)."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:114
msgid ""
"Background opacity of glass panels in dark mode (0 = fully transparent, 1 = "
"fully opaque)."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:43
msgid "Base font size"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:91
#: htdocs/luci-static/resources/view/system/glass.js:107
msgid "Blur intensity (px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:25
msgid ""
"Configure the appearance of the Glass theme. Changes take effect after "
"saving and refreshing the page."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:32
msgid ""
"Controls the overall appearance. \"Normal\" follows the system preference."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:123
msgid "Current background"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:35
msgid "Dark"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:48
msgid "Extra Large (18px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:28
msgid "General"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:104
msgid "Glass Effects — Dark Mode"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:88
msgid "Glass Effects — Light Mode"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:24
msgid "Glass Theme"
msgstr ""
#: root/usr/share/luci/menu.d/luci-theme-glass.json:3
msgid "Glass Theme Config"
msgstr ""
#: ucode/template/themes/glass/header.ut:204
msgid "Go to password configuration..."
msgstr ""
#: root/usr/share/rpcd/acl.d/luci-theme-glass.json:3
msgid "Grant access for luci-theme-glass"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:38
msgid "Header status bar"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:111
msgid "Invalid username and/or password! Please try again."
msgstr ""
#: ucode/template/themes/glass/header.ut:211
msgid "JavaScript required!"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:47
msgid "Large (16px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:34
msgid "Light"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:129
msgid "Log in"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:51
msgid "Login"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:131
msgid ""
"No background set. Upload an image or video named \"bg\" (e.g. bg.jpg, "
"bg.png, bg.mp4) to /www/luci-static/glass/background/ via SCP."
msgstr ""
#: ucode/template/themes/glass/header.ut:201
msgid "No password set!"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:46
msgid "Normal (14px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:97
#: htdocs/luci-static/resources/view/system/glass.js:113
msgid "Panel transparency"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:124
msgid "Password"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:71
msgid "Primary color (dark mode)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:55
msgid "Primary color (light mode)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:44
msgid ""
"Scales all text in the theme. Larger values improve readability on high-DPI "
"displays."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:39
msgid ""
"Show live system stats (CPU, RAM, network, uptime) in the header. Disable to "
"reduce resource usage on low-end devices."
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:106
msgid "Sign in to continue"
msgstr "계속하려면 로그인하세요"
#: htdocs/luci-static/resources/view/system/glass.js:45
msgid "Small (13px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:31
msgid "Theme mode"
msgstr ""
#: ucode/template/themes/glass/header.ut:202
msgid ""
"There is no password set on this router. Please configure a root password to "
"protect the web interface."
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:117
msgid "Username"
msgstr ""
#: ucode/template/themes/glass/header.ut:212
msgid ""
"You must enable JavaScript in your browser or LuCI will not work properly."
msgstr ""
+209
View File
@@ -0,0 +1,209 @@
msgid ""
msgstr ""
"Language: pt_BR\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
#: htdocs/luci-static/resources/view/system/glass.js:52
msgid "Accent Colors"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:72
msgid "Accent color used for active elements, links, and buttons in dark mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:56
msgid ""
"Accent color used for active elements, links, and buttons in light mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:128
msgid "Active"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:33
msgid "Auto (follow system)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:108
msgid "Backdrop blur radius for glass panels in dark mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:92
msgid ""
"Backdrop blur radius for glass panels. Higher values create a more frosted "
"appearance."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:120
msgid "Background"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:98
msgid ""
"Background opacity of glass panels (0 = fully transparent, 1 = fully opaque)."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:114
msgid ""
"Background opacity of glass panels in dark mode (0 = fully transparent, 1 = "
"fully opaque)."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:43
msgid "Base font size"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:91
#: htdocs/luci-static/resources/view/system/glass.js:107
msgid "Blur intensity (px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:25
msgid ""
"Configure the appearance of the Glass theme. Changes take effect after "
"saving and refreshing the page."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:32
msgid ""
"Controls the overall appearance. \"Normal\" follows the system preference."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:123
msgid "Current background"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:35
msgid "Dark"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:48
msgid "Extra Large (18px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:28
msgid "General"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:104
msgid "Glass Effects — Dark Mode"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:88
msgid "Glass Effects — Light Mode"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:24
msgid "Glass Theme"
msgstr ""
#: root/usr/share/luci/menu.d/luci-theme-glass.json:3
msgid "Glass Theme Config"
msgstr ""
#: ucode/template/themes/glass/header.ut:204
msgid "Go to password configuration..."
msgstr ""
#: root/usr/share/rpcd/acl.d/luci-theme-glass.json:3
msgid "Grant access for luci-theme-glass"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:38
msgid "Header status bar"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:111
msgid "Invalid username and/or password! Please try again."
msgstr ""
#: ucode/template/themes/glass/header.ut:211
msgid "JavaScript required!"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:47
msgid "Large (16px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:34
msgid "Light"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:129
msgid "Log in"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:51
msgid "Login"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:131
msgid ""
"No background set. Upload an image or video named \"bg\" (e.g. bg.jpg, "
"bg.png, bg.mp4) to /www/luci-static/glass/background/ via SCP."
msgstr ""
#: ucode/template/themes/glass/header.ut:201
msgid "No password set!"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:46
msgid "Normal (14px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:97
#: htdocs/luci-static/resources/view/system/glass.js:113
msgid "Panel transparency"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:124
msgid "Password"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:71
msgid "Primary color (dark mode)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:55
msgid "Primary color (light mode)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:44
msgid ""
"Scales all text in the theme. Larger values improve readability on high-DPI "
"displays."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:39
msgid ""
"Show live system stats (CPU, RAM, network, uptime) in the header. Disable to "
"reduce resource usage on low-end devices."
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:106
msgid "Sign in to continue"
msgstr "Faça login para continuar"
#: htdocs/luci-static/resources/view/system/glass.js:45
msgid "Small (13px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:31
msgid "Theme mode"
msgstr ""
#: ucode/template/themes/glass/header.ut:202
msgid ""
"There is no password set on this router. Please configure a root password to "
"protect the web interface."
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:117
msgid "Username"
msgstr ""
#: ucode/template/themes/glass/header.ut:212
msgid ""
"You must enable JavaScript in your browser or LuCI will not work properly."
msgstr ""
+209
View File
@@ -0,0 +1,209 @@
msgid ""
msgstr ""
"Language: ru\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
#: htdocs/luci-static/resources/view/system/glass.js:52
msgid "Accent Colors"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:72
msgid "Accent color used for active elements, links, and buttons in dark mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:56
msgid ""
"Accent color used for active elements, links, and buttons in light mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:128
msgid "Active"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:33
msgid "Auto (follow system)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:108
msgid "Backdrop blur radius for glass panels in dark mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:92
msgid ""
"Backdrop blur radius for glass panels. Higher values create a more frosted "
"appearance."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:120
msgid "Background"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:98
msgid ""
"Background opacity of glass panels (0 = fully transparent, 1 = fully opaque)."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:114
msgid ""
"Background opacity of glass panels in dark mode (0 = fully transparent, 1 = "
"fully opaque)."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:43
msgid "Base font size"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:91
#: htdocs/luci-static/resources/view/system/glass.js:107
msgid "Blur intensity (px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:25
msgid ""
"Configure the appearance of the Glass theme. Changes take effect after "
"saving and refreshing the page."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:32
msgid ""
"Controls the overall appearance. \"Normal\" follows the system preference."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:123
msgid "Current background"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:35
msgid "Dark"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:48
msgid "Extra Large (18px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:28
msgid "General"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:104
msgid "Glass Effects — Dark Mode"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:88
msgid "Glass Effects — Light Mode"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:24
msgid "Glass Theme"
msgstr ""
#: root/usr/share/luci/menu.d/luci-theme-glass.json:3
msgid "Glass Theme Config"
msgstr ""
#: ucode/template/themes/glass/header.ut:204
msgid "Go to password configuration..."
msgstr ""
#: root/usr/share/rpcd/acl.d/luci-theme-glass.json:3
msgid "Grant access for luci-theme-glass"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:38
msgid "Header status bar"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:111
msgid "Invalid username and/or password! Please try again."
msgstr ""
#: ucode/template/themes/glass/header.ut:211
msgid "JavaScript required!"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:47
msgid "Large (16px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:34
msgid "Light"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:129
msgid "Log in"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:51
msgid "Login"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:131
msgid ""
"No background set. Upload an image or video named \"bg\" (e.g. bg.jpg, "
"bg.png, bg.mp4) to /www/luci-static/glass/background/ via SCP."
msgstr ""
#: ucode/template/themes/glass/header.ut:201
msgid "No password set!"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:46
msgid "Normal (14px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:97
#: htdocs/luci-static/resources/view/system/glass.js:113
msgid "Panel transparency"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:124
msgid "Password"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:71
msgid "Primary color (dark mode)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:55
msgid "Primary color (light mode)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:44
msgid ""
"Scales all text in the theme. Larger values improve readability on high-DPI "
"displays."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:39
msgid ""
"Show live system stats (CPU, RAM, network, uptime) in the header. Disable to "
"reduce resource usage on low-end devices."
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:106
msgid "Sign in to continue"
msgstr "Войдите для продолжения"
#: htdocs/luci-static/resources/view/system/glass.js:45
msgid "Small (13px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:31
msgid "Theme mode"
msgstr ""
#: ucode/template/themes/glass/header.ut:202
msgid ""
"There is no password set on this router. Please configure a root password to "
"protect the web interface."
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:117
msgid "Username"
msgstr ""
#: ucode/template/themes/glass/header.ut:212
msgid ""
"You must enable JavaScript in your browser or LuCI will not work properly."
msgstr ""
+206
View File
@@ -0,0 +1,206 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
#: htdocs/luci-static/resources/view/system/glass.js:52
msgid "Accent Colors"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:72
msgid "Accent color used for active elements, links, and buttons in dark mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:56
msgid ""
"Accent color used for active elements, links, and buttons in light mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:128
msgid "Active"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:33
msgid "Auto (follow system)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:108
msgid "Backdrop blur radius for glass panels in dark mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:92
msgid ""
"Backdrop blur radius for glass panels. Higher values create a more frosted "
"appearance."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:120
msgid "Background"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:98
msgid ""
"Background opacity of glass panels (0 = fully transparent, 1 = fully opaque)."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:114
msgid ""
"Background opacity of glass panels in dark mode (0 = fully transparent, 1 = "
"fully opaque)."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:43
msgid "Base font size"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:91
#: htdocs/luci-static/resources/view/system/glass.js:107
msgid "Blur intensity (px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:25
msgid ""
"Configure the appearance of the Glass theme. Changes take effect after "
"saving and refreshing the page."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:32
msgid ""
"Controls the overall appearance. \"Normal\" follows the system preference."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:123
msgid "Current background"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:35
msgid "Dark"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:48
msgid "Extra Large (18px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:28
msgid "General"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:104
msgid "Glass Effects — Dark Mode"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:88
msgid "Glass Effects — Light Mode"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:24
msgid "Glass Theme"
msgstr ""
#: root/usr/share/luci/menu.d/luci-theme-glass.json:3
msgid "Glass Theme Config"
msgstr ""
#: ucode/template/themes/glass/header.ut:204
msgid "Go to password configuration..."
msgstr ""
#: root/usr/share/rpcd/acl.d/luci-theme-glass.json:3
msgid "Grant access for luci-theme-glass"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:38
msgid "Header status bar"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:111
msgid "Invalid username and/or password! Please try again."
msgstr ""
#: ucode/template/themes/glass/header.ut:211
msgid "JavaScript required!"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:47
msgid "Large (16px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:34
msgid "Light"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:129
msgid "Log in"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:51
msgid "Login"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:131
msgid ""
"No background set. Upload an image or video named \"bg\" (e.g. bg.jpg, "
"bg.png, bg.mp4) to /www/luci-static/glass/background/ via SCP."
msgstr ""
#: ucode/template/themes/glass/header.ut:201
msgid "No password set!"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:46
msgid "Normal (14px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:97
#: htdocs/luci-static/resources/view/system/glass.js:113
msgid "Panel transparency"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:124
msgid "Password"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:71
msgid "Primary color (dark mode)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:55
msgid "Primary color (light mode)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:44
msgid ""
"Scales all text in the theme. Larger values improve readability on high-DPI "
"displays."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:39
msgid ""
"Show live system stats (CPU, RAM, network, uptime) in the header. Disable to "
"reduce resource usage on low-end devices."
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:106
msgid "Sign in to continue"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:45
msgid "Small (13px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:31
msgid "Theme mode"
msgstr ""
#: ucode/template/themes/glass/header.ut:202
msgid ""
"There is no password set on this router. Please configure a root password to "
"protect the web interface."
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:117
msgid "Username"
msgstr ""
#: ucode/template/themes/glass/header.ut:212
msgid ""
"You must enable JavaScript in your browser or LuCI will not work properly."
msgstr ""
+1
View File
@@ -0,0 +1 @@
zh_Hans
+209
View File
@@ -0,0 +1,209 @@
msgid ""
msgstr ""
"Language: zh_Hans\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: htdocs/luci-static/resources/view/system/glass.js:52
msgid "Accent Colors"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:72
msgid "Accent color used for active elements, links, and buttons in dark mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:56
msgid ""
"Accent color used for active elements, links, and buttons in light mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:128
msgid "Active"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:33
msgid "Auto (follow system)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:108
msgid "Backdrop blur radius for glass panels in dark mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:92
msgid ""
"Backdrop blur radius for glass panels. Higher values create a more frosted "
"appearance."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:120
msgid "Background"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:98
msgid ""
"Background opacity of glass panels (0 = fully transparent, 1 = fully opaque)."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:114
msgid ""
"Background opacity of glass panels in dark mode (0 = fully transparent, 1 = "
"fully opaque)."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:43
msgid "Base font size"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:91
#: htdocs/luci-static/resources/view/system/glass.js:107
msgid "Blur intensity (px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:25
msgid ""
"Configure the appearance of the Glass theme. Changes take effect after "
"saving and refreshing the page."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:32
msgid ""
"Controls the overall appearance. \"Normal\" follows the system preference."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:123
msgid "Current background"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:35
msgid "Dark"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:48
msgid "Extra Large (18px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:28
msgid "General"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:104
msgid "Glass Effects — Dark Mode"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:88
msgid "Glass Effects — Light Mode"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:24
msgid "Glass Theme"
msgstr ""
#: root/usr/share/luci/menu.d/luci-theme-glass.json:3
msgid "Glass Theme Config"
msgstr ""
#: ucode/template/themes/glass/header.ut:204
msgid "Go to password configuration..."
msgstr ""
#: root/usr/share/rpcd/acl.d/luci-theme-glass.json:3
msgid "Grant access for luci-theme-glass"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:38
msgid "Header status bar"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:111
msgid "Invalid username and/or password! Please try again."
msgstr ""
#: ucode/template/themes/glass/header.ut:211
msgid "JavaScript required!"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:47
msgid "Large (16px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:34
msgid "Light"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:129
msgid "Log in"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:51
msgid "Login"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:131
msgid ""
"No background set. Upload an image or video named \"bg\" (e.g. bg.jpg, "
"bg.png, bg.mp4) to /www/luci-static/glass/background/ via SCP."
msgstr ""
#: ucode/template/themes/glass/header.ut:201
msgid "No password set!"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:46
msgid "Normal (14px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:97
#: htdocs/luci-static/resources/view/system/glass.js:113
msgid "Panel transparency"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:124
msgid "Password"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:71
msgid "Primary color (dark mode)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:55
msgid "Primary color (light mode)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:44
msgid ""
"Scales all text in the theme. Larger values improve readability on high-DPI "
"displays."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:39
msgid ""
"Show live system stats (CPU, RAM, network, uptime) in the header. Disable to "
"reduce resource usage on low-end devices."
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:106
msgid "Sign in to continue"
msgstr "登录以继续"
#: htdocs/luci-static/resources/view/system/glass.js:45
msgid "Small (13px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:31
msgid "Theme mode"
msgstr ""
#: ucode/template/themes/glass/header.ut:202
msgid ""
"There is no password set on this router. Please configure a root password to "
"protect the web interface."
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:117
msgid "Username"
msgstr ""
#: ucode/template/themes/glass/header.ut:212
msgid ""
"You must enable JavaScript in your browser or LuCI will not work properly."
msgstr ""
+209
View File
@@ -0,0 +1,209 @@
msgid ""
msgstr ""
"Language: zh_Hant\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: htdocs/luci-static/resources/view/system/glass.js:52
msgid "Accent Colors"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:72
msgid "Accent color used for active elements, links, and buttons in dark mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:56
msgid ""
"Accent color used for active elements, links, and buttons in light mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:128
msgid "Active"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:33
msgid "Auto (follow system)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:108
msgid "Backdrop blur radius for glass panels in dark mode."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:92
msgid ""
"Backdrop blur radius for glass panels. Higher values create a more frosted "
"appearance."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:120
msgid "Background"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:98
msgid ""
"Background opacity of glass panels (0 = fully transparent, 1 = fully opaque)."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:114
msgid ""
"Background opacity of glass panels in dark mode (0 = fully transparent, 1 = "
"fully opaque)."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:43
msgid "Base font size"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:91
#: htdocs/luci-static/resources/view/system/glass.js:107
msgid "Blur intensity (px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:25
msgid ""
"Configure the appearance of the Glass theme. Changes take effect after "
"saving and refreshing the page."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:32
msgid ""
"Controls the overall appearance. \"Normal\" follows the system preference."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:123
msgid "Current background"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:35
msgid "Dark"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:48
msgid "Extra Large (18px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:28
msgid "General"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:104
msgid "Glass Effects — Dark Mode"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:88
msgid "Glass Effects — Light Mode"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:24
msgid "Glass Theme"
msgstr ""
#: root/usr/share/luci/menu.d/luci-theme-glass.json:3
msgid "Glass Theme Config"
msgstr ""
#: ucode/template/themes/glass/header.ut:204
msgid "Go to password configuration..."
msgstr ""
#: root/usr/share/rpcd/acl.d/luci-theme-glass.json:3
msgid "Grant access for luci-theme-glass"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:38
msgid "Header status bar"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:111
msgid "Invalid username and/or password! Please try again."
msgstr ""
#: ucode/template/themes/glass/header.ut:211
msgid "JavaScript required!"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:47
msgid "Large (16px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:34
msgid "Light"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:129
msgid "Log in"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:51
msgid "Login"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:131
msgid ""
"No background set. Upload an image or video named \"bg\" (e.g. bg.jpg, "
"bg.png, bg.mp4) to /www/luci-static/glass/background/ via SCP."
msgstr ""
#: ucode/template/themes/glass/header.ut:201
msgid "No password set!"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:46
msgid "Normal (14px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:97
#: htdocs/luci-static/resources/view/system/glass.js:113
msgid "Panel transparency"
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:124
msgid "Password"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:71
msgid "Primary color (dark mode)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:55
msgid "Primary color (light mode)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:44
msgid ""
"Scales all text in the theme. Larger values improve readability on high-DPI "
"displays."
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:39
msgid ""
"Show live system stats (CPU, RAM, network, uptime) in the header. Disable to "
"reduce resource usage on low-end devices."
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:106
msgid "Sign in to continue"
msgstr "登入以繼續"
#: htdocs/luci-static/resources/view/system/glass.js:45
msgid "Small (13px)"
msgstr ""
#: htdocs/luci-static/resources/view/system/glass.js:31
msgid "Theme mode"
msgstr ""
#: ucode/template/themes/glass/header.ut:202
msgid ""
"There is no password set on this router. Please configure a root password to "
"protect the web interface."
msgstr ""
#: ucode/template/themes/glass/sysauth.ut:117
msgid "Username"
msgstr ""
#: ucode/template/themes/glass/header.ut:212
msgid ""
"You must enable JavaScript in your browser or LuCI will not work properly."
msgstr ""
@@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsUzec0+6lptCFX88129L
y7dDRwWkVL8tBIBwh67C2o54DN2AWgUkmuwnoZa+6UMtHFkyi8GLpw2ISNjiKzJn
GU8G21rg288OIQthhYIWVM3+eQ4J3yMA/r/1JQV80IDZ/awdfPRCjQQoJN96d5Km
gvKZeDp0UjcoD+gUy8S3LzCTNUwwjd9vnEZDTz1d+NckNM4JTTR1d+WFTwSeNAcE
jN/pNPPB/oyiUfyKLYHiDrBZputcnQ2suHC/DIVUSTQNhAyAst9UnUO3Jhv298HE
OrAhUZnwVC9F788Er+9mZAGpcqpPhZ+UDztOoO/aVt56ire/MBGLDkwYVN2W5wCo
QwIDAQAB
-----END PUBLIC KEY-----
+10
View File
@@ -0,0 +1,10 @@
config global 'global'
option mode 'normal'
option primary '#007AFF'
option dark_primary '#0A84FF'
option blur '20'
option transparency '0.72'
option blur_dark '25'
option transparency_dark '0.30'
option status_bar '1'
option font_size '14'
@@ -0,0 +1,2 @@
untrusted comment: luci-theme-glass package signing key public key
RWTvl8Ror3fOoUBhvj1JRuc+0SQ/8vIDJNCPrSXN5UNQJRGizXf/rxX/
+12
View File
@@ -0,0 +1,12 @@
#!/bin/sh
# Always keep Glass in the theme list so it remains selectable in LuCI
uci -q set luci.themes.Glass=/luci-static/glass
# Set as default only on fresh install -- don't stomp user choice on upgrade
[ "$PKG_UPGRADE" = 1 ] || uci -q set luci.main.mediaurlbase=/luci-static/glass
uci -q commit luci
rm -f /tmp/luci-indexcache /tmp/luci-modulecache
exit 0
@@ -0,0 +1,15 @@
{
"admin/system/glass": {
"title": "Glass Theme Config",
"order": 90,
"action": {
"type": "view",
"path": "system/glass"
},
"depends": {
"acl": [
"luci-theme-glass"
]
}
}
}
@@ -0,0 +1,18 @@
{
"luci-theme-glass": {
"description": "Grant access for luci-theme-glass",
"read": {
"uci": [ "glass" ],
"file": {
"/www/luci-static/glass/background/*": [ "list" ]
},
"ubus": {
"network.interface": [ "dump" ],
"network.device": [ "status" ]
}
},
"write": {
"uci": [ "glass" ]
}
}
}
Whitespace-only changes.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

@@ -0,0 +1,185 @@
{# luci-theme-glass — Main page footer template #}
{%
import { readfile, access } from 'fs';
import { cursor } from 'uci';
const glass_version = trim(readfile('/usr/share/ucode/luci/template/themes/glass/version')) ?? '?';
let glass_status_bar = '1';
let _cfg = cursor();
if (access('/etc/config/glass')) {
glass_status_bar = _cfg.get_first('glass', 'global', 'status_bar') ?? '1';
}
%}
{% if (!blank_page): %}
</div>
</div>
</main>
<footer class="glass-footer">
<span>GlassTheme v{{ glass_version }}</span>
<span class="footer-sep">|</span>
<a href="https://github.com/openwrt/luci" target="_blank">{{ version.luciname }} ({{ version.luciversion }})</a>
<span class="footer-sep">|</span>
<a href="{{ version.disturl }}" target="_blank">{{ version.distname }} {{ version.distversion }}</a>
</footer>
<script src="{{ resource }}/luci.js"></script>
<script>
L.require('menu-glass');
{% if (glass_status_bar == '1'): %}
L.require('status-glass');
{% endif %}
if (history.scrollRestoration) history.scrollRestoration = 'manual';
(function() {
var toggle = document.getElementById('menu-toggle');
var sidebar = document.getElementById('sidebar');
var overlay = document.getElementById('sidebar-overlay');
function openSidebar() {
sidebar.classList.add('open');
overlay.classList.add('active');
}
function closeSidebar() {
sidebar.classList.remove('open');
overlay.classList.remove('active');
}
if (toggle) toggle.addEventListener('click', function() {
sidebar.classList.contains('open') ? closeSidebar() : openSidebar();
});
if (overlay) overlay.addEventListener('click', closeSidebar);
})();
/* Theme toggle — auto / light / dark cycle */
(function(){
var btn=document.getElementById('theme-toggle');
if(!btn)return;
var order=['auto','light','dark'];
var labels={auto:'Theme: Auto',light:'Theme: Light',dark:'Theme: Dark'};
var cur=document.documentElement.dataset.theme||'auto';
btn.title=labels[cur];btn.setAttribute('aria-label',labels[cur]);
btn.addEventListener('click',function(){
var cur=document.documentElement.dataset.theme||'auto';
var next=order[(order.indexOf(cur)+1)%3];
document.documentElement.dataset.theme=next;
try{localStorage.setItem('glass-theme',next)}catch(e){}
var d=document.getElementById('dark-styles'),m=document.getElementById('meta-theme-color');
if(next==='dark'){d.media='all';if(m)m.content='#2c2e3a'}
else if(next==='light'){d.media='not all';if(m)m.content='#f5f5f7'}
else{d.media='(prefers-color-scheme: dark)';if(m)m.content=window.matchMedia('(prefers-color-scheme: dark)').matches?'#2c2e3a':'#f5f5f7'}
btn.title=labels[next];btn.setAttribute('aria-label',labels[next]);
});
/* Update theme-color meta when OS changes in auto mode */
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change',function(e){
if(document.documentElement.dataset.theme!=='auto')return;
var m=document.getElementById('meta-theme-color');
if(m)m.content=e.matches?'#2c2e3a':'#f5f5f7';
});
})();
/* Move CBI tabmenus into sub-nav bar; attach descriptions as tooltips */
(function() {
var headerSub = document.getElementById('header-sub');
var headerTitle = document.getElementById('header-title');
var content = document.getElementById('maincontent');
if (!content) return;
function processContent() {
/* Attach page description as tooltip on header title */
if (headerTitle && !headerTitle.title) {
var descr = content.querySelector('.cbi-map-descr');
if (descr && !descr.dataset.moved) {
descr.dataset.moved = '1';
headerTitle.title = descr.textContent.trim();
}
}
/* Move top-level CBI tabmenus into sub-nav bar.
Skip if renderTabMenu already populated header-sub (menu-tree tabs).
Nested tabmenus (e.g. DNS Records sub-tabs inside a tab panel)
stay in-content so they don't get mixed with top-level tabs. */
if (!headerSub) return;
if (headerSub.querySelector('.sub-tab')) return; /* Already has menu-tree tabs */
var allTabmenus = content.querySelectorAll('.cbi-tabmenu');
if (allTabmenus.length === 0) return;
/* Only move the first CBI tabmenu to sub-nav.
Any deeper tabmenus (e.g. DNS Records sub-tabs, dnsmasq section tabs)
stay in-content with glass styling. */
var topTabmenus = [allTabmenus[0]];
if (!topTabmenus[0]) return;
/* Skip rebuild if we're in the middle of a tab click */
if (headerSub._switching) return;
/* Clear existing sub-tabs to prevent duplicates on re-render (Save & Apply) */
headerSub.innerHTML = '';
headerSub.classList.remove('active');
document.body.classList.remove('has-sub-nav');
/* Sliding selector for sub-tabs */
var slider = document.createElement('div');
slider.className = 'tab-slider';
headerSub.appendChild(slider);
topTabmenus.forEach(function(ul) {
var items = ul.querySelectorAll('li');
items.forEach(function(li) {
var a = li.querySelector('a');
if (!a) return;
/* Skip hidden tabs (e.g. DNSSEC when not available) */
if (li.style.display === 'none') return;
var tab = a.cloneNode(true);
tab.className = 'sub-tab' + (li.classList.contains('cbi-tab') ? ' active' : '');
tab.addEventListener('click', function(ev) {
ev.preventDefault();
/* Guard: prevent MutationObserver from rebuilding during tab switch */
headerSub._switching = true;
a.click();
setTimeout(function() { headerSub._switching = false; }, 100);
headerSub.querySelectorAll('.sub-tab').forEach(function(t) {
t.classList.remove('active');
});
tab.classList.add('active');
/* Slide to clicked tab */
slider.style.left = tab.offsetLeft + 'px';
slider.style.width = tab.offsetWidth + 'px';
slider.style.opacity = '1';
});
headerSub.appendChild(tab);
});
ul.style.display = 'none';
});
headerSub.classList.add('active');
document.body.classList.add('has-sub-nav');
/* Position slider on active sub-tab */
requestAnimationFrame(function() {
var active = headerSub.querySelector('.sub-tab.active');
if (active) {
slider.style.transition = 'none';
slider.style.left = active.offsetLeft + 'px';
slider.style.width = active.offsetWidth + 'px';
slider.style.opacity = '1';
requestAnimationFrame(function() {
slider.style.transition = '';
});
}
});
}
processContent();
new MutationObserver(function() {
processContent();
}).observe(content, { childList: true, subtree: true });
})();
</script>
{% endif %}
{% if (js): %}<script>{{ js }}</script>{% endif %}
</body>
</html>
@@ -0,0 +1 @@
{# luci-theme-glass — Login page footer (empty, sysauth.ut is self-contained) #}
@@ -0,0 +1,215 @@
{#
luci-theme-glass — Main page header template
Apple-inspired glassmorphism theme for LuCI
-#}
{%
import { readfile, access } from 'fs';
import { cursor } from 'uci';
import { getuid, getspnam } from 'luci.core';
const glass_version = trim(readfile('/usr/share/ucode/luci/template/themes/glass/version')) ?? '?';
const boardinfo = ubus.call('system', 'board');
const hostname = striptags(boardinfo?.hostname ?? 'OpenWrt');
http.prepare_content('text/html; charset=UTF-8');
/* Read theme config */
let glass_mode = 'normal';
let glass_primary = '#007AFF';
let glass_dark_primary = '#0A84FF';
let glass_blur = '20';
let glass_transparency = '0.72';
let glass_blur_dark = '25';
let glass_transparency_dark = '0.30';
let glass_font_size = '14';
let cfg = cursor();
if (access('/etc/config/glass')) {
glass_mode = cfg.get_first('glass', 'global', 'mode') ?? glass_mode;
glass_primary = cfg.get_first('glass', 'global', 'primary') ?? glass_primary;
glass_dark_primary = cfg.get_first('glass', 'global', 'dark_primary') ?? glass_dark_primary;
glass_blur = cfg.get_first('glass', 'global', 'blur') ?? glass_blur;
glass_transparency = cfg.get_first('glass', 'global', 'transparency') ?? glass_transparency;
glass_blur_dark = cfg.get_first('glass', 'global', 'blur_dark') ?? glass_blur_dark;
glass_transparency_dark = cfg.get_first('glass', 'global', 'transparency_dark') ?? glass_transparency_dark;
glass_font_size = cfg.get_first('glass', 'global', 'font_size') ?? glass_font_size;
}
/* Read dark.css for inline injection */
const dark_css = readfile('/www/luci-static/glass/css/dark.css');
/* Find background media */
let bg_src = null;
let bg_type = 'image';
const bg_dir = '/www/luci-static/glass/background';
const img_exts = ['.jpg', '.jpeg', '.png', '.gif', '.webp'];
const vid_exts = ['.mp4', '.webm'];
for (let ext in img_exts) {
if (access(bg_dir + '/bg' + ext)) {
bg_src = media + '/background/bg' + ext;
break;
}
}
if (!bg_src) {
for (let ext in vid_exts) {
if (access(bg_dir + '/bg' + ext)) {
bg_src = media + '/background/bg' + ext;
bg_type = 'video';
break;
}
}
}
-%}
<!DOCTYPE html>
<html lang="{{ dispatcher.lang }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta name="theme-color" id="meta-theme-color" content="{{ glass_mode == 'dark' ? '#2c2e3a' : '#f5f5f7' }}">
<title>{{ hostname }}{{ node?.title ? ` - ${striptags(node.title)}` : '' }} - LuCI</title>
<link rel="icon" href="{{ media }}/img/glass-logo.svg" type="image/svg+xml">
<link rel="stylesheet" href="{{ media }}/css/cascade.css">
<style id="dark-styles" media="{% if (glass_mode == 'dark'): %}all{% elif (glass_mode == 'light'): %}not all{% else %}(prefers-color-scheme: dark){% endif %}">
{{ dark_css }}
</style>
{% if (access('/etc/config/glass')): %}
<style>
html {
font-size: {{ glass_font_size }}px;
}
:root {
--color-primary: {{ glass_primary }};
--glass-blur: {{ glass_blur }}px;
--glass-bg: rgba(255, 255, 255, {{ glass_transparency }});
}
@media (prefers-color-scheme: dark) {
:root {
--color-primary: {{ glass_dark_primary }};
--glass-blur: {{ glass_blur_dark }}px;
--glass-bg: rgba(38, 38, 42, {{ glass_transparency_dark }});
}
}
[data-theme="dark"] {
--color-primary: {{ glass_dark_primary }};
--glass-blur: {{ glass_blur_dark }}px;
--glass-bg: rgba(38, 38, 42, {{ glass_transparency_dark }});
}
[data-theme="light"] {
--color-primary: {{ glass_primary }};
--glass-blur: {{ glass_blur }}px;
--glass-bg: rgba(255, 255, 255, {{ glass_transparency }});
}
</style>
{% endif %}
<script>
(function(){
var d=document.getElementById('dark-styles'),m=document.getElementById('meta-theme-color'),s;
try{s=localStorage.getItem('glass-theme')}catch(e){}
if(s){
if(s==='dark'){d.media='all';if(m)m.content='#2c2e3a'}
else if(s==='light'){d.media='not all';if(m)m.content='#f5f5f7'}
else{s='auto';d.media='(prefers-color-scheme: dark)';if(m)m.content=window.matchMedia('(prefers-color-scheme: dark)').matches?'#2c2e3a':'#f5f5f7'}
}else{
var media=d.media;
if(media==='all')s='dark';else if(media==='not all')s='light';else{s='auto';if(m)m.content=window.matchMedia('(prefers-color-scheme: dark)').matches?'#2c2e3a':'#f5f5f7'}
}
document.documentElement.dataset.theme=s;
})();
</script>
{% if (node?.css): %}
<link rel="stylesheet" href="{{ resource }}/{{ node.css }}">
{% endif %}
{% if (css): %}
<style>{{ css }}</style>
{% endif %}
<script src="{{ dispatcher.build_url('admin/translations', dispatcher.lang) }}"></script>
<script src="{{ resource }}/cbi.js"></script>
</head>
<body class="lang_{{ dispatcher.lang }}" data-page="{{ entityencode(join('-', ctx.request_path), true) }}">
<div id="bg-wrap">
{% if (bg_src && bg_type == 'video'): %}
<video autoplay muted loop playsinline>
<source src="{{ bg_src }}">
</video>
{% elif (bg_src): %}
<img src="{{ bg_src }}" alt="">
{% endif %}
</div>
{% if (!blank_page): %}
<div class="sidebar-overlay" id="sidebar-overlay"></div>
<aside id="sidebar">
<div class="sidebar-header">
<span class="brand">{{ hostname }}</span>
</div>
<nav class="sidebar-nav" id="sidebar-nav">
</nav>
<div class="sidebar-footer">
<span class="sidebar-version">GlassTheme v{{ glass_version }}</span>
</div>
</aside>
<header id="header">
<button class="menu-toggle" id="menu-toggle" aria-label="Toggle menu">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
<line x1="3" y1="6" x2="21" y2="6"/>
<line x1="3" y1="12" x2="21" y2="12"/>
<line x1="3" y1="18" x2="21" y2="18"/>
</svg>
</button>
<nav id="header-nav">
<span class="header-title" id="header-title"></span>
</nav>
<div id="header-tabs"></div>
<div id="status-indicators"></div>
<div class="header-actions" id="indicators">
<button class="theme-toggle" id="theme-toggle" type="button" title="Theme: Auto" aria-label="Theme: Auto">
<svg class="theme-icon theme-icon-auto" viewBox="0 0 18 18" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<circle cx="9" cy="9" r="7.25"/>
<path d="M9 1.75A7.25 7.25 0 019 16.25" fill="currentColor" stroke="none"/>
</svg>
<svg class="theme-icon theme-icon-light" viewBox="0 0 18 18" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<circle cx="9" cy="9" r="3.5"/>
<line x1="9" y1="1" x2="9" y2="3"/><line x1="9" y1="15" x2="9" y2="17"/>
<line x1="2.87" y1="2.87" x2="4.28" y2="4.28"/><line x1="13.72" y1="13.72" x2="15.13" y2="15.13"/>
<line x1="1" y1="9" x2="3" y2="9"/><line x1="15" y1="9" x2="17" y2="9"/>
<line x1="2.87" y1="15.13" x2="4.28" y2="13.72"/><line x1="13.72" y1="4.28" x2="15.13" y2="2.87"/>
</svg>
<svg class="theme-icon theme-icon-dark" viewBox="0 0 18 18" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<path d="M15.54 9.98a7 7 0 01-8.52-8.52 7.5 7.5 0 108.52 8.52z"/>
</svg>
</button>
</div>
</header>
<nav id="header-sub"></nav>
<main id="content-wrap">
<div id="content">
<div id="maincontent">
{% if (getuid() == 0 && getspnam('root')?.pwdp === ''): %}
<div class="alert-message warning">
<h4>{{ _('No password set!') }}</h4>
<p>{{ _('There is no password set on this router. Please configure a root password to protect the web interface.') }}</p>
{% if (dispatcher.lookup("admin/system/admin")): %}
<div class="right"><a class="btn cbi-button-positive" href="{{ dispatcher.build_url("admin/system/admin") }}">{{ _('Go to password configuration...') }}</a></div>
{% endif %}
</div>
{% endif %}
<noscript>
<div class="alert-message warning">
<h4>{{ _('JavaScript required!') }}</h4>
<p>{{ _('You must enable JavaScript in your browser or LuCI will not work properly.') }}</p>
</div>
</noscript>
{% endif %}
@@ -0,0 +1 @@
{# luci-theme-glass — Login header (not used, sysauth.ut is self-contained) #}
@@ -0,0 +1,160 @@
{# luci-theme-glass — Login page (self-contained, argon-style) #}
{%
import { readfile, access } from 'fs';
import { cursor } from 'uci';
const glass_version = trim(readfile('/usr/share/ucode/luci/template/themes/glass/version')) ?? '?';
const boardinfo = ubus.call('system', 'board');
const hostname = striptags(boardinfo?.hostname ?? 'OpenWrt');
http.prepare_content('text/html; charset=UTF-8');
/* Read theme config */
let glass_mode = 'normal';
let cfg = cursor();
if (access('/etc/config/glass')) {
glass_mode = cfg.get_first('glass', 'global', 'mode') ?? glass_mode;
}
/* Read dark.css */
const dark_css = readfile('/www/luci-static/glass/css/dark.css');
/* Find background media */
let bg_src = null;
let bg_type = 'image';
const bg_dir = '/www/luci-static/glass/background';
const img_exts = ['.jpg', '.jpeg', '.png', '.gif', '.webp'];
const vid_exts = ['.mp4', '.webm'];
for (let ext in img_exts) {
if (access(bg_dir + '/bg' + ext)) {
bg_src = media + '/background/bg' + ext;
break;
}
}
if (!bg_src) {
for (let ext in vid_exts) {
if (access(bg_dir + '/bg' + ext)) {
bg_src = media + '/background/bg' + ext;
bg_type = 'video';
break;
}
}
}
-%}
<!DOCTYPE html>
<html lang="{{ dispatcher.lang }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta name="theme-color" id="meta-theme-color" content="{{ glass_mode == 'dark' ? '#2c2e3a' : '#f5f5f7' }}">
<title>{{ _('Login') }} - {{ hostname }} - LuCI</title>
<link rel="icon" href="{{ media }}/img/glass-logo.svg" type="image/svg+xml">
<link rel="stylesheet" href="{{ media }}/css/cascade.css">
<style id="dark-styles" media="{% if (glass_mode == 'dark'): %}all{% elif (glass_mode == 'light'): %}not all{% else %}(prefers-color-scheme: dark){% endif %}">
{{ dark_css }}
</style>
<script>
(function(){
var d=document.getElementById('dark-styles'),m=document.getElementById('meta-theme-color'),s;
try{s=localStorage.getItem('glass-theme')}catch(e){}
if(s){
if(s==='dark'){d.media='all';if(m)m.content='#2c2e3a'}
else if(s==='light'){d.media='not all';if(m)m.content='#f5f5f7'}
else{s='auto';d.media='(prefers-color-scheme: dark)';if(m)m.content=window.matchMedia('(prefers-color-scheme: dark)').matches?'#2c2e3a':'#f5f5f7'}
}else{
var media=d.media;
if(media==='all')s='dark';else if(media==='not all')s='light';else{s='auto';if(m)m.content=window.matchMedia('(prefers-color-scheme: dark)').matches?'#2c2e3a':'#f5f5f7'}
}
document.documentElement.dataset.theme=s;
})();
</script>
</head>
<body class="lang_{{ dispatcher.lang }}">
<button class="theme-toggle theme-toggle-float" id="theme-toggle" type="button" title="Theme: Auto" aria-label="Theme: Auto">
<svg class="theme-icon theme-icon-auto" viewBox="0 0 18 18" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<circle cx="9" cy="9" r="7.25"/>
<path d="M9 1.75A7.25 7.25 0 019 16.25" fill="currentColor" stroke="none"/>
</svg>
<svg class="theme-icon theme-icon-light" viewBox="0 0 18 18" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<circle cx="9" cy="9" r="3.5"/>
<line x1="9" y1="1" x2="9" y2="3"/><line x1="9" y1="15" x2="9" y2="17"/>
<line x1="2.87" y1="2.87" x2="4.28" y2="4.28"/><line x1="13.72" y1="13.72" x2="15.13" y2="15.13"/>
<line x1="1" y1="9" x2="3" y2="9"/><line x1="15" y1="9" x2="17" y2="9"/>
<line x1="2.87" y1="15.13" x2="4.28" y2="13.72"/><line x1="13.72" y1="4.28" x2="15.13" y2="2.87"/>
</svg>
<svg class="theme-icon theme-icon-dark" viewBox="0 0 18 18" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<path d="M15.54 9.98a7 7 0 01-8.52-8.52 7.5 7.5 0 108.52 8.52z"/>
</svg>
</button>
<div id="bg-wrap">
{% if (bg_src && bg_type == 'video'): %}
<video autoplay muted loop playsinline>
<source src="{{ bg_src }}">
</video>
{% elif (bg_src): %}
<img src="{{ bg_src }}" alt="">
{% endif %}
</div>
<div class="login-wrap">
<div class="login-card">
<img class="login-logo" src="{{ media }}/img/glass-logo.svg" alt="Logo">
<h1 class="login-title">{{ hostname }}</h1>
<p class="login-subtitle">{{ _('Sign in to continue') }}</p>
<p class="login-version">GlassTheme v{{ glass_version }}</p>
{% if (fuser): %}
<div class="login-error">
{{ _('Invalid username and/or password! Please try again.') }}
</div>
{% endif %}
<form class="login-form" method="post" action="{{ http.getenv('REQUEST_URI') }}">
<div class="login-field">
<label for="luci_username">{{ _('Username') }}</label>
<input type="text" id="luci_username" name="luci_username"
value="{{ entityencode(duser, true) }}"
autocomplete="username">
</div>
<div class="login-field">
<label for="luci_password">{{ _('Password') }}</label>
<input type="password" id="luci_password" name="luci_password"
autocomplete="current-password">
</div>
<input type="submit" class="login-btn" value="{{ _('Log in') }}">
</form>
</div>
</div>
<script>
var pw = document.getElementById('luci_password');
if (pw) pw.focus();
(function(){
var btn=document.getElementById('theme-toggle');
if(!btn)return;
var order=['auto','light','dark'];
var labels={auto:'Theme: Auto',light:'Theme: Light',dark:'Theme: Dark'};
var cur=document.documentElement.dataset.theme||'auto';
btn.title=labels[cur];btn.setAttribute('aria-label',labels[cur]);
btn.addEventListener('click',function(){
var cur=document.documentElement.dataset.theme||'auto';
var next=order[(order.indexOf(cur)+1)%3];
document.documentElement.dataset.theme=next;
try{localStorage.setItem('glass-theme',next)}catch(e){}
var d=document.getElementById('dark-styles'),m=document.getElementById('meta-theme-color');
if(next==='dark'){d.media='all';if(m)m.content='#2c2e3a'}
else if(next==='light'){d.media='not all';if(m)m.content='#f5f5f7'}
else{d.media='(prefers-color-scheme: dark)';if(m)m.content=window.matchMedia('(prefers-color-scheme: dark)').matches?'#2c2e3a':'#f5f5f7'}
btn.title=labels[next];btn.setAttribute('aria-label',labels[next]);
});
})();
</script>
</body>
</html>
@@ -0,0 +1 @@
1.1.6
+12
View File
@@ -0,0 +1,12 @@
.research/
.reasonix/
*.ipk
*.apk
# macOS
.DS_Store
.AppleDouble
.LSOverride
reasonix.toml
# CDP/headless 调试临时目录
.liquid-tmp/
+61
View File
@@ -0,0 +1,61 @@
# 更新日志
> 本文件归档 **[README.md](README.md)** 的全部历史更新条目;README 正文只保留最近一次更新。
> English version: **[ChangeLogs_EN.md](ChangeLogs_EN.md)**
- **2026-09-28 · v1.0(主版本升级)**:透明度调节 + 在线更新 + 登录体验 + 宽表格自适应
- **玻璃透明度滑杆**:顶栏颜色区拖动 0–100 即时生效、点刻度回默认;菜单、按钮、主题色背景同步变化,亮 / 暗各有默认;登录页同样可调,设置存在路由器上、换设备保留
- **在线检查更新**:点页脚版本号即可检查新版本、一键更新;检查中 / 已是最新 / 有新版本 / 失败 四种状态一目了然,失败会明确提示;手机页脚也显示版本、按钮加大
- **登录页**:登录前调好的明暗 / 主题色 / 透明度,登录后弹提示一键应用(30 秒可忽略);logo 换上毛玻璃光晕;修复明暗切换闪动与误触提交
- **下拉菜单**:玻璃外观重做,宽度随最长选项伸缩、贴边自动上弹、点内容不闪烁;暗色下选项更清楚;无线设置等页面异常的下拉恢复正常
- **提示弹窗**:成功提示(如“密码已更改”)改为屏幕居中玻璃弹窗、6 秒自动关闭;手机上按钮自动换行不溢出
- **宽表格自适应**:表格超出屏幕时先折叠操作按钮(一行一个)把宽度让给文字,文字不再被挤窄或裁掉;手机上表格收回屏内、无需左右拖动
- **其他修复**:菜单滑块切分类不再停在原处;OpenClash 打开不再先闪黑;选中标签改高对比配色,暗色下更清楚
- **2026-08-18 · v0.7**:移动端体验优化 + 多处体验优化
- **移动端体验优化**
- 滚动页面时浏览器工具栏 / 地址栏自动收缩,移动端获得更大视野
- 底部横幅避让全面屏手势条
- EasyTier 重启、刷新版本确认框在手机上居中显示
- **多处体验优化**
- 修复按钮描边不贴合圆角、边缘出现竖缝的问题(普通按钮 / 保存并应用 / 分割按钮)
- **2026-08-15 · v0.6**:菜单搜索 + 多处体验优化
- **菜单搜索**:颜色区新增搜索入口,点击推出搜索框,实时过滤菜单项,支持中英文匹配
- **多处体验优化**:多实例配置(如 Dropbear)独立卡片显示;刷新按钮玻璃质感;iStoreOS 页面标签适配主题样式
- **2026-08-13 · v0.5**:弹窗居中 + 状态条样式优化
- **弹窗居中**:应用配置提示(正在等待 / 已应用 / 无待应用)与待应用变更窗口在移动端正确居中显示;超高表单弹窗(如添加 DHCP)保持正常滚动
- **状态条样式**:磁盘 / 内存使用条加深主题色、玻璃渐变质感,条内显示已用 / 总量
- **2026-08-08 · v0.3**:自定义主题色 + 颜色开关优化 + 移动端 / 暗色模式改进
- **自定义主题色**:5 套预置色之外新增自定义色——点击彩虹圆点下拉输入 hex 颜色编码(`#RRGGBB`),离开输入框即保存并全局生效;非法输入自动回退默认蓝(仍保持自定义模式启用);经 uci 持久化,换设备保留
- **颜色开关**:外框统一 35px 高;自定义色选中时圆点内部显示自定义色、外圈彩虹渐变描边(一眼识别);Bing 壁纸按钮方形描边贴合图标、启用时单层白色描边
- **移动端**:首屏不再闪现"菜单先展开再收缩"(禁用桌面入场动画干扰抽屉收起态,加载完成即可操作);底部 foot 高度缩减
- **暗色模式**:模式开关图标(外链 svg)反色为浅色,深色背景下清晰可见
- **修复**:自定义色保存(controller 白名单支持 `accent=custom` / `accent_custom`)、登录页颜色开关定位、颜色区外框高度
- **2026-08-08 · v0.2-r52**:移动端体验优化 + 下拉菜单优化
- **移动端接口页**:接口小框(ifacebox)与其所在行卡片左缘间隔优化为 4px,显示更整齐
- **移动端层叠卡片缩进**:弹出窗口宽 95%、嵌套卡片每层向内缩 2px,展示更大操作区
- **移动端菜单**:点击空白处退出菜单
- **桌面端弹出式层叠卡片**:显示效果优化(modal 80% 宽、嵌套卡片逐层限宽防溢出)
- **下拉菜单**:单选 / 多选交互与显示效果优化
- **2026-08-07 · v0.2**:配置持久化(uci)+ Bing 每日壁纸 + 多项修复
- **配置持久化(uci)**:亮/暗/自动模式、5 套主题色、Bing 开关统一存入 `uci /etc/config/liquid`,换客户端(浏览器/设备)仍保留;改动经 LuCI RPC 直接提交,立即生效、无"待应用"提示
- **Bing 每日壁纸(锁屏)**:主题色前新增 Bing 开关按钮(字母 b logo);启用后锁屏显示 Bing 当日壁纸(缓存于各设备 `/tmp/liquid/`);无互联网或按钮关闭时自动回退默认壁纸(亮/暗各按模式)
- **锁屏只读**:登录页仅本地预览,不写入配置
- **uci 优先**:修复本地 localStorage 旧值覆盖 uci 新配置的问题,页面加载即应用路由器端配置
- **接口页修复**:未加入防火墙区域的接口 head 色条由白色改为灰色(亮色浅灰 / 暗色近黑),暗色下接口名不再不可见
- **CI**:GitHub Actions 双平台(x86 + MT798x)× 双格式(ipk / apk)自动构建发布
- 版本号 0.2-r1
- **2026-08-07 · v0.1 首次发布**:全新 macOS 风格 Liquid Glass(液态玻璃)LuCI 主题,带来以下功能:
- **液态玻璃设计语言**:侧栏、内容卡片、登录页、页脚统一 frosted-glass(模糊 + 高光 + 主题色光晕),暗色下玻璃更实、文字更清晰
- **三态模式切换**:亮色 / 暗色 / 跟随系统,顶栏一键切换,`localStorage` 持久化、加载无闪烁
- **主题色**:5 套主题色(蓝 / 玫红 / 橙黄 / 郁金香紫 / 黄绿),菜单、按钮、Tab、logo 全链路联动
- **菜单**:默认全部折叠(点击一级菜单才展开二级)、hover 追踪滑块、选中玻璃胶囊、移动端滑出菜单
- **下拉控件**:一体化渐变胶囊(主体 + 分隔箭头,同"保存并应用"),视口边缘自动向上弹出、不被页脚遮挡
- **悬浮内容框(tooltip)**:磨砂玻璃底、顶层显示不被相邻卡片遮挡、边缘自动避让、互斥防残留
- **表格**:行内单元格等高(分割线对齐)、移动端按内容宽度 + 横向滚动(长列不重叠)
- **接口 / 设备页**:SVG 图标统一、连接状态由图标文件区分(不再半透误导)
- **锁屏(登录页)**:macOS 风格玻璃登录卡片 + Monterey 壁纸 + 主题色水滴 logo
- **兼容**:LuCI ≥ 23(OpenWrt 23.05 / 24.10 / master)
+61
View File
@@ -0,0 +1,61 @@
# Changelog
> Full history of the entries from **[README_EN.md](README_EN.md)**; the README body only keeps the latest one.
> 中文版本:**[ChangeLogs.md](ChangeLogs.md)**
- **2026-09-28 · v1.0 (major release)**: opacity slider + online update + lock screen polish + wide-table adaptivity
- **Glass opacity slider**: drag 0–100 in the top-bar color area for an instant preview, click the tick to reset; menus, buttons and accent backgrounds follow along, with separate light / dark defaults; also on the lock screen, and the setting stays on your router across devices
- **Online update check**: click the footer version to check and install a new release; checking / up to date / update available / failed are all clearly shown, and failures report an error instead of hanging; mobile footers show the version too, with bigger buttons
- **Lock screen**: mode, accent and opacity picked before signing in are offered with one click after login (30-second countdown, dismissible); the logo gets a frosted glass glow; fixed mode-switch flicker and accidental submits
- **Dropdowns**: refreshed glass look — width follows the longest option, menus flip up near the edge, no flash on click; clearer highlights in dark mode; previously broken dropdowns (e.g. wireless settings) work again
- **Notifications**: success messages (e.g. "password changed") now show as a centered glass dialog that closes after 6 seconds; buttons wrap on phones instead of overflowing
- **Wide tables**: when a table no longer fits the screen, action buttons stack one per line so text keeps its width — no more squeezed or clipped columns; on phones the table stays on screen with no sideways scrolling
- **Fixes**: the sidebar slider no longer sticks to the previous category; OpenClash no longer flashes dark on open; the selected tab uses a high-contrast color for dark mode
- **2026-08-18 · v0.7**: mobile UX polish + general UX polish
- **Mobile**
- Toolbar / address bar auto-collapses on scroll, giving a larger view on phones
- Bottom banner clears the fullscreen gesture bar
- EasyTier restart / refresh-version dialogs center on mobile
- **General**
- Fixed button borders not hugging rounded corners / edge seams (plain buttons, Save & Apply, split-select)
- **2026-08-15 · v0.6**: menu search + UX polish
- **Menu search**: new search entry in the color area — opens a search box that filters menu items in real time, matching Chinese and English titles
- **UX polish**: multi-instance configs (e.g. Dropbear) show as separate cards; refresh button gets a frosted glass look; iStoreOS page tabs adopt the theme tab style
- **2026-08-13 · v0.5**: centered modals + status-bar style polish
- **Centered modals**: apply-progress toasts (applying / applied / nothing to apply) and the pending-changes dialog are now properly centered on mobile; tall form modals (e.g. add DHCP) keep normal scrolling
- **Status bars**: disk / memory usage bars get a deeper accent color with a glass gradient, showing used / total inline
- **2026-08-08 · v0.3**: custom accent color + color-switch polish + mobile / dark-mode improvements
- **Custom accent color**: beyond the 5 presets — click the rainbow dot to drop a hex input (`#RRGGBB`); leaving the field saves and applies instantly; invalid values fall back to default blue (custom mode stays enabled); persisted via uci across clients
- **Color switch**: pill fixed at 35px; a selected custom dot shows its color inside with a rainbow ring for instant recognition; the Bing wallpaper button gets a square outline hugging its icon and a single white ring when active
- **Mobile**: no first-load menu flash (desktop entry animation disabled so the drawer starts closed and usable immediately); footer height trimmed
- **Dark mode**: mode-switch icons (external svg) inverted to light so they stay visible on dark backgrounds
- **Fixes**: custom-color persistence (controller whitelist accepts `accent=custom` / `accent_custom`), login-page color-switch position, pill height
- **2026-08-08 · v0.2-r52**: mobile UX & dropdown improvements
- **Mobile interfaces page**: ifacebox aligned 4px from its row card's left edge for a cleaner look
- **Mobile nested-card insets**: modal at 95% width, each nested layer steps in 2px, giving a larger usable area
- **Mobile menu**: tapping outside closes the menu
- **Desktop modal / nested cards**: improved display (modal at 80% width, nested layers width-constrained to prevent overflow)
- **Dropdowns**: single-select & multi-select interaction and display polish
- **2026-08-07 · v0.2**: persistent config (uci) + Bing daily wallpaper + fixes
- **Persistent config (uci)**: light/dark/auto mode, the 5 accent colors and the Bing switch are stored in `uci /etc/config/liquid`, so the settings follow the router across clients (browsers / devices); changes are committed through the theme's own ucode endpoint and take effect immediately with no "pending apply" entries or save prompts.
- **Bing daily wallpaper (lock screen)**: a Bing toggle button (letter-b logo) sits before the five accent colors; when enabled, the lock screen shows Bing's picture of the day (cached per device in `/tmp/liquid/`); when offline or disabled it falls back to the default wallpaper (per mode).
- **Lock screen read-only**: the login page only previews locally and never writes configuration.
- **uci wins**: fixed stale localStorage overriding the uci config — every reload applies the router-wide config.
- **Interfaces page fix**: the head bar of interfaces not assigned to any firewall zone is now gray (light: light gray / dark: near-black) so the interface name stays readable in dark mode.
- **CI**: GitHub Actions build & release on two platforms (x86 + MT798x) × two formats (ipk / apk).
- Version bumped to 0.2-r1.
- **2026-08-07 · v0.1 (initial release)**: a brand-new macOS-style Liquid Glass LuCI theme
- **Liquid glass design language**: frosted glass (blur + highlight + theme glow) across sidebar, content cards, login page and footer
- **Three-way mode**: light / dark / auto from the top bar, persisted, no flash on load
- **Accent colors**: 5 themes driving menus, buttons, tabs and logo
- **Menu**: collapsed by default, hover-tracking slider, selected glass capsule, mobile slide-out menu
- **Dropdowns**: gradient capsule (body + divider + arrow, same as "Save & Apply"), auto-flip at viewport edges
- **Tooltips**: frosted glass, top-level display, edge avoidance
- **Tables**: equal-height rows, horizontal scroll on mobile (no long-column overlap)
- **Interfaces / Devices**: uniform SVG icons, link state told by the icon file
- **Lock screen**: macOS-style frosted login card + Monterey wallpaper + accent-colored waterdrop logo
- **Compatibility**: LuCI ≥ 23 (OpenWrt 23.05 / 24.10 / master)
+674
View File
@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
+67
View File
@@ -0,0 +1,67 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-theme-liquid
PKG_VERSION:=1.0
PKG_RELEASE:=1
PKG_MAINTAINER:=然后七年 <z@7ze.top>
PKG_LICENSE:=Apache-2.0
# OpenWrt 23.05 的 luci.mk 版本规则只取 PKG_VERSION(忽略 PKG_RELEASE),
# 导致 GitHub Action 编译出的 ipk 没有 r 小版本(0.4 vs 0.4-r1)。
# 用 override VERSION 强制统一为 PKG_VERSION-rPKG_RELEASE。注意:必须
# 写在 include luci.mk 之前——luci.mk 末尾会立即 eval BuildPackage,
# 其 ipk 命名/control 里的 $(VERSION) 在那一刻固化,写后面就晚了。
# luci.mk 的 VERSION:= 是普通赋值(被 override 压住),且本值在新版
# luci.mk 与 i18n 子包(PKG_PO_VERSION)下与默认一致,不影响 apk/新版。
override VERSION:=$(if $(PKG_RELEASE),$(PKG_VERSION)-r$(PKG_RELEASE),$(PKG_VERSION))
LUCI_TITLE:=Liquid glass theme for LuCI (>= 23)
LUCI_PKGARCH:=all
LUCI_DEPENDS:=+luci-base
# 汉化/子包版本与主包保持同步
PKG_PO_VERSION:=$(PKG_VERSION)-r$(PKG_RELEASE)
# csstidy 会破坏 @media 块(只保留首条规则,其余泄漏到块外无条件生效),
# 导致移动端断点样式全部失效;本主题关闭 CSS 压缩,样式原样打包。
CONFIG_LUCI_CSSTIDY:=
define Package/$(PKG_NAME)/postinst
#!/bin/sh
[ -n "$${IPKG_INSTROOT}" ] || {
# 公钥信任不在此处写(去冗余):apk 装机时生成的 post-install 会先
# 调 default_postinst —— 它会执行包内 etc/uci-defaults/99-zed-apk-key-liquid
# 完成公钥条件写入并消费该脚本;固件场景由首次开机执行同一脚本覆盖
# (构建期 --no-scripts 不跑脚本,文件随镜像保留);装 r9 之前的设备
# 由 OTA 安装前自举兜底。23.05 为 opkg 系统,不使用 apk 钥匙。
# 23.05 opkg 不执行 uci-defaults,必须在 postinst 中设置主题配置。
# 确保 mediaurlbase 指向 liquid,否则 fallback 到 null。
if [ "$$(uci -q get luci.main.mediaurlbase)" != "/luci-static/liquid" ]; then
uci set luci.main.mediaurlbase=/luci-static/liquid
uci commit luci
fi
rm -f /tmp/luci-indexcache.*
rm -rf /tmp/luci-modulecache/
/etc/init.d/rpcd reload 2>/dev/null
exit 0
}
exit 0
endef
define Package/$(PKG_NAME)/postrm
#!/bin/sh
[ -n "$${IPKG_INSTROOT}" ] || {
uci -q delete luci.themes.Liquid
[ "$$(uci -q get luci.main.mediaurlbase)" = "/luci-static/liquid" ] && \
uci -q delete luci.main.mediaurlbase
uci commit luci
}
exit 0
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature
+177
View File
@@ -0,0 +1,177 @@
<!-- markdownlint-configure-file {
"MD013": {
"code_blocks": false,
"tables": false,
"line_length":200
},
"MD033": false,
"MD041": false
} -->
[license]: /LICENSE
[license-badge]: https://img.shields.io/github/license/zzsj0928/luci-theme-liquid?style=flat-square&a=1
[prs]: https://github.com/zzsj0928/luci-theme-liquid/pulls
[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
[issues]: https://github.com/zzsj0928/luci-theme-liquid/issues/new
[issues-badge]: https://img.shields.io/badge/Issues-welcome-brightgreen.svg?style=flat-square
[release]: https://github.com/zzsj0928/luci-theme-liquid/releases
[release-badge]: https://img.shields.io/github/v/release/zzsj0928/luci-theme-liquid?style=flat-square
[download]: https://github.com/zzsj0928/luci-theme-liquid/releases
[download-badge]: https://img.shields.io/github/downloads/zzsj0928/luci-theme-liquid/total?style=flat-square
[en-us-link]: /README_EN.md
[zh-cn-link]: /README.md
[official]: https://github.com/openwrt/openwrt
[immortalwrt]: https://github.com/immortalwrt/immortalwrt
[luci-mod]: https://github.com/xylz0928/luci-mod
<div align="center">
<p align="center"><img src="logo.svg" width="500"></p>
# 💧 luci-theme-liquid
**macOS 风格 Liquid Glass(液态玻璃)OpenWrt LuCI 主题**,适用于 **LuCI ≥ 23**(OpenWrt 23.05 / 24.10 / master)。
支持**亮色 / 暗色 / 跟随系统**三态切换、**5 套主题色 + 自定义颜色**、可调玻璃模糊与透明度;登录页、侧栏、内容卡片、下拉、悬浮框全链路液态玻璃质感。
[![license][license-badge]][license]
[![prs][prs-badge]][prs]
[![issues][issues-badge]][issues]
[![release][release-badge]][release]
[![download][download-badge]][download]
**简体中文** | [English][en-us-link]
[特性](#特性) •
[更新日志](#更新日志) •
[兼容性](#兼容性) •
[编译安装](#编译安装) •
[界面展示](#界面展示) •
[致谢](#致谢)
<img src="https://raw.githubusercontent.com/zzsj0928/ReadmeContents/master/liquid/luci-theme-liquid_pc.gif">
</div>
## 特性
- **液态玻璃设计语言**:侧栏、内容卡片、登录卡片、页脚统一 frosted-glass(模糊 + 高光 + 主题色光晕),暗色下玻璃更实、文字更清晰。
- **亮 / 暗 / 跟随系统**:顶栏右侧一键切换,设置存在路由器上(换浏览器、换设备仍在),加载即生效、无闪烁;锁屏页同样可切。
- **主题色**:**远空蓝**、**勃艮第红**、**落日金**、**暮山紫**、**青金萃** 5 套 + 自定义色(点彩虹圆点输入 `#RRGGBB`),选中菜单、悬停滑块、按钮、Tab、logo 全链路联动。
- **玻璃透明度滑杆**:顶栏颜色区拖动 0–100 实时调节玻璃深浅,点默认刻度一键还原;亮 / 暗各有默认值;菜单、按钮、主题色背景同步变化;锁屏页同样可调。
- **菜单搜索**:顶栏搜索按钮下推抽屉式搜索框,输入即实时过滤菜单,中文名与英文原题都能匹配,点外部或再点按钮收回。
- **左侧菜单**:默认全部折叠,点一级才展开二级;悬停追踪滑块 + 选中玻璃胶囊;多实例配置(如 Dropbear)自动拆成独立卡片;移动端滑出菜单避让顶栏、点空白关闭。
- **下拉控件**:玻璃胶囊外观,宽度随最长选项自动伸缩、贴近窗口边缘自动向上弹出、点内容区不闪烁;暗色下选项高亮更清楚。
- **表格自适应**:行内单元格等高;表格超出屏幕时先把操作按钮竖排(一行一个)把宽度让给文字,文字不再被挤窄或裁掉;手机上表格收回屏内、无需左右拖动。
- **接口 / 设备页**:接口图标统一 24px、始终不透明(连接状态由图标本身区分);行内等高,按钮平时一行、放不下时自动竖排让位文字;移动端接口小框与所在行卡片保持 4px 间隔。
- **移动端适配**:弹出窗口 95% 宽、嵌套卡片逐层向内缩进;抽屉菜单点空白关闭、首屏直接收起无闪烁;提示按钮自动换行不溢出。
- **在线检查更新**:点页脚版本号即可检查新版本、一键更新,检查中 / 已是最新 / 有新版本 / 失败 四态清晰;手机页脚同样显示主题版本。
- **提示弹窗**:成功提示(如“密码已更改”)升级为屏幕居中的玻璃弹窗,6 秒自动关闭。
- **锁屏(登录页)**:macOS 风格玻璃登录卡片 + Monterey 壁纸(亮/暗)+ 可选 **Bing 每日壁纸**(每日自动抓取缓存)+ 毛玻璃光晕水滴 logo;登录前调好的明暗 / 主题色 / 透明度,登录成功后一键应用。
- **悬浮内容框(tooltip)**:磨砂玻璃底、置顶显示(不被相邻卡片遮挡)、边缘自动避让、互斥防残留。
- **SVG 图标**:网络 / 接口状态图标取自 [xylz0928/luci-mod][luci-mod] `immortalwrt-24.10` 分支的 SVG 图标集;UI 元素图标(sun / moon / auto / refresh / lock / search / close / chevron)为内置 SVG。
## 更新日志
- **2026-09-28 · v1.0(主版本升级)**:透明度调节 + 在线更新 + 登录体验 + 宽表格自适应
- **玻璃透明度滑杆**:顶栏颜色区拖动 0–100 即时生效、点刻度回默认;菜单、按钮、主题色背景同步变化,亮 / 暗各有默认;登录页同样可调,设置存在路由器上、换设备保留
- **在线检查更新**:点页脚版本号即可检查新版本、一键更新;检查中 / 已是最新 / 有新版本 / 失败 四种状态一目了然,失败会明确提示;手机页脚也显示版本、按钮加大
- **登录页**:登录前调好的明暗 / 主题色 / 透明度,登录后弹提示一键应用(30 秒可忽略);logo 换上毛玻璃光晕;修复明暗切换闪动与误触提交
- **下拉菜单**:玻璃外观重做,宽度随最长选项伸缩、贴边自动上弹、点内容不闪烁;暗色下选项更清楚;无线设置等页面异常的下拉恢复正常
- **提示弹窗**:成功提示(如“密码已更改”)改为屏幕居中玻璃弹窗、6 秒自动关闭;手机上按钮自动换行不溢出
- **宽表格自适应**:表格超出屏幕时先折叠操作按钮(一行一个)把宽度让给文字,文字不再被挤窄或裁掉;手机上表格收回屏内、无需左右拖动
- **其他修复**:菜单滑块切分类不再停在原处;OpenClash 打开不再先闪黑;选中标签改高对比配色,暗色下更清楚
> 📜 完整更新日志(v0.1 起全部版本)见 **[ChangeLogs.md](ChangeLogs.md)**。
## 兼容性
支持基于 [OpenWrt 官方][official] 与 [ImmortalWrt][immortalwrt] 的现代 LuCI 环境(LuCI ≥ 23,OpenWrt 23.05 / 24.10 / master)。
## 编译安装
本包使用 LuCI feed 的 `luci.mk` 打包规则(`include $(TOPDIR)/feeds/luci/luci.mk`),因此编译环境需先 `./scripts/feeds update -a && ./scripts/feeds install -a`(含 luci feed)。
把本目录放入 OpenWrt 源码树的 `package/luci-theme-liquid/`(或 `feeds/luci/themes/luci-theme-liquid/`),在 `.config` 中启用该包后编译:
```bash
cd openwrt/package
git clone https://github.com/xylz0928/luci-theme-liquid.git
make menuconfig # 选择 LUCI → Themes → luci-theme-liquid
make -j1 V=s
```
或直接编译单个包:
```sh
# 在 .config 中启用(任选其一)
make menuconfig # LuCI → Themes → luci-theme-liquid
# 或
echo 'CONFIG_PACKAGE_luci-theme-liquid=y' >> .config && make defconfig
make package/luci-theme-liquid/compile -j4 V=s
```
> 注意:`make package/<name>/compile` 只对已在 `.config` 中启用(`=y`/`=m`)的包真正执行构建,未启用时 make 会空转(`Entering/Leaving` 无任何动作),不要误判为成功。
生成的 `bin/packages/<arch>/base/luci-theme-liquid-0.3-r<rel>.apk`(或 `.ipk`)可通过 `apk` / `opkg` 安装:
```sh
apk add --allow-untrusted luci-theme-liquid-0.3-r1.apk
```
首次安装会自动注册主题(`luci.themes.Liquid=/luci-static/liquid`);若 `luci.main.mediaurlbase` 尚未配置则自动设为该主题,否则请在 **System → Advanced → Theme** 中手动选择 **Liquid**。
### 目录结构
```
luci-theme-liquid/
├── Makefile # OpenWrt 包(luci feed 内/独立 package 目录均可编译)
├── logo.svg # 主题 logo(水滴 + Liquid)
├── htdocs/luci-static/liquid/ # 主题媒体资源(/luci-static/liquid/)
│ ├── cascade.css # 全部样式(变量 / 菜单 / tab / cbi / dashboard / 锁屏)
│ ├── main.js # 模式开关注入、下拉避让、tooltip portal 等
│ ├── logo.svg / logo.png # 主题 logo
│ ├── img/ # 锁屏壁纸(MontereyDark / MontereyLight)
│ ├── icons/ # 网络状态 SVG 图标(来自 luci-mod immortalwrt-24.10)
│ └── svg/ # UI 元素 SVG + dashboard 图标
├── htdocs/luci-static/resources/ # 共享资源(/luci-static/resources/)
│ ├── menu-liquid.js # 左侧菜单 / tab 渲染(L.require('menu-liquid'))
│ └── view/liquid/sysauth.js # 锁屏登录视图(ui.showModal 'login')
├── ucode/template/themes/liquid/ # 主题 ucode 模板
│ ├── header.ut / footer.ut # 页面骨架(uci 配置读取 / 防闪烁 / Bing 壁纸缓存)
│ └── sysauth.ut # 登录页模板(blank_page + 居中登录框)
└── root/
├── etc/uci-defaults/ # 安装时注册 luci.themes.Liquid
└── usr/share/ucode/luci/controller/liquid.uc # 主题配置保存端点(/admin/system/liquid/save_config)
```
## 界面展示
- 桌面端
![桌面端-锁屏-暗黑模式](https://raw.githubusercontent.com/zzsj0928/ReadmeContents/master/liquid/luci-theme-liquid_pc-lock-dark.png)
![桌面端-主界面-暗黑模式](https://raw.githubusercontent.com/zzsj0928/ReadmeContents/master/liquid/luci-theme-liquid_pc-mainpage-dark.png)
![桌面端-锁屏-明亮模式](https://raw.githubusercontent.com/zzsj0928/ReadmeContents/master/liquid/luci-theme-liquid_pc-lock-light.png)
![桌面端-主界面-明亮模式](https://raw.githubusercontent.com/zzsj0928/ReadmeContents/master/liquid/luci-theme-liquid_pc-mainpage-light.png)
- 移动端
![移动端-暗黑模式](https://raw.githubusercontent.com/zzsj0928/ReadmeContents/master/liquid/luci-theme-liquid_mobile-dark.jpg)
![移动端-明亮模式](https://raw.githubusercontent.com/zzsj0928/ReadmeContents/master/liquid/luci-theme-liquid_mobile-light.jpg)
## 致谢
- 壁纸:macOS Monterey(Bright/Dark),来自 [xylz0928/luci-mod][luci-mod] `Background/`。
- 网络状态 SVG 图标:来自 [xylz0928/luci-mod][luci-mod] `immortalwrt-24.10` 分支 `feeds/luci/modules/luci-base/htdocs/luci-static/resources/icons/`。
- dashboard 模块图标(router / internet / wireless / devices):来自 OpenWrt 官方 [luci-mod-dashboard](https://github.com/openwrt/luci/tree/master/modules/luci-mod-dashboard)。
- 菜单渲染逻辑参考 [luci-theme-openwrt-2020](https://github.com/openwrt/luci/tree/master/themes/luci-theme-openwrt-2020),锁屏视图参考 [luci-theme-bootstrap](https://github.com/openwrt/luci/tree/master/themes/luci-theme-bootstrap)(Apache-2.0)。
## 🍡 赏我一把 Token
**制作不易,感谢支持**
![赞赠](https://raw.githubusercontent.com/zzsj0928/ReadmeContents/master/general/donate-zed.jpg)
## License
Apache-2.0
+178
View File
@@ -0,0 +1,178 @@
<!-- markdownlint-configure-file {
"MD013": {
"code_blocks": false,
"tables": false,
"line_length":200
},
"MD033": false,
"MD041": false
} -->
[license]: /LICENSE
[license-badge]: https://img.shields.io/github/license/zzsj0928/luci-theme-liquid?style=flat-square&a=1
[prs]: https://github.com/zzsj0928/luci-theme-liquid/pulls
[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
[issues]: https://github.com/zzsj0928/luci-theme-liquid/issues/new
[issues-badge]: https://img.shields.io/badge/Issues-welcome-brightgreen.svg?style=flat-square
[release]: https://github.com/zzsj0928/luci-theme-liquid/releases
[release-badge]: https://img.shields.io/github/v/release/zzsj0928/luci-theme-liquid?style=flat-square
[download]: https://github.com/zzsj0928/luci-theme-liquid/releases
[download-badge]: https://img.shields.io/github/downloads/zzsj0928/luci-theme-liquid/total?style=flat-square
[en-us-link]: /README_EN.md
[zh-cn-link]: /README.md
[official]: https://github.com/openwrt/openwrt
[immortalwrt]: https://github.com/immortalwrt/immortalwrt
[luci-mod]: https://github.com/xylz0928/luci-mod
<div align="center">
<p align="center"><img src="logo.svg" width="300"></p>
# 💧 luci-theme-liquid
**macOS-style Liquid Glass OpenWrt LuCI theme**, for **LuCI ≥ 23** (OpenWrt 23.05 / 24.10 / master).
Supports **light / dark / auto** modes, **5 accent colors + a custom color picker** and adjustable blur & transparency; frosted glass design across the login page, sidebar, content cards, dropdowns and tooltips.
[![license][license-badge]][license]
[![prs][prs-badge]][prs]
[![issues][issues-badge]][issues]
[![release][release-badge]][release]
[![download][download-badge]][download]
**English** | [简体中文][zh-cn-link]
[Features](#features) •
[Changelog](#changelog) •
[Compatibility](#compatibility) •
[Building & Installation](#building--installation) •
[Screenshots](#screenshots) •
[Credits](#credits)
<img src="https://raw.githubusercontent.com/zzsj0928/ReadmeContents/master/liquid/luci-theme-liquid_pc.gif">
</div>
## Features
- **Liquid glass design language**: sidebar, content cards, login card and footer share a frosted-glass look (blur + highlight + accent glow); the dark mode glass is more solid for readable text.
- **Light / dark / system**: one tap in the top bar; settings are stored on your router so they survive new browsers and devices; applied before paint with no flash — the lock screen has the switch too.
- **Accent colors**: **Distant Blue**, **Burgundy Red**, **Sunset Gold**, **Dusk Purple**, **Peridot Essence**, plus a custom hex color (`#RRGGBB`) — menus, hover slider, buttons, tabs and the logo all follow.
- **Glass opacity slider**: drag 0–100 in the top-bar color area to tune the glass live, click the default tick to reset; separate light / dark defaults; menus, buttons and accent backgrounds follow; also on the lock screen.
- **Menu search**: the top-bar search button pushes down a drawer-style search box that filters menu items as you type, matching both Chinese names and English titles; click outside or the button again to close.
- **Sidebar menu**: all top-level menus collapsed by default — click a level-1 menu to expand its submenu; hover-tracking slider + selected glass capsule; multi-instance entries (e.g. Dropbear) split into their own cards; the mobile slide-out menu avoids the top bar and closes on outside taps.
- **Dropdown controls**: glass capsule look, width follows the longest option, the opened list flips upward near the window edge and never flashes when clicking the content area; clearer highlights in dark mode.
- **Adaptive tables**: equal-height cells per row; when a table no longer fits the screen, action buttons stack one per line so text keeps its width — no squeezed or clipped columns; on phones the table stays inside the screen with no sideways scrolling.
- **Interfaces / Devices pages**: uniform 24px interface icons, forced opaque (link state is told by the icon itself); rows keep equal heights, buttons stay on one line and stack only when space runs short; interface boxes keep a 4px gap from their row card on mobile.
- **Mobile adaptation**: modals at 95% width with nested cards stepping in per layer; the drawer menu closes on tapping outside and starts collapsed with no first-load flash; toast buttons wrap instead of overflowing.
- **Online update check**: click the footer version to check for a new release and install it in one click, with four clear states (checking / up to date / update available / failed); mobile footers show the theme version too.
- **Notifications**: success messages (e.g. "password changed") appear as a centered glass dialog that closes after 6 seconds.
- **Lock screen (login)**: macOS-style frosted login card + Monterey wallpaper (light/dark) + optional **Bing daily wallpaper** (auto-fetched and cached) + a glowing waterdrop logo; mode, accent and opacity picked before signing in can be applied with one click after login.
- **Tooltips**: frosted glass background, shown at the page top level (never hidden behind a neighbouring card), auto-avoid viewport edges, mutual exclusion against stale popups.
- **SVG icons**: network / interface status icons taken from [xylz0928/luci-mod][luci-mod] `immortalwrt-24.10`; UI element icons (sun / moon / auto / refresh / lock / search / close / chevron) are built-in SVGs.
## Changelog
- **2026-09-28 · v1.0 (major release)**: opacity slider + online update + lock screen polish + wide-table adaptivity
- **Glass opacity slider**: drag 0–100 in the top-bar color area for an instant preview, click the tick to reset; menus, buttons and accent backgrounds follow along, with separate light / dark defaults; also on the lock screen, and the setting stays on your router across devices
- **Online update check**: click the footer version to check and install a new release; checking / up to date / update available / failed are all clearly shown, and failures report an error instead of hanging; mobile footers show the version too, with bigger buttons
- **Lock screen**: mode, accent and opacity picked before signing in are offered with one click after login (30-second countdown, dismissible); the logo gets a frosted glass glow; fixed mode-switch flicker and accidental submits
- **Dropdowns**: refreshed glass look — width follows the longest option, menus flip up near the edge, no flash on click; clearer highlights in dark mode; previously broken dropdowns (e.g. wireless settings) work again
- **Notifications**: success messages (e.g. "password changed") now show as a centered glass dialog that closes after 6 seconds; buttons wrap on phones instead of overflowing
- **Wide tables**: when a table no longer fits the screen, action buttons stack one per line so text keeps its width — no more squeezed or clipped columns; on phones the table stays on screen with no sideways scrolling
- **Fixes**: the sidebar slider no longer sticks to the previous category; OpenClash no longer flashes dark on open; the selected tab uses a high-contrast color for dark mode
> 📜 Full changelog (all versions since v0.1) lives in **[ChangeLogs_EN.md](ChangeLogs_EN.md)**.
## Compatibility
Targets modern LuCI environments based on [OpenWrt][official] and [ImmortalWrt][immortalwrt] (LuCI ≥ 23, OpenWrt 23.05 / 24.10 / master).
## Building & Installation
This package uses LuCI's `luci.mk` packaging (`include $(TOPDIR)/feeds/luci/luci.mk`), so the build tree needs `./scripts/feeds update -a && ./scripts/feeds install -a` (includes the luci feed).
Put this directory into `package/luci-theme-liquid/` (or `feeds/luci/themes/luci-theme-liquid/`) of the OpenWrt source tree, enable the package in `.config`, then build:
```bash
cd openwrt/package
git clone https://github.com/xylz0928/luci-theme-liquid.git
make menuconfig # choose LUCI → Themes → luci-theme-liquid
make -j1 V=s
```
Or build only this package:
```sh
# enable it in .config (either way)
make menuconfig # LuCI → Themes → luci-theme-liquid
# or
echo 'CONFIG_PACKAGE_luci-theme-liquid=y' >> .config && make defconfig
make package/luci-theme-liquid/compile -j4 V=s
```
> Note: `make package/<name>/compile` only really builds packages enabled (`=y`/`=m`) in `.config`; otherwise make no-ops (just prints `Entering/Leaving`), which is not a successful build.
The produced `bin/packages/<arch>/base/luci-theme-liquid-0.3-r<rel>.apk` (or `.ipk`) can be installed with `apk` / `opkg`:
```sh
apk add --allow-untrusted luci-theme-liquid-0.3-r1.apk
```
On first install the theme is registered automatically (`luci.themes.Liquid=/luci-static/liquid`); if `luci.main.mediaurlbase` is not set it is set to the theme, otherwise pick **Liquid** manually at **System → Advanced → Theme**.
### Directory layout
```
luci-theme-liquid/
├── Makefile # OpenWrt package (works inside luci feed or a standalone package dir)
├── logo.svg # theme logo (waterdrop + Liquid)
├── htdocs/luci-static/liquid/ # theme assets (/luci-static/liquid/)
│ ├── cascade.css # all styles (vars / menu / tab / cbi / dashboard / lock screen)
│ ├── main.js # mode switch, dropdown flip, tooltip portal, config saving
│ ├── logo.svg / logo.png # theme logo
│ ├── img/ # lock screen wallpapers (MontereyDark / MontereyLight)
│ ├── icons/ # network status SVG icons (from luci-mod immortalwrt-24.10)
│ └── svg/ # UI element SVGs + dashboard icons
├── htdocs/luci-static/resources/ # shared resources (/luci-static/resources/)
│ ├── menu-liquid.js # sidebar menu / tab rendering (L.require('menu-liquid'))
│ └── view/liquid/sysauth.js # lock screen login view (ui.showModal 'login')
├── root/usr/share/ucode/luci/ # ucode controller (config save endpoint)
│ └── controller/liquid.uc
├── root/usr/share/luci/menu.d/ # dispatcher route registration
│ └── liquid.json
├── ucode/template/themes/liquid/ # theme ucode templates
│ ├── header.ut / footer.ut # page skeleton (uci config / anti-flash / Bing wallpaper cache)
│ └── sysauth.ut # login template (blank_page + centered login box)
└── root/etc/uci-defaults/ # registers luci.themes.Liquid on install
```
## Screenshots
- 桌面端
![桌面端-锁屏-暗黑模式](https://raw.githubusercontent.com/zzsj0928/ReadmeContents/master/liquid/luci-theme-liquid_pc-lock-dark.png)
![桌面端-主界面-暗黑模式](https://raw.githubusercontent.com/zzsj0928/ReadmeContents/master/liquid/luci-theme-liquid_pc-mainpage-dark.png)
![桌面端-锁屏-明亮模式](https://raw.githubusercontent.com/zzsj0928/ReadmeContents/master/liquid/luci-theme-liquid_pc-lock-light.png)
![桌面端-主界面-明亮模式](https://raw.githubusercontent.com/zzsj0928/ReadmeContents/master/liquid/luci-theme-liquid_pc-mainpage-light.png)
- 移动端
![移动端-暗黑模式](https://raw.githubusercontent.com/zzsj0928/ReadmeContents/master/liquid/luci-theme-liquid_mobile-dark.jpg)
![移动端-明亮模式](https://raw.githubusercontent.com/zzsj0928/ReadmeContents/master/liquid/luci-theme-liquid_mobile-light.jpg)
## Credits
- Wallpapers: macOS Monterey (Bright/Dark), from [xylz0928/luci-mod][luci-mod] `Background/`.
- Network status SVG icons: from [xylz0928/luci-mod][luci-mod] `immortalwrt-24.10` branch `feeds/luci/modules/luci-base/htdocs/luci-static/resources/icons/`.
- dashboard module icons (router / internet / wireless / devices): from official OpenWrt [luci-mod-dashboard](https://github.com/openwrt/luci/tree/master/modules/luci-mod-dashboard).
- Menu rendering logic references [luci-theme-openwrt-2020](https://github.com/openwrt/luci/tree/master/themes/luci-theme-openwrt-2020), lock screen view references [luci-theme-bootstrap](https://github.com/openwrt/luci/tree/master/themes/luci-theme-bootstrap) (Apache-2.0).
## 🍡 Buy me a cup of TOKEN 😜
**Appreciate Your Like!**
![Awards](https://raw.githubusercontent.com/zzsj0928/ReadmeContents/master/general/donate-zed.jpg)
## License
Apache-2.0
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 21.25 25.648438 L 15 25.648438 L 15 33.148438 L 25 33.148438 L 25 25.648438 Z M 22.5 30.648438 L 17.5 30.648438 L 17.5 28.148438 L 22.5 28.148438 Z M 22.5 30.648438 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.901963%,54.901963%,54.901963%);fill-opacity:1;" d="M 1.25 28.148438 L 15 28.148438 L 15 30.648438 L 1.25 30.648438 Z M 18.75 25.648438 L 21.25 25.648438 L 21.25 21.855469 L 18.75 21.855469 Z M 25 28.148438 L 25 30.648438 L 38.75 30.648438 L 38.75 28.148438 Z M 25 28.148438 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(80.000001%,80.000001%,80.000001%);fill-opacity:1;" d="M 38.75 19.976562 C 38.75 21.011719 37.910156 21.851562 36.875 21.851562 L 3.125 21.851562 C 2.089844 21.851562 1.25 21.011719 1.25 19.976562 L 1.25 8.726562 C 1.25 7.691406 2.089844 6.851562 3.125 6.851562 L 36.875 6.851562 C 37.910156 6.851562 38.75 7.691406 38.75 8.726562 Z M 36.25 10.601562 C 36.25 9.914062 35.691406 9.351562 35 9.351562 L 5 9.351562 C 4.308594 9.351562 3.75 9.914062 3.75 10.601562 L 3.75 18.101562 C 3.75 18.792969 4.308594 19.351562 5 19.351562 L 35 19.351562 C 35.691406 19.351562 36.25 18.792969 36.25 18.101562 Z M 36.25 10.601562 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 5.453125 15.1875 L 6.5625 15.1875 L 6.5625 16.296875 L 7.117188 16.296875 L 7.117188 16.851562 L 9.894531 16.851562 L 9.894531 16.296875 L 10.453125 16.296875 L 10.453125 15.1875 L 11.5625 15.1875 L 11.5625 11.855469 L 5.453125 11.855469 Z M 13.113281 15.1875 L 14.226562 15.1875 L 14.226562 16.296875 L 14.78125 16.296875 L 14.78125 16.851562 L 17.558594 16.851562 L 17.558594 16.296875 L 18.113281 16.296875 L 18.113281 15.1875 L 19.226562 15.1875 L 19.226562 11.855469 L 13.113281 11.855469 Z M 20.773438 15.1875 L 21.886719 15.1875 L 21.886719 16.296875 L 22.441406 16.296875 L 22.441406 16.851562 L 25.222656 16.851562 L 25.222656 16.296875 L 25.773438 16.296875 L 25.773438 15.1875 L 26.886719 15.1875 L 26.886719 11.855469 L 20.773438 11.855469 Z M 28.4375 15.1875 L 29.546875 15.1875 L 29.546875 16.296875 L 30.105469 16.296875 L 30.105469 16.851562 L 32.882812 16.851562 L 32.882812 16.296875 L 33.4375 16.296875 L 33.4375 15.1875 L 34.546875 15.1875 L 34.546875 11.855469 L 28.4375 11.855469 Z M 28.4375 15.1875 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(96.078432%,42.352942%,42.352942%);fill-opacity:1;" d="M 21.25 25.648438 L 15 25.648438 L 15 33.148438 L 25 33.148438 L 25 25.648438 Z M 22.5 30.648438 L 17.5 30.648438 L 17.5 28.148438 L 22.5 28.148438 Z M 22.5 30.648438 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.901963%,54.901963%,54.901963%);fill-opacity:1;" d="M 1.25 28.148438 L 15 28.148438 L 15 30.648438 L 1.25 30.648438 Z M 18.75 25.648438 L 21.25 25.648438 L 21.25 21.855469 L 18.75 21.855469 Z M 25 28.148438 L 25 30.648438 L 38.75 30.648438 L 38.75 28.148438 Z M 25 28.148438 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(80.000001%,80.000001%,80.000001%);fill-opacity:1;" d="M 38.75 19.976562 C 38.75 21.011719 37.910156 21.851562 36.875 21.851562 L 3.125 21.851562 C 2.089844 21.851562 1.25 21.011719 1.25 19.976562 L 1.25 8.726562 C 1.25 7.691406 2.089844 6.851562 3.125 6.851562 L 36.875 6.851562 C 37.910156 6.851562 38.75 7.691406 38.75 8.726562 Z M 36.25 10.601562 C 36.25 9.914062 35.691406 9.351562 35 9.351562 L 5 9.351562 C 4.308594 9.351562 3.75 9.914062 3.75 10.601562 L 3.75 18.101562 C 3.75 18.792969 4.308594 19.351562 5 19.351562 L 35 19.351562 C 35.691406 19.351562 36.25 18.792969 36.25 18.101562 Z M 36.25 10.601562 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(96.078432%,42.352942%,42.352942%);fill-opacity:1;" d="M 5.453125 15.1875 L 6.5625 15.1875 L 6.5625 16.296875 L 7.117188 16.296875 L 7.117188 16.851562 L 9.894531 16.851562 L 9.894531 16.296875 L 10.453125 16.296875 L 10.453125 15.1875 L 11.5625 15.1875 L 11.5625 11.855469 L 5.453125 11.855469 Z M 13.113281 15.1875 L 14.226562 15.1875 L 14.226562 16.296875 L 14.78125 16.296875 L 14.78125 16.851562 L 17.558594 16.851562 L 17.558594 16.296875 L 18.113281 16.296875 L 18.113281 15.1875 L 19.226562 15.1875 L 19.226562 11.855469 L 13.113281 11.855469 Z M 20.773438 15.1875 L 21.886719 15.1875 L 21.886719 16.296875 L 22.441406 16.296875 L 22.441406 16.851562 L 25.222656 16.851562 L 25.222656 16.296875 L 25.773438 16.296875 L 25.773438 15.1875 L 26.886719 15.1875 L 26.886719 11.855469 L 20.773438 11.855469 Z M 28.4375 15.1875 L 29.546875 15.1875 L 29.546875 16.296875 L 30.105469 16.296875 L 30.105469 16.851562 L 32.882812 16.851562 L 32.882812 16.296875 L 33.4375 16.296875 L 33.4375 15.1875 L 34.546875 15.1875 L 34.546875 11.855469 L 28.4375 11.855469 Z M 28.4375 15.1875 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 21.25 25.648438 L 15 25.648438 L 15 33.148438 L 25 33.148438 L 25 25.648438 Z M 22.5 30.648438 L 17.5 30.648438 L 17.5 28.148438 L 22.5 28.148438 Z M 22.5 30.648438 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.901963%,54.901963%,54.901963%);fill-opacity:1;" d="M 1.25 28.148438 L 15 28.148438 L 15 30.648438 L 1.25 30.648438 Z M 18.75 25.648438 L 21.25 25.648438 L 21.25 21.855469 L 18.75 21.855469 Z M 25 28.148438 L 25 30.648438 L 38.75 30.648438 L 38.75 28.148438 Z M 25 28.148438 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(80.000001%,80.000001%,80.000001%);fill-opacity:1;" d="M 38.75 19.976562 C 38.75 21.011719 37.910156 21.851562 36.875 21.851562 L 3.125 21.851562 C 2.089844 21.851562 1.25 21.011719 1.25 19.976562 L 1.25 8.726562 C 1.25 7.691406 2.089844 6.851562 3.125 6.851562 L 36.875 6.851562 C 37.910156 6.851562 38.75 7.691406 38.75 8.726562 Z M 36.25 10.601562 C 36.25 9.914062 35.691406 9.351562 35 9.351562 L 5 9.351562 C 4.308594 9.351562 3.75 9.914062 3.75 10.601562 L 3.75 18.101562 C 3.75 18.792969 4.308594 19.351562 5 19.351562 L 35 19.351562 C 35.691406 19.351562 36.25 18.792969 36.25 18.101562 Z M 36.25 10.601562 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 5.453125 15.1875 L 6.5625 15.1875 L 6.5625 16.296875 L 7.117188 16.296875 L 7.117188 16.851562 L 9.894531 16.851562 L 9.894531 16.296875 L 10.453125 16.296875 L 10.453125 15.1875 L 11.5625 15.1875 L 11.5625 11.855469 L 5.453125 11.855469 Z M 13.113281 15.1875 L 14.226562 15.1875 L 14.226562 16.296875 L 14.78125 16.296875 L 14.78125 16.851562 L 17.558594 16.851562 L 17.558594 16.296875 L 18.113281 16.296875 L 18.113281 15.1875 L 19.226562 15.1875 L 19.226562 11.855469 L 13.113281 11.855469 Z M 20.773438 15.1875 L 21.886719 15.1875 L 21.886719 16.296875 L 22.441406 16.296875 L 22.441406 16.851562 L 25.222656 16.851562 L 25.222656 16.296875 L 25.773438 16.296875 L 25.773438 15.1875 L 26.886719 15.1875 L 26.886719 11.855469 L 20.773438 11.855469 Z M 28.4375 15.1875 L 29.546875 15.1875 L 29.546875 16.296875 L 30.105469 16.296875 L 30.105469 16.851562 L 32.882812 16.851562 L 32.882812 16.296875 L 33.4375 16.296875 L 33.4375 15.1875 L 34.546875 15.1875 L 34.546875 11.855469 L 28.4375 11.855469 Z M 28.4375 15.1875 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(96.078432%,42.352942%,42.352942%);fill-opacity:1;" d="M 21.25 25.648438 L 15 25.648438 L 15 33.148438 L 25 33.148438 L 25 25.648438 Z M 22.5 30.648438 L 17.5 30.648438 L 17.5 28.148438 L 22.5 28.148438 Z M 22.5 30.648438 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.901963%,54.901963%,54.901963%);fill-opacity:1;" d="M 1.25 28.148438 L 15 28.148438 L 15 30.648438 L 1.25 30.648438 Z M 18.75 25.648438 L 21.25 25.648438 L 21.25 21.855469 L 18.75 21.855469 Z M 25 28.148438 L 25 30.648438 L 38.75 30.648438 L 38.75 28.148438 Z M 25 28.148438 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(80.000001%,80.000001%,80.000001%);fill-opacity:1;" d="M 38.75 19.976562 C 38.75 21.011719 37.910156 21.851562 36.875 21.851562 L 3.125 21.851562 C 2.089844 21.851562 1.25 21.011719 1.25 19.976562 L 1.25 8.726562 C 1.25 7.691406 2.089844 6.851562 3.125 6.851562 L 36.875 6.851562 C 37.910156 6.851562 38.75 7.691406 38.75 8.726562 Z M 36.25 10.601562 C 36.25 9.914062 35.691406 9.351562 35 9.351562 L 5 9.351562 C 4.308594 9.351562 3.75 9.914062 3.75 10.601562 L 3.75 18.101562 C 3.75 18.792969 4.308594 19.351562 5 19.351562 L 35 19.351562 C 35.691406 19.351562 36.25 18.792969 36.25 18.101562 Z M 36.25 10.601562 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(96.078432%,42.352942%,42.352942%);fill-opacity:1;" d="M 5.453125 15.1875 L 6.5625 15.1875 L 6.5625 16.296875 L 7.117188 16.296875 L 7.117188 16.851562 L 9.894531 16.851562 L 9.894531 16.296875 L 10.453125 16.296875 L 10.453125 15.1875 L 11.5625 15.1875 L 11.5625 11.855469 L 5.453125 11.855469 Z M 13.113281 15.1875 L 14.226562 15.1875 L 14.226562 16.296875 L 14.78125 16.296875 L 14.78125 16.851562 L 17.558594 16.851562 L 17.558594 16.296875 L 18.113281 16.296875 L 18.113281 15.1875 L 19.226562 15.1875 L 19.226562 11.855469 L 13.113281 11.855469 Z M 20.773438 15.1875 L 21.886719 15.1875 L 21.886719 16.296875 L 22.441406 16.296875 L 22.441406 16.851562 L 25.222656 16.851562 L 25.222656 16.296875 L 25.773438 16.296875 L 25.773438 15.1875 L 26.886719 15.1875 L 26.886719 11.855469 L 20.773438 11.855469 Z M 28.4375 15.1875 L 29.546875 15.1875 L 29.546875 16.296875 L 30.105469 16.296875 L 30.105469 16.851562 L 32.882812 16.851562 L 32.882812 16.296875 L 33.4375 16.296875 L 33.4375 15.1875 L 34.546875 15.1875 L 34.546875 11.855469 L 28.4375 11.855469 Z M 28.4375 15.1875 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.11765%,54.11765%,54.11765%);fill-opacity:1;" d="M 30.761719 38.960938 L 8.480469 38.960938 C 5.519531 38.960938 3.121094 36.558594 3.121094 33.601562 L 3.121094 16.800781 C 3.121094 13.839844 5.519531 11.441406 8.480469 11.441406 L 30.800781 11.441406 C 33.761719 11.441406 36.160156 13.839844 36.160156 16.800781 L 36.160156 33.601562 C 36.121094 36.558594 33.71875 38.960938 30.761719 38.960938 Z M 8.480469 14.199219 C 7.039062 14.199219 5.878906 15.359375 5.878906 16.800781 L 5.878906 33.601562 C 5.878906 35.039062 7.039062 36.199219 8.480469 36.199219 L 30.800781 36.199219 C 32.238281 36.199219 33.398438 35.039062 33.398438 33.601562 L 33.398438 16.800781 C 33.398438 15.359375 32.238281 14.199219 30.800781 14.199219 Z M 29.238281 11.441406 L 26.480469 11.441406 C 26.480469 7.640625 23.398438 4.558594 19.601562 4.558594 C 15.800781 4.558594 12.71875 7.640625 12.71875 11.441406 L 9.960938 11.441406 C 9.960938 6.121094 14.320312 1.800781 19.601562 1.800781 C 24.921875 1.800781 29.238281 6.121094 29.238281 11.441406 Z M 29.238281 11.441406 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 19.601562 31.398438 C 18.441406 31.398438 17.519531 30.480469 17.519531 29.320312 L 17.519531 21.078125 C 17.519531 19.921875 18.441406 19 19.601562 19 C 20.761719 19 21.679688 19.921875 21.679688 21.078125 L 21.679688 29.320312 C 21.679688 30.480469 20.761719 31.398438 19.601562 31.398438 Z M 19.601562 31.398438 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.11765%,54.11765%,54.11765%);fill-opacity:1;" d="M 31.503906 40 L 8.457031 40 C 5.394531 40 2.910156 37.765625 2.910156 35.007812 L 2.910156 19.359375 C 2.910156 16.601562 5.394531 14.367188 8.457031 14.367188 L 31.542969 14.367188 C 34.605469 14.367188 37.089844 16.601562 37.089844 19.359375 L 37.089844 35.007812 C 37.046875 37.765625 34.566406 40 31.503906 40 Z M 8.449219 17.214844 C 6.960938 17.214844 5.757812 18.265625 5.757812 19.570312 L 5.757812 34.796875 C 5.757812 36.101562 6.960938 37.152344 8.449219 37.152344 L 31.550781 37.152344 C 33.039062 37.152344 34.242188 36.101562 34.242188 34.796875 L 34.242188 19.574219 C 34.242188 18.269531 33.039062 17.21875 31.550781 17.21875 Z M 29.464844 5.839844 L 26.621094 7.429688 C 24.429688 3.507812 19.476562 2.101562 15.554688 4.292969 C 11.636719 6.484375 10.230469 11.4375 12.421875 15.359375 L 9.574219 16.949219 C 6.507812 11.460938 8.519531 4.488281 13.964844 1.445312 C 19.457031 -1.621094 26.402344 0.351562 29.46875 5.839844 Z M 31.390625 14.363281 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(96.078432%,42.352942%,42.352942%);fill-opacity:1;" d="M 20 31.453125 C 18.808594 31.453125 17.863281 30.820312 17.863281 30.019531 L 17.863281 24.34375 C 17.863281 23.542969 18.808594 22.910156 20 22.910156 C 21.191406 22.910156 22.136719 23.546875 22.136719 24.34375 L 22.136719 30.023438 C 22.136719 30.820312 21.191406 31.453125 20 31.453125 Z M 20 31.453125 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 28.050781 13.054688 C 28.050781 13.820312 27.429688 14.433594 26.667969 14.433594 L 13.332031 14.433594 C 12.5625 14.433594 11.949219 13.8125 11.949219 13.054688 L 11.949219 3.476562 C 11.949219 2.710938 12.570312 2.097656 13.332031 2.097656 L 26.667969 2.097656 C 27.4375 2.097656 28.050781 2.71875 28.050781 3.476562 Z M 28.050781 13.054688 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.11765%,54.11765%,54.11765%);fill-opacity:1;" d="M 26.667969 15.175781 C 27.835938 15.175781 28.792969 14.21875 28.792969 13.054688 L 28.792969 3.476562 C 28.792969 2.308594 27.835938 1.355469 26.667969 1.355469 L 13.332031 1.355469 C 12.164062 1.355469 11.207031 2.308594 11.207031 3.476562 L 11.207031 13.054688 C 11.207031 14.21875 12.164062 15.175781 13.332031 15.175781 L 19.257812 15.175781 L 19.257812 17.152344 L 17.3125 17.152344 C 16.90625 17.152344 16.570312 17.484375 16.570312 17.894531 C 16.570312 18.300781 16.90625 18.636719 17.3125 18.636719 L 22.675781 18.636719 C 23.085938 18.636719 23.421875 18.300781 23.421875 17.894531 C 23.421875 17.484375 23.085938 17.152344 22.675781 17.152344 L 20.734375 17.152344 L 20.734375 15.175781 Z M 12.6875 13.054688 L 12.6875 3.476562 C 12.6875 3.125 12.972656 2.832031 13.332031 2.832031 L 26.667969 2.832031 C 27.019531 2.832031 27.3125 3.117188 27.3125 3.476562 L 27.3125 13.054688 C 27.3125 13.402344 27.027344 13.699219 26.667969 13.699219 L 13.332031 13.699219 C 12.980469 13.699219 12.6875 13.414062 12.6875 13.054688 Z M 12.6875 13.054688 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(85.882354%,85.882354%,85.882354%);fill-opacity:1;" d="M 16.839844 33.070312 C 16.839844 33.835938 16.21875 34.449219 15.460938 34.449219 L 2.121094 34.449219 C 1.355469 34.449219 0.742188 33.828125 0.742188 33.070312 L 0.742188 23.492188 C 0.742188 22.726562 1.363281 22.113281 2.121094 22.113281 L 15.460938 22.113281 C 16.230469 22.113281 16.839844 22.734375 16.839844 23.492188 Z M 39.265625 33.070312 C 39.265625 33.835938 38.644531 34.449219 37.886719 34.449219 L 24.546875 34.449219 C 23.78125 34.449219 23.167969 33.828125 23.167969 33.070312 L 23.167969 23.492188 C 23.167969 22.726562 23.789062 22.113281 24.546875 22.113281 L 37.878906 22.113281 C 38.644531 22.113281 39.257812 22.734375 39.257812 23.492188 L 39.257812 33.070312 Z M 39.265625 33.070312 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.11765%,54.11765%,54.11765%);fill-opacity:1;" d="M 15.453125 21.363281 L 2.121094 21.363281 C 0.957031 21.363281 0 22.316406 0 23.484375 L 0 33.0625 C 0 34.226562 0.957031 35.183594 2.121094 35.183594 L 8.050781 35.183594 L 8.050781 37.160156 L 6.105469 37.160156 C 5.699219 37.160156 5.363281 37.492188 5.363281 37.902344 C 5.363281 38.308594 5.699219 38.644531 6.105469 38.644531 L 11.46875 38.644531 C 11.878906 38.644531 12.210938 38.308594 12.210938 37.902344 C 12.210938 37.492188 11.878906 37.160156 11.46875 37.160156 L 9.527344 37.160156 L 9.527344 35.183594 L 15.453125 35.183594 C 16.621094 35.183594 17.574219 34.226562 17.574219 33.0625 L 17.574219 23.492188 C 17.574219 22.316406 16.628906 21.363281 15.453125 21.363281 Z M 16.097656 33.070312 C 16.097656 33.421875 15.8125 33.714844 15.453125 33.714844 L 2.121094 33.714844 C 1.769531 33.714844 1.476562 33.429688 1.476562 33.070312 L 1.476562 23.492188 C 1.476562 23.144531 1.761719 22.847656 2.121094 22.847656 L 15.460938 22.847656 C 15.8125 22.847656 16.105469 23.132812 16.105469 23.492188 L 16.105469 33.070312 Z M 37.878906 21.363281 L 24.546875 21.363281 C 23.378906 21.363281 22.425781 22.316406 22.425781 23.484375 L 22.425781 33.0625 C 22.425781 34.226562 23.378906 35.183594 24.546875 35.183594 L 30.472656 35.183594 L 30.472656 37.160156 L 28.53125 37.160156 C 28.121094 37.160156 27.789062 37.492188 27.789062 37.902344 C 27.789062 38.308594 28.121094 38.644531 28.53125 38.644531 L 33.894531 38.644531 C 34.300781 38.644531 34.636719 38.308594 34.636719 37.902344 C 34.636719 37.492188 34.300781 37.160156 33.894531 37.160156 L 31.949219 37.160156 L 31.949219 35.183594 L 37.878906 35.183594 C 39.042969 35.183594 40 34.226562 40 33.0625 L 40 23.492188 C 40.007812 22.316406 39.054688 21.363281 37.878906 21.363281 Z M 38.523438 33.070312 C 38.523438 33.421875 38.238281 33.714844 37.878906 33.714844 L 24.546875 33.714844 C 24.195312 33.714844 23.902344 33.429688 23.902344 33.070312 L 23.902344 23.492188 C 23.902344 23.144531 24.1875 22.847656 24.546875 22.847656 L 37.878906 22.847656 C 38.226562 22.847656 38.523438 23.132812 38.523438 23.492188 Z M 3.003906 18.628906 C 3.414062 18.628906 3.746094 18.292969 3.746094 17.886719 L 3.746094 7.722656 L 8.1875 7.722656 C 8.597656 7.722656 8.929688 7.386719 8.929688 6.980469 C 8.929688 6.570312 8.597656 6.238281 8.1875 6.238281 L 3.003906 6.238281 C 2.597656 6.238281 2.261719 6.570312 2.261719 6.980469 L 2.261719 17.894531 C 2.261719 18.300781 2.597656 18.628906 3.003906 18.628906 Z M 36.996094 18.628906 C 37.402344 18.628906 37.738281 18.292969 37.738281 17.886719 L 37.738281 6.980469 C 37.738281 6.570312 37.402344 6.238281 36.996094 6.238281 L 31.8125 6.238281 C 31.402344 6.238281 31.070312 6.570312 31.070312 6.980469 C 31.070312 7.386719 31.402344 7.722656 31.8125 7.722656 L 36.253906 7.722656 L 36.253906 17.894531 C 36.261719 18.300781 36.585938 18.628906 36.996094 18.628906 Z M 36.996094 18.628906 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(96.078432%,42.352942%,42.352942%);fill-opacity:1;" d="M 28.050781 13.054688 C 28.050781 13.820312 27.429688 14.433594 26.667969 14.433594 L 13.332031 14.433594 C 12.5625 14.433594 11.949219 13.8125 11.949219 13.054688 L 11.949219 3.476562 C 11.949219 2.710938 12.570312 2.097656 13.332031 2.097656 L 26.667969 2.097656 C 27.4375 2.097656 28.050781 2.71875 28.050781 3.476562 Z M 28.050781 13.054688 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.11765%,54.11765%,54.11765%);fill-opacity:1;" d="M 26.667969 15.175781 C 27.835938 15.175781 28.792969 14.21875 28.792969 13.054688 L 28.792969 3.476562 C 28.792969 2.308594 27.835938 1.355469 26.667969 1.355469 L 13.332031 1.355469 C 12.164062 1.355469 11.207031 2.308594 11.207031 3.476562 L 11.207031 13.054688 C 11.207031 14.21875 12.164062 15.175781 13.332031 15.175781 L 19.257812 15.175781 L 19.257812 17.152344 L 17.3125 17.152344 C 16.90625 17.152344 16.570312 17.484375 16.570312 17.894531 C 16.570312 18.300781 16.90625 18.636719 17.3125 18.636719 L 22.675781 18.636719 C 23.085938 18.636719 23.421875 18.300781 23.421875 17.894531 C 23.421875 17.484375 23.085938 17.152344 22.675781 17.152344 L 20.734375 17.152344 L 20.734375 15.175781 Z M 12.6875 13.054688 L 12.6875 3.476562 C 12.6875 3.125 12.972656 2.832031 13.332031 2.832031 L 26.667969 2.832031 C 27.019531 2.832031 27.3125 3.117188 27.3125 3.476562 L 27.3125 13.054688 C 27.3125 13.402344 27.027344 13.699219 26.667969 13.699219 L 13.332031 13.699219 C 12.980469 13.699219 12.6875 13.414062 12.6875 13.054688 Z M 12.6875 13.054688 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(85.882354%,85.882354%,85.882354%);fill-opacity:1;" d="M 16.839844 33.070312 C 16.839844 33.835938 16.21875 34.449219 15.460938 34.449219 L 2.121094 34.449219 C 1.355469 34.449219 0.742188 33.828125 0.742188 33.070312 L 0.742188 23.492188 C 0.742188 22.726562 1.363281 22.113281 2.121094 22.113281 L 15.460938 22.113281 C 16.230469 22.113281 16.839844 22.734375 16.839844 23.492188 Z M 39.265625 33.070312 C 39.265625 33.835938 38.644531 34.449219 37.886719 34.449219 L 24.546875 34.449219 C 23.78125 34.449219 23.167969 33.828125 23.167969 33.070312 L 23.167969 23.492188 C 23.167969 22.726562 23.789062 22.113281 24.546875 22.113281 L 37.878906 22.113281 C 38.644531 22.113281 39.257812 22.734375 39.257812 23.492188 L 39.257812 33.070312 Z M 39.265625 33.070312 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.11765%,54.11765%,54.11765%);fill-opacity:1;" d="M 15.453125 21.363281 L 2.121094 21.363281 C 0.957031 21.363281 0 22.316406 0 23.484375 L 0 33.0625 C 0 34.226562 0.957031 35.183594 2.121094 35.183594 L 8.050781 35.183594 L 8.050781 37.160156 L 6.105469 37.160156 C 5.699219 37.160156 5.363281 37.492188 5.363281 37.902344 C 5.363281 38.308594 5.699219 38.644531 6.105469 38.644531 L 11.46875 38.644531 C 11.878906 38.644531 12.210938 38.308594 12.210938 37.902344 C 12.210938 37.492188 11.878906 37.160156 11.46875 37.160156 L 9.527344 37.160156 L 9.527344 35.183594 L 15.453125 35.183594 C 16.621094 35.183594 17.574219 34.226562 17.574219 33.0625 L 17.574219 23.492188 C 17.574219 22.316406 16.628906 21.363281 15.453125 21.363281 Z M 16.097656 33.070312 C 16.097656 33.421875 15.8125 33.714844 15.453125 33.714844 L 2.121094 33.714844 C 1.769531 33.714844 1.476562 33.429688 1.476562 33.070312 L 1.476562 23.492188 C 1.476562 23.144531 1.761719 22.847656 2.121094 22.847656 L 15.460938 22.847656 C 15.8125 22.847656 16.105469 23.132812 16.105469 23.492188 L 16.105469 33.070312 Z M 37.878906 21.363281 L 24.546875 21.363281 C 23.378906 21.363281 22.425781 22.316406 22.425781 23.484375 L 22.425781 33.0625 C 22.425781 34.226562 23.378906 35.183594 24.546875 35.183594 L 30.472656 35.183594 L 30.472656 37.160156 L 28.53125 37.160156 C 28.121094 37.160156 27.789062 37.492188 27.789062 37.902344 C 27.789062 38.308594 28.121094 38.644531 28.53125 38.644531 L 33.894531 38.644531 C 34.300781 38.644531 34.636719 38.308594 34.636719 37.902344 C 34.636719 37.492188 34.300781 37.160156 33.894531 37.160156 L 31.949219 37.160156 L 31.949219 35.183594 L 37.878906 35.183594 C 39.042969 35.183594 40 34.226562 40 33.0625 L 40 23.492188 C 40.007812 22.316406 39.054688 21.363281 37.878906 21.363281 Z M 38.523438 33.070312 C 38.523438 33.421875 38.238281 33.714844 37.878906 33.714844 L 24.546875 33.714844 C 24.195312 33.714844 23.902344 33.429688 23.902344 33.070312 L 23.902344 23.492188 C 23.902344 23.144531 24.1875 22.847656 24.546875 22.847656 L 37.878906 22.847656 C 38.226562 22.847656 38.523438 23.132812 38.523438 23.492188 Z M 3.003906 18.628906 C 3.414062 18.628906 3.746094 18.292969 3.746094 17.886719 L 3.746094 7.722656 L 8.1875 7.722656 C 8.597656 7.722656 8.929688 7.386719 8.929688 6.980469 C 8.929688 6.570312 8.597656 6.238281 8.1875 6.238281 L 3.003906 6.238281 C 2.597656 6.238281 2.261719 6.570312 2.261719 6.980469 L 2.261719 17.894531 C 2.261719 18.300781 2.597656 18.628906 3.003906 18.628906 Z M 36.996094 18.628906 C 37.402344 18.628906 37.738281 18.292969 37.738281 17.886719 L 37.738281 6.980469 C 37.738281 6.570312 37.402344 6.238281 36.996094 6.238281 L 31.8125 6.238281 C 31.402344 6.238281 31.070312 6.570312 31.070312 6.980469 C 31.070312 7.386719 31.402344 7.722656 31.8125 7.722656 L 36.253906 7.722656 L 36.253906 17.894531 C 36.261719 18.300781 36.585938 18.628906 36.996094 18.628906 Z M 36.996094 18.628906 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

@@ -0,0 +1,2 @@
<svg width="48" height="48" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g><rect x="11" y="1" width="2" height="5" opacity=".14"/><rect x="11" y="1" width="2" height="5" transform="rotate(30 12 12)" opacity=".29"/><rect x="11" y="1" width="2" height="5" transform="rotate(60 12 12)" opacity=".43"/><rect x="11" y="1" width="2" height="5" transform="rotate(90 12 12)" opacity=".57"/><rect x="11" y="1" width="2" height="5" transform="rotate(120 12 12)" opacity=".71"/><rect x="11" y="1" width="2" height="5" transform="rotate(150 12 12)" opacity=".86"/><rect x="11" y="1" width="2" height="5" transform="rotate(180 12 12)"/><animateTransform attributeName="transform" type="rotate" calcMode="discrete" dur="0.75s" values="0 12 12;30 12 12;60 12 12;90 12 12;120 12 12;150 12 12;180 12 12;210 12 12;240 12 12;270 12 12;300 12 12;330 12 12;360 12 12" repeatCount="indefinite"/></g></svg>
<!-- https://github.com/n3r4zzurr0/svg-spinners MIT License -->

After

Width:  |  Height:  |  Size: 958 B

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.11765%,54.11765%,54.11765%);fill-opacity:1;" d="M 21.25 31.292969 L 18.75 31.292969 L 18.75 26.875 L 21.25 26.875 Z M 38.75 33.792969 L 25 33.792969 L 25 36.292969 L 38.75 36.292969 Z M 1.25 33.792969 L 1.25 36.292969 L 15 36.292969 L 15 33.792969 Z M 1.25 33.792969 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(96.078432%,42.352942%,42.352942%);fill-opacity:1;" d="M 21.25 31.292969 L 15 31.292969 L 15 38.792969 L 25 38.792969 L 25 31.292969 Z M 22.5 36.292969 L 17.5 36.292969 L 17.5 33.792969 L 22.5 33.792969 Z M 22.5 36.292969 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(80.000001%,80.000001%,80.000001%);fill-opacity:1;" d="M 4.375 1.457031 L 4.375 28.542969 L 35.625 28.542969 L 35.625 1.457031 Z M 33.542969 26.457031 L 6.457031 26.457031 L 6.457031 3.542969 L 33.542969 3.542969 Z M 33.542969 26.457031 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.11765%,54.11765%,54.11765%);fill-opacity:1;" d="M 12.707031 22.289062 L 14.792969 22.289062 L 14.792969 24.375 L 25.207031 24.375 L 25.207031 22.289062 L 27.292969 22.289062 L 27.292969 18.125 L 31.457031 18.125 L 31.457031 5.625 L 8.542969 5.625 L 8.542969 18.125 L 12.707031 18.125 Z M 12.707031 22.289062 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(96.078432%,42.352942%,42.352942%);fill-opacity:1;" d="M 25.207031 9.792969 L 27.292969 9.792969 L 27.292969 13.957031 L 25.207031 13.957031 Z M 21.042969 9.792969 L 23.125 9.792969 L 23.125 13.957031 L 21.042969 13.957031 Z M 16.875 9.792969 L 18.957031 9.792969 L 18.957031 13.957031 L 16.875 13.957031 Z M 12.707031 9.792969 L 14.792969 9.792969 L 14.792969 13.957031 L 12.707031 13.957031 Z M 12.707031 9.792969 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.11765%,54.11765%,54.11765%);fill-opacity:1;" d="M 21.25 31.292969 L 18.75 31.292969 L 18.75 26.875 L 21.25 26.875 Z M 38.75 33.792969 L 25 33.792969 L 25 36.292969 L 38.75 36.292969 Z M 1.25 33.792969 L 1.25 36.292969 L 15 36.292969 L 15 33.792969 Z M 1.25 33.792969 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 21.25 31.292969 L 15 31.292969 L 15 38.792969 L 25 38.792969 L 25 31.292969 Z M 22.5 36.292969 L 17.5 36.292969 L 17.5 33.792969 L 22.5 33.792969 Z M 22.5 36.292969 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(80.000001%,80.000001%,80.000001%);fill-opacity:1;" d="M 4.375 1.457031 L 4.375 28.542969 L 35.625 28.542969 L 35.625 1.457031 Z M 33.542969 26.457031 L 6.457031 26.457031 L 6.457031 3.542969 L 33.542969 3.542969 Z M 33.542969 26.457031 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.11765%,54.11765%,54.11765%);fill-opacity:1;" d="M 12.707031 22.289062 L 14.792969 22.289062 L 14.792969 24.375 L 25.207031 24.375 L 25.207031 22.289062 L 27.292969 22.289062 L 27.292969 18.125 L 31.457031 18.125 L 31.457031 5.625 L 8.542969 5.625 L 8.542969 18.125 L 12.707031 18.125 Z M 12.707031 22.289062 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 25.207031 9.792969 L 27.292969 9.792969 L 27.292969 13.957031 L 25.207031 13.957031 Z M 21.042969 9.792969 L 23.125 9.792969 L 23.125 13.957031 L 21.042969 13.957031 Z M 16.875 9.792969 L 18.957031 9.792969 L 18.957031 13.957031 L 16.875 13.957031 Z M 12.707031 9.792969 L 14.792969 9.792969 L 14.792969 13.957031 L 12.707031 13.957031 Z M 12.707031 9.792969 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 48 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(85.882354%,85.882354%,85.882354%);fill-opacity:1;" d="M 42.273438 14.421875 C 41.640625 15.179688 40.535156 15.300781 39.761719 14.71875 C 34.921875 11.101562 29.769531 8.539062 23.980469 8.539062 C 18.191406 8.539062 13.058594 11.101562 8.21875 14.71875 C 7.425781 15.300781 6.339844 15.179688 5.707031 14.441406 C 5.351562 14.019531 5.214844 13.539062 5.273438 13 C 5.332031 12.460938 5.589844 12.019531 6.003906 11.699219 C 11.496094 7.601562 17.441406 4.800781 23.980469 4.800781 C 30.519531 4.800781 36.464844 7.601562 41.957031 11.699219 C 42.390625 12.019531 42.628906 12.460938 42.6875 13 C 42.746094 13.539062 42.628906 14.019531 42.273438 14.421875 Z M 42.273438 14.421875 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(85.882354%,85.882354%,85.882354%);fill-opacity:1;" d="M 24 17.199219 C 27.929688 17.199219 31.328125 18.398438 34.6875 20.820312 C 35.476562 21.378906 36.542969 21.261719 37.15625 20.519531 C 37.511719 20.101562 37.648438 19.621094 37.589844 19.078125 C 37.53125 18.539062 37.253906 18.101562 36.820312 17.78125 C 32.828125 14.921875 28.679688 13.480469 24 13.480469 C 19.320312 13.480469 15.152344 14.921875 11.179688 17.78125 C 10.746094 18.101562 10.488281 18.539062 10.410156 19.078125 C 10.351562 19.621094 10.488281 20.121094 10.84375 20.519531 C 11.476562 21.261719 12.542969 21.398438 13.3125 20.820312 C 16.652344 18.421875 20.050781 17.199219 24 17.199219 Z M 24 25.621094 L 23.921875 25.621094 C 22.042969 25.621094 20.226562 26.179688 18.6875 27.21875 C 17.894531 27.738281 16.867188 27.601562 16.257812 26.878906 C 15.902344 26.460938 15.742188 25.960938 15.820312 25.398438 C 15.902344 24.839844 16.179688 24.398438 16.632812 24.101562 C 18.785156 22.660156 21.3125 21.878906 23.921875 21.878906 L 24.058594 21.878906 C 26.667969 21.878906 29.214844 22.660156 31.347656 24.101562 C 31.800781 24.398438 32.078125 24.859375 32.15625 25.398438 C 32.238281 25.960938 32.078125 26.460938 31.722656 26.878906 C 31.109375 27.601562 30.0625 27.738281 29.292969 27.21875 C 27.753906 26.179688 25.9375 25.621094 24.058594 25.621094 Z M 24 25.621094 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(85.882354%,85.882354%,85.882354%);fill-opacity:1;" d="M 21.214844 33.078125 C 21.175781 34.121094 21.707031 35.078125 22.578125 35.601562 C 23.445312 36.121094 24.554688 36.121094 25.421875 35.601562 C 26.292969 35.078125 26.824219 34.101562 26.785156 33.078125 C 26.726562 31.558594 25.5 30.359375 24 30.359375 C 22.5 30.359375 21.253906 31.558594 21.214844 33.078125 Z M 21.214844 33.078125 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 48 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(85.882354%,85.882354%,85.882354%);fill-opacity:1;" d="M 42.273438 14.421875 C 41.640625 15.179688 40.535156 15.300781 39.761719 14.71875 C 34.921875 11.101562 29.769531 8.539062 23.980469 8.539062 C 18.191406 8.539062 13.058594 11.101562 8.21875 14.71875 C 7.425781 15.300781 6.339844 15.179688 5.707031 14.441406 C 5.351562 14.019531 5.214844 13.539062 5.273438 13 C 5.332031 12.460938 5.589844 12.019531 6.003906 11.699219 C 11.496094 7.601562 17.441406 4.800781 23.980469 4.800781 C 30.519531 4.800781 36.464844 7.601562 41.957031 11.699219 C 42.390625 12.019531 42.628906 12.460938 42.6875 13 C 42.746094 13.539062 42.628906 14.019531 42.273438 14.421875 Z M 42.273438 14.421875 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(85.882354%,85.882354%,85.882354%);fill-opacity:1;" d="M 24 17.199219 C 27.929688 17.199219 31.328125 18.398438 34.6875 20.820312 C 35.476562 21.378906 36.542969 21.261719 37.15625 20.519531 C 37.511719 20.101562 37.648438 19.621094 37.589844 19.078125 C 37.53125 18.539062 37.253906 18.101562 36.820312 17.78125 C 32.828125 14.921875 28.679688 13.480469 24 13.480469 C 19.320312 13.480469 15.152344 14.921875 11.179688 17.78125 C 10.746094 18.101562 10.488281 18.539062 10.410156 19.078125 C 10.351562 19.621094 10.488281 20.121094 10.84375 20.519531 C 11.476562 21.261719 12.542969 21.398438 13.3125 20.820312 C 16.652344 18.421875 20.050781 17.199219 24 17.199219 Z M 24 25.621094 L 23.921875 25.621094 C 22.042969 25.621094 20.226562 26.179688 18.6875 27.21875 C 17.894531 27.738281 16.867188 27.601562 16.257812 26.878906 C 15.902344 26.460938 15.742188 25.960938 15.820312 25.398438 C 15.902344 24.839844 16.179688 24.398438 16.632812 24.101562 C 18.785156 22.660156 21.3125 21.878906 23.921875 21.878906 L 24.058594 21.878906 C 26.667969 21.878906 29.214844 22.660156 31.347656 24.101562 C 31.800781 24.398438 32.078125 24.859375 32.15625 25.398438 C 32.238281 25.960938 32.078125 26.460938 31.722656 26.878906 C 31.109375 27.601562 30.0625 27.738281 29.292969 27.21875 C 27.753906 26.179688 25.9375 25.621094 24.058594 25.621094 Z M 24 25.621094 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(90.980393%,35.686275%,35.686275%);fill-opacity:1;" d="M 21.214844 33.078125 C 21.175781 34.121094 21.707031 35.078125 22.578125 35.601562 C 23.445312 36.121094 24.554688 36.121094 25.421875 35.601562 C 26.292969 35.078125 26.824219 34.101562 26.785156 33.078125 C 26.726562 31.558594 25.5 30.359375 24 30.359375 C 22.5 30.359375 21.253906 31.558594 21.214844 33.078125 Z M 21.214844 33.078125 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 48 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(85.882354%,85.882354%,85.882354%);fill-opacity:1;" d="M 42.273438 18.421875 C 41.640625 19.179688 40.535156 19.300781 39.761719 18.71875 C 34.921875 15.101562 29.769531 12.539062 23.980469 12.539062 C 18.191406 12.539062 13.058594 15.101562 8.21875 18.71875 C 7.425781 19.300781 6.339844 19.179688 5.707031 18.441406 C 5.351562 18.019531 5.214844 17.539062 5.273438 17 C 5.332031 16.460938 5.589844 16.019531 6.003906 15.699219 C 11.496094 11.601562 17.441406 8.800781 23.980469 8.800781 C 30.519531 8.800781 36.464844 11.601562 41.957031 15.699219 C 42.390625 16.019531 42.628906 16.460938 42.6875 17 C 42.746094 17.539062 42.628906 18.019531 42.273438 18.421875 Z M 42.273438 18.421875 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(85.882354%,85.882354%,85.882354%);fill-opacity:1;" d="M 24 21.199219 C 27.929688 21.199219 31.328125 22.398438 34.6875 24.820312 C 35.476562 25.378906 36.542969 25.261719 37.15625 24.519531 C 37.511719 24.101562 37.648438 23.621094 37.589844 23.078125 C 37.53125 22.539062 37.253906 22.101562 36.820312 21.78125 C 32.828125 18.921875 28.679688 17.480469 24 17.480469 C 19.320312 17.480469 15.152344 18.921875 11.179688 21.78125 C 10.746094 22.101562 10.488281 22.539062 10.410156 23.078125 C 10.351562 23.621094 10.488281 24.121094 10.84375 24.519531 C 11.476562 25.261719 12.542969 25.398438 13.3125 24.820312 C 16.652344 22.421875 20.050781 21.199219 24 21.199219 Z M 24 21.199219 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(96.078432%,42.352942%,42.352942%);fill-opacity:1;" d="M 24 29.621094 L 23.921875 29.621094 C 22.042969 29.621094 20.226562 30.179688 18.6875 31.21875 C 17.894531 31.738281 16.867188 31.601562 16.257812 30.878906 C 15.902344 30.460938 15.742188 29.960938 15.820312 29.398438 C 15.902344 28.839844 16.179688 28.398438 16.632812 28.101562 C 18.785156 26.660156 21.3125 25.878906 23.921875 25.878906 L 24.058594 25.878906 C 26.667969 25.878906 29.214844 26.660156 31.347656 28.101562 C 31.800781 28.398438 32.078125 28.859375 32.15625 29.398438 C 32.238281 29.960938 32.078125 30.460938 31.722656 30.878906 C 31.109375 31.601562 30.0625 31.738281 29.292969 31.21875 C 27.753906 30.179688 25.9375 29.621094 24.058594 29.621094 Z M 21.214844 37.078125 C 21.175781 38.121094 21.707031 39.078125 22.578125 39.601562 C 23.445312 40.121094 24.554688 40.121094 25.421875 39.601562 C 26.292969 39.078125 26.824219 38.101562 26.785156 37.078125 C 26.726562 35.558594 25.5 34.359375 24 34.359375 C 22.5 34.359375 21.253906 35.558594 21.214844 37.078125 Z M 21.214844 37.078125 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 48 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(85.882354%,85.882354%,85.882354%);fill-opacity:1;" d="M 42.292969 18.441406 C 41.640625 19.199219 40.554688 19.320312 39.761719 18.738281 C 34.921875 15.121094 29.75 12.578125 24 12.578125 C 18.25 12.578125 13.058594 15.121094 8.21875 18.738281 C 7.445312 19.320312 6.339844 19.199219 5.707031 18.441406 L 5.6875 18.421875 C 5.332031 18.019531 5.195312 17.539062 5.253906 16.980469 C 5.3125 16.441406 5.570312 16 5.984375 15.679688 C 11.515625 11.578125 17.441406 8.800781 23.980469 8.800781 C 30.519531 8.800781 36.464844 11.601562 41.957031 15.699219 C 42.390625 16.019531 42.628906 16.460938 42.6875 17 C 42.746094 17.539062 42.605469 18.019531 42.25 18.441406 Z M 42.292969 18.441406 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(90.196079%,63.529414%,23.529412%);fill-opacity:1;" d="M 24 21.21875 C 27.929688 21.21875 31.328125 22.421875 34.6875 24.839844 C 35.457031 25.398438 36.542969 25.28125 37.175781 24.539062 L 37.195312 24.519531 C 37.550781 24.101562 37.6875 23.621094 37.628906 23.078125 C 37.570312 22.539062 37.292969 22.101562 36.859375 21.78125 C 32.867188 18.921875 28.703125 17.480469 24.039062 17.480469 C 19.359375 17.480469 15.210938 18.921875 11.21875 21.78125 C 10.785156 22.101562 10.507812 22.539062 10.449219 23.078125 C 10.390625 23.621094 10.527344 24.101562 10.882812 24.519531 L 10.902344 24.539062 C 11.535156 25.28125 12.601562 25.421875 13.394531 24.839844 C 16.730469 22.441406 20.128906 21.21875 24.078125 21.21875 Z M 24 29.621094 L 23.921875 29.621094 C 22.042969 29.621094 20.226562 30.179688 18.6875 31.21875 C 17.894531 31.761719 16.867188 31.601562 16.257812 30.878906 C 15.902344 30.460938 15.761719 29.960938 15.820312 29.398438 C 15.902344 28.839844 16.179688 28.398438 16.632812 28.101562 C 18.785156 26.660156 21.3125 25.878906 23.921875 25.878906 L 24.078125 25.878906 C 26.6875 25.878906 29.234375 26.660156 31.367188 28.101562 C 31.820312 28.398438 32.097656 28.839844 32.179688 29.398438 C 32.257812 29.960938 32.097656 30.460938 31.742188 30.878906 C 31.132812 31.601562 30.082031 31.761719 29.3125 31.21875 C 27.773438 30.179688 25.957031 29.621094 24.078125 29.621094 Z M 21.214844 37.078125 C 21.175781 38.101562 21.707031 39.078125 22.578125 39.601562 C 23.445312 40.121094 24.554688 40.121094 25.421875 39.601562 C 26.292969 39.078125 26.824219 38.101562 26.785156 37.078125 C 26.726562 35.558594 25.5 34.359375 24 34.359375 C 22.5 34.359375 21.273438 35.558594 21.214844 37.078125 Z M 21.214844 37.078125 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 48 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 42.265625 18.4375 C 41.632812 19.175781 40.527344 19.316406 39.777344 18.738281 C 34.9375 15.117188 29.765625 12.558594 24.015625 12.558594 C 18.230469 12.558594 13.09375 15.117188 8.253906 18.738281 C 7.464844 19.316406 6.398438 19.199219 5.765625 18.4375 C 5.429688 18.039062 5.273438 17.539062 5.351562 16.996094 C 5.410156 16.457031 5.667969 16.019531 6.082031 15.699219 C 11.574219 11.597656 17.5 8.777344 24.054688 8.777344 C 30.613281 8.777344 36.539062 11.578125 42.03125 15.699219 C 42.445312 16.019531 42.71875 16.476562 42.761719 16.996094 C 42.820312 17.539062 42.679688 18.019531 42.34375 18.4375 Z M 42.265625 18.4375 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 23.976562 21.199219 C 27.90625 21.199219 31.304688 22.398438 34.664062 24.816406 C 35.453125 25.375 36.519531 25.238281 37.132812 24.496094 C 37.46875 24.078125 37.625 23.597656 37.546875 23.058594 C 37.488281 22.515625 37.230469 22.078125 36.777344 21.757812 C 32.785156 18.878906 28.636719 17.457031 23.957031 17.457031 C 19.277344 17.457031 15.109375 18.898438 11.140625 21.757812 C 10.683594 22.078125 10.429688 22.496094 10.367188 23.058594 C 10.289062 23.597656 10.449219 24.097656 10.785156 24.496094 C 11.414062 25.238281 12.460938 25.375 13.253906 24.816406 C 16.628906 22.417969 20.046875 21.199219 23.976562 21.199219 Z M 23.976562 29.617188 L 23.898438 29.617188 C 22.042969 29.617188 20.183594 30.175781 18.644531 31.214844 C 17.855469 31.757812 16.828125 31.597656 16.195312 30.875 C 15.820312 30.457031 15.703125 29.9375 15.78125 29.394531 C 15.859375 28.835938 16.117188 28.375 16.589844 28.097656 C 18.742188 26.65625 21.269531 25.855469 23.898438 25.855469 L 24.054688 25.855469 C 26.664062 25.855469 29.210938 26.636719 31.363281 28.097656 C 31.816406 28.417969 32.09375 28.835938 32.171875 29.394531 C 32.253906 29.957031 32.09375 30.457031 31.757812 30.875 C 31.148438 31.597656 30.101562 31.757812 29.308594 31.214844 C 27.769531 30.175781 25.953125 29.617188 24.054688 29.617188 Z M 21.191406 37.074219 C 21.171875 38.117188 21.6875 39.074219 22.554688 39.59375 C 23.425781 40.136719 24.53125 40.136719 25.398438 39.59375 C 26.269531 39.054688 26.78125 38.117188 26.761719 37.074219 C 26.703125 35.554688 25.476562 34.355469 23.976562 34.355469 C 22.476562 34.355469 21.25 35.554688 21.191406 37.074219 Z M 21.191406 37.074219 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 48 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(85.882354%,85.882354%,85.882354%);fill-opacity:1;" d="M 42.273438 14.421875 C 41.640625 15.179688 40.535156 15.300781 39.761719 14.71875 C 34.921875 11.101562 29.769531 8.539062 23.980469 8.539062 C 18.191406 8.539062 13.058594 11.101562 8.21875 14.71875 C 7.425781 15.300781 6.339844 15.179688 5.707031 14.441406 C 5.351562 14.019531 5.214844 13.539062 5.273438 13 C 5.332031 12.460938 5.589844 12.019531 6.003906 11.699219 C 11.496094 7.601562 17.441406 4.800781 23.980469 4.800781 C 30.519531 4.800781 36.464844 7.601562 41.957031 11.699219 C 42.390625 12.019531 42.628906 12.460938 42.6875 13 C 42.746094 13.539062 42.628906 14.019531 42.273438 14.421875 Z M 42.273438 14.421875 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(85.882354%,85.882354%,85.882354%);fill-opacity:1;" d="M 24 17.199219 C 27.929688 17.199219 31.328125 18.398438 34.6875 20.820312 C 35.476562 21.378906 36.542969 21.261719 37.15625 20.519531 C 37.511719 20.101562 37.648438 19.621094 37.589844 19.078125 C 37.53125 18.539062 37.253906 18.101562 36.820312 17.78125 C 32.828125 14.921875 28.679688 13.480469 24 13.480469 C 19.320312 13.480469 15.152344 14.921875 11.179688 17.78125 C 10.746094 18.101562 10.488281 18.539062 10.410156 19.078125 C 10.351562 19.621094 10.488281 20.121094 10.84375 20.519531 C 11.476562 21.261719 12.542969 21.398438 13.3125 20.820312 C 16.652344 18.421875 20.050781 17.199219 24 17.199219 Z M 24 25.621094 L 23.921875 25.621094 C 22.042969 25.621094 20.226562 26.179688 18.6875 27.21875 C 17.894531 27.738281 16.867188 27.601562 16.257812 26.878906 C 15.902344 26.460938 15.742188 25.960938 15.820312 25.398438 C 15.902344 24.839844 16.179688 24.398438 16.632812 24.101562 C 18.785156 22.660156 21.3125 21.878906 23.921875 21.878906 L 24.058594 21.878906 C 26.667969 21.878906 29.214844 22.660156 31.347656 24.101562 C 31.800781 24.398438 32.078125 24.859375 32.15625 25.398438 C 32.238281 25.960938 32.078125 26.460938 31.722656 26.878906 C 31.109375 27.601562 30.0625 27.738281 29.292969 27.21875 C 27.753906 26.179688 25.9375 25.621094 24.058594 25.621094 Z M 21.214844 33.078125 C 21.175781 34.121094 21.707031 35.078125 22.578125 35.601562 C 23.445312 36.121094 24.554688 36.121094 25.421875 35.601562 C 26.292969 35.078125 26.824219 34.101562 26.785156 33.078125 C 26.726562 31.558594 25.5 30.359375 24 30.359375 C 22.5 30.359375 21.253906 31.558594 21.214844 33.078125 Z M 21.214844 33.078125 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(96.078432%,42.352942%,42.352942%);fill-opacity:1;" d="M 33.085938 26.078125 C 29.945312 26.078125 27.398438 28.660156 27.398438 31.839844 C 27.398438 35.019531 29.945312 37.601562 33.085938 37.601562 C 36.226562 37.601562 38.773438 35.019531 38.773438 31.839844 C 38.773438 28.660156 36.226562 26.078125 33.085938 26.078125 Z M 35.515625 33.558594 C 35.714844 33.761719 35.714844 34.101562 35.515625 34.300781 C 35.320312 34.5 34.984375 34.5 34.785156 34.300781 L 33.085938 32.578125 L 31.386719 34.300781 C 31.191406 34.5 30.855469 34.5 30.65625 34.300781 C 30.460938 34.101562 30.460938 33.761719 30.65625 33.558594 L 32.355469 31.839844 L 30.65625 30.121094 C 30.460938 29.921875 30.460938 29.578125 30.65625 29.378906 C 30.855469 29.179688 31.191406 29.179688 31.386719 29.378906 L 33.085938 31.101562 L 34.785156 29.378906 C 34.984375 29.179688 35.320312 29.179688 35.515625 29.378906 C 35.714844 29.578125 35.714844 29.921875 35.515625 30.121094 L 33.816406 31.839844 Z M 35.515625 33.558594 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.11765%,54.11765%,54.11765%);fill-opacity:1;" d="M 40 18.75 L 35 18.75 L 35 12.5 L 32.5 12.5 L 32.5 18.75 L 21.25 18.75 L 21.25 12.5 L 18.75 12.5 L 18.75 18.75 L 7.5 18.75 L 7.5 12.5 L 5 12.5 L 5 18.75 L 0 18.75 L 0 21.25 L 11.25 21.25 L 11.25 27.5 L 13.75 27.5 L 13.75 21.25 L 25 21.25 L 25 27.5 L 27.5 27.5 L 27.5 21.25 L 40 21.25 Z M 40 18.75 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 22.5 13.75 L 17.5 13.75 C 16.125 13.75 15 12.625 15 11.25 L 15 6.25 C 15 4.875 16.125 3.75 17.5 3.75 L 22.5 3.75 C 23.875 3.75 25 4.875 25 6.25 L 25 11.25 C 25 12.625 23.875 13.75 22.5 13.75 Z M 36.25 13.75 L 31.25 13.75 C 29.875 13.75 28.75 12.625 28.75 11.25 L 28.75 6.25 C 28.75 4.875 29.875 3.75 31.25 3.75 L 36.25 3.75 C 37.625 3.75 38.75 4.875 38.75 6.25 L 38.75 11.25 C 38.75 12.625 37.625 13.75 36.25 13.75 Z M 8.75 13.75 L 3.75 13.75 C 2.375 13.75 1.25 12.625 1.25 11.25 L 1.25 6.25 C 1.25 4.875 2.375 3.75 3.75 3.75 L 8.75 3.75 C 10.125 3.75 11.25 4.875 11.25 6.25 L 11.25 11.25 C 11.25 12.625 10.125 13.75 8.75 13.75 Z M 15 36.25 L 10 36.25 C 8.625 36.25 7.5 35.125 7.5 33.75 L 7.5 28.75 C 7.5 27.375 8.625 26.25 10 26.25 L 15 26.25 C 16.375 26.25 17.5 27.375 17.5 28.75 L 17.5 33.75 C 17.5 35.125 16.375 36.25 15 36.25 Z M 28.75 36.25 L 23.75 36.25 C 22.375 36.25 21.25 35.125 21.25 33.75 L 21.25 28.75 C 21.25 27.375 22.375 26.25 23.75 26.25 L 28.75 26.25 C 30.125 26.25 31.25 27.375 31.25 28.75 L 31.25 33.75 C 31.25 35.125 30.125 36.25 28.75 36.25 Z M 28.75 36.25 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.11765%,54.11765%,54.11765%);fill-opacity:1;" d="M 40 18.75 L 35 18.75 L 35 12.5 L 32.5 12.5 L 32.5 18.75 L 21.25 18.75 L 21.25 12.5 L 18.75 12.5 L 18.75 18.75 L 7.5 18.75 L 7.5 12.5 L 5 12.5 L 5 18.75 L 0 18.75 L 0 21.25 L 11.25 21.25 L 11.25 27.5 L 13.75 27.5 L 13.75 21.25 L 25 21.25 L 25 27.5 L 27.5 27.5 L 27.5 21.25 L 40 21.25 Z M 40 18.75 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(85.882354%,85.882354%,85.882354%);fill-opacity:1;" d="M 22.5 13.75 L 17.5 13.75 C 16.125 13.75 15 12.625 15 11.25 L 15 6.25 C 15 4.875 16.125 3.75 17.5 3.75 L 22.5 3.75 C 23.875 3.75 25 4.875 25 6.25 L 25 11.25 C 25 12.625 23.875 13.75 22.5 13.75 Z M 36.25 13.75 L 31.25 13.75 C 29.875 13.75 28.75 12.625 28.75 11.25 L 28.75 6.25 C 28.75 4.875 29.875 3.75 31.25 3.75 L 36.25 3.75 C 37.625 3.75 38.75 4.875 38.75 6.25 L 38.75 11.25 C 38.75 12.625 37.625 13.75 36.25 13.75 Z M 8.75 13.75 L 3.75 13.75 C 2.375 13.75 1.25 12.625 1.25 11.25 L 1.25 6.25 C 1.25 4.875 2.375 3.75 3.75 3.75 L 8.75 3.75 C 10.125 3.75 11.25 4.875 11.25 6.25 L 11.25 11.25 C 11.25 12.625 10.125 13.75 8.75 13.75 Z M 15 36.25 L 10 36.25 C 8.625 36.25 7.5 35.125 7.5 33.75 L 7.5 28.75 C 7.5 27.375 8.625 26.25 10 26.25 L 15 26.25 C 16.375 26.25 17.5 27.375 17.5 28.75 L 17.5 33.75 C 17.5 35.125 16.375 36.25 15 36.25 Z M 28.75 36.25 L 23.75 36.25 C 22.375 36.25 21.25 35.125 21.25 33.75 L 21.25 28.75 C 21.25 27.375 22.375 26.25 23.75 26.25 L 28.75 26.25 C 30.125 26.25 31.25 27.375 31.25 28.75 L 31.25 33.75 C 31.25 35.125 30.125 36.25 28.75 36.25 Z M 28.75 36.25 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 23.5625 0.0546875 C 18.582031 0.0507812 13.882812 2.359375 10.84375 6.300781 C 12.640625 5.710938 14.523438 5.410156 16.417969 5.414062 C 26.296875 5.414062 34.300781 13.417969 34.300781 23.296875 C 34.304688 25.167969 34.011719 27.027344 33.4375 28.808594 C 37.351562 25.765625 39.636719 21.085938 39.632812 16.128906 C 39.636719 7.25 32.441406 0.0546875 23.5625 0.0546875 Z M 23.5625 0.0546875 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(25.490198%,25.490198%,25.490198%);fill-opacity:1;" d="M 16.4375 7.175781 C 7.554688 7.175781 0.285156 14.445312 0.285156 23.328125 C 0.285156 32.210938 7.554688 39.476562 16.4375 39.476562 C 25.316406 39.476562 32.585938 32.207031 32.585938 23.328125 C 32.585938 14.445312 25.316406 7.175781 16.4375 7.175781 Z M 11.5 9.871094 C 10.695312 10.855469 9.976562 12.113281 9.347656 13.550781 C 8.636719 13.183594 7.976562 12.730469 7.378906 12.203125 C 8.632812 11.214844 9.976562 10.40625 11.503906 9.871094 Z M 6.027344 13.457031 C 6.746094 14.175781 7.644531 14.714844 8.628906 15.253906 C 7.910156 17.40625 7.554688 19.828125 7.464844 22.429688 L 2.082031 22.429688 C 2.351562 18.929688 3.785156 15.789062 6.027344 13.457031 Z M 2.171875 24.222656 L 7.554688 24.222656 C 7.640625 26.65625 8.035156 29.066406 8.71875 31.402344 C 7.734375 31.941406 6.835938 32.476562 6.121094 33.195312 C 3.785156 30.863281 2.351562 27.722656 2.171875 24.222656 Z M 7.378906 34.453125 C 7.914062 34.003906 8.632812 33.554688 9.351562 33.105469 C 9.980469 34.542969 10.695312 35.796875 11.503906 36.789062 C 9.976562 36.246094 8.628906 35.4375 7.378906 34.453125 Z M 15.539062 37.503906 C 13.65625 37.054688 12.039062 35.082031 10.871094 32.300781 C 12.308594 31.761719 13.832031 31.496094 15.539062 31.40625 Z M 15.539062 29.609375 C 13.65625 29.699219 11.855469 30.058594 10.335938 30.6875 C 9.796875 28.800781 9.4375 26.558594 9.347656 24.226562 L 15.628906 24.226562 L 15.628906 29.609375 Z M 15.539062 22.433594 L 9.257812 22.433594 C 9.347656 20.101562 9.707031 17.855469 10.246094 15.972656 C 11.910156 16.613281 13.667969 16.976562 15.449219 17.050781 L 15.449219 22.433594 Z M 15.539062 15.253906 C 13.832031 15.164062 12.308594 14.804688 10.871094 14.359375 C 12.039062 11.578125 13.65625 9.691406 15.539062 9.152344 Z M 25.5 12.203125 C 24.960938 12.652344 24.242188 13.101562 23.527344 13.550781 C 22.898438 12.113281 22.179688 10.859375 21.371094 9.871094 C 22.898438 10.40625 24.242188 11.214844 25.5 12.203125 Z M 17.332031 9.152344 C 19.21875 9.601562 20.832031 11.574219 21.996094 14.355469 C 20.5625 14.894531 19.039062 15.164062 17.332031 15.253906 Z M 17.332031 17.046875 C 19.21875 16.957031 21.015625 16.597656 22.535156 15.96875 C 23.074219 17.855469 23.433594 20.097656 23.523438 22.429688 L 17.246094 22.429688 L 17.246094 17.046875 Z M 17.332031 24.222656 L 23.613281 24.222656 C 23.523438 26.554688 23.164062 28.800781 22.625 30.683594 C 20.960938 30.042969 19.203125 29.679688 17.421875 29.609375 L 17.421875 24.222656 Z M 17.332031 37.503906 L 17.332031 31.402344 C 19.039062 31.492188 20.5625 31.851562 21.996094 32.300781 C 20.832031 35.167969 19.214844 37.054688 17.332031 37.503906 Z M 21.371094 36.785156 C 22.175781 35.796875 22.894531 34.539062 23.523438 33.101562 C 24.234375 33.46875 24.894531 33.921875 25.496094 34.453125 C 24.242188 35.4375 22.894531 36.246094 21.371094 36.785156 Z M 26.84375 33.195312 C 26.125 32.476562 25.226562 31.9375 24.242188 31.402344 C 24.957031 29.246094 25.316406 26.824219 25.40625 24.222656 L 30.789062 24.222656 C 30.523438 27.722656 29.085938 30.863281 26.84375 33.195312 Z M 25.40625 22.429688 C 25.320312 20 24.925781 17.585938 24.242188 15.253906 C 25.226562 14.714844 26.125 14.175781 26.84375 13.457031 C 29.085938 15.789062 30.609375 18.929688 30.789062 22.429688 Z M 23.613281 0 C 18.410156 0 13.832031 2.421875 10.871094 6.28125 C 12.238281 5.832031 13.65625 5.558594 15.089844 5.472656 C 14.910156 5.382812 14.730469 5.203125 14.550781 5.113281 C 15.808594 4.125 17.148438 3.316406 18.679688 2.777344 C 18.050781 3.496094 17.511719 4.484375 16.972656 5.46875 C 17.601562 5.46875 18.230469 5.558594 18.859375 5.648438 C 19.9375 3.679688 21.28125 2.425781 22.804688 2.066406 L 22.804688 6.640625 C 23.433594 6.910156 24.0625 7.089844 24.601562 7.449219 L 24.601562 2.066406 C 26.484375 2.511719 28.097656 4.488281 29.265625 7.269531 C 28.152344 7.726562 26.96875 8 25.765625 8.078125 C 26.488281 8.523438 27.203125 8.972656 27.832031 9.511719 C 28.546875 9.332031 29.265625 9.148438 29.894531 8.882812 C 30.253906 9.960938 30.433594 11.125 30.609375 12.292969 C 31.738281 13.71875 32.621094 15.328125 33.214844 17.046875 L 37.878906 17.046875 C 37.699219 20.457031 36.261719 23.417969 34.109375 25.75 C 33.929688 26.828125 33.75 27.902344 33.394531 28.890625 C 37.25 25.929688 39.671875 21.355469 39.671875 16.152344 C 39.761719 7.269531 32.496094 0 23.613281 0 Z M 28.546875 2.691406 C 30.074219 3.230469 31.417969 4.035156 32.675781 5.023438 C 32.136719 5.472656 31.417969 5.921875 30.703125 6.371094 C 30.164062 4.933594 29.445312 3.679688 28.546875 2.6875 Z M 32.585938 15.25 C 32.496094 12.820312 32.105469 10.40625 31.417969 8.074219 C 32.40625 7.535156 33.304688 6.996094 34.015625 6.277344 C 36.261719 8.609375 37.785156 11.75 37.964844 15.25 Z M 32.585938 15.25 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

@@ -0,0 +1,394 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 39" version="1.1">
<defs>
<filter id="alpha" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%">
<feColorMatrix type="matrix" in="SourceGraphic" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
</filter>
<mask id="mask0">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip1">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface5" clip-path="url(#clip1)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(81.176472%,81.568629%,81.960785%);fill-opacity:1;" d="M 5.824219 24.257812 C 5.824219 31.980469 12.171875 38.238281 19.996094 38.238281 C 27.824219 38.238281 34.171875 31.980469 34.171875 24.257812 C 34.171875 16.535156 27.824219 10.273438 19.996094 10.273438 C 12.171875 10.273438 5.824219 16.535156 5.824219 24.257812 Z M 5.824219 24.257812 "/>
</g>
<mask id="mask1">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip2">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface8" clip-path="url(#clip2)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(69.411767%,70.588237%,70.980394%);fill-opacity:1;" d="M 21.226562 13.519531 C 21.78125 13.910156 22.480469 13.996094 23.070312 13.746094 C 23.65625 13.496094 24.039062 12.945312 24.074219 12.304688 C 24.105469 11.664062 23.785156 11.03125 23.234375 10.640625 C 22.679688 10.25 21.980469 10.164062 21.390625 10.414062 C 20.804688 10.667969 20.421875 11.214844 20.386719 11.855469 C 20.355469 12.496094 20.675781 13.132812 21.226562 13.519531 Z M 21.226562 13.519531 "/>
</g>
<mask id="mask2">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip3">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface11" clip-path="url(#clip3)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 21.542969 13.1875 C 22.3125 13.703125 23.332031 13.582031 23.816406 12.917969 C 24.304688 12.253906 24.078125 11.296875 23.308594 10.78125 C 22.539062 10.265625 21.519531 10.390625 21.03125 11.054688 C 20.542969 11.71875 20.769531 12.671875 21.542969 13.1875 Z M 21.542969 13.1875 "/>
</g>
<mask id="mask3">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip4">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface14" clip-path="url(#clip4)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(69.411767%,70.588237%,70.980394%);fill-opacity:1;" d="M 6.035156 26.320312 C 6.367188 26.578125 6.976562 26.417969 7.398438 25.960938 C 7.816406 25.503906 7.890625 24.921875 7.554688 24.664062 C 7.222656 24.40625 6.613281 24.566406 6.191406 25.023438 C 5.773438 25.480469 5.703125 26.0625 6.035156 26.320312 Z M 6.035156 26.320312 "/>
</g>
<mask id="mask4">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip5">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface17" clip-path="url(#clip5)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 6.007812 26.515625 C 6.199219 26.679688 6.507812 26.671875 6.816406 26.496094 C 7.125 26.320312 7.390625 26.003906 7.507812 25.664062 C 7.625 25.324219 7.578125 25.015625 7.390625 24.851562 C 7.199219 24.6875 6.890625 24.691406 6.582031 24.867188 C 6.269531 25.042969 6.007812 25.359375 5.890625 25.699219 C 5.769531 26.039062 5.816406 26.351562 6.007812 26.515625 Z M 6.007812 26.515625 "/>
</g>
<mask id="mask5">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip6">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface20" clip-path="url(#clip6)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(69.411767%,70.588237%,70.980394%);fill-opacity:1;" d="M 13.257812 36.859375 C 14.191406 37.515625 15.375 37.660156 16.363281 37.238281 C 17.351562 36.816406 17.996094 35.890625 18.050781 34.8125 C 18.109375 33.734375 17.570312 32.664062 16.640625 32.007812 C 15.707031 31.351562 14.527344 31.207031 13.539062 31.628906 C 12.550781 32.050781 11.90625 32.976562 11.847656 34.054688 C 11.789062 35.136719 12.328125 36.203125 13.257812 36.859375 Z M 13.257812 36.859375 "/>
</g>
<mask id="mask6">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip7">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface23" clip-path="url(#clip7)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 13.644531 36.320312 C 14.554688 36.9375 15.703125 37.078125 16.652344 36.6875 C 17.601562 36.296875 18.210938 35.433594 18.25 34.421875 C 18.285156 33.414062 17.75 32.40625 16.839844 31.789062 C 15.925781 31.167969 14.78125 31.027344 13.832031 31.417969 C 12.878906 31.808594 12.273438 32.671875 12.234375 33.683594 C 12.195312 34.695312 12.734375 35.699219 13.644531 36.320312 Z M 13.644531 36.320312 "/>
</g>
<mask id="mask7">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip8">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface26" clip-path="url(#clip8)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(69.411767%,70.588237%,70.980394%);fill-opacity:1;" d="M 32.34375 23.308594 C 32.867188 23.992188 33.496094 24.515625 33.992188 24.679688 C 34.488281 24.84375 34.777344 24.625 34.75 24.105469 C 34.726562 23.585938 34.386719 22.84375 33.863281 22.160156 C 33.339844 21.476562 32.710938 20.953125 32.214844 20.789062 C 31.71875 20.625 31.425781 20.84375 31.453125 21.363281 C 31.480469 21.882812 31.820312 22.625 32.34375 23.308594 Z M 32.34375 23.308594 "/>
</g>
<mask id="mask8">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip9">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface29" clip-path="url(#clip9)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 32.472656 23.769531 C 32.960938 24.417969 33.554688 24.910156 34.023438 25.0625 C 34.492188 25.214844 34.773438 25.003906 34.753906 24.503906 C 34.734375 24.007812 34.417969 23.300781 33.929688 22.652344 C 33.4375 22 32.847656 21.507812 32.375 21.355469 C 31.90625 21.203125 31.628906 21.417969 31.648438 21.914062 C 31.667969 22.410156 31.980469 23.117188 32.472656 23.769531 Z M 32.472656 23.769531 "/>
</g>
<mask id="mask9">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip10">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface32" clip-path="url(#clip10)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(69.411767%,70.588237%,70.980394%);fill-opacity:1;" d="M 28.503906 32.734375 C 28.777344 33.101562 29.371094 33.203125 30.058594 33 C 30.75 32.796875 31.429688 32.320312 31.84375 31.75 C 32.257812 31.183594 32.34375 30.605469 32.070312 30.238281 C 31.796875 29.871094 31.203125 29.769531 30.515625 29.972656 C 29.828125 30.171875 29.148438 30.648438 28.730469 31.21875 C 28.316406 31.789062 28.230469 32.367188 28.503906 32.734375 Z M 28.503906 32.734375 "/>
</g>
<mask id="mask10">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip11">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface35" clip-path="url(#clip11)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 28.683594 32.765625 C 29.078125 33.292969 30.160156 33.191406 31.097656 32.535156 C 32.039062 31.878906 32.480469 30.921875 32.085938 30.394531 C 31.828125 30.054688 31.269531 29.964844 30.617188 30.160156 C 29.960938 30.355469 29.316406 30.808594 28.914062 31.347656 C 28.515625 31.882812 28.429688 32.425781 28.683594 32.765625 Z M 28.683594 32.765625 "/>
</g>
<mask id="mask11">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip12">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface38" clip-path="url(#clip12)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(69.411767%,70.588237%,70.980394%);fill-opacity:1;" d="M 31.542969 28.15625 C 31.785156 28.15625 32.011719 28.03125 32.132812 27.828125 C 32.257812 27.625 32.261719 27.371094 32.140625 27.160156 C 32.023438 26.953125 31.796875 26.828125 31.554688 26.824219 C 31.3125 26.824219 31.089844 26.949219 30.964844 27.152344 C 30.839844 27.355469 30.839844 27.609375 30.957031 27.820312 C 31.078125 28.027344 31.300781 28.152344 31.542969 28.15625 Z M 31.542969 28.15625 "/>
</g>
<mask id="mask12">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip13">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface41" clip-path="url(#clip13)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 31.640625 28.15625 C 31.960938 28.160156 32.226562 27.863281 32.230469 27.496094 C 32.230469 27.128906 31.972656 26.828125 31.652344 26.824219 C 31.332031 26.820312 31.066406 27.117188 31.0625 27.484375 C 31.0625 27.851562 31.320312 28.152344 31.640625 28.15625 Z M 31.640625 28.15625 "/>
</g>
<mask id="mask13">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip14">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface44" clip-path="url(#clip14)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(69.411767%,70.588237%,70.980394%);fill-opacity:1;" d="M 15.738281 23.429688 C 15.789062 23.800781 16.039062 24.117188 16.390625 24.265625 C 16.746094 24.414062 17.148438 24.367188 17.449219 24.144531 C 17.75 23.917969 17.90625 23.550781 17.851562 23.179688 C 17.796875 22.808594 17.550781 22.492188 17.195312 22.34375 C 16.84375 22.195312 16.4375 22.242188 16.136719 22.46875 C 15.835938 22.691406 15.683594 23.058594 15.738281 23.429688 Z M 15.738281 23.429688 "/>
</g>
<mask id="mask14">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip15">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface47" clip-path="url(#clip15)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 15.929688 23.425781 C 15.980469 23.796875 16.207031 24.117188 16.527344 24.265625 C 16.84375 24.414062 17.222656 24.367188 17.488281 24.144531 C 17.761719 23.921875 17.902344 23.554688 17.851562 23.183594 C 17.804688 22.8125 17.574219 22.492188 17.253906 22.34375 C 16.9375 22.195312 16.558594 22.242188 16.292969 22.464844 C 16.019531 22.6875 15.882812 23.054688 15.929688 23.425781 Z M 15.929688 23.425781 "/>
</g>
<mask id="mask15">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip16">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface50" clip-path="url(#clip16)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(69.411767%,70.588237%,70.980394%);fill-opacity:1;" d="M 10.40625 19.292969 C 10.84375 19.71875 11.582031 19.691406 12.054688 19.226562 C 12.523438 18.765625 12.550781 18.042969 12.113281 17.613281 C 11.832031 17.339844 11.40625 17.242188 11.003906 17.363281 C 10.59375 17.488281 10.273438 17.800781 10.148438 18.203125 C 10.023438 18.601562 10.125 19.015625 10.40625 19.292969 Z M 10.40625 19.292969 "/>
</g>
<mask id="mask16">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip17">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface53" clip-path="url(#clip17)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 10.566406 19.324219 C 10.824219 19.574219 11.210938 19.660156 11.582031 19.542969 C 11.960938 19.425781 12.253906 19.136719 12.375 18.765625 C 12.492188 18.402344 12.40625 18.023438 12.148438 17.773438 C 11.894531 17.519531 11.503906 17.4375 11.132812 17.554688 C 10.757812 17.671875 10.460938 17.960938 10.339844 18.332031 C 10.222656 18.695312 10.308594 19.074219 10.566406 19.324219 Z M 10.566406 19.324219 "/>
</g>
<mask id="mask17">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip18">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface56" clip-path="url(#clip18)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(69.411767%,70.588237%,70.980394%);fill-opacity:1;" d="M 25.976562 20.078125 C 26.152344 20.214844 26.453125 20.191406 26.765625 20.019531 C 27.074219 19.851562 27.351562 19.558594 27.484375 19.25 C 27.617188 18.945312 27.59375 18.675781 27.414062 18.542969 C 27.238281 18.40625 26.9375 18.429688 26.625 18.597656 C 26.316406 18.769531 26.042969 19.0625 25.90625 19.367188 C 25.773438 19.671875 25.800781 19.945312 25.976562 20.078125 Z M 25.976562 20.078125 "/>
</g>
<mask id="mask18">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip19">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface59" clip-path="url(#clip19)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 26.132812 20.082031 C 26.265625 20.214844 26.5 20.1875 26.742188 20.015625 C 26.984375 19.84375 27.199219 19.550781 27.304688 19.246094 C 27.414062 18.9375 27.394531 18.671875 27.261719 18.539062 C 27.125 18.40625 26.890625 18.429688 26.648438 18.601562 C 26.40625 18.777344 26.191406 19.070312 26.085938 19.375 C 25.980469 19.679688 25.996094 19.949219 26.132812 20.082031 Z M 26.132812 20.082031 "/>
</g>
<mask id="mask19">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip20">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface62" clip-path="url(#clip20)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(69.411767%,70.588237%,70.980394%);fill-opacity:1;" d="M 17.542969 18.035156 C 17.621094 18.09375 17.753906 18.085938 17.890625 18.007812 C 18.03125 17.933594 18.152344 17.800781 18.210938 17.667969 C 18.273438 17.53125 18.261719 17.410156 18.183594 17.351562 C 18.101562 17.292969 17.96875 17.300781 17.832031 17.375 C 17.691406 17.453125 17.570312 17.582031 17.511719 17.71875 C 17.453125 17.855469 17.464844 17.976562 17.542969 18.035156 Z M 17.542969 18.035156 "/>
</g>
<mask id="mask20">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip21">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface65" clip-path="url(#clip21)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 17.894531 18.035156 C 17.933594 18.09375 18 18.082031 18.070312 18.007812 C 18.136719 17.929688 18.199219 17.800781 18.230469 17.664062 C 18.261719 17.527344 18.253906 17.410156 18.21875 17.351562 C 18.179688 17.289062 18.113281 17.300781 18.042969 17.378906 C 17.972656 17.457031 17.914062 17.585938 17.882812 17.722656 C 17.851562 17.855469 17.855469 17.976562 17.894531 18.035156 Z M 17.894531 18.035156 "/>
</g>
<mask id="mask21">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip22">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface68" clip-path="url(#clip22)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(69.411767%,70.588237%,70.980394%);fill-opacity:1;" d="M 23.097656 36.058594 C 23.621094 36.226562 24.136719 36.144531 24.246094 35.878906 C 24.359375 35.609375 24.023438 35.257812 23.496094 35.089844 C 23.160156 34.984375 22.808594 34.976562 22.574219 35.070312 C 22.34375 35.167969 22.269531 35.351562 22.375 35.554688 C 22.484375 35.761719 22.757812 35.953125 23.097656 36.058594 Z M 23.097656 36.058594 "/>
</g>
<mask id="mask22">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip23">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface71" clip-path="url(#clip23)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 23.101562 36.054688 C 23.441406 36.167969 23.792969 36.175781 24.023438 36.082031 C 24.253906 35.988281 24.328125 35.804688 24.21875 35.601562 C 24.109375 35.398438 23.832031 35.203125 23.492188 35.09375 C 23.152344 34.984375 22.804688 34.976562 22.574219 35.070312 C 22.34375 35.164062 22.269531 35.347656 22.375 35.550781 C 22.484375 35.753906 22.761719 35.945312 23.101562 36.054688 Z M 23.101562 36.054688 "/>
</g>
<mask id="mask23">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip24">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface74" clip-path="url(#clip24)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 10.941406 27.355469 C 11.019531 27.417969 11.152344 27.40625 11.292969 27.332031 C 11.429688 27.253906 11.550781 27.125 11.609375 26.988281 C 11.671875 26.851562 11.660156 26.734375 11.582031 26.671875 C 11.460938 26.582031 11.21875 26.660156 11.039062 26.847656 C 10.863281 27.035156 10.820312 27.265625 10.941406 27.355469 Z M 10.941406 27.355469 "/>
</g>
<mask id="mask24">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip25">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface77" clip-path="url(#clip25)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 11.101562 27.359375 C 11.160156 27.449219 11.28125 27.367188 11.367188 27.179688 C 11.457031 26.988281 11.480469 26.761719 11.421875 26.671875 C 11.382812 26.613281 11.316406 26.625 11.246094 26.699219 C 11.179688 26.777344 11.117188 26.90625 11.085938 27.042969 C 11.054688 27.179688 11.0625 27.300781 11.101562 27.359375 Z M 11.101562 27.359375 "/>
</g>
<mask id="mask25">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip26">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface80" clip-path="url(#clip26)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(60.000002%,60.000002%,60.000002%);fill-opacity:1;" d="M 20 39 C 11.753906 39 5.046875 32.429688 5.046875 24.351562 C 5.046875 16.273438 11.753906 9.703125 20 9.703125 C 28.242188 9.703125 34.945312 16.273438 34.945312 24.351562 C 34.945312 32.429688 28.242188 39 20 39 Z M 20 11.222656 C 12.609375 11.222656 6.601562 17.113281 6.601562 24.351562 C 6.601562 31.589844 12.609375 37.480469 20 37.480469 C 27.386719 37.480469 33.394531 31.589844 33.394531 24.351562 C 33.394531 17.113281 27.386719 11.222656 20 11.222656 Z M 20 11.222656 "/>
</g>
<mask id="mask26">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip27">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface83" clip-path="url(#clip27)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(69.411767%,70.588237%,70.980394%);fill-opacity:1;" d="M 24.816406 30.246094 C 24.921875 30.261719 25.023438 30.101562 25.042969 29.890625 C 25.0625 29.679688 24.992188 29.5 24.886719 29.488281 C 24.78125 29.476562 24.679688 29.636719 24.660156 29.847656 C 24.640625 30.054688 24.710938 30.234375 24.816406 30.246094 Z M 24.816406 30.246094 "/>
</g>
<mask id="mask27">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip28">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface86" clip-path="url(#clip28)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(84.705883%,11.764706%,2.352941%);fill-opacity:1;" d="M 8.214844 34.433594 C 4.128906 34.433594 1.039062 33.460938 0.214844 31.1875 C -0.648438 28.8125 1.097656 25.902344 5.125 23.003906 C 5.347656 22.839844 5.640625 22.808594 5.894531 22.917969 C 6.148438 23.027344 6.324219 23.261719 6.355469 23.53125 C 6.382812 23.800781 6.265625 24.066406 6.042969 24.230469 C 2.664062 26.660156 1.074219 29.011719 1.679688 30.679688 C 2.699219 33.492188 11.363281 34 22.164062 30.230469 C 27.171875 28.484375 31.625 26.167969 34.699219 23.707031 C 37.53125 21.445312 38.851562 19.324219 38.332031 17.894531 C 37.847656 16.566406 35.113281 15.84375 30.800781 15.933594 L 30.785156 15.933594 C 30.363281 15.925781 30.023438 15.59375 30.019531 15.179688 C 30.011719 14.765625 30.347656 14.425781 30.769531 14.410156 C 36.003906 14.3125 39.046875 15.308594 39.796875 17.382812 C 40.5625 19.488281 39.101562 22.152344 35.683594 24.886719 C 32.472656 27.453125 27.855469 29.859375 22.683594 31.664062 C 17.734375 33.390625 12.441406 34.433594 8.214844 34.433594 Z M 11.90625 12.59375 C 11.640625 12.59375 11.394531 12.460938 11.25 12.242188 L 10.367188 10.878906 C 10.214844 10.652344 10.199219 10.359375 10.324219 10.117188 C 10.453125 9.871094 10.703125 9.714844 10.984375 9.703125 C 11.261719 9.691406 11.527344 9.828125 11.675781 10.058594 L 12.5625 11.421875 C 12.714844 11.65625 12.722656 11.953125 12.585938 12.195312 C 12.453125 12.441406 12.191406 12.59375 11.90625 12.59375 Z M 11.90625 12.59375 "/>
</g>
<mask id="mask28">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip29">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface89" clip-path="url(#clip29)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(60.000002%,60.000002%,60.000002%);fill-opacity:1;" d="M 6.398438 29.105469 C 6.050781 29.105469 5.746094 28.882812 5.648438 28.558594 C 5.25 27.214844 5.046875 25.820312 5.046875 24.421875 C 5.046875 16.304688 11.777344 9.703125 20.046875 9.703125 C 27.132812 9.703125 33.3125 14.640625 34.738281 21.441406 C 34.800781 21.710938 34.710938 21.996094 34.5 22.179688 C 34.289062 22.363281 33.996094 22.421875 33.726562 22.335938 C 33.460938 22.246094 33.265625 22.023438 33.214844 21.75 C 31.9375 15.652344 26.398438 11.226562 20.046875 11.226562 C 12.632812 11.226562 6.605469 17.144531 6.605469 24.417969 C 6.601562 25.671875 6.785156 26.921875 7.144531 28.125 C 7.210938 28.359375 7.164062 28.605469 7.019531 28.800781 C 6.871094 28.992188 6.640625 29.105469 6.394531 29.105469 Z M 6.398438 29.105469 "/>
</g>
<mask id="mask29">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip30">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface92" clip-path="url(#clip30)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(84.705883%,11.764706%,2.352941%);fill-opacity:1;" d="M 8.308594 8.289062 C 7.664062 8.289062 7.082031 7.90625 6.835938 7.316406 C 6.585938 6.726562 6.722656 6.050781 7.179688 5.597656 C 7.632812 5.148438 8.320312 5.011719 8.917969 5.257812 C 9.511719 5.5 9.902344 6.074219 9.902344 6.714844 C 9.898438 7.582031 9.1875 8.289062 8.308594 8.289062 Z M 6.382812 10.652344 C 4.683594 10.652344 3.300781 9.289062 3.300781 7.605469 C 3.292969 7.320312 3.441406 7.054688 3.691406 6.90625 C 3.941406 6.761719 4.25 6.761719 4.5 6.90625 C 4.75 7.054688 4.898438 7.320312 4.890625 7.605469 C 4.894531 8.417969 5.558594 9.078125 6.382812 9.082031 C 6.671875 9.074219 6.945312 9.222656 7.089844 9.46875 C 7.234375 9.714844 7.234375 10.019531 7.089844 10.265625 C 6.945312 10.511719 6.671875 10.660156 6.382812 10.652344 Z M 6.382812 10.652344 "/>
</g>
<mask id="mask30">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip31">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface95" clip-path="url(#clip31)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(84.705883%,11.764706%,2.352941%);fill-opacity:1;" d="M 6.4375 12.933594 C 3.207031 12.929688 0.585938 10.328125 0.582031 7.109375 C 0.574219 6.835938 0.71875 6.578125 0.960938 6.4375 C 1.199219 6.296875 1.496094 6.296875 1.734375 6.4375 C 1.976562 6.578125 2.121094 6.835938 2.113281 7.109375 C 2.113281 9.488281 4.050781 11.414062 6.4375 11.414062 C 6.714844 11.410156 6.976562 11.550781 7.113281 11.789062 C 7.253906 12.027344 7.253906 12.324219 7.113281 12.5625 C 6.976562 12.796875 6.714844 12.941406 6.4375 12.9375 Z M 11.992188 7.003906 C 11.933594 7.003906 11.875 6.996094 11.820312 6.984375 C 11.410156 6.886719 11.152344 6.480469 11.246094 6.070312 C 11.425781 5.300781 10.945312 4.535156 10.175781 4.359375 C 9.902344 4.300781 9.683594 4.101562 9.605469 3.839844 C 9.519531 3.578125 9.585938 3.292969 9.777344 3.089844 C 9.964844 2.890625 10.25 2.808594 10.519531 2.875 C 11.285156 3.050781 11.949219 3.523438 12.367188 4.1875 C 12.78125 4.855469 12.914062 5.652344 12.738281 6.414062 C 12.65625 6.757812 12.347656 7.003906 11.992188 7.003906 Z M 11.992188 7.003906 "/>
</g>
<mask id="mask31">
<g filter="url(#alpha)">
<rect x="0" y="0" width="40" height="39" style="fill:rgb(0%,0%,0%);fill-opacity:0.2;stroke:none;"/>
</g>
</mask>
<clipPath id="clip32">
<rect x="0" y="0" width="40" height="39"/>
</clipPath>
<g id="surface98" clip-path="url(#clip32)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(84.705883%,11.764706%,2.352941%);fill-opacity:1;" d="M 14.609375 7.609375 C 14.550781 7.609375 14.488281 7.601562 14.429688 7.589844 C 14.226562 7.542969 14.050781 7.421875 13.9375 7.25 C 13.828125 7.078125 13.792969 6.871094 13.839844 6.671875 C 14.109375 5.5625 13.90625 4.390625 13.28125 3.421875 C 12.65625 2.453125 11.660156 1.761719 10.507812 1.503906 C 10.085938 1.40625 9.824219 1 9.921875 0.589844 C 10.019531 0.183594 10.441406 -0.0742188 10.863281 0.0195312 C 12.421875 0.367188 13.773438 1.300781 14.621094 2.613281 C 15.464844 3.921875 15.738281 5.511719 15.375 7.019531 C 15.292969 7.363281 14.976562 7.609375 14.609375 7.609375 Z M 14.609375 7.609375 "/>
</g>
</defs>
<g id="surface1">
<use xlink:href="#surface5" mask="url(#mask0)"/>
<use xlink:href="#surface8" mask="url(#mask1)"/>
<use xlink:href="#surface11" mask="url(#mask2)"/>
<use xlink:href="#surface14" mask="url(#mask3)"/>
<use xlink:href="#surface17" mask="url(#mask4)"/>
<use xlink:href="#surface20" mask="url(#mask5)"/>
<use xlink:href="#surface23" mask="url(#mask6)"/>
<use xlink:href="#surface26" mask="url(#mask7)"/>
<use xlink:href="#surface29" mask="url(#mask8)"/>
<use xlink:href="#surface32" mask="url(#mask9)"/>
<use xlink:href="#surface35" mask="url(#mask10)"/>
<use xlink:href="#surface38" mask="url(#mask11)"/>
<use xlink:href="#surface41" mask="url(#mask12)"/>
<use xlink:href="#surface44" mask="url(#mask13)"/>
<use xlink:href="#surface47" mask="url(#mask14)"/>
<use xlink:href="#surface50" mask="url(#mask15)"/>
<use xlink:href="#surface53" mask="url(#mask16)"/>
<use xlink:href="#surface56" mask="url(#mask17)"/>
<use xlink:href="#surface59" mask="url(#mask18)"/>
<use xlink:href="#surface62" mask="url(#mask19)"/>
<use xlink:href="#surface65" mask="url(#mask20)"/>
<use xlink:href="#surface68" mask="url(#mask21)"/>
<use xlink:href="#surface71" mask="url(#mask22)"/>
<use xlink:href="#surface74" mask="url(#mask23)"/>
<use xlink:href="#surface77" mask="url(#mask24)"/>
<use xlink:href="#surface80" mask="url(#mask25)"/>
<use xlink:href="#surface83" mask="url(#mask26)"/>
<use xlink:href="#surface86" mask="url(#mask27)"/>
<use xlink:href="#surface89" mask="url(#mask28)"/>
<use xlink:href="#surface92" mask="url(#mask29)"/>
<use xlink:href="#surface95" mask="url(#mask30)"/>
<use xlink:href="#surface98" mask="url(#mask31)"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 29 KiB

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.11765%,54.11765%,54.11765%);fill-opacity:1;" d="M 29.746094 8.769531 C 29.359375 8.410156 28.847656 8.207031 28.316406 8.199219 L 17.160156 8.199219 L 17.160156 10.757812 L 27.675781 10.757812 L 27.675781 20 L 30.375 20 L 30.375 10.15625 C 30.371094 9.625 30.144531 9.121094 29.746094 8.769531 Z M 29.746094 8.769531 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 17.570312 2.484375 L 4.230469 2.484375 C 3.867188 2.492188 3.519531 2.632812 3.257812 2.886719 C 3.003906 3.148438 2.863281 3.496094 2.855469 3.855469 L 2.855469 14.355469 C 2.855469 14.539062 2.890625 14.71875 2.957031 14.886719 C 3.027344 15.046875 3.128906 15.195312 3.257812 15.3125 C 3.386719 15.441406 3.535156 15.542969 3.699219 15.613281 C 3.863281 15.675781 4.039062 15.707031 4.214844 15.714844 L 17.570312 15.714844 C 17.742188 15.710938 17.914062 15.675781 18.070312 15.613281 C 18.40625 15.476562 18.679688 15.214844 18.828125 14.886719 C 18.890625 14.714844 18.921875 14.539062 18.929688 14.355469 L 18.929688 3.855469 C 18.917969 3.5 18.777344 3.15625 18.527344 2.898438 C 18.273438 2.644531 17.929688 2.5 17.570312 2.484375 Z M 16.355469 5.070312 L 16.355469 13.171875 L 5.441406 13.171875 L 5.441406 5.070312 Z M 17.644531 18.199219 L 4.144531 18.199219 C 3.773438 18.214844 3.429688 18.398438 3.214844 18.699219 C 2.738281 19.367188 2.738281 20.261719 3.214844 20.929688 C 3.429688 21.230469 3.773438 21.414062 4.144531 21.429688 L 17.644531 21.429688 C 18.007812 21.417969 18.347656 21.230469 18.558594 20.929688 C 19.050781 20.269531 19.050781 19.359375 18.558594 18.699219 C 18.347656 18.398438 18.007812 18.210938 17.644531 18.199219 Z M 37.070312 18.644531 C 36.796875 18.355469 36.414062 18.195312 36.015625 18.199219 L 21.472656 18.199219 C 21.078125 18.199219 20.699219 18.359375 20.429688 18.644531 C 20.15625 18.929688 20.003906 19.308594 20 19.699219 L 20 31.355469 C 20.003906 31.75 20.15625 32.128906 20.429688 32.414062 C 20.699219 32.699219 21.078125 32.859375 21.472656 32.855469 L 35.972656 32.855469 C 36.371094 32.863281 36.753906 32.703125 37.027344 32.414062 C 37.300781 32.128906 37.453125 31.75 37.457031 31.355469 L 37.457031 19.699219 C 37.464844 19.3125 37.328125 18.933594 37.070312 18.644531 Z M 34.699219 21.027344 L 34.699219 30.058594 L 22.785156 30.058594 L 22.785156 21.027344 Z M 36.113281 33.914062 L 21.386719 33.914062 C 21.003906 33.925781 20.640625 34.101562 20.398438 34.398438 C 20.136719 34.71875 19.996094 35.117188 20 35.527344 C 19.996094 35.941406 20.136719 36.339844 20.398438 36.65625 C 20.640625 36.957031 21 37.132812 21.386719 37.144531 L 36.113281 37.144531 C 36.496094 37.132812 36.859375 36.957031 37.101562 36.65625 C 37.363281 36.339844 37.503906 35.941406 37.5 35.527344 C 37.503906 35.117188 37.363281 34.71875 37.101562 34.398438 C 36.859375 34.101562 36.496094 33.925781 36.113281 33.914062 Z M 36.113281 33.914062 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.11765%,54.11765%,54.11765%);fill-opacity:1;" d="M 29.746094 8.769531 C 29.359375 8.410156 28.847656 8.207031 28.316406 8.199219 L 17.160156 8.199219 L 17.160156 10.757812 L 27.675781 10.757812 L 27.675781 20 L 30.375 20 L 30.375 10.15625 C 30.371094 9.625 30.144531 9.121094 29.746094 8.769531 Z M 29.746094 8.769531 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(96.078432%,42.352942%,42.352942%);fill-opacity:1;" d="M 17.570312 2.484375 L 4.230469 2.484375 C 3.867188 2.492188 3.519531 2.632812 3.257812 2.886719 C 3.003906 3.148438 2.863281 3.496094 2.855469 3.855469 L 2.855469 14.355469 C 2.855469 14.539062 2.890625 14.71875 2.957031 14.886719 C 3.027344 15.046875 3.128906 15.195312 3.257812 15.3125 C 3.386719 15.441406 3.535156 15.542969 3.699219 15.613281 C 3.863281 15.675781 4.039062 15.707031 4.214844 15.714844 L 17.570312 15.714844 C 17.742188 15.710938 17.914062 15.675781 18.070312 15.613281 C 18.40625 15.476562 18.679688 15.214844 18.828125 14.886719 C 18.890625 14.714844 18.921875 14.539062 18.929688 14.355469 L 18.929688 3.855469 C 18.917969 3.5 18.777344 3.15625 18.527344 2.898438 C 18.273438 2.644531 17.929688 2.5 17.570312 2.484375 Z M 16.355469 5.070312 L 16.355469 13.171875 L 5.441406 13.171875 L 5.441406 5.070312 Z M 17.644531 18.199219 L 4.144531 18.199219 C 3.773438 18.214844 3.429688 18.398438 3.214844 18.699219 C 2.738281 19.367188 2.738281 20.261719 3.214844 20.929688 C 3.429688 21.230469 3.773438 21.414062 4.144531 21.429688 L 17.644531 21.429688 C 18.007812 21.417969 18.347656 21.230469 18.558594 20.929688 C 19.050781 20.269531 19.050781 19.359375 18.558594 18.699219 C 18.347656 18.398438 18.007812 18.210938 17.644531 18.199219 Z M 37.070312 18.644531 C 36.796875 18.355469 36.414062 18.195312 36.015625 18.199219 L 21.472656 18.199219 C 21.078125 18.199219 20.699219 18.359375 20.429688 18.644531 C 20.15625 18.929688 20.003906 19.308594 20 19.699219 L 20 31.355469 C 20.003906 31.75 20.15625 32.128906 20.429688 32.414062 C 20.699219 32.699219 21.078125 32.859375 21.472656 32.855469 L 35.972656 32.855469 C 36.371094 32.863281 36.753906 32.703125 37.027344 32.414062 C 37.300781 32.128906 37.453125 31.75 37.457031 31.355469 L 37.457031 19.699219 C 37.464844 19.3125 37.328125 18.933594 37.070312 18.644531 Z M 34.699219 21.027344 L 34.699219 30.058594 L 22.785156 30.058594 L 22.785156 21.027344 Z M 36.113281 33.914062 L 21.386719 33.914062 C 21.003906 33.925781 20.640625 34.101562 20.398438 34.398438 C 20.136719 34.71875 19.996094 35.117188 20 35.527344 C 19.996094 35.941406 20.136719 36.339844 20.398438 36.65625 C 20.640625 36.957031 21 37.132812 21.386719 37.144531 L 36.113281 37.144531 C 36.496094 37.132812 36.859375 36.957031 37.101562 36.65625 C 37.363281 36.339844 37.503906 35.941406 37.5 35.527344 C 37.503906 35.117188 37.363281 34.71875 37.101562 34.398438 C 36.859375 34.101562 36.496094 33.925781 36.113281 33.914062 Z M 36.113281 33.914062 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.11765%,54.11765%,54.11765%);fill-opacity:1;" d="M 6.253906 7.738281 C 6.542969 7.734375 6.816406 7.625 7.027344 7.425781 C 7.4375 6.996094 7.4375 6.3125 7.027344 5.882812 C 6.589844 5.453125 5.890625 5.453125 5.453125 5.882812 C 5.253906 6.089844 5.140625 6.367188 5.140625 6.65625 C 5.140625 7.253906 5.625 7.738281 6.226562 7.738281 Z M 6.253906 7.738281 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 30.5 3 C 27.347656 1.03125 23.707031 -0.0078125 19.992188 0 C 16.964844 -0.00390625 13.976562 0.679688 11.253906 2 C 10.714844 2.277344 10.488281 2.929688 10.738281 3.484375 C 11.007812 4.035156 11.671875 4.265625 12.222656 4 C 13.371094 3.429688 14.578125 2.988281 15.820312 2.683594 C 13.105469 4.617188 11.101562 7.386719 10.109375 10.566406 C 7.273438 11.507812 4.757812 13.230469 2.855469 15.535156 C 3.285156 13.8125 3.957031 12.15625 4.855469 10.625 C 5.171875 10.113281 5.011719 9.441406 4.5 9.125 C 3.984375 8.808594 3.3125 8.96875 3 9.480469 C -2.816406 18.871094 0.0859375 31.195312 9.476562 37.007812 C 18.867188 42.820312 31.191406 39.914062 37 30.519531 C 42.808594 21.125 39.898438 8.804688 30.5 3 Z M 19.992188 3.628906 C 22.847656 3.628906 25.332031 6.027344 27.046875 9.738281 C 22.402344 8.683594 17.582031 8.683594 12.9375 9.738281 C 14.652344 6.027344 17.136719 3.628906 19.992188 3.628906 Z M 24.445312 20.761719 C 24.882812 20.332031 25.582031 20.332031 26.019531 20.761719 C 26.222656 20.964844 26.339844 21.246094 26.339844 21.535156 C 26.339844 21.824219 26.222656 22.101562 26.019531 22.304688 L 22.476562 26.246094 C 22.25 26.457031 21.957031 26.578125 21.648438 26.589844 C 21.355469 26.589844 21.074219 26.472656 20.871094 26.261719 C 20.667969 26.050781 20.554688 25.769531 20.5625 25.476562 L 20.5625 15.222656 C 20.492188 14.789062 20.683594 14.351562 21.054688 14.109375 C 21.425781 13.871094 21.902344 13.871094 22.269531 14.109375 C 22.640625 14.351562 22.832031 14.789062 22.761719 15.222656 L 22.761719 22.847656 Z M 13.023438 18.191406 L 16.648438 14.453125 C 16.964844 14.125 17.445312 14.023438 17.867188 14.195312 C 18.285156 14.363281 18.5625 14.769531 18.5625 15.222656 L 18.5625 25.476562 C 18.546875 26.085938 18.058594 26.574219 17.449219 26.589844 C 16.847656 26.574219 16.363281 26.078125 16.363281 25.476562 L 16.363281 17.992188 L 14.652344 19.792969 C 14.242188 20.234375 13.550781 20.257812 13.109375 19.847656 C 12.667969 19.4375 12.640625 18.75 13.050781 18.308594 Z M 9.394531 13.308594 C 8.339844 17.941406 8.339844 22.753906 9.394531 27.390625 C 5.710938 25.703125 3.253906 23.132812 3.253906 20.335938 C 3.253906 17.535156 5.710938 14.992188 9.394531 13.308594 Z M 3.113281 25.703125 C 5.027344 27.824219 7.472656 29.402344 10.195312 30.273438 C 11.03125 32.75 12.429688 34.996094 14.28125 36.84375 C 9.03125 35.0625 4.902344 30.949219 3.113281 25.703125 Z M 19.992188 37.128906 C 17.136719 37.128906 14.652344 34.730469 12.9375 31.015625 C 17.582031 32.074219 22.402344 32.074219 27.046875 31.015625 C 25.332031 34.671875 22.847656 37.128906 19.992188 37.128906 Z M 25.703125 36.898438 C 27.59375 35.019531 29.011719 32.71875 29.84375 30.1875 C 32.539062 29.332031 34.960938 27.785156 36.871094 25.703125 C 35.078125 30.949219 30.953125 35.0625 25.703125 36.84375 Z M 30.644531 13.367188 C 34.355469 15.050781 36.785156 17.621094 36.785156 20.390625 C 36.785156 23.160156 34.273438 25.703125 30.585938 27.390625 C 31.644531 22.753906 31.644531 17.941406 30.585938 13.308594 Z M 29.84375 10.511719 C 28.828125 7.417969 26.84375 4.738281 24.191406 2.855469 C 30.503906 4.40625 35.464844 9.28125 37.128906 15.566406 C 35.21875 13.21875 32.667969 11.484375 29.789062 10.566406 Z M 29.84375 10.511719 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.11765%,54.11765%,54.11765%);fill-opacity:1;" d="M 6.253906 7.738281 C 6.542969 7.734375 6.816406 7.625 7.027344 7.425781 C 7.4375 6.996094 7.4375 6.3125 7.027344 5.882812 C 6.589844 5.453125 5.890625 5.453125 5.453125 5.882812 C 5.253906 6.089844 5.140625 6.367188 5.140625 6.65625 C 5.140625 7.253906 5.625 7.738281 6.226562 7.738281 Z M 6.253906 7.738281 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(96.078432%,42.352942%,42.352942%);fill-opacity:1;" d="M 30.5 3 C 27.347656 1.03125 23.707031 -0.0078125 19.992188 0 C 16.964844 -0.00390625 13.976562 0.679688 11.253906 2 C 10.714844 2.277344 10.488281 2.929688 10.738281 3.484375 C 11.007812 4.035156 11.671875 4.265625 12.222656 4 C 13.371094 3.429688 14.578125 2.988281 15.820312 2.683594 C 13.105469 4.617188 11.101562 7.386719 10.109375 10.566406 C 7.273438 11.507812 4.757812 13.230469 2.855469 15.535156 C 3.285156 13.8125 3.957031 12.15625 4.855469 10.625 C 5.171875 10.113281 5.011719 9.441406 4.5 9.125 C 3.984375 8.808594 3.3125 8.96875 3 9.480469 C -2.816406 18.871094 0.0859375 31.195312 9.476562 37.007812 C 18.867188 42.820312 31.191406 39.914062 37 30.519531 C 42.808594 21.125 39.898438 8.804688 30.5 3 Z M 19.992188 3.628906 C 22.847656 3.628906 25.332031 6.027344 27.046875 9.738281 C 22.402344 8.683594 17.582031 8.683594 12.9375 9.738281 C 14.652344 6.027344 17.136719 3.628906 19.992188 3.628906 Z M 24.445312 20.761719 C 24.882812 20.332031 25.582031 20.332031 26.019531 20.761719 C 26.222656 20.964844 26.339844 21.246094 26.339844 21.535156 C 26.339844 21.824219 26.222656 22.101562 26.019531 22.304688 L 22.476562 26.246094 C 22.25 26.457031 21.957031 26.578125 21.648438 26.589844 C 21.355469 26.589844 21.074219 26.472656 20.871094 26.261719 C 20.667969 26.050781 20.554688 25.769531 20.5625 25.476562 L 20.5625 15.222656 C 20.492188 14.789062 20.683594 14.351562 21.054688 14.109375 C 21.425781 13.871094 21.902344 13.871094 22.269531 14.109375 C 22.640625 14.351562 22.832031 14.789062 22.761719 15.222656 L 22.761719 22.847656 Z M 13.023438 18.191406 L 16.648438 14.453125 C 16.964844 14.125 17.445312 14.023438 17.867188 14.195312 C 18.285156 14.363281 18.5625 14.769531 18.5625 15.222656 L 18.5625 25.476562 C 18.546875 26.085938 18.058594 26.574219 17.449219 26.589844 C 16.847656 26.574219 16.363281 26.078125 16.363281 25.476562 L 16.363281 17.992188 L 14.652344 19.792969 C 14.242188 20.234375 13.550781 20.257812 13.109375 19.847656 C 12.667969 19.4375 12.640625 18.75 13.050781 18.308594 Z M 9.394531 13.308594 C 8.339844 17.941406 8.339844 22.753906 9.394531 27.390625 C 5.710938 25.703125 3.253906 23.132812 3.253906 20.335938 C 3.253906 17.535156 5.710938 14.992188 9.394531 13.308594 Z M 3.113281 25.703125 C 5.027344 27.824219 7.472656 29.402344 10.195312 30.273438 C 11.03125 32.75 12.429688 34.996094 14.28125 36.84375 C 9.03125 35.0625 4.902344 30.949219 3.113281 25.703125 Z M 19.992188 37.128906 C 17.136719 37.128906 14.652344 34.730469 12.9375 31.015625 C 17.582031 32.074219 22.402344 32.074219 27.046875 31.015625 C 25.332031 34.671875 22.847656 37.128906 19.992188 37.128906 Z M 25.703125 36.898438 C 27.59375 35.019531 29.011719 32.71875 29.84375 30.1875 C 32.539062 29.332031 34.960938 27.785156 36.871094 25.703125 C 35.078125 30.949219 30.953125 35.0625 25.703125 36.84375 Z M 30.644531 13.367188 C 34.355469 15.050781 36.785156 17.621094 36.785156 20.390625 C 36.785156 23.160156 34.273438 25.703125 30.585938 27.390625 C 31.644531 22.753906 31.644531 17.941406 30.585938 13.308594 Z M 29.84375 10.511719 C 28.828125 7.417969 26.84375 4.738281 24.191406 2.855469 C 30.503906 4.40625 35.464844 9.28125 37.128906 15.566406 C 35.21875 13.21875 32.667969 11.484375 29.789062 10.566406 Z M 29.84375 10.511719 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(90.588236%,90.588236%,92.54902%);fill-opacity:1;" d="M 20 0 C 33.332031 0 40 6.667969 40 20 C 40 33.332031 33.332031 40 20 40 C 6.667969 40 0 33.332031 0 20 C 0 6.667969 6.667969 0 20 0 Z M 20 0 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 18.582031 29.328125 C 18.582031 28.53125 19.226562 27.882812 20.027344 27.882812 C 20.824219 27.882812 21.46875 28.53125 21.46875 29.328125 C 21.46875 30.125 20.824219 30.769531 20.027344 30.769531 C 19.230469 30.769531 18.582031 30.125 18.582031 29.328125 Z M 32.34375 15.113281 C 32.855469 15.625 32.855469 16.449219 32.347656 16.960938 C 31.835938 17.472656 31.011719 17.472656 30.496094 16.960938 C 24.699219 11.164062 15.300781 11.164062 9.503906 16.960938 C 8.996094 17.472656 8.167969 17.472656 7.65625 16.960938 C 7.410156 16.71875 7.273438 16.382812 7.273438 16.039062 C 7.273438 15.691406 7.410156 15.359375 7.65625 15.113281 C 14.472656 8.296875 25.527344 8.296875 32.34375 15.113281 Z M 11.285156 19.25 C 16.097656 14.441406 23.898438 14.441406 28.710938 19.25 C 29.222656 19.761719 29.222656 20.589844 28.710938 21.097656 C 28.46875 21.34375 28.136719 21.484375 27.789062 21.484375 C 27.441406 21.484375 27.109375 21.34375 26.863281 21.097656 C 23.074219 17.308594 16.921875 17.308594 13.132812 21.097656 C 12.625 21.613281 11.796875 21.613281 11.285156 21.101562 C 11.039062 20.855469 10.902344 20.523438 10.902344 20.175781 C 10.902344 19.828125 11.039062 19.496094 11.285156 19.25 Z M 25.183594 25.558594 C 24.738281 26.007812 24.035156 26.070312 23.515625 25.710938 L 23.5 25.730469 L 23.257812 25.484375 C 21.46875 23.699219 18.574219 23.695312 16.785156 25.484375 C 16.277344 25.996094 15.449219 25.996094 14.9375 25.488281 C 14.691406 25.242188 14.554688 24.910156 14.554688 24.5625 C 14.554688 24.214844 14.691406 23.882812 14.9375 23.636719 C 17.746094 20.828125 22.296875 20.828125 25.105469 23.636719 L 25.160156 23.695312 L 25.179688 23.710938 L 25.234375 23.765625 L 25.347656 23.882812 L 25.335938 23.894531 C 25.6875 24.402344 25.636719 25.105469 25.183594 25.558594 Z M 25.183594 25.558594 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 49 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(68.627453%,80.392158%,31.37255%);fill-opacity:1;" d="M 20.429688 34.667969 L 20.003906 34.660156 C 11.925781 34.441406 5.445312 27.960938 5.445312 20 C 5.445312 11.898438 12.15625 5.332031 20.429688 5.332031 L 28.601562 5.332031 C 36.875 5.332031 43.582031 11.898438 43.582031 20 C 43.582031 28.101562 36.875 34.667969 28.601562 34.667969 Z M 20.429688 34.667969 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 25.472656 29.703125 C 25.472656 29.957031 25.371094 30.199219 25.195312 30.375 C 24.816406 30.746094 24.210938 30.746094 23.832031 30.375 C 23.652344 30.199219 23.550781 29.957031 23.554688 29.703125 L 23.554688 20.542969 C 22.628906 20.167969 22.027344 19.269531 22.019531 18.273438 C 22.019531 16.914062 23.140625 15.8125 24.515625 15.8125 C 25.890625 15.8125 27.007812 16.914062 27.007812 18.273438 C 27.007812 19.277344 26.394531 20.164062 25.476562 20.542969 L 25.476562 29.703125 Z M 31.429688 18.269531 C 31.429688 20.378906 30.324219 22.328125 28.519531 23.40625 C 28.066406 23.679688 27.480469 23.542969 27.199219 23.09375 C 27.066406 22.878906 27.023438 22.621094 27.082031 22.375 C 27.140625 22.128906 27.296875 21.921875 27.511719 21.789062 C 28.75 21.054688 29.507812 19.714844 29.507812 18.269531 C 29.507812 16.824219 28.75 15.488281 27.511719 14.75 C 27.296875 14.621094 27.140625 14.410156 27.082031 14.167969 C 27.023438 13.921875 27.066406 13.664062 27.199219 13.449219 C 27.480469 13.003906 28.066406 12.863281 28.519531 13.136719 C 30.324219 14.210938 31.433594 16.164062 31.433594 18.269531 Z M 31.738281 25.699219 C 31.3125 26.015625 30.714844 25.929688 30.394531 25.507812 C 30.242188 25.308594 30.175781 25.054688 30.210938 24.804688 C 30.25 24.554688 30.382812 24.332031 30.585938 24.183594 C 32.472656 22.808594 33.585938 20.609375 33.578125 18.269531 C 33.585938 15.933594 32.472656 13.730469 30.585938 12.359375 C 30.382812 12.210938 30.25 11.984375 30.210938 11.734375 C 30.175781 11.488281 30.242188 11.234375 30.394531 11.03125 C 30.71875 10.617188 31.3125 10.53125 31.738281 10.839844 C 34.121094 12.601562 35.519531 15.355469 35.503906 18.273438 C 35.507812 21.210938 34.109375 23.972656 31.738281 25.699219 Z M 19.515625 18.269531 C 19.515625 19.71875 20.261719 21.035156 21.511719 21.789062 C 21.726562 21.917969 21.882812 22.128906 21.941406 22.375 C 22.003906 22.621094 21.960938 22.878906 21.828125 23.09375 C 21.542969 23.539062 20.957031 23.675781 20.503906 23.40625 C 18.699219 22.328125 17.59375 20.378906 17.59375 18.269531 C 17.59375 16.164062 18.699219 14.210938 20.503906 13.136719 C 20.957031 12.867188 21.542969 13.003906 21.828125 13.449219 C 21.960938 13.664062 22.003906 13.921875 21.941406 14.167969 C 21.882812 14.410156 21.726562 14.621094 21.511719 14.75 C 20.273438 15.488281 19.515625 16.824219 19.515625 18.269531 Z M 18.429688 24.1875 C 18.632812 24.335938 18.765625 24.5625 18.800781 24.808594 C 18.839844 25.058594 18.773438 25.3125 18.621094 25.515625 C 18.296875 25.933594 17.699219 26.019531 17.273438 25.703125 C 14.90625 23.976562 13.503906 21.214844 13.511719 18.273438 C 13.503906 15.335938 14.90625 12.574219 17.273438 10.847656 C 17.480469 10.699219 17.734375 10.632812 17.988281 10.667969 C 18.238281 10.703125 18.464844 10.835938 18.621094 11.039062 C 18.773438 11.242188 18.839844 11.492188 18.800781 11.742188 C 18.765625 11.992188 18.632812 12.21875 18.429688 12.367188 C 16.542969 13.738281 15.429688 15.9375 15.433594 18.273438 C 15.429688 20.613281 16.542969 22.8125 18.429688 24.1875 Z M 18.429688 24.1875 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 49 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(96.078432%,42.352942%,42.352942%);fill-opacity:1;" d="M 20.429688 34.667969 L 20.003906 34.660156 C 11.925781 34.441406 5.445312 27.960938 5.445312 20 C 5.445312 11.898438 12.15625 5.332031 20.429688 5.332031 L 28.601562 5.332031 C 36.875 5.332031 43.582031 11.898438 43.582031 20 C 43.582031 28.101562 36.875 34.667969 28.601562 34.667969 Z M 20.429688 34.667969 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 25.472656 29.703125 C 25.472656 29.957031 25.371094 30.199219 25.195312 30.375 C 24.816406 30.746094 24.210938 30.746094 23.832031 30.375 C 23.652344 30.199219 23.550781 29.957031 23.554688 29.703125 L 23.554688 20.542969 C 22.628906 20.167969 22.027344 19.269531 22.019531 18.273438 C 22.019531 16.914062 23.140625 15.8125 24.515625 15.8125 C 25.890625 15.8125 27.007812 16.914062 27.007812 18.273438 C 27.007812 19.277344 26.394531 20.164062 25.476562 20.542969 L 25.476562 29.703125 Z M 31.429688 18.269531 C 31.429688 20.378906 30.324219 22.328125 28.519531 23.40625 C 28.066406 23.679688 27.480469 23.542969 27.199219 23.09375 C 27.066406 22.878906 27.023438 22.621094 27.082031 22.375 C 27.140625 22.128906 27.296875 21.921875 27.511719 21.789062 C 28.75 21.054688 29.507812 19.714844 29.507812 18.269531 C 29.507812 16.824219 28.75 15.488281 27.511719 14.75 C 27.296875 14.621094 27.140625 14.410156 27.082031 14.167969 C 27.023438 13.921875 27.066406 13.664062 27.199219 13.449219 C 27.480469 13.003906 28.066406 12.863281 28.519531 13.136719 C 30.324219 14.210938 31.433594 16.164062 31.433594 18.269531 Z M 31.738281 25.699219 C 31.3125 26.015625 30.714844 25.929688 30.394531 25.507812 C 30.242188 25.308594 30.175781 25.054688 30.210938 24.804688 C 30.25 24.554688 30.382812 24.332031 30.585938 24.183594 C 32.472656 22.808594 33.585938 20.609375 33.578125 18.269531 C 33.585938 15.933594 32.472656 13.730469 30.585938 12.359375 C 30.382812 12.210938 30.25 11.984375 30.210938 11.734375 C 30.175781 11.488281 30.242188 11.234375 30.394531 11.03125 C 30.71875 10.617188 31.3125 10.53125 31.738281 10.839844 C 34.121094 12.601562 35.519531 15.355469 35.503906 18.273438 C 35.507812 21.210938 34.109375 23.972656 31.738281 25.699219 Z M 19.515625 18.269531 C 19.515625 19.71875 20.261719 21.035156 21.511719 21.789062 C 21.726562 21.917969 21.882812 22.128906 21.941406 22.375 C 22.003906 22.621094 21.960938 22.878906 21.828125 23.09375 C 21.542969 23.539062 20.957031 23.675781 20.503906 23.40625 C 18.699219 22.328125 17.59375 20.378906 17.59375 18.269531 C 17.59375 16.164062 18.699219 14.210938 20.503906 13.136719 C 20.957031 12.867188 21.542969 13.003906 21.828125 13.449219 C 21.960938 13.664062 22.003906 13.921875 21.941406 14.167969 C 21.882812 14.410156 21.726562 14.621094 21.511719 14.75 C 20.273438 15.488281 19.515625 16.824219 19.515625 18.269531 Z M 18.429688 24.1875 C 18.632812 24.335938 18.765625 24.5625 18.800781 24.808594 C 18.839844 25.058594 18.773438 25.3125 18.621094 25.515625 C 18.296875 25.933594 17.699219 26.019531 17.273438 25.703125 C 14.90625 23.976562 13.503906 21.214844 13.511719 18.273438 C 13.503906 15.335938 14.90625 12.574219 17.273438 10.847656 C 17.480469 10.699219 17.734375 10.632812 17.988281 10.667969 C 18.238281 10.703125 18.464844 10.835938 18.621094 11.039062 C 18.773438 11.242188 18.839844 11.492188 18.800781 11.742188 C 18.765625 11.992188 18.632812 12.21875 18.429688 12.367188 C 16.542969 13.738281 15.429688 15.9375 15.433594 18.273438 C 15.429688 20.613281 16.542969 22.8125 18.429688 24.1875 Z M 18.429688 24.1875 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(90.588236%,90.588236%,92.54902%);fill-opacity:1;" d="M 20 0 C 33.332031 0 40 6.667969 40 20 C 40 33.332031 33.332031 40 20 40 C 6.667969 40 0 33.332031 0 20 C 0 6.667969 6.667969 0 20 0 Z M 20 0 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(96.078432%,42.352942%,42.352942%);fill-opacity:1;" d="M 18.582031 29.328125 C 18.582031 28.53125 19.226562 27.882812 20.027344 27.882812 C 20.824219 27.882812 21.46875 28.53125 21.46875 29.328125 C 21.46875 30.125 20.824219 30.769531 20.027344 30.769531 C 19.230469 30.769531 18.582031 30.125 18.582031 29.328125 Z M 32.34375 15.113281 C 32.855469 15.625 32.855469 16.449219 32.347656 16.960938 C 31.835938 17.472656 31.011719 17.472656 30.496094 16.960938 C 24.699219 11.164062 15.300781 11.164062 9.503906 16.960938 C 8.996094 17.472656 8.167969 17.472656 7.65625 16.960938 C 7.410156 16.71875 7.273438 16.382812 7.273438 16.039062 C 7.273438 15.691406 7.410156 15.359375 7.65625 15.113281 C 14.472656 8.296875 25.527344 8.296875 32.34375 15.113281 Z M 11.285156 19.25 C 16.097656 14.441406 23.898438 14.441406 28.710938 19.25 C 29.222656 19.761719 29.222656 20.589844 28.710938 21.097656 C 28.46875 21.34375 28.136719 21.484375 27.789062 21.484375 C 27.441406 21.484375 27.109375 21.34375 26.863281 21.097656 C 23.074219 17.308594 16.921875 17.308594 13.132812 21.097656 C 12.625 21.613281 11.796875 21.613281 11.285156 21.101562 C 11.039062 20.855469 10.902344 20.523438 10.902344 20.175781 C 10.902344 19.828125 11.039062 19.496094 11.285156 19.25 Z M 25.183594 25.558594 C 24.738281 26.007812 24.035156 26.070312 23.515625 25.710938 L 23.5 25.730469 L 23.257812 25.484375 C 21.46875 23.699219 18.574219 23.695312 16.785156 25.484375 C 16.277344 25.996094 15.449219 25.996094 14.9375 25.488281 C 14.691406 25.242188 14.554688 24.910156 14.554688 24.5625 C 14.554688 24.214844 14.691406 23.882812 14.9375 23.636719 C 17.746094 20.828125 22.296875 20.828125 25.105469 23.636719 L 25.160156 23.695312 L 25.179688 23.710938 L 25.234375 23.765625 L 25.347656 23.882812 L 25.335938 23.894531 C 25.6875 24.402344 25.636719 25.105469 25.183594 25.558594 Z M 25.183594 25.558594 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(53.333336%,9.019608%,10.196079%);fill-opacity:1;" d="M 39.964844 19.410156 C 39.964844 19.410156 40.886719 0 19.558594 0 C 0.695312 0 0.105469 18.617188 0.105469 18.617188 C 0.105469 18.617188 -2.667969 40 19.996094 40 C 41.734375 40 39.964844 19.410156 39.964844 19.410156 Z M 13.589844 12.625 C 17.589844 10.175781 22.707031 11.675781 24.621094 15.355469 C 24.984375 16.054688 25.03125 17.128906 24.800781 17.859375 C 24.007812 20.386719 22.132812 21.804688 19.558594 22.40625 C 20.320312 21.757812 20.921875 21.019531 21.113281 20.003906 C 21.320312 19.023438 21.097656 18.003906 20.503906 17.199219 L 20.507812 17.210938 C 19.566406 15.914062 17.875 15.40625 16.375 15.96875 L 16.398438 15.960938 C 14.816406 16.558594 13.949219 18.007812 14.105469 19.785156 C 14.25 21.433594 15.503906 22.503906 17.847656 22.910156 C 17.496094 23.09375 17.226562 23.230469 16.960938 23.378906 C 15.898438 23.964844 14.96875 24.769531 14.238281 25.738281 L 14.222656 25.761719 C 13.984375 26.082031 13.824219 26.109375 13.457031 25.886719 C 8.746094 23.007812 8.445312 15.777344 13.589844 12.628906 Z M 10.066406 30.429688 C 9.308594 30.625 8.574219 30.90625 7.800781 31.160156 C 8.179688 28.605469 11.171875 26.253906 13.699219 26.523438 C 12.96875 27.527344 12.539062 28.71875 12.46875 29.957031 L 12.464844 29.976562 C 11.625 30.132812 10.832031 30.234375 10.066406 30.429688 Z M 26.171875 5.5 C 26.917969 5.527344 27.667969 5.515625 28.417969 5.535156 C 28.621094 5.546875 28.8125 5.578125 29 5.617188 L 28.972656 5.609375 C 28.804688 5.871094 28.613281 6.113281 28.402344 6.335938 L 28.40625 6.332031 C 28.140625 6.582031 27.835938 6.828125 27.449219 6.449219 C 27.359375 6.359375 27.140625 6.378906 26.980469 6.375 C 26.234375 6.367188 25.488281 6.339844 24.746094 6.371094 C 24.070312 6.390625 23.402344 6.460938 22.738281 6.578125 L 22.820312 6.566406 C 22.703125 6.585938 22.523438 6.984375 22.578125 7.128906 C 22.707031 7.476562 22.894531 7.855469 23.175781 8.074219 C 24.207031 8.890625 25.304688 9.621094 26.34375 10.429688 C 27.347656 11.214844 28.289062 12.078125 28.859375 13.265625 C 29.601562 14.808594 29.625 16.429688 29.304688 18.058594 C 28.765625 20.773438 27.390625 23.023438 25.164062 24.664062 C 24.269531 25.320312 23.15625 25.695312 22.128906 26.167969 C 21.226562 26.582031 20.296875 26.941406 19.390625 27.355469 C 17.757812 28.097656 16.839844 29.871094 17.109375 31.710938 C 17.359375 33.402344 18.84375 34.816406 20.539062 35.109375 C 22.578125 35.457031 24.683594 34.132812 25.179688 32.058594 C 25.742188 29.730469 24.476562 27.648438 22.105469 27.015625 L 21.679688 26.90625 C 22.3125 26.625 22.859375 26.421875 23.367188 26.144531 C 24.246094 25.65625 25.113281 25.144531 25.960938 24.601562 C 26.210938 24.441406 26.347656 24.441406 26.5625 24.625 C 28.191406 26.035156 29.164062 27.789062 29.4375 29.9375 C 29.886719 33.496094 28.203125 36.765625 25.027344 38.4375 C 20.113281 41.03125 14.097656 38.078125 13.011719 32.632812 C 12.082031 27.964844 15.375 23.734375 19.339844 22.917969 C 21.046875 22.566406 22.605469 21.855469 23.816406 20.542969 C 24.601562 19.695312 24.976562 18.96875 25.109375 18.640625 C 25.335938 18.070312 25.46875 17.410156 25.46875 16.71875 L 25.46875 16.707031 C 25.441406 16.128906 25.304688 15.554688 25.0625 15.027344 L 25.074219 15.054688 C 24.660156 14.109375 23.074219 12.609375 22.683594 12.296875 L 18.949219 9.371094 C 18.816406 9.261719 18.667969 9.269531 18.347656 9.292969 C 17.964844 9.320312 16.988281 9.371094 16.570312 9.261719 C 16.910156 9.003906 17.835938 8.628906 18.234375 8.328125 C 17.027344 7.511719 15.644531 7.804688 14.378906 7.5625 C 14.671875 7.015625 16.121094 6.175781 16.945312 6.082031 C 16.894531 5.59375 16.816406 5.109375 16.703125 4.628906 L 16.722656 4.710938 C 16.671875 4.527344 16.464844 4.347656 16.28125 4.242188 C 15.847656 3.984375 15.382812 3.773438 14.878906 3.515625 C 15.328125 3.226562 15.847656 3.0625 16.382812 3.050781 L 16.386719 3.050781 C 16.910156 3.035156 17.433594 3.085938 17.941406 3.207031 L 17.902344 3.199219 C 18.800781 3.402344 19.515625 3.269531 20.234375 2.660156 C 19.667969 2.433594 19.105469 2.226562 18.5625 1.980469 C 17.929688 1.691406 17.414062 1.417969 16.917969 1.117188 L 16.992188 1.160156 C 18.40625 1.355469 19.777344 1.886719 21.226562 1.691406 L 21.261719 1.496094 L 17.898438 0.710938 C 19.902344 0.527344 21.769531 0.5 23.539062 1.359375 C 24.035156 1.601562 24.554688 1.800781 25.03125 2.078125 C 25.265625 2.210938 25.421875 2.480469 25.613281 2.6875 C 25.761719 2.851562 25.886719 3.070312 26.074219 3.171875 C 26.777344 3.546875 27.554688 3.5625 28.347656 3.542969 L 28.363281 3.277344 C 29.164062 3.527344 30.058594 4.445312 30.058594 5.117188 C 28.765625 5.117188 27.476562 5.113281 26.183594 5.125 C 26.046875 5.125 25.910156 5.226562 25.773438 5.28125 C 25.902344 5.355469 26.03125 5.492188 26.164062 5.5 Z M 24.503906 3.589844 C 24.453125 3.621094 24.417969 3.675781 24.410156 3.738281 C 24.40625 3Line truncated
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="px" height="40px" viewBox="0 0 40 40" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(54.11765%,54.11765%,54.11765%);fill-opacity:1;" d="M 39.964844 19.410156 C 39.964844 19.410156 40.886719 0 19.558594 0 C 0.695312 0 0.105469 18.617188 0.105469 18.617188 C 0.105469 18.617188 -2.667969 40 19.996094 40 C 41.734375 40 39.964844 19.410156 39.964844 19.410156 Z M 13.589844 12.625 C 17.589844 10.175781 22.707031 11.675781 24.621094 15.355469 C 24.984375 16.054688 25.03125 17.128906 24.800781 17.863281 C 24.007812 20.386719 22.132812 21.804688 19.558594 22.410156 C 20.316406 21.757812 20.921875 21.023438 21.113281 20.003906 C 21.316406 19.03125 21.097656 18.015625 20.507812 17.210938 C 19.570312 15.921875 17.894531 15.414062 16.398438 15.960938 C 14.816406 16.558594 13.949219 18.007812 14.105469 19.785156 C 14.25 21.433594 15.503906 22.503906 17.847656 22.910156 C 17.496094 23.09375 17.226562 23.230469 16.964844 23.378906 C 15.890625 23.964844 14.953125 24.78125 14.222656 25.761719 C 13.984375 26.082031 13.824219 26.109375 13.460938 25.886719 C 8.75 23.003906 8.445312 15.773438 13.589844 12.625 Z M 10.066406 30.429688 C 9.308594 30.625 8.574219 30.90625 7.800781 31.160156 C 8.179688 28.605469 11.171875 26.253906 13.699219 26.523438 C 12.96875 27.53125 12.539062 28.730469 12.464844 29.976562 C 11.625 30.132812 10.832031 30.234375 10.066406 30.429688 Z M 26.171875 5.5 C 26.917969 5.527344 27.667969 5.515625 28.417969 5.535156 C 28.605469 5.546875 28.789062 5.570312 28.972656 5.613281 C 28.804688 5.867188 28.617188 6.109375 28.40625 6.335938 C 28.140625 6.585938 27.839844 6.828125 27.453125 6.449219 C 27.359375 6.359375 27.140625 6.378906 26.980469 6.375 C 26.234375 6.367188 25.488281 6.34375 24.746094 6.371094 C 24.101562 6.390625 23.460938 6.457031 22.824219 6.566406 C 22.703125 6.589844 22.527344 6.984375 22.578125 7.132812 C 22.710938 7.476562 22.898438 7.855469 23.179688 8.078125 C 24.210938 8.894531 25.308594 9.625 26.34375 10.433594 C 27.351562 11.21875 28.289062 12.082031 28.863281 13.265625 C 29.605469 14.8125 29.628906 16.433594 29.308594 18.058594 C 28.769531 20.777344 27.394531 23.027344 25.167969 24.664062 C 24.273438 25.320312 23.160156 25.695312 22.132812 26.167969 C 21.226562 26.585938 20.300781 26.941406 19.394531 27.355469 C 17.761719 28.097656 16.84375 29.871094 17.113281 31.714844 C 17.359375 33.40625 18.84375 34.816406 20.542969 35.109375 C 22.582031 35.457031 24.6875 34.132812 25.183594 32.058594 C 25.746094 29.730469 24.480469 27.648438 22.109375 27.019531 L 21.683594 26.910156 C 22.316406 26.625 22.863281 26.421875 23.371094 26.144531 C 24.25 25.660156 25.117188 25.144531 25.964844 24.601562 C 26.214844 24.441406 26.351562 24.441406 26.566406 24.625 C 28.195312 26.035156 29.167969 27.789062 29.441406 29.9375 C 29.890625 33.496094 28.207031 36.765625 25.03125 38.441406 C 20.117188 41.03125 14.101562 38.082031 13.015625 32.632812 C 12.085938 27.964844 15.378906 23.734375 19.34375 22.917969 C 21.050781 22.566406 22.609375 21.855469 23.820312 20.542969 C 24.601562 19.695312 24.980469 18.96875 25.113281 18.640625 C 25.351562 18.023438 25.476562 17.371094 25.472656 16.710938 C 25.449219 16.140625 25.3125 15.578125 25.078125 15.058594 C 24.664062 14.113281 23.078125 12.613281 22.6875 12.296875 L 18.953125 9.375 C 18.820312 9.265625 18.671875 9.273438 18.351562 9.296875 C 17.96875 9.320312 16.996094 9.375 16.574219 9.265625 C 16.914062 9.007812 17.839844 8.632812 18.242188 8.332031 C 17.03125 7.515625 15.652344 7.808594 14.382812 7.566406 C 14.675781 7.019531 16.125 6.179688 16.953125 6.085938 C 16.902344 5.625 16.828125 5.167969 16.726562 4.714844 C 16.675781 4.53125 16.46875 4.347656 16.289062 4.242188 C 15.851562 3.988281 15.386719 3.773438 14.882812 3.519531 C 15.335938 3.230469 15.855469 3.066406 16.394531 3.054688 C 16.902344 3.035156 17.410156 3.082031 17.90625 3.199219 C 18.808594 3.40625 19.523438 3.269531 20.238281 2.660156 C 19.675781 2.433594 19.113281 2.226562 18.566406 1.980469 C 18.027344 1.734375 17.503906 1.460938 16.996094 1.160156 C 18.414062 1.355469 19.78125 1.886719 21.230469 1.691406 L 21.265625 1.496094 L 17.902344 0.714844 C 19.910156 0.53125 21.773438 0.5 23.542969 1.359375 C 24.042969 1.601562 24.558594 1.804688 25.039062 2.078125 C 25.273438 2.214844 25.425781 2.480469 25.617188 2.6875 C 25.769531 2.851562 25.890625 3.070312 26.078125 3.171875 C 26.785156 3.546875 27.5625 3.5625 28.355469 3.542969 L 28.371094 3.277344 C 29.171875 3.527344 30.066406 4.445312 30.066406 5.117188 C 28.773438 5.117188 27.484375 5.113281 26.191406 5.125 C 26.054688 5.125 25.917969 5.226562 25.78125 5.28125 C 25.910156 5.359375 26.039062 5.496094 26.171875 5.5 Z M 24.503906 3.589844 C 24.453125 3.621094 24.417969 3.675781 24.410156 3.738281 C 24.40625 3.800781 24.429688 3.863281 24.476562 3.90625 C 24.519531 3.972656 24.582031 4.023438 24.660156 4.042969 C 24.738281 4.066406 24.820312 4.054688 24.886719 4.011719 C 25.011719 3.949219 25.136719 3.882812 25.285156 3.804688 C 25.164062 3.703125 25.066406 3.613281 24.96875 3.535156 Line truncated
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

@@ -0,0 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 68">
<defs>
<linearGradient id="lg" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#ffffff" stop-opacity="0.9"/>
<stop offset="0.45" stop-color="#9fd4ff" stop-opacity="0.5"/>
<stop offset="1" stop-color="#1273c9" stop-opacity="0.92"/>
</linearGradient>
</defs>
<path d="M32 3 C46 20 57 30 57 42 a25 25 0 0 1 -50 0 C7 30 18 20 32 3 Z" fill="url(#lg)" stroke="rgba(255,255,255,0.65)" stroke-width="1.5"/>
<ellipse cx="23" cy="39" rx="9.5" ry="6" fill="#ffffff" opacity="0.55"/>
</svg>

After

Width:  |  Height:  |  Size: 584 B

File diff suppressed because it is too large. Load diff
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a9 9 0 0 0 0 18 7 7 0 0 1 0-18z"/><path d="M19 4.5v4M17 6.5h4M20 15h.01M18.5 18.5l.01.01"/></svg>

After

Width:  |  Height:  |  Size: 270 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9l6 6 6-6"/></svg>

After

Width:  |  Height:  |  Size: 191 B

Loaded 100 of 124 files, more files were not shown because too many files have changed in this diff. Show more