mirror of
https://github.com/alexhopeoconnor/WiFiManager.git
synced 2026-10-14 15:11:32 +10:00
234 lines
16 KiB
C
234 lines
16 KiB
C
/**
|
|
* CSS.h
|
|
*
|
|
* @author alexhopeoconnor
|
|
* @license MIT
|
|
*
|
|
* CSS stylesheet for WiFiManager web interface.
|
|
* Embedded styles to avoid external file dependencies.
|
|
*/
|
|
|
|
#ifndef _CSS_TEMPLATES_H_
|
|
#define _CSS_TEMPLATES_H_
|
|
|
|
#include <Arduino.h>
|
|
|
|
const char CSS_STYLE[] PROGMEM = "<style>"
|
|
/* Design tokens */
|
|
":root{"
|
|
"--wm-bg:#f0f4f8;"
|
|
"--wm-surface:#ffffff;"
|
|
"--wm-text:#0f172a;"
|
|
"--wm-muted:#64748b;"
|
|
"--wm-border:#e2e8f0;"
|
|
"--wm-brand:#0ea5e9;"
|
|
"--wm-brand-hover:#0284c7;"
|
|
"--wm-brand-text:#ffffff;"
|
|
"--wm-danger:#dc2626;"
|
|
"--wm-danger-hover:#b91c1c;"
|
|
"--wm-success:#16a34a;"
|
|
"--wm-radius:12px;"
|
|
"--wm-radius-sm:8px;"
|
|
"--wm-shadow:0 1px 3px rgba(15,23,42,.08),0 4px 16px rgba(15,23,42,.06);"
|
|
"--wm-font:system-ui,-apple-system,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;"
|
|
"}"
|
|
"body.invert{"
|
|
"--wm-bg:#0c1222;"
|
|
"--wm-surface:#151d2e;"
|
|
"--wm-text:#f1f5f9;"
|
|
"--wm-muted:#94a3b8;"
|
|
"--wm-border:#334155;"
|
|
"--wm-brand:#38bdf8;"
|
|
"--wm-brand-hover:#7dd3fc;"
|
|
"--wm-danger:#f87171;"
|
|
"--wm-danger-hover:#fca5a5;"
|
|
"--wm-success:#4ade80;"
|
|
"--wm-shadow:0 4px 24px rgba(0,0,0,.45);"
|
|
"}"
|
|
/* Base */
|
|
"*,*::before,*::after{box-sizing:border-box}"
|
|
"body.portal{margin:0;min-height:100vh;background:var(--wm-bg);color:var(--wm-text);"
|
|
"font-family:var(--wm-font);font-size:16px;line-height:1.5;-webkit-text-size-adjust:100%;text-align:left}"
|
|
"a{color:var(--wm-brand);font-weight:600;text-decoration:none}"
|
|
"a:hover{color:var(--wm-brand-hover);text-decoration:underline}"
|
|
/* Layout shell */
|
|
".wm-layout{width:100%;max-width:420px;margin:0 auto;padding:16px 18px 28px;}"
|
|
"h1,h2,h3{margin:0 0 .35em;font-weight:700;letter-spacing:-.02em}"
|
|
"h1{font-size:1.5rem}"
|
|
"h2{font-size:1.15rem}"
|
|
"h3{font-size:1rem}"
|
|
"p{margin:.5em 0}"
|
|
/* Top navigation — single row; overflow scrollable but scrollbar hidden (touch still pans) */
|
|
".wm-nav{display:flex;flex-wrap:nowrap;align-items:stretch;gap:4px;margin:0 0 20px;padding:4px 6px;"
|
|
"overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;-ms-overflow-style:none;"
|
|
"background:var(--wm-surface);border-radius:var(--wm-radius);box-shadow:var(--wm-shadow);border:1px solid var(--wm-border)}"
|
|
".wm-nav::-webkit-scrollbar{display:none;width:0;height:0}"
|
|
".wm-nav-link{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;padding:6px 8px;border-radius:var(--wm-radius-sm);"
|
|
"font-size:.8rem;font-weight:600;color:var(--wm-muted);text-decoration:none;border:1px solid transparent;white-space:nowrap}"
|
|
".wm-nav-link:hover{color:var(--wm-brand);background:rgba(14,165,233,.08);text-decoration:none}"
|
|
"body.invert .wm-nav-link:hover{background:rgba(56,189,248,.12)}"
|
|
".wm-nav-link--active{color:var(--wm-text);background:rgba(14,165,233,.15);border-color:rgba(14,165,233,.35)}"
|
|
"body.invert .wm-nav-link--active{background:rgba(56,189,248,.2);border-color:rgba(56,189,248,.4)}"
|
|
".wm-nav .wm-icon-label{gap:4px}"
|
|
".wm-nav .wm-icon{width:.95rem;height:.95rem;flex:0 0 .95rem}"
|
|
".wm-icon-label{display:inline-flex;align-items:center;gap:8px;min-width:0}"
|
|
".wm-icon{display:inline-flex;align-items:center;justify-content:center;width:1.1rem;height:1.1rem;flex:0 0 1.1rem;color:currentColor}"
|
|
".wm-icon svg{display:block;width:100%;height:100%}"
|
|
/* Header / page chrome */
|
|
".wm-site-header{display:flex;align-items:center;gap:10px;min-height:40px;margin:0 0 12px}"
|
|
".wm-site-logo{display:flex;align-items:center;justify-content:center;width:40px;height:40px;flex:0 0 40px;line-height:0}"
|
|
".wm-site-logo svg{display:block;width:100%;height:100%}"
|
|
".wm-site-brand-copy{min-width:0}"
|
|
".wm-site-brand-name{margin:0;font-size:.78rem;font-weight:800;letter-spacing:.09em;text-transform:uppercase;color:var(--wm-text)}"
|
|
".wm-site-tagline{margin:2px 0 0;font-size:.82rem;line-height:1.25;color:var(--wm-muted)}"
|
|
".wm-page-head{margin-bottom:16px}"
|
|
".wm-page-head h1{font-size:1.45rem}"
|
|
".wm-page-desc{font-size:.95rem;color:var(--wm-muted);margin:.35em 0 0}"
|
|
/* Cards */
|
|
".wm-card{background:var(--wm-surface);border:1px solid var(--wm-border);border-radius:var(--wm-radius);"
|
|
"box-shadow:var(--wm-shadow);padding:18px 16px;margin-bottom:16px;text-align:left}"
|
|
".wm-scan-card,.wm-ota-card{position:relative;overflow:hidden}"
|
|
".wm-scan-results{min-height:126px}"
|
|
".wm-card-title{font-size:1rem;margin:0 0 12px;padding-bottom:10px;border-bottom:1px solid var(--wm-border);"
|
|
"color:var(--wm-text)}"
|
|
".wm-card-subtitle{margin:-4px 0 12px;font-size:.9rem;line-height:1.45;color:var(--wm-muted)}"
|
|
".wm-lead{margin:0 0 8px;font-size:.95rem;color:var(--wm-muted);line-height:1.5}"
|
|
".wm-home-summary{margin:0 0 14px;font-size:1rem;font-weight:600;line-height:1.45;color:var(--wm-text)}"
|
|
/* Callout / status */
|
|
".wm-callout{padding:12px 14px;border-radius:var(--wm-radius-sm);border:1px solid var(--wm-border);"
|
|
"background:rgba(14,165,233,.06);margin-bottom:16px}"
|
|
"body.invert .wm-callout{background:rgba(56,189,248,.08)}"
|
|
".wm-callout--info{border-left:4px solid var(--wm-brand)}"
|
|
".wm-info-summary{font-weight:600;color:var(--wm-text)}"
|
|
".wm-status{margin:0 0 12px;padding:10px 12px;font-size:.92rem;font-weight:700;color:var(--wm-brand);"
|
|
"text-align:center;border-radius:var(--wm-radius-sm);background:rgba(14,165,233,.08);border:1px solid rgba(14,165,233,.18)}"
|
|
".wm-status--warning{color:#c2410c;background:rgba(249,115,22,.12);border-color:rgba(249,115,22,.28)}"
|
|
".wm-status--caution{color:#a16207;background:rgba(234,179,8,.14);border-color:rgba(234,179,8,.3)}"
|
|
".wm-status--danger{color:var(--wm-danger);background:rgba(220,38,38,.12);border-color:rgba(220,38,38,.28)}"
|
|
"body.invert .wm-status{background:rgba(56,189,248,.12);border-color:rgba(56,189,248,.22)}"
|
|
"body.invert .wm-status--warning{background:rgba(249,115,22,.18);border-color:rgba(249,115,22,.34)}"
|
|
"body.invert .wm-status--caution{background:rgba(234,179,8,.18);border-color:rgba(234,179,8,.34)}"
|
|
"body.invert .wm-status--danger{background:rgba(220,38,38,.18);border-color:rgba(220,38,38,.34)}"
|
|
/* Form fields */
|
|
".wm-field{margin-bottom:14px;text-align:left}"
|
|
".wm-field:last-child{margin-bottom:0}"
|
|
".wm-field label{display:block;font-size:.82rem;font-weight:600;color:var(--wm-muted);margin-bottom:6px}"
|
|
"input[type=text],input[type=password],input[type=number],input[type=email],select{"
|
|
"display:block;width:100%;padding:12px 14px;font-size:1rem;font-family:inherit;"
|
|
"color:var(--wm-text);background:var(--wm-bg);border:1px solid var(--wm-border);border-radius:var(--wm-radius-sm);"
|
|
"-webkit-appearance:none;appearance:none}"
|
|
"input:focus,select:focus{outline:2px solid var(--wm-brand);outline-offset:0;border-color:var(--wm-brand)}"
|
|
"input[type=radio],input[type=checkbox]{width:auto;margin-right:8px;accent-color:var(--wm-brand)}"
|
|
".wm-checkbox-row{display:flex;align-items:center;gap:8px;margin:12px 0;font-size:.92rem}"
|
|
".wm-checkbox-row label{display:inline;margin:0;font-weight:500;color:var(--wm-text)}"
|
|
".wm-form-actions{margin-top:16px}"
|
|
".wm-wifi-details-card{position:relative}"
|
|
".wm-wifi-save-overlay{position:fixed;inset:0;z-index:10002;display:none;align-items:center;justify-content:center;padding:18px;"
|
|
"box-sizing:border-box;background:rgba(15,23,42,.58)}"
|
|
".wm-wifi-save-panel{display:flex;align-items:center;gap:14px;width:100%;max-width:340px;padding:18px;border:1px solid var(--wm-border);"
|
|
"border-radius:var(--wm-radius-sm);background:var(--wm-surface);box-shadow:var(--wm-shadow);text-align:left}"
|
|
".wm-wifi-save-panel strong{display:block;font-size:1rem;color:var(--wm-text)}"
|
|
".wm-wifi-save-panel p{margin:4px 0 0;font-size:.9rem;line-height:1.45;color:var(--wm-muted)}"
|
|
".wm-operation-overlay{position:absolute;inset:0;z-index:5;display:none;align-items:center;justify-content:center;padding:16px;background:rgba(15,23,42,.56)}"
|
|
".wm-operation-panel{display:flex;align-items:center;gap:12px;width:100%;max-width:310px;padding:16px;border:1px solid var(--wm-border);border-radius:var(--wm-radius-sm);background:var(--wm-surface);box-shadow:var(--wm-shadow);text-align:left}"
|
|
".wm-operation-panel strong{display:block;font-size:.98rem;color:var(--wm-text)}"
|
|
".wm-operation-panel p{margin:3px 0 0;font-size:.88rem;line-height:1.4;color:var(--wm-muted)}"
|
|
".wm-operation-progress{margin-top:10px}"
|
|
".wm-operation-progress-track{height:7px;overflow:hidden;border-radius:999px;background:var(--wm-border)}"
|
|
".wm-operation-progress-track span{display:block;width:0;height:100%;border-radius:inherit;background:var(--wm-brand);transition:width .15s ease}"
|
|
".wm-operation-progress-label{display:block;margin-top:4px;font-size:.8rem;font-weight:700;color:var(--wm-muted);text-align:right}"
|
|
".wm-portal-timeout-row{display:flex;align-items:stretch;gap:8px;margin:0 0 12px}"
|
|
".wm-portal-timeout-row .wm-status{flex:1;margin:0}"
|
|
".wm-icon-button{display:inline-flex;align-items:center;justify-content:center;width:42px;min-height:42px;padding:0;border:1px solid var(--wm-border);border-radius:var(--wm-radius-sm);background:var(--wm-bg);color:var(--wm-text);cursor:pointer}"
|
|
".wm-icon-button:hover{border-color:var(--wm-brand);color:var(--wm-brand)}"
|
|
".wm-icon-button:disabled{opacity:.5;cursor:not-allowed}"
|
|
".wm-icon-button .wm-icon{width:1.05rem;height:1.05rem}"
|
|
".wm-inline-link{display:inline-block;margin-top:12px;font-size:.92rem}"
|
|
".wm-spinner{width:24px;height:24px;flex:0 0 24px;border:3px solid var(--wm-border);border-top-color:var(--wm-brand);border-radius:50%;animation:wm-spin .8s linear infinite}"
|
|
"@keyframes wm-spin{to{transform:rotate(360deg)}}"
|
|
"@media (prefers-reduced-motion:reduce){.wm-spinner{animation:none;border-right-color:var(--wm-brand)}}"
|
|
/* Buttons */
|
|
".wm-btn{display:inline-flex;align-items:center;justify-content:center;min-height:44px;padding:0 18px;"
|
|
"font-size:1rem;font-weight:600;font-family:inherit;border-radius:var(--wm-radius-sm);border:0;cursor:pointer;"
|
|
"transition:background .15s,transform .1s,opacity .15s}"
|
|
".wm-btn:disabled{opacity:.5;cursor:not-allowed}"
|
|
".wm-btn:active{transform:scale(.98)}"
|
|
"a.wm-btn{box-sizing:border-box;text-decoration:none}"
|
|
".wm-btn .wm-icon-label{justify-content:center}"
|
|
".wm-btn--block{width:100%}"
|
|
".wm-btn--primary{background:var(--wm-brand);color:var(--wm-brand-text)}"
|
|
".wm-btn--primary:hover{background:var(--wm-brand-hover)}"
|
|
".wm-btn--secondary{background:var(--wm-bg);color:var(--wm-text);border:1px solid var(--wm-border)}"
|
|
".wm-btn--secondary:hover{border-color:var(--wm-brand);color:var(--wm-brand)}"
|
|
".wm-btn--danger{background:var(--wm-danger);color:var(--wm-brand-text)}"
|
|
".wm-btn--danger:hover{background:var(--wm-danger-hover)}"
|
|
"input[type=file]{width:100%;padding:10px;border:1px dashed var(--wm-border);border-radius:var(--wm-radius-sm);"
|
|
"background:var(--wm-bg);font-size:.9rem}"
|
|
/* Legacy: unclassed submit in forms */
|
|
"button[type=submit],.wm-form-actions .wm-btn--primary{background:var(--wm-brand);color:var(--wm-brand-text)}"
|
|
"button[type=submit]:hover{background:var(--wm-brand-hover)}"
|
|
/* Device actions / button stack */
|
|
".wm-actions-stack{display:flex;flex-direction:column;gap:10px;margin-top:4px}"
|
|
".wm-btn-group{display:flex;flex-direction:column;gap:10px}"
|
|
/* WiFi scan list */
|
|
".wm-scan-list{margin:0 0 12px;border:1px solid var(--wm-border);border-radius:var(--wm-radius-sm);"
|
|
"overflow:hidden;background:var(--wm-bg)}"
|
|
".wm-scan-row{display:flex;align-items:center;gap:10px;min-height:48px;padding:10px 12px;"
|
|
"border-bottom:1px solid var(--wm-border);text-decoration:none;color:inherit;cursor:pointer}"
|
|
".wm-scan-row:last-child{border-bottom:0}"
|
|
".wm-scan-row:hover{background:rgba(14,165,233,.1)}"
|
|
"body.invert .wm-scan-row:hover{background:rgba(56,189,248,.12)}"
|
|
".wm-scan-ssid{flex:1;min-width:0;font-weight:600;font-size:.95rem;text-align:left;word-break:break-word}"
|
|
".wm-scan-meta{display:flex;align-items:center;justify-content:flex-end;gap:6px;flex-shrink:0;min-width:78px}"
|
|
".wm-scan-signal{display:block;flex-shrink:0;font-size:.8rem;color:var(--wm-muted);font-weight:600;min-width:38px;text-align:right}"
|
|
".wm-scan-lock,.wm-scan-bars{display:block;flex:0 0 16px}"
|
|
// quality icons
|
|
".q{position:relative;height:16px;width:16px;margin:0;padding:0;flex-shrink:0}.q.q-0:after{background-position-x:0}.q.q-1:after{background-position-x:-16px}.q.q-2:after{background-position-x:-32px}.q.q-3:after{background-position-x:-48px}.q.q-4:after{background-position-x:-64px}.q.l:before{background-position-x:-80px}.ql .q{float:left}.q:after,.q:before{content:'';position:absolute;left:0;top:0;width:16px;height:16px;display:block;background-repeat:no-repeat;background-position:16px 0;"
|
|
"background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAAAQCAMAAADeZIrLAAAAJFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADHJj5lAAAAC3RSTlMAIjN3iJmqu8zd7vF8pzcAAABsSURBVHja7Y1BCsAwCASNSVo3/v+/BUEiXnIoXkoX5jAQMxTHzK9cVSnvDxwD8bFx8PhZ9q8FmghXBhqA1faxk92PsxvRc2CCCFdhQCbRkLoAQ3q/wWUBqG35ZxtVzW4Ed6LngPyBU2CobdIDQ5oPWI5nCUwAAAAASUVORK5CYII=');}"
|
|
".wm-scan-lock:after,.wm-scan-bars:before{content:none}"
|
|
"@media (-webkit-min-device-pixel-ratio: 2),(min-resolution: 192dpi){.q:before,.q:after {"
|
|
"background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALwAAAAgCAMAAACfM+KhAAAALVBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAOrOgAAAADnRSTlMAESIzRGZ3iJmqu8zd7gKjCLQAAACmSURBVHgB7dDBCoMwEEXRmKlVY3L//3NLhyzqIqSUggy8uxnhCR5Mo8xLt+14aZ7wwgsvvPA/ofv9+44334UXXngvb6XsFhO/VoC2RsSv9J7x8BnYLW+AjT56ud/uePMdb7IP8Bsc/e7h8Cfk912ghsNXWPpDC4hvN+D1560A1QPORyh84VKLjjdvfPFm++i9EWq0348XXnjhhT+4dIbCW+WjZim9AKk4UZMnnCEuAAAAAElFTkSuQmCC');"
|
|
"background-size: 95px 16px;}}"
|
|
// messages from firmware / server
|
|
".msg{padding:16px;margin:12px 0;border-radius:var(--wm-radius-sm);border:1px solid var(--wm-border);"
|
|
"border-left-width:4px;border-left-color:var(--wm-muted);background:var(--wm-surface);text-align:left}"
|
|
".msg h4{margin:0 0 8px;font-size:1rem}"
|
|
".msg.P{border-left-color:var(--wm-brand)}.msg.P h4{color:var(--wm-brand)}"
|
|
".msg.D{border-left-color:var(--wm-danger)}.msg.D h4{color:var(--wm-danger)}"
|
|
".msg.S{border-left-color:var(--wm-success)}.msg.S h4{color:var(--wm-success)}"
|
|
"dt{font-weight:700;font-size:.85rem;color:var(--wm-muted)}dd{margin:2px 0 12px 0;padding:0;font-size:.95rem}"
|
|
"td{vertical-align:top}"
|
|
".h{display:none}"
|
|
/* Info page key-value grid */
|
|
".wm-kv{margin:0;padding:0}"
|
|
".wm-kv dt{padding-top:10px}"
|
|
".wm-kv dt:first-of-type{padding-top:0}"
|
|
".wm-kv dd{margin-left:0;padding-bottom:4px;border-bottom:1px solid var(--wm-border)}"
|
|
".wm-kv dd:last-of-type{border-bottom:0}"
|
|
/* Feedback areas */
|
|
"#wm-wifi-msg,#wm-param-msg{font-size:.9rem;margin-top:12px;min-height:1.2em;color:var(--wm-muted)}"
|
|
// invert legacy body
|
|
"body.invert{background-color:var(--wm-bg)}"
|
|
"body.invert .msg{border-color:var(--wm-border)}"
|
|
"body.invert .q[role=img]{-webkit-filter:invert(1);filter:invert(1)}"
|
|
":disabled{opacity:.55}"
|
|
// toast + modal
|
|
".wm-toast{position:fixed;left:50%;top:12px;transform:translateX(-50%);z-index:10001;max-width:92%;padding:12px 16px;border-radius:var(--wm-radius-sm);"
|
|
"box-shadow:var(--wm-shadow);font-size:.95rem;text-align:center;font-weight:600}"
|
|
".wm-toast.ok{background:rgba(22,163,74,.15);border:1px solid var(--wm-success);color:var(--wm-text)}"
|
|
".wm-toast.err{background:rgba(220,38,38,.12);border:1px solid var(--wm-danger);color:var(--wm-text)}"
|
|
".wm-dialog{position:fixed;inset:0;z-index:10000;display:none;align-items:center;justify-content:center;padding:16px;box-sizing:border-box}"
|
|
".wm-dialog-backdrop{position:absolute;inset:0;background:rgba(15,23,42,.5)}"
|
|
".wm-dialog-panel{position:relative;z-index:1;background:var(--wm-surface);border-radius:var(--wm-radius);padding:20px 18px;max-width:400px;width:100%;"
|
|
"box-shadow:var(--wm-shadow);border:1px solid var(--wm-border);text-align:left}"
|
|
".wm-dialog-msg{margin:0 0 16px;line-height:1.45;color:var(--wm-text)}"
|
|
".wm-dialog-actions{display:flex;gap:10px;justify-content:flex-end;flex-wrap:wrap}"
|
|
".wm-dialog-actions .wm-btn{min-width:108px}"
|
|
".wm-dialog-ok,.wm-btn.wm-dialog-ok{background:var(--wm-brand)!important;color:var(--wm-brand-text)!important}"
|
|
".wm-dialog-ok:hover{background:var(--wm-brand-hover)!important}"
|
|
"body.invert .wm-toast.ok{background:rgba(22,163,74,.2)}"
|
|
"body.invert .wm-toast.err{background:rgba(220,38,38,.2)}"
|
|
"</style>";
|
|
|
|
#endif // _CSS_TEMPLATES_H_
|