/* Sami Grotesk Custom Font Family */ @font-face { font-family: 'Sami Grotesk'; src: url('/assets/fonts/sami-grotesk/SamiGrotesk-Light.woff2') format('woff2'); font-weight: 300; font-style: normal; font-display: swap; } @font-face { font-family: 'Sami Grotesk'; src: url('/assets/fonts/sami-grotesk/SamiGrotesk-Regular.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; } @font-face { font-family: 'Sami Grotesk'; src: url('/assets/fonts/sami-grotesk/SamiGrotesk-Medium.woff2') format('woff2'); font-weight: 500; font-style: normal; font-display: swap; } @font-face { font-family: 'Sami Grotesk'; src: url('/assets/fonts/sami-grotesk/SamiGrotesk-Bold.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; } @font-face { font-family: 'Sami Grotesk'; src: url('/assets/fonts/sami-grotesk/SamiGrotesk-Black.woff2') format('woff2'); font-weight: 900; font-style: normal; font-display: swap; } /* Italic variants */ @font-face { font-family: 'Sami Grotesk'; src: url('/assets/fonts/sami-grotesk/SamiGrotesk-RegularItalic.woff2') format('woff2'); font-weight: 400; font-style: italic; font-display: swap; } @font-face { font-family: 'Sami Grotesk'; src: url('/assets/fonts/sami-grotesk/SamiGrotesk-MediumItalic.woff2') format('woff2'); font-weight: 500; font-style: italic; font-display: swap; } @font-face { font-family: 'Sami Grotesk'; src: url('/assets/fonts/sami-grotesk/SamiGrotesk-BoldItalic.woff2') format('woff2'); font-weight: 700; font-style: italic; font-display: swap; } /* Theme variables and transitions are in themes.css */ * { box-sizing: border-box } html, body { height: 100% } body { margin: 0; padding: 24px; background: radial-gradient(1200px 900px at 8% -12%, rgba(96, 128, 255, .18), transparent 60%), radial-gradient(1000px 700px at 110% -10%, rgba(150, 60, 255, .12), transparent 55%), radial-gradient(900px 650px at 50% 120%, rgba(30, 60, 160, .16), transparent 60%), var(--bg); color: var(--fg); font: 16px/1.5 'Sami Grotesk', 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, Roboto, "Helvetica Neue", Arial, sans-serif; } /* Per-theme body backgrounds are in themes.css */ /* Optional: faint watermark */ body::before { content: ""; position: fixed; inset: auto auto 6% 50%; translate: -50% 0; width: min(60vw, 900px); aspect-ratio: 3 / 1; background: url(/assets/dashcaddy-logo-dark.png) center/contain no-repeat; opacity: .06; filter: blur(.4px); pointer-events: none; z-index: 0; } .muted { color: var(--muted) } button { padding: .38rem .75rem; border-radius: 10px; border: 1px solid var(--border); background: transparent; color: var(--fg); cursor: pointer; font-size: .88rem; font-family: 'Sami Grotesk', 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, Roboto, "Helvetica Neue", Arial, sans-serif; transition: background-color .15s ease, border-color .15s ease, transform .12s ease, box-shadow .15s ease, backdrop-filter .15s ease; } /* (1) Glassy button hover effects */ button:hover { background: color-mix(in srgb, var(--accent) 20%, transparent); backdrop-filter: blur(4px) saturate(160%); box-shadow: 0 0 4px rgba(255, 255, 255, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.08); border-color: color-mix(in srgb, var(--accent) 40%, var(--border) 60%); } /* Per-theme button hover overrides are in themes.css */ button:active { transform: translateY(1px) } button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 30%, transparent); } /* ===== Top bar: logo and weather on top row, tools below ===== */ .bar { display: flex; flex-direction: column; gap: 8px; margin: 0 0 8px; padding-right: 8px; } .top-row { display: flex; align-items: flex-start; width: 100%; position: relative; } .brand-weather-group { display: flex; align-items: center; gap: 20px; } .reload-caddy-container { position: absolute; right: 0; top: 0; padding-top: 10px; display: flex; flex-direction: column; align-items: flex-end; gap: 6px; } .reload-caddy-main { display: flex; align-items: center; gap: 18px; } .dashboard-version { font-size: 0.78rem; color: var(--muted); line-height: 1; padding: 0 2px; user-select: text; background: transparent; border: none; cursor: pointer; transition: color 0.15s ease, opacity 0.15s ease; } .dashboard-version:hover { color: var(--fg); opacity: 0.9; } .version-info-modal-content { min-width: 420px; max-width: 620px; } .version-info-subtitle { font-size: 0.85rem; color: var(--muted); margin: 0 0 16px; } .version-info-status { font-size: 0.85rem; color: var(--muted); margin-bottom: 14px; } .version-info-grid { display: grid; gap: 10px; margin-bottom: 18px; } .version-info-row { display: flex; justify-content: space-between; gap: 18px; padding: 10px 12px; border-radius: 8px; background: var(--card-bg); border: 1px solid var(--border); } .version-info-label { font-weight: 600; color: var(--fg); } .version-info-value { color: var(--muted); text-align: right; word-break: break-word; } .version-info-history h4 { margin: 0 0 10px; } .version-history-entry { padding: 10px 12px; border-radius: 8px; background: var(--card-bg); border: 1px solid var(--border); margin-bottom: 8px; } .version-history-status { color: var(--muted); font-size: 0.82rem; margin-left: 6px; } .version-history-meta { font-size: 0.78rem; color: var(--muted); margin-top: 4px; } .license-status-topbar { display: flex; align-items: center; gap: 6px; padding: 7px 14px; border-radius: 6px; font-size: 0.82rem; font-weight: 600; cursor: pointer; transition: all 0.2s ease; white-space: nowrap; border: 1px solid transparent; } .license-status-topbar:hover { opacity: 0.85; } .license-status-topbar.premium { background: rgba(46, 204, 113, 0.12); color: var(--ok-fg); border-color: rgba(46, 204, 113, 0.25); } .license-status-topbar.free { background: rgba(149, 165, 166, 0.12); color: var(--muted); border-color: rgba(149, 165, 166, 0.25); } .license-status-topbar .license-topbar-time { font-weight: 400; font-size: 0.78rem; opacity: 0.85; margin-left: 2px; } .tools-row { display: flex; flex-direction: column; gap: 6px; margin-left: 0; } /* ===== Collapsible Toolbar Sections ===== */ .tools-primary { flex-wrap: wrap; } .tools-sections { display: flex; gap: 4px; flex-wrap: wrap; align-items: flex-start; } .tools-section { display: flex; align-items: center; gap: 0; flex-wrap: wrap; } .tools-section-header { display: inline-flex; align-items: center; gap: 4px; padding: .28rem .6rem !important; border: 1px solid color-mix(in srgb, var(--border) 60%, transparent) !important; background: color-mix(in srgb, var(--card-base) 40%, transparent) !important; color: var(--muted) !important; font-size: .74rem !important; font-weight: 600; text-transform: uppercase; letter-spacing: .6px; border-radius: 8px !important; cursor: pointer; transition: all .15s ease; line-height: 1; white-space: nowrap; min-width: auto; } .tools-section-header:hover { color: var(--fg) !important; border-color: var(--border) !important; background: color-mix(in srgb, var(--accent) 8%, transparent) !important; backdrop-filter: none !important; box-shadow: none !important; } .tools-section-arrow { font-size: .65rem; transition: transform .2s ease; display: inline-block; } .tools-section.open .tools-section-arrow { transform: rotate(90deg); } .tools-section-label { pointer-events: none; } .tools-section-items { display: none; gap: 6px; align-items: center; margin-left: 4px; animation: sectionFadeIn .2s ease; } .tools-section.open .tools-section-items { display: flex; } @keyframes sectionFadeIn { from { opacity: 0; transform: translateX(-6px); } to { opacity: 1; transform: translateX(0); } } #brand { display: flex; align-items: flex-end; gap: 12px; min-height: calc(var(--brand-h) + 4px); cursor: pointer; transition: opacity 0.2s; } #brand:hover { opacity: 0.85; } /* Logo position variants - logo and weather grouped together */ /* Left: Logo then Weather then Clock, group on left */ .top-row[data-logo-pos="left"] .brand-weather-group { margin-right: auto; } .top-row[data-logo-pos="left"] #brand { order: 0; } .top-row[data-logo-pos="left"] .weather-widget-container { order: 1; } .top-row[data-logo-pos="left"] .clock-widget-container { order: 2; } /* Center: Logo then Weather then Clock, group centered */ .top-row[data-logo-pos="center"] .brand-weather-group { margin: 0 auto; } .top-row[data-logo-pos="center"] #brand { order: 0; } .top-row[data-logo-pos="center"] .weather-widget-container { order: 1; } .top-row[data-logo-pos="center"] .clock-widget-container { order: 2; } /* Right: Clock then Weather then Logo, group on right - weather aligned to logo center */ .top-row[data-logo-pos="right"] .brand-weather-group { margin-left: auto; gap: 150px; align-items: center; } .top-row[data-logo-pos="right"] #brand { order: 2; } .top-row[data-logo-pos="right"] .weather-widget-container { order: 1; margin-top: -80px; } .top-row[data-logo-pos="right"] .clock-widget-container { order: 0; margin-top: -80px; } #brand img { height: var(--brand-h); width: auto; max-width: 70vw; display: block; filter: drop-shadow(0 3px 10px rgba(0, 0, 0, .38)); } #brand .brand-logo-light { display: none; } :root.light-bg #brand .brand-logo-dark { display: none; } :root.light-bg #brand .brand-logo-light { display: block; } /* Weather widget positioned directly right of logo */ .weather-widget-container { display: flex; align-items: center; margin-bottom: 0; flex-shrink: 1; } .tools { display: flex; gap: 10px; align-items: center } .tools .chip { font-size: .8rem; padding: .3rem .55rem; border-radius: 999px; border: 1px solid var(--border); background: transparent } /* Weather Widget - Large, no background, same line as logo */ .weather-widget { display: flex; align-items: flex-end; gap: 16px; padding: 0; border: none; background: transparent; backdrop-filter: none; position: relative; min-width: 0; box-shadow: none; margin-bottom: 0; max-width: 100%; } .weather-content { display: flex; align-items: center; gap: 12px; flex: 1; min-width: 0; } .weather-icon { flex-shrink: 0; display: flex; align-items: center; justify-content: center; } .weather-icon-img { width: clamp(80px, 9vw, 140px); height: auto; filter: drop-shadow(0 3px 12px rgba(0, 0, 0, .4)); object-fit: contain; } .weather-emoji { font-size: clamp(3rem, 6vw, 6rem); line-height: 1; font-family: "Segoe UI Emoji", "Apple Color Emoji", "Noto Color Emoji", emoji; filter: drop-shadow(0 3px 12px rgba(0, 0, 0, .4)); } .weather-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; align-items: flex-start; flex: 1; } .weather-location { font-size: clamp(0.8rem, 1vw, 1rem); color: var(--muted); line-height: 1.2; font-weight: 700; white-space: nowrap; overflow: visible; text-overflow: clip; max-width: 100%; margin-bottom: 4px; } .weather-temp { font-weight: 800; font-size: clamp(1.5rem, 2.5vw, 2.5rem); line-height: 1; text-shadow: 0 2px 4px rgba(0, 0, 0, .4); color: var(--fg); white-space: nowrap; } :root.light .weather-temp { text-shadow: 0 1px 2px rgba(0, 0, 0, .2); } .weather-condition { font-size: clamp(0.75rem, 0.9vw, 0.9rem); color: var(--fg); line-height: 1.2; font-weight: 600; white-space: nowrap; text-transform: capitalize; } .weather-wind { font-size: clamp(0.7rem, 0.85vw, 0.85rem); color: var(--muted); line-height: 1.2; font-weight: 500; white-space: nowrap; } .weather-settings-btn { padding: 6px; border: none; background: transparent; color: var(--muted); cursor: pointer; border-radius: 6px; font-size: 1.2rem; transition: all .15s ease; opacity: .6; margin-left: 8px; } .weather-settings-btn:hover { background: rgba(255, 255, 255, .1); color: var(--fg); opacity: 1; transform: scale(1.15); } /* Weather settings button at bottom */ .weather-settings-btn-bottom { padding: 4px; border: none; background: transparent; color: var(--muted); cursor: pointer; border-radius: 4px; font-size: 0.9rem; transition: all .15s ease; opacity: .7; margin-top: 4px; align-self: flex-start; } .weather-settings-btn-bottom:hover { background: rgba(255, 255, 255, .1); color: var(--fg); opacity: 1; transform: scale(1.1); } /* LCD Clock Font */ @font-face { font-family: 'DSEG7'; src: url('/assets/fonts/DSEG7Classic-Bold.woff2') format('woff2'), url('/assets/fonts/DSEG7Classic-Bold.ttf') format('truetype'); font-weight: 700; font-style: normal; font-display: swap; } /* Digital Clock Widget */ .clock-widget-container { display: flex; align-items: center; flex-shrink: 0; } .clock-widget { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; padding: 0; border: none; background: transparent; } .clock-time { font-size: clamp(1.8rem, 3vw, 3.2rem); font-weight: 700; color: var(--fg); line-height: 1.1; letter-spacing: 2px; font-variant-numeric: tabular-nums; font-family: inherit; text-shadow: 0 2px 8px rgba(0, 0, 0, .25); } .clock-time .clock-ampm { font-size: 0.45em; font-weight: 600; color: var(--muted); letter-spacing: 1px; margin-left: 4px; vertical-align: baseline; } .clock-time .clock-seconds { font-size: 0.55em; color: var(--muted); font-weight: 500; } .clock-date { font-size: clamp(0.75rem, 1vw, 0.95rem); color: var(--muted); font-weight: 600; line-height: 1.2; white-space: nowrap; } /* Clock settings gear button */ .clock-settings-btn { padding: 4px; border: none; background: transparent; color: var(--muted); cursor: pointer; border-radius: 4px; font-size: 0.9rem; transition: all .15s ease; opacity: .7; margin-top: 4px; align-self: flex-start; } .clock-settings-btn:hover { background: rgba(255, 255, 255, .1); color: var(--fg); opacity: 1; transform: scale(1.1); } /* LCD Green Clock Style */ .clock-widget.lcd { background: rgba(0, 0, 0, 0.6); border-radius: 8px; padding: 8px 14px; border: 1px solid rgba(0, 255, 65, 0.15); } .clock-widget.lcd .clock-time { font-family: 'DSEG7', monospace; color: #00ff41; text-shadow: 0 0 8px rgba(0, 255, 65, 0.6), 0 0 20px rgba(0, 255, 65, 0.3); letter-spacing: 3px; } .clock-widget.lcd .clock-time .clock-ampm, .clock-widget.lcd .clock-time .clock-seconds { font-family: 'Sami Grotesk', sans-serif; color: #00ff41; opacity: 0.7; text-shadow: 0 0 6px rgba(0, 255, 65, 0.4); } .clock-widget.lcd .clock-date { font-family: 'Sami Grotesk', sans-serif; color: #00ff41; opacity: 0.7; text-shadow: 0 0 6px rgba(0, 255, 65, 0.3); } /* LCD Blue Clock Style */ .clock-widget.lcd-blue { background: rgba(0, 0, 0, 0.6); border-radius: 8px; padding: 8px 14px; border: 1px solid rgba(0, 136, 255, 0.15); } .clock-widget.lcd-blue .clock-time { font-family: 'DSEG7', monospace; color: #00aaff; text-shadow: 0 0 8px rgba(0, 136, 255, 0.6), 0 0 20px rgba(0, 136, 255, 0.3); letter-spacing: 3px; } .clock-widget.lcd-blue .clock-time .clock-ampm, .clock-widget.lcd-blue .clock-time .clock-seconds { font-family: 'Sami Grotesk', sans-serif; color: #00aaff; opacity: 0.7; text-shadow: 0 0 6px rgba(0, 136, 255, 0.4); } .clock-widget.lcd-blue .clock-date { font-family: 'Sami Grotesk', sans-serif; color: #00aaff; opacity: 0.7; text-shadow: 0 0 6px rgba(0, 136, 255, 0.3); } /* LCD Amber Clock Style */ .clock-widget.lcd-amber { background: rgba(0, 0, 0, 0.6); border-radius: 8px; padding: 8px 14px; border: 1px solid rgba(255, 170, 0, 0.15); } .clock-widget.lcd-amber .clock-time { font-family: 'DSEG7', monospace; color: #ffaa00; text-shadow: 0 0 8px rgba(255, 170, 0, 0.6), 0 0 20px rgba(255, 170, 0, 0.3); letter-spacing: 3px; } .clock-widget.lcd-amber .clock-time .clock-ampm, .clock-widget.lcd-amber .clock-time .clock-seconds { font-family: 'Sami Grotesk', sans-serif; color: #ffaa00; opacity: 0.7; text-shadow: 0 0 6px rgba(255, 170, 0, 0.4); } .clock-widget.lcd-amber .clock-date { font-family: 'Sami Grotesk', sans-serif; color: #ffaa00; opacity: 0.7; text-shadow: 0 0 6px rgba(255, 170, 0, 0.3); } /* LCD Retro Green Clock Style */ .clock-widget.lcd-retro { background: #43895a; border-radius: 8px; padding: 8px 14px; border: 2px solid #2d5e3e; box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1); } .clock-widget.lcd-retro .clock-time { font-family: 'DSEG7', monospace; color: #0a1f10; text-shadow: 0 0 2px rgba(10, 31, 16, 0.3); letter-spacing: 3px; } .clock-widget.lcd-retro .clock-time .clock-ampm, .clock-widget.lcd-retro .clock-time .clock-seconds { font-family: 'Sami Grotesk', sans-serif; color: #0a1f10; opacity: 0.8; } .clock-widget.lcd-retro .clock-date { font-family: 'Sami Grotesk', sans-serif; color: #0a1f10; opacity: 0.7; } /* LCD Taxi (Black & Yellow) Clock Style */ .clock-widget.lcd-taxi { background: #1a1a1a; border-radius: 8px; padding: 8px 14px; border: 2px solid #ccaa00; box-shadow: inset 0 0 0 1px rgba(255, 221, 0, 0.08); } .clock-widget.lcd-taxi .clock-time { font-family: 'DSEG7', monospace; color: #ffdd00; text-shadow: 0 0 8px rgba(255, 221, 0, 0.6), 0 0 20px rgba(255, 221, 0, 0.25); letter-spacing: 3px; } .clock-widget.lcd-taxi .clock-time .clock-ampm, .clock-widget.lcd-taxi .clock-time .clock-seconds { font-family: 'Sami Grotesk', sans-serif; color: #ffdd00; opacity: 0.7; text-shadow: 0 0 6px rgba(255, 221, 0, 0.4); } .clock-widget.lcd-taxi .clock-date { font-family: 'Sami Grotesk', sans-serif; color: #ffdd00; opacity: 0.7; text-shadow: 0 0 6px rgba(255, 221, 0, 0.3); } /* Flip Clock Style */ .flip-clock-row { display: flex; align-items: center; gap: 3px; } .flip-card { display: flex; flex-direction: column; width: clamp(24px, 3vw, 36px); height: clamp(36px, 4.5vw, 52px); border-radius: 4px; overflow: hidden; position: relative; background: rgba(0, 0, 0, 0.5); border: 1px solid var(--border); } .flip-top, .flip-bottom { display: flex; align-items: center; justify-content: center; flex: 1; font-size: clamp(1.2rem, 2vw, 1.8rem); font-weight: 700; color: var(--fg); font-variant-numeric: tabular-nums; } .flip-top { background: rgba(40, 40, 40, 0.8); border-bottom: 1px solid rgba(0, 0, 0, 0.3); } .flip-bottom { background: rgba(30, 30, 30, 0.8); } .flip-card.flipping { animation: flipBounce 0.3s ease-out; } @keyframes flipBounce { 0% { transform: scaleY(0.85); } 50% { transform: scaleY(1.05); } 100% { transform: scaleY(1); } } .flip-colon { font-size: clamp(1.2rem, 2vw, 1.8rem); font-weight: 700; color: var(--fg); padding: 0 2px; line-height: 1; } .flip-ampm { font-size: clamp(0.6rem, 0.9vw, 0.85rem); font-weight: 600; color: var(--muted); margin-left: 6px; align-self: flex-end; margin-bottom: 4px; } .clock-widget.flip { padding: 0; background: transparent; } .clock-widget.flip .clock-date { margin-top: 4px; } /* Binary Clock Style */ .binary-clock { display: flex; flex-direction: column; align-items: center; gap: 4px; background: rgba(0, 0, 0, 0.5); border-radius: 8px; padding: 10px 14px; border: 1px solid rgba(0, 200, 255, 0.15); } .binary-labels { display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px; width: 100%; text-align: center; font-size: 0.6rem; color: rgba(0, 200, 255, 0.5); font-weight: 600; } .binary-row { display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px; } .binary-dot { width: clamp(10px, 1.5vw, 16px); height: clamp(10px, 1.5vw, 16px); border-radius: 50%; background: rgba(0, 200, 255, 0.1); border: 1px solid rgba(0, 200, 255, 0.2); transition: all 0.2s ease; } .binary-dot.on { background: #00c8ff; box-shadow: 0 0 6px rgba(0, 200, 255, 0.6), 0 0 12px rgba(0, 200, 255, 0.3); border-color: #00c8ff; } .binary-values { display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px; width: 100%; text-align: center; font-size: 0.7rem; color: #00c8ff; font-weight: 600; font-variant-numeric: tabular-nums; } .binary-ampm { font-size: 0.7rem; color: #00c8ff; opacity: 0.7; margin-top: 2px; } .clock-widget.binary { padding: 0; background: transparent; } .clock-widget.binary .clock-date { color: #00c8ff; opacity: 0.6; margin-top: 4px; text-align: center; } /* Analog Clock Style */ .analog-clock-wrap { display: flex; align-items: center; gap: 12px; } .analog-clock-svg { flex-shrink: 0; } .analog-info { display: flex; flex-direction: column; gap: 2px; } .analog-digital { font-size: clamp(1rem, 1.5vw, 1.4rem); font-weight: 700; color: var(--fg); font-variant-numeric: tabular-nums; } .analog-date-sm { font-size: clamp(0.7rem, 0.9vw, 0.85rem); color: var(--muted); font-weight: 600; white-space: nowrap; } .clock-widget.analog, .clock-widget.roman { padding: 0; background: transparent; } .clock-widget.analog .clock-date, .clock-widget.roman .clock-date { display: none; } /* Clock Settings Style Grid */ .clock-style-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(80px, 1fr)); gap: 8px; } .clock-style-option { cursor: pointer; } .clock-style-option input[type="radio"] { display: none; } .clock-style-card { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 10px 6px; border-radius: 8px; border: 2px solid var(--border); transition: all 0.15s ease; text-align: center; } .clock-style-option input:checked + .clock-style-card { border-color: var(--ok-fg); background: rgba(46, 204, 113, 0.1); } .clock-style-card:hover { border-color: var(--muted); background: rgba(255, 255, 255, 0.03); } .clock-style-icon { font-size: 1.5rem; } .clock-style-label { font-size: 0.72rem; font-weight: 600; color: var(--fg); } /* Weather Settings Modal */ .weather-modal { position: fixed; inset: 0; background: rgba(0, 0, 0, .6); display: none; align-items: center; justify-content: center; z-index: 1000; backdrop-filter: blur(4px); } .weather-modal.show { display: flex } .weather-modal-content { background: var(--card-base); border: 1px solid var(--border); border-radius: var(--radius); padding: 24px; min-width: 300px; box-shadow: 0 20px 60px rgba(0, 0, 0, .4); position: relative; resize: both; overflow: auto; min-height: 200px; max-width: 90vw; max-height: 90vh; } /* Draggable Dialog Enhancements */ .draggable-dialog { position: fixed !important; z-index: 1000; background: var(--card-base); border: 2px solid var(--accent); border-radius: var(--radius); box-shadow: 0 20px 60px rgba(0, 0, 0, .8); resize: both; overflow: auto; min-width: 300px; min-height: 200px; max-width: 95vw; max-height: 95vh; } .dialog-header { background: linear-gradient(90deg, var(--accent), var(--accent-strong)); color: var(--bg); padding: 12px 16px; margin: -24px -24px 16px -24px; cursor: move; user-select: none; display: flex; justify-content: space-between; align-items: center; font-weight: 600; border-radius: var(--radius) var(--radius) 0 0; } .dialog-controls { display: flex; gap: 8px; align-items: center; } .dialog-btn { background: rgba(255, 255, 255, 0.2); border: none; color: var(--bg); width: 24px; height: 24px; border-radius: 4px; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 12px; transition: background 0.2s ease; } .dialog-btn:hover { background: rgba(255, 255, 255, 0.3); } .dialog-resize-handle { position: absolute; bottom: 0; right: 0; width: 20px; height: 20px; cursor: se-resize; background: linear-gradient(-45deg, transparent 0%, transparent 40%, var(--accent) 50%, transparent 60%, transparent 100%); } /* Make all modals draggable */ .logs-modal .logs-modal-content, .weather-modal .weather-modal-content, #add-service-modal .weather-modal-content, #app-selector-modal .app-selector-content { position: fixed; resize: both; overflow: auto; min-width: 300px; min-height: 200px; max-width: 95vw; max-height: 95vh; } /* Add Service Modal - Ultra Compact */ #add-service-modal { position: fixed !important; top: 50% !important; left: 50% !important; transform: translate(-50%, -50%) !important; width: 750px !important; max-width: 95vw !important; max-height: 92vh !important; background: var(--card-base) !important; z-index: 1000 !important; display: none !important; overflow-y: auto !important; border: 2px solid var(--accent) !important; border-radius: 8px !important; box-shadow: 0 20px 60px rgba(0, 0, 0, .8) !important; } #add-service-modal.show { display: block !important; } #add-service-modal .weather-modal-content { width: 100% !important; margin: 0 !important; padding: 14px !important; background: transparent !important; border: none !important; } #add-service-modal::-webkit-scrollbar { width: 8px !important; } #add-service-modal::-webkit-scrollbar-track { background: var(--bg) !important; } #add-service-modal::-webkit-scrollbar-thumb { background: var(--accent) !important; border-radius: 4px !important; } #add-service-modal::-webkit-scrollbar-thumb:hover { background: var(--accent-strong) !important; } /* Make form elements ultra compact */ #add-service-modal input, #add-service-modal select, #add-service-modal textarea { font-size: 0.75rem !important; padding: 4px 6px !important; margin-bottom: 3px !important; line-height: 1.2 !important; } #add-service-modal label { font-size: 0.7rem !important; margin-bottom: 2px !important; display: block !important; line-height: 1.2 !important; } #add-service-modal h3 { font-size: 0.95rem !important; margin: 0 0 8px !important; font-weight: 600 !important; } #add-service-modal h4 { font-size: 0.8rem !important; margin: 6px 0 4px !important; padding-top: 4px !important; font-weight: 600 !important; } #add-service-modal h4:first-of-type { padding-top: 0 !important; margin-top: 0 !important; } /* Compact sections */ #add-service-modal .weather-modal-content > div { gap: 6px !important; } #add-service-modal p { font-size: 0.7rem !important; margin: 2px 0 4px !important; line-height: 1.3 !important; } #add-service-modal details { margin-top: 6px !important; } #add-service-modal details summary { font-size: 0.75rem !important; padding: 3px 0 !important; } #add-service-modal details > div { margin-top: 4px !important; gap: 6px !important; } /* Quick IP selection buttons - compact */ .quick-ip-btn { padding: 3px 8px !important; font-size: 0.7rem !important; background: color-mix(in srgb, var(--accent) 15%, transparent) !important; border: 1px solid var(--accent) !important; border-radius: 3px !important; color: var(--accent) !important; cursor: pointer; transition: all 0.2s ease; white-space: nowrap; line-height: 1.2 !important; } .quick-ip-btn:hover { background: color-mix(in srgb, var(--accent) 30%, transparent) !important; } .quick-ip-btn.active { background: var(--accent) !important; color: var(--bg) !important; } .quick-ip-btn:disabled { opacity: 0.5; cursor: not-allowed; } /* Compact modal buttons */ #add-service-modal button { padding: 5px 10px !important; font-size: 0.75rem !important; line-height: 1.2 !important; } #add-service-modal .weather-modal-buttons { margin-top: 10px !important; gap: 6px !important; } /* Compact grid spacing */ #add-service-modal div[style*="grid"] { gap: 5px !important; } #add-service-modal .quick-ip-buttons { gap: 4px !important; margin-top: 3px !important; } .weather-modal h3 { margin: 0 0 16px; color: var(--fg) } .weather-modal label { display: block; margin-bottom: 8px; color: var(--fg); font-size: .9rem } .weather-modal input { width: 100%; padding: 8px 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg); color: var(--fg); font-size: .9rem; margin-bottom: 16px; } .weather-modal-buttons { display: flex; gap: 8px; justify-content: flex-end } .weather-modal button { margin: 0 } /* Weather Unit Toggle */ .weather-unit-option { cursor: pointer; flex: 1; } .weather-unit-option input[type="radio"] { display: none; } .weather-unit-card { display: block; text-align: center; padding: 8px 12px; border-radius: 6px; border: 2px solid var(--border); font-size: 0.85rem; font-weight: 600; color: var(--fg); transition: all 0.15s ease; } .weather-unit-option input:checked + .weather-unit-card { border-color: var(--ok-fg); background: rgba(46, 204, 113, 0.1); } .weather-unit-card:hover { border-color: var(--muted); background: rgba(255, 255, 255, 0.03); } /* Setup Wizard Styles */ .setup-wizard { position: fixed; inset: 0; background: rgba(0, 0, 0, .85); display: flex; align-items: center; justify-content: center; z-index: 2000; backdrop-filter: blur(8px); } .setup-wizard-content { background: var(--card-base); border: 2px solid var(--accent); border-radius: 16px; padding: 40px; min-width: 600px; max-width: 800px; max-height: 90vh; overflow-y: auto; box-shadow: 0 20px 80px rgba(0, 0, 0, .6); } .setup-step { animation: fadeIn 0.3s ease-out; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .setup-options { display: grid; gap: 16px; margin-bottom: 32px; } .setup-option { display: flex; align-items: flex-start; padding: 20px; background: var(--card-bg); border: 2px solid var(--border); border-radius: 12px; cursor: pointer; transition: all 0.2s ease; } .setup-option:hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0, 0, 0, .2); } .setup-option input[type="radio"] { margin-right: 16px; margin-top: 4px; width: 20px; height: 20px; cursor: pointer; } .setup-option input[type="radio"]:checked ~ .setup-option-content { color: var(--accent); } .setup-option:has(input:checked) { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 5%, transparent); } .setup-option-content { flex: 1; } .setup-option-icon { font-size: 2rem; margin-bottom: 8px; } .setup-option-title { font-size: 1.1rem; font-weight: 600; margin-bottom: 6px; } .setup-option-desc { font-size: 0.9rem; color: var(--muted); line-height: 1.5; margin-bottom: 8px; } .setup-option-example { font-size: 0.85rem; color: var(--accent); font-family: monospace; padding: 6px 10px; background: color-mix(in srgb, var(--accent) 10%, transparent); border-radius: 4px; display: inline-block; } .setup-wizard-buttons { display: flex; gap: 12px; margin-top: 32px; align-items: center; position: relative; z-index: 10; } .setup-wizard-buttons button { padding: 12px 24px; border-radius: 8px; border: 2px solid var(--border); background: var(--card-bg); color: var(--fg); font-size: 1rem; cursor: pointer; transition: all 0.2s ease; position: relative; z-index: 11; } .setup-wizard-buttons button:hover { transform: translateY(-1px); box-shadow: 0 4px 8px rgba(0, 0, 0, .2); } .setup-btn-primary { background: color-mix(in srgb, var(--accent) 20%, transparent) !important; border-color: var(--accent) !important; color: var(--accent) !important; font-weight: 600 !important; } .setup-btn-primary:hover { background: color-mix(in srgb, var(--accent) 30%, transparent) !important; } /* App Selector Modal - No backdrop, positioned in corner */ #app-selector-modal { background: transparent; backdrop-filter: none; align-items: flex-start; justify-content: flex-end; padding: 20px; } #app-selector-modal.show { display: flex; } .app-selector-content { background: var(--card-base); border: 1px solid var(--border); border-radius: var(--radius); padding: 24px; width: 600px; max-width: calc(100vw - 40px); max-height: calc(100vh - 40px); overflow-y: auto; box-shadow: 0 20px 60px rgba(0, 0, 0, .6), 0 0 0 1px rgba(255, 255, 255, .08); backdrop-filter: blur(20px) saturate(150%); -webkit-backdrop-filter: blur(20px) saturate(150%); } .app-selector-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 16px; margin-bottom: 16px; } .app-option { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 20px 12px; border-radius: 12px; border: 1px solid var(--border); background: linear-gradient(180deg, rgba(255, 255, 255, .04), rgba(255, 255, 255, .01)); cursor: pointer; transition: all .2s ease; text-align: center; } .app-option:hover { transform: translateY(-4px); border-color: var(--accent); background: linear-gradient(180deg, rgba(255, 255, 255, .10), rgba(255, 255, 255, .04)); box-shadow: 0 8px 24px rgba(0, 0, 0, .3), 0 0 0 2px color-mix(in srgb, var(--accent) 40%, transparent); } .app-option-icon { font-size: 48px; margin-bottom: 8px; filter: drop-shadow(0 2px 4px rgba(0, 0, 0, .3)); } .app-option-name { font-size: .9rem; font-weight: 600; color: var(--fg); margin-bottom: 4px; } .app-option-desc { font-size: .75rem; color: var(--muted); line-height: 1.3; } .app-category-header { grid-column: 1 / -1; font-size: 1.1rem; font-weight: 700; color: var(--accent-strong); margin-top: 16px; margin-bottom: 8px; padding-bottom: 8px; border-bottom: 2px solid var(--border); } @media (max-width: 800px) { #app-selector-modal { justify-content: center; align-items: center; } .app-selector-content { width: calc(100vw - 32px); max-height: calc(100vh - 32px); padding: 20px 16px; } .app-selector-grid { grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: 10px; } .app-option { padding: 12px 6px; } .app-option-icon { font-size: 32px; } .app-option-name { font-size: .85rem; } .app-option-desc { font-size: .7rem; } } @keyframes spin { to { transform: rotate(360deg) } } .brand-spinner { width: 18px; height: 18px; display: inline-block; vertical-align: -3px; margin-right: 8px; mask: url(/assets/dashcaddy-logo-dark.png) center/contain no-repeat; -webkit-mask: url(/assets/dashcaddy-logo-dark.png) center/contain no-repeat; background: linear-gradient(90deg, var(--accent), var(--accent-strong)); animation: spin 1.2s linear infinite; } /* ---------- TOP ANCHOR ROW (DNS/Internet) ---------- */ .top { display: grid; gap: 16px; margin: 16px 0 24px; grid-template-columns: repeat(3, minmax(280px, 1fr)); align-items: stretch; position: relative; } .top::after { content: ""; position: absolute; left: 0; right: 0; bottom: -10px; height: 2px; background: linear-gradient(90deg, transparent 0%, var(--accent) 25%, var(--accent-strong) 50%, var(--accent) 75%, transparent 100%); opacity: .35; filter: blur(.2px); } @media (max-width: 1100px) { .top { grid-template-columns: repeat(2, minmax(260px, 1fr)) } } @media (max-width: 760px) { .top { grid-template-columns: 1fr } } .top .card { width: auto; min-width: 0; min-height: 200px; padding-bottom: 48px; } .top .row .name { font-size: clamp(20px, 1.4vw + 18px, 26px) } /* ---------- APP GRID ---------- */ .grid { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); align-items: stretch; position: relative; z-index: 1; } /* === Glass cards === */ .card { position: relative; background: linear-gradient(180deg, rgba(180, 200, 255, .10), rgba(180, 200, 255, .03)), rgba(18, 24, 38, .42); border: 1px solid rgba(120, 170, 255, .22); border-radius: var(--radius); padding: 14px 16px 60px; min-height: 180px; box-shadow: 0 10px 34px rgba(0, 10, 40, .55), inset 0 1px 0 rgba(200, 220, 255, .14); backdrop-filter: blur(12px) saturate(135%); -webkit-backdrop-filter: blur(12px) saturate(135%); display: flex; flex-direction: column; gap: .6rem; transition: box-shadow .18s ease, border-color .18s ease, background-color .18s ease, backdrop-filter .18s ease, transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1); padding-bottom: 44px; opacity: 0; transform: translateY(20px); } /* Staggered loading animation */ .card.loaded { opacity: 1; transform: translateY(0); } .grid .card { min-width: 300px; width: clamp(300px, 30vw, 380px); max-width: 100%; } /* Sheen animation (all themes) */ @keyframes sheen { from { background-position: -200% 0 } to { background-position: 200% 0 } } .card::before, .card::after { content: ""; position: absolute; inset: 0; border-radius: var(--radius); pointer-events: none } .card::before { background: linear-gradient(180deg, rgba(255, 255, 255, .16), rgba(255, 255, 255, 0) 28%); mix-blend-mode: screen; opacity: .55; } .card:hover::before { background: linear-gradient(180deg, rgba(255, 255, 255, .16), rgba(255, 255, 255, 0) 28%), linear-gradient(120deg, rgba(255, 255, 255, .25) 8%, rgba(255, 255, 255, 0) 22%, rgba(255, 255, 255, .18) 36%, rgba(255, 255, 255, 0) 52%); background-size: 100% 100%, 220% 220%; animation: sheen 2s ease-in-out infinite; opacity: .5; } .card::after { background: radial-gradient(1px 1px at 20% 30%, rgba(255, 255, 255, .06), transparent 60%), radial-gradient(1px 1px at 70% 60%, rgba(255, 255, 255, .05), transparent 60%), radial-gradient(1px 1px at 40% 80%, rgba(255, 255, 255, .04), transparent 60%); opacity: .35; filter: saturate(130%); } /* (2) Floating motion on hover */ @keyframes float { 0%, 100% { transform: translateY(-2px); } 50% { transform: translateY(-6px); } } .card:hover { animation: float 3.5s ease-in-out infinite; } /* (3) Animated border pulse (subtle) */ @keyframes borderPulse { 0% { box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 28%, rgba(192, 192, 192, 0.25)), 0 6px 24px color-mix(in srgb, var(--accent-strong) 12%, rgba(255, 255, 255, 0.12)), 0 0 18px 4px color-mix(in srgb, var(--accent) 14%, rgba(255, 255, 255, 0.10)), inset 0 1px 0 rgba(255, 255, 255, 0.08); } 50% { box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 45%, rgba(192, 192, 192, 0.35)), 0 10px 28px color-mix(in srgb, var(--accent-strong) 18%, rgba(255, 255, 255, 0.16)), 0 0 24px 6px color-mix(in srgb, var(--accent) 22%, rgba(255, 255, 255, 0.14)), inset 0 1px 0 rgba(255, 255, 255, 0.12); } 100% { box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 28%, rgba(192, 192, 192, 0.25)), 0 6px 24px color-mix(in srgb, var(--accent-strong) 12%, rgba(255, 255, 255, 0.12)), 0 0 18px 4px color-mix(in srgb, var(--accent) 14%, rgba(255, 255, 255, 0.10)), inset 0 1px 0 rgba(255, 255, 255, 0.08); } } .card:hover { animation-name: float, borderPulse; animation-duration: 3.5s, 2.2s; animation-timing-function: ease-in-out, ease-in-out; animation-iteration-count: infinite, infinite; } /* Content rows */ .row { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; } .row .name { font-weight: 700; font-size: clamp(18px, 1.1vw + 16px, 24px); line-height: 1.25; letter-spacing: .1px; text-shadow: 0 1px 1px rgba(0, 0, 0, .35); flex: 1 1 140px; min-width: 0; white-space: normal; word-break: normal; overflow-wrap: anywhere; hyphens: auto; } :root.light .row .name { text-shadow: none } .row .spacer { margin-left: auto } .dot { width: .75rem; height: .75rem; border-radius: 50%; position: relative; box-shadow: 0 0 0 2px rgba(0, 0, 0, .25), 0 0 10px rgba(0, 0, 0, .35) inset } .dot.ok { background: var(--dot-ok) } .dot.bad { background: var(--dot-bad); animation: pulse-bad 2.4s ease-out infinite } @keyframes pulse-bad { 0% { box-shadow: 0 0 0 0 rgba(255, 103, 103, .35) } 70% { box-shadow: 0 0 0 8px rgba(255, 103, 103, 0) } 100% { box-shadow: 0 0 0 0 rgba(255, 103, 103, 0) } } .at-bl { position: absolute; bottom: 12px; left: 16px } /* Glow dot when hovering Open button */ .card:has(.btn-row:hover) .dot.at-bl { box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.25), 0 0 10px rgba(0, 0, 0, 0.35) inset, 0 0 12px 4px currentColor; transition: box-shadow .2s ease; } .card:has(.btn-row:hover) .dot.ok { background-color: color-mix(in srgb, var(--dot-ok) 90%, white 10%) } .card:has(.btn-row:hover) .dot.bad { background-color: color-mix(in srgb, var(--dot-bad) 90%, white 10%) } .badge { display: inline-block; font-weight: 700; padding: 6px 12px 6px 28px; border-radius: 999px; position: relative; letter-spacing: .25px; box-shadow: 0 1px 0 rgba(255, 255, 255, .06) inset; white-space: nowrap; } .badge::before { content: ""; position: absolute; left: 10px; top: 50%; transform: translateY(-50%); width: 8px; height: 8px; border-radius: 50%; background: currentColor; filter: drop-shadow(0 0 6px currentColor); opacity: .9 } .badge.on { background: color-mix(in srgb, var(--ok-bg) 80%, var(--accent) 20%); color: var(--ok-fg) } .badge.off { background: color-mix(in srgb, var(--bad-bg) 85%, var(--accent-strong) 15%); color: var(--bad-fg) } .logo-wrap { width: 64px; height: 64px; border-radius: 14px; background: linear-gradient(180deg, rgba(255, 255, 255, .06), rgba(255, 255, 255, .01)); border: 1px solid color-mix(in oklab, var(--border) 60%, #fff 3%); display: grid; place-items: center; flex: 0 0 64px; } :root.light .logo-wrap { background: linear-gradient(180deg, rgba(0, 0, 0, .03), rgba(0, 0, 0, .01)); border: 1px solid rgba(0, 0, 0, .06) } :root.blue .logo-wrap { background: linear-gradient(180deg, rgba(255, 255, 255, .14), rgba(255, 255, 255, .04)); border: 1px solid rgba(255, 255, 255, .35) } /* PNG Logo Images - Reliable and Fast */ .logo-img { width: 54px; height: 54px; object-fit: contain; display: block; transition: all .2s ease; filter: drop-shadow(0 1px 3px rgba(0, 0, 0, .3)); } .card:hover .logo-img { transform: scale(1.1); filter: drop-shadow(0 3px 8px rgba(0, 0, 0, .4)); } .card.loaded .logo-img { animation: iconFadeIn 0.4s ease-out 0.2s both; } @keyframes iconFadeIn { from { opacity: 0; transform: scale(0.8); } to { opacity: 1; transform: scale(1); } } /* DNS and Internet icons in top row */ .top .logo-img { width: 48px; height: 48px; } .btn-row { position: absolute; right: 12px; bottom: 12px } .btn-row button { opacity: .95; transition: opacity .15s ease, transform .15s } .card:hover .btn-row button { opacity: 1; transform: translateY(-1px) } /* Logs button styling */ .logs-btn { margin-left: 8px !important; font-size: .8rem !important; padding: .3rem .6rem !important; } /* Delete button styling */ .delete-btn { margin-right: 8px !important; font-size: .8rem !important; padding: .3rem .5rem !important; background: color-mix(in srgb, var(--bad-fg) 10%, transparent) !important; border-color: color-mix(in srgb, var(--bad-fg) 40%, var(--border)) !important; color: var(--bad-fg) !important; opacity: 0.7; transition: all 0.2s ease; } .delete-btn:hover { background: color-mix(in srgb, var(--bad-fg) 25%, transparent) !important; border-color: var(--bad-fg) !important; opacity: 1; transform: scale(1.1); } /* Settings button styling */ .settings-btn { margin-left: 4px !important; font-size: .8rem !important; padding: .3rem .5rem !important; min-width: auto !important; } /* Options button styling */ .options-btn { margin-right: 8px !important; font-size: .8rem !important; padding: .3rem .5rem !important; background: color-mix(in srgb, var(--accent) 10%, transparent) !important; border-color: color-mix(in srgb, var(--accent) 40%, var(--border)) !important; color: var(--accent) !important; opacity: 0.7; transition: all 0.2s ease; } .options-btn:hover { background: color-mix(in srgb, var(--accent) 25%, transparent) !important; border-color: var(--accent) !important; opacity: 1; transform: scale(1.1); } /* Update button styling */ .update-btn { margin-left: 4px !important; font-size: .8rem !important; padding: .3rem .6rem !important; } .update-btn:disabled { opacity: 0.5; cursor: wait; } /* Exec/terminal button styling — subtle, hover-only */ .exec-btn { margin-left: 4px !important; font-size: .7rem !important; font-family: monospace !important; padding: .2rem .45rem !important; opacity: 0; transition: opacity 0.2s ease; } .card:hover .exec-btn { opacity: 0.6; } .exec-btn:hover { opacity: 1 !important; } /* Credentials (key) button styling */ .creds-btn { margin-right: 8px !important; font-size: .8rem !important; padding: .3rem .5rem !important; background: color-mix(in srgb, var(--ok-fg, #74dfc4) 10%, transparent) !important; border-color: color-mix(in srgb, var(--ok-fg, #74dfc4) 40%, var(--border)) !important; color: var(--ok-fg, #74dfc4) !important; opacity: 0.7; transition: all 0.2s ease; } .creds-btn:hover { background: color-mix(in srgb, var(--ok-fg, #74dfc4) 25%, transparent) !important; border-color: var(--ok-fg, #74dfc4) !important; opacity: 1; transform: scale(1.1); } .creds-btn.has-creds { opacity: 1; background: color-mix(in srgb, var(--ok-fg, #74dfc4) 20%, transparent) !important; } /* Service credentials modal */ #service-creds-modal { position: fixed; inset: 0; z-index: 1500; display: none; align-items: center; justify-content: center; background: rgba(0,0,0,0.5); backdrop-filter: blur(4px); } #service-creds-modal.show { display: flex; } .service-creds-content { background: var(--card-base, #1a1f2e); border: 1px solid var(--border); border-radius: 12px; padding: 20px; min-width: 340px; max-width: 420px; box-shadow: 0 8px 32px rgba(0,0,0,0.4); } /* Internet card packet blink */ .card[data-app="internet"] .dot { transition: background-color 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease; } .card[data-app="internet"][data-status="on"] .dot { animation: internet-traffic 1.35s ease-in-out infinite; } @keyframes internet-traffic { 0%, 100% { transform: scale(1); background: var(--dot-ok); box-shadow: 0 0 0 rgba(39, 174, 96, 0); } 38% { transform: scale(1.06); background: #4caf50; box-shadow: 0 0 10px 2px rgba(76, 175, 80, 0.55); } 68% { transform: scale(0.98); background: #2196f3; box-shadow: 0 0 10px 2px rgba(33, 150, 243, 0.5); } } @media (prefers-reduced-motion: reduce) { .card[data-app="internet"][data-status="on"] .dot { animation: none; } } /* Restart button styling */ .restart-btn { margin-right: 8px !important; font-size: .8rem !important; padding: .3rem .6rem !important; } /* Token Management Modal Styles */ .token-section { background: color-mix(in srgb, var(--accent) 5%, var(--card-base) 95%); border: 1px solid var(--border); border-radius: 8px; padding: 12px; margin-bottom: 12px; } .token-section-title { margin: 0 0 10px; color: var(--accent); font-size: 0.95rem; font-weight: 600; } .token-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; } .token-field label { display: block; font-size: 0.8rem; color: var(--muted); margin-bottom: 4px; } .token-input-row { display: flex; gap: 4px; } .token-input-row input { flex: 1; font-size: 0.85rem; padding: 6px 10px; } .token-toggle { padding: 6px 10px !important; min-width: auto !important; font-size: 0.8rem !important; background: color-mix(in srgb, var(--accent) 10%, transparent) !important; border-color: var(--border) !important; } .token-toggle:hover { background: color-mix(in srgb, var(--accent) 20%, transparent) !important; } .token-status { margin-top: 8px; font-size: 0.75rem; min-height: 18px; } .token-status.success { color: var(--ok-fg); } .token-status.error { color: var(--bad-fg); } @media (max-width: 600px) { .token-grid { grid-template-columns: 1fr; } } /* DNS Logs Modal */ .logs-modal { position: fixed; inset: 0; background: rgba(0, 0, 0, .7); display: none; align-items: center; justify-content: center; z-index: 1001; backdrop-filter: blur(6px); } .logs-modal.show { display: flex; } .logs-modal-content { background: var(--card-base); border: 1px solid var(--border); border-radius: var(--radius); width: min(90vw, 800px); height: min(80vh, 600px); box-shadow: 0 25px 80px rgba(0, 0, 0, .5); display: flex; flex-direction: column; overflow: hidden; } .logs-header { display: flex; align-items: center; justify-content: space-between; padding: 16px 20px; border-bottom: 1px solid var(--border); background: color-mix(in srgb, var(--card-base) 95%, var(--accent) 5%); } .logs-header h3 { margin: 0; color: var(--fg); font-size: 1.1rem; } .logs-controls { display: flex; align-items: center; gap: 12px; } .logs-controls label { color: var(--muted); font-size: .9rem; font-weight: 500; } .logs-controls select { padding: 4px 8px; border: 1px solid var(--border); border-radius: 6px; background: var(--bg); color: var(--fg); font-size: .85rem; } .pause-btn, .close-btn { padding: 4px 8px !important; font-size: .85rem !important; min-width: auto !important; } .pause-btn.paused { background: color-mix(in srgb, #ff6600 15%, transparent) !important; border-color: #ff6600 !important; color: #ff6600 !important; } .close-btn { background: color-mix(in srgb, var(--bad-fg) 15%, transparent) !important; border-color: var(--bad-fg) !important; color: var(--bad-fg) !important; } .stream-btn { padding: 4px 10px !important; font-size: .85rem !important; min-width: auto !important; transition: all 0.3s ease; } .stream-btn.active { background: color-mix(in srgb, #00cc66 20%, transparent) !important; border-color: #00cc66 !important; color: #00cc66 !important; animation: pulse-glow 2s infinite; } @keyframes pulse-glow { 0%, 100% { box-shadow: 0 0 5px rgba(0, 204, 102, 0.3); } 50% { box-shadow: 0 0 15px rgba(0, 204, 102, 0.6); } } .logs-container { flex: 1; overflow: hidden; position: relative; } .logs-content { height: 100%; overflow-y: auto; padding: 16px; font-family: 'Consolas', 'Monaco', 'Courier New', monospace; font-size: .8rem; line-height: 1.4; background: color-mix(in srgb, var(--bg) 60%, var(--card-base) 40%); } .logs-loading { display: flex; align-items: center; justify-content: center; height: 100%; color: var(--muted); font-style: italic; } .log-entry { margin-bottom: 4px; padding: 4px 8px; border-radius: 4px; border-left: 3px solid transparent; transition: all .2s ease; word-wrap: break-word; white-space: pre-wrap; } .log-entry:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); } .log-entry.error { border-left-color: var(--bad-fg); background: color-mix(in srgb, var(--bad-fg) 5%, transparent); color: color-mix(in srgb, var(--bad-fg) 90%, var(--fg) 10%); } .log-entry.warning { border-left-color: #ffaa00; background: color-mix(in srgb, #ffaa00 5%, transparent); color: color-mix(in srgb, #ffaa00 90%, var(--fg) 10%); } .log-entry.info { border-left-color: var(--accent); background: color-mix(in srgb, var(--accent) 5%, transparent); color: var(--fg); } .log-timestamp { color: var(--muted); font-weight: 600; margin-right: 8px; } .log-level { font-weight: 700; margin-right: 8px; text-transform: uppercase; font-size: .75rem; } .log-message { color: var(--fg); } /* Response time display */ .response-row { display: flex; justify-content: flex-start; margin-top: 4px; margin-bottom: 8px; } .response-time { font-size: .75rem; font-weight: 600; padding: 2px 8px; border-radius: 6px; letter-spacing: .3px; text-transform: uppercase; transition: all .2s ease; min-width: 60px; text-align: center; border: 1px solid transparent; } /* Response time color coding */ .response-time.excellent { background: color-mix(in srgb, #00ff88 15%, var(--card-base) 85%); color: #00ff88; border-color: color-mix(in srgb, #00ff88 30%, transparent 70%); box-shadow: 0 0 8px color-mix(in srgb, #00ff88 20%, transparent 80%); } .response-time.good { background: color-mix(in srgb, var(--ok-fg) 15%, var(--card-base) 85%); color: var(--ok-fg); border-color: color-mix(in srgb, var(--ok-fg) 30%, transparent 70%); box-shadow: 0 0 6px color-mix(in srgb, var(--ok-fg) 15%, transparent 85%); } .response-time.fair { background: color-mix(in srgb, #ffaa00 15%, var(--card-base) 85%); color: #ffaa00; border-color: color-mix(in srgb, #ffaa00 30%, transparent 70%); box-shadow: 0 0 6px color-mix(in srgb, #ffaa00 15%, transparent 85%); } .response-time.slow { background: color-mix(in srgb, #ff6600 15%, var(--card-base) 85%); color: #ff6600; border-color: color-mix(in srgb, #ff6600 30%, transparent 70%); box-shadow: 0 0 6px color-mix(in srgb, #ff6600 15%, transparent 85%); } .response-time.timeout { background: color-mix(in srgb, var(--bad-fg) 15%, var(--card-base) 85%); color: var(--bad-fg); border-color: color-mix(in srgb, var(--bad-fg) 30%, transparent 70%); box-shadow: 0 0 6px color-mix(in srgb, var(--bad-fg) 15%, transparent 85%); } /* Light theme adjustments */ :root.light .response-time.excellent { background: color-mix(in srgb, #00cc66 12%, white 88%); color: #00aa55; border-color: color-mix(in srgb, #00cc66 25%, transparent 75%); box-shadow: 0 1px 3px color-mix(in srgb, #00cc66 20%, transparent 80%); } :root.light .response-time.fair { background: color-mix(in srgb, #ff8800 12%, white 88%); color: #cc6600; border-color: color-mix(in srgb, #ff8800 25%, transparent 75%); box-shadow: 0 1px 3px color-mix(in srgb, #ff8800 20%, transparent 80%); } :root.light .response-time.slow { background: color-mix(in srgb, #ff4400 12%, white 88%); color: #cc3300; border-color: color-mix(in srgb, #ff4400 25%, transparent 75%); box-shadow: 0 1px 3px color-mix(in srgb, #ff4400 20%, transparent 80%); } /* Blue theme adjustments */ :root.blue .response-time.excellent { background: color-mix(in srgb, #88ffcc 18%, var(--card-base) 82%); color: #88ffcc; border-color: color-mix(in srgb, #88ffcc 35%, transparent 65%); } :root.blue .response-time.fair { background: color-mix(in srgb, #ffcc88 18%, var(--card-base) 82%); color: #ffcc88; border-color: color-mix(in srgb, #ffcc88 35%, transparent 65%); } :root.blue .response-time.slow { background: color-mix(in srgb, #ff8888 18%, var(--card-base) 82%); color: #ff8888; border-color: color-mix(in srgb, #ff8888 35%, transparent 65%); } @media (max-width: 1200px) { .top-row { flex-direction: column; align-items: center; gap: 16px; } .tools-row { justify-content: center; } .weather-widget-container { max-width: 90vw; } .weather-icon { font-size: clamp(48px, 6vw, 64px); } .weather-temp { font-size: clamp(1.5rem, 2.5vw, 2.5rem); } .clock-time { font-size: clamp(1.5rem, 2.5vw, 2.5rem); } } @media (max-width: 900px) { body { padding: 20px } #brand img { max-width: 76vw } .card { min-height: 170px; padding: 12px 14px 56px } .weather-widget { min-width: 180px; padding: 12px 16px; } .weather-icon { font-size: 36px; } .weather-temp { font-size: 1.2rem; } .clock-time { font-size: 1.2rem; } .clock-date { font-size: 0.75rem; } } @media (max-width: 640px) { body { padding: 16px } .grid .card { min-width: 260px; width: clamp(260px, 80vw, 340px) } .logo-wrap { width: 56px; height: 56px } .logo-img { width: 48px; height: 48px } :root { --brand-min: 110px; --brand-max: 240px; --brand-h: clamp(var(--brand-min), 28vw, var(--brand-max)); } .weather-widget { min-width: 160px; padding: 10px 14px; gap: 10px; } .weather-icon { font-size: 32px; } .weather-temp { font-size: 1.1rem; } .weather-location { font-size: .8rem; } .clock-time { font-size: 1.1rem; } .clock-date { font-size: 0.7rem; } } @media (max-width: 420px) { .grid .card { min-width: 240px; width: 100% } :root { --brand-min: 100px; --brand-max: 220px; --brand-h: clamp(var(--brand-min), 32vw, var(--brand-max)); } .weather-widget { min-width: 140px; padding: 8px 12px; } .weather-icon { font-size: 28px; } .weather-temp { font-size: 1rem; } .weather-location { font-size: .75rem; } .clock-time { font-size: 1rem; } .clock-date { font-size: 0.65rem; } } /* qBittorrent title slight tweak for awkward wraps at some widths */ .card[data-app="torrent"] .row .name { font-size: clamp(17px, 1vw + 16px, 22px); } /* Responsive behavior for weather widget */ @media (max-width: 1200px) { #brand { flex-direction: column; align-items: center; gap: 16px; } .weather-widget-container { margin-bottom: 0; } .weather-icon { font-size: clamp(48px, 6vw, 64px); } .weather-temp { font-size: clamp(1.5rem, 2.5vw, 2.5rem); } } @media (max-width: 900px) { body { padding: 20px; } #brand img { max-width: 76vw; } .card { min-height: 170px; padding: 12px 14px 56px; } .weather-icon { font-size: clamp(40px, 5vw, 56px); } .weather-temp { font-size: clamp(1.3rem, 2.2vw, 2rem); } } @media (max-width: 640px) { body { padding: 16px; } .grid .card { min-width: 260px; width: clamp(260px, 80vw, 340px); } .logo-wrap { width: 56px; height: 56px; } .logo-img { width: 48px; height: 48px; } :root { --brand-min: 110px; --brand-max: 240px; --brand-h: clamp(var(--brand-min), 28vw, var(--brand-max)); } .weather-icon { font-size: clamp(36px, 4.5vw, 48px); } .weather-temp { font-size: clamp(1.1rem, 2vw, 1.8rem); } .weather-location { font-size: clamp(0.8rem, 1.1vw, 1rem); } } @media (max-width: 420px) { .grid .card { min-width: 240px; width: 100%; } :root { --brand-min: 100px; --brand-max: 220px; --brand-h: clamp(var(--brand-min), 32vw, var(--brand-max)); } .weather-icon { font-size: clamp(32px, 4vw, 40px); } .weather-temp { font-size: clamp(1rem, 1.8vw, 1.5rem); } .weather-location { font-size: clamp(0.75rem, 1vw, 0.9rem); } } /* ===== MONITORING & HEALTH PANEL STYLES ===== */ /* Tab bar used in multi-section modals */ .panel-tabs { display: flex; gap: 0; border-bottom: 2px solid var(--border); margin-bottom: 16px; } .panel-tab { padding: 8px 16px; border: none; background: transparent; color: var(--muted); font-size: 0.85rem; font-weight: 500; cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -2px; transition: color 0.2s, border-color 0.2s; } .panel-tab:hover { color: var(--fg); background: transparent; box-shadow: none; } .panel-tab.active { color: var(--accent); border-bottom-color: var(--accent); background: transparent; box-shadow: none; } .panel-section { display: none; } .panel-section.active { display: block; } /* Status badges (Health and Updates) */ .status-badge { display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: 999px; font-size: 0.7rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; } .status-badge.up { background: color-mix(in srgb, var(--dot-ok) 15%, transparent); color: var(--dot-ok); border: 1px solid color-mix(in srgb, var(--dot-ok) 30%, transparent); } .status-badge.down { background: color-mix(in srgb, var(--dot-bad) 15%, transparent); color: var(--dot-bad); border: 1px solid color-mix(in srgb, var(--dot-bad) 30%, transparent); } .status-badge.warning { background: color-mix(in srgb, #f39c12 15%, transparent); color: #f39c12; border: 1px solid color-mix(in srgb, #f39c12 30%, transparent); } .status-badge.info { background: color-mix(in srgb, #3498db 15%, transparent); color: #3498db; border: 1px solid color-mix(in srgb, #3498db 30%, transparent); } .status-badge.success { background: color-mix(in srgb, #2ecc71 15%, transparent); color: #2ecc71; border: 1px solid color-mix(in srgb, #2ecc71 30%, transparent); } /* CSS-only mini bar chart */ .mini-bar-chart { display: flex; align-items: flex-end; gap: 1px; height: 32px; padding: 0; } .mini-bar-chart .bar-segment { flex: 1; min-width: 2px; max-width: 6px; background: var(--accent); border-radius: 1px 1px 0 0; transition: height 0.3s, background 0.3s; } /* Uptime bar (horizontal) */ .uptime-bar { display: flex; height: 8px; border-radius: 4px; overflow: hidden; background: color-mix(in srgb, var(--dot-bad) 20%, transparent); } .uptime-bar .up-segment { background: var(--dot-ok); height: 100%; transition: width 0.3s; } /* Stat mini card for aggregated metrics */ .stat-mini-card { display: flex; flex-direction: column; align-items: center; padding: 8px; background: color-mix(in srgb, var(--accent) 6%, transparent); border-radius: 8px; border: 1px solid color-mix(in srgb, var(--accent) 15%, transparent); } .stat-mini-card .stat-val { font-size: 1.1rem; font-weight: 700; color: var(--accent); } .stat-mini-card .stat-lbl { font-size: 0.65rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; } /* Service row card (Health panel) */ .service-health-row { padding: 12px; background: var(--card-base); border-radius: 8px; border: 1px solid var(--border); transition: border-color 0.2s; } .service-health-row:hover { border-color: var(--accent); } /* Update row card */ .update-row { padding: 12px; background: var(--card-base); border-radius: 8px; border: 1px solid var(--border); } /* Consistent empty state */ .panel-empty { text-align: center; padding: 40px 20px; color: var(--muted); font-size: 0.9rem; } .panel-empty .empty-icon { font-size: 2rem; margin-bottom: 8px; display: block; } /* Alert config form rows */ .alert-config-row { display: grid; grid-template-columns: 120px 1fr 60px; gap: 8px; align-items: center; font-size: 0.85rem; } .alert-config-row label { margin: 0; font-size: 0.8rem; } .alert-config-row input[type="number"] { width: 100%; padding: 4px 8px; margin: 0; font-size: 0.85rem; } /* Card health/uptime row */ .health-row { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; padding: 0 2px; min-height: 18px; } .health-row .uptime-chip { font-size: 0.65rem; font-weight: 600; padding: 1px 6px; border-radius: 4px; letter-spacing: 0.3px; } .health-row .uptime-chip.excellent { background: color-mix(in srgb, var(--uptime) 12%, var(--card-base) 88%); color: var(--uptime); } .health-row .uptime-chip.good { background: color-mix(in srgb, var(--uptime) 12%, var(--card-base) 88%); color: var(--uptime); } .health-row .uptime-chip.degraded { background: color-mix(in srgb, #ffaa00 12%, var(--card-base) 88%); color: #ffaa00; } .health-row .uptime-chip.poor { background: color-mix(in srgb, #ff6600 12%, var(--card-base) 88%); color: #ff6600; } .health-row .uptime-mini-bar { flex: 1; height: 4px; border-radius: 2px; background: color-mix(in srgb, var(--dot-bad) 15%, transparent); overflow: hidden; } .health-row .uptime-mini-bar .fill { height: 100%; border-radius: 2px; background: var(--uptime); transition: width 0.5s ease; } /* Update available badge on card */ .card .update-available-badge { display: none; font-size: 0.6rem; font-weight: 700; padding: 1px 5px; border-radius: 4px; background: color-mix(in srgb, #f39c12 18%, transparent); color: #f39c12; border: 1px solid color-mix(in srgb, #f39c12 30%, transparent); text-transform: uppercase; letter-spacing: 0.3px; margin-left: 6px; animation: pulse-update 2s infinite; } .card .update-available-badge.visible { display: inline-flex; } @keyframes pulse-update { 0%, 100% { opacity: 1; } 50% { opacity: 0.6; } } /* Incident row */ .incident-row { padding: 10px 12px; background: var(--card-base); border-radius: 6px; border: 1px solid var(--border); font-size: 0.85rem; } .incident-row .incident-severity { font-size: 0.7rem; font-weight: 600; text-transform: uppercase; } .incident-row .incident-severity.critical { color: var(--dot-bad); } .incident-row .incident-severity.high { color: #e74c3c; } .incident-row .incident-severity.medium { color: #f39c12; } .incident-row .incident-severity.low { color: #3498db; } /* Driver.js tour - completely hide overlay */ .driver-overlay { display: none !important; opacity: 0 !important; pointer-events: none !important; } .driver-popover { z-index: 999999 !important; } /* ===== TOTP Authentication Overlay ===== */ #totp-overlay { position: fixed; inset: 0; background: var(--bg, #0b0f1a); z-index: 2000; display: none; align-items: center; justify-content: center; flex-direction: column; } #totp-overlay.show { display: flex; } .totp-card { background: var(--card-base, #121826); border: 1px solid var(--border, #263552); border-radius: 16px; padding: 24px 36px 36px; display: flex; flex-direction: column; align-items: center; gap: 0; max-width: 400px; width: 90%; text-align: center; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5); } .totp-logo { width: 300px; margin-bottom: 6px; opacity: 0.85; } .totp-logo-light { display: none; } :root.light-bg .totp-logo-dark { display: none; } :root.light-bg .totp-logo-light { display: inline; } :root.light-bg .totp-card .subtitle { color: var(--fg, #111); } .totp-card h2 { margin: 0 0 4px; color: var(--fg, #e8ecf5); font-size: 1.5rem; font-weight: 600; } .totp-card .subtitle { color: var(--muted, #9aa6bf); font-size: 1.1rem; margin: 0 0 20px; } .totp-digits { display: flex; gap: 8px; justify-content: center; margin-bottom: 16px; } .totp-digits input { width: 46px; height: 58px; text-align: center; font-size: 1.6rem; font-weight: 600; font-family: 'Sami Grotesk', monospace; border: 2px solid var(--border, #263552); border-radius: 10px; background: var(--bg, #0b0f1a); color: var(--fg, #e8ecf5); outline: none; transition: border-color 0.2s; caret-color: transparent; } .totp-digits input:focus { border-color: var(--accent, #8FD6FF); box-shadow: 0 0 0 3px rgba(143, 214, 255, 0.15); } .totp-error { color: var(--bad-fg, #ff9aa3); font-size: 0.85rem; min-height: 1.2em; margin-top: 4px; } .totp-error.verifying { color: var(--accent, #8FD6FF); } /* ============================================= Extracted Utility Classes (inline style cleanup) ============================================= */ /* --- Form Labels --- */ .form-label-accent { display: block; margin-bottom: 8px; color: var(--accent); font-weight: 500; } .form-label-accent-sm { display: block; margin-bottom: 6px; color: var(--accent); font-weight: 500; } .form-label-bold { display: block; margin-bottom: 8px; font-weight: 600; } .label-bold { font-size: 0.8rem; font-weight: 600; color: var(--fg); } .field-label { font-size: 0.85rem; color: var(--muted); } .field-label-sm { font-size: 0.8rem; } /* --- Form Inputs --- */ .form-input { width: 100%; padding: 8px; border-radius: 6px; border: 1px solid var(--border); background: var(--bg); color: var(--fg); } .form-input-lg { width: 100%; padding: 12px; background: var(--card-bg); color: var(--fg); border: 1px solid var(--border); border-radius: 6px; font-size: 1rem; } .form-input-md { width: 100%; padding: 10px; background: var(--card-bg); color: var(--fg); border: 1px solid var(--border); border-radius: 6px; } .form-input-card { width: 100%; padding: 8px; background: var(--card-bg); color: var(--fg); border: 1px solid var(--border); border-radius: 6px; } /* --- Radio/Checkbox Option Labels --- */ .radio-option { display: flex; align-items: center; padding: 10px; background: var(--card-bg); border: 1px solid var(--border); border-radius: 6px; cursor: pointer; } .checkbox-label { display: flex; align-items: center; gap: 8px; cursor: pointer; } .checkbox-label-sm { display: flex; align-items: center; gap: 6px; font-size: 0.85rem; cursor: pointer; } .option-label { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; cursor: pointer; font-size: 0.85rem; } /* --- Buttons --- */ .btn-accent { background: color-mix(in srgb, var(--accent) 20%, transparent); border-color: var(--accent); color: var(--accent); } .btn-accent-solid { background: var(--accent); color: var(--bg); border-color: var(--accent); } .btn-sm { padding: 6px 12px; font-size: 0.8rem; } .btn-xs { padding: 4px 10px; font-size: 0.75rem; } .btn-option { flex: 1; padding: 8px; border: 1px solid var(--border); border-radius: 4px; background: var(--card-bg); color: var(--fg); cursor: pointer; } /* --- Text Utilities --- */ .fw-500 { font-weight: 500; } .text-hint { font-size: 0.8rem; color: var(--muted); } .text-muted-sm { font-size: 0.85rem; color: var(--muted); } .text-tiny-muted { font-size: 0.75rem; color: var(--muted); } .form-hint { font-size: 0.85rem; color: var(--muted); margin-top: 6px; } .form-hint-sm { font-size: 0.8rem; color: var(--muted); margin-top: 4px; } .tiny-hint { font-size: 0.75rem; color: var(--muted); margin-top: 4px; } .micro-hint { font-size: 0.7rem; color: var(--muted); margin: 4px 0 0; } .micro-hint-indented { font-size: 0.7rem; color: var(--muted); margin: 4px 0 0 24px; } .modal-subtitle { color: var(--muted); margin: 0 0 12px; font-size: 0.9rem; } .text-auto-right { margin-left: auto; font-size: 0.75rem; color: var(--muted); } /* --- Layout Utilities --- */ .flex-row-gap { display: flex; gap: 8px; } .flex-row-gap-center { display: flex; gap: 8px; align-items: center; } .flex-col-gap { display: flex; flex-direction: column; gap: 8px; } .grid-2col { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; } /* --- Scrollable Containers --- */ .scroll-container { max-height: 500px; overflow-y: auto; } /* --- Card / Section Patterns --- */ .provider-card { padding: 12px; background: var(--card-base); border-radius: 8px; margin-bottom: 10px; border: 1px solid var(--border); } .provider-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; } .section-heading { margin: 16px 0 8px; color: var(--accent); font-size: 0.9rem; } .heading-accent { margin: 0 0 8px; color: var(--accent); } .modal-footer-bar { margin-top: 16px; } .panel-bottom-bar { margin-top: 16px; display: flex; align-items: center; gap: 12px; } .hr-divider { border: none; border-top: 1px solid var(--border); margin: 16px 0; } .mb-16 { margin-bottom: 16px; } .input-flex { flex: 1; padding: 10px; background: var(--card-bg); color: var(--fg); border: 1px solid var(--border); border-radius: 6px; } .input-creds { width: 100%; padding: 8px 10px; background: var(--bg); color: var(--fg); border: 1px solid var(--border); border-radius: 6px; font-size: 0.85rem; box-sizing: border-box; } .input-card-alt { width: 100%; padding: 8px; border: 1px solid var(--border); border-radius: 4px; background: var(--card-bg); color: var(--fg); } .checkbox-sm { width: 16px; height: 16px; } .status-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); } .font-bold-sm { font-size: 0.85rem; font-weight: 600; color: var(--fg); } .hint-micro { font-size: 0.7rem; color: var(--muted); margin: 2px 0 8px; } .accent-info-box { margin-bottom: 16px; padding: 12px; background: color-mix(in srgb, var(--accent) 10%, transparent); border-radius: 8px; border: 1px solid var(--accent); } .divider-line { flex: 1; height: 1px; background: var(--border); } .setup-desc { color: var(--muted); margin-bottom: 24px; } .heading-accent-lg { margin: 24px 0 16px; color: var(--accent); } .heading-accent-md { margin: 0 0 12px; color: var(--accent); } .heading-accent-section { margin: 0 0 12px; color: var(--accent); font-size: 0.9rem; } /* ===== Skeleton loading placeholders ===== */ .skeleton-card { background: var(--card-base); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px 16px 44px; min-height: 180px; min-width: 300px; width: clamp(300px, 30vw, 380px); max-width: 100%; display: flex; flex-direction: column; gap: .6rem; opacity: 0; transform: translateY(20px); transition: opacity 0.3s ease, transform 0.3s ease; } .skeleton-card.loaded { opacity: 1; transform: translateY(0); } .skeleton-bar { border-radius: 4px; background: linear-gradient(90deg, var(--card-base) 0%, color-mix(in srgb, var(--fg) 8%, var(--card-base)) 50%, var(--card-base) 100%); background-size: 200% 100%; animation: sheen 1.5s ease-in-out infinite; } /* ===== Theme Toggle (top-right) ===== */ .theme-toggle-group { display: flex; flex-direction: column; align-items: center; gap: 2px; } .theme-toggle-btn { display: flex; align-items: center; gap: 6px; padding: 7px 14px; border-radius: 6px; font-size: 0.82rem; font-weight: 600; cursor: pointer; transition: all 0.2s ease; white-space: nowrap; background: var(--card-base); color: var(--accent); border: 1px solid var(--border); } .theme-toggle-btn:hover { background: color-mix(in srgb, var(--accent) 22%, transparent); } .theme-customize-link { background: none !important; border: none !important; color: var(--muted); font-size: 0.7rem; cursor: pointer; padding: 2px 6px; font-family: inherit; opacity: 0.8; transition: opacity 0.2s, color 0.2s; } .theme-customize-link:hover { opacity: 1; color: var(--accent); } /* ===== Theme Picker Popover ===== */ .theme-picker-wrap { position: relative; display: inline-block; } .theme-picker { position: absolute; top: calc(100% + 6px); left: 0; z-index: 999; min-width: 240px; background: var(--card-base); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: 0 12px 40px rgba(0, 0, 0, .35); backdrop-filter: blur(12px); padding: 6px; display: none; } .theme-picker.show { display: block; animation: fadeIn .15s ease; } @keyframes fadeIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } } .theme-picker-item { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 8px; cursor: pointer; border: none; background: transparent; width: 100%; font-size: .85rem; color: var(--fg); font-family: inherit; } .theme-picker-item:hover { background: var(--hover); } .theme-picker-item.active { background: color-mix(in srgb, var(--accent) 15%, transparent); } .theme-picker-name { flex: 1; text-align: left; } .theme-picker-dots { display: flex; gap: 3px; } .theme-picker-dot { width: 12px; height: 12px; border-radius: 50%; border: 1px solid rgba(128, 128, 128, .3); } .theme-picker-check { width: 16px; text-align: center; font-size: .75rem; color: var(--accent); } .theme-picker-divider { height: 1px; background: var(--border); margin: 4px 6px; } .theme-picker-customize { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-radius: 8px; cursor: pointer; border: none; background: transparent; width: 100%; font-size: .85rem; color: var(--accent); font-family: inherit; font-weight: 500; } .theme-picker-customize:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); } /* ===== Theme Builder Modal ===== */ .theme-builder-preview { padding: 20px; border-radius: var(--radius); border: 1px solid var(--border); margin-bottom: 20px; } .theme-builder-card { padding: 16px; border-radius: 8px; border: 1px solid; max-width: 320px; margin: 0 auto; } .theme-builder-card .preview-title { font-weight: 600; font-size: 1rem; margin-bottom: 4px; } .theme-builder-card .preview-muted { font-size: .85rem; margin-bottom: 12px; } .theme-builder-card .preview-badges { display: flex; gap: 8px; margin-bottom: 10px; } .theme-builder-card .preview-badge { padding: 3px 10px; border-radius: 6px; font-size: .75rem; font-weight: 600; } .theme-builder-card .preview-dots { display: flex; gap: 12px; margin-bottom: 12px; font-size: .8rem; } .theme-builder-card .preview-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; margin-right: 4px; vertical-align: middle; } .theme-builder-card .preview-btn { padding: 6px 16px; border-radius: 8px; border: none; font-size: .8rem; font-weight: 500; cursor: default; } .theme-builder-section { margin-bottom: 16px; } .theme-builder-section-title { font-size: .8rem; font-weight: 600; color: var(--accent); text-transform: uppercase; letter-spacing: .05em; margin-bottom: 8px; padding-bottom: 4px; border-bottom: 1px solid var(--border); } .theme-builder-row { display: flex; align-items: center; gap: 10px; padding: 4px 0; } .theme-builder-label { flex: 1; font-size: .85rem; color: var(--fg); } .theme-builder-color { width: 32px; height: 32px; border: 2px solid var(--border); border-radius: 6px; cursor: pointer; padding: 0; background: none; -webkit-appearance: none; appearance: none; } .theme-builder-color::-webkit-color-swatch-wrapper { padding: 0; } .theme-builder-color::-webkit-color-swatch { border: none; border-radius: 4px; } .theme-builder-color::-moz-color-swatch { border: none; border-radius: 4px; } .theme-builder-hex { font-family: monospace; font-size: .8rem; color: var(--muted); width: 70px; text-align: right; } /* ===== Footer ===== */ .dashcaddy-footer { display: flex; align-items: center; justify-content: center; gap: 14px; padding: 40px 0 20px; margin-top: 48px; opacity: 0.45; transition: opacity 0.3s ease; } .dashcaddy-footer:hover { opacity: 0.8; } .footer-copy { font-size: 1.1rem; color: var(--muted); letter-spacing: 0.5px; } .footer-logo { height: 140px; width: auto; }