diff --git a/base.css b/base.css index 0347dca..1f37600 100644 --- a/base.css +++ b/base.css @@ -175,7 +175,16 @@ --z-popover: 10012; --z-tooltip: 10013; --z-toast: 10014; + --z-panel: 10020; /* notification / generic dropdown panels — above everything */ --z-overlay: 9999; /* scanlines / CRT effects */ + + /* --- Corner cuts (clip-path polygon notches) --- */ + --corner-cut: 8px; + --corner-cut-sm: 5px; + --corner-cut-lg: 16px; + + /* --- Syntax highlight --- */ + --color-tok-cmt: #5c8c6a; } @@ -763,6 +772,12 @@ hr { .lt-btn:active { transform: translateY(1px); } +.lt-btn:focus-visible { + outline: 2px solid var(--accent-cyan); + outline-offset: 2px; + box-shadow: var(--box-glow-cyan); +} + .lt-btn:disabled, .lt-btn[disabled] { opacity: 0.30; @@ -859,10 +874,27 @@ hr { .lt-input:focus, .lt-select:focus, -.lt-textarea:focus { +.lt-textarea:focus, +.lt-input:focus-visible, +.lt-select:focus-visible, +.lt-textarea:focus-visible { border-color: var(--accent-cyan); box-shadow: var(--box-glow-cyan); background: rgba(0,212,255,0.025); + outline: 2px solid var(--accent-cyan); + outline-offset: 1px; +} + +.lt-input:disabled, +.lt-select:disabled, +.lt-textarea:disabled, +.lt-input[readonly], +.lt-textarea[readonly] { + opacity: 0.45; + cursor: not-allowed; + background: var(--bg-tertiary); + color: var(--text-muted); + border-color: var(--border-dim); } .lt-input::placeholder, @@ -949,6 +981,47 @@ select option:checked { text-shadow: var(--glow-cyan); } .lt-checkbox:hover { border-color: var(--accent-cyan); } +.lt-checkbox:focus-visible { + outline: 2px solid var(--accent-cyan); + outline-offset: 2px; +} +.lt-checkbox:disabled { + opacity: 0.4; + cursor: not-allowed; +} + +/* Radio (same visual language as checkbox) */ +.lt-radio { + appearance: none; + width: 14px; + height: 14px; + border: 1px solid var(--accent-cyan-border); + border-radius: 50%; + background: var(--bg-terminal); + cursor: pointer; + flex-shrink: 0; + vertical-align: middle; + transition: var(--transition-fast); + position: relative; +} +.lt-radio:checked { + border-color: var(--accent-cyan); + background: var(--accent-cyan-dim); +} +.lt-radio:checked::after { + content: ''; + position: absolute; + inset: 3px; + border-radius: 50%; + background: var(--accent-cyan); + box-shadow: var(--glow-cyan); +} +.lt-radio:hover { border-color: var(--accent-cyan); } +.lt-radio:focus-visible { + outline: 2px solid var(--accent-cyan); + outline-offset: 2px; +} +.lt-radio:disabled { opacity: 0.4; cursor: not-allowed; } /* ---------------------------------------------------------------- @@ -1055,7 +1128,7 @@ select option:checked { .lt-status-closed { color: var(--status-closed); background: rgba(255,45,85,0.07); } .lt-status-online { color: var(--status-online); background: rgba(0,255,136,0.07); text-shadow: var(--glow-green); } .lt-status-offline { color: var(--status-offline); background: rgba(255,45,85,0.07); } -.lt-status-running { color: var(--status-running); background: rgba(255,179,0,0.07); animation: pulse-amber 2s infinite; } +.lt-status-running { color: var(--status-running); background: rgba(255,179,0,0.07); animation: pulse-amber 2s infinite; will-change: color; } .lt-status-completed { color: var(--status-completed); background: rgba(0,212,255,0.07); } .lt-status-failed { color: var(--status-failed); background: rgba(255,45,85,0.07); } @@ -1107,6 +1180,17 @@ select option:checked { .lt-badge-amber { color: var(--accent-amber); } .lt-badge-red { color: var(--accent-red); } +/* Status + priority badge variants (dark-mode base) */ +.lt-badge-open { color: var(--accent-green); background: rgba(0,255,136,0.08); border-color: rgba(0,255,136,0.35); text-shadow: var(--glow-green); } +.lt-badge-closed { color: var(--text-muted); background: rgba(74,90,112,0.10); border-color: rgba(74,90,112,0.35); } +.lt-badge-in-progress, +.lt-badge-progress { color: var(--accent-amber); background: rgba(255,179,0,0.08); border-color: rgba(255,179,0,0.35); } +.lt-badge-pending { color: var(--accent-purple); background: rgba(191,95,255,0.08); border-color: rgba(191,95,255,0.35); } +.lt-badge-p1 { color: var(--accent-red); background: rgba(255,45,85,0.09); border-color: rgba(255,45,85,0.40); text-shadow: var(--glow-red); } +.lt-badge-p2 { color: var(--accent-orange); background: rgba(255,107,0,0.09); border-color: rgba(255,107,0,0.38); } +.lt-badge-p3 { color: var(--accent-cyan); background: rgba(0,212,255,0.07); border-color: rgba(0,212,255,0.30); } +.lt-badge-p4 { color: var(--accent-green); background: rgba(0,255,136,0.07); border-color: rgba(0,255,136,0.30); } + /* Status dots */ .lt-dot { display: inline-block; @@ -1115,9 +1199,9 @@ select option:checked { border-radius: 50%; flex-shrink: 0; } -.lt-dot-up { background: var(--accent-green); box-shadow: 0 0 6px var(--accent-green), 0 0 14px var(--accent-green); animation: pulse-green 2.2s ease-in-out infinite; } +.lt-dot-up { background: var(--accent-green); box-shadow: 0 0 6px var(--accent-green), 0 0 14px var(--accent-green); animation: pulse-green 2.2s ease-in-out infinite; will-change: box-shadow; } .lt-dot-down { background: var(--accent-red); box-shadow: 0 0 6px var(--accent-red), 0 0 12px var(--accent-red); } -.lt-dot-warn { background: var(--accent-amber); box-shadow: 0 0 6px var(--accent-amber), 0 0 12px var(--accent-amber); animation: pulse-amber 2.2s ease-in-out infinite; } +.lt-dot-warn { background: var(--accent-amber); box-shadow: 0 0 6px var(--accent-amber), 0 0 12px var(--accent-amber); animation: pulse-amber 2.2s ease-in-out infinite; will-change: box-shadow; } .lt-dot-idle { background: var(--text-muted); box-shadow: none; } @@ -1193,7 +1277,9 @@ select option:checked { padding: 0.2rem 0.4rem; transition: var(--transition-fast); } -.lt-modal-close:hover { color: var(--accent-red); text-shadow: var(--glow-red); } +.lt-modal-close:hover { color: var(--accent-red); text-shadow: var(--glow-red); } +.lt-modal-close:active { color: var(--accent-red); opacity: 0.7; } +.lt-modal-close:focus-visible { outline: 2px solid var(--accent-cyan); outline-offset: 2px; border-radius: 2px; } .lt-modal-body { padding: var(--space-lg); @@ -1292,6 +1378,10 @@ select option:checked { border-color: var(--accent-orange-border); border-bottom-color: var(--bg-card); } +.lt-tab:focus-visible { + outline: 2px solid var(--accent-orange); + outline-offset: -2px; +} .lt-tab-panel { display: none; } .lt-tab-panel.active { display: block; } @@ -1339,8 +1429,10 @@ select option:checked { .lt-filter-group { margin-bottom: var(--space-md); - padding-bottom: var(--space-md); + padding: 0 0 var(--space-md) 0; + border: none; border-bottom: 1px solid var(--border-color-dim); + min-width: 0; /* fieldset UA reset */ } .lt-filter-group:last-child { border-bottom: none; } @@ -2195,7 +2287,35 @@ select option:checked { .lt-text-upper { text-transform: uppercase; letter-spacing: 0.1em; } .lt-hidden { display: none !important; } -.lt-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); border: 0; } + +/* Skip navigation link — visible only on focus */ +.lt-skip-link { + position: absolute; + top: -100%; + left: var(--space-sm); + padding: var(--space-xs) var(--space-md); + background: var(--bg-terminal); + color: var(--accent-cyan); + border: 1px solid var(--accent-cyan); + font-family: var(--font-mono); + font-size: 0.8rem; + text-decoration: none; + text-transform: uppercase; + letter-spacing: 0.05em; + z-index: var(--z-toast); + transition: top 0.1s; +} +.lt-skip-link:focus { top: var(--space-sm); } + +.lt-sr-only { + position: absolute; + width: 1px; height: 1px; + padding: 0; margin: -1px; + overflow: hidden; + clip-path: inset(50%); /* replaces deprecated clip: rect(0,0,0,0) */ + white-space: nowrap; + border: 0; +} /* Cursor blink */ .lt-cursor::after { @@ -2206,6 +2326,9 @@ select option:checked { font-size: 0.85em; margin-left: 1px; } +@media (prefers-reduced-motion: reduce) { + .lt-cursor::after { animation: none; } +} /* Glitch text effect */ .lt-glitch { position: relative; } @@ -2221,11 +2344,13 @@ select option:checked { color: var(--accent-cyan); opacity: 0.65; animation: glitch-1 4s infinite; + will-change: clip-path, transform; } .lt-glitch::after { color: var(--accent-orange); opacity: 0.65; animation: glitch-2 4s 0.12s infinite; + will-change: clip-path, transform; } @@ -2459,6 +2584,7 @@ select option:checked { text-align: left; } .lt-accordion-header:hover { background: var(--bg-tertiary); color: var(--accent-cyan); } +.lt-accordion-header:focus-visible { outline: 2px solid var(--accent-cyan); outline-offset: -2px; } .lt-accordion-header[aria-expanded="true"] { color: var(--accent-orange); } .lt-accordion-icon { width: 14px; @@ -2573,9 +2699,17 @@ input[type="range"].lt-range { height: 4px; background: var(--bg-tertiary); border: 1px solid var(--border-dim); - outline: none; + outline: none; /* reset; :focus-visible below provides keyboard ring */ cursor: pointer; } +input[type="range"].lt-range:focus-visible { + outline: 2px solid var(--accent-orange); + outline-offset: 4px; +} +input[type="range"].lt-range:disabled { + opacity: 0.4; + cursor: not-allowed; +} input[type="range"].lt-range::-webkit-slider-thumb { -webkit-appearance: none; width: 14px; height: 14px; @@ -2586,6 +2720,7 @@ input[type="range"].lt-range::-webkit-slider-thumb { transition: transform 0.15s; } input[type="range"].lt-range::-webkit-slider-thumb:hover { transform: scale(1.3); } +input[type="range"].lt-range:focus-visible::-webkit-slider-thumb { transform: scale(1.3); box-shadow: 0 0 0 3px var(--bg-primary), 0 0 0 5px var(--accent-cyan); } input[type="range"].lt-range::-moz-range-thumb { width: 14px; height: 14px; background: var(--accent-orange); @@ -2638,6 +2773,8 @@ input[type="range"].lt-range::-moz-range-thumb { .lt-file-item-name { color: var(--text-secondary); } .lt-file-item-size { color: var(--text-dim); } .lt-file-item-remove { background: none; border: none; color: var(--accent-red); cursor: pointer; padding: 0; font-size: 0.9rem; } +.lt-file-item-remove:hover { opacity: 0.75; text-shadow: var(--glow-red); } +.lt-file-item-remove:focus-visible { outline: 2px solid var(--accent-cyan); outline-offset: 2px; border-radius: 2px; } /* ---------------------------------------------------------------- @@ -2681,6 +2818,7 @@ input[type="range"].lt-range::-moz-range-thumb { font-size: 0.9rem; caret-color: var(--accent-orange); } +.lt-cmd-input-wrap:focus-within { border-bottom-color: var(--accent-cyan); } .lt-cmd-results { max-height: 320px; overflow-y: auto; } .lt-cmd-group-label { padding: var(--space-xs) var(--space-md); @@ -2788,7 +2926,7 @@ input[type="range"].lt-range::-moz-range-thumb { .tok-kw { color: var(--accent-cyan); } .tok-str { color: var(--accent-green); } .tok-num { color: var(--accent-orange); } -.tok-cmt { color: #5c8c6a; font-style: italic; } +.tok-cmt { color: var(--color-tok-cmt); font-style: italic; } .tok-fn { color: var(--accent-purple); } @@ -2827,6 +2965,7 @@ input[type="range"].lt-range::-moz-range-thumb { line-height: 1; } .lt-tag-remove:hover { opacity: 1; } +.lt-tag-remove:focus-visible { outline: 2px solid var(--accent-cyan); outline-offset: 1px; border-radius: 2px; opacity: 1; } /* ---------------------------------------------------------------- @@ -3113,7 +3252,8 @@ input[type="range"].lt-range::-moz-range-thumb { .lt-gauge svg { overflow: visible; } .lt-gauge-track { fill: none; stroke: var(--bg-tertiary); stroke-width: 8; } .lt-gauge-fill { fill: none; stroke: var(--accent-orange); stroke-width: 8; stroke-linecap: butt; - transition: stroke-dashoffset 0.6s cubic-bezier(0.4,0,0.2,1); } + transition: stroke-dashoffset 0.6s cubic-bezier(0.4,0,0.2,1); + will-change: stroke-dashoffset; } .lt-gauge-label { position: absolute; bottom: 0; left: 50%; @@ -3138,6 +3278,7 @@ input[type="range"].lt-range::-moz-range-thumb { border-top-color: var(--accent-orange); border-radius: 50%; animation: lt-spin 0.7s linear infinite; + will-change: transform; } .lt-spinner--cyan { border-top-color: var(--accent-cyan); } .lt-spinner--green { border-top-color: var(--accent-green); } @@ -3247,7 +3388,6 @@ input[type="range"].lt-range::-moz-range-thumb { .lt-border-red { border-color: var(--accent-red) !important; } /* Display */ -.lt-hidden { display: none !important; } .lt-visible { display: block !important; } .lt-flex { display: flex; } .lt-grid { display: grid; } @@ -3404,6 +3544,9 @@ html[data-theme="light"] { --box-glow-red: 0 0 0 2px rgba(181,0,31,0.22), 0 2px 8px rgba(181,0,31,0.12); --box-glow-amber: 0 0 0 2px rgba(138,90,0,0.22), 0 2px 8px rgba(138,90,0,0.12); + /* — Syntax highlight — */ + --color-tok-cmt: #2e6540; + color-scheme: light; } @@ -3504,13 +3647,16 @@ html[data-theme="light"] .lt-table-wrap { border-color: var(--border-color); /* — Badges & status — */ html[data-theme="light"] .lt-badge { background: var(--bg-tertiary); color: var(--text-secondary); } -html[data-theme="light"] .lt-badge-open { background: rgba(0,109,53,0.12); color: #006d35; } -html[data-theme="light"] .lt-badge-closed { background: rgba(90,110,150,0.12); color: #5a6e8c; } -html[data-theme="light"] .lt-badge-p1 { background: rgba(181,0,31,0.12); color: #b5001f; } -html[data-theme="light"] .lt-badge-p2 { background: rgba(196,78,0,0.12); color: #c44e00; } -html[data-theme="light"] .lt-badge-p3 { background: rgba(138,90,0,0.12); color: #8a5a00; } -html[data-theme="light"] .lt-badge-p4 { background: rgba(50,80,130,0.10); color: #2d3d56; } -html[data-theme="light"] .lt-badge-admin { background: rgba(107,47,184,0.12); color: #6b2fb8; } +html[data-theme="light"] .lt-badge-open { background: rgba(0,109,53,0.12); color: #006d35; } +html[data-theme="light"] .lt-badge-closed { background: rgba(90,110,150,0.12); color: #5a6e8c; } +html[data-theme="light"] .lt-badge-in-progress, +html[data-theme="light"] .lt-badge-progress { background: rgba(138,90,0,0.12); color: #8a5a00; text-shadow: none; } +html[data-theme="light"] .lt-badge-pending { background: rgba(107,47,184,0.10); color: #7c22cc; } +html[data-theme="light"] .lt-badge-p1 { background: rgba(181,0,31,0.12); color: #b5001f; text-shadow: none; } +html[data-theme="light"] .lt-badge-p2 { background: rgba(196,78,0,0.12); color: #c44e00; } +html[data-theme="light"] .lt-badge-p3 { background: rgba(138,90,0,0.12); color: #8a5a00; } +html[data-theme="light"] .lt-badge-p4 { background: rgba(50,80,130,0.10); color: #2d3d56; } +html[data-theme="light"] .lt-badge-admin { background: rgba(107,47,184,0.12); color: #6b2fb8; } /* — Toast — */ html[data-theme="light"] .lt-toast { @@ -3614,8 +3760,8 @@ html[data-theme="light"] .lt-divider-label { color: var(--text-dim); } html[data-theme="light"] .lt-tag { background: var(--bg-tertiary); border-color: var(--border-color); color: var(--text-secondary); } /* — Tooltips — */ -html[data-theme="light"] [data-tooltip]::before { background: #1a2035; color: #fff; } -html[data-theme="light"] [data-tooltip]::after { border-top-color: #1a2035; } +html[data-theme="light"] [data-tooltip]::before { background: var(--bg-terminal); color: var(--text-primary); } +html[data-theme="light"] [data-tooltip]::after { border-top-color: var(--bg-terminal); } /* — Pagination — */ html[data-theme="light"] .lt-page-btn { background: var(--bg-card); border-color: var(--border-color); color: var(--text-secondary); } @@ -3766,6 +3912,7 @@ html[data-theme="light"] ::-webkit-scrollbar-thumb:hover { background: var(--acc animation: lt-shimmer 1.6s ease-in-out infinite; border-radius: 2px; display: block; + will-change: opacity; } @keyframes lt-shimmer { 0% { background-position: 200% 0; } @@ -3941,7 +4088,8 @@ html[data-theme="light"] ::-webkit-scrollbar-thumb:hover { background: var(--acc border-radius: 2px; transition: var(--transition-fast); } -.lt-drawer-right-close:hover { color: var(--accent-red); border-color: var(--accent-red); } +.lt-drawer-right-close:hover { color: var(--accent-red); border-color: var(--accent-red); } +.lt-drawer-right-close:active { color: var(--accent-red); opacity: 0.7; } .lt-drawer-right-close:focus-visible { outline: 1px solid var(--accent-cyan); outline-offset: 2px; } .lt-drawer-right-body { flex: 1; @@ -4056,6 +4204,7 @@ html[data-theme="light"] ::-webkit-scrollbar-thumb:hover { background: var(--acc display: flex; align-items: center; } .lt-combobox-tag-remove:hover { color: var(--accent-red); } +.lt-combobox-tag-remove:focus-visible { outline: 2px solid var(--accent-cyan); outline-offset: 1px; border-radius: 2px; } /* Dropdown list */ .lt-combobox-dropdown { position: absolute; @@ -4908,7 +5057,7 @@ body.lt-is-offline .lt-main { margin-top: 2rem; transition: margin-top 0.25s eas background: var(--bg-secondary); border: 1px solid var(--border-color); clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%); - z-index: 10020; + z-index: var(--z-panel); box-shadow: 0 8px 32px rgba(0,0,0,0.5); transform-origin: top right; transform: scale(0.95); @@ -4946,7 +5095,9 @@ body.lt-is-offline .lt-main { margin-top: 2rem; transition: margin-top 0.25s eas text-transform: uppercase; letter-spacing: 0.04em; } -.lt-notif-panel-clear:hover { text-decoration: underline; } +.lt-notif-panel-clear:hover { text-decoration: underline; } +.lt-notif-panel-clear:active { opacity: 0.7; } +.lt-notif-panel-clear:focus-visible { outline: 2px solid var(--accent-cyan); outline-offset: 2px; border-radius: 2px; } .lt-notif-panel-list { max-height: min(280px, calc(80vh - 110px)); overflow-y: auto; } @@ -5015,7 +5166,7 @@ body.lt-is-offline .lt-main { margin-top: 2rem; transition: margin-top 0.25s eas background: var(--bg-secondary); border: 1px solid var(--border-color); clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 0 100%); - z-index: 10020; + z-index: var(--z-panel); box-shadow: 0 8px 24px rgba(0,0,0,0.4); transform-origin: top left; transform: scale(0.95); @@ -5250,3 +5401,24 @@ body.lt-is-offline .lt-main { margin-top: 2rem; transition: margin-top 0.25s eas .lt-stats-grid { grid-template-columns: repeat(8, 1fr); max-width: 100%; } .lt-modal { max-width: 800px; } } + +/* ---------------------------------------------------------------- + 79. FOOTER + ---------------------------------------------------------------- */ +.lt-footer { + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: var(--space-sm); + padding: var(--space-md) var(--space-lg); + border-top: 1px solid var(--border-dim); + margin-top: auto; + background: var(--bg-secondary); + color: var(--text-muted); + font-size: 0.7rem; + font-family: var(--font-mono); +} +@media (max-width: 479px) { + .lt-footer { flex-direction: column; align-items: flex-start; gap: 0.25rem; } +} diff --git a/base.html b/base.html index 7a82f0f..723b990 100644 --- a/base.html +++ b/base.html @@ -1,6 +1,6 @@ -