- - - - - - - +
diff --git a/public/assets/css/app.css b/public/assets/css/app.css index 4bae690..5e2cfd2 100644 --- a/public/assets/css/app.css +++ b/public/assets/css/app.css @@ -1,516 +1,23 @@ -@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;600;700&family=IBM+Plex+Mono:wght@400;600&display=swap'); - -:root { - --bg: #f5f7fb; - --panel: #ffffff; - --panel-2: #eef2ff; - --text: #111827; - --muted: #5b6475; - --accent: #ff5a3d; - --accent-2: #00b3a4; - --line: #d7dceb; - --shadow: 0 18px 36px rgba(20, 32, 64, 0.15); -} - -* { box-sizing: border-box; } -html, body { height: 100%; } -body { - margin: 0; - font-family: "Space Grotesk", "Segoe UI", sans-serif; - background: radial-gradient(1200px 500px at 10% -10%, rgba(255, 90, 61, 0.15), transparent 60%), - radial-gradient(900px 500px at 90% 10%, rgba(0, 179, 164, 0.12), transparent 55%), - var(--bg); - color: var(--text); - min-height: 100vh; - display: flex; - flex-direction: column; -} - -.bg-orb { - position: fixed; - width: 420px; - height: 420px; - border-radius: 50%; - filter: blur(90px); - opacity: 0.35; - z-index: 0; - pointer-events: none; -} -.orb-a { top: -140px; left: -100px; background: #ff5a3d; } -.orb-b { bottom: -180px; right: -120px; background: #00b3a4; } - -.card { - background: var(--panel); - border: 1px solid var(--line); - border-radius: 18px; - box-shadow: var(--shadow); -} - -.main-content > .card { - border: none; - box-shadow: none; - background: transparent; -} - -.site-header { - position: sticky; - top: 0; - z-index: 20; - margin: 18px 24px 8px; - padding: 10px 16px; - display: flex; - align-items: center; - justify-content: space-between; - gap: 16px; -} - -.logo-wrap { display: flex; align-items: center; } -.site-logo { height: 80px; width: auto; filter: drop-shadow(0 6px 12px rgba(0,0,0,0.12)); } - -.header-nav { - display: flex; - align-items: center; - gap: 12px; -} - -.nav-link { - color: var(--text); - text-decoration: none; - padding: 8px 14px; - border-radius: 10px; - border: 1px solid transparent; - font-weight: 600; - transition: all 180ms ease; -} -.nav-link:hover { - border-color: var(--line); - background: var(--panel-2); -} - -.dropdown { position: relative; display: inline-flex; } -.dropdown-toggle { background: transparent; } -.dropdown-menu { - position: absolute; - top: 100%; - right: 0; - min-width: 220px; - background: var(--panel); - border: 1px solid var(--line); - border-radius: 12px; - box-shadow: var(--shadow); - padding: 8px; - display: none; - z-index: 30; - margin-top: 6px; -} -.dropdown-menu::before { - content: ""; - position: absolute; - top: -8px; - left: 0; - right: 0; - height: 8px; -} -.dropdown-menu-right { right: 0; left: auto; } -.dropdown:hover .dropdown-menu, -.dropdown:focus-within .dropdown-menu { display: block; } -.dropdown-item { - display: block; - padding: 8px 10px; - border-radius: 10px; - color: var(--text); - text-decoration: none; - font-weight: 600; -} -.dropdown-item:hover { background: var(--panel-2); } -.dropdown-divider { height: 1px; background: var(--line); margin: 6px 4px; } -.dropdown-header { padding: 6px 10px; font-size: 0.85rem; color: var(--muted); } - -.avatar-btn { background: transparent; border: none; padding: 0; cursor: pointer; } -.avatar { - width: 34px; - height: 34px; - border-radius: 50%; - background: var(--accent); - color: #ffffff; - display: inline-flex; - align-items: center; - justify-content: center; - font-weight: 700; -} - -.module-subnav { - margin: 0 24px 6px; - padding: 8px 12px; - display: flex; - gap: 10px; - flex-wrap: wrap; - background-color: var(--panel) !important; - background: var(--panel) !important; - background-image: none !important; - opacity: 1 !important; - backdrop-filter: none !important; - mix-blend-mode: normal; - border: 1px solid var(--line); - box-shadow: var(--shadow); - border-radius: 18px; -} -.module-subnav.card { background-color: var(--panel); background-image: none; } - -.nav-dropdown { - position: relative; - display: inline-flex; -} -.nav-link-button { - border: 1px solid transparent; - background: transparent; - cursor: pointer; -} -.nav-dropdown-menu { - position: absolute; - top: 100%; - left: 0; - min-width: 180px; - background: var(--panel); - border: 1px solid var(--line); - border-radius: 12px; - box-shadow: var(--shadow); - padding: 6px; - display: none; - z-index: 20; - margin-top: 6px; -} -.nav-dropdown-menu::before { - content: ""; - position: absolute; - top: -8px; - left: 0; - right: 0; - height: 8px; -} -.nav-dropdown:hover .nav-dropdown-menu, -.nav-dropdown:focus-within .nav-dropdown-menu { - display: flex; - flex-direction: column; - gap: 4px; -} - -.layout-body { - display: grid; - grid-template-columns: 1fr; - gap: 16px; - padding: 6px 24px 24px; - transition: grid-template-columns 260ms ease; - position: relative; -} -.layout-body.sidebar-open { - grid-template-columns: 260px 1fr; -} - -.layout-body.no-sidebar { - grid-template-columns: 1fr; - gap: 20px; -} - -.main-content { - width: 100%; -} - -.sidebar, -.sidebar-toggle, -.sidebar-fab { - display: none !important; -} - -.console-fab { - position: fixed; - bottom: 18px; - left: 18px; - width: 52px; - height: 52px; - border-radius: 999px; - background: #0b0f17; - color: #ffffff; - border: 1px solid rgba(255,255,255,0.08); - box-shadow: var(--shadow); - display: none; - align-items: center; - justify-content: center; - cursor: pointer; - z-index: 50; -} -.console-fab.is-visible { display: inline-flex; } -.console-fab span { font-size: 1.2rem; } - -.console-modal { - position: fixed; - inset: 0; - background: rgba(10, 14, 24, 0.55); - display: none; - align-items: center; - justify-content: center; - padding: 24px; - z-index: 45; -} -.console-modal.is-open { display: flex; } -.console-modal-card { - width: min(1200px, 96vw); - max-height: 92vh; - overflow: auto; - background: var(--panel); - border: 1px solid var(--line); - border-radius: 16px; - box-shadow: var(--shadow); - padding: 16px; -} -.console-modal-header { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; -} - -.sidebar { - padding: 16px; - display: flex; - flex-direction: column; - gap: 12px; - position: sticky; - top: 120px; - height: fit-content; - transform: translateX(-12px); - opacity: 0; - pointer-events: none; - transition: transform 260ms ease, opacity 260ms ease; -} -.layout-body.sidebar-collapsed .sidebar { - position: absolute; - top: 0; - left: 0; - width: 240px; - max-height: 0; - padding: 0; - margin: 0; - border: 0; - box-shadow: none; - overflow: hidden; -} -.layout-body.sidebar-open .sidebar { - transform: translateX(0); - opacity: 1; - pointer-events: auto; -} - -.sidebar-toggle { - align-self: flex-start; - background: var(--panel-2); - border: 1px solid var(--line); - border-radius: 10px; - padding: 6px 10px; - cursor: pointer; - font-weight: 700; -} - -.sidebar-items .nav-link { display: block; } - -.sidebar-fab { - position: fixed; - left: 24px; - bottom: 24px; - width: 52px; - height: 52px; - border-radius: 50%; - background: var(--panel); - border: 1px solid var(--line); - box-shadow: var(--shadow); - font-weight: 800; - z-index: 60; -} - -.main-content { - min-height: 60vh; - background: var(--panel); - background-image: none; - border-radius: 18px; - box-shadow: var(--shadow); - padding: 16px; - position: relative; - z-index: 1; -} - -.main-content > .card { - background: transparent; - border: none; - box-shadow: none; - padding: 0; - border-radius: 0; -} - -.site-footer { - margin: 0 24px 18px; - padding: 10px 16px; - color: var(--muted); - display: flex; - justify-content: space-between; - font-size: 0.85rem; - margin-top: auto; -} - -.debug-fab { - position: fixed; - right: 24px; - bottom: 24px; - width: 52px; - height: 52px; - border-radius: 50%; - background: var(--accent); - color: #ffffff; - display: inline-flex; - align-items: center; - justify-content: center; - text-decoration: none; - font-size: 22px; - box-shadow: 0 16px 32px rgba(255, 90, 61, 0.28); - z-index: 50; - border: none; - cursor: pointer; -} - -.debug-modal { - position: fixed; - inset: 0; - display: none; - z-index: 80; -} -.debug-modal.is-open { display: block; } -.debug-modal__backdrop { - position: absolute; - inset: 0; - background: rgba(10, 12, 20, 0.35); -} -.debug-modal__panel { - position: relative; - max-width: 980px; - width: calc(100% - 40px); - margin: 60px auto; - padding: 16px; -} -.debug-modal__header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 12px; -} -.debug-modal__close { - background: transparent; - border: none; - font-size: 20px; - cursor: pointer; -} -.debug-modal__body { - display: grid; - grid-template-columns: 220px 1fr; - gap: 16px; -} -.debug-modal__list ul { - list-style: none; - padding: 0; - margin: 8px 0 0; - display: grid; - gap: 6px; -} -.debug-modal__list a { - text-decoration: none; - color: var(--text); - padding: 6px 8px; - border-radius: 8px; - display: block; -} -.debug-modal__list a:hover { background: var(--panel-2); } -.debug-modal__content pre { - background: var(--panel-2); - padding: 10px; - border-radius: 8px; - max-height: 520px; - overflow: auto; - white-space: pre-wrap; -} -@media (max-width: 800px) { - .debug-modal__body { grid-template-columns: 1fr; } -} - -.muted { color: var(--muted); } -.pill { - display: inline-flex; - align-items: center; - gap: 6px; - padding: 4px 10px; - border-radius: 999px; - border: 1px solid var(--line); - color: var(--muted); - background: rgba(255,255,255,0.6); - font-size: 0.85rem; -} - -.card input, -.card textarea, -.card select { - background: #ffffff; - border: 1px solid var(--line); - color: var(--text); - padding: 10px 12px; - border-radius: 10px; - font-family: inherit; -} - -.cta-button { - background: linear-gradient(120deg, var(--accent), #ff9f45); - border: none; - color: #ffffff; - font-weight: 700; - padding: 10px 18px; - border-radius: 12px; - cursor: pointer; - box-shadow: 0 14px 30px rgba(255, 90, 61, 0.35); -} - -/* Minimal utility support (tables + spacing) */ -.px-6 { padding-left: 1.5rem; padding-right: 1.5rem; } -.py-3 { padding-top: 0.75rem; padding-bottom: 0.75rem; } -.py-4 { padding-top: 1rem; padding-bottom: 1rem; } -.text-left { text-align: left; } -.text-sm { font-size: 0.9rem; } -.text-xs { font-size: 0.75rem; } -.uppercase { text-transform: uppercase; letter-spacing: 0.08em; } -.font-medium { font-weight: 600; } -.font-mono { font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace; } -.bg-gray-900 { background: var(--panel-2); } -.bg-gray-800 { background: var(--panel); } -.divide-y > * + * { border-top: 1px solid var(--line); } -.border-gray-700 { border-color: var(--line); } - -@media (max-width: 900px) { - .site-header { margin: 12px; } - .layout-body { padding: 6px 12px 12px; } - .module-subnav { margin: 0 12px 6px; } - .site-footer { margin: 0 12px 12px; } - .header-nav { flex-wrap: wrap; justify-content: flex-end; } -} - :root { + --bg: #07121a; --surface: rgba(255, 255, 255, 0.9); --surface-strong: #ffffff; - --accent-pink: #ed1671; + --text: #10212b; + --muted: #66737b; + --accent: #ed1671; --accent-cyan: #06a9c8; --accent-orange: #f6aa21; --accent-green: #8bc53f; - --brand-accent: var(--accent-pink); + --brand-accent: var(--accent); --brand-accent-2: var(--accent-cyan); --brand-accent-3: var(--accent-orange); + --accent-soft: rgba(237, 22, 113, 0.12); + --line: rgba(16, 33, 43, 0.12); + --shadow: 0 18px 45px rgba(1, 22, 32, 0.14); } :root[data-accent="pink"] { - --brand-accent: var(--accent-pink); + --brand-accent: var(--accent); --brand-accent-2: var(--accent-orange); --brand-accent-3: var(--accent-cyan); } @@ -518,12 +25,12 @@ body { :root[data-accent="cyan"] { --brand-accent: var(--accent-cyan); --brand-accent-2: var(--accent-green); - --brand-accent-3: var(--accent-pink); + --brand-accent-3: var(--accent); } :root[data-accent="orange"] { --brand-accent: var(--accent-orange); - --brand-accent-2: var(--accent-pink); + --brand-accent-2: var(--accent); --brand-accent-3: var(--accent-cyan); } @@ -533,38 +40,24 @@ body { --brand-accent-3: var(--accent-orange); } -:root[data-theme="day"] { - --bg: #f7fbfb; - --panel: rgba(255, 255, 255, 0.92); - --panel-2: #f1fbf7; - --surface: rgba(255, 255, 255, 0.9); - --surface-strong: #ffffff; - --text: #10212b; - --muted: #66737b; - --accent: var(--brand-accent); - --accent-2: var(--brand-accent-2); - --line: rgba(16, 33, 43, 0.12); -} - :root[data-theme="night"] { - --bg: #07121a; - --panel: rgba(8, 18, 28, 0.9); - --panel-2: rgba(18, 33, 48, 0.92); --surface: rgba(8, 18, 28, 0.88); --surface-strong: #101d2a; --text: #eff8fb; --muted: #a6b8c2; - --accent: var(--brand-accent); - --accent-2: var(--brand-accent-2); --line: rgba(255, 255, 255, 0.12); --shadow: 0 22px 60px rgba(0, 0, 0, 0.34); } +* { + box-sizing: border-box; +} + html { min-height: 100%; background: - radial-gradient(circle at top left, color-mix(in srgb, var(--brand-accent-2) 20%, transparent), transparent 26%), - radial-gradient(circle at top right, color-mix(in srgb, var(--brand-accent) 18%, transparent), transparent 24%), + radial-gradient(circle at top left, rgba(6, 169, 200, 0.2), transparent 26%), + radial-gradient(circle at top right, rgba(237, 22, 113, 0.18), transparent 24%), linear-gradient(135deg, #f7fbfb 0%, #eef7f5 52%, #fff4df 100%); } @@ -576,37 +69,30 @@ html { } body { + margin: 0; + min-height: 100vh; + color: var(--text); + font-family: "Space Grotesk", "Trebuchet MS", sans-serif; background: - radial-gradient(circle at 12% 20%, color-mix(in srgb, var(--accent-green) 16%, transparent), transparent 24%), - radial-gradient(circle at 90% 6%, color-mix(in srgb, var(--accent-orange) 16%, transparent), transparent 20%), - var(--bg); + radial-gradient(circle at 12% 20%, rgba(139, 197, 63, 0.16), transparent 24%), + radial-gradient(circle at 90% 6%, rgba(246, 170, 33, 0.16), transparent 20%); } -.site-header { - padding: 8px 14px; +:root[data-theme="night"] body { + background: + radial-gradient(circle at 12% 20%, color-mix(in srgb, var(--brand-accent) 16%, transparent), transparent 24%), + radial-gradient(circle at 90% 6%, color-mix(in srgb, var(--brand-accent-3) 14%, transparent), transparent 20%); } -.site-logo { - height: 46px; +a { + color: inherit; + text-decoration: none; } -.main-content { +.main-shell { width: min(80vw, 1680px); margin: 0 auto; - background: transparent; - box-shadow: none; - padding: 0; -} - -.main-content > .card, -.home-hero, -.module-row, -.empty-state, -.module-host-card { - border: 1px solid var(--line); - background: var(--surface); - box-shadow: 0 12px 30px rgba(1, 22, 32, 0.08); - backdrop-filter: blur(8px); + padding: 22px 0 48px; } .home-hero { @@ -617,7 +103,30 @@ body { gap: 18px; margin-bottom: 16px; padding: 16px 18px; + border: 1px solid var(--line); border-radius: 20px; + background: + linear-gradient(135deg, rgba(255, 255, 255, 0.94), rgba(245, 252, 251, 0.88)), + linear-gradient(90deg, color-mix(in srgb, var(--brand-accent) 14%, transparent), color-mix(in srgb, var(--brand-accent-2) 14%, transparent)); + box-shadow: var(--shadow); +} + +:root[data-theme="night"] .home-hero { + background: + linear-gradient(135deg, rgba(8, 18, 28, 0.94), rgba(15, 29, 42, 0.86)), + linear-gradient(90deg, color-mix(in srgb, var(--brand-accent) 18%, transparent), color-mix(in srgb, var(--brand-accent-2) 16%, transparent)); +} + +.home-hero::after { + content: ""; + position: absolute; + inset: auto -70px -86px auto; + width: 190px; + height: 190px; + border-radius: 50%; + background: + radial-gradient(circle, color-mix(in srgb, var(--brand-accent) 26%, transparent), transparent 64%), + radial-gradient(circle at 20% 20%, color-mix(in srgb, var(--brand-accent-2) 22%, transparent), transparent 58%); } .brand-mark { @@ -633,6 +142,10 @@ body { box-shadow: inset 0 0 0 1px rgba(16, 33, 43, 0.08), 0 12px 30px rgba(6, 169, 200, 0.12); } +:root[data-theme="night"] .brand-mark { + background: rgba(255, 255, 255, 0.96); +} + .brand-mark img { display: block; width: 62px; @@ -646,26 +159,25 @@ body { min-width: 0; } -.eyebrow, -.module-kicker { +.eyebrow { + display: inline-flex; + align-items: center; + gap: 8px; + margin-bottom: 6px; + padding: 4px 9px; + border-radius: 999px; + background: color-mix(in srgb, var(--brand-accent) 12%, transparent); color: var(--brand-accent); - font-size: 0.74rem; + font-size: 0.72rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; } -.eyebrow { - display: inline-flex; - margin-bottom: 6px; - padding: 4px 9px; - border-radius: 999px; - background: color-mix(in srgb, var(--brand-accent) 12%, transparent); -} - .home-hero h1, .section-title { margin: 0; + font-family: "Space Grotesk", "Trebuchet MS", sans-serif; font-weight: 700; letter-spacing: -0.03em; } @@ -675,12 +187,55 @@ body { line-height: 1; } -.home-hero p, -.section-head p, -.module-desc { +.home-hero p { + margin: 7px 0 0; + font-size: 0.98rem; + line-height: 1.45; color: var(--muted); } +.stats { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); + gap: 16px; + margin: 24px 0 0; +} + +.stat-card, +.module-card, +.module-row, +.empty-state { + border: 1px solid var(--line); + border-radius: 18px; + background: var(--surface); + box-shadow: 0 12px 30px rgba(1, 22, 32, 0.08); + backdrop-filter: blur(8px); +} + +:root[data-theme="night"] .module-row:hover, +:root[data-theme="night"] .module-row:focus-visible { + background: var(--surface-strong); +} + +.stat-card { + padding: 18px 20px; +} + +.stat-label { + display: block; + color: var(--muted); + font-size: 0.88rem; + text-transform: uppercase; + letter-spacing: 0.08em; +} + +.stat-value { + display: block; + margin-top: 10px; + font-size: 2rem; + font-weight: 700; +} + .section-head { display: flex; align-items: end; @@ -689,6 +244,19 @@ body { margin: 8px 0 12px; } +.section-head p { + margin: 4px 0 0; + color: var(--muted); +} + +.section-title { + font-size: 1.15rem; +} + +.module-list-section { + margin-top: 0; +} + .module-list { display: grid; gap: 10px; @@ -700,7 +268,6 @@ body { align-items: center; gap: 14px; padding: 14px; - border-radius: 18px; transition: transform 160ms ease, box-shadow 160ms ease, border-color 160ms ease, background 160ms ease; } @@ -708,7 +275,8 @@ body { .module-row:focus-visible { transform: translateY(-2px); border-color: color-mix(in srgb, var(--brand-accent) 36%, transparent); - background: var(--surface-strong); + background: #ffffff; + box-shadow: 0 16px 35px rgba(1, 22, 32, 0.13); } .module-row__icon { @@ -719,7 +287,9 @@ body { border-radius: 14px; color: #ffffff; font-weight: 800; - background: linear-gradient(135deg, var(--brand-accent-2), var(--brand-accent)), var(--brand-accent); + background: + linear-gradient(135deg, var(--brand-accent-2), var(--brand-accent)), + var(--brand-accent); } .module-row__content { @@ -728,10 +298,10 @@ body { min-width: 0; } -.module-row__action, -.auth-pill { +.module-row__action { display: inline-flex; align-items: center; + gap: 8px; padding: 9px 12px; border-radius: 999px; color: #ffffff; @@ -742,7 +312,60 @@ body { .module-row__action::after { content: "->"; - margin-left: 8px; +} + +.module-card { + position: relative; + display: flex; + flex-direction: column; + gap: 14px; + padding: 22px; + transition: transform 180ms ease, box-shadow 180ms ease, border-color 180ms ease; +} + +.module-host-card { + position: relative; + overflow: hidden; + border: 1px solid var(--line); + border-radius: 18px; + background: var(--surface); + box-shadow: 0 12px 30px rgba(1, 22, 32, 0.08); + backdrop-filter: blur(8px); +} + +.module-card:hover, +.module-card:focus-within { + transform: translateY(-3px); + border-color: color-mix(in srgb, var(--brand-accent) 38%, transparent); + box-shadow: 0 20px 36px rgba(1, 22, 32, 0.14); +} + +.module-kicker { + color: var(--brand-accent); + font-size: 0.74rem; + font-weight: 800; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.module-title { + margin: 0; + font-size: 1.12rem; +} + +.module-desc { + margin: 0; + color: var(--muted); + line-height: 1.45; +} + +.module-link { + display: inline-flex; + align-items: center; + gap: 10px; + margin-top: auto; + color: var(--brand-accent); + font-weight: 700; } .theme-switcher { @@ -754,6 +377,20 @@ body { margin-left: auto; } +.auth-pill { + align-self: end; + display: inline-flex; + align-items: center; + min-height: 36px; + padding: 8px 13px; + border: 1px solid var(--line); + border-radius: 999px; + color: #ffffff; + font-size: 0.86rem; + font-weight: 800; + background: linear-gradient(135deg, var(--brand-accent), var(--brand-accent-2)); +} + .theme-switcher label { display: grid; gap: 4px; @@ -764,34 +401,27 @@ body { text-transform: uppercase; } -.theme-switcher select, -.card select { - background: var(--surface-strong); - color: var(--text); -} - .theme-switcher select { min-width: 118px; border: 1px solid var(--line); border-radius: 999px; padding: 8px 30px 8px 11px; + color: var(--text); + background: var(--surface-strong); font: inherit; font-size: 0.86rem; letter-spacing: 0; text-transform: none; } -.empty-state { - padding: 28px; - border-radius: 18px; - color: var(--muted); - line-height: 1.7; +.module-link::after { + content: "->"; } -.module-host-card { - position: relative; - overflow: hidden; - border-radius: 18px; +.empty-state { + padding: 28px; + color: var(--muted); + line-height: 1.7; } .reveal { @@ -800,6 +430,18 @@ body { animation: rise 480ms ease forwards; } +.reveal:nth-child(2) { + animation-delay: 90ms; +} + +.reveal:nth-child(3) { + animation-delay: 160ms; +} + +.reveal:nth-child(4) { + animation-delay: 230ms; +} + @keyframes rise { to { opacity: 1; @@ -808,34 +450,17 @@ body { } @media (max-width: 720px) { - .site-header { - align-items: flex-start; - flex-direction: column; - margin: 10px; - } - - .header-nav { - width: 100%; - justify-content: flex-start; - } - - .layout-body, - .module-subnav { - padding-left: 0; - padding-right: 0; - margin-left: 0; - margin-right: 0; - } - - .main-content { + .main-shell { width: min(100% - 20px, 1680px); + padding-top: 12px; } - .main-content:has(#mining-checker-app) { + .main-shell:has(#mining-checker-app) { width: 100%; + padding-top: 0; } - .module-host-card:has(#mining-checker-app) { + .module-host-card { border-left: 0; border-right: 0; border-radius: 0; @@ -879,3 +504,90 @@ body { flex-direction: column; } } + +.card { + border: 1px solid var(--line); + border-radius: 18px; + background: var(--surface); + box-shadow: 0 12px 30px rgba(1, 22, 32, 0.08); + backdrop-filter: blur(8px); + padding: 18px; +} + +.card + .card { + margin-top: 14px; +} + +.muted { + color: var(--muted); +} + +.pill { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 4px 10px; + border-radius: 999px; + border: 1px solid var(--line); + color: var(--brand-accent); + background: color-mix(in srgb, var(--brand-accent) 10%, transparent); + font-size: 0.78rem; + font-weight: 800; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.nav-link { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + color: var(--text); + text-decoration: none; + padding: 8px 14px; + border-radius: 999px; + border: 1px solid var(--line); + font-weight: 800; + background: var(--surface); + transition: border-color 160ms ease, background 160ms ease, transform 160ms ease; +} + +.nav-link:hover, +.nav-link:focus-visible { + transform: translateY(-1px); + border-color: color-mix(in srgb, var(--brand-accent) 36%, transparent); + background: var(--surface-strong); +} + +.cta-button { + border: 0; + color: #ffffff; + font-weight: 800; + padding: 10px 18px; + border-radius: 999px; + cursor: pointer; + background: linear-gradient(135deg, var(--brand-accent), var(--brand-accent-3)); + box-shadow: 0 14px 30px color-mix(in srgb, var(--brand-accent) 24%, transparent); +} + +.card input, +.card textarea, +.card select { + width: 100%; + border: 1px solid var(--line); + color: var(--text); + background: var(--surface-strong); + padding: 10px 12px; + border-radius: 12px; + font: inherit; +} + +.card input[type="checkbox"] { + width: auto; +} + +.grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 14px; +} diff --git a/public/assets/js/app.js b/public/assets/js/app.js index 23530b9..b86a46c 100755 --- a/public/assets/js/app.js +++ b/public/assets/js/app.js @@ -1,33 +1,3 @@ -(() => { - const layout = document.querySelector('.layout-body'); - if (!layout) return; - - const enabled = layout.dataset.sidebarEnabled === '1'; - const collapsible = layout.dataset.sidebarCollapsible === '1'; - const defaultState = layout.dataset.sidebarDefault || 'collapsed'; - - const toggles = document.querySelectorAll('[data-sidebar-toggle]'); - if (!enabled || !collapsible) { - toggles.forEach((t) => t.remove()); - return; - } - - const saved = localStorage.getItem('sidebar-state'); - const initial = saved || defaultState; - if (initial === 'open') { - layout.classList.add('sidebar-open'); - } else { - layout.classList.remove('sidebar-open'); - } - - toggles.forEach((toggle) => { - toggle.addEventListener('click', () => { - layout.classList.toggle('sidebar-open'); - localStorage.setItem('sidebar-state', layout.classList.contains('sidebar-open') ? 'open' : 'collapsed'); - }); - }); -})(); - document.documentElement.classList.add('js'); function readThemePreference(key, fallback) { @@ -76,101 +46,3 @@ if (themeAccentSelect) { for (const element of document.querySelectorAll('[data-reveal]')) { element.classList.add('reveal'); } - -(() => { - const openBtn = document.querySelector('[data-debug-open]'); - const modal = document.getElementById('debug-modal'); - if (!openBtn || !modal) return; - - const listEl = document.getElementById('debug-log-list'); - const contentEl = document.getElementById('debug-log-content'); - const closeEls = modal.querySelectorAll('[data-debug-close]'); - - const open = () => { - modal.classList.add('is-open'); - modal.setAttribute('aria-hidden', 'false'); - loadList(); - startRefresh(); - }; - const close = () => { - modal.classList.remove('is-open'); - modal.setAttribute('aria-hidden', 'true'); - if (refreshTimer) { - clearInterval(refreshTimer); - refreshTimer = null; - } - }; - - let activeFile = null; - let refreshTimer = null; - - const loadList = async () => { - try { - const res = await fetch('/debug?list=1', { cache: 'no-store' }); - if (!res.ok) { - listEl.innerHTML = `
  • Fehler: ${res.status}
  • `; - return; - } - const files = await res.json(); - listEl.innerHTML = ''; - files.forEach((f) => { - const a = document.createElement('a'); - a.href = '#'; - a.textContent = f; - a.addEventListener('click', (e) => { - e.preventDefault(); - loadFile(f); - }); - const li = document.createElement('li'); - li.appendChild(a); - listEl.appendChild(li); - }); - if (files.includes('oidc_login.log')) { - loadFile('oidc_login.log'); - } - } catch (e) { - listEl.innerHTML = '
  • Fehler beim Laden der Logs.
  • '; - } - }; - - const loadFile = async (name) => { - activeFile = name; - try { - const res = await fetch(`/debug?raw=1&file=${encodeURIComponent(name)}&tail=200`, { cache: 'no-store' }); - if (!res.ok) { - contentEl.textContent = `Fehler: ${res.status}`; - return; - } - const text = await res.text(); - contentEl.textContent = formatLog(text); - } catch (e) { - contentEl.textContent = 'Fehler beim Laden der Datei.'; - } - }; - - const formatLog = (text) => { - const lines = text.split(/\\r?\\n/).filter(Boolean); - const pretty = lines.map((line) => { - try { - const obj = JSON.parse(line); - return JSON.stringify(obj, null, 2); - } catch (e) { - return line; - } - }); - return pretty.join('\\n\\n'); - }; - - const startRefresh = () => { - if (refreshTimer) clearInterval(refreshTimer); - refreshTimer = setInterval(() => { - if (activeFile) loadFile(activeFile); - }, 3000); - }; - - openBtn.addEventListener('click', open); - closeEls.forEach((el) => el.addEventListener('click', close)); - if (modal.classList.contains('is-open')) { - startRefresh(); - } -})(); diff --git a/src/App/Assets.php b/src/App/Assets.php index 6bd655b..267ac3e 100755 --- a/src/App/Assets.php +++ b/src/App/Assets.php @@ -41,4 +41,9 @@ final class Assets public function styles(): array { return $this->styles; } public function headerScripts(): array { return $this->scriptsHeader; } public function footerScripts(): array { return $this->scriptsFooter; } + + public function versioned(string $path): string + { + return $path . '?v=' . rawurlencode($this->config->assetVersion); + } }